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