Add time seek interface stub
[babeltrace.git] / formats / ctf / ir / trace.c
CommitLineData
bc37ae52
JG
1/*
2 * trace.c
3 *
4 * Babeltrace CTF IR - Trace
5 *
6 * Copyright 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
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
29#include <babeltrace/ctf-ir/trace-internal.h>
30#include <babeltrace/ctf-ir/clock-internal.h>
31#include <babeltrace/ctf-ir/stream-internal.h>
32#include <babeltrace/ctf-ir/stream-class-internal.h>
09840de5 33#include <babeltrace/ctf-ir/event-internal.h>
272df73e
PP
34#include <babeltrace/ctf-ir/event-class.h>
35#include <babeltrace/ctf-ir/event-class-internal.h>
bc37ae52 36#include <babeltrace/ctf-writer/functor-internal.h>
2e33ac5a 37#include <babeltrace/ctf-ir/field-types-internal.h>
44e0a4f5 38#include <babeltrace/ctf-ir/attributes-internal.h>
09840de5 39#include <babeltrace/ctf-ir/validation-internal.h>
8bf65fbd 40#include <babeltrace/ctf-ir/visitor-internal.h>
654c1444 41#include <babeltrace/ctf-ir/utils.h>
8bf65fbd 42#include <babeltrace/plugin/notification/schema.h>
bc37ae52 43#include <babeltrace/compiler.h>
dac5c838 44#include <babeltrace/values.h>
83509119 45#include <babeltrace/ref.h>
a0b720b2 46#include <babeltrace/endian.h>
bc37ae52
JG
47
48#define DEFAULT_IDENTIFIER_SIZE 128
49#define DEFAULT_METADATA_STRING_SIZE 4096
50
50ad4244
JG
51struct listener_wrapper {
52 bt_ctf_listener_cb listener;
2204c381
JG
53 void *data;
54};
55
bc37ae52 56static
83509119 57void bt_ctf_trace_destroy(struct bt_object *obj);
bc37ae52
JG
58static
59int init_trace_packet_header(struct bt_ctf_trace *trace);
f67f3a6e 60static
09840de5 61void bt_ctf_trace_freeze(struct bt_ctf_trace *trace);
bc37ae52 62
bc37ae52
JG
63static
64const unsigned int field_type_aliases_alignments[] = {
65 [FIELD_TYPE_ALIAS_UINT5_T] = 1,
66 [FIELD_TYPE_ALIAS_UINT8_T ... FIELD_TYPE_ALIAS_UINT16_T] = 8,
67 [FIELD_TYPE_ALIAS_UINT27_T] = 1,
68 [FIELD_TYPE_ALIAS_UINT32_T ... FIELD_TYPE_ALIAS_UINT64_T] = 8,
69};
70
71static
72const unsigned int field_type_aliases_sizes[] = {
73 [FIELD_TYPE_ALIAS_UINT5_T] = 5,
74 [FIELD_TYPE_ALIAS_UINT8_T] = 8,
75 [FIELD_TYPE_ALIAS_UINT16_T] = 16,
76 [FIELD_TYPE_ALIAS_UINT27_T] = 27,
77 [FIELD_TYPE_ALIAS_UINT32_T] = 32,
78 [FIELD_TYPE_ALIAS_UINT64_T] = 64,
79};
80
bc37ae52
JG
81struct bt_ctf_trace *bt_ctf_trace_create(void)
82{
83 struct bt_ctf_trace *trace = NULL;
84
85 trace = g_new0(struct bt_ctf_trace, 1);
86 if (!trace) {
87 goto error;
88 }
89
90 bt_ctf_trace_set_byte_order(trace, BT_CTF_BYTE_ORDER_NATIVE);
83509119 91 bt_object_init(trace, bt_ctf_trace_destroy);
bc37ae52 92 trace->clocks = g_ptr_array_new_with_free_func(
83509119 93 (GDestroyNotify) bt_put);
bc37ae52 94 trace->streams = g_ptr_array_new_with_free_func(
e6a8e8e4 95 (GDestroyNotify) bt_object_release);
bc37ae52 96 trace->stream_classes = g_ptr_array_new_with_free_func(
e6a8e8e4 97 (GDestroyNotify) bt_object_release);
7f800dc7 98 if (!trace->clocks || !trace->stream_classes || !trace->streams) {
83509119 99 goto error;
bc37ae52
JG
100 }
101
102 /* Generate a trace UUID */
103 uuid_generate(trace->uuid);
104 if (init_trace_packet_header(trace)) {
83509119 105 goto error;
bc37ae52
JG
106 }
107
7f800dc7
PP
108 /* Create the environment array object */
109 trace->environment = bt_ctf_attributes_create();
110 if (!trace->environment) {
83509119 111 goto error;
7f800dc7
PP
112 }
113
9b888ff3
JG
114 trace->listeners = g_ptr_array_new_with_free_func(
115 (GDestroyNotify) g_free);
116 if (!trace->listeners) {
117 goto error;
118 }
119
bc37ae52
JG
120 return trace;
121
bc37ae52 122error:
83509119 123 BT_PUT(trace);
bc37ae52
JG
124 return trace;
125}
126
e96045d4
JG
127const char *bt_ctf_trace_get_name(struct bt_ctf_trace *trace)
128{
129 const char *name = NULL;
130
131 if (!trace || !trace->name) {
132 goto end;
133 }
134
135 name = trace->name->str;
136end:
137 return name;
138}
139
140int bt_ctf_trace_set_name(struct bt_ctf_trace *trace, const char *name)
141{
142 int ret = 0;
143
144 if (!trace || !name || trace->frozen) {
145 ret = -1;
146 goto end;
147 }
148
149 trace->name = trace->name ? g_string_assign(trace->name, name) :
150 g_string_new(name);
151 if (!trace->name) {
152 ret = -1;
153 goto end;
154 }
155end:
156 return ret;
157}
158
83509119 159void bt_ctf_trace_destroy(struct bt_object *obj)
bc37ae52
JG
160{
161 struct bt_ctf_trace *trace;
bc37ae52 162
83509119 163 trace = container_of(obj, struct bt_ctf_trace, base);
bc37ae52 164 if (trace->environment) {
7f800dc7 165 bt_ctf_attributes_destroy(trace->environment);
bc37ae52
JG
166 }
167
e96045d4
JG
168 if (trace->name) {
169 g_string_free(trace->name, TRUE);
170 }
171
bc37ae52
JG
172 if (trace->clocks) {
173 g_ptr_array_free(trace->clocks, TRUE);
174 }
175
176 if (trace->streams) {
177 g_ptr_array_free(trace->streams, TRUE);
178 }
179
180 if (trace->stream_classes) {
181 g_ptr_array_free(trace->stream_classes, TRUE);
182 }
183
9b888ff3
JG
184 if (trace->listeners) {
185 g_ptr_array_free(trace->listeners, TRUE);
186 }
187
83509119 188 bt_put(trace->packet_header_type);
bc37ae52
JG
189 g_free(trace);
190}
191
7f800dc7 192int bt_ctf_trace_set_environment_field(struct bt_ctf_trace *trace,
dac5c838 193 const char *name, struct bt_value *value)
bc37ae52 194{
bc37ae52
JG
195 int ret = 0;
196
a0d12916 197 if (!trace || !name || !value ||
7f800dc7 198 bt_ctf_validate_identifier(name) ||
dac5c838 199 !(bt_value_is_integer(value) || bt_value_is_string(value))) {
bc37ae52 200 ret = -1;
7f800dc7 201 goto end;
bc37ae52
JG
202 }
203
204 if (strchr(name, ' ')) {
205 ret = -1;
7f800dc7 206 goto end;
bc37ae52
JG
207 }
208
a0d12916
JG
209 if (trace->frozen) {
210 /*
211 * New environment fields may be added to a frozen trace,
212 * but existing fields may not be changed.
213 *
214 * The object passed is frozen like all other attributes.
215 */
dac5c838 216 struct bt_value *attribute =
a0d12916
JG
217 bt_ctf_attributes_get_field_value_by_name(
218 trace->environment, name);
219
220 if (attribute) {
83509119 221 BT_PUT(attribute);
a0d12916
JG
222 ret = -1;
223 goto end;
224 }
225
dac5c838 226 bt_value_freeze(value);
a0d12916
JG
227 }
228
7f800dc7
PP
229 ret = bt_ctf_attributes_set_field_value(trace->environment, name,
230 value);
bc37ae52 231
7f800dc7
PP
232end:
233 return ret;
234}
bc37ae52 235
7f800dc7
PP
236int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace,
237 const char *name, const char *value)
238{
239 int ret = 0;
dac5c838 240 struct bt_value *env_value_string_obj = NULL;
7f800dc7
PP
241
242 if (!trace || !name || !value) {
bc37ae52 243 ret = -1;
7f800dc7 244 goto end;
bc37ae52
JG
245 }
246
a0d12916
JG
247 if (trace->frozen) {
248 /*
249 * New environment fields may be added to a frozen trace,
250 * but existing fields may not be changed.
251 */
dac5c838 252 struct bt_value *attribute =
a0d12916
JG
253 bt_ctf_attributes_get_field_value_by_name(
254 trace->environment, name);
255
256 if (attribute) {
83509119 257 BT_PUT(attribute);
a0d12916
JG
258 ret = -1;
259 goto end;
260 }
261 }
262
dac5c838 263 env_value_string_obj = bt_value_string_create_init(value);
bc37ae52 264
7f800dc7
PP
265 if (!env_value_string_obj) {
266 ret = -1;
267 goto end;
bc37ae52
JG
268 }
269
a0d12916 270 if (trace->frozen) {
dac5c838 271 bt_value_freeze(env_value_string_obj);
a0d12916 272 }
7f800dc7
PP
273 ret = bt_ctf_trace_set_environment_field(trace, name,
274 env_value_string_obj);
275
276end:
83509119 277 BT_PUT(env_value_string_obj);
3487c9f3
JG
278 return ret;
279}
280
7f800dc7
PP
281int bt_ctf_trace_set_environment_field_integer(struct bt_ctf_trace *trace,
282 const char *name, int64_t value)
3487c9f3 283{
3487c9f3 284 int ret = 0;
dac5c838 285 struct bt_value *env_value_integer_obj = NULL;
3487c9f3
JG
286
287 if (!trace || !name) {
288 ret = -1;
7f800dc7 289 goto end;
3487c9f3
JG
290 }
291
a0d12916
JG
292 if (trace->frozen) {
293 /*
294 * New environment fields may be added to a frozen trace,
295 * but existing fields may not be changed.
296 */
dac5c838 297 struct bt_value *attribute =
a0d12916
JG
298 bt_ctf_attributes_get_field_value_by_name(
299 trace->environment, name);
300
301 if (attribute) {
83509119 302 BT_PUT(attribute);
a0d12916
JG
303 ret = -1;
304 goto end;
305 }
306 }
307
dac5c838 308 env_value_integer_obj = bt_value_integer_create_init(value);
7f800dc7 309 if (!env_value_integer_obj) {
3487c9f3 310 ret = -1;
7f800dc7 311 goto end;
3487c9f3
JG
312 }
313
7f800dc7
PP
314 ret = bt_ctf_trace_set_environment_field(trace, name,
315 env_value_integer_obj);
a0d12916 316 if (trace->frozen) {
dac5c838 317 bt_value_freeze(env_value_integer_obj);
a0d12916 318 }
7f800dc7 319end:
83509119 320 BT_PUT(env_value_integer_obj);
bc37ae52
JG
321 return ret;
322}
323
e6fa2160
JG
324int bt_ctf_trace_get_environment_field_count(struct bt_ctf_trace *trace)
325{
326 int ret = 0;
327
328 if (!trace) {
329 ret = -1;
330 goto end;
331 }
332
7f800dc7 333 ret = bt_ctf_attributes_get_count(trace->environment);
e6fa2160 334
e6fa2160 335end:
7f800dc7 336 return ret;
e6fa2160
JG
337}
338
339const char *
340bt_ctf_trace_get_environment_field_name(struct bt_ctf_trace *trace,
341 int index)
342{
e6fa2160
JG
343 const char *ret = NULL;
344
7f800dc7 345 if (!trace) {
e6fa2160
JG
346 goto end;
347 }
348
7f800dc7
PP
349 ret = bt_ctf_attributes_get_field_name(trace->environment, index);
350
e6fa2160
JG
351end:
352 return ret;
353}
354
dac5c838 355struct bt_value *bt_ctf_trace_get_environment_field_value(
7f800dc7 356 struct bt_ctf_trace *trace, int index)
e6fa2160 357{
dac5c838 358 struct bt_value *ret = NULL;
e6fa2160 359
7f800dc7 360 if (!trace) {
e6fa2160
JG
361 goto end;
362 }
363
7f800dc7
PP
364 ret = bt_ctf_attributes_get_field_value(trace->environment, index);
365
e6fa2160
JG
366end:
367 return ret;
368}
369
dac5c838 370struct bt_value *bt_ctf_trace_get_environment_field_value_by_name(
7f800dc7 371 struct bt_ctf_trace *trace, const char *name)
e6fa2160 372{
dac5c838 373 struct bt_value *ret = NULL;
e6fa2160 374
7f800dc7 375 if (!trace || !name) {
e6fa2160
JG
376 goto end;
377 }
378
7f800dc7
PP
379 ret = bt_ctf_attributes_get_field_value_by_name(trace->environment,
380 name);
381
e6fa2160
JG
382end:
383 return ret;
384}
385
bc37ae52
JG
386int bt_ctf_trace_add_clock(struct bt_ctf_trace *trace,
387 struct bt_ctf_clock *clock)
388{
389 int ret = 0;
390 struct search_query query = { .value = clock, .found = 0 };
391
c06116f3 392 if (!trace || !bt_ctf_clock_is_valid(clock)) {
bc37ae52
JG
393 ret = -1;
394 goto end;
395 }
396
397 /* Check for duplicate clocks */
398 g_ptr_array_foreach(trace->clocks, value_exists, &query);
399 if (query.found) {
400 ret = -1;
401 goto end;
402 }
403
83509119 404 bt_get(clock);
bc37ae52 405 g_ptr_array_add(trace->clocks, clock);
6474e016 406
cfeb617e
PP
407 if (!trace->is_created_by_writer) {
408 /*
409 * Non-writer mode trace: disable clock value functions
410 * because clock values are per-stream in that
411 * situation.
412 */
413 clock->has_value = 0;
414 }
415
6474e016
PP
416 if (trace->frozen) {
417 bt_ctf_clock_freeze(clock);
418 }
bc37ae52
JG
419end:
420 return ret;
421}
422
884cd6c3
JG
423int bt_ctf_trace_get_clock_count(struct bt_ctf_trace *trace)
424{
425 int ret = -1;
426
427 if (!trace) {
428 goto end;
429 }
430
431 ret = trace->clocks->len;
432end:
433 return ret;
434}
435
436struct bt_ctf_clock *bt_ctf_trace_get_clock(struct bt_ctf_trace *trace,
437 int index)
438{
439 struct bt_ctf_clock *clock = NULL;
440
441 if (!trace || index < 0 || index >= trace->clocks->len) {
442 goto end;
443 }
444
445 clock = g_ptr_array_index(trace->clocks, index);
83509119 446 bt_get(clock);
884cd6c3
JG
447end:
448 return clock;
449}
450
ef0c4a15
JG
451int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace,
452 struct bt_ctf_stream_class *stream_class)
453{
454 int ret, i;
455 int64_t stream_id;
09840de5
PP
456 struct bt_ctf_validation_output trace_sc_validation_output = { 0 };
457 struct bt_ctf_validation_output *ec_validation_outputs = NULL;
458 const enum bt_ctf_validation_flag trace_sc_validation_flags =
459 BT_CTF_VALIDATION_FLAG_TRACE |
460 BT_CTF_VALIDATION_FLAG_STREAM;
461 const enum bt_ctf_validation_flag ec_validation_flags =
462 BT_CTF_VALIDATION_FLAG_EVENT;
463 struct bt_ctf_field_type *packet_header_type = NULL;
464 struct bt_ctf_field_type *packet_context_type = NULL;
465 struct bt_ctf_field_type *event_header_type = NULL;
466 struct bt_ctf_field_type *stream_event_ctx_type = NULL;
467 int event_class_count;
fe13b5c0 468 struct bt_ctf_clock *clock_to_add_to_trace = NULL;
2789e5d9 469 struct bt_ctf_trace *current_parent_trace = NULL;
ef0c4a15
JG
470
471 if (!trace || !stream_class) {
472 ret = -1;
473 goto end;
474 }
475
2789e5d9
JG
476 current_parent_trace = bt_ctf_stream_class_get_trace(stream_class);
477 if (current_parent_trace) {
478 /* Stream class is already associated to a trace, abort. */
479 ret = -1;
480 goto end;
481 }
482
09840de5
PP
483 event_class_count =
484 bt_ctf_stream_class_get_event_class_count(stream_class);
485 assert(event_class_count >= 0);
486
487 /* Check for duplicate stream classes */
ef0c4a15
JG
488 for (i = 0; i < trace->stream_classes->len; i++) {
489 if (trace->stream_classes->pdata[i] == stream_class) {
09840de5 490 /* Stream class already registered to the trace */
ef0c4a15
JG
491 ret = -1;
492 goto end;
493 }
494 }
495
fe13b5c0
PP
496 /*
497 * If the stream class has a clock, register this clock to this
498 * trace if not already done.
499 */
500 if (stream_class->clock) {
501 const char *clock_name =
502 bt_ctf_clock_get_name(stream_class->clock);
503 struct bt_ctf_clock *trace_clock;
504
505 assert(clock_name);
506 trace_clock = bt_ctf_trace_get_clock_by_name(trace, clock_name);
507 bt_put(trace_clock);
508 if (trace_clock) {
509 if (trace_clock != stream_class->clock) {
510 /*
511 * Error: two different clocks in the
512 * trace would share the same name.
513 */
514 ret = -1;
515 goto end;
516 }
517 } else {
518 clock_to_add_to_trace = bt_get(stream_class->clock);
519 }
520 }
521
09840de5
PP
522 /*
523 * We're about to freeze both the trace and the stream class.
524 * Also, each event class contained in this stream class are
525 * already frozen.
526 *
527 * This trace, this stream class, and all its event classes
528 * should be valid at this point.
529 *
530 * Validate trace and stream class first, then each event
531 * class of this stream class can be validated individually.
532 */
533 packet_header_type =
534 bt_ctf_trace_get_packet_header_type(trace);
535 packet_context_type =
536 bt_ctf_stream_class_get_packet_context_type(stream_class);
537 event_header_type =
538 bt_ctf_stream_class_get_event_header_type(stream_class);
539 stream_event_ctx_type =
540 bt_ctf_stream_class_get_event_context_type(stream_class);
541 ret = bt_ctf_validate_class_types(trace->environment,
542 packet_header_type, packet_context_type, event_header_type,
543 stream_event_ctx_type, NULL, NULL, trace->valid,
544 stream_class->valid, 1, &trace_sc_validation_output,
545 trace_sc_validation_flags);
546 BT_PUT(packet_header_type);
547 BT_PUT(packet_context_type);
548 BT_PUT(event_header_type);
549 BT_PUT(stream_event_ctx_type);
550
2bd7f864 551 if (ret) {
09840de5
PP
552 /*
553 * This means something went wrong during the validation
554 * process, not that the objects are invalid.
555 */
2bd7f864
JG
556 goto end;
557 }
558
09840de5
PP
559 if ((trace_sc_validation_output.valid_flags &
560 trace_sc_validation_flags) !=
561 trace_sc_validation_flags) {
562 /* Invalid trace/stream class */
563 ret = -1;
564 goto end;
565 }
566
567 if (event_class_count > 0) {
568 ec_validation_outputs = g_new0(struct bt_ctf_validation_output,
569 event_class_count);
570 if (!ec_validation_outputs) {
571 ret = -1;
572 goto end;
573 }
574 }
575
576 /* Validate each event class individually */
6474e016 577 for (i = 0; i < event_class_count; i++) {
09840de5
PP
578 struct bt_ctf_event_class *event_class =
579 bt_ctf_stream_class_get_event_class(stream_class, i);
580 struct bt_ctf_field_type *event_context_type = NULL;
581 struct bt_ctf_field_type *event_payload_type = NULL;
582
583 event_context_type =
584 bt_ctf_event_class_get_context_type(event_class);
585 event_payload_type =
586 bt_ctf_event_class_get_payload_type(event_class);
587
588 /*
589 * It is important to use the field types returned by
590 * the previous trace and stream class validation here
591 * because copies could have been made.
592 */
593 ret = bt_ctf_validate_class_types(trace->environment,
594 trace_sc_validation_output.packet_header_type,
595 trace_sc_validation_output.packet_context_type,
596 trace_sc_validation_output.event_header_type,
597 trace_sc_validation_output.stream_event_ctx_type,
598 event_context_type, event_payload_type,
599 1, 1, event_class->valid, &ec_validation_outputs[i],
600 ec_validation_flags);
601 BT_PUT(event_context_type);
602 BT_PUT(event_payload_type);
603 BT_PUT(event_class);
604
605 if (ret) {
606 goto end;
607 }
608
609 if ((ec_validation_outputs[i].valid_flags &
610 ec_validation_flags) != ec_validation_flags) {
611 /* Invalid event class */
612 ret = -1;
613 goto end;
614 }
615 }
616
ef0c4a15
JG
617 stream_id = bt_ctf_stream_class_get_id(stream_class);
618 if (stream_id < 0) {
619 stream_id = trace->next_stream_id++;
620
621 /* Try to assign a new stream id */
622 for (i = 0; i < trace->stream_classes->len; i++) {
623 if (stream_id == bt_ctf_stream_class_get_id(
624 trace->stream_classes->pdata[i])) {
625 /* Duplicate stream id found */
626 ret = -1;
627 goto end;
628 }
629 }
630
0ddffae5
JG
631 if (bt_ctf_stream_class_set_id_no_check(stream_class,
632 stream_id)) {
ef0c4a15
JG
633 /* TODO Should retry with a different stream id */
634 ret = -1;
635 goto end;
636 }
637 }
638
e6a8e8e4 639 bt_object_set_parent(stream_class, trace);
ef0c4a15
JG
640 g_ptr_array_add(trace->stream_classes, stream_class);
641
642 /*
09840de5
PP
643 * At this point we know that the function will be successful.
644 * Therefore we can replace the trace and stream class field
645 * types with what's in their validation output structure and
646 * mark them as valid. We can also replace the field types of
647 * all the event classes of the stream class and mark them as
648 * valid.
649 */
650 bt_ctf_validation_replace_types(trace, stream_class, NULL,
651 &trace_sc_validation_output, trace_sc_validation_flags);
652 trace->valid = 1;
653 stream_class->valid = 1;
654
655 /*
656 * Put what was not moved in bt_ctf_validation_replace_types().
657 */
658 bt_ctf_validation_output_put_types(&trace_sc_validation_output);
659
6474e016 660 for (i = 0; i < event_class_count; i++) {
09840de5
PP
661 struct bt_ctf_event_class *event_class =
662 bt_ctf_stream_class_get_event_class(stream_class, i);
663
664 bt_ctf_validation_replace_types(NULL, NULL, event_class,
665 &ec_validation_outputs[i], ec_validation_flags);
666 event_class->valid = 1;
667 BT_PUT(event_class);
668
669 /*
670 * Put what was not moved in
671 * bt_ctf_validation_replace_types().
672 */
673 bt_ctf_validation_output_put_types(&ec_validation_outputs[i]);
674 }
675
676 /*
ef0c4a15
JG
677 * All field type byte orders set as "native" byte ordering can now be
678 * safely set to trace's own endianness, including the stream class'.
679 */
680 bt_ctf_field_type_set_native_byte_order(trace->packet_header_type,
681 trace->byte_order);
445c3471 682 bt_ctf_stream_class_set_byte_order(stream_class, trace->byte_order);
ef0c4a15 683
fe13b5c0
PP
684 /* Add stream class's clock if it exists */
685 if (clock_to_add_to_trace) {
686 int add_clock_ret =
687 bt_ctf_trace_add_clock(trace, clock_to_add_to_trace);
688 assert(add_clock_ret == 0);
689 }
690
09840de5
PP
691 /*
692 * Freeze the trace and the stream class.
693 */
f67f3a6e 694 bt_ctf_stream_class_freeze(stream_class);
09840de5
PP
695 bt_ctf_trace_freeze(trace);
696
9b888ff3
JG
697 /* Notifiy listeners of the trace's schema modification. */
698 bt_ctf_stream_class_visit(stream_class,
d9a13d86 699 bt_ctf_trace_object_modification, trace);
ef0c4a15 700end:
d3814b54 701 if (ret) {
e6a8e8e4 702 bt_object_set_parent(stream_class, NULL);
09840de5
PP
703
704 if (ec_validation_outputs) {
6474e016 705 for (i = 0; i < event_class_count; i++) {
09840de5
PP
706 bt_ctf_validation_output_put_types(
707 &ec_validation_outputs[i]);
708 }
709 }
d3814b54 710 }
09840de5
PP
711
712 g_free(ec_validation_outputs);
713 bt_ctf_validation_output_put_types(&trace_sc_validation_output);
fe13b5c0 714 BT_PUT(clock_to_add_to_trace);
2789e5d9 715 bt_put(current_parent_trace);
09840de5
PP
716 assert(!packet_header_type);
717 assert(!packet_context_type);
718 assert(!event_header_type);
719 assert(!stream_event_ctx_type);
720
ef0c4a15
JG
721 return ret;
722}
723
724int bt_ctf_trace_get_stream_class_count(struct bt_ctf_trace *trace)
725{
726 int ret;
727
728 if (!trace) {
729 ret = -1;
730 goto end;
731 }
732
733 ret = trace->stream_classes->len;
734end:
735 return ret;
736}
737
738struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class(
739 struct bt_ctf_trace *trace, int index)
740{
741 struct bt_ctf_stream_class *stream_class = NULL;
742
743 if (!trace || index < 0 || index >= trace->stream_classes->len) {
744 goto end;
745 }
746
747 stream_class = g_ptr_array_index(trace->stream_classes, index);
83509119 748 bt_get(stream_class);
ef0c4a15
JG
749end:
750 return stream_class;
751}
752
4841ccc1
PP
753struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class_by_id(
754 struct bt_ctf_trace *trace, uint32_t id)
755{
756 int i;
757 struct bt_ctf_stream_class *stream_class = NULL;
758
759 if (!trace) {
760 goto end;
761 }
762
6474e016 763 for (i = 0; i < trace->stream_classes->len; i++) {
4841ccc1
PP
764 struct bt_ctf_stream_class *stream_class_candidate;
765
766 stream_class_candidate =
767 g_ptr_array_index(trace->stream_classes, i);
768
769 if (bt_ctf_stream_class_get_id(stream_class_candidate) ==
770 (int64_t) id) {
771 stream_class = stream_class_candidate;
83509119 772 bt_get(stream_class);
4841ccc1
PP
773 goto end;
774 }
775 }
776
777end:
778 return stream_class;
779}
780
7e4347a3
PP
781struct bt_ctf_clock *bt_ctf_trace_get_clock_by_name(
782 struct bt_ctf_trace *trace, const char *name)
783{
784 size_t i;
785 struct bt_ctf_clock *clock = NULL;
786
787 if (!trace || !name) {
788 goto end;
789 }
790
6474e016 791 for (i = 0; i < trace->clocks->len; i++) {
7e4347a3
PP
792 struct bt_ctf_clock *cur_clk =
793 g_ptr_array_index(trace->clocks, i);
794 const char *cur_clk_name = bt_ctf_clock_get_name(cur_clk);
795
796 if (!cur_clk_name) {
797 goto end;
798 }
799
800 if (!strcmp(cur_clk_name, name)) {
801 clock = cur_clk;
83509119 802 bt_get(clock);
7e4347a3
PP
803 goto end;
804 }
805 }
806
807end:
808 return clock;
809}
810
bc37ae52
JG
811BT_HIDDEN
812const char *get_byte_order_string(int byte_order)
813{
814 const char *string;
815
816 switch (byte_order) {
817 case LITTLE_ENDIAN:
818 string = "le";
819 break;
820 case BIG_ENDIAN:
821 string = "be";
822 break;
823 default:
824 string = "unknown";
825 break;
826 }
827
828 return string;
829}
830
831static
832int append_trace_metadata(struct bt_ctf_trace *trace,
833 struct metadata_context *context)
834{
835 unsigned char *uuid = trace->uuid;
836 int ret;
837
838 g_string_append(context->string, "trace {\n");
839
840 g_string_append(context->string, "\tmajor = 1;\n");
841 g_string_append(context->string, "\tminor = 8;\n");
842
843 g_string_append_printf(context->string,
844 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
845 uuid[0], uuid[1], uuid[2], uuid[3],
846 uuid[4], uuid[5], uuid[6], uuid[7],
847 uuid[8], uuid[9], uuid[10], uuid[11],
848 uuid[12], uuid[13], uuid[14], uuid[15]);
849 g_string_append_printf(context->string, "\tbyte_order = %s;\n",
850 get_byte_order_string(trace->byte_order));
851
852 g_string_append(context->string, "\tpacket.header := ");
853 context->current_indentation_level++;
854 g_string_assign(context->field_name, "");
d246b111 855 ret = bt_ctf_field_type_serialize(trace->packet_header_type,
bc37ae52
JG
856 context);
857 if (ret) {
858 goto end;
859 }
860 context->current_indentation_level--;
861
862 g_string_append(context->string, ";\n};\n\n");
863end:
864 return ret;
865}
866
bc37ae52
JG
867static
868void append_env_metadata(struct bt_ctf_trace *trace,
869 struct metadata_context *context)
870{
7f800dc7
PP
871 int i;
872 int env_size;
873
874 env_size = bt_ctf_attributes_get_count(trace->environment);
875
876 if (env_size <= 0) {
bc37ae52
JG
877 return;
878 }
879
880 g_string_append(context->string, "env {\n");
7f800dc7 881
6474e016 882 for (i = 0; i < env_size; i++) {
dac5c838 883 struct bt_value *env_field_value_obj = NULL;
7f800dc7 884 const char *entry_name;
7f800dc7
PP
885
886 entry_name = bt_ctf_attributes_get_field_name(
887 trace->environment, i);
888 env_field_value_obj = bt_ctf_attributes_get_field_value(
889 trace->environment, i);
890
891 if (!entry_name || !env_field_value_obj) {
892 goto loop_next;
893 }
894
dac5c838
PP
895 switch (bt_value_get_type(env_field_value_obj)) {
896 case BT_VALUE_TYPE_INTEGER:
b8248cc0
PP
897 {
898 int ret;
899 int64_t int_value;
900
dac5c838 901 ret = bt_value_integer_get(env_field_value_obj,
7f800dc7
PP
902 &int_value);
903
904 if (ret) {
905 goto loop_next;
906 }
907
908 g_string_append_printf(context->string,
909 "\t%s = %" PRId64 ";\n", entry_name,
910 int_value);
911 break;
b8248cc0 912 }
dac5c838 913 case BT_VALUE_TYPE_STRING:
7f800dc7
PP
914 {
915 int ret;
916 const char *str_value;
917 char *escaped_str = NULL;
918
dac5c838 919 ret = bt_value_string_get(env_field_value_obj,
7f800dc7
PP
920 &str_value);
921
922 if (ret) {
923 goto loop_next;
924 }
925
926 escaped_str = g_strescape(str_value, NULL);
927
928 if (!escaped_str) {
929 goto loop_next;
930 }
931
932 g_string_append_printf(context->string,
933 "\t%s = \"%s\";\n", entry_name, escaped_str);
934 free(escaped_str);
935 break;
936 }
937
938 default:
939 goto loop_next;
940 }
941
942loop_next:
83509119 943 BT_PUT(env_field_value_obj);
7f800dc7
PP
944 }
945
bc37ae52
JG
946 g_string_append(context->string, "};\n\n");
947}
948
949char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace)
950{
951 char *metadata = NULL;
952 struct metadata_context *context = NULL;
953 int err = 0;
954 size_t i;
955
956 if (!trace) {
957 goto end;
958 }
959
960 context = g_new0(struct metadata_context, 1);
961 if (!context) {
962 goto end;
963 }
964
965 context->field_name = g_string_sized_new(DEFAULT_IDENTIFIER_SIZE);
966 context->string = g_string_sized_new(DEFAULT_METADATA_STRING_SIZE);
967 g_string_append(context->string, "/* CTF 1.8 */\n\n");
968 if (append_trace_metadata(trace, context)) {
969 goto error;
970 }
971 append_env_metadata(trace, context);
972 g_ptr_array_foreach(trace->clocks,
973 (GFunc)bt_ctf_clock_serialize, context);
974
975 for (i = 0; i < trace->stream_classes->len; i++) {
976 err = bt_ctf_stream_class_serialize(
977 trace->stream_classes->pdata[i], context);
978 if (err) {
979 goto error;
980 }
981 }
982
983 metadata = context->string->str;
984error:
985 g_string_free(context->string, err ? TRUE : FALSE);
986 g_string_free(context->field_name, TRUE);
987 g_free(context);
988end:
989 return metadata;
990}
991
4ed90fb3
JG
992enum bt_ctf_byte_order bt_ctf_trace_get_byte_order(struct bt_ctf_trace *trace)
993{
994 enum bt_ctf_byte_order ret = BT_CTF_BYTE_ORDER_UNKNOWN;
995
996 if (!trace) {
997 goto end;
998 }
999
1000 switch (trace->byte_order) {
1001 case BIG_ENDIAN:
1002 ret = BT_CTF_BYTE_ORDER_BIG_ENDIAN;
1003 break;
1004 case LITTLE_ENDIAN:
1005 ret = BT_CTF_BYTE_ORDER_LITTLE_ENDIAN;
1006 break;
1007 default:
1008 break;
1009 }
1010end:
1011 return ret;
1012}
1013
bc37ae52
JG
1014int bt_ctf_trace_set_byte_order(struct bt_ctf_trace *trace,
1015 enum bt_ctf_byte_order byte_order)
1016{
1017 int ret = 0;
1018 int internal_byte_order;
1019
1020 if (!trace || trace->frozen) {
1021 ret = -1;
1022 goto end;
1023 }
1024
1025 switch (byte_order) {
1026 case BT_CTF_BYTE_ORDER_NATIVE:
c35a1669
JG
1027 /*
1028 * This doesn't make sense since the CTF specification defines
1029 * the "native" byte order as "the byte order described in the
1030 * trace description". However, this behavior had been
1031 * implemented as part of v1.2 and is kept to maintain
1032 * compatibility.
1033 *
1034 * This may be changed on a major version bump only.
1035 */
1036 internal_byte_order = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ?
bc37ae52
JG
1037 LITTLE_ENDIAN : BIG_ENDIAN;
1038 break;
1039 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
1040 internal_byte_order = LITTLE_ENDIAN;
1041 break;
1042 case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
1043 case BT_CTF_BYTE_ORDER_NETWORK:
1044 internal_byte_order = BIG_ENDIAN;
1045 break;
1046 default:
1047 ret = -1;
1048 goto end;
1049 }
1050
1051 trace->byte_order = internal_byte_order;
bc37ae52
JG
1052end:
1053 return ret;
1054}
1055
d246b111
JG
1056struct bt_ctf_field_type *bt_ctf_trace_get_packet_header_type(
1057 struct bt_ctf_trace *trace)
1058{
1059 struct bt_ctf_field_type *field_type = NULL;
1060
1061 if (!trace) {
1062 goto end;
1063 }
1064
83509119 1065 bt_get(trace->packet_header_type);
d246b111
JG
1066 field_type = trace->packet_header_type;
1067end:
1068 return field_type;
1069}
1070
1071int bt_ctf_trace_set_packet_header_type(struct bt_ctf_trace *trace,
1072 struct bt_ctf_field_type *packet_header_type)
1073{
1074 int ret = 0;
1075
1076 if (!trace || !packet_header_type || trace->frozen) {
1077 ret = -1;
1078 goto end;
1079 }
1080
1081 /* packet_header_type must be a structure */
1082 if (bt_ctf_field_type_get_type_id(packet_header_type) !=
9a19a512 1083 BT_CTF_TYPE_ID_STRUCT) {
d246b111
JG
1084 ret = -1;
1085 goto end;
1086 }
1087
83509119
JG
1088 bt_get(packet_header_type);
1089 bt_put(trace->packet_header_type);
d246b111
JG
1090 trace->packet_header_type = packet_header_type;
1091end:
1092 return ret;
1093}
1094
8bf65fbd
JG
1095static
1096int get_stream_class_count(void *element)
1097{
1098 return bt_ctf_trace_get_stream_class_count(
1099 (struct bt_ctf_trace *) element);
1100}
1101
1102static
1103void *get_stream_class(void *element, int i)
1104{
1105 return bt_ctf_trace_get_stream_class(
1106 (struct bt_ctf_trace *) element, i);
1107}
1108
1109static
d9a13d86 1110int visit_stream_class(void *object, bt_ctf_visitor visitor,void *data)
8bf65fbd 1111{
d9a13d86 1112 return bt_ctf_stream_class_visit(object, visitor, data);
8bf65fbd
JG
1113}
1114
1115int bt_ctf_trace_visit(struct bt_ctf_trace *trace,
d9a13d86 1116 bt_ctf_visitor visitor, void *data)
8bf65fbd
JG
1117{
1118 int ret;
d9a13d86
PP
1119 struct bt_ctf_object obj =
1120 { .object = trace, .type = BT_CTF_OBJECT_TYPE_TRACE };
8bf65fbd
JG
1121
1122 if (!trace || !visitor) {
1123 ret = -1;
1124 goto end;
1125 }
1126
d9a13d86 1127 ret = visitor_helper(&obj, get_stream_class_count,
8bf65fbd
JG
1128 get_stream_class, visit_stream_class, visitor, data);
1129end:
1130 return ret;
1131}
1132
1133static
d9a13d86 1134int invoke_listener(struct bt_ctf_object *object, void *data)
8bf65fbd 1135{
9b888ff3 1136 struct listener_wrapper *listener_wrapper = data;
8bf65fbd 1137
d9a13d86 1138 listener_wrapper->listener(object, listener_wrapper->data);
9b888ff3 1139 return 0;
8bf65fbd
JG
1140}
1141
50ad4244
JG
1142int bt_ctf_trace_add_listener(struct bt_ctf_trace *trace,
1143 bt_ctf_listener_cb listener, void *listener_data)
2204c381
JG
1144{
1145 int ret = 0;
50ad4244
JG
1146 struct listener_wrapper *listener_wrapper =
1147 g_new0(struct listener_wrapper, 1);
2204c381 1148
50ad4244 1149 if (!trace || !listener || !listener_wrapper) {
2204c381
JG
1150 ret = -1;
1151 goto error;
1152 }
1153
50ad4244
JG
1154 listener_wrapper->listener = listener;
1155 listener_wrapper->data = listener_data;
8bf65fbd 1156
50ad4244 1157 /* Visit the current schema. */
9b888ff3 1158 ret = bt_ctf_trace_visit(trace, invoke_listener, listener_wrapper);
8bf65fbd
JG
1159 if (ret) {
1160 goto error;
1161 }
1162
50ad4244
JG
1163 /*
1164 * Add listener to the array of callbacks which will be invoked on
1165 * schema changes.
1166 */
1167 g_ptr_array_add(trace->listeners, listener_wrapper);
2204c381
JG
1168 return ret;
1169error:
50ad4244 1170 g_free(listener_wrapper);
2204c381
JG
1171 return ret;
1172}
1173
bc37ae52 1174BT_HIDDEN
d9a13d86 1175int bt_ctf_trace_object_modification(struct bt_ctf_object *object,
9b888ff3
JG
1176 void *trace_ptr)
1177{
1178 size_t i;
1179 struct bt_ctf_trace *trace = trace_ptr;
1180
1181 assert(trace);
d9a13d86 1182 assert(object);
9b888ff3
JG
1183
1184 if (trace->listeners->len == 0) {
1185 goto end;
1186 }
1187
1188 for (i = 0; i < trace->listeners->len; i++) {
1189 struct listener_wrapper *listener =
1190 g_ptr_array_index(trace->listeners, i);
1191
d9a13d86 1192 listener->listener(object, listener->data);
9b888ff3
JG
1193 }
1194end:
1195 return 0;
1196}
1197
1198BT_HIDDEN
bc37ae52
JG
1199struct bt_ctf_field_type *get_field_type(enum field_type_alias alias)
1200{
a25e0d14 1201 int ret;
bc37ae52 1202 unsigned int alignment, size;
8bdcb82e 1203 struct bt_ctf_field_type *field_type = NULL;
bc37ae52
JG
1204
1205 if (alias >= NR_FIELD_TYPE_ALIAS) {
8bdcb82e 1206 goto end;
bc37ae52
JG
1207 }
1208
1209 alignment = field_type_aliases_alignments[alias];
1210 size = field_type_aliases_sizes[alias];
1211 field_type = bt_ctf_field_type_integer_create(size);
a25e0d14
JG
1212 ret = bt_ctf_field_type_set_alignment(field_type, alignment);
1213 if (ret) {
1214 BT_PUT(field_type);
1215 }
8bdcb82e 1216end:
bc37ae52
JG
1217 return field_type;
1218}
1219
f67f3a6e 1220static
09840de5 1221void bt_ctf_trace_freeze(struct bt_ctf_trace *trace)
f67f3a6e 1222{
6474e016
PP
1223 int i;
1224
09840de5 1225 bt_ctf_field_type_freeze(trace->packet_header_type);
f67f3a6e 1226 bt_ctf_attributes_freeze(trace->environment);
6474e016
PP
1227
1228 for (i = 0; i < trace->clocks->len; i++) {
1229 struct bt_ctf_clock *clock =
1230 g_ptr_array_index(trace->clocks, i);
1231
1232 bt_ctf_clock_freeze(clock);
1233 }
1234
f67f3a6e
JG
1235 trace->frozen = 1;
1236}
1237
bc37ae52
JG
1238static
1239int init_trace_packet_header(struct bt_ctf_trace *trace)
1240{
bc37ae52 1241 int ret = 0;
d246b111 1242 struct bt_ctf_field *magic = NULL, *uuid_array = NULL;
bc37ae52
JG
1243 struct bt_ctf_field_type *_uint32_t =
1244 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
1245 struct bt_ctf_field_type *_uint8_t =
1246 get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
1247 struct bt_ctf_field_type *trace_packet_header_type =
1248 bt_ctf_field_type_structure_create();
1249 struct bt_ctf_field_type *uuid_array_type =
1250 bt_ctf_field_type_array_create(_uint8_t, 16);
1251
1252 if (!trace_packet_header_type || !uuid_array_type) {
1253 ret = -1;
1254 goto end;
1255 }
1256
bc37ae52
JG
1257 ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
1258 _uint32_t, "magic");
1259 if (ret) {
1260 goto end;
1261 }
1262
1263 ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
1264 uuid_array_type, "uuid");
1265 if (ret) {
1266 goto end;
1267 }
1268
1269 ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
1270 _uint32_t, "stream_id");
1271 if (ret) {
1272 goto end;
1273 }
1274
662e778c
JG
1275 ret = bt_ctf_trace_set_packet_header_type(trace,
1276 trace_packet_header_type);
1277 if (ret) {
1278 goto end;
1279 }
bc37ae52 1280end:
83509119
JG
1281 bt_put(uuid_array_type);
1282 bt_put(_uint32_t);
1283 bt_put(_uint8_t);
1284 bt_put(magic);
1285 bt_put(uuid_array);
1286 bt_put(trace_packet_header_type);
bc37ae52
JG
1287 return ret;
1288}
This page took 0.119031 seconds and 4 git commands to generate.