75a47952eedd4f68e5c0b44ec1c624ddf8e8c5c8
[babeltrace.git] / formats / ctf / ir / trace.c
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>
33 #include <babeltrace/ctf-ir/event-internal.h>
34 #include <babeltrace/ctf-writer/functor-internal.h>
35 #include <babeltrace/ctf-ir/event-types-internal.h>
36 #include <babeltrace/ctf-ir/attributes-internal.h>
37 #include <babeltrace/ctf-ir/validation-internal.h>
38 #include <babeltrace/ctf-ir/utils.h>
39 #include <babeltrace/compiler.h>
40 #include <babeltrace/values.h>
41 #include <babeltrace/ref.h>
42 #include <babeltrace/endian.h>
43
44 #define DEFAULT_IDENTIFIER_SIZE 128
45 #define DEFAULT_METADATA_STRING_SIZE 4096
46
47 static
48 void bt_ctf_trace_destroy(struct bt_object *obj);
49 static
50 int init_trace_packet_header(struct bt_ctf_trace *trace);
51 static
52 void bt_ctf_trace_freeze(struct bt_ctf_trace *trace);
53
54 static
55 const 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
62 static
63 const 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
72 struct 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);
82 bt_object_init(trace, bt_ctf_trace_destroy);
83 trace->clocks = g_ptr_array_new_with_free_func(
84 (GDestroyNotify) bt_put);
85 trace->streams = g_ptr_array_new_with_free_func(
86 (GDestroyNotify) bt_object_release);
87 trace->stream_classes = g_ptr_array_new_with_free_func(
88 (GDestroyNotify) bt_object_release);
89 if (!trace->clocks || !trace->stream_classes || !trace->streams) {
90 goto error;
91 }
92
93 /* Generate a trace UUID */
94 uuid_generate(trace->uuid);
95 if (init_trace_packet_header(trace)) {
96 goto error;
97 }
98
99 /* Create the environment array object */
100 trace->environment = bt_ctf_attributes_create();
101 if (!trace->environment) {
102 goto error;
103 }
104
105 return trace;
106
107 error:
108 BT_PUT(trace);
109 return trace;
110 }
111
112 void bt_ctf_trace_destroy(struct bt_object *obj)
113 {
114 struct bt_ctf_trace *trace;
115
116 trace = container_of(obj, struct bt_ctf_trace, base);
117 if (trace->environment) {
118 bt_ctf_attributes_destroy(trace->environment);
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
133 bt_put(trace->packet_header_type);
134 g_free(trace);
135 }
136
137 struct 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
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) {
156 ret = bt_ctf_trace_add_stream_class(trace, stream_class);
157 if (ret) {
158 goto error;
159 }
160 }
161
162 stream = bt_ctf_stream_create(stream_class, trace);
163 if (!stream) {
164 goto error;
165 }
166
167 g_ptr_array_add(trace->streams, stream);
168 return stream;
169 error:
170 BT_PUT(stream);
171 return stream;
172 }
173
174 int bt_ctf_trace_set_environment_field(struct bt_ctf_trace *trace,
175 const char *name, struct bt_value *value)
176 {
177 int ret = 0;
178
179 if (!trace || !name || !value ||
180 bt_ctf_validate_identifier(name) ||
181 !(bt_value_is_integer(value) || bt_value_is_string(value))) {
182 ret = -1;
183 goto end;
184 }
185
186 if (strchr(name, ' ')) {
187 ret = -1;
188 goto end;
189 }
190
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 */
198 struct bt_value *attribute =
199 bt_ctf_attributes_get_field_value_by_name(
200 trace->environment, name);
201
202 if (attribute) {
203 BT_PUT(attribute);
204 ret = -1;
205 goto end;
206 }
207
208 bt_value_freeze(value);
209 }
210
211 ret = bt_ctf_attributes_set_field_value(trace->environment, name,
212 value);
213
214 end:
215 return ret;
216 }
217
218 int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace,
219 const char *name, const char *value)
220 {
221 int ret = 0;
222 struct bt_value *env_value_string_obj = NULL;
223
224 if (!trace || !name || !value) {
225 ret = -1;
226 goto end;
227 }
228
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 */
234 struct bt_value *attribute =
235 bt_ctf_attributes_get_field_value_by_name(
236 trace->environment, name);
237
238 if (attribute) {
239 BT_PUT(attribute);
240 ret = -1;
241 goto end;
242 }
243 }
244
245 env_value_string_obj = bt_value_string_create_init(value);
246
247 if (!env_value_string_obj) {
248 ret = -1;
249 goto end;
250 }
251
252 if (trace->frozen) {
253 bt_value_freeze(env_value_string_obj);
254 }
255 ret = bt_ctf_trace_set_environment_field(trace, name,
256 env_value_string_obj);
257
258 end:
259 BT_PUT(env_value_string_obj);
260 return ret;
261 }
262
263 int bt_ctf_trace_set_environment_field_integer(struct bt_ctf_trace *trace,
264 const char *name, int64_t value)
265 {
266 int ret = 0;
267 struct bt_value *env_value_integer_obj = NULL;
268
269 if (!trace || !name) {
270 ret = -1;
271 goto end;
272 }
273
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 */
279 struct bt_value *attribute =
280 bt_ctf_attributes_get_field_value_by_name(
281 trace->environment, name);
282
283 if (attribute) {
284 BT_PUT(attribute);
285 ret = -1;
286 goto end;
287 }
288 }
289
290 env_value_integer_obj = bt_value_integer_create_init(value);
291 if (!env_value_integer_obj) {
292 ret = -1;
293 goto end;
294 }
295
296 ret = bt_ctf_trace_set_environment_field(trace, name,
297 env_value_integer_obj);
298 if (trace->frozen) {
299 bt_value_freeze(env_value_integer_obj);
300 }
301 end:
302 BT_PUT(env_value_integer_obj);
303 return ret;
304 }
305
306 int 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
315 ret = bt_ctf_attributes_get_count(trace->environment);
316
317 end:
318 return ret;
319 }
320
321 const char *
322 bt_ctf_trace_get_environment_field_name(struct bt_ctf_trace *trace,
323 int index)
324 {
325 const char *ret = NULL;
326
327 if (!trace) {
328 goto end;
329 }
330
331 ret = bt_ctf_attributes_get_field_name(trace->environment, index);
332
333 end:
334 return ret;
335 }
336
337 struct bt_value *bt_ctf_trace_get_environment_field_value(
338 struct bt_ctf_trace *trace, int index)
339 {
340 struct bt_value *ret = NULL;
341
342 if (!trace) {
343 goto end;
344 }
345
346 ret = bt_ctf_attributes_get_field_value(trace->environment, index);
347
348 end:
349 return ret;
350 }
351
352 struct bt_value *bt_ctf_trace_get_environment_field_value_by_name(
353 struct bt_ctf_trace *trace, const char *name)
354 {
355 struct bt_value *ret = NULL;
356
357 if (!trace || !name) {
358 goto end;
359 }
360
361 ret = bt_ctf_attributes_get_field_value_by_name(trace->environment,
362 name);
363
364 end:
365 return ret;
366 }
367
368 int 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
386 bt_get(clock);
387 g_ptr_array_add(trace->clocks, clock);
388 end:
389 return ret;
390 }
391
392 int 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;
401 end:
402 return ret;
403 }
404
405 struct 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);
415 bt_get(clock);
416 end:
417 return clock;
418 }
419
420 int 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;
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;
437
438 if (!trace || !stream_class) {
439 ret = -1;
440 goto end;
441 }
442
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 */
448 for (i = 0; i < trace->stream_classes->len; i++) {
449 if (trace->stream_classes->pdata[i] == stream_class) {
450 /* Stream class already registered to the trace */
451 ret = -1;
452 goto end;
453 }
454 }
455
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
485 if (ret) {
486 /*
487 * This means something went wrong during the validation
488 * process, not that the objects are invalid.
489 */
490 goto end;
491 }
492
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
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
565 if (bt_ctf_stream_class_set_id_no_check(stream_class,
566 stream_id)) {
567 /* TODO Should retry with a different stream id */
568 ret = -1;
569 goto end;
570 }
571 }
572
573 bt_object_set_parent(stream_class, trace);
574 g_ptr_array_add(trace->stream_classes, stream_class);
575
576 /*
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 /*
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);
616 bt_ctf_stream_class_set_byte_order(stream_class, trace->byte_order);
617
618 /*
619 * Freeze the trace and the stream class.
620 */
621 bt_ctf_stream_class_freeze(stream_class);
622 bt_ctf_trace_freeze(trace);
623
624 end:
625 if (ret) {
626 bt_object_set_parent(stream_class, NULL);
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 }
634 }
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
643 return ret;
644 }
645
646 int 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;
656 end:
657 return ret;
658 }
659
660 struct 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);
670 bt_get(stream_class);
671 end:
672 return stream_class;
673 }
674
675 struct 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;
694 bt_get(stream_class);
695 goto end;
696 }
697 }
698
699 end:
700 return stream_class;
701 }
702
703 struct 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;
724 bt_get(clock);
725 goto end;
726 }
727 }
728
729 end:
730 return clock;
731 }
732
733 BT_HIDDEN
734 const 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
753 static
754 int 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, "");
777 ret = bt_ctf_field_type_serialize(trace->packet_header_type,
778 context);
779 if (ret) {
780 goto end;
781 }
782 context->current_indentation_level--;
783
784 g_string_append(context->string, ";\n};\n\n");
785 end:
786 return ret;
787 }
788
789 static
790 void append_env_metadata(struct bt_ctf_trace *trace,
791 struct metadata_context *context)
792 {
793 int i;
794 int env_size;
795
796 env_size = bt_ctf_attributes_get_count(trace->environment);
797
798 if (env_size <= 0) {
799 return;
800 }
801
802 g_string_append(context->string, "env {\n");
803
804 for (i = 0; i < env_size; ++i) {
805 struct bt_value *env_field_value_obj = NULL;
806 const char *entry_name;
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
817 switch (bt_value_get_type(env_field_value_obj)) {
818 case BT_VALUE_TYPE_INTEGER:
819 {
820 int ret;
821 int64_t int_value;
822
823 ret = bt_value_integer_get(env_field_value_obj,
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;
834 }
835 case BT_VALUE_TYPE_STRING:
836 {
837 int ret;
838 const char *str_value;
839 char *escaped_str = NULL;
840
841 ret = bt_value_string_get(env_field_value_obj,
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
864 loop_next:
865 BT_PUT(env_field_value_obj);
866 }
867
868 g_string_append(context->string, "};\n\n");
869 }
870
871 char *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;
906 error:
907 g_string_free(context->string, err ? TRUE : FALSE);
908 g_string_free(context->field_name, TRUE);
909 g_free(context);
910 end:
911 return metadata;
912 }
913
914 enum 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 }
932 end:
933 return ret;
934 }
935
936 int 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:
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) ?
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;
974 end:
975 return ret;
976 }
977
978 struct 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
987 bt_get(trace->packet_header_type);
988 field_type = trace->packet_header_type;
989 end:
990 return field_type;
991 }
992
993 int 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) !=
1005 BT_CTF_TYPE_ID_STRUCT) {
1006 ret = -1;
1007 goto end;
1008 }
1009
1010 bt_get(packet_header_type);
1011 bt_put(trace->packet_header_type);
1012 trace->packet_header_type = packet_header_type;
1013 end:
1014 return ret;
1015 }
1016
1017 void bt_ctf_trace_get(struct bt_ctf_trace *trace)
1018 {
1019 bt_get(trace);
1020 }
1021
1022 void bt_ctf_trace_put(struct bt_ctf_trace *trace)
1023 {
1024 bt_put(trace);
1025
1026 }
1027
1028 BT_HIDDEN
1029 struct bt_ctf_field_type *get_field_type(enum field_type_alias alias)
1030 {
1031 unsigned int alignment, size;
1032 struct bt_ctf_field_type *field_type = NULL;
1033
1034 if (alias >= NR_FIELD_TYPE_ALIAS) {
1035 goto end;
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);
1042 end:
1043 return field_type;
1044 }
1045
1046 static
1047 void bt_ctf_trace_freeze(struct bt_ctf_trace *trace)
1048 {
1049 bt_ctf_field_type_freeze(trace->packet_header_type);
1050 bt_ctf_attributes_freeze(trace->environment);
1051 trace->frozen = 1;
1052 }
1053
1054 static
1055 int init_trace_packet_header(struct bt_ctf_trace *trace)
1056 {
1057 int ret = 0;
1058 struct bt_ctf_field *magic = NULL, *uuid_array = NULL;
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
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
1091 ret = bt_ctf_trace_set_packet_header_type(trace,
1092 trace_packet_header_type);
1093 if (ret) {
1094 goto end;
1095 }
1096 end:
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);
1103 return ret;
1104 }
This page took 0.049845 seconds and 3 git commands to generate.