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