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