ir: stream: add bt_ctf_stream_is_writer()
[babeltrace.git] / plugins / ctf / common / notif-iter / notif-iter.c
CommitLineData
e98a2d6e
PP
1/*
2 * Babeltrace - CTF notification iterator
06a626b8 3 *
e98a2d6e
PP
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>
78586d8a
JG
41#include <babeltrace/plugin/notification/packet.h>
42#include <babeltrace/plugin/notification/event.h>
b7726e32 43#include <babeltrace/plugin/notification/stream.h>
e98a2d6e
PP
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
06a626b8
JG
51#include "notif-iter.h"
52#include "../btr/btr.h"
e98a2d6e
PP
53
54#define BYTES_TO_BITS(x) ((x) * 8)
55
56struct bt_ctf_notif_iter;
57
58/* A visit stack entry */
59struct 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 */
78struct stack {
79 /* Entries (struct stack_entry *) (top is last element) */
80 GPtrArray *entries;
e98a2d6e
PP
81};
82
83/* State */
84enum 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
5f870343
JG
107struct 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
116struct 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
134struct 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
e98a2d6e
PP
140/* CTF notification iterator */
141struct 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
5f870343
JG
167 /*
168 * Current timestamp_end field (to consider before switching packets).
169 */
170 struct bt_ctf_field *cur_timestamp_end;
171
e98a2d6e
PP
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
5f870343
JG
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
e98a2d6e
PP
197 /* Current state */
198 enum state state;
199
2cf1d51e 200 /* Current medium buffer data */
e98a2d6e
PP
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
2cf1d51e 218 /* Current medium data */
e98a2d6e
PP
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) */
e7a4393b 226 int64_t cur_packet_size;
e98a2d6e
PP
227
228 /* Current content size (bits) (-1 if unknown) */
e7a4393b 229 int64_t cur_content_size;
c44c3e70
JG
230
231 /* bt_ctf_clock to uint64_t. */
232 GHashTable *clock_states;
5f870343
JG
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;
e98a2d6e
PP
248};
249
2cf1d51e
JG
250static
251int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter *notit);
252
5f870343
JG
253static
254enum bt_ctf_btr_status btr_timestamp_end_cb(void *value,
255 struct bt_ctf_field_type *type, void *data);
256
e98a2d6e
PP
257static
258void 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
266static
267struct 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
e98a2d6e 281 return stack;
e98a2d6e
PP
282error:
283 g_free(stack);
e98a2d6e
PP
284 return NULL;
285}
286
287static
288void stack_destroy(struct stack *stack)
289{
290 assert(stack);
291 g_ptr_array_free(stack->entries, TRUE);
292 g_free(stack);
293}
294
295static
296int stack_push(struct stack *stack, struct bt_ctf_field *base)
297{
298 int ret = 0;
299 struct stack_entry *entry;
e98a2d6e
PP
300
301 assert(stack);
302 assert(base);
e98a2d6e
PP
303 entry = g_new0(struct stack_entry, 1);
304 if (!entry) {
e98a2d6e
PP
305 ret = -1;
306 goto end;
307 }
308
309 entry->base = bt_get(base);
310 g_ptr_array_add(stack->entries, entry);
311
312end:
313 return ret;
314}
315
316static inline
317unsigned int stack_size(struct stack *stack)
318{
319 assert(stack);
320
321 return stack->entries->len;
322}
323
324static
325void 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
332static inline
333struct 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
341static inline
342bool stack_empty(struct stack *stack)
343{
344 return stack_size(stack) == 0;
345}
346
347static
348void 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
359static inline
360enum 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
366static inline
367size_t buf_size_bits(struct bt_ctf_notif_iter *notit)
368{
369 return BYTES_TO_BITS(notit->buf.sz);
370}
371
372static inline
373size_t buf_available_bits(struct bt_ctf_notif_iter *notit)
374{
375 return buf_size_bits(notit) - notit->buf.at;
376}
377
378static inline
379size_t packet_at(struct bt_ctf_notif_iter *notit)
380{
381 return notit->buf.packet_offset + notit->buf.at;
382}
383
384static inline
385size_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
394static inline
395size_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
404static inline
405void buf_consume_bits(struct bt_ctf_notif_iter *notit, size_t incr)
406{
407 notit->buf.at += incr;
408}
409
410static inline
411bool buf_has_enough_bits(struct bt_ctf_notif_iter *notit, size_t sz)
412{
413 return buf_available_bits(notit) >= sz;
414}
415
416static
2cf1d51e
JG
417enum bt_ctf_notif_iter_status request_medium_bytes(
418 struct bt_ctf_notif_iter *notit)
e98a2d6e
PP
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
446static inline
447enum 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
463static
464enum 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
502end:
503 return status;
504}
505
506static
507enum 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,
78586d8a 520 notit->buf.sz, &btr_status);
e98a2d6e
PP
521
522 switch (btr_status) {
523 case BT_CTF_BTR_STATUS_OK:
78586d8a 524 /* Type was read completely. */
e98a2d6e
PP
525 notit->state = done_state;
526 break;
527 case BT_CTF_BTR_STATUS_EOF:
78586d8a 528 /* Stay in this continue state. */
e98a2d6e
PP
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
78586d8a 536 /* Consume bits now since we know we're not in an error state. */
e98a2d6e 537 buf_consume_bits(notit, consumed_bits);
e98a2d6e
PP
538end:
539 return status;
540}
541
542static
543void 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
551static
552void 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
559static
560enum bt_ctf_notif_iter_status read_packet_header_begin_state(
561 struct bt_ctf_notif_iter *notit)
562{
2cf1d51e
JG
563 struct bt_ctf_field_type *packet_header_type = NULL;
564 enum bt_ctf_notif_iter_status ret = BT_CTF_NOTIF_ITER_STATUS_OK;
e98a2d6e 565
2cf1d51e
JG
566 if (bt_ctf_notif_iter_switch_packet(notit)) {
567 ret = BT_CTF_NOTIF_ITER_STATUS_ERROR;
568 goto end;
569 }
e98a2d6e 570
2cf1d51e 571 /* Packet header type is common to the whole trace. */
e98a2d6e 572 packet_header_type = bt_ctf_trace_get_packet_header_type(
78586d8a 573 notit->meta.trace);
e98a2d6e 574 if (!packet_header_type) {
835b2d10 575 notit->state = STATE_AFTER_TRACE_PACKET_HEADER;
e98a2d6e
PP
576 goto end;
577 }
578
2cf1d51e 579 ret = read_dscope_begin_state(notit, packet_header_type,
78586d8a
JG
580 STATE_AFTER_TRACE_PACKET_HEADER,
581 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
582 &notit->dscopes.trace_packet_header);
e98a2d6e
PP
583end:
584 BT_PUT(packet_header_type);
2cf1d51e 585 return ret;
e98a2d6e
PP
586}
587
588static
589enum 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,
78586d8a 593 STATE_AFTER_TRACE_PACKET_HEADER);
e98a2d6e
PP
594}
595
596static inline
597bool is_struct_type(struct bt_ctf_field_type *field_type)
598{
78586d8a
JG
599 return bt_ctf_field_type_get_type_id(field_type) ==
600 BT_CTF_TYPE_ID_STRUCT;
e98a2d6e
PP
601}
602
603static inline
604bool is_variant_type(struct bt_ctf_field_type *field_type)
605{
78586d8a
JG
606 return bt_ctf_field_type_get_type_id(field_type) ==
607 BT_CTF_TYPE_ID_VARIANT;
e98a2d6e
PP
608}
609
5f870343
JG
610static
611struct stream_class_field_path_cache *
612create_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;
718end:
719 BT_PUT(event_header);
720 BT_PUT(packet_context);
721 return cache_entry;
722error:
723 g_free(cache_entry);
724 cache_entry = NULL;
725 goto end;
726}
727
728static
729struct 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
e98a2d6e 749static inline
835b2d10
JG
750enum bt_ctf_notif_iter_status set_current_stream_class(
751 struct bt_ctf_notif_iter *notit)
e98a2d6e
PP
752{
753 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
5f870343 754 struct bt_ctf_field_type *packet_header_type = NULL;
e98a2d6e
PP
755 struct bt_ctf_field_type *stream_id_field_type = NULL;
756 uint64_t stream_id;
757
5f870343
JG
758 /* Clear the current stream class field path cache. */
759 notit->cur_sc_field_path_cache = NULL;
760
e98a2d6e
PP
761 /* Is there any "stream_id" field in the packet header? */
762 packet_header_type = bt_ctf_trace_get_packet_header_type(
78586d8a 763 notit->meta.trace);
e98a2d6e
PP
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 =
78586d8a
JG
774 bt_ctf_field_type_structure_get_field_type_by_name(
775 packet_header_type, "stream_id");
e98a2d6e
PP
776 if (stream_id_field_type) {
777 /* Find appropriate stream class using current stream ID */
e98a2d6e 778 int ret;
5f870343 779 struct bt_ctf_field *stream_id_field = NULL;
e98a2d6e
PP
780
781 assert(notit->dscopes.trace_packet_header);
782
783 // TODO: optimalize!
784 stream_id_field = bt_ctf_field_structure_get_field(
78586d8a 785 notit->dscopes.trace_packet_header, "stream_id");
e98a2d6e
PP
786 assert(stream_id_field);
787 ret = bt_ctf_field_unsigned_integer_get_value(
78586d8a 788 stream_id_field, &stream_id);
e98a2d6e
PP
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(
78586d8a 794 notit->meta.trace) == 1);
e98a2d6e
PP
795 stream_id = 0;
796 }
797
798 BT_PUT(notit->meta.stream_class);
5b29e799 799 notit->meta.stream_class = bt_ctf_trace_get_stream_class_by_id(
78586d8a 800 notit->meta.trace, stream_id);
e98a2d6e
PP
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
5f870343
JG
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 }
e98a2d6e
PP
819end:
820 BT_PUT(packet_header_type);
821 BT_PUT(stream_id_field_type);
822
823 return status;
824}
825
826static
827enum 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
840static
841enum 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(
78586d8a 849 notit->meta.stream_class);
e98a2d6e 850 if (!packet_context_type) {
835b2d10 851 notit->state = STATE_AFTER_STREAM_PACKET_CONTEXT;
e98a2d6e
PP
852 goto end;
853 }
854
855 status = read_dscope_begin_state(notit, packet_context_type,
78586d8a
JG
856 STATE_AFTER_STREAM_PACKET_CONTEXT,
857 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
858 &notit->dscopes.stream_packet_context);
e98a2d6e
PP
859
860end:
861 BT_PUT(packet_context_type);
e98a2d6e
PP
862 return status;
863}
864
865static
866enum 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,
78586d8a 870 STATE_AFTER_STREAM_PACKET_CONTEXT);
e98a2d6e
PP
871}
872
78586d8a 873static
e98a2d6e
PP
874enum 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
e98a2d6e 884 packet_size_field = bt_ctf_field_structure_get_field(
78586d8a 885 notit->dscopes.stream_packet_context, "packet_size");
e98a2d6e 886 content_size_field = bt_ctf_field_structure_get_field(
78586d8a 887 notit->dscopes.stream_packet_context, "content_size");
e98a2d6e
PP
888 if (packet_size_field) {
889 int ret = bt_ctf_field_unsigned_integer_get_value(
78586d8a 890 packet_size_field, &packet_size);
e98a2d6e 891
78586d8a 892 assert(!ret);
e98a2d6e
PP
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 }
78586d8a 903
e98a2d6e
PP
904 if (content_size_field) {
905 int ret = bt_ctf_field_unsigned_integer_get_value(
906 content_size_field, &content_size);
78586d8a 907
e98a2d6e
PP
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;
e98a2d6e
PP
915end:
916 BT_PUT(packet_size_field);
917 BT_PUT(content_size_field);
e98a2d6e
PP
918 return status;
919}
920
921static
922enum 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
935static
936enum 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");
78586d8a 951 PERR("\tDecoded content size: %zu\n",
e98a2d6e 952 notit->cur_content_size);
78586d8a 953 PERR("\tCursor position: %zu\n", packet_at(notit));
e98a2d6e
PP
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) {
835b2d10 962 notit->state = STATE_AFTER_STREAM_EVENT_HEADER;
e98a2d6e
PP
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);
e98a2d6e
PP
971end:
972 BT_PUT(event_header_type);
973
974 return status;
975}
976
977static
978enum 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
985static inline
986enum 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
1053end_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
1104end:
1105 BT_PUT(event_header_type);
1106 BT_PUT(id_field_type);
1107 BT_PUT(v_field_type);
1108
1109 return status;
1110}
1111
1112static
1113enum 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
e98a2d6e
PP
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
1126end:
1127 return status;
1128}
1129
1130static
1131enum 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) {
835b2d10 1140 notit->state = STATE_DSCOPE_EVENT_CONTEXT_BEGIN;
e98a2d6e
PP
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
1149end:
1150 BT_PUT(stream_event_context_type);
1151
1152 return status;
1153}
1154
1155static
1156enum 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
1163static
1164enum 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) {
835b2d10 1173 notit->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN;
e98a2d6e
PP
1174 goto end;
1175 }
e98a2d6e
PP
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
1181end:
1182 BT_PUT(event_context_type);
1183
1184 return status;
1185}
1186
1187static
1188enum 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
1195static
1196enum 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) {
835b2d10 1205 notit->state = STATE_EMIT_NOTIF_EVENT;
e98a2d6e
PP
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
1214end:
1215 BT_PUT(event_payload_type);
1216
1217 return status;
1218}
1219
1220static
1221enum 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
1227static
1228enum 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
1255end:
1256 return status;
1257}
1258
1259static inline
1260enum 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
2cf1d51e
JG
1333/**
1334 * Resets the internal state of a CTF notification iterator.
2cf1d51e
JG
1335 */
1336static
e98a2d6e
PP
1337void 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
2cf1d51e
JG
1354static
1355int 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);
5f870343 1364 BT_PUT(notit->cur_timestamp_end);
2cf1d51e
JG
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;
5f870343 1388 notit->cur_sc_field_path_cache = NULL;
2cf1d51e
JG
1389end:
1390 return ret;
1391}
1392
e98a2d6e
PP
1393static
1394struct 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
1429end:
1430 BT_PUT(base_type);
1431
1432 return next_field;
1433}
1434
c44c3e70
JG
1435static
1436void 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;
1484end:
1485 bt_put(value_type);
1486}
1487
1488static
1489enum 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);
1526end:
1527 bt_put(clock);
1528end_no_clock:
1529 return ret;
1530}
1531
e98a2d6e 1532static
5f870343
JG
1533enum 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)
e98a2d6e
PP
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
5f870343 1543 /* Create next field */
e98a2d6e
PP
1544 field = get_next_field(notit);
1545 if (!field) {
5f870343 1546 PERR("Failed to get next field (unsigned int)\n");
e98a2d6e 1547 status = BT_CTF_BTR_STATUS_ERROR;
c44c3e70 1548 goto end_no_put;
e98a2d6e
PP
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);
c44c3e70 1555 bt_get(type);
e98a2d6e
PP
1556 break;
1557 case BT_CTF_TYPE_ID_ENUM:
1558 int_field = bt_ctf_field_enumeration_get_container(field);
c44c3e70 1559 type = bt_ctf_field_get_type(int_field);
e98a2d6e
PP
1560 break;
1561 default:
c44c3e70
JG
1562 assert(0);
1563 type = NULL;
e98a2d6e
PP
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
5f870343 1573 ret = bt_ctf_field_unsigned_integer_set_value(int_field, value);
e98a2d6e
PP
1574 assert(!ret);
1575 stack_top(notit->stack)->index++;
5f870343
JG
1576 *_field = int_field;
1577
e98a2d6e
PP
1578end:
1579 BT_PUT(field);
c44c3e70
JG
1580 BT_PUT(type);
1581end_no_put:
e98a2d6e
PP
1582 return status;
1583}
1584
5f870343
JG
1585static
1586enum 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
e98a2d6e
PP
1601static
1602enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value,
1603 struct bt_ctf_field_type *type, void *data)
5f870343
JG
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);
1624end:
1625 return status;
1626}
1627
1628static
1629enum bt_ctf_btr_status btr_signed_int_cb(int64_t value,
1630 struct bt_ctf_field_type *type, void *data)
e98a2d6e
PP
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
5f870343 1638 /* create next field */
e98a2d6e
PP
1639 field = get_next_field(notit);
1640 if (!field) {
5f870343 1641 PERR("Failed to get next field (signed int)\n");
e98a2d6e 1642 status = BT_CTF_BTR_STATUS_ERROR;
c44c3e70 1643 goto end_no_put;
e98a2d6e
PP
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);
c44c3e70 1650 bt_get(type);
e98a2d6e
PP
1651 break;
1652 case BT_CTF_TYPE_ID_ENUM:
1653 int_field = bt_ctf_field_enumeration_get_container(field);
c44c3e70 1654 type = bt_ctf_field_get_type(int_field);
e98a2d6e
PP
1655 break;
1656 default:
c44c3e70
JG
1657 assert(0);
1658 type = NULL;
e98a2d6e
PP
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
5f870343 1668 ret = bt_ctf_field_signed_integer_set_value(int_field, value);
e98a2d6e
PP
1669 assert(!ret);
1670 stack_top(notit->stack)->index++;
c44c3e70 1671 status = update_clock(notit, type, int_field);
e98a2d6e
PP
1672end:
1673 BT_PUT(field);
1674 BT_PUT(int_field);
c44c3e70
JG
1675 BT_PUT(type);
1676end_no_put:
e98a2d6e
PP
1677 return status;
1678}
1679
1680static
1681enum 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
1701end:
1702 BT_PUT(field);
1703
1704 return status;
1705}
1706
1707static
1708enum 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
e5df2ae3
JG
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
e98a2d6e
PP
1748end:
1749 BT_PUT(field);
1750
1751 return status;
1752}
1753
1754static
1755enum 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
1775end:
1776 return status;
1777}
1778
1779static
1780enum 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
1794enum 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
1833end:
1834 BT_PUT(field);
1835
1836 return status;
1837}
1838
1839enum 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
1857static
1858struct 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
1923end:
1924 return field;
1925}
1926
1927static
1928int64_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;
2cf1d51e 1934 struct bt_ctf_field *length_field = NULL;
e98a2d6e
PP
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
2cf1d51e
JG
1942 length_field = resolve_field(notit, field_path);
1943 if (!length_field) {
e98a2d6e
PP
1944 goto end;
1945 }
1946
2cf1d51e 1947 iret = bt_ctf_field_unsigned_integer_get_value(length_field, &length);
e98a2d6e
PP
1948 if (iret) {
1949 goto end;
1950 }
1951
2cf1d51e
JG
1952 iret = bt_ctf_field_sequence_set_length(stack_top(notit->stack)->base,
1953 length_field);
1954 if (iret) {
1955 goto end;
1956 }
e98a2d6e
PP
1957 ret = (int64_t) length;
1958
1959end:
2cf1d51e 1960 BT_PUT(length_field);
e98a2d6e
PP
1961 BT_PUT(field_path);
1962
1963 return ret;
1964}
1965
1966static
1967struct 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
2006end:
2007 BT_PUT(tag_field);
2008 BT_PUT(selected_field);
f77ae72a 2009 BT_PUT(path);
e98a2d6e
PP
2010
2011 return selected_field_type;
2012}
2013
1556a1af
JG
2014static
2015int 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;
2041end:
2042 return ret;
2043}
2044
78586d8a
JG
2045static
2046struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit)
e98a2d6e 2047{
e98a2d6e 2048 int ret;
78586d8a 2049 struct bt_ctf_event *event;
e98a2d6e 2050
78586d8a 2051 /* Create event object. */
e98a2d6e
PP
2052 event = bt_ctf_event_create(notit->meta.event_class);
2053 if (!event) {
2054 goto error;
2055 }
2056
78586d8a 2057 /* Set header, stream event context, context, and payload fields. */
e98a2d6e
PP
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
1556a1af
JG
2082 ret = set_event_clocks(event, notit);
2083 if (ret) {
2084 goto error;
2085 }
2086
78586d8a 2087 /* Associate with current packet. */
e98a2d6e
PP
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;
e98a2d6e
PP
2095error:
2096 BT_PUT(event);
e98a2d6e
PP
2097end:
2098 return event;
2099}
2100
78586d8a
JG
2101static
2102void create_packet(struct bt_ctf_notif_iter *notit)
e98a2d6e
PP
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,
78586d8a 2110 notit->medium.data);
e98a2d6e
PP
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,
78586d8a 2124 notit->dscopes.trace_packet_header);
e98a2d6e
PP
2125 if (ret) {
2126 goto error;
2127 }
2128 }
2129
2130 if (notit->dscopes.stream_packet_context) {
2131 ret = bt_ctf_packet_set_context(packet,
78586d8a 2132 notit->dscopes.stream_packet_context);
e98a2d6e
PP
2133 if (ret) {
2134 goto error;
2135 }
2136 }
2137
2138 goto end;
e98a2d6e
PP
2139error:
2140 BT_PUT(packet);
e98a2d6e
PP
2141end:
2142 BT_MOVE(notit->packet, packet);
2143}
2144
78586d8a
JG
2145static
2146void notify_new_packet(struct bt_ctf_notif_iter *notit,
2147 struct bt_notification **notification)
e98a2d6e 2148{
78586d8a 2149 struct bt_notification *ret;
e98a2d6e 2150
78586d8a 2151 /* Initialize the iterator's current packet */
e98a2d6e
PP
2152 create_packet(notit);
2153 if (!notit->packet) {
78586d8a 2154 return;
e98a2d6e
PP
2155 }
2156
ea0e619e 2157 ret = bt_notification_packet_begin_create(notit->packet);
78586d8a
JG
2158 if (!ret) {
2159 return;
2160 }
2161 *notification = ret;
e98a2d6e
PP
2162}
2163
78586d8a
JG
2164static
2165void notify_end_of_packet(struct bt_ctf_notif_iter *notit,
2166 struct bt_notification **notification)
e98a2d6e 2167{
78586d8a 2168 struct bt_notification *ret;
e98a2d6e 2169
e98a2d6e 2170 if (!notit->packet) {
78586d8a 2171 return;
e98a2d6e
PP
2172 }
2173
78586d8a
JG
2174 ret = bt_notification_packet_end_create(notit->packet);
2175 if (!ret) {
2176 return;
2177 }
2178 BT_PUT(notit->packet);
2179 *notification = ret;
e98a2d6e
PP
2180}
2181
78586d8a
JG
2182static
2183void notify_event(struct bt_ctf_notif_iter *notit,
2184 struct bt_notification **notification)
e98a2d6e 2185{
78586d8a
JG
2186 struct bt_ctf_event *event;
2187 struct bt_notification *ret = NULL;
e98a2d6e
PP
2188
2189 /* Create event */
2190 event = create_event(notit);
2191 if (!event) {
78586d8a 2192 goto end;
e98a2d6e 2193 }
e98a2d6e 2194
78586d8a
JG
2195 ret = bt_notification_event_create(event);
2196 if (!ret) {
2197 goto end;
e98a2d6e 2198 }
78586d8a
JG
2199 *notification = ret;
2200end:
2201 BT_PUT(event);
e98a2d6e
PP
2202}
2203
b7726e32 2204//FIXME: not used ?
043e2020
JG
2205static
2206void notify_eos(struct bt_ctf_notif_iter *notit,
2207 struct bt_notification **notification)
2208{
b7726e32 2209 struct bt_ctf_stream *stream = NULL;
043e2020
JG
2210 struct bt_notification *ret = NULL;
2211
b7726e32
MD
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) {
043e2020
JG
2216 goto end;
2217 }
2218
b7726e32 2219 ret = bt_notification_stream_end_create(stream);
043e2020
JG
2220 if (!ret) {
2221 goto end;
2222 }
2223 *notification = ret;
2224end:
b7726e32 2225 BT_PUT(stream);
043e2020
JG
2226}
2227
c44c3e70
JG
2228static
2229int 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 }
2251end:
2252 return ret;
2253}
2254
5f870343
JG
2255static
2256void 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 }
2295end:
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
c44c3e70 2301BT_HIDDEN
e98a2d6e
PP
2302struct 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{
c44c3e70 2307 int ret;
e98a2d6e
PP
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 }
c44c3e70
JG
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 }
35d47007 2344 notit->meta.trace = bt_get(trace);
e98a2d6e
PP
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");
c44c3e70 2352 goto error;
e98a2d6e
PP
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");
c44c3e70 2358 goto error;
e98a2d6e
PP
2359 }
2360
2361 bt_ctf_notif_iter_reset(notit);
2362
5f870343
JG
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
e98a2d6e
PP
2377end:
2378 return notit;
c44c3e70
JG
2379error:
2380 bt_ctf_notif_iter_destroy(notit);
2381 notit = NULL;
2382 goto end;
e98a2d6e
PP
2383}
2384
2385void 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);
5f870343 2391 BT_PUT(notit->cur_timestamp_end);
e98a2d6e
PP
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
c44c3e70
JG
2402 if (notit->clock_states) {
2403 g_hash_table_destroy(notit->clock_states);
2404 }
5f870343
JG
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 }
e98a2d6e
PP
2413 g_free(notit);
2414}
2415
2416enum bt_ctf_notif_iter_status bt_ctf_notif_iter_get_next_notification(
2417 struct bt_ctf_notif_iter *notit,
78586d8a 2418 struct bt_notification **notification)
e98a2d6e
PP
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) {
78586d8a 2429 PDBG("Medium operation reported end of stream\n");
e98a2d6e
PP
2430 } else {
2431 PERR("Failed to handle state:\n");
78586d8a 2432 PERR("\tState: %d\n", notit->state);
e98a2d6e
PP
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:
5f870343
JG
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
e98a2d6e
PP
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
2481end:
2482 return status;
2483}
This page took 0.127045 seconds and 4 git commands to generate.