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