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