Standardize *get_*() functions
[babeltrace.git] / plugins / ctf / common / notif-iter / notif-iter.c
1 /*
2 * Babeltrace - CTF notification iterator
3 *
4 * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #include <stdint.h>
27 #include <inttypes.h>
28 #include <stdio.h>
29 #include <stddef.h>
30 #include <stdbool.h>
31 #include <assert.h>
32 #include <string.h>
33 #include <babeltrace/ctf-ir/field-types.h>
34 #include <babeltrace/ctf-ir/field-path.h>
35 #include <babeltrace/ctf-ir/fields.h>
36 #include <babeltrace/ctf-ir/stream-class.h>
37 #include <babeltrace/ctf-ir/packet.h>
38 #include <babeltrace/ctf-ir/stream.h>
39 #include <babeltrace/ctf-ir/clock-class.h>
40 #include <babeltrace/ctf-ir/event-class.h>
41 #include <babeltrace/graph/notification-packet.h>
42 #include <babeltrace/graph/notification-event.h>
43 #include <babeltrace/graph/notification-stream.h>
44 #include <babeltrace/graph/clock-class-priority-map.h>
45 #include <babeltrace/ref.h>
46 #include <glib.h>
47
48 #define PRINT_ERR_STREAM notit->err_stream
49 #define PRINT_PREFIX "ctf-notif-iter"
50 #include "../print.h"
51
52 #include "notif-iter.h"
53 #include "../btr/btr.h"
54
55 #define BYTES_TO_BITS(x) ((x) * 8)
56
57 struct bt_ctf_notif_iter;
58
59 /* A visit stack entry */
60 struct stack_entry {
61 /*
62 * Current base field, one of:
63 *
64 * * string
65 * * structure
66 * * array
67 * * sequence
68 * * variant
69 *
70 * Field is owned by this.
71 */
72 struct bt_ctf_field *base;
73
74 /* index of next field to set */
75 size_t index;
76 };
77
78 /* Visit stack */
79 struct stack {
80 /* Entries (struct stack_entry *) (top is last element) */
81 GPtrArray *entries;
82 };
83
84 /* State */
85 enum state {
86 STATE_INIT,
87 STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN,
88 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
89 STATE_AFTER_TRACE_PACKET_HEADER,
90 STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN,
91 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
92 STATE_AFTER_STREAM_PACKET_CONTEXT,
93 STATE_EMIT_NOTIF_NEW_PACKET,
94 STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN,
95 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE,
96 STATE_AFTER_STREAM_EVENT_HEADER,
97 STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN,
98 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE,
99 STATE_DSCOPE_EVENT_CONTEXT_BEGIN,
100 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE,
101 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
102 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE,
103 STATE_EMIT_NOTIF_EVENT,
104 STATE_EMIT_NOTIF_END_OF_PACKET,
105 STATE_SKIP_PACKET_PADDING,
106 };
107
108 struct trace_field_path_cache {
109 /*
110 * Indexes of the stream_id and stream_instance_id field in the packet
111 * header structure, -1 if unset.
112 */
113 int stream_id;
114 int stream_instance_id;
115 };
116
117 struct stream_class_field_path_cache {
118 /*
119 * Indexes of the v and id fields in the stream event header structure,
120 * -1 if unset.
121 */
122 int v;
123 int id;
124
125 /*
126 * index of the timestamp_end, packet_size and content_size fields in
127 * the stream packet context structure. Set to -1 if the fields were
128 * not found.
129 */
130 int timestamp_end;
131 int packet_size;
132 int content_size;
133 };
134
135 struct field_cb_override {
136 enum bt_ctf_btr_status (* func)(void *value,
137 struct bt_ctf_field_type *type, void *data);
138 void *data;
139 };
140
141 /* CTF notification iterator */
142 struct bt_ctf_notif_iter {
143 /* Visit stack */
144 struct stack *stack;
145
146 /* Error stream (may be NULL) */
147 FILE *err_stream;
148
149 /*
150 * Current dynamic scope field pointer.
151 *
152 * This is set when a dynamic scope field is first created by
153 * btr_compound_begin_cb(). It points to one of the fields in
154 * dscopes below.
155 */
156 struct bt_ctf_field **cur_dscope_field;
157
158 /* Trace and classes (owned by this) */
159 struct {
160 struct bt_ctf_trace *trace;
161 struct bt_ctf_stream_class *stream_class;
162 struct bt_ctf_event_class *event_class;
163 } meta;
164
165 /* Current packet (NULL if not created yet) */
166 struct bt_ctf_packet *packet;
167
168 /*
169 * Current timestamp_end field (to consider before switching packets).
170 */
171 struct bt_ctf_field *cur_timestamp_end;
172
173 /* Database of current dynamic scopes (owned by this) */
174 struct {
175 struct bt_ctf_field *trace_packet_header;
176 struct bt_ctf_field *stream_packet_context;
177 struct bt_ctf_field *stream_event_header;
178 struct bt_ctf_field *stream_event_context;
179 struct bt_ctf_field *event_context;
180 struct bt_ctf_field *event_payload;
181 } dscopes;
182
183 /*
184 * Special field overrides.
185 *
186 * Overrides are used to implement the behaviours of special fields such
187 * as "timestamp_end" (which must be ignored until the end of the
188 * packet), "id" (event id) which can be present multiple times and must
189 * be updated multiple time.
190 *
191 * This should be used to implement the behaviour of integer fields
192 * mapped to clocks and other "tagged" fields (in CTF 2).
193 *
194 * bt_ctf_field_type to struct field_cb_override
195 */
196 GHashTable *field_overrides;
197
198 /* Current state */
199 enum state state;
200
201 /* Current medium buffer data */
202 struct {
203 /* Last address provided by medium */
204 const uint8_t *addr;
205
206 /* Buffer size provided by medium (bytes) */
207 size_t sz;
208
209 /* Offset within whole packet of addr (bits) */
210 size_t packet_offset;
211
212 /* Current position from addr (bits) */
213 size_t at;
214 } buf;
215
216 /* Binary type reader */
217 struct bt_ctf_btr *btr;
218
219 /* Current medium data */
220 struct {
221 struct bt_ctf_notif_iter_medium_ops medops;
222 size_t max_request_sz;
223 void *data;
224 } medium;
225
226 /* Current packet size (bits) (-1 if unknown) */
227 int64_t cur_packet_size;
228
229 /* Current content size (bits) (-1 if unknown) */
230 int64_t cur_content_size;
231
232 /* bt_ctf_clock_class to uint64_t. */
233 GHashTable *clock_states;
234
235 /*
236 * Cache of the trace-constant field paths (event header type)
237 * associated to the current trace.
238 */
239 struct trace_field_path_cache trace_field_path_cache;
240
241 /*
242 * Field path cache associated with the current stream class.
243 * Ownership of this structure belongs to the field_path_caches HT.
244 */
245 struct stream_class_field_path_cache *cur_sc_field_path_cache;
246
247 /* bt_ctf_stream_class to struct stream_class_field_path_cache. */
248 GHashTable *sc_field_path_caches;
249 };
250
251 static
252 int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter *notit);
253
254 static
255 enum bt_ctf_btr_status btr_timestamp_end_cb(void *value,
256 struct bt_ctf_field_type *type, void *data);
257
258 static
259 void stack_entry_free_func(gpointer data)
260 {
261 struct stack_entry *entry = data;
262
263 bt_put(entry->base);
264 g_free(entry);
265 }
266
267 static
268 struct stack *stack_new(struct bt_ctf_notif_iter *notit)
269 {
270 struct stack *stack = NULL;
271
272 stack = g_new0(struct stack, 1);
273 if (!stack) {
274 goto error;
275 }
276
277 stack->entries = g_ptr_array_new_with_free_func(stack_entry_free_func);
278 if (!stack->entries) {
279 goto error;
280 }
281
282 return stack;
283 error:
284 g_free(stack);
285 return NULL;
286 }
287
288 static
289 void stack_destroy(struct stack *stack)
290 {
291 assert(stack);
292 g_ptr_array_free(stack->entries, TRUE);
293 g_free(stack);
294 }
295
296 static
297 int stack_push(struct stack *stack, struct bt_ctf_field *base)
298 {
299 int ret = 0;
300 struct stack_entry *entry;
301
302 assert(stack);
303 assert(base);
304 entry = g_new0(struct stack_entry, 1);
305 if (!entry) {
306 ret = -1;
307 goto end;
308 }
309
310 entry->base = bt_get(base);
311 g_ptr_array_add(stack->entries, entry);
312
313 end:
314 return ret;
315 }
316
317 static inline
318 unsigned int stack_size(struct stack *stack)
319 {
320 assert(stack);
321
322 return stack->entries->len;
323 }
324
325 static
326 void stack_pop(struct stack *stack)
327 {
328 assert(stack);
329 assert(stack_size(stack));
330 g_ptr_array_remove_index(stack->entries, stack->entries->len - 1);
331 }
332
333 static inline
334 struct stack_entry *stack_top(struct stack *stack)
335 {
336 assert(stack);
337 assert(stack_size(stack));
338
339 return g_ptr_array_index(stack->entries, stack->entries->len - 1);
340 }
341
342 static inline
343 bool stack_empty(struct stack *stack)
344 {
345 return stack_size(stack) == 0;
346 }
347
348 static
349 void stack_clear(struct stack *stack)
350 {
351 assert(stack);
352
353 if (!stack_empty(stack)) {
354 g_ptr_array_remove_range(stack->entries, 0, stack_size(stack));
355 }
356
357 assert(stack_empty(stack));
358 }
359
360 static inline
361 enum bt_ctf_notif_iter_status notif_iter_status_from_m_status(
362 enum bt_ctf_notif_iter_medium_status m_status)
363 {
364 return m_status;
365 }
366
367 static inline
368 size_t buf_size_bits(struct bt_ctf_notif_iter *notit)
369 {
370 return BYTES_TO_BITS(notit->buf.sz);
371 }
372
373 static inline
374 size_t buf_available_bits(struct bt_ctf_notif_iter *notit)
375 {
376 return buf_size_bits(notit) - notit->buf.at;
377 }
378
379 static inline
380 size_t packet_at(struct bt_ctf_notif_iter *notit)
381 {
382 return notit->buf.packet_offset + notit->buf.at;
383 }
384
385 static inline
386 size_t remaining_content_bits(struct bt_ctf_notif_iter *notit)
387 {
388 if (notit->cur_content_size == -1) {
389 return -1;
390 }
391
392 return notit->cur_content_size - packet_at(notit);
393 }
394
395 static inline
396 size_t remaining_packet_bits(struct bt_ctf_notif_iter *notit)
397 {
398 if (notit->cur_packet_size == -1) {
399 return -1;
400 }
401
402 return notit->cur_packet_size - packet_at(notit);
403 }
404
405 static inline
406 void buf_consume_bits(struct bt_ctf_notif_iter *notit, size_t incr)
407 {
408 notit->buf.at += incr;
409 }
410
411 static inline
412 bool buf_has_enough_bits(struct bt_ctf_notif_iter *notit, size_t sz)
413 {
414 return buf_available_bits(notit) >= sz;
415 }
416
417 static
418 enum bt_ctf_notif_iter_status request_medium_bytes(
419 struct bt_ctf_notif_iter *notit)
420 {
421 uint8_t *buffer_addr;
422 size_t buffer_sz;
423 enum bt_ctf_notif_iter_medium_status m_status;
424
425 m_status = notit->medium.medops.request_bytes(
426 notit->medium.max_request_sz, &buffer_addr,
427 &buffer_sz, notit->medium.data);
428 if (m_status == BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK) {
429 assert(buffer_sz != 0);
430
431 /* New packet offset is old one + old size (in bits) */
432 notit->buf.packet_offset += buf_size_bits(notit);
433
434 /* Restart at the beginning of the new medium buffer */
435 notit->buf.at = 0;
436
437 /* New medium buffer size */
438 notit->buf.sz = buffer_sz;
439
440 /* New medium buffer address */
441 notit->buf.addr = buffer_addr;
442 }
443
444 return notif_iter_status_from_m_status(m_status);
445 }
446
447 static inline
448 enum bt_ctf_notif_iter_status buf_ensure_available_bits(
449 struct bt_ctf_notif_iter *notit)
450 {
451 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
452
453 if (buf_available_bits(notit) == 0) {
454 /*
455 * This _cannot_ return BT_CTF_NOTIF_ITER_STATUS_OK
456 * _and_ no bits.
457 */
458 status = request_medium_bytes(notit);
459 }
460
461 return status;
462 }
463
464 static
465 enum bt_ctf_notif_iter_status read_dscope_begin_state(
466 struct bt_ctf_notif_iter *notit,
467 struct bt_ctf_field_type *dscope_field_type,
468 enum state done_state, enum state continue_state,
469 struct bt_ctf_field **dscope_field)
470 {
471 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
472 enum bt_ctf_btr_status btr_status;
473 size_t consumed_bits;
474
475 status = buf_ensure_available_bits(notit);
476 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
477 goto end;
478 }
479
480 bt_put(*dscope_field);
481 notit->cur_dscope_field = dscope_field;
482 consumed_bits = bt_ctf_btr_start(notit->btr, dscope_field_type,
483 notit->buf.addr, notit->buf.at, packet_at(notit),
484 notit->buf.sz, &btr_status);
485
486 switch (btr_status) {
487 case BT_CTF_BTR_STATUS_OK:
488 /* type was read completely */
489 notit->state = done_state;
490 break;
491 case BT_CTF_BTR_STATUS_EOF:
492 notit->state = continue_state;
493 break;
494 default:
495 PERR("Binary type reader failed to start\n");
496 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
497 goto end;
498 }
499
500 /* Consume bits now since we know we're not in an error state */
501 buf_consume_bits(notit, consumed_bits);
502
503 end:
504 return status;
505 }
506
507 static
508 enum bt_ctf_notif_iter_status read_dscope_continue_state(
509 struct bt_ctf_notif_iter *notit, enum state done_state)
510 {
511 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
512 enum bt_ctf_btr_status btr_status;
513 size_t consumed_bits;
514
515 status = buf_ensure_available_bits(notit);
516 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
517 goto end;
518 }
519
520 consumed_bits = bt_ctf_btr_continue(notit->btr, notit->buf.addr,
521 notit->buf.sz, &btr_status);
522
523 switch (btr_status) {
524 case BT_CTF_BTR_STATUS_OK:
525 /* Type was read completely. */
526 notit->state = done_state;
527 break;
528 case BT_CTF_BTR_STATUS_EOF:
529 /* Stay in this continue state. */
530 break;
531 default:
532 PERR("Binary type reader failed to continue\n");
533 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
534 goto end;
535 }
536
537 /* Consume bits now since we know we're not in an error state. */
538 buf_consume_bits(notit, consumed_bits);
539 end:
540 return status;
541 }
542
543 static
544 void put_event_dscopes(struct bt_ctf_notif_iter *notit)
545 {
546 BT_PUT(notit->dscopes.stream_event_header);
547 BT_PUT(notit->dscopes.stream_event_context);
548 BT_PUT(notit->dscopes.event_context);
549 BT_PUT(notit->dscopes.event_payload);
550 }
551
552 static
553 void put_all_dscopes(struct bt_ctf_notif_iter *notit)
554 {
555 BT_PUT(notit->dscopes.trace_packet_header);
556 BT_PUT(notit->dscopes.stream_packet_context);
557 put_event_dscopes(notit);
558 }
559
560 static
561 enum bt_ctf_notif_iter_status read_packet_header_begin_state(
562 struct bt_ctf_notif_iter *notit)
563 {
564 struct bt_ctf_field_type *packet_header_type = NULL;
565 enum bt_ctf_notif_iter_status ret = BT_CTF_NOTIF_ITER_STATUS_OK;
566
567 if (bt_ctf_notif_iter_switch_packet(notit)) {
568 ret = BT_CTF_NOTIF_ITER_STATUS_ERROR;
569 goto end;
570 }
571
572 /* Packet header type is common to the whole trace. */
573 packet_header_type = bt_ctf_trace_get_packet_header_type(
574 notit->meta.trace);
575 if (!packet_header_type) {
576 notit->state = STATE_AFTER_TRACE_PACKET_HEADER;
577 goto end;
578 }
579
580 ret = read_dscope_begin_state(notit, packet_header_type,
581 STATE_AFTER_TRACE_PACKET_HEADER,
582 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
583 &notit->dscopes.trace_packet_header);
584 end:
585 BT_PUT(packet_header_type);
586 return ret;
587 }
588
589 static
590 enum bt_ctf_notif_iter_status read_packet_header_continue_state(
591 struct bt_ctf_notif_iter *notit)
592 {
593 return read_dscope_continue_state(notit,
594 STATE_AFTER_TRACE_PACKET_HEADER);
595 }
596
597 static inline
598 bool is_struct_type(struct bt_ctf_field_type *field_type)
599 {
600 return bt_ctf_field_type_get_type_id(field_type) ==
601 BT_CTF_FIELD_TYPE_ID_STRUCT;
602 }
603
604 static inline
605 bool is_variant_type(struct bt_ctf_field_type *field_type)
606 {
607 return bt_ctf_field_type_get_type_id(field_type) ==
608 BT_CTF_FIELD_TYPE_ID_VARIANT;
609 }
610
611 static
612 struct stream_class_field_path_cache *
613 create_stream_class_field_path_cache_entry(
614 struct bt_ctf_notif_iter *notit,
615 struct bt_ctf_stream_class *stream_class)
616 {
617 int v = -1;
618 int id = -1;
619 int timestamp_end = -1;
620 int packet_size = -1;
621 int content_size = -1;
622 struct stream_class_field_path_cache *cache_entry = g_new0(
623 struct stream_class_field_path_cache, 1);
624 struct bt_ctf_field_type *event_header = NULL, *packet_context = NULL;
625
626 if (!cache_entry) {
627 goto end;
628 }
629
630 event_header = bt_ctf_stream_class_get_event_header_type(stream_class);
631 if (event_header && bt_ctf_field_type_is_structure(event_header)) {
632 int i, count;
633
634 count = bt_ctf_field_type_structure_get_field_count(
635 event_header);
636 if (count < 0) {
637 goto error;
638 }
639 for (i = 0; i < count; i++) {
640 int ret;
641 const char *name;
642
643 ret = bt_ctf_field_type_structure_get_field(
644 event_header, &name, NULL, i);
645 if (ret) {
646 goto error;
647 }
648
649 if (v != -1 && id != -1) {
650 break;
651 }
652 if (v == -1 && !strcmp(name, "v")) {
653 v = i;
654 } else if (id == -1 && !strcmp(name, "id")) {
655 id = i;
656 }
657 }
658 }
659
660 packet_context = bt_ctf_stream_class_get_packet_context_type(
661 stream_class);
662 if (packet_context && bt_ctf_field_type_is_structure(packet_context)) {
663 int i, count;
664
665 count = bt_ctf_field_type_structure_get_field_count(
666 packet_context);
667 if (count < 0) {
668 goto error;
669 }
670 for (i = 0; i < count; i++) {
671 int ret;
672 const char *name;
673 struct bt_ctf_field_type *field_type;
674
675 if (timestamp_end != -1 && packet_size != -1 &&
676 content_size != -1) {
677 break;
678 }
679
680 ret = bt_ctf_field_type_structure_get_field(
681 packet_context, &name, &field_type, i);
682 if (ret) {
683 goto error;
684 }
685
686 if (timestamp_end == -1 &&
687 !strcmp(name, "timestamp_end")) {
688 struct field_cb_override *override = g_new0(
689 struct field_cb_override, 1);
690
691 if (!override) {
692 BT_PUT(field_type);
693 goto error;
694 }
695
696 override->func = btr_timestamp_end_cb;
697 override->data = notit;
698
699 g_hash_table_insert(notit->field_overrides,
700 bt_get(field_type), override);
701
702 timestamp_end = i;
703 } else if (packet_size == -1 &&
704 !strcmp(name, "packet_size")) {
705 packet_size = i;
706 } else if (content_size == -1 &&
707 !strcmp(name, "content_size")) {
708 content_size = i;
709 }
710 BT_PUT(field_type);
711 }
712 }
713
714 cache_entry->v = v;
715 cache_entry->id = id;
716 cache_entry->timestamp_end = timestamp_end;
717 cache_entry->packet_size = packet_size;
718 cache_entry->content_size = content_size;
719 end:
720 BT_PUT(event_header);
721 BT_PUT(packet_context);
722 return cache_entry;
723 error:
724 g_free(cache_entry);
725 cache_entry = NULL;
726 goto end;
727 }
728
729 static
730 struct stream_class_field_path_cache *get_stream_class_field_path_cache(
731 struct bt_ctf_notif_iter *notit,
732 struct bt_ctf_stream_class *stream_class)
733 {
734 bool cache_entry_found;
735 struct stream_class_field_path_cache *cache_entry;
736
737 cache_entry_found = g_hash_table_lookup_extended(
738 notit->sc_field_path_caches,
739 stream_class, NULL, (gpointer) &cache_entry);
740 if (unlikely(!cache_entry_found)) {
741 cache_entry = create_stream_class_field_path_cache_entry(notit,
742 stream_class);
743 g_hash_table_insert(notit->sc_field_path_caches,
744 bt_get(stream_class), (gpointer) cache_entry);
745 }
746
747 return cache_entry;
748 }
749
750 static inline
751 enum bt_ctf_notif_iter_status set_current_stream_class(
752 struct bt_ctf_notif_iter *notit)
753 {
754 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
755 struct bt_ctf_field_type *packet_header_type = NULL;
756 struct bt_ctf_field_type *stream_id_field_type = NULL;
757 uint64_t stream_id;
758
759 /* Clear the current stream class field path cache. */
760 notit->cur_sc_field_path_cache = NULL;
761
762 /* Is there any "stream_id" field in the packet header? */
763 packet_header_type = bt_ctf_trace_get_packet_header_type(
764 notit->meta.trace);
765 if (!packet_header_type) {
766 PERR("Failed to retrieve trace's packet header type\n");
767 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
768 goto end;
769 }
770
771 assert(is_struct_type(packet_header_type));
772
773 // TODO: optimalize!
774 stream_id_field_type =
775 bt_ctf_field_type_structure_get_field_type_by_name(
776 packet_header_type, "stream_id");
777 if (stream_id_field_type) {
778 /* Find appropriate stream class using current stream ID */
779 int ret;
780 struct bt_ctf_field *stream_id_field = NULL;
781
782 assert(notit->dscopes.trace_packet_header);
783
784 // TODO: optimalize!
785 stream_id_field = bt_ctf_field_structure_get_field(
786 notit->dscopes.trace_packet_header, "stream_id");
787 assert(stream_id_field);
788 ret = bt_ctf_field_unsigned_integer_get_value(
789 stream_id_field, &stream_id);
790 assert(!ret);
791 BT_PUT(stream_id_field);
792 } else {
793 /* Only one stream: pick the first stream class */
794 assert(bt_ctf_trace_get_stream_class_count(
795 notit->meta.trace) == 1);
796 stream_id = 0;
797 }
798
799 BT_PUT(notit->meta.stream_class);
800 notit->meta.stream_class = bt_ctf_trace_get_stream_class_by_id(
801 notit->meta.trace, stream_id);
802 if (!notit->meta.stream_class) {
803 PERR("Cannot find stream class with ID %" PRIu64 "\n",
804 stream_id);
805 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
806 goto end;
807 }
808
809 /*
810 * Retrieve (or lazily create) the current stream class field path
811 * cache.
812 */
813 notit->cur_sc_field_path_cache = get_stream_class_field_path_cache(
814 notit, notit->meta.stream_class);
815 if (!notit->cur_sc_field_path_cache) {
816 PERR("Failed to retrieve stream class field path cache\n");
817 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
818 goto end;
819 }
820 end:
821 BT_PUT(packet_header_type);
822 BT_PUT(stream_id_field_type);
823
824 return status;
825 }
826
827 static
828 enum bt_ctf_notif_iter_status after_packet_header_state(
829 struct bt_ctf_notif_iter *notit)
830 {
831 enum bt_ctf_notif_iter_status status;
832
833 status = set_current_stream_class(notit);
834 if (status == BT_CTF_NOTIF_ITER_STATUS_OK) {
835 notit->state = STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN;
836 }
837
838 return status;
839 }
840
841 static
842 enum bt_ctf_notif_iter_status read_packet_context_begin_state(
843 struct bt_ctf_notif_iter *notit)
844 {
845 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
846 struct bt_ctf_field_type *packet_context_type;
847
848 assert(notit->meta.stream_class);
849 packet_context_type = bt_ctf_stream_class_get_packet_context_type(
850 notit->meta.stream_class);
851 if (!packet_context_type) {
852 notit->state = STATE_AFTER_STREAM_PACKET_CONTEXT;
853 goto end;
854 }
855
856 status = read_dscope_begin_state(notit, packet_context_type,
857 STATE_AFTER_STREAM_PACKET_CONTEXT,
858 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
859 &notit->dscopes.stream_packet_context);
860
861 end:
862 BT_PUT(packet_context_type);
863 return status;
864 }
865
866 static
867 enum bt_ctf_notif_iter_status read_packet_context_continue_state(
868 struct bt_ctf_notif_iter *notit)
869 {
870 return read_dscope_continue_state(notit,
871 STATE_AFTER_STREAM_PACKET_CONTEXT);
872 }
873
874 static
875 enum bt_ctf_notif_iter_status set_current_packet_content_sizes(
876 struct bt_ctf_notif_iter *notit)
877 {
878 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
879 struct bt_ctf_field *packet_size_field = NULL;
880 struct bt_ctf_field *content_size_field = NULL;
881 uint64_t content_size = -1, packet_size = -1;
882
883 assert(notit->dscopes.stream_packet_context);
884
885 packet_size_field = bt_ctf_field_structure_get_field(
886 notit->dscopes.stream_packet_context, "packet_size");
887 content_size_field = bt_ctf_field_structure_get_field(
888 notit->dscopes.stream_packet_context, "content_size");
889 if (packet_size_field) {
890 int ret = bt_ctf_field_unsigned_integer_get_value(
891 packet_size_field, &packet_size);
892
893 assert(!ret);
894 if (packet_size == 0) {
895 PERR("Decoded packet size is 0\n");
896 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
897 goto end;
898 } else if ((packet_size % 8) != 0) {
899 PERR("Decoded packet size is not a multiple of 8\n");
900 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
901 goto end;
902 }
903 }
904
905 if (content_size_field) {
906 int ret = bt_ctf_field_unsigned_integer_get_value(
907 content_size_field, &content_size);
908
909 assert(!ret);
910 } else {
911 content_size = packet_size;
912 }
913
914 notit->cur_packet_size = packet_size;
915 notit->cur_content_size = content_size;
916 end:
917 BT_PUT(packet_size_field);
918 BT_PUT(content_size_field);
919 return status;
920 }
921
922 static
923 enum bt_ctf_notif_iter_status after_packet_context_state(
924 struct bt_ctf_notif_iter *notit)
925 {
926 enum bt_ctf_notif_iter_status status;
927
928 status = set_current_packet_content_sizes(notit);
929 if (status == BT_CTF_NOTIF_ITER_STATUS_OK) {
930 notit->state = STATE_EMIT_NOTIF_NEW_PACKET;
931 }
932
933 return status;
934 }
935
936 static
937 enum bt_ctf_notif_iter_status read_event_header_begin_state(
938 struct bt_ctf_notif_iter *notit)
939 {
940 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
941 struct bt_ctf_field_type *event_header_type = NULL;
942
943 /* Check if we have some content left */
944 if (notit->cur_content_size >= 0) {
945 if (packet_at(notit) == notit->cur_content_size) {
946 /* No more events! */
947 notit->state = STATE_EMIT_NOTIF_END_OF_PACKET;
948 goto end;
949 } else if (packet_at(notit) > notit->cur_content_size) {
950 /* That's not supposed to happen */
951 PERR("Cursor passed packet's content size:\n");
952 PERR("\tDecoded content size: %zu\n",
953 notit->cur_content_size);
954 PERR("\tCursor position: %zu\n", packet_at(notit));
955 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
956 goto end;
957 }
958 }
959
960 event_header_type = bt_ctf_stream_class_get_event_header_type(
961 notit->meta.stream_class);
962 if (!event_header_type) {
963 notit->state = STATE_AFTER_STREAM_EVENT_HEADER;
964 goto end;
965 }
966
967 put_event_dscopes(notit);
968 status = read_dscope_begin_state(notit, event_header_type,
969 STATE_AFTER_STREAM_EVENT_HEADER,
970 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE,
971 &notit->dscopes.stream_event_header);
972 end:
973 BT_PUT(event_header_type);
974
975 return status;
976 }
977
978 static
979 enum bt_ctf_notif_iter_status read_event_header_continue_state(
980 struct bt_ctf_notif_iter *notit)
981 {
982 return read_dscope_continue_state(notit,
983 STATE_AFTER_STREAM_EVENT_HEADER);
984 }
985
986 static inline
987 enum bt_ctf_notif_iter_status set_current_event_class(struct bt_ctf_notif_iter *notit)
988 {
989 /*
990 * The assert() calls in this function are okay because it is
991 * assumed here that all the metadata objects have been
992 * validated for CTF correctness before decoding actual streams.
993 */
994
995 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
996 struct bt_ctf_field_type *event_header_type;
997 struct bt_ctf_field_type *id_field_type = NULL;
998 struct bt_ctf_field_type *v_field_type = NULL;
999 uint64_t event_id = -1ULL;
1000 int ret;
1001
1002 event_header_type = bt_ctf_stream_class_get_event_header_type(
1003 notit->meta.stream_class);
1004 if (!event_header_type) {
1005 PERR("Failed to retrieve stream class's event header type\n");
1006 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
1007 goto end;
1008 }
1009
1010 /* Is there any "id"/"v" field in the event header? */
1011 assert(is_struct_type(event_header_type));
1012 id_field_type = bt_ctf_field_type_structure_get_field_type_by_name(
1013 event_header_type, "id");
1014 v_field_type = bt_ctf_field_type_structure_get_field_type_by_name(
1015 event_header_type, "v");
1016 assert(notit->dscopes.stream_event_header);
1017 if (v_field_type) {
1018 /*
1019 * _ _____ _____
1020 * | | |_ _|_ _| __ __ _
1021 * | | | | | || '_ \ / _` |
1022 * | |___| | | || | | | (_| | S P E C I A L
1023 * |_____|_| |_||_| |_|\__, | C A S E â„¢
1024 * |___/
1025 */
1026 struct bt_ctf_field *v_field = NULL;
1027 struct bt_ctf_field *v_struct_field = NULL;
1028 struct bt_ctf_field *v_struct_id_field = NULL;
1029
1030 // TODO: optimalize!
1031 v_field = bt_ctf_field_structure_get_field(
1032 notit->dscopes.stream_event_header, "v");
1033 assert(v_field);
1034
1035 v_struct_field =
1036 bt_ctf_field_variant_get_current_field(v_field);
1037 if (!v_struct_field) {
1038 goto end_v_field_type;
1039 }
1040
1041 // TODO: optimalize!
1042 v_struct_id_field =
1043 bt_ctf_field_structure_get_field(v_struct_field, "id");
1044 if (!v_struct_id_field) {
1045 goto end_v_field_type;
1046 }
1047
1048 ret = bt_ctf_field_unsigned_integer_get_value(
1049 v_struct_id_field, &event_id);
1050 if (ret) {
1051 event_id = -1ULL;
1052 }
1053
1054 end_v_field_type:
1055 BT_PUT(v_field);
1056 BT_PUT(v_struct_field);
1057 BT_PUT(v_struct_id_field);
1058 }
1059
1060 if (id_field_type && event_id == -1ULL) {
1061 /* Check "id" field */
1062 struct bt_ctf_field *id_field = NULL;
1063 int ret;
1064
1065 // TODO: optimalize!
1066 id_field = bt_ctf_field_structure_get_field(
1067 notit->dscopes.stream_event_header, "id");
1068 assert(id_field);
1069 assert(bt_ctf_field_is_integer(id_field) ||
1070 bt_ctf_field_is_enumeration(id_field));
1071
1072 if (bt_ctf_field_is_integer(id_field)) {
1073 ret = bt_ctf_field_unsigned_integer_get_value(
1074 id_field, &event_id);
1075 } else {
1076 struct bt_ctf_field *container;
1077
1078 container = bt_ctf_field_enumeration_get_container(
1079 id_field);
1080 assert(container);
1081 ret = bt_ctf_field_unsigned_integer_get_value(
1082 container, &event_id);
1083 BT_PUT(container);
1084 }
1085 assert(!ret);
1086 BT_PUT(id_field);
1087 }
1088
1089 if (event_id == -1ULL) {
1090 /* Event ID not found: single event? */
1091 assert(bt_ctf_stream_class_get_event_class_count(
1092 notit->meta.stream_class) == 1);
1093 event_id = 0;
1094 }
1095
1096 BT_PUT(notit->meta.event_class);
1097 notit->meta.event_class = bt_ctf_stream_class_get_event_class_by_id(
1098 notit->meta.stream_class, event_id);
1099 if (!notit->meta.event_class) {
1100 PERR("Cannot find event class with ID %" PRIu64 "\n", event_id);
1101 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
1102 goto end;
1103 }
1104
1105 end:
1106 BT_PUT(event_header_type);
1107 BT_PUT(id_field_type);
1108 BT_PUT(v_field_type);
1109
1110 return status;
1111 }
1112
1113 static
1114 enum bt_ctf_notif_iter_status after_event_header_state(
1115 struct bt_ctf_notif_iter *notit)
1116 {
1117 enum bt_ctf_notif_iter_status status;
1118
1119 status = set_current_event_class(notit);
1120 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
1121 PERR("Failed to set current event class\n");
1122 goto end;
1123 }
1124
1125 notit->state = STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN;
1126
1127 end:
1128 return status;
1129 }
1130
1131 static
1132 enum bt_ctf_notif_iter_status read_stream_event_context_begin_state(
1133 struct bt_ctf_notif_iter *notit)
1134 {
1135 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
1136 struct bt_ctf_field_type *stream_event_context_type;
1137
1138 stream_event_context_type = bt_ctf_stream_class_get_event_context_type(
1139 notit->meta.stream_class);
1140 if (!stream_event_context_type) {
1141 notit->state = STATE_DSCOPE_EVENT_CONTEXT_BEGIN;
1142 goto end;
1143 }
1144
1145 status = read_dscope_begin_state(notit, stream_event_context_type,
1146 STATE_DSCOPE_EVENT_CONTEXT_BEGIN,
1147 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE,
1148 &notit->dscopes.stream_event_context);
1149
1150 end:
1151 BT_PUT(stream_event_context_type);
1152
1153 return status;
1154 }
1155
1156 static
1157 enum bt_ctf_notif_iter_status read_stream_event_context_continue_state(
1158 struct bt_ctf_notif_iter *notit)
1159 {
1160 return read_dscope_continue_state(notit,
1161 STATE_DSCOPE_EVENT_CONTEXT_BEGIN);
1162 }
1163
1164 static
1165 enum bt_ctf_notif_iter_status read_event_context_begin_state(
1166 struct bt_ctf_notif_iter *notit)
1167 {
1168 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
1169 struct bt_ctf_field_type *event_context_type;
1170
1171 event_context_type = bt_ctf_event_class_get_context_type(
1172 notit->meta.event_class);
1173 if (!event_context_type) {
1174 notit->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN;
1175 goto end;
1176 }
1177 status = read_dscope_begin_state(notit, event_context_type,
1178 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
1179 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE,
1180 &notit->dscopes.event_context);
1181
1182 end:
1183 BT_PUT(event_context_type);
1184
1185 return status;
1186 }
1187
1188 static
1189 enum bt_ctf_notif_iter_status read_event_context_continue_state(
1190 struct bt_ctf_notif_iter *notit)
1191 {
1192 return read_dscope_continue_state(notit,
1193 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN);
1194 }
1195
1196 static
1197 enum bt_ctf_notif_iter_status read_event_payload_begin_state(
1198 struct bt_ctf_notif_iter *notit)
1199 {
1200 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
1201 struct bt_ctf_field_type *event_payload_type;
1202
1203 event_payload_type = bt_ctf_event_class_get_payload_type(
1204 notit->meta.event_class);
1205 if (!event_payload_type) {
1206 notit->state = STATE_EMIT_NOTIF_EVENT;
1207 goto end;
1208 }
1209
1210 status = read_dscope_begin_state(notit, event_payload_type,
1211 STATE_EMIT_NOTIF_EVENT,
1212 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE,
1213 &notit->dscopes.event_payload);
1214
1215 end:
1216 BT_PUT(event_payload_type);
1217
1218 return status;
1219 }
1220
1221 static
1222 enum bt_ctf_notif_iter_status read_event_payload_continue_state(
1223 struct bt_ctf_notif_iter *notit)
1224 {
1225 return read_dscope_continue_state(notit, STATE_EMIT_NOTIF_EVENT);
1226 }
1227
1228 static
1229 enum bt_ctf_notif_iter_status skip_packet_padding_state(
1230 struct bt_ctf_notif_iter *notit)
1231 {
1232 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
1233 size_t bits_to_skip;
1234
1235 assert(notit->cur_packet_size > 0);
1236 bits_to_skip = notit->cur_packet_size - packet_at(notit);
1237 if (bits_to_skip == 0) {
1238 notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
1239 goto end;
1240 } else {
1241 size_t bits_to_consume;
1242 status = buf_ensure_available_bits(notit);
1243 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
1244 goto end;
1245 }
1246
1247 bits_to_consume = MIN(buf_available_bits(notit), bits_to_skip);
1248 buf_consume_bits(notit, bits_to_consume);
1249 bits_to_skip = notit->cur_packet_size - packet_at(notit);
1250 if (bits_to_skip == 0) {
1251 notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
1252 goto end;
1253 }
1254 }
1255
1256 end:
1257 return status;
1258 }
1259
1260 static inline
1261 enum bt_ctf_notif_iter_status handle_state(struct bt_ctf_notif_iter *notit)
1262 {
1263 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
1264
1265 PDBG("Handling state %d\n", notit->state);
1266
1267 // TODO: optimalize!
1268 switch (notit->state) {
1269 case STATE_INIT:
1270 notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
1271 break;
1272 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN:
1273 status = read_packet_header_begin_state(notit);
1274 break;
1275 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE:
1276 status = read_packet_header_continue_state(notit);
1277 break;
1278 case STATE_AFTER_TRACE_PACKET_HEADER:
1279 status = after_packet_header_state(notit);
1280 break;
1281 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN:
1282 status = read_packet_context_begin_state(notit);
1283 break;
1284 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE:
1285 status = read_packet_context_continue_state(notit);
1286 break;
1287 case STATE_AFTER_STREAM_PACKET_CONTEXT:
1288 status = after_packet_context_state(notit);
1289 break;
1290 case STATE_EMIT_NOTIF_NEW_PACKET:
1291 notit->state = STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN;
1292 break;
1293 case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN:
1294 status = read_event_header_begin_state(notit);
1295 break;
1296 case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE:
1297 status = read_event_header_continue_state(notit);
1298 break;
1299 case STATE_AFTER_STREAM_EVENT_HEADER:
1300 status = after_event_header_state(notit);
1301 break;
1302 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN:
1303 status = read_stream_event_context_begin_state(notit);
1304 break;
1305 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE:
1306 status = read_stream_event_context_continue_state(notit);
1307 break;
1308 case STATE_DSCOPE_EVENT_CONTEXT_BEGIN:
1309 status = read_event_context_begin_state(notit);
1310 break;
1311 case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE:
1312 status = read_event_context_continue_state(notit);
1313 break;
1314 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN:
1315 status = read_event_payload_begin_state(notit);
1316 break;
1317 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE:
1318 status = read_event_payload_continue_state(notit);
1319 break;
1320 case STATE_EMIT_NOTIF_EVENT:
1321 notit->state = STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN;
1322 break;
1323 case STATE_SKIP_PACKET_PADDING:
1324 status = skip_packet_padding_state(notit);
1325 break;
1326 case STATE_EMIT_NOTIF_END_OF_PACKET:
1327 notit->state = STATE_SKIP_PACKET_PADDING;
1328 break;
1329 }
1330
1331 return status;
1332 }
1333
1334 /**
1335 * Resets the internal state of a CTF notification iterator.
1336 */
1337 static
1338 void bt_ctf_notif_iter_reset(struct bt_ctf_notif_iter *notit)
1339 {
1340 assert(notit);
1341 stack_clear(notit->stack);
1342 BT_PUT(notit->meta.stream_class);
1343 BT_PUT(notit->meta.event_class);
1344 BT_PUT(notit->packet);
1345 put_all_dscopes(notit);
1346 notit->buf.addr = NULL;
1347 notit->buf.sz = 0;
1348 notit->buf.at = 0;
1349 notit->buf.packet_offset = 0;
1350 notit->state = STATE_INIT;
1351 notit->cur_content_size = -1;
1352 notit->cur_packet_size = -1;
1353 }
1354
1355 static
1356 int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter *notit)
1357 {
1358 int ret = 0;
1359
1360 assert(notit);
1361 stack_clear(notit->stack);
1362 BT_PUT(notit->meta.stream_class);
1363 BT_PUT(notit->meta.event_class);
1364 BT_PUT(notit->packet);
1365 BT_PUT(notit->cur_timestamp_end);
1366 put_all_dscopes(notit);
1367
1368 /*
1369 * Adjust current buffer so that addr points to the beginning of the new
1370 * packet.
1371 */
1372 if (notit->buf.addr) {
1373 size_t consumed_bytes = (size_t) (notit->buf.at / CHAR_BIT);
1374
1375 /* Packets are assumed to start on a byte frontier. */
1376 if (notit->buf.at % CHAR_BIT) {
1377 ret = -1;
1378 goto end;
1379 }
1380
1381 notit->buf.addr += consumed_bytes;
1382 notit->buf.sz -= consumed_bytes;
1383 notit->buf.at = 0;
1384 notit->buf.packet_offset = 0;
1385 }
1386
1387 notit->cur_content_size = -1;
1388 notit->cur_packet_size = -1;
1389 notit->cur_sc_field_path_cache = NULL;
1390 end:
1391 return ret;
1392 }
1393
1394 static
1395 struct bt_ctf_field *get_next_field(struct bt_ctf_notif_iter *notit)
1396 {
1397 struct bt_ctf_field *next_field = NULL;
1398 struct bt_ctf_field *base_field;
1399 struct bt_ctf_field_type *base_type;
1400 size_t index;
1401
1402 assert(!stack_empty(notit->stack));
1403 index = stack_top(notit->stack)->index;
1404 base_field = stack_top(notit->stack)->base;
1405 base_type = bt_ctf_field_get_type(base_field);
1406 if (!base_type) {
1407 PERR("Failed to get base field's type\n");
1408 goto end;
1409 }
1410
1411 switch (bt_ctf_field_type_get_type_id(base_type)) {
1412 case BT_CTF_FIELD_TYPE_ID_STRUCT:
1413 next_field = bt_ctf_field_structure_get_field_by_index(
1414 base_field, index);
1415 break;
1416 case BT_CTF_FIELD_TYPE_ID_ARRAY:
1417 next_field = bt_ctf_field_array_get_field(base_field, index);
1418 break;
1419 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
1420 next_field = bt_ctf_field_sequence_get_field(base_field, index);
1421 break;
1422 case BT_CTF_FIELD_TYPE_ID_VARIANT:
1423 next_field = bt_ctf_field_variant_get_current_field(base_field);
1424 break;
1425 default:
1426 assert(false);
1427 break;
1428 }
1429
1430 end:
1431 BT_PUT(base_type);
1432
1433 return next_field;
1434 }
1435
1436 static
1437 void update_clock_state(uint64_t *state,
1438 struct bt_ctf_field *value_field)
1439 {
1440 struct bt_ctf_field_type *value_type = NULL;
1441 uint64_t requested_new_value;
1442 uint64_t requested_new_value_mask;
1443 uint64_t cur_value_masked;
1444 int requested_new_value_size;
1445 int ret;
1446
1447 value_type = bt_ctf_field_get_type(value_field);
1448 assert(value_type);
1449
1450 requested_new_value_size =
1451 bt_ctf_field_type_integer_get_size(value_type);
1452 assert(requested_new_value_size > 0);
1453
1454 ret = bt_ctf_field_unsigned_integer_get_value(value_field,
1455 &requested_new_value);
1456 assert(!ret);
1457
1458 /*
1459 * Special case for a 64-bit new value, which is the limit
1460 * of a clock value as of this version: overwrite the
1461 * current value directly.
1462 */
1463 if (requested_new_value_size == 64) {
1464 *state = requested_new_value;
1465 goto end;
1466 }
1467
1468 requested_new_value_mask = (1ULL << requested_new_value_size) - 1;
1469 cur_value_masked = *state & requested_new_value_mask;
1470
1471 if (requested_new_value < cur_value_masked) {
1472 /*
1473 * It looks like a wrap happened on the number of bits
1474 * of the requested new value. Assume that the clock
1475 * value wrapped only one time.
1476 */
1477 *state += requested_new_value_mask + 1;
1478 }
1479
1480 /* Clear the low bits of the current clock value. */
1481 *state &= ~requested_new_value_mask;
1482
1483 /* Set the low bits of the current clock value. */
1484 *state |= requested_new_value;
1485 end:
1486 bt_put(value_type);
1487 }
1488
1489 static
1490 enum bt_ctf_btr_status update_clock(struct bt_ctf_notif_iter *notit,
1491 struct bt_ctf_field *int_field)
1492 {
1493 gboolean clock_class_found;
1494 uint64_t *clock_state;
1495 struct bt_ctf_field_type *int_field_type = NULL;
1496 enum bt_ctf_btr_status ret = BT_CTF_BTR_STATUS_OK;
1497 struct bt_ctf_clock_class *clock_class = NULL;
1498
1499 int_field_type = bt_ctf_field_get_type(int_field);
1500 if (unlikely(!int_field_type)) {
1501 goto end;
1502 }
1503
1504 clock_class = bt_ctf_field_type_integer_get_mapped_clock_class(
1505 int_field_type);
1506 if (likely(!clock_class)) {
1507 goto end;
1508 }
1509
1510 clock_class_found = g_hash_table_lookup_extended(notit->clock_states,
1511 clock_class, NULL, (gpointer) &clock_state);
1512 if (unlikely(!clock_class_found)) {
1513 const char *clock_class_name =
1514 bt_ctf_clock_class_get_name(clock_class);
1515
1516 PERR("Unknown clock class %s mapped to integer encountered in stream\n",
1517 clock_class_name ? : "NULL");
1518 ret = BT_CTF_BTR_STATUS_ERROR;
1519 goto end;
1520 }
1521
1522 if (unlikely(!clock_state)) {
1523 clock_state = g_new0(uint64_t, 1);
1524 if (!clock_state) {
1525 ret = BT_CTF_BTR_STATUS_ENOMEM;
1526 goto end;
1527 }
1528 g_hash_table_insert(notit->clock_states, bt_get(clock_class),
1529 clock_state);
1530 }
1531
1532 /* Update the clock's state. */
1533 update_clock_state(clock_state, int_field);
1534 end:
1535 bt_put(int_field_type);
1536 bt_put(clock_class);
1537 return ret;
1538 }
1539
1540 static
1541 enum bt_ctf_btr_status btr_unsigned_int_common(uint64_t value,
1542 struct bt_ctf_field_type *type, void *data,
1543 struct bt_ctf_field **out_int_field)
1544 {
1545 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1546 struct bt_ctf_field *field = NULL;
1547 struct bt_ctf_field *int_field = NULL;
1548 struct bt_ctf_notif_iter *notit = data;
1549 int ret;
1550
1551 /* Create next field */
1552 field = get_next_field(notit);
1553 if (!field) {
1554 PERR("Failed to get next field (unsigned int)\n");
1555 status = BT_CTF_BTR_STATUS_ERROR;
1556 goto end_no_put;
1557 }
1558
1559 switch(bt_ctf_field_type_get_type_id(type)) {
1560 case BT_CTF_FIELD_TYPE_ID_INTEGER:
1561 /* Integer field is created field */
1562 BT_MOVE(int_field, field);
1563 bt_get(type);
1564 break;
1565 case BT_CTF_FIELD_TYPE_ID_ENUM:
1566 int_field = bt_ctf_field_enumeration_get_container(field);
1567 type = bt_ctf_field_get_type(int_field);
1568 break;
1569 default:
1570 assert(0);
1571 type = NULL;
1572 break;
1573 }
1574
1575 if (!int_field) {
1576 PERR("Failed to get integer field\n");
1577 status = BT_CTF_BTR_STATUS_ERROR;
1578 goto end;
1579 }
1580
1581 ret = bt_ctf_field_unsigned_integer_set_value(int_field, value);
1582 assert(!ret);
1583 stack_top(notit->stack)->index++;
1584 *out_int_field = int_field;
1585
1586 end:
1587 BT_PUT(field);
1588 BT_PUT(type);
1589 end_no_put:
1590 return status;
1591 }
1592
1593 static
1594 enum bt_ctf_btr_status btr_timestamp_end_cb(void *value,
1595 struct bt_ctf_field_type *type, void *data)
1596 {
1597 enum bt_ctf_btr_status status;
1598 struct bt_ctf_field *field = NULL;
1599 struct bt_ctf_notif_iter *notit = data;
1600
1601 status = btr_unsigned_int_common(*((uint64_t *) value), type, data,
1602 &field);
1603
1604 /* Set as the current packet's timestamp_end field. */
1605 BT_MOVE(notit->cur_timestamp_end, field);
1606 return status;
1607 }
1608
1609 static
1610 enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value,
1611 struct bt_ctf_field_type *type, void *data)
1612 {
1613 struct bt_ctf_notif_iter *notit = data;
1614 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1615 struct bt_ctf_field *field = NULL;
1616 struct field_cb_override *override;
1617
1618 override = g_hash_table_lookup(notit->field_overrides,
1619 type);
1620 if (unlikely(override)) {
1621 status = override->func(&value, type, override->data);
1622 goto end;
1623 }
1624
1625 status = btr_unsigned_int_common(value, type, data, &field);
1626 if (status != BT_CTF_BTR_STATUS_OK) {
1627 goto end;
1628 }
1629
1630 status = update_clock(notit, field);
1631 BT_PUT(field);
1632 end:
1633 return status;
1634 }
1635
1636 static
1637 enum bt_ctf_btr_status btr_signed_int_cb(int64_t value,
1638 struct bt_ctf_field_type *type, void *data)
1639 {
1640 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1641 struct bt_ctf_field *field = NULL;
1642 struct bt_ctf_field *int_field = NULL;
1643 struct bt_ctf_notif_iter *notit = data;
1644 int ret;
1645
1646 /* create next field */
1647 field = get_next_field(notit);
1648 if (!field) {
1649 PERR("Failed to get next field (signed int)\n");
1650 status = BT_CTF_BTR_STATUS_ERROR;
1651 goto end_no_put;
1652 }
1653
1654 switch(bt_ctf_field_type_get_type_id(type)) {
1655 case BT_CTF_FIELD_TYPE_ID_INTEGER:
1656 /* Integer field is created field */
1657 BT_MOVE(int_field, field);
1658 bt_get(type);
1659 break;
1660 case BT_CTF_FIELD_TYPE_ID_ENUM:
1661 int_field = bt_ctf_field_enumeration_get_container(field);
1662 type = bt_ctf_field_get_type(int_field);
1663 break;
1664 default:
1665 assert(0);
1666 type = NULL;
1667 break;
1668 }
1669
1670 if (!int_field) {
1671 PERR("Failed to get integer field\n");
1672 status = BT_CTF_BTR_STATUS_ERROR;
1673 goto end;
1674 }
1675
1676 ret = bt_ctf_field_signed_integer_set_value(int_field, value);
1677 assert(!ret);
1678 stack_top(notit->stack)->index++;
1679 status = update_clock(notit, int_field);
1680 end:
1681 BT_PUT(field);
1682 BT_PUT(int_field);
1683 BT_PUT(type);
1684 end_no_put:
1685 return status;
1686 }
1687
1688 static
1689 enum bt_ctf_btr_status btr_floating_point_cb(double value,
1690 struct bt_ctf_field_type *type, void *data)
1691 {
1692 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1693 struct bt_ctf_field *field = NULL;
1694 struct bt_ctf_notif_iter *notit = data;
1695 int ret;
1696
1697 /* Create next field */
1698 field = get_next_field(notit);
1699 if (!field) {
1700 PERR("Failed to get next field (floating point number)\n");
1701 status = BT_CTF_BTR_STATUS_ERROR;
1702 goto end;
1703 }
1704
1705 ret = bt_ctf_field_floating_point_set_value(field, value);
1706 assert(!ret);
1707 stack_top(notit->stack)->index++;
1708
1709 end:
1710 BT_PUT(field);
1711
1712 return status;
1713 }
1714
1715 static
1716 enum bt_ctf_btr_status btr_string_begin_cb(
1717 struct bt_ctf_field_type *type, void *data)
1718 {
1719 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1720 struct bt_ctf_field *field = NULL;
1721 struct bt_ctf_notif_iter *notit = data;
1722 int ret;
1723
1724 /* Create next field */
1725 field = get_next_field(notit);
1726 if (!field) {
1727 PERR("Failed to get next field (string)\n");
1728 status = BT_CTF_BTR_STATUS_ERROR;
1729 goto end;
1730 }
1731
1732 /*
1733 * Push on stack. Not a compound type per se, but we know that only
1734 * btr_string_cb() may be called between this call and a subsequent
1735 * call to btr_string_end_cb().
1736 */
1737 ret = stack_push(notit->stack, field);
1738 if (ret) {
1739 PERR("Failed to push string field onto the stack\n");
1740 status = BT_CTF_BTR_STATUS_ERROR;
1741 goto end;
1742 }
1743
1744 /*
1745 * Initialize string field payload to an empty string since in the
1746 * case of a length 0 string the btr_string_cb won't be called and
1747 * we will end up with an unset string payload.
1748 */
1749 ret = bt_ctf_field_string_set_value(field, "");
1750 if (ret) {
1751 PERR("Failed to initialize string field\n");
1752 status = BT_CTF_BTR_STATUS_ERROR;
1753 goto end;
1754 }
1755
1756 end:
1757 BT_PUT(field);
1758
1759 return status;
1760 }
1761
1762 static
1763 enum bt_ctf_btr_status btr_string_cb(const char *value,
1764 size_t len, struct bt_ctf_field_type *type, void *data)
1765 {
1766 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1767 struct bt_ctf_field *field = NULL;
1768 struct bt_ctf_notif_iter *notit = data;
1769 int ret;
1770
1771 /* Get string field */
1772 field = stack_top(notit->stack)->base;
1773 assert(field);
1774
1775 /* Append current string */
1776 ret = bt_ctf_field_string_append_len(field, value, len);
1777 if (ret) {
1778 PERR("Failed to append a string to a string field\n");
1779 status = BT_CTF_BTR_STATUS_ERROR;
1780 goto end;
1781 }
1782
1783 end:
1784 return status;
1785 }
1786
1787 static
1788 enum bt_ctf_btr_status btr_string_end_cb(
1789 struct bt_ctf_field_type *type, void *data)
1790 {
1791 struct bt_ctf_notif_iter *notit = data;
1792
1793 /* Pop string field */
1794 stack_pop(notit->stack);
1795
1796 /* Go to next field */
1797 stack_top(notit->stack)->index++;
1798
1799 return BT_CTF_BTR_STATUS_OK;
1800 }
1801
1802 enum bt_ctf_btr_status btr_compound_begin_cb(
1803 struct bt_ctf_field_type *type, void *data)
1804 {
1805 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1806 struct bt_ctf_notif_iter *notit = data;
1807 struct bt_ctf_field *field;
1808 int ret;
1809
1810 /* Create field */
1811 if (stack_empty(notit->stack)) {
1812 /* Root: create dynamic scope field */
1813 *notit->cur_dscope_field = bt_ctf_field_create(type);
1814 field = *notit->cur_dscope_field;
1815
1816 /*
1817 * Field will be put at the end of this function
1818 * (stack_push() will take one reference, but this
1819 * reference is lost upon the equivalent stack_pop()
1820 * later), so also get it for our context to own it.
1821 */
1822 bt_get(*notit->cur_dscope_field);
1823 } else {
1824 field = get_next_field(notit);
1825 }
1826
1827 if (!field) {
1828 PERR("Failed to get next field or create dynamic scope field\n");
1829 status = BT_CTF_BTR_STATUS_ERROR;
1830 goto end;
1831 }
1832
1833 /* Push field */
1834 ret = stack_push(notit->stack, field);
1835 if (ret) {
1836 PERR("Failed to push compound field onto the stack\n");
1837 status = BT_CTF_BTR_STATUS_ERROR;
1838 goto end;
1839 }
1840
1841 end:
1842 BT_PUT(field);
1843
1844 return status;
1845 }
1846
1847 enum bt_ctf_btr_status btr_compound_end_cb(
1848 struct bt_ctf_field_type *type, void *data)
1849 {
1850 struct bt_ctf_notif_iter *notit = data;
1851
1852 assert(!stack_empty(notit->stack));
1853
1854 /* Pop stack */
1855 stack_pop(notit->stack);
1856
1857 /* If the stack is not empty, increment the base's index */
1858 if (!stack_empty(notit->stack)) {
1859 stack_top(notit->stack)->index++;
1860 }
1861
1862 return BT_CTF_BTR_STATUS_OK;
1863 }
1864
1865 static
1866 struct bt_ctf_field *resolve_field(struct bt_ctf_notif_iter *notit,
1867 struct bt_ctf_field_path *path)
1868 {
1869 struct bt_ctf_field *field = NULL;
1870 unsigned int i;
1871
1872 switch (bt_ctf_field_path_get_root_scope(path)) {
1873 case BT_CTF_SCOPE_TRACE_PACKET_HEADER:
1874 field = notit->dscopes.trace_packet_header;
1875 break;
1876 case BT_CTF_SCOPE_STREAM_PACKET_CONTEXT:
1877 field = notit->dscopes.stream_packet_context;
1878 break;
1879 case BT_CTF_SCOPE_STREAM_EVENT_HEADER:
1880 field = notit->dscopes.stream_event_header;
1881 break;
1882 case BT_CTF_SCOPE_STREAM_EVENT_CONTEXT:
1883 field = notit->dscopes.stream_event_context;
1884 break;
1885 case BT_CTF_SCOPE_EVENT_CONTEXT:
1886 field = notit->dscopes.event_context;
1887 break;
1888 case BT_CTF_SCOPE_EVENT_FIELDS:
1889 field = notit->dscopes.event_payload;
1890 break;
1891 default:
1892 break;
1893 }
1894
1895 if (!field) {
1896 goto end;
1897 }
1898
1899 bt_get(field);
1900
1901 for (i = 0; i < bt_ctf_field_path_get_index_count(path); ++i) {
1902 struct bt_ctf_field *next_field = NULL;
1903 struct bt_ctf_field_type *field_type;
1904 int index = bt_ctf_field_path_get_index(path, i);
1905
1906 field_type = bt_ctf_field_get_type(field);
1907 if (!field_type) {
1908 BT_PUT(field);
1909 goto end;
1910 }
1911
1912 if (is_struct_type(field_type)) {
1913 next_field = bt_ctf_field_structure_get_field_by_index(
1914 field, index);
1915 } else if (is_variant_type(field_type)) {
1916 next_field =
1917 bt_ctf_field_variant_get_current_field(field);
1918 }
1919
1920 BT_PUT(field);
1921 BT_PUT(field_type);
1922
1923 if (!next_field) {
1924 goto end;
1925 }
1926
1927 /* Move next field -> field */
1928 BT_MOVE(field, next_field);
1929 }
1930
1931 end:
1932 return field;
1933 }
1934
1935 static
1936 int64_t btr_get_sequence_length_cb(struct bt_ctf_field_type *type, void *data)
1937 {
1938 int64_t ret = -1;
1939 int iret;
1940 struct bt_ctf_field_path *field_path;
1941 struct bt_ctf_notif_iter *notit = data;
1942 struct bt_ctf_field *length_field = NULL;
1943 uint64_t length;
1944
1945 field_path = bt_ctf_field_type_sequence_get_length_field_path(type);
1946 if (!field_path) {
1947 goto end;
1948 }
1949
1950 length_field = resolve_field(notit, field_path);
1951 if (!length_field) {
1952 goto end;
1953 }
1954
1955 iret = bt_ctf_field_unsigned_integer_get_value(length_field, &length);
1956 if (iret) {
1957 goto end;
1958 }
1959
1960 iret = bt_ctf_field_sequence_set_length(stack_top(notit->stack)->base,
1961 length_field);
1962 if (iret) {
1963 goto end;
1964 }
1965 ret = (int64_t) length;
1966
1967 end:
1968 BT_PUT(length_field);
1969 BT_PUT(field_path);
1970
1971 return ret;
1972 }
1973
1974 static
1975 struct bt_ctf_field_type *btr_get_variant_type_cb(
1976 struct bt_ctf_field_type *type, void *data)
1977 {
1978 struct bt_ctf_field_path *path;
1979 struct bt_ctf_notif_iter *notit = data;
1980 struct bt_ctf_field *tag_field = NULL;
1981 struct bt_ctf_field *selected_field = NULL;
1982 struct bt_ctf_field_type *selected_field_type = NULL;
1983
1984 path = bt_ctf_field_type_variant_get_tag_field_path(type);
1985 if (!path) {
1986 goto end;
1987 }
1988
1989 tag_field = resolve_field(notit, path);
1990 if (!tag_field) {
1991 goto end;
1992 }
1993
1994 /*
1995 * We found the enumeration tag field instance which should be
1996 * able to select a current field for this variant. This
1997 * callback function we're in is called _after_
1998 * compound_begin(), so the current stack top's base field is
1999 * the variant field in question. We get the selected field here
2000 * thanks to this tag field (thus creating the selected field),
2001 * which will also provide us with its type. Then, this field
2002 * will remain the current selected one until the next callback
2003 * function call which is used to fill the current selected
2004 * field.
2005 */
2006 selected_field = bt_ctf_field_variant_get_field(
2007 stack_top(notit->stack)->base, tag_field);
2008 if (!selected_field) {
2009 goto end;
2010 }
2011
2012 selected_field_type = bt_ctf_field_get_type(selected_field);
2013
2014 end:
2015 BT_PUT(tag_field);
2016 BT_PUT(selected_field);
2017 BT_PUT(path);
2018
2019 return selected_field_type;
2020 }
2021
2022 static
2023 int set_event_clocks(struct bt_ctf_event *event,
2024 struct bt_ctf_notif_iter *notit)
2025 {
2026 int ret;
2027 GHashTableIter iter;
2028 struct bt_ctf_clock_class *clock_class;
2029 uint64_t *clock_state;
2030
2031 g_hash_table_iter_init(&iter, notit->clock_states);
2032
2033 while (g_hash_table_iter_next(&iter, (gpointer) &clock_class,
2034 (gpointer) &clock_state)) {
2035 struct bt_ctf_clock_value *clock_value;
2036
2037 clock_value = bt_ctf_clock_value_create(clock_class,
2038 *clock_state);
2039 if (!clock_value) {
2040 ret = -1;
2041 goto end;
2042 }
2043 ret = bt_ctf_event_set_clock_value(event, clock_value);
2044 bt_put(clock_value);
2045 if (ret) {
2046 goto end;
2047 }
2048 }
2049 ret = 0;
2050 end:
2051 return ret;
2052 }
2053
2054 static
2055 struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit)
2056 {
2057 int ret;
2058 struct bt_ctf_event *event;
2059
2060 /* Create event object. */
2061 event = bt_ctf_event_create(notit->meta.event_class);
2062 if (!event) {
2063 goto error;
2064 }
2065
2066 /* Set header, stream event context, context, and payload fields. */
2067 ret = bt_ctf_event_set_header(event,
2068 notit->dscopes.stream_event_header);
2069 if (ret) {
2070 goto error;
2071 }
2072
2073 ret = bt_ctf_event_set_stream_event_context(event,
2074 notit->dscopes.stream_event_context);
2075 if (ret) {
2076 goto error;
2077 }
2078
2079 ret = bt_ctf_event_set_event_context(event,
2080 notit->dscopes.event_context);
2081 if (ret) {
2082 goto error;
2083 }
2084
2085 ret = bt_ctf_event_set_event_payload(event,
2086 notit->dscopes.event_payload);
2087 if (ret) {
2088 goto error;
2089 }
2090
2091 ret = set_event_clocks(event, notit);
2092 if (ret) {
2093 goto error;
2094 }
2095
2096 /* Associate with current packet. */
2097 assert(notit->packet);
2098 ret = bt_ctf_event_set_packet(event, notit->packet);
2099 if (ret) {
2100 goto error;
2101 }
2102
2103 goto end;
2104 error:
2105 BT_PUT(event);
2106 end:
2107 return event;
2108 }
2109
2110 static
2111 void create_packet(struct bt_ctf_notif_iter *notit)
2112 {
2113 int ret;
2114 struct bt_ctf_stream *stream = NULL;
2115 struct bt_ctf_packet *packet = NULL;
2116
2117 /* Ask the user for the stream */
2118 stream = notit->medium.medops.get_stream(notit->meta.stream_class,
2119 notit->medium.data);
2120 if (!stream) {
2121 goto error;
2122 }
2123
2124 /* Create packet */
2125 packet = bt_ctf_packet_create(stream);
2126 if (!packet) {
2127 goto error;
2128 }
2129
2130 /* Set packet's context and header fields */
2131 if (notit->dscopes.trace_packet_header) {
2132 ret = bt_ctf_packet_set_header(packet,
2133 notit->dscopes.trace_packet_header);
2134 if (ret) {
2135 goto error;
2136 }
2137 }
2138
2139 if (notit->dscopes.stream_packet_context) {
2140 ret = bt_ctf_packet_set_context(packet,
2141 notit->dscopes.stream_packet_context);
2142 if (ret) {
2143 goto error;
2144 }
2145 }
2146
2147 goto end;
2148 error:
2149 BT_PUT(packet);
2150 end:
2151 BT_MOVE(notit->packet, packet);
2152 }
2153
2154 static
2155 void notify_new_packet(struct bt_ctf_notif_iter *notit,
2156 struct bt_notification **notification)
2157 {
2158 struct bt_notification *ret;
2159
2160 /* Initialize the iterator's current packet */
2161 create_packet(notit);
2162 if (!notit->packet) {
2163 return;
2164 }
2165
2166 ret = bt_notification_packet_begin_create(notit->packet);
2167 if (!ret) {
2168 return;
2169 }
2170 *notification = ret;
2171 }
2172
2173 static
2174 void notify_end_of_packet(struct bt_ctf_notif_iter *notit,
2175 struct bt_notification **notification)
2176 {
2177 struct bt_notification *ret;
2178
2179 if (!notit->packet) {
2180 return;
2181 }
2182
2183 ret = bt_notification_packet_end_create(notit->packet);
2184 if (!ret) {
2185 return;
2186 }
2187 BT_PUT(notit->packet);
2188 *notification = ret;
2189 }
2190
2191 static
2192 void notify_event(struct bt_ctf_notif_iter *notit,
2193 struct bt_clock_class_priority_map *cc_prio_map,
2194 struct bt_notification **notification)
2195 {
2196 struct bt_ctf_event *event;
2197 struct bt_notification *ret = NULL;
2198
2199 /* Create event */
2200 event = create_event(notit);
2201 if (!event) {
2202 goto end;
2203 }
2204
2205 ret = bt_notification_event_create(event, cc_prio_map);
2206 if (!ret) {
2207 goto end;
2208 }
2209 *notification = ret;
2210 end:
2211 BT_PUT(event);
2212 }
2213
2214 //FIXME: not used ?
2215 static
2216 void notify_eos(struct bt_ctf_notif_iter *notit,
2217 struct bt_notification **notification)
2218 {
2219 struct bt_ctf_stream *stream = NULL;
2220 struct bt_notification *ret = NULL;
2221
2222 /* Ask the user for the stream */
2223 stream = notit->medium.medops.get_stream(notit->meta.stream_class,
2224 notit->medium.data);
2225 if (!stream) {
2226 goto end;
2227 }
2228
2229 ret = bt_notification_stream_end_create(stream);
2230 if (!ret) {
2231 goto end;
2232 }
2233 *notification = ret;
2234 end:
2235 BT_PUT(stream);
2236 }
2237
2238 static
2239 int init_clock_states(GHashTable *clock_states, struct bt_ctf_trace *trace)
2240 {
2241 int clock_class_count, i, ret = 0;
2242
2243 clock_class_count = bt_ctf_trace_get_clock_class_count(trace);
2244 if (clock_class_count <= 0) {
2245 ret = -1;
2246 goto end;
2247 }
2248
2249 for (i = 0; i < clock_class_count; i++) {
2250 struct bt_ctf_clock_class *clock_class;
2251
2252 clock_class = bt_ctf_trace_get_clock_class_by_index(trace, i);
2253 if (!clock_class) {
2254 ret = -1;
2255 goto end;
2256 }
2257
2258 g_hash_table_insert(clock_states, bt_get(clock_class), NULL);
2259 bt_put(clock_class);
2260 }
2261 end:
2262 return ret;
2263 }
2264
2265 static
2266 void init_trace_field_path_cache(struct bt_ctf_trace *trace,
2267 struct trace_field_path_cache *trace_field_path_cache)
2268 {
2269 int stream_id = -1;
2270 int stream_instance_id = -1;
2271 int i, count;
2272 struct bt_ctf_field_type *packet_header = NULL;
2273
2274 packet_header = bt_ctf_trace_get_packet_header_type(trace);
2275 if (!packet_header) {
2276 goto end;
2277 }
2278
2279 if (!bt_ctf_field_type_is_structure(packet_header)) {
2280 goto end;
2281 }
2282
2283 count = bt_ctf_field_type_structure_get_field_count(packet_header);
2284 if (count < 0) {
2285 goto end;
2286 }
2287
2288 for (i = 0; (i < count && (stream_id == -1 || stream_instance_id == -1)); i++) {
2289 int ret;
2290 const char *field_name;
2291
2292 ret = bt_ctf_field_type_structure_get_field(packet_header,
2293 &field_name, NULL, i);
2294 if (ret) {
2295 goto end;
2296 }
2297
2298 if (stream_id == -1 && !strcmp(field_name, "stream_id")) {
2299 stream_id = i;
2300 } else if (stream_instance_id == -1 &&
2301 !strcmp(field_name, "stream_instance_id")) {
2302 stream_instance_id = i;
2303 }
2304 }
2305 end:
2306 trace_field_path_cache->stream_id = stream_id;
2307 trace_field_path_cache->stream_instance_id = stream_instance_id;
2308 BT_PUT(packet_header);
2309 }
2310
2311 BT_HIDDEN
2312 struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace,
2313 size_t max_request_sz,
2314 struct bt_ctf_notif_iter_medium_ops medops,
2315 void *data, FILE *err_stream)
2316 {
2317 int ret;
2318 struct bt_ctf_notif_iter *notit = NULL;
2319 struct bt_ctf_btr_cbs cbs = {
2320 .types = {
2321 .signed_int = btr_signed_int_cb,
2322 .unsigned_int = btr_unsigned_int_cb,
2323 .floating_point = btr_floating_point_cb,
2324 .string_begin = btr_string_begin_cb,
2325 .string = btr_string_cb,
2326 .string_end = btr_string_end_cb,
2327 .compound_begin = btr_compound_begin_cb,
2328 .compound_end = btr_compound_end_cb,
2329 },
2330 .query = {
2331 .get_sequence_length = btr_get_sequence_length_cb,
2332 .get_variant_type = btr_get_variant_type_cb,
2333 },
2334 };
2335
2336 assert(trace);
2337 assert(medops.request_bytes);
2338 assert(medops.get_stream);
2339 notit = g_new0(struct bt_ctf_notif_iter, 1);
2340 if (!notit) {
2341 PERR("Failed to allocate memory for CTF notification iterator\n");
2342 goto end;
2343 }
2344 notit->clock_states = g_hash_table_new_full(g_direct_hash,
2345 g_direct_equal, bt_put, g_free);
2346 if (!notit->clock_states) {
2347 PERR("Failed to create hash table\n");
2348 goto error;
2349 }
2350 ret = init_clock_states(notit->clock_states, trace);
2351 if (ret) {
2352 PERR("Failed to initialize stream clock states\n");
2353 goto error;
2354 }
2355 notit->meta.trace = bt_get(trace);
2356 notit->medium.medops = medops;
2357 notit->medium.max_request_sz = max_request_sz;
2358 notit->medium.data = data;
2359 notit->err_stream = err_stream;
2360 notit->stack = stack_new(notit);
2361 if (!notit->stack) {
2362 PERR("Failed to create stack\n");
2363 goto error;
2364 }
2365
2366 notit->btr = bt_ctf_btr_create(cbs, notit, err_stream);
2367 if (!notit->btr) {
2368 PERR("Failed to create binary type reader\n");
2369 goto error;
2370 }
2371
2372 bt_ctf_notif_iter_reset(notit);
2373
2374 init_trace_field_path_cache(trace, &notit->trace_field_path_cache);
2375 notit->sc_field_path_caches = g_hash_table_new_full(g_direct_hash,
2376 g_direct_equal, bt_put, g_free);
2377 if (!notit->sc_field_path_caches) {
2378 PERR("Failed to create stream class field path caches\n");
2379 goto error;
2380 }
2381
2382 notit->field_overrides = g_hash_table_new_full(g_direct_hash,
2383 g_direct_equal, bt_put, g_free);
2384 if (!notit->field_overrides) {
2385 goto error;
2386 }
2387
2388 end:
2389 return notit;
2390 error:
2391 bt_ctf_notif_iter_destroy(notit);
2392 notit = NULL;
2393 goto end;
2394 }
2395
2396 void bt_ctf_notif_iter_destroy(struct bt_ctf_notif_iter *notit)
2397 {
2398 BT_PUT(notit->meta.trace);
2399 BT_PUT(notit->meta.stream_class);
2400 BT_PUT(notit->meta.event_class);
2401 BT_PUT(notit->packet);
2402 BT_PUT(notit->cur_timestamp_end);
2403 put_all_dscopes(notit);
2404
2405 if (notit->stack) {
2406 stack_destroy(notit->stack);
2407 }
2408
2409 if (notit->btr) {
2410 bt_ctf_btr_destroy(notit->btr);
2411 }
2412
2413 if (notit->clock_states) {
2414 g_hash_table_destroy(notit->clock_states);
2415 }
2416
2417 if (notit->sc_field_path_caches) {
2418 g_hash_table_destroy(notit->sc_field_path_caches);
2419 }
2420
2421 if (notit->field_overrides) {
2422 g_hash_table_destroy(notit->field_overrides);
2423 }
2424 g_free(notit);
2425 }
2426
2427 enum bt_ctf_notif_iter_status bt_ctf_notif_iter_get_next_notification(
2428 struct bt_ctf_notif_iter *notit,
2429 struct bt_clock_class_priority_map *cc_prio_map,
2430 struct bt_notification **notification)
2431 {
2432 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
2433
2434 assert(notit);
2435 assert(notification);
2436
2437 while (true) {
2438 status = handle_state(notit);
2439 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
2440 if (status == BT_CTF_NOTIF_ITER_STATUS_EOF) {
2441 PDBG("Medium operation reported end of stream\n");
2442 } else {
2443 PERR("Failed to handle state:\n");
2444 PERR("\tState: %d\n", notit->state);
2445 }
2446 goto end;
2447 }
2448
2449 switch (notit->state) {
2450 case STATE_EMIT_NOTIF_NEW_PACKET:
2451 PDBG("Emitting new packet notification\n");
2452 notify_new_packet(notit, notification);
2453 if (!*notification) {
2454 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
2455 }
2456 goto end;
2457 case STATE_EMIT_NOTIF_EVENT:
2458 PDBG("Emitting event notification\n");
2459 notify_event(notit, cc_prio_map, notification);
2460 if (!*notification) {
2461 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
2462 }
2463 goto end;
2464 case STATE_EMIT_NOTIF_END_OF_PACKET:
2465 /* Update clock with timestamp_end field. */
2466 if (notit->cur_timestamp_end) {
2467 enum bt_ctf_btr_status btr_status;
2468 struct bt_ctf_field_type *field_type =
2469 bt_ctf_field_get_type(
2470 notit->cur_timestamp_end);
2471
2472 btr_status = update_clock(notit,
2473 notit->cur_timestamp_end);
2474 BT_PUT(field_type);
2475 if (btr_status != BT_CTF_BTR_STATUS_OK) {
2476 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
2477 goto end;
2478 }
2479 }
2480
2481 PDBG("Emitting end of packet notification\n");
2482 notify_end_of_packet(notit, notification);
2483 if (!*notification) {
2484 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
2485 }
2486 goto end;
2487 default:
2488 /* Non-emitting state: continue */
2489 break;
2490 }
2491 }
2492
2493 end:
2494 return status;
2495 }
This page took 0.11082 seconds and 5 git commands to generate.