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