Event notification: pass CC priority map on creation
[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_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_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_TYPE_ID_STRUCT:
1416 next_field = bt_ctf_field_structure_get_field_by_index(
1417 base_field, index);
1418 break;
1419 case BT_CTF_TYPE_ID_ARRAY:
1420 next_field = bt_ctf_field_array_get_field(base_field, index);
1421 break;
1422 case BT_CTF_TYPE_ID_SEQUENCE:
1423 next_field = bt_ctf_field_sequence_get_field(base_field, index);
1424 break;
1425 case BT_CTF_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_type *int_field_type,
1495 struct bt_ctf_field *int_field)
1496 {
1497 gboolean clock_class_found;
1498 uint64_t *clock_state;
1499 enum bt_ctf_btr_status ret = BT_CTF_BTR_STATUS_OK;
1500 struct bt_ctf_clock_class *clock_class =
1501 bt_ctf_field_type_integer_get_mapped_clock_class(
1502 int_field_type);
1503
1504 if (likely(!clock_class)) {
1505 goto end_no_clock;
1506 }
1507
1508 clock_class_found = g_hash_table_lookup_extended(notit->clock_states,
1509 clock_class, NULL, (gpointer) &clock_state);
1510 if (unlikely(!clock_class_found)) {
1511 const char *clock_class_name =
1512 bt_ctf_clock_class_get_name(clock_class);
1513
1514 PERR("Unknown clock class %s mapped to integer encountered in stream\n",
1515 clock_class_name ? : "NULL");
1516 ret = BT_CTF_BTR_STATUS_ERROR;
1517 goto end;
1518 }
1519
1520 if (unlikely(!clock_state)) {
1521 clock_state = g_new0(uint64_t, 1);
1522 if (!clock_state) {
1523 ret = BT_CTF_BTR_STATUS_ENOMEM;
1524 goto end;
1525 }
1526 g_hash_table_insert(notit->clock_states, bt_get(clock_class),
1527 clock_state);
1528 }
1529
1530 /* Update the clock's state. */
1531 update_clock_state(clock_state, int_field);
1532 end:
1533 bt_put(clock_class);
1534 end_no_clock:
1535 return ret;
1536 }
1537
1538 static
1539 enum bt_ctf_btr_status btr_unsigned_int_common(uint64_t value,
1540 struct bt_ctf_field_type *type, void *data,
1541 struct bt_ctf_field **_field)
1542 {
1543 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1544 struct bt_ctf_field *field = NULL;
1545 struct bt_ctf_field *int_field = NULL;
1546 struct bt_ctf_notif_iter *notit = data;
1547 int ret;
1548
1549 /* Create next field */
1550 field = get_next_field(notit);
1551 if (!field) {
1552 PERR("Failed to get next field (unsigned int)\n");
1553 status = BT_CTF_BTR_STATUS_ERROR;
1554 goto end_no_put;
1555 }
1556
1557 switch(bt_ctf_field_type_get_type_id(type)) {
1558 case BT_CTF_TYPE_ID_INTEGER:
1559 /* Integer field is created field */
1560 BT_MOVE(int_field, field);
1561 bt_get(type);
1562 break;
1563 case BT_CTF_TYPE_ID_ENUM:
1564 int_field = bt_ctf_field_enumeration_get_container(field);
1565 type = bt_ctf_field_get_type(int_field);
1566 break;
1567 default:
1568 assert(0);
1569 type = NULL;
1570 break;
1571 }
1572
1573 if (!int_field) {
1574 PERR("Failed to get integer field\n");
1575 status = BT_CTF_BTR_STATUS_ERROR;
1576 goto end;
1577 }
1578
1579 ret = bt_ctf_field_unsigned_integer_set_value(int_field, value);
1580 assert(!ret);
1581 stack_top(notit->stack)->index++;
1582 *_field = int_field;
1583
1584 end:
1585 BT_PUT(field);
1586 BT_PUT(type);
1587 end_no_put:
1588 return status;
1589 }
1590
1591 static
1592 enum bt_ctf_btr_status btr_timestamp_end_cb(void *value,
1593 struct bt_ctf_field_type *type, void *data)
1594 {
1595 enum bt_ctf_btr_status status;
1596 struct bt_ctf_field *field = NULL;
1597 struct bt_ctf_notif_iter *notit = data;
1598
1599 status = btr_unsigned_int_common(*((uint64_t *) value), type, data,
1600 &field);
1601
1602 /* Set as the current packet's timestamp_end field. */
1603 BT_MOVE(notit->cur_timestamp_end, field);
1604 return status;
1605 }
1606
1607 static
1608 enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value,
1609 struct bt_ctf_field_type *type, void *data)
1610 {
1611 struct bt_ctf_notif_iter *notit = data;
1612 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1613 struct bt_ctf_field *field = NULL;
1614 struct field_cb_override *override;
1615
1616 override = g_hash_table_lookup(notit->field_overrides,
1617 type);
1618 if (unlikely(override)) {
1619 status = override->func(&value, type, override->data);
1620 goto end;
1621 }
1622
1623 status = btr_unsigned_int_common(value, type, data, &field);
1624 if (status != BT_CTF_BTR_STATUS_OK) {
1625 goto end;
1626 }
1627
1628 status = update_clock(notit, type, field);
1629 BT_PUT(field);
1630 end:
1631 return status;
1632 }
1633
1634 static
1635 enum bt_ctf_btr_status btr_signed_int_cb(int64_t value,
1636 struct bt_ctf_field_type *type, void *data)
1637 {
1638 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1639 struct bt_ctf_field *field = NULL;
1640 struct bt_ctf_field *int_field = NULL;
1641 struct bt_ctf_notif_iter *notit = data;
1642 int ret;
1643
1644 /* create next field */
1645 field = get_next_field(notit);
1646 if (!field) {
1647 PERR("Failed to get next field (signed int)\n");
1648 status = BT_CTF_BTR_STATUS_ERROR;
1649 goto end_no_put;
1650 }
1651
1652 switch(bt_ctf_field_type_get_type_id(type)) {
1653 case BT_CTF_TYPE_ID_INTEGER:
1654 /* Integer field is created field */
1655 BT_MOVE(int_field, field);
1656 bt_get(type);
1657 break;
1658 case BT_CTF_TYPE_ID_ENUM:
1659 int_field = bt_ctf_field_enumeration_get_container(field);
1660 type = bt_ctf_field_get_type(int_field);
1661 break;
1662 default:
1663 assert(0);
1664 type = NULL;
1665 break;
1666 }
1667
1668 if (!int_field) {
1669 PERR("Failed to get integer field\n");
1670 status = BT_CTF_BTR_STATUS_ERROR;
1671 goto end;
1672 }
1673
1674 ret = bt_ctf_field_signed_integer_set_value(int_field, value);
1675 assert(!ret);
1676 stack_top(notit->stack)->index++;
1677 status = update_clock(notit, type, int_field);
1678 end:
1679 BT_PUT(field);
1680 BT_PUT(int_field);
1681 BT_PUT(type);
1682 end_no_put:
1683 return status;
1684 }
1685
1686 static
1687 enum bt_ctf_btr_status btr_floating_point_cb(double value,
1688 struct bt_ctf_field_type *type, void *data)
1689 {
1690 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1691 struct bt_ctf_field *field = NULL;
1692 struct bt_ctf_notif_iter *notit = data;
1693 int ret;
1694
1695 /* Create next field */
1696 field = get_next_field(notit);
1697 if (!field) {
1698 PERR("Failed to get next field (floating point number)\n");
1699 status = BT_CTF_BTR_STATUS_ERROR;
1700 goto end;
1701 }
1702
1703 ret = bt_ctf_field_floating_point_set_value(field, value);
1704 assert(!ret);
1705 stack_top(notit->stack)->index++;
1706
1707 end:
1708 BT_PUT(field);
1709
1710 return status;
1711 }
1712
1713 static
1714 enum bt_ctf_btr_status btr_string_begin_cb(
1715 struct bt_ctf_field_type *type, void *data)
1716 {
1717 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1718 struct bt_ctf_field *field = NULL;
1719 struct bt_ctf_notif_iter *notit = data;
1720 int ret;
1721
1722 /* Create next field */
1723 field = get_next_field(notit);
1724 if (!field) {
1725 PERR("Failed to get next field (string)\n");
1726 status = BT_CTF_BTR_STATUS_ERROR;
1727 goto end;
1728 }
1729
1730 /*
1731 * Push on stack. Not a compound type per se, but we know that only
1732 * btr_string_cb() may be called between this call and a subsequent
1733 * call to btr_string_end_cb().
1734 */
1735 ret = stack_push(notit->stack, field);
1736 if (ret) {
1737 PERR("Failed to push string field onto the stack\n");
1738 status = BT_CTF_BTR_STATUS_ERROR;
1739 goto end;
1740 }
1741
1742 /*
1743 * Initialize string field payload to an empty string since in the
1744 * case of a length 0 string the btr_string_cb won't be called and
1745 * we will end up with an unset string payload.
1746 */
1747 ret = bt_ctf_field_string_set_value(field, "");
1748 if (ret) {
1749 PERR("Failed to initialize string field\n");
1750 status = BT_CTF_BTR_STATUS_ERROR;
1751 goto end;
1752 }
1753
1754 end:
1755 BT_PUT(field);
1756
1757 return status;
1758 }
1759
1760 static
1761 enum bt_ctf_btr_status btr_string_cb(const char *value,
1762 size_t len, struct bt_ctf_field_type *type, void *data)
1763 {
1764 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1765 struct bt_ctf_field *field = NULL;
1766 struct bt_ctf_notif_iter *notit = data;
1767 int ret;
1768
1769 /* Get string field */
1770 field = stack_top(notit->stack)->base;
1771 assert(field);
1772
1773 /* Append current string */
1774 ret = bt_ctf_field_string_append_len(field, value, len);
1775 if (ret) {
1776 PERR("Failed to append a string to a string field\n");
1777 status = BT_CTF_BTR_STATUS_ERROR;
1778 goto end;
1779 }
1780
1781 end:
1782 return status;
1783 }
1784
1785 static
1786 enum bt_ctf_btr_status btr_string_end_cb(
1787 struct bt_ctf_field_type *type, void *data)
1788 {
1789 struct bt_ctf_notif_iter *notit = data;
1790
1791 /* Pop string field */
1792 stack_pop(notit->stack);
1793
1794 /* Go to next field */
1795 stack_top(notit->stack)->index++;
1796
1797 return BT_CTF_BTR_STATUS_OK;
1798 }
1799
1800 enum bt_ctf_btr_status btr_compound_begin_cb(
1801 struct bt_ctf_field_type *type, void *data)
1802 {
1803 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1804 struct bt_ctf_notif_iter *notit = data;
1805 struct bt_ctf_field *field;
1806 int ret;
1807
1808 /* Create field */
1809 if (stack_empty(notit->stack)) {
1810 /* Root: create dynamic scope field */
1811 *notit->cur_dscope_field = bt_ctf_field_create(type);
1812 field = *notit->cur_dscope_field;
1813
1814 /*
1815 * Field will be put at the end of this function
1816 * (stack_push() will take one reference, but this
1817 * reference is lost upon the equivalent stack_pop()
1818 * later), so also get it for our context to own it.
1819 */
1820 bt_get(*notit->cur_dscope_field);
1821 } else {
1822 field = get_next_field(notit);
1823 }
1824
1825 if (!field) {
1826 PERR("Failed to get next field or create dynamic scope field\n");
1827 status = BT_CTF_BTR_STATUS_ERROR;
1828 goto end;
1829 }
1830
1831 /* Push field */
1832 ret = stack_push(notit->stack, field);
1833 if (ret) {
1834 PERR("Failed to push compound field onto the stack\n");
1835 status = BT_CTF_BTR_STATUS_ERROR;
1836 goto end;
1837 }
1838
1839 end:
1840 BT_PUT(field);
1841
1842 return status;
1843 }
1844
1845 enum bt_ctf_btr_status btr_compound_end_cb(
1846 struct bt_ctf_field_type *type, void *data)
1847 {
1848 struct bt_ctf_notif_iter *notit = data;
1849
1850 assert(!stack_empty(notit->stack));
1851
1852 /* Pop stack */
1853 stack_pop(notit->stack);
1854
1855 /* If the stack is not empty, increment the base's index */
1856 if (!stack_empty(notit->stack)) {
1857 stack_top(notit->stack)->index++;
1858 }
1859
1860 return BT_CTF_BTR_STATUS_OK;
1861 }
1862
1863 static
1864 struct bt_ctf_field *resolve_field(struct bt_ctf_notif_iter *notit,
1865 struct bt_ctf_field_path *path)
1866 {
1867 struct bt_ctf_field *field = NULL;
1868 unsigned int i;
1869
1870 switch (bt_ctf_field_path_get_root_scope(path)) {
1871 case BT_CTF_SCOPE_TRACE_PACKET_HEADER:
1872 field = notit->dscopes.trace_packet_header;
1873 break;
1874 case BT_CTF_SCOPE_STREAM_PACKET_CONTEXT:
1875 field = notit->dscopes.stream_packet_context;
1876 break;
1877 case BT_CTF_SCOPE_STREAM_EVENT_HEADER:
1878 field = notit->dscopes.stream_event_header;
1879 break;
1880 case BT_CTF_SCOPE_STREAM_EVENT_CONTEXT:
1881 field = notit->dscopes.stream_event_context;
1882 break;
1883 case BT_CTF_SCOPE_EVENT_CONTEXT:
1884 field = notit->dscopes.event_context;
1885 break;
1886 case BT_CTF_SCOPE_EVENT_FIELDS:
1887 field = notit->dscopes.event_payload;
1888 break;
1889 default:
1890 break;
1891 }
1892
1893 if (!field) {
1894 goto end;
1895 }
1896
1897 bt_get(field);
1898
1899 for (i = 0; i < bt_ctf_field_path_get_index_count(path); ++i) {
1900 struct bt_ctf_field *next_field = NULL;
1901 struct bt_ctf_field_type *field_type;
1902 int index = bt_ctf_field_path_get_index(path, i);
1903
1904 field_type = bt_ctf_field_get_type(field);
1905 if (!field_type) {
1906 BT_PUT(field);
1907 goto end;
1908 }
1909
1910 if (is_struct_type(field_type)) {
1911 next_field = bt_ctf_field_structure_get_field_by_index(
1912 field, index);
1913 } else if (is_variant_type(field_type)) {
1914 next_field =
1915 bt_ctf_field_variant_get_current_field(field);
1916 }
1917
1918 BT_PUT(field);
1919 BT_PUT(field_type);
1920
1921 if (!next_field) {
1922 goto end;
1923 }
1924
1925 /* Move next field -> field */
1926 BT_MOVE(field, next_field);
1927 }
1928
1929 end:
1930 return field;
1931 }
1932
1933 static
1934 int64_t btr_get_sequence_length_cb(struct bt_ctf_field_type *type, void *data)
1935 {
1936 int64_t ret = -1;
1937 int iret;
1938 struct bt_ctf_field_path *field_path;
1939 struct bt_ctf_notif_iter *notit = data;
1940 struct bt_ctf_field *length_field = NULL;
1941 uint64_t length;
1942
1943 field_path = bt_ctf_field_type_sequence_get_length_field_path(type);
1944 if (!field_path) {
1945 goto end;
1946 }
1947
1948 length_field = resolve_field(notit, field_path);
1949 if (!length_field) {
1950 goto end;
1951 }
1952
1953 iret = bt_ctf_field_unsigned_integer_get_value(length_field, &length);
1954 if (iret) {
1955 goto end;
1956 }
1957
1958 iret = bt_ctf_field_sequence_set_length(stack_top(notit->stack)->base,
1959 length_field);
1960 if (iret) {
1961 goto end;
1962 }
1963 ret = (int64_t) length;
1964
1965 end:
1966 BT_PUT(length_field);
1967 BT_PUT(field_path);
1968
1969 return ret;
1970 }
1971
1972 static
1973 struct bt_ctf_field_type *btr_get_variant_type_cb(
1974 struct bt_ctf_field_type *type, void *data)
1975 {
1976 struct bt_ctf_field_path *path;
1977 struct bt_ctf_notif_iter *notit = data;
1978 struct bt_ctf_field *tag_field = NULL;
1979 struct bt_ctf_field *selected_field = NULL;
1980 struct bt_ctf_field_type *selected_field_type = NULL;
1981
1982 path = bt_ctf_field_type_variant_get_tag_field_path(type);
1983 if (!path) {
1984 goto end;
1985 }
1986
1987 tag_field = resolve_field(notit, path);
1988 if (!tag_field) {
1989 goto end;
1990 }
1991
1992 /*
1993 * We found the enumeration tag field instance which should be
1994 * able to select a current field for this variant. This
1995 * callback function we're in is called _after_
1996 * compound_begin(), so the current stack top's base field is
1997 * the variant field in question. We get the selected field here
1998 * thanks to this tag field (thus creating the selected field),
1999 * which will also provide us with its type. Then, this field
2000 * will remain the current selected one until the next callback
2001 * function call which is used to fill the current selected
2002 * field.
2003 */
2004 selected_field = bt_ctf_field_variant_get_field(
2005 stack_top(notit->stack)->base, tag_field);
2006 if (!selected_field) {
2007 goto end;
2008 }
2009
2010 selected_field_type = bt_ctf_field_get_type(selected_field);
2011
2012 end:
2013 BT_PUT(tag_field);
2014 BT_PUT(selected_field);
2015 BT_PUT(path);
2016
2017 return selected_field_type;
2018 }
2019
2020 static
2021 int set_event_clocks(struct bt_ctf_event *event,
2022 struct bt_ctf_notif_iter *notit)
2023 {
2024 int ret;
2025 GHashTableIter iter;
2026 struct bt_ctf_clock_class *clock_class;
2027 uint64_t *clock_state;
2028
2029 g_hash_table_iter_init(&iter, notit->clock_states);
2030
2031 while (g_hash_table_iter_next(&iter, (gpointer) &clock_class,
2032 (gpointer) &clock_state)) {
2033 struct bt_ctf_clock_value *clock_value;
2034
2035 clock_value = bt_ctf_clock_value_create(clock_class,
2036 *clock_state);
2037 if (!clock_value) {
2038 ret = -1;
2039 goto end;
2040 }
2041 ret = bt_ctf_event_set_clock_value(event, clock_value);
2042 bt_put(clock_value);
2043 if (ret) {
2044 goto end;
2045 }
2046 }
2047 ret = 0;
2048 end:
2049 return ret;
2050 }
2051
2052 static
2053 struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit)
2054 {
2055 int ret;
2056 struct bt_ctf_event *event;
2057
2058 /* Create event object. */
2059 event = bt_ctf_event_create(notit->meta.event_class);
2060 if (!event) {
2061 goto error;
2062 }
2063
2064 /* Set header, stream event context, context, and payload fields. */
2065 ret = bt_ctf_event_set_header(event,
2066 notit->dscopes.stream_event_header);
2067 if (ret) {
2068 goto error;
2069 }
2070
2071 ret = bt_ctf_event_set_stream_event_context(event,
2072 notit->dscopes.stream_event_context);
2073 if (ret) {
2074 goto error;
2075 }
2076
2077 ret = bt_ctf_event_set_event_context(event,
2078 notit->dscopes.event_context);
2079 if (ret) {
2080 goto error;
2081 }
2082
2083 ret = bt_ctf_event_set_payload_field(event,
2084 notit->dscopes.event_payload);
2085 if (ret) {
2086 goto error;
2087 }
2088
2089 ret = set_event_clocks(event, notit);
2090 if (ret) {
2091 goto error;
2092 }
2093
2094 /* Associate with current packet. */
2095 assert(notit->packet);
2096 ret = bt_ctf_event_set_packet(event, notit->packet);
2097 if (ret) {
2098 goto error;
2099 }
2100
2101 goto end;
2102 error:
2103 BT_PUT(event);
2104 end:
2105 return event;
2106 }
2107
2108 static
2109 void create_packet(struct bt_ctf_notif_iter *notit)
2110 {
2111 int ret;
2112 struct bt_ctf_stream *stream = NULL;
2113 struct bt_ctf_packet *packet = NULL;
2114
2115 /* Ask the user for the stream */
2116 stream = notit->medium.medops.get_stream(notit->meta.stream_class,
2117 notit->medium.data);
2118 if (!stream) {
2119 goto error;
2120 }
2121
2122 /* Create packet */
2123 packet = bt_ctf_packet_create(stream);
2124 if (!packet) {
2125 goto error;
2126 }
2127
2128 /* Set packet's context and header fields */
2129 if (notit->dscopes.trace_packet_header) {
2130 ret = bt_ctf_packet_set_header(packet,
2131 notit->dscopes.trace_packet_header);
2132 if (ret) {
2133 goto error;
2134 }
2135 }
2136
2137 if (notit->dscopes.stream_packet_context) {
2138 ret = bt_ctf_packet_set_context(packet,
2139 notit->dscopes.stream_packet_context);
2140 if (ret) {
2141 goto error;
2142 }
2143 }
2144
2145 goto end;
2146 error:
2147 BT_PUT(packet);
2148 end:
2149 BT_MOVE(notit->packet, packet);
2150 }
2151
2152 static
2153 void notify_new_packet(struct bt_ctf_notif_iter *notit,
2154 struct bt_notification **notification)
2155 {
2156 struct bt_notification *ret;
2157
2158 /* Initialize the iterator's current packet */
2159 create_packet(notit);
2160 if (!notit->packet) {
2161 return;
2162 }
2163
2164 ret = bt_notification_packet_begin_create(notit->packet);
2165 if (!ret) {
2166 return;
2167 }
2168 *notification = ret;
2169 }
2170
2171 static
2172 void notify_end_of_packet(struct bt_ctf_notif_iter *notit,
2173 struct bt_notification **notification)
2174 {
2175 struct bt_notification *ret;
2176
2177 if (!notit->packet) {
2178 return;
2179 }
2180
2181 ret = bt_notification_packet_end_create(notit->packet);
2182 if (!ret) {
2183 return;
2184 }
2185 BT_PUT(notit->packet);
2186 *notification = ret;
2187 }
2188
2189 static
2190 void notify_event(struct bt_ctf_notif_iter *notit,
2191 struct bt_notification **notification)
2192 {
2193 struct bt_ctf_event *event;
2194 struct bt_notification *ret = NULL;
2195
2196 /* Create event */
2197 event = create_event(notit);
2198 if (!event) {
2199 goto end;
2200 }
2201
2202 ret = bt_notification_event_create(event, notit->cc_prio_map);
2203 if (!ret) {
2204 goto end;
2205 }
2206 *notification = ret;
2207 end:
2208 BT_PUT(event);
2209 }
2210
2211 //FIXME: not used ?
2212 static
2213 void notify_eos(struct bt_ctf_notif_iter *notit,
2214 struct bt_notification **notification)
2215 {
2216 struct bt_ctf_stream *stream = NULL;
2217 struct bt_notification *ret = NULL;
2218
2219 /* Ask the user for the stream */
2220 stream = notit->medium.medops.get_stream(notit->meta.stream_class,
2221 notit->medium.data);
2222 if (!stream) {
2223 goto end;
2224 }
2225
2226 ret = bt_notification_stream_end_create(stream);
2227 if (!ret) {
2228 goto end;
2229 }
2230 *notification = ret;
2231 end:
2232 BT_PUT(stream);
2233 }
2234
2235 static
2236 int init_clock_states(GHashTable *clock_states, struct bt_ctf_trace *trace)
2237 {
2238 int clock_class_count, i, ret = 0;
2239
2240 clock_class_count = bt_ctf_trace_get_clock_class_count(trace);
2241 if (clock_class_count <= 0) {
2242 ret = -1;
2243 goto end;
2244 }
2245
2246 for (i = 0; i < clock_class_count; i++) {
2247 struct bt_ctf_clock_class *clock_class;
2248
2249 clock_class = bt_ctf_trace_get_clock_class(trace, i);
2250 if (!clock_class) {
2251 ret = -1;
2252 goto end;
2253 }
2254
2255 g_hash_table_insert(clock_states, bt_get(clock_class), NULL);
2256 bt_put(clock_class);
2257 }
2258 end:
2259 return ret;
2260 }
2261
2262 static
2263 void init_trace_field_path_cache(struct bt_ctf_trace *trace,
2264 struct trace_field_path_cache *trace_field_path_cache)
2265 {
2266 int stream_id = -1;
2267 int stream_instance_id = -1;
2268 int i, count;
2269 struct bt_ctf_field_type *packet_header = NULL;
2270
2271 packet_header = bt_ctf_trace_get_packet_header_type(trace);
2272 if (!packet_header) {
2273 goto end;
2274 }
2275
2276 if (!bt_ctf_field_type_is_structure(packet_header)) {
2277 goto end;
2278 }
2279
2280 count = bt_ctf_field_type_structure_get_field_count(packet_header);
2281 if (count < 0) {
2282 goto end;
2283 }
2284
2285 for (i = 0; (i < count && (stream_id == -1 || stream_instance_id == -1)); i++) {
2286 int ret;
2287 const char *field_name;
2288
2289 ret = bt_ctf_field_type_structure_get_field(packet_header,
2290 &field_name, NULL, i);
2291 if (ret) {
2292 goto end;
2293 }
2294
2295 if (stream_id == -1 && !strcmp(field_name, "stream_id")) {
2296 stream_id = i;
2297 } else if (stream_instance_id == -1 &&
2298 !strcmp(field_name, "stream_instance_id")) {
2299 stream_instance_id = i;
2300 }
2301 }
2302 end:
2303 trace_field_path_cache->stream_id = stream_id;
2304 trace_field_path_cache->stream_instance_id = stream_instance_id;
2305 BT_PUT(packet_header);
2306 }
2307
2308 BT_HIDDEN
2309 struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace,
2310 struct bt_clock_class_priority_map *cc_prio_map,
2311 size_t max_request_sz,
2312 struct bt_ctf_notif_iter_medium_ops medops,
2313 void *data, FILE *err_stream)
2314 {
2315 int ret;
2316 struct bt_ctf_notif_iter *notit = NULL;
2317 struct bt_ctf_btr_cbs cbs = {
2318 .types = {
2319 .signed_int = btr_signed_int_cb,
2320 .unsigned_int = btr_unsigned_int_cb,
2321 .floating_point = btr_floating_point_cb,
2322 .string_begin = btr_string_begin_cb,
2323 .string = btr_string_cb,
2324 .string_end = btr_string_end_cb,
2325 .compound_begin = btr_compound_begin_cb,
2326 .compound_end = btr_compound_end_cb,
2327 },
2328 .query = {
2329 .get_sequence_length = btr_get_sequence_length_cb,
2330 .get_variant_type = btr_get_variant_type_cb,
2331 },
2332 };
2333
2334 assert(trace);
2335 assert(cc_prio_map);
2336 assert(medops.request_bytes);
2337 assert(medops.get_stream);
2338 notit = g_new0(struct bt_ctf_notif_iter, 1);
2339 if (!notit) {
2340 PERR("Failed to allocate memory for CTF notification iterator\n");
2341 goto end;
2342 }
2343 notit->clock_states = g_hash_table_new_full(g_direct_hash,
2344 g_direct_equal, bt_put, g_free);
2345 if (!notit->clock_states) {
2346 PERR("Failed to create hash table\n");
2347 goto error;
2348 }
2349 ret = init_clock_states(notit->clock_states, trace);
2350 if (ret) {
2351 PERR("Failed to initialize stream clock states\n");
2352 goto error;
2353 }
2354 notit->cc_prio_map = bt_get(cc_prio_map);
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->cc_prio_map);
2399 BT_PUT(notit->meta.trace);
2400 BT_PUT(notit->meta.stream_class);
2401 BT_PUT(notit->meta.event_class);
2402 BT_PUT(notit->packet);
2403 BT_PUT(notit->cur_timestamp_end);
2404 put_all_dscopes(notit);
2405
2406 if (notit->stack) {
2407 stack_destroy(notit->stack);
2408 }
2409
2410 if (notit->btr) {
2411 bt_ctf_btr_destroy(notit->btr);
2412 }
2413
2414 if (notit->clock_states) {
2415 g_hash_table_destroy(notit->clock_states);
2416 }
2417
2418 if (notit->sc_field_path_caches) {
2419 g_hash_table_destroy(notit->sc_field_path_caches);
2420 }
2421
2422 if (notit->field_overrides) {
2423 g_hash_table_destroy(notit->field_overrides);
2424 }
2425 g_free(notit);
2426 }
2427
2428 enum bt_ctf_notif_iter_status bt_ctf_notif_iter_get_next_notification(
2429 struct bt_ctf_notif_iter *notit,
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, 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, field_type,
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.113648 seconds and 5 git commands to generate.