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