Integrate ctf proto into the plugin build system
[babeltrace.git] / plugins / ctf / common / notif-iter / notif-iter.c
1 /*
2 * Babeltrace - CTF notification iterator
3 *
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>
39 #include <babeltrace/ctf-ir/clock.h>
40 #include <babeltrace/ctf-ir/event-class.h>
41 #include <babeltrace/ref.h>
42 #include <glib.h>
43
44 #define PRINT_ERR_STREAM notit->err_stream
45 #define PRINT_PREFIX "ctf-notif-iter"
46 #include "print.h"
47
48 #include "notif-iter.h"
49 #include "../btr/btr.h"
50
51 #define BYTES_TO_BITS(x) ((x) * 8)
52
53 struct bt_ctf_notif_iter;
54
55 /* A visit stack entry */
56 struct stack_entry {
57 /*
58 * Current base field, one of:
59 *
60 * * string
61 * * structure
62 * * array
63 * * sequence
64 * * variant
65 *
66 * Field is owned by this.
67 */
68 struct bt_ctf_field *base;
69
70 /* index of next field to set */
71 size_t index;
72 };
73
74 /* Visit stack */
75 struct stack {
76 /* Entries (struct stack_entry *) (top is last element) */
77 GPtrArray *entries;
78
79 /* Link to owner */
80 struct bt_ctf_notif_iter *notit;
81 };
82
83 /* State */
84 enum 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
107 /* CTF notification iterator */
108 struct bt_ctf_notif_iter {
109 /* Visit stack */
110 struct stack *stack;
111
112 /* Error stream (may be NULL) */
113 FILE *err_stream;
114
115 /*
116 * Current dynamic scope field pointer.
117 *
118 * This is set when a dynamic scope field is first created by
119 * btr_compound_begin_cb(). It points to one of the fields in
120 * dscopes below.
121 */
122 struct bt_ctf_field **cur_dscope_field;
123
124 /* Trace and classes (owned by this) */
125 struct {
126 struct bt_ctf_trace *trace;
127 struct bt_ctf_stream_class *stream_class;
128 struct bt_ctf_event_class *event_class;
129 } meta;
130
131 /* Current packet (NULL if not created yet) */
132 struct bt_ctf_packet *packet;
133
134 /* Database of current dynamic scopes (owned by this) */
135 struct {
136 struct bt_ctf_field *trace_packet_header;
137 struct bt_ctf_field *stream_packet_context;
138 struct bt_ctf_field *stream_event_header;
139 struct bt_ctf_field *stream_event_context;
140 struct bt_ctf_field *event_context;
141 struct bt_ctf_field *event_payload;
142 } dscopes;
143
144 /* Current state */
145 enum state state;
146
147 /* User buffer stuff */
148 struct {
149 /* Last address provided by medium */
150 const uint8_t *addr;
151
152 /* Buffer size provided by medium (bytes) */
153 size_t sz;
154
155 /* Offset within whole packet of addr (bits) */
156 size_t packet_offset;
157
158 /* Current position from addr (bits) */
159 size_t at;
160 } buf;
161
162 /* Binary type reader */
163 struct bt_ctf_btr *btr;
164
165 /* Medium stuff */
166 struct {
167 struct bt_ctf_notif_iter_medium_ops medops;
168 size_t max_request_sz;
169 void *data;
170 } medium;
171
172 /* Current packet size (bits) (-1 if unknown) */
173 size_t cur_packet_size;
174
175 /* Current content size (bits) (-1 if unknown) */
176 size_t cur_content_size;
177 };
178
179 static
180 void stack_entry_free_func(gpointer data)
181 {
182 struct stack_entry *entry = data;
183
184 bt_put(entry->base);
185 g_free(entry);
186 }
187
188 static
189 struct stack *stack_new(struct bt_ctf_notif_iter *notit)
190 {
191 struct stack *stack = NULL;
192
193 stack = g_new0(struct stack, 1);
194 if (!stack) {
195 goto error;
196 }
197
198 stack->entries = g_ptr_array_new_with_free_func(stack_entry_free_func);
199 if (!stack->entries) {
200 goto error;
201 }
202
203 stack->notit = notit;
204
205 return stack;
206
207 error:
208 g_free(stack);
209
210 return NULL;
211 }
212
213 static
214 void stack_destroy(struct stack *stack)
215 {
216 assert(stack);
217 g_ptr_array_free(stack->entries, TRUE);
218 g_free(stack);
219 }
220
221 static
222 int stack_push(struct stack *stack, struct bt_ctf_field *base)
223 {
224 int ret = 0;
225 struct stack_entry *entry;
226 struct bt_ctf_notif_iter *notit;
227
228 assert(stack);
229 assert(base);
230 notit = stack->notit;
231 entry = g_new0(struct stack_entry, 1);
232 if (!entry) {
233 PERR("Cannot create new stack entry\n");
234 ret = -1;
235 goto end;
236 }
237
238 entry->base = bt_get(base);
239 g_ptr_array_add(stack->entries, entry);
240
241 end:
242 return ret;
243 }
244
245 static inline
246 unsigned int stack_size(struct stack *stack)
247 {
248 assert(stack);
249
250 return stack->entries->len;
251 }
252
253 static
254 void stack_pop(struct stack *stack)
255 {
256 assert(stack);
257 assert(stack_size(stack));
258 g_ptr_array_remove_index(stack->entries, stack->entries->len - 1);
259 }
260
261 static inline
262 struct stack_entry *stack_top(struct stack *stack)
263 {
264 assert(stack);
265 assert(stack_size(stack));
266
267 return g_ptr_array_index(stack->entries, stack->entries->len - 1);
268 }
269
270 static inline
271 bool stack_empty(struct stack *stack)
272 {
273 return stack_size(stack) == 0;
274 }
275
276 static
277 void stack_clear(struct stack *stack)
278 {
279 assert(stack);
280
281 if (!stack_empty(stack)) {
282 g_ptr_array_remove_range(stack->entries, 0, stack_size(stack));
283 }
284
285 assert(stack_empty(stack));
286 }
287
288 static inline
289 enum bt_ctf_notif_iter_status notif_iter_status_from_m_status(
290 enum bt_ctf_notif_iter_medium_status m_status)
291 {
292 return m_status;
293 }
294
295 static inline
296 size_t buf_size_bits(struct bt_ctf_notif_iter *notit)
297 {
298 return BYTES_TO_BITS(notit->buf.sz);
299 }
300
301 static inline
302 size_t buf_available_bits(struct bt_ctf_notif_iter *notit)
303 {
304 return buf_size_bits(notit) - notit->buf.at;
305 }
306
307 static inline
308 size_t packet_at(struct bt_ctf_notif_iter *notit)
309 {
310 return notit->buf.packet_offset + notit->buf.at;
311 }
312
313 static inline
314 size_t remaining_content_bits(struct bt_ctf_notif_iter *notit)
315 {
316 if (notit->cur_content_size == -1) {
317 return -1;
318 }
319
320 return notit->cur_content_size - packet_at(notit);
321 }
322
323 static inline
324 size_t remaining_packet_bits(struct bt_ctf_notif_iter *notit)
325 {
326 if (notit->cur_packet_size == -1) {
327 return -1;
328 }
329
330 return notit->cur_packet_size - packet_at(notit);
331 }
332
333 static inline
334 void buf_consume_bits(struct bt_ctf_notif_iter *notit, size_t incr)
335 {
336 notit->buf.at += incr;
337 }
338
339 static inline
340 bool buf_has_enough_bits(struct bt_ctf_notif_iter *notit, size_t sz)
341 {
342 return buf_available_bits(notit) >= sz;
343 }
344
345 static
346 enum bt_ctf_notif_iter_status request_medium_bytes(struct bt_ctf_notif_iter *notit)
347 {
348 uint8_t *buffer_addr;
349 size_t buffer_sz;
350 enum bt_ctf_notif_iter_medium_status m_status;
351
352 m_status = notit->medium.medops.request_bytes(
353 notit->medium.max_request_sz, &buffer_addr,
354 &buffer_sz, notit->medium.data);
355 if (m_status == BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK) {
356 assert(buffer_sz != 0);
357
358 /* New packet offset is old one + old size (in bits) */
359 notit->buf.packet_offset += buf_size_bits(notit);
360
361 /* Restart at the beginning of the new medium buffer */
362 notit->buf.at = 0;
363
364 /* New medium buffer size */
365 notit->buf.sz = buffer_sz;
366
367 /* New medium buffer address */
368 notit->buf.addr = buffer_addr;
369 }
370
371 return notif_iter_status_from_m_status(m_status);
372 }
373
374 static inline
375 enum bt_ctf_notif_iter_status buf_ensure_available_bits(
376 struct bt_ctf_notif_iter *notit)
377 {
378 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
379
380 if (buf_available_bits(notit) == 0) {
381 /*
382 * This _cannot_ return BT_CTF_NOTIF_ITER_STATUS_OK
383 * _and_ no bits.
384 */
385 status = request_medium_bytes(notit);
386 }
387
388 return status;
389 }
390
391 static
392 enum bt_ctf_notif_iter_status read_dscope_begin_state(
393 struct bt_ctf_notif_iter *notit,
394 struct bt_ctf_field_type *dscope_field_type,
395 enum state done_state, enum state continue_state,
396 struct bt_ctf_field **dscope_field)
397 {
398 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
399 enum bt_ctf_btr_status btr_status;
400 size_t consumed_bits;
401
402 status = buf_ensure_available_bits(notit);
403 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
404 goto end;
405 }
406
407 bt_put(*dscope_field);
408 notit->cur_dscope_field = dscope_field;
409 consumed_bits = bt_ctf_btr_start(notit->btr, dscope_field_type,
410 notit->buf.addr, notit->buf.at, packet_at(notit),
411 notit->buf.sz, &btr_status);
412
413 switch (btr_status) {
414 case BT_CTF_BTR_STATUS_OK:
415 /* type was read completely */
416 notit->state = done_state;
417 break;
418 case BT_CTF_BTR_STATUS_EOF:
419 notit->state = continue_state;
420 break;
421 default:
422 PERR("Binary type reader failed to start\n");
423 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
424 goto end;
425 }
426
427 /* Consume bits now since we know we're not in an error state */
428 buf_consume_bits(notit, consumed_bits);
429
430 end:
431 return status;
432 }
433
434 static
435 enum bt_ctf_notif_iter_status read_dscope_continue_state(
436 struct bt_ctf_notif_iter *notit, enum state done_state)
437 {
438 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
439 enum bt_ctf_btr_status btr_status;
440 size_t consumed_bits;
441
442 status = buf_ensure_available_bits(notit);
443 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
444 goto end;
445 }
446
447 consumed_bits = bt_ctf_btr_continue(notit->btr, notit->buf.addr,
448 notit->buf.sz, &btr_status);
449
450 switch (btr_status) {
451 case BT_CTF_BTR_STATUS_OK:
452 /* Type was read completely */
453 notit->state = done_state;
454 break;
455 case BT_CTF_BTR_STATUS_EOF:
456 /* Stay in this continue state */
457 break;
458 default:
459 PERR("Binary type reader failed to continue\n");
460 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
461 goto end;
462 }
463
464 /* Consume bits now since we know we're not in an error state */
465 buf_consume_bits(notit, consumed_bits);
466
467 end:
468 return status;
469 }
470
471 static
472 void put_event_dscopes(struct bt_ctf_notif_iter *notit)
473 {
474 BT_PUT(notit->dscopes.stream_event_header);
475 BT_PUT(notit->dscopes.stream_event_context);
476 BT_PUT(notit->dscopes.event_context);
477 BT_PUT(notit->dscopes.event_payload);
478 }
479
480 static
481 void put_all_dscopes(struct bt_ctf_notif_iter *notit)
482 {
483 BT_PUT(notit->dscopes.trace_packet_header);
484 BT_PUT(notit->dscopes.stream_packet_context);
485 put_event_dscopes(notit);
486 }
487
488 static
489 enum bt_ctf_notif_iter_status read_packet_header_begin_state(
490 struct bt_ctf_notif_iter *notit)
491 {
492 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
493 struct bt_ctf_field_type *packet_header_type;
494
495 /* Reset all dynamic scopes since we're reading a new packet */
496 put_all_dscopes(notit);
497 BT_PUT(notit->packet);
498 BT_PUT(notit->meta.stream_class);
499 BT_PUT(notit->meta.event_class);
500
501 /* Packet header type is common to the whole trace */
502 packet_header_type = bt_ctf_trace_get_packet_header_type(
503 notit->meta.trace);
504 if (!packet_header_type) {
505 PERR("Failed to retrieve trace's packet header type\n");
506 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
507 goto end;
508 }
509
510 status = read_dscope_begin_state(notit, packet_header_type,
511 STATE_AFTER_TRACE_PACKET_HEADER,
512 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
513 &notit->dscopes.trace_packet_header);
514
515 end:
516 BT_PUT(packet_header_type);
517
518 return status;
519 }
520
521 static
522 enum bt_ctf_notif_iter_status read_packet_header_continue_state(
523 struct bt_ctf_notif_iter *notit)
524 {
525 return read_dscope_continue_state(notit,
526 STATE_AFTER_TRACE_PACKET_HEADER);
527 }
528
529 static inline
530 bool is_struct_type(struct bt_ctf_field_type *field_type)
531 {
532 return bt_ctf_field_type_get_type_id(field_type) == BT_CTF_TYPE_ID_STRUCT;
533 }
534
535 static inline
536 bool is_variant_type(struct bt_ctf_field_type *field_type)
537 {
538 return bt_ctf_field_type_get_type_id(field_type) == BT_CTF_TYPE_ID_VARIANT;
539 }
540
541 static inline
542 enum bt_ctf_notif_iter_status set_current_stream_class(struct bt_ctf_notif_iter *notit)
543 {
544 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
545 struct bt_ctf_field_type *packet_header_type;
546 struct bt_ctf_field_type *stream_id_field_type = NULL;
547 uint64_t stream_id;
548
549 /* Is there any "stream_id" field in the packet header? */
550 packet_header_type = bt_ctf_trace_get_packet_header_type(
551 notit->meta.trace);
552 if (!packet_header_type) {
553 PERR("Failed to retrieve trace's packet header type\n");
554 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
555 goto end;
556 }
557
558 assert(is_struct_type(packet_header_type));
559
560 // TODO: optimalize!
561 stream_id_field_type =
562 bt_ctf_field_type_structure_get_field_type_by_name(
563 packet_header_type, "stream_id");
564 if (stream_id_field_type) {
565 /* Find appropriate stream class using current stream ID */
566 struct bt_ctf_field *stream_id_field = NULL;
567 int ret;
568
569 assert(notit->dscopes.trace_packet_header);
570
571 // TODO: optimalize!
572 stream_id_field = bt_ctf_field_structure_get_field(
573 notit->dscopes.trace_packet_header, "stream_id");
574 assert(stream_id_field);
575 ret = bt_ctf_field_unsigned_integer_get_value(
576 stream_id_field, &stream_id);
577 assert(!ret);
578 BT_PUT(stream_id_field);
579 } else {
580 /* Only one stream: pick the first stream class */
581 assert(bt_ctf_trace_get_stream_class_count(
582 notit->meta.trace) == 1);
583 stream_id = 0;
584 }
585
586 BT_PUT(notit->meta.stream_class);
587
588 // TODO: get by ID
589 notit->meta.stream_class = bt_ctf_trace_get_stream_class(
590 notit->meta.trace, stream_id);
591 if (!notit->meta.stream_class) {
592 PERR("Cannot find stream class with ID %" PRIu64 "\n",
593 stream_id);
594 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
595 goto end;
596 }
597
598 end:
599 BT_PUT(packet_header_type);
600 BT_PUT(stream_id_field_type);
601
602 return status;
603 }
604
605 static
606 enum bt_ctf_notif_iter_status after_packet_header_state(
607 struct bt_ctf_notif_iter *notit)
608 {
609 enum bt_ctf_notif_iter_status status;
610
611 status = set_current_stream_class(notit);
612 if (status == BT_CTF_NOTIF_ITER_STATUS_OK) {
613 notit->state = STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN;
614 }
615
616 return status;
617 }
618
619 static
620 enum bt_ctf_notif_iter_status read_packet_context_begin_state(
621 struct bt_ctf_notif_iter *notit)
622 {
623 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
624 struct bt_ctf_field_type *packet_context_type;
625
626 assert(notit->meta.stream_class);
627 packet_context_type = bt_ctf_stream_class_get_packet_context_type(
628 notit->meta.stream_class);
629 if (!packet_context_type) {
630 PERR("Failed to retrieve stream class's packet context\n");
631 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
632 goto end;
633 }
634
635 status = read_dscope_begin_state(notit, packet_context_type,
636 STATE_AFTER_STREAM_PACKET_CONTEXT,
637 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
638 &notit->dscopes.stream_packet_context);
639
640 end:
641 BT_PUT(packet_context_type);
642
643 return status;
644 }
645
646 static
647 enum bt_ctf_notif_iter_status read_packet_context_continue_state(
648 struct bt_ctf_notif_iter *notit)
649 {
650 return read_dscope_continue_state(notit,
651 STATE_AFTER_STREAM_PACKET_CONTEXT);
652 }
653
654 static inline
655 enum bt_ctf_notif_iter_status set_current_packet_content_sizes(
656 struct bt_ctf_notif_iter *notit)
657 {
658 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
659 struct bt_ctf_field *packet_size_field = NULL;
660 struct bt_ctf_field *content_size_field = NULL;
661 uint64_t content_size = -1, packet_size = -1;
662
663 assert(notit->dscopes.stream_packet_context);
664
665 // TODO: optimalize!
666 packet_size_field = bt_ctf_field_structure_get_field(
667 notit->dscopes.stream_packet_context, "packet_size");
668 content_size_field = bt_ctf_field_structure_get_field(
669 notit->dscopes.stream_packet_context, "content_size");
670 if (packet_size_field) {
671 int ret = bt_ctf_field_unsigned_integer_get_value(
672 packet_size_field, &packet_size);
673 assert(!ret);
674
675 if (packet_size == 0) {
676 PERR("Decoded packet size is 0\n");
677 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
678 goto end;
679 } else if ((packet_size % 8) != 0) {
680 PERR("Decoded packet size is not a multiple of 8\n");
681 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
682 goto end;
683 }
684 }
685 if (content_size_field) {
686 int ret = bt_ctf_field_unsigned_integer_get_value(
687 content_size_field, &content_size);
688 assert(!ret);
689 } else {
690 content_size = packet_size;
691 }
692
693 notit->cur_packet_size = packet_size;
694 notit->cur_content_size = content_size;
695
696 end:
697 BT_PUT(packet_size_field);
698 BT_PUT(content_size_field);
699
700 return status;
701 }
702
703 static
704 enum bt_ctf_notif_iter_status after_packet_context_state(
705 struct bt_ctf_notif_iter *notit)
706 {
707 enum bt_ctf_notif_iter_status status;
708
709 status = set_current_packet_content_sizes(notit);
710 if (status == BT_CTF_NOTIF_ITER_STATUS_OK) {
711 notit->state = STATE_EMIT_NOTIF_NEW_PACKET;
712 }
713
714 return status;
715 }
716
717 static
718 enum bt_ctf_notif_iter_status read_event_header_begin_state(
719 struct bt_ctf_notif_iter *notit)
720 {
721 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
722 struct bt_ctf_field_type *event_header_type = NULL;
723
724 /* Check if we have some content left */
725 if (notit->cur_content_size >= 0) {
726 if (packet_at(notit) == notit->cur_content_size) {
727 /* No more events! */
728 notit->state = STATE_EMIT_NOTIF_END_OF_PACKET;
729 goto end;
730 } else if (packet_at(notit) > notit->cur_content_size) {
731 /* That's not supposed to happen */
732 PERR("Cursor passed packet's content size:\n");
733 PERR(" Decoded content size: %zu\n",
734 notit->cur_content_size);
735 PERR(" Cursor position: %zu\n", packet_at(notit));
736 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
737 goto end;
738 }
739 }
740
741 event_header_type = bt_ctf_stream_class_get_event_header_type(
742 notit->meta.stream_class);
743 if (!event_header_type) {
744 PERR("Failed to retrieve stream class's event header type\n");
745 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
746 goto end;
747 }
748
749 put_event_dscopes(notit);
750 status = read_dscope_begin_state(notit, event_header_type,
751 STATE_AFTER_STREAM_EVENT_HEADER,
752 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE,
753 &notit->dscopes.stream_event_header);
754
755 end:
756 BT_PUT(event_header_type);
757
758 return status;
759 }
760
761 static
762 enum bt_ctf_notif_iter_status read_event_header_continue_state(
763 struct bt_ctf_notif_iter *notit)
764 {
765 return read_dscope_continue_state(notit,
766 STATE_AFTER_STREAM_EVENT_HEADER);
767 }
768
769 static inline
770 enum bt_ctf_notif_iter_status set_current_event_class(struct bt_ctf_notif_iter *notit)
771 {
772 /*
773 * The assert() calls in this function are okay because it is
774 * assumed here that all the metadata objects have been
775 * validated for CTF correctness before decoding actual streams.
776 */
777
778 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
779 struct bt_ctf_field_type *event_header_type;
780 struct bt_ctf_field_type *id_field_type = NULL;
781 struct bt_ctf_field_type *v_field_type = NULL;
782 uint64_t event_id = -1ULL;
783 int ret;
784
785 event_header_type = bt_ctf_stream_class_get_event_header_type(
786 notit->meta.stream_class);
787 if (!event_header_type) {
788 PERR("Failed to retrieve stream class's event header type\n");
789 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
790 goto end;
791 }
792
793 /* Is there any "id"/"v" field in the event header? */
794 assert(is_struct_type(event_header_type));
795 id_field_type = bt_ctf_field_type_structure_get_field_type_by_name(
796 event_header_type, "id");
797 v_field_type = bt_ctf_field_type_structure_get_field_type_by_name(
798 event_header_type, "v");
799 assert(notit->dscopes.stream_event_header);
800 if (v_field_type) {
801 /*
802 * _ _____ _____
803 * | | |_ _|_ _| __ __ _
804 * | | | | | || '_ \ / _` |
805 * | |___| | | || | | | (_| | S P E C I A L
806 * |_____|_| |_||_| |_|\__, | C A S E â„¢
807 * |___/
808 */
809 struct bt_ctf_field *v_field = NULL;
810 struct bt_ctf_field *v_struct_field = NULL;
811 struct bt_ctf_field *v_struct_id_field = NULL;
812
813 // TODO: optimalize!
814 v_field = bt_ctf_field_structure_get_field(
815 notit->dscopes.stream_event_header, "v");
816 assert(v_field);
817
818 v_struct_field =
819 bt_ctf_field_variant_get_current_field(v_field);
820 if (!v_struct_field) {
821 goto end_v_field_type;
822 }
823
824 // TODO: optimalize!
825 v_struct_id_field =
826 bt_ctf_field_structure_get_field(v_struct_field, "id");
827 if (!v_struct_id_field) {
828 goto end_v_field_type;
829 }
830
831 ret = bt_ctf_field_unsigned_integer_get_value(
832 v_struct_id_field, &event_id);
833 if (ret) {
834 event_id = -1ULL;
835 }
836
837 end_v_field_type:
838 BT_PUT(v_field);
839 BT_PUT(v_struct_field);
840 BT_PUT(v_struct_id_field);
841 }
842
843 if (id_field_type && event_id == -1ULL) {
844 /* Check "id" field */
845 struct bt_ctf_field *id_field = NULL;
846 int ret;
847
848 // TODO: optimalize!
849 id_field = bt_ctf_field_structure_get_field(
850 notit->dscopes.stream_event_header, "id");
851 assert(id_field);
852 assert(bt_ctf_field_is_integer(id_field) ||
853 bt_ctf_field_is_enumeration(id_field));
854
855 if (bt_ctf_field_is_integer(id_field)) {
856 ret = bt_ctf_field_unsigned_integer_get_value(
857 id_field, &event_id);
858 } else {
859 struct bt_ctf_field *container;
860
861 container = bt_ctf_field_enumeration_get_container(
862 id_field);
863 assert(container);
864 ret = bt_ctf_field_unsigned_integer_get_value(
865 container, &event_id);
866 BT_PUT(container);
867 }
868 assert(!ret);
869 BT_PUT(id_field);
870 }
871
872 if (event_id == -1ULL) {
873 /* Event ID not found: single event? */
874 assert(bt_ctf_stream_class_get_event_class_count(
875 notit->meta.stream_class) == 1);
876 event_id = 0;
877 }
878
879 BT_PUT(notit->meta.event_class);
880 notit->meta.event_class = bt_ctf_stream_class_get_event_class_by_id(
881 notit->meta.stream_class, event_id);
882 if (!notit->meta.event_class) {
883 PERR("Cannot find event class with ID %" PRIu64 "\n", event_id);
884 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
885 goto end;
886 }
887
888 end:
889 BT_PUT(event_header_type);
890 BT_PUT(id_field_type);
891 BT_PUT(v_field_type);
892
893 return status;
894 }
895
896 static
897 enum bt_ctf_notif_iter_status after_event_header_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 PERR("Failed to set current packet and content sizes\n");
905 goto end;
906 }
907
908 status = set_current_event_class(notit);
909 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
910 PERR("Failed to set current event class\n");
911 goto end;
912 }
913
914 notit->state = STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN;
915
916 end:
917 return status;
918 }
919
920 static
921 enum bt_ctf_notif_iter_status read_stream_event_context_begin_state(
922 struct bt_ctf_notif_iter *notit)
923 {
924 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
925 struct bt_ctf_field_type *stream_event_context_type;
926
927 stream_event_context_type = bt_ctf_stream_class_get_event_context_type(
928 notit->meta.stream_class);
929 if (!stream_event_context_type) {
930 PERR("Failed to retrieve stream class's event context type\n");
931 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
932 goto end;
933 }
934
935 status = read_dscope_begin_state(notit, stream_event_context_type,
936 STATE_DSCOPE_EVENT_CONTEXT_BEGIN,
937 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE,
938 &notit->dscopes.stream_event_context);
939
940 end:
941 BT_PUT(stream_event_context_type);
942
943 return status;
944 }
945
946 static
947 enum bt_ctf_notif_iter_status read_stream_event_context_continue_state(
948 struct bt_ctf_notif_iter *notit)
949 {
950 return read_dscope_continue_state(notit,
951 STATE_DSCOPE_EVENT_CONTEXT_BEGIN);
952 }
953
954 static
955 enum bt_ctf_notif_iter_status read_event_context_begin_state(
956 struct bt_ctf_notif_iter *notit)
957 {
958 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
959 struct bt_ctf_field_type *event_context_type;
960
961 event_context_type = bt_ctf_event_class_get_context_type(
962 notit->meta.event_class);
963 if (!event_context_type) {
964 PERR("Failed to retrieve event class's context type\n");
965 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
966 goto end;
967 }
968
969 status = read_dscope_begin_state(notit, event_context_type,
970 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
971 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE,
972 &notit->dscopes.event_context);
973
974 end:
975 BT_PUT(event_context_type);
976
977 return status;
978 }
979
980 static
981 enum bt_ctf_notif_iter_status read_event_context_continue_state(
982 struct bt_ctf_notif_iter *notit)
983 {
984 return read_dscope_continue_state(notit,
985 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN);
986 }
987
988 static
989 enum bt_ctf_notif_iter_status read_event_payload_begin_state(
990 struct bt_ctf_notif_iter *notit)
991 {
992 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
993 struct bt_ctf_field_type *event_payload_type;
994
995 event_payload_type = bt_ctf_event_class_get_payload_type(
996 notit->meta.event_class);
997 if (!event_payload_type) {
998 PERR("Failed to retrieve event class's payload type\n");
999 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
1000 goto end;
1001 }
1002
1003 status = read_dscope_begin_state(notit, event_payload_type,
1004 STATE_EMIT_NOTIF_EVENT,
1005 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE,
1006 &notit->dscopes.event_payload);
1007
1008 end:
1009 BT_PUT(event_payload_type);
1010
1011 return status;
1012 }
1013
1014 static
1015 enum bt_ctf_notif_iter_status read_event_payload_continue_state(
1016 struct bt_ctf_notif_iter *notit)
1017 {
1018 return read_dscope_continue_state(notit, STATE_EMIT_NOTIF_EVENT);
1019 }
1020
1021 static
1022 enum bt_ctf_notif_iter_status skip_packet_padding_state(
1023 struct bt_ctf_notif_iter *notit)
1024 {
1025 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
1026 size_t bits_to_skip;
1027
1028 assert(notit->cur_packet_size > 0);
1029 bits_to_skip = notit->cur_packet_size - packet_at(notit);
1030 if (bits_to_skip == 0) {
1031 notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
1032 goto end;
1033 } else {
1034 size_t bits_to_consume;
1035 status = buf_ensure_available_bits(notit);
1036 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
1037 goto end;
1038 }
1039
1040 bits_to_consume = MIN(buf_available_bits(notit), bits_to_skip);
1041 buf_consume_bits(notit, bits_to_consume);
1042 bits_to_skip = notit->cur_packet_size - packet_at(notit);
1043 if (bits_to_skip == 0) {
1044 notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
1045 goto end;
1046 }
1047 }
1048
1049 end:
1050 return status;
1051 }
1052
1053 static inline
1054 enum bt_ctf_notif_iter_status handle_state(struct bt_ctf_notif_iter *notit)
1055 {
1056 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
1057
1058 PDBG("Handling state %d\n", notit->state);
1059
1060 // TODO: optimalize!
1061 switch (notit->state) {
1062 case STATE_INIT:
1063 notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
1064 break;
1065 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN:
1066 status = read_packet_header_begin_state(notit);
1067 break;
1068 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE:
1069 status = read_packet_header_continue_state(notit);
1070 break;
1071 case STATE_AFTER_TRACE_PACKET_HEADER:
1072 status = after_packet_header_state(notit);
1073 break;
1074 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN:
1075 status = read_packet_context_begin_state(notit);
1076 break;
1077 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE:
1078 status = read_packet_context_continue_state(notit);
1079 break;
1080 case STATE_AFTER_STREAM_PACKET_CONTEXT:
1081 status = after_packet_context_state(notit);
1082 break;
1083 case STATE_EMIT_NOTIF_NEW_PACKET:
1084 notit->state = STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN;
1085 break;
1086 case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN:
1087 status = read_event_header_begin_state(notit);
1088 break;
1089 case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE:
1090 status = read_event_header_continue_state(notit);
1091 break;
1092 case STATE_AFTER_STREAM_EVENT_HEADER:
1093 status = after_event_header_state(notit);
1094 break;
1095 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN:
1096 status = read_stream_event_context_begin_state(notit);
1097 break;
1098 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE:
1099 status = read_stream_event_context_continue_state(notit);
1100 break;
1101 case STATE_DSCOPE_EVENT_CONTEXT_BEGIN:
1102 status = read_event_context_begin_state(notit);
1103 break;
1104 case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE:
1105 status = read_event_context_continue_state(notit);
1106 break;
1107 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN:
1108 status = read_event_payload_begin_state(notit);
1109 break;
1110 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE:
1111 status = read_event_payload_continue_state(notit);
1112 break;
1113 case STATE_EMIT_NOTIF_EVENT:
1114 notit->state = STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN;
1115 break;
1116 case STATE_SKIP_PACKET_PADDING:
1117 status = skip_packet_padding_state(notit);
1118 break;
1119 case STATE_EMIT_NOTIF_END_OF_PACKET:
1120 notit->state = STATE_SKIP_PACKET_PADDING;
1121 break;
1122 }
1123
1124 return status;
1125 }
1126
1127 void bt_ctf_notif_iter_reset(struct bt_ctf_notif_iter *notit)
1128 {
1129 assert(notit);
1130 stack_clear(notit->stack);
1131 BT_PUT(notit->meta.stream_class);
1132 BT_PUT(notit->meta.event_class);
1133 BT_PUT(notit->packet);
1134 put_all_dscopes(notit);
1135 notit->buf.addr = NULL;
1136 notit->buf.sz = 0;
1137 notit->buf.at = 0;
1138 notit->buf.packet_offset = 0;
1139 notit->state = STATE_INIT;
1140 notit->cur_content_size = -1;
1141 notit->cur_packet_size = -1;
1142 }
1143
1144 static
1145 struct bt_ctf_field *get_next_field(struct bt_ctf_notif_iter *notit)
1146 {
1147 struct bt_ctf_field *next_field = NULL;
1148 struct bt_ctf_field *base_field;
1149 struct bt_ctf_field_type *base_type;
1150 size_t index;
1151
1152 assert(!stack_empty(notit->stack));
1153 index = stack_top(notit->stack)->index;
1154 base_field = stack_top(notit->stack)->base;
1155 base_type = bt_ctf_field_get_type(base_field);
1156 if (!base_type) {
1157 PERR("Failed to get base field's type\n");
1158 goto end;
1159 }
1160
1161 switch (bt_ctf_field_type_get_type_id(base_type)) {
1162 case BT_CTF_TYPE_ID_STRUCT:
1163 next_field = bt_ctf_field_structure_get_field_by_index(
1164 base_field, index);
1165 break;
1166 case BT_CTF_TYPE_ID_ARRAY:
1167 next_field = bt_ctf_field_array_get_field(base_field, index);
1168 break;
1169 case BT_CTF_TYPE_ID_SEQUENCE:
1170 next_field = bt_ctf_field_sequence_get_field(base_field, index);
1171 break;
1172 case BT_CTF_TYPE_ID_VARIANT:
1173 next_field = bt_ctf_field_variant_get_current_field(base_field);
1174 break;
1175 default:
1176 assert(false);
1177 break;
1178 }
1179
1180 end:
1181 BT_PUT(base_type);
1182
1183 return next_field;
1184 }
1185
1186 static
1187 enum bt_ctf_btr_status btr_signed_int_cb(int64_t value,
1188 struct bt_ctf_field_type *type, void *data)
1189 {
1190 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1191 struct bt_ctf_field *field = NULL;
1192 struct bt_ctf_field *int_field = NULL;
1193 struct bt_ctf_notif_iter *notit = data;
1194 int ret;
1195
1196 /* create next field */
1197 field = get_next_field(notit);
1198 if (!field) {
1199 PERR("Failed to get next field (signed int)\n");
1200 status = BT_CTF_BTR_STATUS_ERROR;
1201 goto end;
1202 }
1203
1204 switch(bt_ctf_field_type_get_type_id(type)) {
1205 case BT_CTF_TYPE_ID_INTEGER:
1206 /* Integer field is created field */
1207 BT_MOVE(int_field, field);
1208 break;
1209 case BT_CTF_TYPE_ID_ENUM:
1210 int_field = bt_ctf_field_enumeration_get_container(field);
1211 break;
1212 default:
1213 break;
1214 }
1215
1216 if (!int_field) {
1217 PERR("Failed to get integer field\n");
1218 status = BT_CTF_BTR_STATUS_ERROR;
1219 goto end;
1220 }
1221
1222 ret = bt_ctf_field_signed_integer_set_value(int_field, value);
1223 assert(!ret);
1224 stack_top(notit->stack)->index++;
1225
1226 end:
1227 BT_PUT(field);
1228 BT_PUT(int_field);
1229
1230 return status;
1231 }
1232
1233 static
1234 enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value,
1235 struct bt_ctf_field_type *type, void *data)
1236 {
1237 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1238 struct bt_ctf_field *field = NULL;
1239 struct bt_ctf_field *int_field = NULL;
1240 struct bt_ctf_notif_iter *notit = data;
1241 int ret;
1242
1243 /* Create next field */
1244 field = get_next_field(notit);
1245 if (!field) {
1246 PERR("Failed to get next field (unsigned int)\n");
1247 status = BT_CTF_BTR_STATUS_ERROR;
1248 goto end;
1249 }
1250
1251 switch(bt_ctf_field_type_get_type_id(type)) {
1252 case BT_CTF_TYPE_ID_INTEGER:
1253 /* Integer field is created field */
1254 BT_MOVE(int_field, field);
1255 break;
1256 case BT_CTF_TYPE_ID_ENUM:
1257 int_field = bt_ctf_field_enumeration_get_container(field);
1258 break;
1259 default:
1260 break;
1261 }
1262
1263 if (!int_field) {
1264 PERR("Failed to get integer field\n");
1265 status = BT_CTF_BTR_STATUS_ERROR;
1266 goto end;
1267 }
1268
1269 ret = bt_ctf_field_unsigned_integer_set_value(int_field, value);
1270 assert(!ret);
1271 stack_top(notit->stack)->index++;
1272
1273 end:
1274 BT_PUT(field);
1275 BT_PUT(int_field);
1276
1277 return status;
1278 }
1279
1280 static
1281 enum bt_ctf_btr_status btr_floating_point_cb(double value,
1282 struct bt_ctf_field_type *type, void *data)
1283 {
1284 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1285 struct bt_ctf_field *field = NULL;
1286 struct bt_ctf_notif_iter *notit = data;
1287 int ret;
1288
1289 /* Create next field */
1290 field = get_next_field(notit);
1291 if (!field) {
1292 PERR("Failed to get next field (floating point number)\n");
1293 status = BT_CTF_BTR_STATUS_ERROR;
1294 goto end;
1295 }
1296
1297 ret = bt_ctf_field_floating_point_set_value(field, value);
1298 assert(!ret);
1299 stack_top(notit->stack)->index++;
1300
1301 end:
1302 BT_PUT(field);
1303
1304 return status;
1305 }
1306
1307 static
1308 enum bt_ctf_btr_status btr_string_begin_cb(
1309 struct bt_ctf_field_type *type, void *data)
1310 {
1311 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1312 struct bt_ctf_field *field = NULL;
1313 struct bt_ctf_notif_iter *notit = data;
1314 int ret;
1315
1316 /* Create next field */
1317 field = get_next_field(notit);
1318 if (!field) {
1319 PERR("Failed to get next field (string)\n");
1320 status = BT_CTF_BTR_STATUS_ERROR;
1321 goto end;
1322 }
1323
1324 /*
1325 * Push on stack. Not a compound type per se, but we know that only
1326 * btr_string_cb() may be called between this call and a subsequent
1327 * call to btr_string_end_cb().
1328 */
1329 ret = stack_push(notit->stack, field);
1330 if (ret) {
1331 PERR("Failed to push string field onto the stack\n");
1332 status = BT_CTF_BTR_STATUS_ERROR;
1333 goto end;
1334 }
1335
1336 end:
1337 BT_PUT(field);
1338
1339 return status;
1340 }
1341
1342 static
1343 enum bt_ctf_btr_status btr_string_cb(const char *value,
1344 size_t len, struct bt_ctf_field_type *type, void *data)
1345 {
1346 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1347 struct bt_ctf_field *field = NULL;
1348 struct bt_ctf_notif_iter *notit = data;
1349 int ret;
1350
1351 /* Get string field */
1352 field = stack_top(notit->stack)->base;
1353 assert(field);
1354
1355 /* Append current string */
1356 ret = bt_ctf_field_string_append_len(field, value, len);
1357 if (ret) {
1358 PERR("Failed to append a string to a string field\n");
1359 status = BT_CTF_BTR_STATUS_ERROR;
1360 goto end;
1361 }
1362
1363 end:
1364 return status;
1365 }
1366
1367 static
1368 enum bt_ctf_btr_status btr_string_end_cb(
1369 struct bt_ctf_field_type *type, void *data)
1370 {
1371 struct bt_ctf_notif_iter *notit = data;
1372
1373 /* Pop string field */
1374 stack_pop(notit->stack);
1375
1376 /* Go to next field */
1377 stack_top(notit->stack)->index++;
1378
1379 return BT_CTF_BTR_STATUS_OK;
1380 }
1381
1382 enum bt_ctf_btr_status btr_compound_begin_cb(
1383 struct bt_ctf_field_type *type, void *data)
1384 {
1385 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1386 struct bt_ctf_notif_iter *notit = data;
1387 struct bt_ctf_field *field;
1388 int ret;
1389
1390 /* Create field */
1391 if (stack_empty(notit->stack)) {
1392 /* Root: create dynamic scope field */
1393 *notit->cur_dscope_field = bt_ctf_field_create(type);
1394 field = *notit->cur_dscope_field;
1395
1396 /*
1397 * Field will be put at the end of this function
1398 * (stack_push() will take one reference, but this
1399 * reference is lost upon the equivalent stack_pop()
1400 * later), so also get it for our context to own it.
1401 */
1402 bt_get(*notit->cur_dscope_field);
1403 } else {
1404 field = get_next_field(notit);
1405 }
1406
1407 if (!field) {
1408 PERR("Failed to get next field or create dynamic scope field\n");
1409 status = BT_CTF_BTR_STATUS_ERROR;
1410 goto end;
1411 }
1412
1413 /* Push field */
1414 ret = stack_push(notit->stack, field);
1415 if (ret) {
1416 PERR("Failed to push compound field onto the stack\n");
1417 status = BT_CTF_BTR_STATUS_ERROR;
1418 goto end;
1419 }
1420
1421 end:
1422 BT_PUT(field);
1423
1424 return status;
1425 }
1426
1427 enum bt_ctf_btr_status btr_compound_end_cb(
1428 struct bt_ctf_field_type *type, void *data)
1429 {
1430 struct bt_ctf_notif_iter *notit = data;
1431
1432 assert(!stack_empty(notit->stack));
1433
1434 /* Pop stack */
1435 stack_pop(notit->stack);
1436
1437 /* If the stack is not empty, increment the base's index */
1438 if (!stack_empty(notit->stack)) {
1439 stack_top(notit->stack)->index++;
1440 }
1441
1442 return BT_CTF_BTR_STATUS_OK;
1443 }
1444
1445 static
1446 struct bt_ctf_field *resolve_field(struct bt_ctf_notif_iter *notit,
1447 struct bt_ctf_field_path *path)
1448 {
1449 struct bt_ctf_field *field = NULL;
1450 unsigned int i;
1451
1452 switch (bt_ctf_field_path_get_root_scope(path)) {
1453 case BT_CTF_SCOPE_TRACE_PACKET_HEADER:
1454 field = notit->dscopes.trace_packet_header;
1455 break;
1456 case BT_CTF_SCOPE_STREAM_PACKET_CONTEXT:
1457 field = notit->dscopes.stream_packet_context;
1458 break;
1459 case BT_CTF_SCOPE_STREAM_EVENT_HEADER:
1460 field = notit->dscopes.stream_event_header;
1461 break;
1462 case BT_CTF_SCOPE_STREAM_EVENT_CONTEXT:
1463 field = notit->dscopes.stream_event_context;
1464 break;
1465 case BT_CTF_SCOPE_EVENT_CONTEXT:
1466 field = notit->dscopes.event_context;
1467 break;
1468 case BT_CTF_SCOPE_EVENT_FIELDS:
1469 field = notit->dscopes.event_payload;
1470 break;
1471 default:
1472 break;
1473 }
1474
1475 if (!field) {
1476 goto end;
1477 }
1478
1479 bt_get(field);
1480
1481 for (i = 0; i < bt_ctf_field_path_get_index_count(path); ++i) {
1482 struct bt_ctf_field *next_field = NULL;
1483 struct bt_ctf_field_type *field_type;
1484 int index = bt_ctf_field_path_get_index(path, i);
1485
1486 field_type = bt_ctf_field_get_type(field);
1487 if (!field_type) {
1488 BT_PUT(field);
1489 goto end;
1490 }
1491
1492 if (is_struct_type(field_type)) {
1493 next_field = bt_ctf_field_structure_get_field_by_index(
1494 field, index);
1495 } else if (is_variant_type(field_type)) {
1496 next_field =
1497 bt_ctf_field_variant_get_current_field(field);
1498 }
1499
1500 BT_PUT(field);
1501 BT_PUT(field_type);
1502
1503 if (!next_field) {
1504 goto end;
1505 }
1506
1507 /* Move next field -> field */
1508 BT_MOVE(field, next_field);
1509 }
1510
1511 end:
1512 return field;
1513 }
1514
1515 static
1516 int64_t btr_get_sequence_length_cb(struct bt_ctf_field_type *type, void *data)
1517 {
1518 int64_t ret = -1;
1519 int iret;
1520 struct bt_ctf_field_path *field_path;
1521 struct bt_ctf_notif_iter *notit = data;
1522 struct bt_ctf_field *field = NULL;
1523 uint64_t length;
1524
1525 field_path = bt_ctf_field_type_sequence_get_length_field_path(type);
1526 if (!field_path) {
1527 goto end;
1528 }
1529
1530 field = resolve_field(notit, field_path);
1531 if (!field) {
1532 goto end;
1533 }
1534
1535 iret = bt_ctf_field_unsigned_integer_get_value(field, &length);
1536 if (iret) {
1537 goto end;
1538 }
1539
1540 ret = (int64_t) length;
1541
1542 end:
1543 BT_PUT(field);
1544 BT_PUT(field_path);
1545
1546 return ret;
1547 }
1548
1549 static
1550 struct bt_ctf_field_type *btr_get_variant_type_cb(
1551 struct bt_ctf_field_type *type, void *data)
1552 {
1553 struct bt_ctf_field_path *path;
1554 struct bt_ctf_notif_iter *notit = data;
1555 struct bt_ctf_field *tag_field = NULL;
1556 struct bt_ctf_field *selected_field = NULL;
1557 struct bt_ctf_field_type *selected_field_type = NULL;
1558
1559 path = bt_ctf_field_type_variant_get_tag_field_path(type);
1560 if (!path) {
1561 goto end;
1562 }
1563
1564 tag_field = resolve_field(notit, path);
1565 if (!tag_field) {
1566 goto end;
1567 }
1568
1569 /*
1570 * We found the enumeration tag field instance which should be
1571 * able to select a current field for this variant. This
1572 * callback function we're in is called _after_
1573 * compound_begin(), so the current stack top's base field is
1574 * the variant field in question. We get the selected field here
1575 * thanks to this tag field (thus creating the selected field),
1576 * which will also provide us with its type. Then, this field
1577 * will remain the current selected one until the next callback
1578 * function call which is used to fill the current selected
1579 * field.
1580 */
1581 selected_field = bt_ctf_field_variant_get_field(
1582 stack_top(notit->stack)->base, tag_field);
1583 if (!selected_field) {
1584 goto end;
1585 }
1586
1587 selected_field_type = bt_ctf_field_get_type(selected_field);
1588
1589 end:
1590 BT_PUT(tag_field);
1591 BT_PUT(selected_field);
1592
1593 return selected_field_type;
1594 }
1595
1596 static struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit)
1597 {
1598 struct bt_ctf_event *event;
1599 int ret;
1600
1601 /* Create event object */
1602 event = bt_ctf_event_create(notit->meta.event_class);
1603 if (!event) {
1604 goto error;
1605 }
1606
1607 /* Set header, stream event context, context, and payload fields */
1608 ret = bt_ctf_event_set_header(event,
1609 notit->dscopes.stream_event_header);
1610 if (ret) {
1611 goto error;
1612 }
1613
1614 ret = bt_ctf_event_set_stream_event_context(event,
1615 notit->dscopes.stream_event_context);
1616 if (ret) {
1617 goto error;
1618 }
1619
1620 ret = bt_ctf_event_set_event_context(event,
1621 notit->dscopes.event_context);
1622 if (ret) {
1623 goto error;
1624 }
1625
1626 ret = bt_ctf_event_set_payload_field(event,
1627 notit->dscopes.event_payload);
1628 if (ret) {
1629 goto error;
1630 }
1631
1632 /* Associate with current packet */
1633 assert(notit->packet);
1634 ret = bt_ctf_event_set_packet(event, notit->packet);
1635 if (ret) {
1636 goto error;
1637 }
1638
1639 goto end;
1640
1641 error:
1642 BT_PUT(event);
1643
1644 end:
1645 return event;
1646 }
1647
1648 static void create_packet(struct bt_ctf_notif_iter *notit)
1649 {
1650 int ret;
1651 struct bt_ctf_stream *stream = NULL;
1652 struct bt_ctf_packet *packet = NULL;
1653
1654 /* Ask the user for the stream */
1655 stream = notit->medium.medops.get_stream(notit->meta.stream_class,
1656 notit->medium.data);
1657 if (!stream) {
1658 goto error;
1659 }
1660
1661 /* Create packet */
1662 packet = bt_ctf_packet_create(stream);
1663 if (!packet) {
1664 goto error;
1665 }
1666
1667 /* Set packet's context and header fields */
1668 if (notit->dscopes.trace_packet_header) {
1669 ret = bt_ctf_packet_set_header(packet,
1670 notit->dscopes.trace_packet_header);
1671 if (ret) {
1672 goto error;
1673 }
1674 }
1675
1676 if (notit->dscopes.stream_packet_context) {
1677 ret = bt_ctf_packet_set_context(packet,
1678 notit->dscopes.stream_packet_context);
1679 if (ret) {
1680 goto error;
1681 }
1682 }
1683
1684 goto end;
1685
1686 error:
1687 BT_PUT(packet);
1688
1689 end:
1690 BT_MOVE(notit->packet, packet);
1691 }
1692
1693 static void notify_new_packet(struct bt_ctf_notif_iter *notit,
1694 struct bt_ctf_notif_iter_notif **notification)
1695 {
1696 struct bt_ctf_notif_iter_notif_new_packet *rnotif;
1697
1698 rnotif = g_new0(struct bt_ctf_notif_iter_notif_new_packet, 1);
1699 if (!rnotif) {
1700 goto error;
1701 }
1702
1703 rnotif->base.type = BT_CTF_NOTIF_ITER_NOTIF_NEW_PACKET;
1704
1705 /* Create packet */
1706 create_packet(notit);
1707 if (!notit->packet) {
1708 goto error;
1709 }
1710
1711 rnotif->packet = bt_get(notit->packet);
1712 *notification = (struct bt_ctf_notif_iter_notif *) rnotif;
1713 return;
1714
1715 error:
1716 bt_ctf_notif_iter_notif_destroy(rnotif);
1717 }
1718
1719 static void notify_end_of_packet(struct bt_ctf_notif_iter *notit,
1720 struct bt_ctf_notif_iter_notif **notification)
1721 {
1722 struct bt_ctf_notif_iter_notif_end_of_packet *rnotif;
1723
1724 rnotif = g_new0(struct bt_ctf_notif_iter_notif_end_of_packet, 1);
1725 if (!rnotif) {
1726 goto error;
1727 }
1728
1729 rnotif->base.type = BT_CTF_NOTIF_ITER_NOTIF_END_OF_PACKET;
1730
1731 /* Create packet */
1732 create_packet(notit);
1733 if (!notit->packet) {
1734 goto error;
1735 }
1736
1737 rnotif->packet = bt_get(notit->packet);
1738 *notification = (struct bt_ctf_notif_iter_notif *) rnotif;
1739 return;
1740
1741 error:
1742 bt_ctf_notif_iter_notif_destroy(rnotif);
1743 }
1744
1745 static void notify_event(struct bt_ctf_notif_iter *notit,
1746 struct bt_ctf_notif_iter_notif **notification)
1747 {
1748 struct bt_ctf_notif_iter_notif_event *rnotif;
1749 struct bt_ctf_event *event = NULL;
1750
1751 rnotif = g_new0(struct bt_ctf_notif_iter_notif_event, 1);
1752 if (!rnotif) {
1753 goto error;
1754 }
1755
1756 rnotif->base.type = BT_CTF_NOTIF_ITER_NOTIF_EVENT;
1757
1758 /* Create event */
1759 event = create_event(notit);
1760 if (!event) {
1761 goto error;
1762 }
1763
1764 BT_MOVE(rnotif->event, event);
1765 *notification = (struct bt_ctf_notif_iter_notif *) rnotif;
1766 return;
1767
1768 error:
1769 BT_PUT(event);
1770 bt_ctf_notif_iter_notif_destroy(rnotif);
1771 }
1772
1773 void bt_ctf_notif_iter_notif_destroy(void *vnotif)
1774 {
1775 struct bt_ctf_notif_iter_notif *notif = vnotif;
1776
1777 switch (notif->type) {
1778 case BT_CTF_NOTIF_ITER_NOTIF_NEW_PACKET:
1779 {
1780 struct bt_ctf_notif_iter_notif_new_packet *rnotif =
1781 (struct bt_ctf_notif_iter_notif_new_packet *) notif;
1782
1783 BT_PUT(rnotif->packet);
1784 break;
1785 }
1786 case BT_CTF_NOTIF_ITER_NOTIF_END_OF_PACKET:
1787 {
1788 struct bt_ctf_notif_iter_notif_end_of_packet *rnotif =
1789 (struct bt_ctf_notif_iter_notif_end_of_packet *) notif;
1790
1791 BT_PUT(rnotif->packet);
1792 break;
1793 }
1794 case BT_CTF_NOTIF_ITER_NOTIF_EVENT:
1795 {
1796 struct bt_ctf_notif_iter_notif_event *rnotif =
1797 (struct bt_ctf_notif_iter_notif_event *) notif;
1798
1799 BT_PUT(rnotif->event);
1800 break;
1801 }
1802 default:
1803 assert(false);
1804 }
1805
1806 g_free(notif);
1807 }
1808
1809 struct bt_ctf_notif_iter *bt_ctf_notif_iter_create(struct bt_ctf_trace *trace,
1810 size_t max_request_sz,
1811 struct bt_ctf_notif_iter_medium_ops medops,
1812 void *data, FILE *err_stream)
1813 {
1814 struct bt_ctf_notif_iter *notit = NULL;
1815 struct bt_ctf_btr_cbs cbs = {
1816 .types = {
1817 .signed_int = btr_signed_int_cb,
1818 .unsigned_int = btr_unsigned_int_cb,
1819 .floating_point = btr_floating_point_cb,
1820 .string_begin = btr_string_begin_cb,
1821 .string = btr_string_cb,
1822 .string_end = btr_string_end_cb,
1823 .compound_begin = btr_compound_begin_cb,
1824 .compound_end = btr_compound_end_cb,
1825 },
1826 .query = {
1827 .get_sequence_length = btr_get_sequence_length_cb,
1828 .get_variant_type = btr_get_variant_type_cb,
1829 },
1830 };
1831
1832 assert(trace);
1833 assert(medops.request_bytes);
1834 notit = g_new0(struct bt_ctf_notif_iter, 1);
1835 if (!notit) {
1836 PERR("Failed to allocate memory for CTF notification iterator\n");
1837 goto end;
1838 }
1839
1840 notit->meta.trace = trace;
1841 bt_get(notit->meta.trace);
1842 notit->medium.medops = medops;
1843 notit->medium.max_request_sz = max_request_sz;
1844 notit->medium.data = data;
1845 notit->err_stream = err_stream;
1846 notit->stack = stack_new(notit);
1847 if (!notit->stack) {
1848 PERR("Failed to create stack\n");
1849 bt_ctf_notif_iter_destroy(notit);
1850 notit = NULL;
1851 goto end;
1852 }
1853
1854 notit->btr = bt_ctf_btr_create(cbs, notit, err_stream);
1855 if (!notit->btr) {
1856 PERR("Failed to create binary type reader\n");
1857 bt_ctf_notif_iter_destroy(notit);
1858 notit = NULL;
1859 goto end;
1860 }
1861
1862 bt_ctf_notif_iter_reset(notit);
1863
1864 end:
1865 return notit;
1866 }
1867
1868 void bt_ctf_notif_iter_destroy(struct bt_ctf_notif_iter *notit)
1869 {
1870 BT_PUT(notit->meta.trace);
1871 BT_PUT(notit->meta.stream_class);
1872 BT_PUT(notit->meta.event_class);
1873 BT_PUT(notit->packet);
1874 put_all_dscopes(notit);
1875
1876 if (notit->stack) {
1877 stack_destroy(notit->stack);
1878 }
1879
1880 if (notit->btr) {
1881 bt_ctf_btr_destroy(notit->btr);
1882 }
1883
1884 g_free(notit);
1885 }
1886
1887 enum bt_ctf_notif_iter_status bt_ctf_notif_iter_get_next_notification(
1888 struct bt_ctf_notif_iter *notit,
1889 struct bt_ctf_notif_iter_notif **notification)
1890 {
1891 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
1892
1893 assert(notit);
1894 assert(notification);
1895
1896 while (true) {
1897 status = handle_state(notit);
1898 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
1899 if (status == BT_CTF_NOTIF_ITER_STATUS_EOF) {
1900 PDBG("Medium operation reported end of file\n");
1901 } else {
1902 PERR("Failed to handle state:\n");
1903 PERR(" State: %d\n", notit->state);
1904 }
1905 goto end;
1906 }
1907
1908 switch (notit->state) {
1909 case STATE_EMIT_NOTIF_NEW_PACKET:
1910 PDBG("Emitting new packet notification\n");
1911 notify_new_packet(notit, notification);
1912 if (!*notification) {
1913 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
1914 }
1915 goto end;
1916 case STATE_EMIT_NOTIF_EVENT:
1917 PDBG("Emitting event notification\n");
1918 notify_event(notit, notification);
1919 if (!*notification) {
1920 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
1921 }
1922 goto end;
1923 case STATE_EMIT_NOTIF_END_OF_PACKET:
1924 PDBG("Emitting end of packet notification\n");
1925 notify_end_of_packet(notit, notification);
1926 if (!*notification) {
1927 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
1928 }
1929 goto end;
1930 default:
1931 /* Non-emitting state: continue */
1932 break;
1933 }
1934 }
1935
1936 end:
1937 return status;
1938 }
This page took 0.068682 seconds and 5 git commands to generate.