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