496f95a4222ebdc2e977d0fab866733e4ae3e0b4
[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-class.h>
40 #include <babeltrace/ctf-ir/event-class.h>
41 #include <babeltrace/graph/notification-packet.h>
42 #include <babeltrace/graph/notification-event.h>
43 #include <babeltrace/graph/notification-stream.h>
44 #include <babeltrace/graph/clock-class-priority-map.h>
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"
50 #include "../print.h"
51
52 #include "notif-iter.h"
53 #include "../btr/btr.h"
54
55 #define BYTES_TO_BITS(x) ((x) * 8)
56
57 struct bt_ctf_notif_iter;
58
59 /* A visit stack entry */
60 struct 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 */
79 struct stack {
80 /* Entries (struct stack_entry *) (top is last element) */
81 GPtrArray *entries;
82 };
83
84 /* State */
85 enum 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
108 struct 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
117 struct 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
135 struct 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
141 /* CTF notification iterator */
142 struct 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
168 /*
169 * Current timestamp_end field (to consider before switching packets).
170 */
171 struct bt_ctf_field *cur_timestamp_end;
172
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
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
198 /* Current state */
199 enum state state;
200
201 /* Current medium buffer data */
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
219 /* Current medium data */
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) */
227 int64_t cur_packet_size;
228
229 /* Current content size (bits) (-1 if unknown) */
230 int64_t cur_content_size;
231
232 /* bt_ctf_clock_class to uint64_t. */
233 GHashTable *clock_states;
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;
249 };
250
251 static
252 int bt_ctf_notif_iter_switch_packet(struct bt_ctf_notif_iter *notit);
253
254 static
255 enum bt_ctf_btr_status btr_timestamp_end_cb(void *value,
256 struct bt_ctf_field_type *type, void *data);
257
258 static
259 void 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
267 static
268 struct 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
282 return stack;
283 error:
284 g_free(stack);
285 return NULL;
286 }
287
288 static
289 void stack_destroy(struct stack *stack)
290 {
291 assert(stack);
292 g_ptr_array_free(stack->entries, TRUE);
293 g_free(stack);
294 }
295
296 static
297 int stack_push(struct stack *stack, struct bt_ctf_field *base)
298 {
299 int ret = 0;
300 struct stack_entry *entry;
301
302 assert(stack);
303 assert(base);
304 entry = g_new0(struct stack_entry, 1);
305 if (!entry) {
306 ret = -1;
307 goto end;
308 }
309
310 entry->base = bt_get(base);
311 g_ptr_array_add(stack->entries, entry);
312
313 end:
314 return ret;
315 }
316
317 static inline
318 unsigned int stack_size(struct stack *stack)
319 {
320 assert(stack);
321
322 return stack->entries->len;
323 }
324
325 static
326 void 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
333 static inline
334 struct 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
342 static inline
343 bool stack_empty(struct stack *stack)
344 {
345 return stack_size(stack) == 0;
346 }
347
348 static
349 void 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
360 static inline
361 enum bt_ctf_notif_iter_status notif_iter_status_from_m_status(
362 enum bt_ctf_notif_iter_medium_status m_status)
363 {
364 return (int) m_status;
365 }
366
367 static inline
368 size_t buf_size_bits(struct bt_ctf_notif_iter *notit)
369 {
370 return BYTES_TO_BITS(notit->buf.sz);
371 }
372
373 static inline
374 size_t buf_available_bits(struct bt_ctf_notif_iter *notit)
375 {
376 return buf_size_bits(notit) - notit->buf.at;
377 }
378
379 static inline
380 size_t packet_at(struct bt_ctf_notif_iter *notit)
381 {
382 return notit->buf.packet_offset + notit->buf.at;
383 }
384
385 static inline
386 void buf_consume_bits(struct bt_ctf_notif_iter *notit, size_t incr)
387 {
388 notit->buf.at += incr;
389 }
390
391 static
392 enum bt_ctf_notif_iter_status request_medium_bytes(
393 struct bt_ctf_notif_iter *notit)
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
421 static inline
422 enum 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
438 static
439 enum 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
477 end:
478 return status;
479 }
480
481 static
482 enum 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,
495 notit->buf.sz, &btr_status);
496
497 switch (btr_status) {
498 case BT_CTF_BTR_STATUS_OK:
499 /* Type was read completely. */
500 notit->state = done_state;
501 break;
502 case BT_CTF_BTR_STATUS_EOF:
503 /* Stay in this continue state. */
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
511 /* Consume bits now since we know we're not in an error state. */
512 buf_consume_bits(notit, consumed_bits);
513 end:
514 return status;
515 }
516
517 static
518 void 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
526 static
527 void 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
534 static
535 enum bt_ctf_notif_iter_status read_packet_header_begin_state(
536 struct bt_ctf_notif_iter *notit)
537 {
538 struct bt_ctf_field_type *packet_header_type = NULL;
539 enum bt_ctf_notif_iter_status ret = BT_CTF_NOTIF_ITER_STATUS_OK;
540
541 if (bt_ctf_notif_iter_switch_packet(notit)) {
542 ret = BT_CTF_NOTIF_ITER_STATUS_ERROR;
543 goto end;
544 }
545
546 /* Packet header type is common to the whole trace. */
547 packet_header_type = bt_ctf_trace_get_packet_header_type(
548 notit->meta.trace);
549 if (!packet_header_type) {
550 notit->state = STATE_AFTER_TRACE_PACKET_HEADER;
551 goto end;
552 }
553
554 ret = read_dscope_begin_state(notit, packet_header_type,
555 STATE_AFTER_TRACE_PACKET_HEADER,
556 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
557 &notit->dscopes.trace_packet_header);
558 end:
559 BT_PUT(packet_header_type);
560 return ret;
561 }
562
563 static
564 enum 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,
568 STATE_AFTER_TRACE_PACKET_HEADER);
569 }
570
571 static inline
572 bool is_struct_type(struct bt_ctf_field_type *field_type)
573 {
574 return bt_ctf_field_type_get_type_id(field_type) ==
575 BT_CTF_FIELD_TYPE_ID_STRUCT;
576 }
577
578 static inline
579 bool is_variant_type(struct bt_ctf_field_type *field_type)
580 {
581 return bt_ctf_field_type_get_type_id(field_type) ==
582 BT_CTF_FIELD_TYPE_ID_VARIANT;
583 }
584
585 static
586 struct stream_class_field_path_cache *
587 create_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;
693 end:
694 BT_PUT(event_header);
695 BT_PUT(packet_context);
696 return cache_entry;
697 error:
698 g_free(cache_entry);
699 cache_entry = NULL;
700 goto end;
701 }
702
703 static
704 struct 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
724 static inline
725 enum bt_ctf_notif_iter_status set_current_stream_class(
726 struct bt_ctf_notif_iter *notit)
727 {
728 enum bt_ctf_notif_iter_status status = BT_CTF_NOTIF_ITER_STATUS_OK;
729 struct bt_ctf_field_type *packet_header_type = NULL;
730 struct bt_ctf_field_type *stream_id_field_type = NULL;
731 uint64_t stream_id;
732
733 /* Clear the current stream class field path cache. */
734 notit->cur_sc_field_path_cache = NULL;
735
736 /* Is there any "stream_id" field in the packet header? */
737 packet_header_type = bt_ctf_trace_get_packet_header_type(
738 notit->meta.trace);
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 =
749 bt_ctf_field_type_structure_get_field_type_by_name(
750 packet_header_type, "stream_id");
751 if (stream_id_field_type) {
752 /* Find appropriate stream class using current stream ID */
753 int ret;
754 struct bt_ctf_field *stream_id_field = NULL;
755
756 assert(notit->dscopes.trace_packet_header);
757
758 // TODO: optimalize!
759 stream_id_field = bt_ctf_field_structure_get_field(
760 notit->dscopes.trace_packet_header, "stream_id");
761 assert(stream_id_field);
762 ret = bt_ctf_field_unsigned_integer_get_value(
763 stream_id_field, &stream_id);
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(
769 notit->meta.trace) == 1);
770 stream_id = 0;
771 }
772
773 BT_PUT(notit->meta.stream_class);
774 notit->meta.stream_class = bt_ctf_trace_get_stream_class_by_id(
775 notit->meta.trace, stream_id);
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
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 }
794 end:
795 BT_PUT(packet_header_type);
796 BT_PUT(stream_id_field_type);
797
798 return status;
799 }
800
801 static
802 enum 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
815 static
816 enum 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(
824 notit->meta.stream_class);
825 if (!packet_context_type) {
826 notit->state = STATE_AFTER_STREAM_PACKET_CONTEXT;
827 goto end;
828 }
829
830 status = read_dscope_begin_state(notit, packet_context_type,
831 STATE_AFTER_STREAM_PACKET_CONTEXT,
832 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
833 &notit->dscopes.stream_packet_context);
834
835 end:
836 BT_PUT(packet_context_type);
837 return status;
838 }
839
840 static
841 enum 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,
845 STATE_AFTER_STREAM_PACKET_CONTEXT);
846 }
847
848 static
849 enum 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
859 packet_size_field = bt_ctf_field_structure_get_field(
860 notit->dscopes.stream_packet_context, "packet_size");
861 content_size_field = bt_ctf_field_structure_get_field(
862 notit->dscopes.stream_packet_context, "content_size");
863 if (packet_size_field) {
864 int ret = bt_ctf_field_unsigned_integer_get_value(
865 packet_size_field, &packet_size);
866
867 assert(!ret);
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 }
878
879 if (content_size_field) {
880 int ret = bt_ctf_field_unsigned_integer_get_value(
881 content_size_field, &content_size);
882
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;
890 end:
891 BT_PUT(packet_size_field);
892 BT_PUT(content_size_field);
893 return status;
894 }
895
896 static
897 enum 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
910 static
911 enum 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");
926 PERR("\tDecoded content size: %zu\n",
927 notit->cur_content_size);
928 PERR("\tCursor position: %zu\n", packet_at(notit));
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) {
937 notit->state = STATE_AFTER_STREAM_EVENT_HEADER;
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);
946 end:
947 BT_PUT(event_header_type);
948
949 return status;
950 }
951
952 static
953 enum 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
960 static inline
961 enum 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
1028 end_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
1079 end:
1080 BT_PUT(event_header_type);
1081 BT_PUT(id_field_type);
1082 BT_PUT(v_field_type);
1083
1084 return status;
1085 }
1086
1087 static
1088 enum 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
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
1101 end:
1102 return status;
1103 }
1104
1105 static
1106 enum 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) {
1115 notit->state = STATE_DSCOPE_EVENT_CONTEXT_BEGIN;
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
1124 end:
1125 BT_PUT(stream_event_context_type);
1126
1127 return status;
1128 }
1129
1130 static
1131 enum 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
1138 static
1139 enum 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) {
1148 notit->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN;
1149 goto end;
1150 }
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
1156 end:
1157 BT_PUT(event_context_type);
1158
1159 return status;
1160 }
1161
1162 static
1163 enum 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
1170 static
1171 enum 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) {
1180 notit->state = STATE_EMIT_NOTIF_EVENT;
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
1189 end:
1190 BT_PUT(event_payload_type);
1191
1192 return status;
1193 }
1194
1195 static
1196 enum 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
1202 static
1203 enum 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
1230 end:
1231 return status;
1232 }
1233
1234 static inline
1235 enum 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
1308 /**
1309 * Resets the internal state of a CTF notification iterator.
1310 */
1311 static
1312 void 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
1329 static
1330 int 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);
1339 BT_PUT(notit->cur_timestamp_end);
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;
1363 notit->cur_sc_field_path_cache = NULL;
1364 end:
1365 return ret;
1366 }
1367
1368 static
1369 struct 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)) {
1386 case BT_CTF_FIELD_TYPE_ID_STRUCT:
1387 next_field = bt_ctf_field_structure_get_field_by_index(
1388 base_field, index);
1389 break;
1390 case BT_CTF_FIELD_TYPE_ID_ARRAY:
1391 next_field = bt_ctf_field_array_get_field(base_field, index);
1392 break;
1393 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
1394 next_field = bt_ctf_field_sequence_get_field(base_field, index);
1395 break;
1396 case BT_CTF_FIELD_TYPE_ID_VARIANT:
1397 next_field = bt_ctf_field_variant_get_current_field(base_field);
1398 break;
1399 default:
1400 assert(false);
1401 break;
1402 }
1403
1404 end:
1405 BT_PUT(base_type);
1406
1407 return next_field;
1408 }
1409
1410 static
1411 void 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;
1459 end:
1460 bt_put(value_type);
1461 }
1462
1463 static
1464 enum bt_ctf_btr_status update_clock(struct bt_ctf_notif_iter *notit,
1465 struct bt_ctf_field *int_field)
1466 {
1467 gboolean clock_class_found;
1468 uint64_t *clock_state;
1469 struct bt_ctf_field_type *int_field_type = NULL;
1470 enum bt_ctf_btr_status ret = BT_CTF_BTR_STATUS_OK;
1471 struct bt_ctf_clock_class *clock_class = NULL;
1472
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);
1480 if (likely(!clock_class)) {
1481 goto end;
1482 }
1483
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);
1489
1490 PERR("Unknown clock class %s mapped to integer encountered in stream\n",
1491 clock_class_name ? : "NULL");
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 }
1502 g_hash_table_insert(notit->clock_states, bt_get(clock_class),
1503 clock_state);
1504 }
1505
1506 /* Update the clock's state. */
1507 update_clock_state(clock_state, int_field);
1508 end:
1509 bt_put(int_field_type);
1510 bt_put(clock_class);
1511 return ret;
1512 }
1513
1514 static
1515 enum bt_ctf_btr_status btr_unsigned_int_common(uint64_t value,
1516 struct bt_ctf_field_type *type, void *data,
1517 struct bt_ctf_field **out_int_field)
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
1525 /* Create next field */
1526 field = get_next_field(notit);
1527 if (!field) {
1528 PERR("Failed to get next field (unsigned int)\n");
1529 status = BT_CTF_BTR_STATUS_ERROR;
1530 goto end_no_put;
1531 }
1532
1533 switch(bt_ctf_field_type_get_type_id(type)) {
1534 case BT_CTF_FIELD_TYPE_ID_INTEGER:
1535 /* Integer field is created field */
1536 BT_MOVE(int_field, field);
1537 bt_get(type);
1538 break;
1539 case BT_CTF_FIELD_TYPE_ID_ENUM:
1540 int_field = bt_ctf_field_enumeration_get_container(field);
1541 type = bt_ctf_field_get_type(int_field);
1542 break;
1543 default:
1544 assert(0);
1545 type = NULL;
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
1555 ret = bt_ctf_field_unsigned_integer_set_value(int_field, value);
1556 assert(!ret);
1557 stack_top(notit->stack)->index++;
1558 *out_int_field = int_field;
1559
1560 end:
1561 BT_PUT(field);
1562 BT_PUT(type);
1563 end_no_put:
1564 return status;
1565 }
1566
1567 static
1568 enum 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
1583 static
1584 enum bt_ctf_btr_status btr_unsigned_int_cb(uint64_t value,
1585 struct bt_ctf_field_type *type, void *data)
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
1604 status = update_clock(notit, field);
1605 BT_PUT(field);
1606 end:
1607 return status;
1608 }
1609
1610 static
1611 enum bt_ctf_btr_status btr_signed_int_cb(int64_t value,
1612 struct bt_ctf_field_type *type, void *data)
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
1620 /* create next field */
1621 field = get_next_field(notit);
1622 if (!field) {
1623 PERR("Failed to get next field (signed int)\n");
1624 status = BT_CTF_BTR_STATUS_ERROR;
1625 goto end_no_put;
1626 }
1627
1628 switch(bt_ctf_field_type_get_type_id(type)) {
1629 case BT_CTF_FIELD_TYPE_ID_INTEGER:
1630 /* Integer field is created field */
1631 BT_MOVE(int_field, field);
1632 bt_get(type);
1633 break;
1634 case BT_CTF_FIELD_TYPE_ID_ENUM:
1635 int_field = bt_ctf_field_enumeration_get_container(field);
1636 type = bt_ctf_field_get_type(int_field);
1637 break;
1638 default:
1639 assert(0);
1640 type = NULL;
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
1650 ret = bt_ctf_field_signed_integer_set_value(int_field, value);
1651 assert(!ret);
1652 stack_top(notit->stack)->index++;
1653 status = update_clock(notit, int_field);
1654 end:
1655 BT_PUT(field);
1656 BT_PUT(int_field);
1657 BT_PUT(type);
1658 end_no_put:
1659 return status;
1660 }
1661
1662 static
1663 enum 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
1683 end:
1684 BT_PUT(field);
1685
1686 return status;
1687 }
1688
1689 static
1690 enum 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
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
1730 end:
1731 BT_PUT(field);
1732
1733 return status;
1734 }
1735
1736 static
1737 enum 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
1757 end:
1758 return status;
1759 }
1760
1761 static
1762 enum 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
1776 enum 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
1815 end:
1816 BT_PUT(field);
1817
1818 return status;
1819 }
1820
1821 enum 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
1839 static
1840 struct 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
1905 end:
1906 return field;
1907 }
1908
1909 static
1910 int64_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;
1916 struct bt_ctf_field *length_field = NULL;
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
1924 length_field = resolve_field(notit, field_path);
1925 if (!length_field) {
1926 goto end;
1927 }
1928
1929 iret = bt_ctf_field_unsigned_integer_get_value(length_field, &length);
1930 if (iret) {
1931 goto end;
1932 }
1933
1934 iret = bt_ctf_field_sequence_set_length(stack_top(notit->stack)->base,
1935 length_field);
1936 if (iret) {
1937 goto end;
1938 }
1939 ret = (int64_t) length;
1940
1941 end:
1942 BT_PUT(length_field);
1943 BT_PUT(field_path);
1944
1945 return ret;
1946 }
1947
1948 static
1949 struct 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
1988 end:
1989 BT_PUT(tag_field);
1990 BT_PUT(selected_field);
1991 BT_PUT(path);
1992
1993 return selected_field_type;
1994 }
1995
1996 static
1997 int set_event_clocks(struct bt_ctf_event *event,
1998 struct bt_ctf_notif_iter *notit)
1999 {
2000 int ret;
2001 GHashTableIter iter;
2002 struct bt_ctf_clock_class *clock_class;
2003 uint64_t *clock_state;
2004
2005 g_hash_table_iter_init(&iter, notit->clock_states);
2006
2007 while (g_hash_table_iter_next(&iter, (gpointer) &clock_class,
2008 (gpointer) &clock_state)) {
2009 struct bt_ctf_clock_value *clock_value;
2010
2011 clock_value = bt_ctf_clock_value_create(clock_class,
2012 *clock_state);
2013 if (!clock_value) {
2014 ret = -1;
2015 goto end;
2016 }
2017 ret = bt_ctf_event_set_clock_value(event, clock_value);
2018 bt_put(clock_value);
2019 if (ret) {
2020 goto end;
2021 }
2022 }
2023 ret = 0;
2024 end:
2025 return ret;
2026 }
2027
2028 static
2029 struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit)
2030 {
2031 int ret;
2032 struct bt_ctf_event *event;
2033
2034 /* Create event object. */
2035 event = bt_ctf_event_create(notit->meta.event_class);
2036 if (!event) {
2037 goto error;
2038 }
2039
2040 /* Set header, stream event context, context, and payload fields. */
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
2059 ret = bt_ctf_event_set_event_payload(event,
2060 notit->dscopes.event_payload);
2061 if (ret) {
2062 goto error;
2063 }
2064
2065 ret = set_event_clocks(event, notit);
2066 if (ret) {
2067 goto error;
2068 }
2069
2070 /* Associate with current packet. */
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;
2078 error:
2079 BT_PUT(event);
2080 end:
2081 return event;
2082 }
2083
2084 static
2085 void create_packet(struct bt_ctf_notif_iter *notit)
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,
2093 notit->medium.data);
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,
2107 notit->dscopes.trace_packet_header);
2108 if (ret) {
2109 goto error;
2110 }
2111 }
2112
2113 if (notit->dscopes.stream_packet_context) {
2114 ret = bt_ctf_packet_set_context(packet,
2115 notit->dscopes.stream_packet_context);
2116 if (ret) {
2117 goto error;
2118 }
2119 }
2120
2121 goto end;
2122 error:
2123 BT_PUT(packet);
2124 end:
2125 BT_MOVE(notit->packet, packet);
2126 }
2127
2128 static
2129 void notify_new_packet(struct bt_ctf_notif_iter *notit,
2130 struct bt_notification **notification)
2131 {
2132 struct bt_notification *ret;
2133
2134 /* Initialize the iterator's current packet */
2135 create_packet(notit);
2136 if (!notit->packet) {
2137 return;
2138 }
2139
2140 ret = bt_notification_packet_begin_create(notit->packet);
2141 if (!ret) {
2142 return;
2143 }
2144 *notification = ret;
2145 }
2146
2147 static
2148 void notify_end_of_packet(struct bt_ctf_notif_iter *notit,
2149 struct bt_notification **notification)
2150 {
2151 struct bt_notification *ret;
2152
2153 if (!notit->packet) {
2154 return;
2155 }
2156
2157 ret = bt_notification_packet_end_create(notit->packet);
2158 if (!ret) {
2159 return;
2160 }
2161 BT_PUT(notit->packet);
2162 *notification = ret;
2163 }
2164
2165 static
2166 void notify_event(struct bt_ctf_notif_iter *notit,
2167 struct bt_clock_class_priority_map *cc_prio_map,
2168 struct bt_notification **notification)
2169 {
2170 struct bt_ctf_event *event;
2171 struct bt_notification *ret = NULL;
2172
2173 /* Create event */
2174 event = create_event(notit);
2175 if (!event) {
2176 goto end;
2177 }
2178
2179 ret = bt_notification_event_create(event, cc_prio_map);
2180 if (!ret) {
2181 goto end;
2182 }
2183 *notification = ret;
2184 end:
2185 BT_PUT(event);
2186 }
2187
2188 static
2189 int init_clock_states(GHashTable *clock_states, struct bt_ctf_trace *trace)
2190 {
2191 int clock_class_count, i, ret = 0;
2192
2193 clock_class_count = bt_ctf_trace_get_clock_class_count(trace);
2194 if (clock_class_count <= 0) {
2195 ret = -1;
2196 goto end;
2197 }
2198
2199 for (i = 0; i < clock_class_count; i++) {
2200 struct bt_ctf_clock_class *clock_class;
2201
2202 clock_class = bt_ctf_trace_get_clock_class_by_index(trace, i);
2203 if (!clock_class) {
2204 ret = -1;
2205 goto end;
2206 }
2207
2208 g_hash_table_insert(clock_states, bt_get(clock_class), NULL);
2209 bt_put(clock_class);
2210 }
2211 end:
2212 return ret;
2213 }
2214
2215 static
2216 void 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 }
2255 end:
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
2261 BT_HIDDEN
2262 struct 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 {
2267 int ret;
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);
2288 assert(medops.get_stream);
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 }
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 }
2305 notit->meta.trace = bt_get(trace);
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");
2313 goto error;
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");
2319 goto error;
2320 }
2321
2322 bt_ctf_notif_iter_reset(notit);
2323
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
2338 end:
2339 return notit;
2340 error:
2341 bt_ctf_notif_iter_destroy(notit);
2342 notit = NULL;
2343 goto end;
2344 }
2345
2346 void 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);
2352 BT_PUT(notit->cur_timestamp_end);
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
2363 if (notit->clock_states) {
2364 g_hash_table_destroy(notit->clock_states);
2365 }
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 }
2374 g_free(notit);
2375 }
2376
2377 enum bt_ctf_notif_iter_status bt_ctf_notif_iter_get_next_notification(
2378 struct bt_ctf_notif_iter *notit,
2379 struct bt_clock_class_priority_map *cc_prio_map,
2380 struct bt_notification **notification)
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);
2389 if (status != BT_CTF_NOTIF_ITER_STATUS_OK) {
2390 if (status == BT_CTF_NOTIF_ITER_STATUS_EOF) {
2391 PDBG("Medium operation reported end of stream\n");
2392 } else {
2393 PERR("Failed to handle state:\n");
2394 PERR("\tState: %d\n", notit->state);
2395 }
2396 goto end;
2397 }
2398
2399 switch (notit->state) {
2400 case STATE_EMIT_NOTIF_NEW_PACKET:
2401 PDBG("Emitting new packet notification\n");
2402 notify_new_packet(notit, notification);
2403 if (!*notification) {
2404 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
2405 }
2406 goto end;
2407 case STATE_EMIT_NOTIF_EVENT:
2408 PDBG("Emitting event notification\n");
2409 notify_event(notit, cc_prio_map, notification);
2410 if (!*notification) {
2411 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
2412 }
2413 goto end;
2414 case STATE_EMIT_NOTIF_END_OF_PACKET:
2415 /* Update clock with timestamp_end field. */
2416 if (notit->cur_timestamp_end) {
2417 enum bt_ctf_btr_status btr_status;
2418 struct bt_ctf_field_type *field_type =
2419 bt_ctf_field_get_type(
2420 notit->cur_timestamp_end);
2421
2422 btr_status = update_clock(notit,
2423 notit->cur_timestamp_end);
2424 BT_PUT(field_type);
2425 if (btr_status != BT_CTF_BTR_STATUS_OK) {
2426 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
2427 goto end;
2428 }
2429 }
2430
2431 PDBG("Emitting end of packet notification\n");
2432 notify_end_of_packet(notit, notification);
2433 if (!*notification) {
2434 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
2435 }
2436 goto end;
2437 default:
2438 /* Non-emitting state: continue */
2439 break;
2440 }
2441 }
2442
2443 end:
2444 return status;
2445 }
This page took 0.119533 seconds and 3 git commands to generate.