ir: bt_ctf_trace_add_stream_class(): add stream class's clock
[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-ir/event-class.h>
35 #include <babeltrace/ctf-ir/event-class-internal.h>
36 #include <babeltrace/ctf-writer/functor-internal.h>
37 #include <babeltrace/ctf-ir/field-types-internal.h>
38 #include <babeltrace/ctf-ir/attributes-internal.h>
39 #include <babeltrace/ctf-ir/validation-internal.h>
40 #include <babeltrace/ctf-ir/utils.h>
41 #include <babeltrace/compiler.h>
42 #include <babeltrace/values.h>
43 #include <babeltrace/ref.h>
44 #include <babeltrace/endian.h>
45
46 #define DEFAULT_IDENTIFIER_SIZE 128
47 #define DEFAULT_METADATA_STRING_SIZE 4096
48
49 static
50 void bt_ctf_trace_destroy(struct bt_object *obj);
51 static
52 int init_trace_packet_header(struct bt_ctf_trace *trace);
53 static
54 void bt_ctf_trace_freeze(struct bt_ctf_trace *trace);
55
56 static
57 const 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
64 static
65 const 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
74 struct 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);
84 bt_object_init(trace, bt_ctf_trace_destroy);
85 trace->clocks = g_ptr_array_new_with_free_func(
86 (GDestroyNotify) bt_put);
87 trace->streams = g_ptr_array_new_with_free_func(
88 (GDestroyNotify) bt_object_release);
89 trace->stream_classes = g_ptr_array_new_with_free_func(
90 (GDestroyNotify) bt_object_release);
91 if (!trace->clocks || !trace->stream_classes || !trace->streams) {
92 goto error;
93 }
94
95 /* Generate a trace UUID */
96 uuid_generate(trace->uuid);
97 if (init_trace_packet_header(trace)) {
98 goto error;
99 }
100
101 /* Create the environment array object */
102 trace->environment = bt_ctf_attributes_create();
103 if (!trace->environment) {
104 goto error;
105 }
106
107 return trace;
108
109 error:
110 BT_PUT(trace);
111 return trace;
112 }
113
114 void bt_ctf_trace_destroy(struct bt_object *obj)
115 {
116 struct bt_ctf_trace *trace;
117
118 trace = container_of(obj, struct bt_ctf_trace, base);
119 if (trace->environment) {
120 bt_ctf_attributes_destroy(trace->environment);
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
135 bt_put(trace->packet_header_type);
136 g_free(trace);
137 }
138
139 struct 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
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) {
158 ret = bt_ctf_trace_add_stream_class(trace, stream_class);
159 if (ret) {
160 goto error;
161 }
162 }
163
164 stream = bt_ctf_stream_create(stream_class, trace);
165 if (!stream) {
166 goto error;
167 }
168
169 g_ptr_array_add(trace->streams, stream);
170 return stream;
171 error:
172 BT_PUT(stream);
173 return stream;
174 }
175
176 int bt_ctf_trace_set_environment_field(struct bt_ctf_trace *trace,
177 const char *name, struct bt_value *value)
178 {
179 int ret = 0;
180
181 if (!trace || !name || !value ||
182 bt_ctf_validate_identifier(name) ||
183 !(bt_value_is_integer(value) || bt_value_is_string(value))) {
184 ret = -1;
185 goto end;
186 }
187
188 if (strchr(name, ' ')) {
189 ret = -1;
190 goto end;
191 }
192
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 */
200 struct bt_value *attribute =
201 bt_ctf_attributes_get_field_value_by_name(
202 trace->environment, name);
203
204 if (attribute) {
205 BT_PUT(attribute);
206 ret = -1;
207 goto end;
208 }
209
210 bt_value_freeze(value);
211 }
212
213 ret = bt_ctf_attributes_set_field_value(trace->environment, name,
214 value);
215
216 end:
217 return ret;
218 }
219
220 int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace,
221 const char *name, const char *value)
222 {
223 int ret = 0;
224 struct bt_value *env_value_string_obj = NULL;
225
226 if (!trace || !name || !value) {
227 ret = -1;
228 goto end;
229 }
230
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 */
236 struct bt_value *attribute =
237 bt_ctf_attributes_get_field_value_by_name(
238 trace->environment, name);
239
240 if (attribute) {
241 BT_PUT(attribute);
242 ret = -1;
243 goto end;
244 }
245 }
246
247 env_value_string_obj = bt_value_string_create_init(value);
248
249 if (!env_value_string_obj) {
250 ret = -1;
251 goto end;
252 }
253
254 if (trace->frozen) {
255 bt_value_freeze(env_value_string_obj);
256 }
257 ret = bt_ctf_trace_set_environment_field(trace, name,
258 env_value_string_obj);
259
260 end:
261 BT_PUT(env_value_string_obj);
262 return ret;
263 }
264
265 int bt_ctf_trace_set_environment_field_integer(struct bt_ctf_trace *trace,
266 const char *name, int64_t value)
267 {
268 int ret = 0;
269 struct bt_value *env_value_integer_obj = NULL;
270
271 if (!trace || !name) {
272 ret = -1;
273 goto end;
274 }
275
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 */
281 struct bt_value *attribute =
282 bt_ctf_attributes_get_field_value_by_name(
283 trace->environment, name);
284
285 if (attribute) {
286 BT_PUT(attribute);
287 ret = -1;
288 goto end;
289 }
290 }
291
292 env_value_integer_obj = bt_value_integer_create_init(value);
293 if (!env_value_integer_obj) {
294 ret = -1;
295 goto end;
296 }
297
298 ret = bt_ctf_trace_set_environment_field(trace, name,
299 env_value_integer_obj);
300 if (trace->frozen) {
301 bt_value_freeze(env_value_integer_obj);
302 }
303 end:
304 BT_PUT(env_value_integer_obj);
305 return ret;
306 }
307
308 int 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
317 ret = bt_ctf_attributes_get_count(trace->environment);
318
319 end:
320 return ret;
321 }
322
323 const char *
324 bt_ctf_trace_get_environment_field_name(struct bt_ctf_trace *trace,
325 int index)
326 {
327 const char *ret = NULL;
328
329 if (!trace) {
330 goto end;
331 }
332
333 ret = bt_ctf_attributes_get_field_name(trace->environment, index);
334
335 end:
336 return ret;
337 }
338
339 struct bt_value *bt_ctf_trace_get_environment_field_value(
340 struct bt_ctf_trace *trace, int index)
341 {
342 struct bt_value *ret = NULL;
343
344 if (!trace) {
345 goto end;
346 }
347
348 ret = bt_ctf_attributes_get_field_value(trace->environment, index);
349
350 end:
351 return ret;
352 }
353
354 struct bt_value *bt_ctf_trace_get_environment_field_value_by_name(
355 struct bt_ctf_trace *trace, const char *name)
356 {
357 struct bt_value *ret = NULL;
358
359 if (!trace || !name) {
360 goto end;
361 }
362
363 ret = bt_ctf_attributes_get_field_value_by_name(trace->environment,
364 name);
365
366 end:
367 return ret;
368 }
369
370 int 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
388 bt_get(clock);
389 g_ptr_array_add(trace->clocks, clock);
390
391 if (trace->frozen) {
392 bt_ctf_clock_freeze(clock);
393 }
394 end:
395 return ret;
396 }
397
398 int 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;
407 end:
408 return ret;
409 }
410
411 struct 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);
421 bt_get(clock);
422 end:
423 return clock;
424 }
425
426 int 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;
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;
443 struct bt_ctf_clock *clock_to_add_to_trace = NULL;
444
445 if (!trace || !stream_class) {
446 ret = -1;
447 goto end;
448 }
449
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 */
455 for (i = 0; i < trace->stream_classes->len; i++) {
456 if (trace->stream_classes->pdata[i] == stream_class) {
457 /* Stream class already registered to the trace */
458 ret = -1;
459 goto end;
460 }
461 }
462
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
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
518 if (ret) {
519 /*
520 * This means something went wrong during the validation
521 * process, not that the objects are invalid.
522 */
523 goto end;
524 }
525
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 */
544 for (i = 0; i < event_class_count; i++) {
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
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
598 if (bt_ctf_stream_class_set_id_no_check(stream_class,
599 stream_id)) {
600 /* TODO Should retry with a different stream id */
601 ret = -1;
602 goto end;
603 }
604 }
605
606 bt_object_set_parent(stream_class, trace);
607 g_ptr_array_add(trace->stream_classes, stream_class);
608
609 /*
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
627 for (i = 0; i < event_class_count; i++) {
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 /*
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);
649 bt_ctf_stream_class_set_byte_order(stream_class, trace->byte_order);
650
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
658 /*
659 * Freeze the trace and the stream class.
660 */
661 bt_ctf_stream_class_freeze(stream_class);
662 bt_ctf_trace_freeze(trace);
663
664 end:
665 if (ret) {
666 bt_object_set_parent(stream_class, NULL);
667
668 if (ec_validation_outputs) {
669 for (i = 0; i < event_class_count; i++) {
670 bt_ctf_validation_output_put_types(
671 &ec_validation_outputs[i]);
672 }
673 }
674 }
675
676 g_free(ec_validation_outputs);
677 bt_ctf_validation_output_put_types(&trace_sc_validation_output);
678 BT_PUT(clock_to_add_to_trace);
679 assert(!packet_header_type);
680 assert(!packet_context_type);
681 assert(!event_header_type);
682 assert(!stream_event_ctx_type);
683
684 return ret;
685 }
686
687 int 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;
697 end:
698 return ret;
699 }
700
701 struct 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);
711 bt_get(stream_class);
712 end:
713 return stream_class;
714 }
715
716 struct 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
726 for (i = 0; i < trace->stream_classes->len; i++) {
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;
735 bt_get(stream_class);
736 goto end;
737 }
738 }
739
740 end:
741 return stream_class;
742 }
743
744 struct 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
754 for (i = 0; i < trace->clocks->len; i++) {
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;
765 bt_get(clock);
766 goto end;
767 }
768 }
769
770 end:
771 return clock;
772 }
773
774 BT_HIDDEN
775 const 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
794 static
795 int 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, "");
818 ret = bt_ctf_field_type_serialize(trace->packet_header_type,
819 context);
820 if (ret) {
821 goto end;
822 }
823 context->current_indentation_level--;
824
825 g_string_append(context->string, ";\n};\n\n");
826 end:
827 return ret;
828 }
829
830 static
831 void append_env_metadata(struct bt_ctf_trace *trace,
832 struct metadata_context *context)
833 {
834 int i;
835 int env_size;
836
837 env_size = bt_ctf_attributes_get_count(trace->environment);
838
839 if (env_size <= 0) {
840 return;
841 }
842
843 g_string_append(context->string, "env {\n");
844
845 for (i = 0; i < env_size; i++) {
846 struct bt_value *env_field_value_obj = NULL;
847 const char *entry_name;
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
858 switch (bt_value_get_type(env_field_value_obj)) {
859 case BT_VALUE_TYPE_INTEGER:
860 {
861 int ret;
862 int64_t int_value;
863
864 ret = bt_value_integer_get(env_field_value_obj,
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;
875 }
876 case BT_VALUE_TYPE_STRING:
877 {
878 int ret;
879 const char *str_value;
880 char *escaped_str = NULL;
881
882 ret = bt_value_string_get(env_field_value_obj,
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
905 loop_next:
906 BT_PUT(env_field_value_obj);
907 }
908
909 g_string_append(context->string, "};\n\n");
910 }
911
912 char *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;
947 error:
948 g_string_free(context->string, err ? TRUE : FALSE);
949 g_string_free(context->field_name, TRUE);
950 g_free(context);
951 end:
952 return metadata;
953 }
954
955 enum 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 }
973 end:
974 return ret;
975 }
976
977 int 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:
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) ?
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;
1015 end:
1016 return ret;
1017 }
1018
1019 struct 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
1028 bt_get(trace->packet_header_type);
1029 field_type = trace->packet_header_type;
1030 end:
1031 return field_type;
1032 }
1033
1034 int 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) !=
1046 BT_CTF_TYPE_ID_STRUCT) {
1047 ret = -1;
1048 goto end;
1049 }
1050
1051 bt_get(packet_header_type);
1052 bt_put(trace->packet_header_type);
1053 trace->packet_header_type = packet_header_type;
1054 end:
1055 return ret;
1056 }
1057
1058 BT_HIDDEN
1059 struct bt_ctf_field_type *get_field_type(enum field_type_alias alias)
1060 {
1061 unsigned int alignment, size;
1062 struct bt_ctf_field_type *field_type = NULL;
1063
1064 if (alias >= NR_FIELD_TYPE_ALIAS) {
1065 goto end;
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);
1072 end:
1073 return field_type;
1074 }
1075
1076 static
1077 void bt_ctf_trace_freeze(struct bt_ctf_trace *trace)
1078 {
1079 int i;
1080
1081 bt_ctf_field_type_freeze(trace->packet_header_type);
1082 bt_ctf_attributes_freeze(trace->environment);
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
1091 trace->frozen = 1;
1092 }
1093
1094 static
1095 int init_trace_packet_header(struct bt_ctf_trace *trace)
1096 {
1097 int ret = 0;
1098 struct bt_ctf_field *magic = NULL, *uuid_array = NULL;
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
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
1131 ret = bt_ctf_trace_set_packet_header_type(trace,
1132 trace_packet_header_type);
1133 if (ret) {
1134 goto end;
1135 }
1136 end:
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);
1143 return ret;
1144 }
This page took 0.07486 seconds and 5 git commands to generate.