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