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