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