lib: add internal object pool API and use it; adapt plugins/tests
[babeltrace.git] / plugins / ctf / common / notif-iter / notif-iter.c
CommitLineData
e98a2d6e
PP
1/*
2 * Babeltrace - CTF notification iterator
06a626b8 3 *
e98a2d6e
PP
4 * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
fdf0e7a0
PP
26#define BT_LOG_TAG "PLUGIN-CTF-NOTIF-ITER"
27#include "logging.h"
28
e98a2d6e
PP
29#include <stdint.h>
30#include <inttypes.h>
31#include <stdio.h>
32#include <stddef.h>
33#include <stdbool.h>
f6ccaed9 34#include <babeltrace/assert-internal.h>
e98a2d6e 35#include <string.h>
9d408fca 36#include <babeltrace/babeltrace.h>
3dca2276 37#include <babeltrace/common-internal.h>
e98a2d6e 38#include <glib.h>
0fbb9a9f 39#include <stdlib.h>
e98a2d6e 40
06a626b8
JG
41#include "notif-iter.h"
42#include "../btr/btr.h"
e98a2d6e 43
50842bdc 44struct bt_notif_iter;
e98a2d6e
PP
45
46/* A visit stack entry */
47struct stack_entry {
48 /*
49 * Current base field, one of:
50 *
51 * * string
52 * * structure
53 * * array
54 * * sequence
55 * * variant
56 *
312c056a 57 * Field is borrowed.
e98a2d6e 58 */
50842bdc 59 struct bt_field *base;
e98a2d6e
PP
60
61 /* index of next field to set */
62 size_t index;
63};
64
65/* Visit stack */
66struct stack {
67 /* Entries (struct stack_entry *) (top is last element) */
68 GPtrArray *entries;
e98a2d6e
PP
69};
70
71/* State */
72enum state {
73 STATE_INIT,
74 STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN,
75 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
76 STATE_AFTER_TRACE_PACKET_HEADER,
77 STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN,
78 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
79 STATE_AFTER_STREAM_PACKET_CONTEXT,
f42867e2 80 STATE_EMIT_NOTIF_NEW_STREAM,
e98a2d6e
PP
81 STATE_EMIT_NOTIF_NEW_PACKET,
82 STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN,
83 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE,
84 STATE_AFTER_STREAM_EVENT_HEADER,
85 STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN,
86 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE,
87 STATE_DSCOPE_EVENT_CONTEXT_BEGIN,
88 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE,
89 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
90 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE,
91 STATE_EMIT_NOTIF_EVENT,
92 STATE_EMIT_NOTIF_END_OF_PACKET,
f42867e2 93 STATE_DONE,
e98a2d6e
PP
94 STATE_SKIP_PACKET_PADDING,
95};
96
5f870343
JG
97struct trace_field_path_cache {
98 /*
99 * Indexes of the stream_id and stream_instance_id field in the packet
100 * header structure, -1 if unset.
101 */
102 int stream_id;
103 int stream_instance_id;
104};
105
106struct stream_class_field_path_cache {
107 /*
108 * Indexes of the v and id fields in the stream event header structure,
109 * -1 if unset.
110 */
111 int v;
112 int id;
113
114 /*
115 * index of the timestamp_end, packet_size and content_size fields in
116 * the stream packet context structure. Set to -1 if the fields were
117 * not found.
118 */
119 int timestamp_end;
120 int packet_size;
121 int content_size;
122};
123
124struct field_cb_override {
50842bdc
PP
125 enum bt_btr_status (* func)(void *value,
126 struct bt_field_type *type, void *data);
5f870343
JG
127 void *data;
128};
129
e98a2d6e 130/* CTF notification iterator */
50842bdc 131struct bt_notif_iter {
e98a2d6e
PP
132 /* Visit stack */
133 struct stack *stack;
134
e98a2d6e
PP
135 /*
136 * Current dynamic scope field pointer.
137 *
312c056a
PP
138 * This is set by read_dscope_begin_state() and contains the
139 * value of one of the pointers in `dscopes` below.
e98a2d6e 140 */
312c056a 141 struct bt_field *cur_dscope_field;
e98a2d6e
PP
142
143 /* Trace and classes (owned by this) */
144 struct {
50842bdc
PP
145 struct bt_trace *trace;
146 struct bt_stream_class *stream_class;
147 struct bt_event_class *event_class;
312c056a 148 struct bt_clock_class_priority_map *cc_prio_map;
e98a2d6e
PP
149 } meta;
150
312c056a
PP
151 /* Current packet header field wrapper (NULL if not created yet) */
152 struct bt_packet_header_field *packet_header_field;
153
154 /* Current packet header field wrapper (NULL if not created yet) */
155 struct bt_packet_context_field *packet_context_field;
156
157 /* Current event header field (NULL if not created yet) */
158 struct bt_event_header_field *event_header_field;
159
e98a2d6e 160 /* Current packet (NULL if not created yet) */
50842bdc 161 struct bt_packet *packet;
e98a2d6e 162
af87daef 163 /* Current stream (NULL if not set yet) */
50842bdc 164 struct bt_stream *stream;
af87daef 165
312c056a
PP
166 /* Current event (NULL if not created yet) */
167 struct bt_event *event;
168
169 /* Current event notification (NULL if not created yet) */
170 struct bt_notification *event_notif;
171
5f870343 172 /*
312c056a
PP
173 * Current `timestamp_end` field (to consider before switching
174 * packets). If it's set, it's a field which is within
175 * `dscopes.stream_packet_context` below, which is in `packet`
176 * above.
5f870343 177 */
50842bdc 178 struct bt_field *cur_timestamp_end;
5f870343 179
e98a2d6e
PP
180 /* Database of current dynamic scopes (owned by this) */
181 struct {
50842bdc
PP
182 struct bt_field *trace_packet_header;
183 struct bt_field *stream_packet_context;
184 struct bt_field *stream_event_header;
185 struct bt_field *stream_event_context;
186 struct bt_field *event_context;
187 struct bt_field *event_payload;
e98a2d6e
PP
188 } dscopes;
189
5f870343
JG
190 /*
191 * Special field overrides.
192 *
193 * Overrides are used to implement the behaviours of special fields such
194 * as "timestamp_end" (which must be ignored until the end of the
195 * packet), "id" (event id) which can be present multiple times and must
196 * be updated multiple time.
197 *
198 * This should be used to implement the behaviour of integer fields
199 * mapped to clocks and other "tagged" fields (in CTF 2).
200 *
50842bdc 201 * bt_field_type to struct field_cb_override
5f870343
JG
202 */
203 GHashTable *field_overrides;
204
e98a2d6e
PP
205 /* Current state */
206 enum state state;
207
2cf1d51e 208 /* Current medium buffer data */
e98a2d6e
PP
209 struct {
210 /* Last address provided by medium */
211 const uint8_t *addr;
212
213 /* Buffer size provided by medium (bytes) */
214 size_t sz;
215
216 /* Offset within whole packet of addr (bits) */
217 size_t packet_offset;
218
219 /* Current position from addr (bits) */
220 size_t at;
174e773b
PP
221
222 /* Position of the last event header from addr (bits) */
223 size_t last_eh_at;
e98a2d6e
PP
224 } buf;
225
226 /* Binary type reader */
50842bdc 227 struct bt_btr *btr;
e98a2d6e 228
2cf1d51e 229 /* Current medium data */
e98a2d6e 230 struct {
50842bdc 231 struct bt_notif_iter_medium_ops medops;
e98a2d6e
PP
232 size_t max_request_sz;
233 void *data;
234 } medium;
235
f42867e2
PP
236 /* Stream beginning was emitted */
237 bool stream_begin_emitted;
238
e98a2d6e 239 /* Current packet size (bits) (-1 if unknown) */
e7a4393b 240 int64_t cur_packet_size;
e98a2d6e
PP
241
242 /* Current content size (bits) (-1 if unknown) */
e7a4393b 243 int64_t cur_content_size;
c44c3e70 244
9e0c8dbb
JG
245 /*
246 * Offset, in the underlying media, of the current packet's start
247 * (-1 if unknown).
248 */
249 off_t cur_packet_offset;
250
50842bdc 251 /* bt_clock_class to uint64_t. */
c44c3e70 252 GHashTable *clock_states;
5f870343
JG
253
254 /*
255 * Cache of the trace-constant field paths (event header type)
256 * associated to the current trace.
257 */
258 struct trace_field_path_cache trace_field_path_cache;
259
260 /*
261 * Field path cache associated with the current stream class.
262 * Ownership of this structure belongs to the field_path_caches HT.
263 */
264 struct stream_class_field_path_cache *cur_sc_field_path_cache;
265
50842bdc 266 /* bt_stream_class to struct stream_class_field_path_cache. */
5f870343 267 GHashTable *sc_field_path_caches;
e98a2d6e
PP
268};
269
fdf0e7a0
PP
270static inline
271const char *state_string(enum state state)
272{
273 switch (state) {
274 case STATE_INIT:
275 return "STATE_INIT";
276 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN:
277 return "STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN";
278 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE:
279 return "STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE";
280 case STATE_AFTER_TRACE_PACKET_HEADER:
281 return "STATE_AFTER_TRACE_PACKET_HEADER";
282 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN:
283 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN";
284 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE:
285 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE";
286 case STATE_AFTER_STREAM_PACKET_CONTEXT:
287 return "STATE_AFTER_STREAM_PACKET_CONTEXT";
288 case STATE_EMIT_NOTIF_NEW_PACKET:
289 return "STATE_EMIT_NOTIF_NEW_PACKET";
f42867e2
PP
290 case STATE_EMIT_NOTIF_NEW_STREAM:
291 return "STATE_EMIT_NOTIF_NEW_STREAM";
fdf0e7a0
PP
292 case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN:
293 return "STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN";
294 case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE:
295 return "STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE";
296 case STATE_AFTER_STREAM_EVENT_HEADER:
297 return "STATE_AFTER_STREAM_EVENT_HEADER";
298 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN:
299 return "STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN";
300 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE:
301 return "STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE";
302 case STATE_DSCOPE_EVENT_CONTEXT_BEGIN:
303 return "STATE_DSCOPE_EVENT_CONTEXT_BEGIN";
304 case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE:
305 return "STATE_DSCOPE_EVENT_CONTEXT_CONTINUE";
306 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN:
307 return "STATE_DSCOPE_EVENT_PAYLOAD_BEGIN";
308 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE:
309 return "STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE";
310 case STATE_EMIT_NOTIF_EVENT:
311 return "STATE_EMIT_NOTIF_EVENT";
312 case STATE_EMIT_NOTIF_END_OF_PACKET:
313 return "STATE_EMIT_NOTIF_END_OF_PACKET";
f42867e2
PP
314 case STATE_DONE:
315 return "STATE_DONE";
fdf0e7a0
PP
316 case STATE_SKIP_PACKET_PADDING:
317 return "STATE_SKIP_PACKET_PADDING";
318 default:
319 return "(unknown)";
320 }
321}
322
2cf1d51e 323static
50842bdc 324int bt_notif_iter_switch_packet(struct bt_notif_iter *notit);
2cf1d51e 325
5f870343 326static
50842bdc
PP
327enum bt_btr_status btr_timestamp_end_cb(void *value,
328 struct bt_field_type *type, void *data);
5f870343 329
e98a2d6e
PP
330static
331void stack_entry_free_func(gpointer data)
332{
312c056a 333 g_free(data);
e98a2d6e
PP
334}
335
336static
50842bdc 337struct stack *stack_new(struct bt_notif_iter *notit)
e98a2d6e
PP
338{
339 struct stack *stack = NULL;
340
341 stack = g_new0(struct stack, 1);
342 if (!stack) {
fdf0e7a0 343 BT_LOGE_STR("Failed to allocate one stack.");
e98a2d6e
PP
344 goto error;
345 }
346
347 stack->entries = g_ptr_array_new_with_free_func(stack_entry_free_func);
348 if (!stack->entries) {
fdf0e7a0 349 BT_LOGE_STR("Failed to allocate a GPtrArray.");
e98a2d6e
PP
350 goto error;
351 }
352
fdf0e7a0 353 BT_LOGD("Created stack: notit-addr=%p, stack-addr=%p", notit, stack);
e98a2d6e 354 return stack;
fdf0e7a0 355
e98a2d6e
PP
356error:
357 g_free(stack);
e98a2d6e
PP
358 return NULL;
359}
360
361static
362void stack_destroy(struct stack *stack)
363{
f6ccaed9 364 BT_ASSERT(stack);
fdf0e7a0 365 BT_LOGD("Destroying stack: addr=%p", stack);
e98a2d6e
PP
366 g_ptr_array_free(stack->entries, TRUE);
367 g_free(stack);
368}
369
370static
50842bdc 371int stack_push(struct stack *stack, struct bt_field *base)
e98a2d6e
PP
372{
373 int ret = 0;
374 struct stack_entry *entry;
e98a2d6e 375
f6ccaed9
PP
376 BT_ASSERT(stack);
377 BT_ASSERT(base);
fdf0e7a0
PP
378 BT_LOGV("Pushing base field on stack: stack-addr=%p, "
379 "stack-size-before=%u, stack-size-after=%u",
380 stack, stack->entries->len, stack->entries->len + 1);
e98a2d6e
PP
381 entry = g_new0(struct stack_entry, 1);
382 if (!entry) {
fdf0e7a0 383 BT_LOGE_STR("Failed to allocate one stack entry.");
e98a2d6e
PP
384 ret = -1;
385 goto end;
386 }
387
312c056a 388 entry->base = base;
e98a2d6e
PP
389 g_ptr_array_add(stack->entries, entry);
390
391end:
392 return ret;
393}
394
395static inline
396unsigned int stack_size(struct stack *stack)
397{
f6ccaed9 398 BT_ASSERT(stack);
e98a2d6e
PP
399
400 return stack->entries->len;
401}
402
403static
404void stack_pop(struct stack *stack)
405{
f6ccaed9
PP
406 BT_ASSERT(stack);
407 BT_ASSERT(stack_size(stack));
fdf0e7a0
PP
408 BT_LOGV("Popping from stack: "
409 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
410 stack, stack->entries->len, stack->entries->len - 1);
e98a2d6e
PP
411 g_ptr_array_remove_index(stack->entries, stack->entries->len - 1);
412}
413
414static inline
415struct stack_entry *stack_top(struct stack *stack)
416{
f6ccaed9
PP
417 BT_ASSERT(stack);
418 BT_ASSERT(stack_size(stack));
e98a2d6e
PP
419
420 return g_ptr_array_index(stack->entries, stack->entries->len - 1);
421}
422
423static inline
424bool stack_empty(struct stack *stack)
425{
426 return stack_size(stack) == 0;
427}
428
429static
430void stack_clear(struct stack *stack)
431{
f6ccaed9 432 BT_ASSERT(stack);
e98a2d6e
PP
433
434 if (!stack_empty(stack)) {
fdf0e7a0
PP
435 BT_LOGV("Clearing stack: stack-addr=%p, stack-size=%u",
436 stack, stack->entries->len);
e98a2d6e
PP
437 g_ptr_array_remove_range(stack->entries, 0, stack_size(stack));
438 }
439
f6ccaed9 440 BT_ASSERT(stack_empty(stack));
e98a2d6e
PP
441}
442
443static inline
50842bdc
PP
444enum bt_notif_iter_status notif_iter_status_from_m_status(
445 enum bt_notif_iter_medium_status m_status)
e98a2d6e 446{
dc77b521 447 return (int) m_status;
e98a2d6e
PP
448}
449
450static inline
50842bdc 451size_t buf_size_bits(struct bt_notif_iter *notit)
e98a2d6e 452{
fdf0e7a0 453 return notit->buf.sz * 8;
e98a2d6e
PP
454}
455
456static inline
50842bdc 457size_t buf_available_bits(struct bt_notif_iter *notit)
e98a2d6e
PP
458{
459 return buf_size_bits(notit) - notit->buf.at;
460}
461
462static inline
50842bdc 463size_t packet_at(struct bt_notif_iter *notit)
e98a2d6e
PP
464{
465 return notit->buf.packet_offset + notit->buf.at;
466}
467
e98a2d6e 468static inline
50842bdc 469void buf_consume_bits(struct bt_notif_iter *notit, size_t incr)
e98a2d6e 470{
fdf0e7a0
PP
471 BT_LOGV("Advancing cursor: notit-addr=%p, cur-before=%zu, cur-after=%zu",
472 notit, notit->buf.at, notit->buf.at + incr);
e98a2d6e
PP
473 notit->buf.at += incr;
474}
475
e98a2d6e 476static
50842bdc
PP
477enum bt_notif_iter_status request_medium_bytes(
478 struct bt_notif_iter *notit)
e98a2d6e 479{
fdf0e7a0
PP
480 uint8_t *buffer_addr = NULL;
481 size_t buffer_sz = 0;
50842bdc 482 enum bt_notif_iter_medium_status m_status;
e98a2d6e 483
fdf0e7a0
PP
484 BT_LOGV("Calling user function (request bytes): notit-addr=%p, "
485 "request-size=%zu", notit, notit->medium.max_request_sz);
e98a2d6e
PP
486 m_status = notit->medium.medops.request_bytes(
487 notit->medium.max_request_sz, &buffer_addr,
488 &buffer_sz, notit->medium.data);
fdf0e7a0 489 BT_LOGV("User function returned: status=%s, buf-addr=%p, buf-size=%zu",
50842bdc 490 bt_notif_iter_medium_status_string(m_status),
fdf0e7a0 491 buffer_addr, buffer_sz);
50842bdc 492 if (m_status == BT_NOTIF_ITER_MEDIUM_STATUS_OK) {
f6ccaed9 493 BT_ASSERT(buffer_sz != 0);
e98a2d6e
PP
494
495 /* New packet offset is old one + old size (in bits) */
496 notit->buf.packet_offset += buf_size_bits(notit);
497
498 /* Restart at the beginning of the new medium buffer */
499 notit->buf.at = 0;
2b186c3e 500 notit->buf.last_eh_at = SIZE_MAX;
e98a2d6e
PP
501
502 /* New medium buffer size */
503 notit->buf.sz = buffer_sz;
504
505 /* New medium buffer address */
506 notit->buf.addr = buffer_addr;
fdf0e7a0
PP
507
508 BT_LOGV("User function returned new bytes: "
509 "packet-offset=%zu, cur=%zu, size=%zu, addr=%p",
510 notit->buf.packet_offset, notit->buf.at,
511 notit->buf.sz, notit->buf.addr);
512 BT_LOGV_MEM(buffer_addr, buffer_sz, "Returned bytes at %p:",
513 buffer_addr);
50842bdc 514 } else if (m_status == BT_NOTIF_ITER_MEDIUM_STATUS_EOF) {
0684124b
PP
515 /*
516 * User returned end of stream: validate that we're not
517 * in the middle of a packet header, packet context, or
518 * event.
519 */
df0139b8
PP
520 if (notit->cur_packet_size >= 0) {
521 if (packet_at(notit) == notit->cur_packet_size) {
522 goto end;
0684124b 523 }
df0139b8
PP
524 } else {
525 if (packet_at(notit) == 0) {
526 goto end;
0684124b 527 }
0684124b 528
df0139b8
PP
529 if (notit->buf.last_eh_at != SIZE_MAX &&
530 notit->buf.at == notit->buf.last_eh_at) {
531 goto end;
0684124b
PP
532 }
533 }
534
0684124b
PP
535 /* All other states are invalid */
536 BT_LOGW("User function returned %s, but notification iterator is in an unexpected state: "
df0139b8
PP
537 "state=%s, cur-packet-size=%" PRId64 ", cur=%zu, "
538 "packet-cur=%zu, last-eh-at=%zu",
50842bdc 539 bt_notif_iter_medium_status_string(m_status),
df0139b8
PP
540 state_string(notit->state),
541 notit->cur_packet_size,
542 notit->buf.at, packet_at(notit),
543 notit->buf.last_eh_at);
50842bdc 544 m_status = BT_NOTIF_ITER_MEDIUM_STATUS_ERROR;
fdf0e7a0
PP
545 } else if (m_status < 0) {
546 BT_LOGW("User function failed: status=%s",
50842bdc 547 bt_notif_iter_medium_status_string(m_status));
e98a2d6e
PP
548 }
549
df0139b8 550end:
e98a2d6e
PP
551 return notif_iter_status_from_m_status(m_status);
552}
553
554static inline
50842bdc
PP
555enum bt_notif_iter_status buf_ensure_available_bits(
556 struct bt_notif_iter *notit)
e98a2d6e 557{
50842bdc 558 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
e98a2d6e
PP
559
560 if (buf_available_bits(notit) == 0) {
561 /*
50842bdc 562 * This _cannot_ return BT_NOTIF_ITER_STATUS_OK
e98a2d6e
PP
563 * _and_ no bits.
564 */
565 status = request_medium_bytes(notit);
566 }
567
568 return status;
569}
570
571static
50842bdc
PP
572enum bt_notif_iter_status read_dscope_begin_state(
573 struct bt_notif_iter *notit,
574 struct bt_field_type *dscope_field_type,
e98a2d6e 575 enum state done_state, enum state continue_state,
312c056a 576 struct bt_field *dscope_field)
e98a2d6e 577{
50842bdc
PP
578 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
579 enum bt_btr_status btr_status;
e98a2d6e
PP
580 size_t consumed_bits;
581
e98a2d6e 582 notit->cur_dscope_field = dscope_field;
fdf0e7a0
PP
583 BT_LOGV("Starting BTR: notit-addr=%p, btr-addr=%p, ft-addr=%p",
584 notit, notit->btr, dscope_field_type);
50842bdc 585 consumed_bits = bt_btr_start(notit->btr, dscope_field_type,
e98a2d6e
PP
586 notit->buf.addr, notit->buf.at, packet_at(notit),
587 notit->buf.sz, &btr_status);
fdf0e7a0 588 BT_LOGV("BTR consumed bits: size=%zu", consumed_bits);
e98a2d6e
PP
589
590 switch (btr_status) {
50842bdc 591 case BT_BTR_STATUS_OK:
e98a2d6e 592 /* type was read completely */
fdf0e7a0 593 BT_LOGV_STR("Field was completely decoded.");
e98a2d6e
PP
594 notit->state = done_state;
595 break;
50842bdc 596 case BT_BTR_STATUS_EOF:
fdf0e7a0 597 BT_LOGV_STR("BTR needs more data to decode field completely.");
e98a2d6e
PP
598 notit->state = continue_state;
599 break;
600 default:
fdf0e7a0
PP
601 BT_LOGW("BTR failed to start: notit-addr=%p, btr-addr=%p, "
602 "status=%s", notit, notit->btr,
50842bdc
PP
603 bt_btr_status_string(btr_status));
604 status = BT_NOTIF_ITER_STATUS_ERROR;
e98a2d6e
PP
605 goto end;
606 }
607
608 /* Consume bits now since we know we're not in an error state */
609 buf_consume_bits(notit, consumed_bits);
610
611end:
612 return status;
613}
614
615static
50842bdc
PP
616enum bt_notif_iter_status read_dscope_continue_state(
617 struct bt_notif_iter *notit, enum state done_state)
e98a2d6e 618{
50842bdc
PP
619 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
620 enum bt_btr_status btr_status;
e98a2d6e
PP
621 size_t consumed_bits;
622
df0139b8
PP
623 BT_LOGV("Continuing BTR: notit-addr=%p, btr-addr=%p",
624 notit, notit->btr);
625
e98a2d6e 626 status = buf_ensure_available_bits(notit);
50842bdc 627 if (status != BT_NOTIF_ITER_STATUS_OK) {
fdf0e7a0
PP
628 if (status < 0) {
629 BT_LOGW("Cannot ensure that buffer has at least one byte: "
630 "notif-addr=%p, status=%s",
50842bdc 631 notit, bt_notif_iter_status_string(status));
fdf0e7a0
PP
632 } else {
633 BT_LOGV("Cannot ensure that buffer has at least one byte: "
634 "notif-addr=%p, status=%s",
50842bdc 635 notit, bt_notif_iter_status_string(status));
fdf0e7a0
PP
636 }
637
e98a2d6e
PP
638 goto end;
639 }
640
df0139b8 641
50842bdc 642 consumed_bits = bt_btr_continue(notit->btr, notit->buf.addr,
fdf0e7a0
PP
643 notit->buf.sz, &btr_status);
644 BT_LOGV("BTR consumed bits: size=%zu", consumed_bits);
e98a2d6e
PP
645
646 switch (btr_status) {
50842bdc 647 case BT_BTR_STATUS_OK:
78586d8a 648 /* Type was read completely. */
fdf0e7a0 649 BT_LOGV_STR("Field was completely decoded.");
e98a2d6e
PP
650 notit->state = done_state;
651 break;
50842bdc 652 case BT_BTR_STATUS_EOF:
78586d8a 653 /* Stay in this continue state. */
fdf0e7a0 654 BT_LOGV_STR("BTR needs more data to decode field completely.");
e98a2d6e
PP
655 break;
656 default:
fdf0e7a0
PP
657 BT_LOGW("BTR failed to continue: notit-addr=%p, btr-addr=%p, "
658 "status=%s", notit, notit->btr,
50842bdc
PP
659 bt_btr_status_string(btr_status));
660 status = BT_NOTIF_ITER_STATUS_ERROR;
e98a2d6e
PP
661 goto end;
662 }
663
78586d8a 664 /* Consume bits now since we know we're not in an error state. */
e98a2d6e 665 buf_consume_bits(notit, consumed_bits);
e98a2d6e
PP
666end:
667 return status;
668}
669
670static
312c056a 671void release_event_dscopes(struct bt_notif_iter *notit)
e98a2d6e 672{
312c056a
PP
673 notit->dscopes.stream_event_header = NULL;
674
675 if (notit->event_header_field) {
676 bt_event_header_field_release(notit->event_header_field);
677 notit->event_header_field = NULL;
678 }
679
680 notit->dscopes.stream_event_context = NULL;
681 notit->dscopes.event_context = NULL;
682 notit->dscopes.event_payload = NULL;
e98a2d6e
PP
683}
684
685static
312c056a 686void release_all_dscopes(struct bt_notif_iter *notit)
e98a2d6e 687{
312c056a
PP
688 notit->dscopes.trace_packet_header = NULL;
689
690 if (notit->packet_header_field) {
691 bt_packet_header_field_release(notit->packet_header_field);
692 notit->packet_header_field = NULL;
693 }
694
695 notit->dscopes.stream_packet_context = NULL;
696
697 if (notit->packet_context_field) {
698 bt_packet_context_field_release(notit->packet_context_field);
699 notit->packet_context_field = NULL;
700 }
701
702 release_event_dscopes(notit);
e98a2d6e
PP
703}
704
705static
50842bdc
PP
706enum bt_notif_iter_status read_packet_header_begin_state(
707 struct bt_notif_iter *notit)
e98a2d6e 708{
50842bdc
PP
709 struct bt_field_type *packet_header_type = NULL;
710 enum bt_notif_iter_status ret = BT_NOTIF_ITER_STATUS_OK;
e98a2d6e 711
50842bdc 712 if (bt_notif_iter_switch_packet(notit)) {
fdf0e7a0 713 BT_LOGW("Cannot switch packet: notit-addr=%p", notit);
50842bdc 714 ret = BT_NOTIF_ITER_STATUS_ERROR;
2cf1d51e
JG
715 goto end;
716 }
e98a2d6e 717
2cf1d51e 718 /* Packet header type is common to the whole trace. */
d1e46835 719 packet_header_type = bt_trace_borrow_packet_header_field_type(
78586d8a 720 notit->meta.trace);
e98a2d6e 721 if (!packet_header_type) {
835b2d10 722 notit->state = STATE_AFTER_TRACE_PACKET_HEADER;
e98a2d6e
PP
723 goto end;
724 }
725
312c056a
PP
726 /*
727 * Create free packet header field from trace. This field is
728 * going to be moved to the packet once we create it. We cannot
729 * create the packet now because:
730 *
731 * 1. A packet is created from a stream.
732 * 2. A stream is created from a stream class.
733 * 3. We need the packet header field's content to know the ID
734 * of the stream class to select.
735 */
736 BT_ASSERT(!notit->packet_header_field);
737 notit->packet_header_field = bt_trace_create_packet_header_field(
738 notit->meta.trace);
739 if (!notit->packet_header_field) {
740 BT_LOGE_STR("Cannot create packet header field wrapper from trace.");
741 ret = BT_NOTIF_ITER_STATUS_ERROR;
742 goto end;
743 }
744
745 notit->dscopes.trace_packet_header =
746 bt_packet_header_field_borrow_field(notit->packet_header_field);
747 BT_ASSERT(notit->dscopes.trace_packet_header);
fdf0e7a0
PP
748 BT_LOGV("Decoding packet header field:"
749 "notit-addr=%p, trace-addr=%p, trace-name=\"%s\", ft-addr=%p",
750 notit, notit->meta.trace,
50842bdc 751 bt_trace_get_name(notit->meta.trace), packet_header_type);
2cf1d51e 752 ret = read_dscope_begin_state(notit, packet_header_type,
fdf0e7a0
PP
753 STATE_AFTER_TRACE_PACKET_HEADER,
754 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
312c056a 755 notit->dscopes.trace_packet_header);
fdf0e7a0
PP
756 if (ret < 0) {
757 BT_LOGW("Cannot decode packet header field: "
758 "notit-addr=%p, trace-addr=%p, "
759 "trace-name=\"%s\", ft-addr=%p",
760 notit, notit->meta.trace,
50842bdc 761 bt_trace_get_name(notit->meta.trace),
fdf0e7a0
PP
762 packet_header_type);
763 }
d1e46835 764
e98a2d6e 765end:
2cf1d51e 766 return ret;
e98a2d6e
PP
767}
768
769static
50842bdc
PP
770enum bt_notif_iter_status read_packet_header_continue_state(
771 struct bt_notif_iter *notit)
e98a2d6e
PP
772{
773 return read_dscope_continue_state(notit,
78586d8a 774 STATE_AFTER_TRACE_PACKET_HEADER);
e98a2d6e
PP
775}
776
5f870343
JG
777static
778struct stream_class_field_path_cache *
779create_stream_class_field_path_cache_entry(
50842bdc
PP
780 struct bt_notif_iter *notit,
781 struct bt_stream_class *stream_class)
5f870343
JG
782{
783 int v = -1;
784 int id = -1;
785 int timestamp_end = -1;
786 int packet_size = -1;
787 int content_size = -1;
788 struct stream_class_field_path_cache *cache_entry = g_new0(
789 struct stream_class_field_path_cache, 1);
50842bdc 790 struct bt_field_type *event_header = NULL, *packet_context = NULL;
5f870343
JG
791
792 if (!cache_entry) {
fdf0e7a0 793 BT_LOGE_STR("Failed to allocate one stream class field path cache.");
5f870343
JG
794 goto end;
795 }
796
d1e46835
PP
797 event_header = bt_stream_class_borrow_event_header_field_type(
798 stream_class);
50842bdc 799 if (event_header && bt_field_type_is_structure(event_header)) {
5f870343
JG
800 int i, count;
801
50842bdc 802 count = bt_field_type_structure_get_field_count(
fdf0e7a0 803 event_header);
f6ccaed9 804 BT_ASSERT(count >= 0);
fdf0e7a0 805
5f870343
JG
806 for (i = 0; i < count; i++) {
807 int ret;
808 const char *name;
809
d1e46835 810 ret = bt_field_type_structure_borrow_field_by_index(
5f870343
JG
811 event_header, &name, NULL, i);
812 if (ret) {
fdf0e7a0
PP
813 BT_LOGE("Cannot get event header structure field type's field: "
814 "notit-addr=%p, stream-class-addr=%p, "
815 "stream-class-name=\"%s\", "
816 "stream-class-id=%" PRId64 ", "
817 "ft-addr=%p, index=%d",
818 notit, stream_class,
50842bdc
PP
819 bt_stream_class_get_name(stream_class),
820 bt_stream_class_get_id(stream_class),
fdf0e7a0 821 event_header, i);
5f870343
JG
822 goto error;
823 }
824
825 if (v != -1 && id != -1) {
826 break;
827 }
fdf0e7a0
PP
828
829 if (v == -1 && strcmp(name, "v") == 0) {
5f870343
JG
830 v = i;
831 } else if (id == -1 && !strcmp(name, "id")) {
832 id = i;
833 }
834 }
835 }
836
d1e46835 837 packet_context = bt_stream_class_borrow_packet_context_field_type(
5f870343 838 stream_class);
50842bdc 839 if (packet_context && bt_field_type_is_structure(packet_context)) {
5f870343
JG
840 int i, count;
841
50842bdc 842 count = bt_field_type_structure_get_field_count(
fdf0e7a0 843 packet_context);
f6ccaed9 844 BT_ASSERT(count >= 0);
fdf0e7a0 845
5f870343
JG
846 for (i = 0; i < count; i++) {
847 int ret;
848 const char *name;
50842bdc 849 struct bt_field_type *field_type;
5f870343
JG
850
851 if (timestamp_end != -1 && packet_size != -1 &&
852 content_size != -1) {
853 break;
854 }
855
d1e46835 856 ret = bt_field_type_structure_borrow_field_by_index(
5f870343
JG
857 packet_context, &name, &field_type, i);
858 if (ret) {
fdf0e7a0
PP
859 BT_LOGE("Cannot get packet context structure field type's field: "
860 "notit-addr=%p, stream-class-addr=%p, "
861 "stream-class-name=\"%s\", "
862 "stream-class-id=%" PRId64 ", "
863 "ft-addr=%p, index=%d",
864 notit, stream_class,
50842bdc
PP
865 bt_stream_class_get_name(stream_class),
866 bt_stream_class_get_id(stream_class),
fdf0e7a0 867 event_header, i);
5f870343
JG
868 goto error;
869 }
870
871 if (timestamp_end == -1 &&
fdf0e7a0 872 strcmp(name, "timestamp_end") == 0) {
5f870343
JG
873 struct field_cb_override *override = g_new0(
874 struct field_cb_override, 1);
875
876 if (!override) {
5f870343
JG
877 goto error;
878 }
879
880 override->func = btr_timestamp_end_cb;
881 override->data = notit;
5f870343 882 g_hash_table_insert(notit->field_overrides,
d1e46835 883 field_type, override);
5f870343
JG
884 timestamp_end = i;
885 } else if (packet_size == -1 &&
886 !strcmp(name, "packet_size")) {
887 packet_size = i;
888 } else if (content_size == -1 &&
889 !strcmp(name, "content_size")) {
890 content_size = i;
891 }
5f870343
JG
892 }
893 }
894
895 cache_entry->v = v;
896 cache_entry->id = id;
897 cache_entry->timestamp_end = timestamp_end;
898 cache_entry->packet_size = packet_size;
899 cache_entry->content_size = content_size;
d1e46835 900
5f870343 901end:
5f870343 902 return cache_entry;
d1e46835 903
5f870343
JG
904error:
905 g_free(cache_entry);
906 cache_entry = NULL;
907 goto end;
908}
909
910static
911struct stream_class_field_path_cache *get_stream_class_field_path_cache(
50842bdc
PP
912 struct bt_notif_iter *notit,
913 struct bt_stream_class *stream_class)
5f870343
JG
914{
915 bool cache_entry_found;
916 struct stream_class_field_path_cache *cache_entry;
917
918 cache_entry_found = g_hash_table_lookup_extended(
919 notit->sc_field_path_caches,
920 stream_class, NULL, (gpointer) &cache_entry);
921 if (unlikely(!cache_entry_found)) {
922 cache_entry = create_stream_class_field_path_cache_entry(notit,
fdf0e7a0 923 stream_class);
5f870343 924 g_hash_table_insert(notit->sc_field_path_caches,
d1e46835 925 stream_class, (gpointer) cache_entry);
5f870343
JG
926 }
927
928 return cache_entry;
929}
930
e98a2d6e 931static inline
50842bdc
PP
932enum bt_notif_iter_status set_current_stream_class(
933 struct bt_notif_iter *notit)
e98a2d6e 934{
50842bdc
PP
935 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
936 struct bt_field_type *packet_header_type = NULL;
937 struct bt_field_type *stream_id_field_type = NULL;
938 struct bt_stream_class *new_stream_class = NULL;
e98a2d6e
PP
939 uint64_t stream_id;
940
5f870343
JG
941 /* Clear the current stream class field path cache. */
942 notit->cur_sc_field_path_cache = NULL;
943
e98a2d6e 944 /* Is there any "stream_id" field in the packet header? */
d1e46835 945 packet_header_type = bt_trace_borrow_packet_header_field_type(
fdf0e7a0 946 notit->meta.trace);
e98a2d6e 947 if (!packet_header_type) {
fdf0e7a0
PP
948 /*
949 * No packet header, therefore no `stream_id` field,
950 * therefore only one stream class.
951 */
952 goto single_stream_class;
e98a2d6e
PP
953 }
954
312c056a 955 BT_ASSERT(bt_field_type_is_structure(packet_header_type));
e98a2d6e
PP
956
957 // TODO: optimalize!
958 stream_id_field_type =
d1e46835 959 bt_field_type_structure_borrow_field_type_by_name(
fdf0e7a0 960 packet_header_type, "stream_id");
e98a2d6e
PP
961 if (stream_id_field_type) {
962 /* Find appropriate stream class using current stream ID */
e98a2d6e 963 int ret;
50842bdc 964 struct bt_field *stream_id_field = NULL;
e98a2d6e 965
f6ccaed9 966 BT_ASSERT(notit->dscopes.trace_packet_header);
e98a2d6e
PP
967
968 // TODO: optimalize!
312c056a 969 stream_id_field = bt_field_structure_borrow_field_by_name(
78586d8a 970 notit->dscopes.trace_packet_header, "stream_id");
f6ccaed9 971 BT_ASSERT(stream_id_field);
3dca2276 972 ret = bt_field_integer_unsigned_get_value(
78586d8a 973 stream_id_field, &stream_id);
f6ccaed9 974 BT_ASSERT(!ret);
e98a2d6e 975 } else {
fdf0e7a0 976single_stream_class:
e98a2d6e 977 /* Only one stream: pick the first stream class */
f6ccaed9 978 BT_ASSERT(bt_trace_get_stream_class_count(
78586d8a 979 notit->meta.trace) == 1);
e98a2d6e
PP
980 stream_id = 0;
981 }
982
fdf0e7a0
PP
983 BT_LOGV("Found stream class ID to use: notit-addr=%p, "
984 "stream-class-id=%" PRIu64 ", "
985 "trace-addr=%p, trace-name=\"%s\"",
986 notit, stream_id, notit->meta.trace,
50842bdc 987 bt_trace_get_name(notit->meta.trace));
fdf0e7a0 988
d1e46835 989 new_stream_class = bt_trace_borrow_stream_class_by_id(
fdf0e7a0 990 notit->meta.trace, stream_id);
115de887 991 if (!new_stream_class) {
fdf0e7a0
PP
992 BT_LOGW("No stream class with ID of stream class ID to use in trace: "
993 "notit-addr=%p, stream-class-id=%" PRIu64 ", "
994 "trace-addr=%p, trace-name=\"%s\"",
995 notit, stream_id, notit->meta.trace,
50842bdc
PP
996 bt_trace_get_name(notit->meta.trace));
997 status = BT_NOTIF_ITER_STATUS_ERROR;
e98a2d6e
PP
998 goto end;
999 }
1000
115de887
PP
1001 if (notit->meta.stream_class) {
1002 if (new_stream_class != notit->meta.stream_class) {
1003 BT_LOGW("Two packets refer to two different stream classes within the same packet sequence: "
1004 "notit-addr=%p, prev-stream-class-addr=%p, "
1005 "prev-stream-class-name=\"%s\", "
1006 "prev-stream-class-id=%" PRId64 ", "
1007 "next-stream-class-addr=%p, "
1008 "next-stream-class-name=\"%s\", "
1009 "next-stream-class-id=%" PRId64 ", "
1010 "trace-addr=%p, trace-name=\"%s\"",
1011 notit, notit->meta.stream_class,
50842bdc
PP
1012 bt_stream_class_get_name(notit->meta.stream_class),
1013 bt_stream_class_get_id(notit->meta.stream_class),
115de887 1014 new_stream_class,
50842bdc
PP
1015 bt_stream_class_get_name(new_stream_class),
1016 bt_stream_class_get_id(new_stream_class),
115de887 1017 notit->meta.trace,
50842bdc
PP
1018 bt_trace_get_name(notit->meta.trace));
1019 status = BT_NOTIF_ITER_STATUS_ERROR;
115de887
PP
1020 goto end;
1021 }
1022 } else {
d1e46835 1023 notit->meta.stream_class = new_stream_class;
115de887
PP
1024 }
1025
fdf0e7a0
PP
1026 BT_LOGV("Set current stream class: "
1027 "notit-addr=%p, stream-class-addr=%p, "
1028 "stream-class-name=\"%s\", stream-class-id=%" PRId64,
1029 notit, notit->meta.stream_class,
50842bdc
PP
1030 bt_stream_class_get_name(notit->meta.stream_class),
1031 bt_stream_class_get_id(notit->meta.stream_class));
fdf0e7a0 1032
5f870343
JG
1033 /*
1034 * Retrieve (or lazily create) the current stream class field path
1035 * cache.
1036 */
1037 notit->cur_sc_field_path_cache = get_stream_class_field_path_cache(
fdf0e7a0 1038 notit, notit->meta.stream_class);
5f870343 1039 if (!notit->cur_sc_field_path_cache) {
fdf0e7a0
PP
1040 BT_LOGW("Cannot retrieve stream class field path from cache: "
1041 "notit-addr=%p, stream-class-addr=%p, "
1042 "stream-class-name=\"%s\", stream-class-id=%" PRId64,
1043 notit, notit->meta.stream_class,
50842bdc
PP
1044 bt_stream_class_get_name(notit->meta.stream_class),
1045 bt_stream_class_get_id(notit->meta.stream_class));
1046 status = BT_NOTIF_ITER_STATUS_ERROR;
5f870343
JG
1047 goto end;
1048 }
d1e46835 1049
e98a2d6e 1050end:
e98a2d6e
PP
1051 return status;
1052}
1053
312c056a
PP
1054static inline
1055uint64_t get_cur_stream_instance_id(struct bt_notif_iter *notit)
1056{
1057 struct bt_field *stream_instance_id_field = NULL;
1058 uint64_t stream_instance_id = -1ULL;
1059 int ret;
1060
1061 if (!notit->dscopes.trace_packet_header) {
1062 goto end;
1063 }
1064
1065 stream_instance_id_field = bt_field_structure_borrow_field_by_name(
1066 notit->dscopes.trace_packet_header, "stream_instance_id");
1067 if (!stream_instance_id_field) {
1068 goto end;
1069 }
1070
1071 ret = bt_field_integer_unsigned_get_value(stream_instance_id_field,
1072 &stream_instance_id);
1073 if (ret) {
1074 stream_instance_id = -1ULL;
1075 goto end;
1076 }
1077
1078end:
1079 return stream_instance_id;
1080}
1081
1082static inline
1083enum bt_notif_iter_status set_current_stream(struct bt_notif_iter *notit)
1084{
1085 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
1086 struct bt_stream *stream = NULL;
1087
1088 BT_LOGV("Calling user function (get stream): notit-addr=%p, "
1089 "stream-class-addr=%p, stream-class-name=\"%s\", "
1090 "stream-class-id=%" PRId64,
1091 notit, notit->meta.stream_class,
1092 bt_stream_class_get_name(notit->meta.stream_class),
1093 bt_stream_class_get_id(notit->meta.stream_class));
1094 stream = bt_get(notit->medium.medops.borrow_stream(
1095 notit->meta.stream_class, get_cur_stream_instance_id(notit),
1096 notit->medium.data));
1097 BT_LOGV("User function returned: stream-addr=%p", stream);
1098 if (!stream) {
1099 BT_LOGW_STR("User function failed to return a stream object for the given stream class.");
1100 status = BT_NOTIF_ITER_STATUS_ERROR;
1101 goto end;
1102 }
1103
1104 if (notit->stream && stream != notit->stream) {
1105 BT_LOGW("User function returned a different stream than the previous one for the same sequence of packets.");
1106 status = BT_NOTIF_ITER_STATUS_ERROR;
1107 goto end;
1108 }
1109
1110 BT_MOVE(notit->stream, stream);
1111
1112end:
1113 bt_put(stream);
1114 return status;
1115}
1116
1117static inline
1118enum bt_notif_iter_status set_current_packet(struct bt_notif_iter *notit)
1119{
1120 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
1121 struct bt_packet *packet = NULL;
1122
1123 BT_LOGV("Creating packet for packet notification: "
1124 "notit-addr=%p", notit);
1125 BT_LOGV("Creating packet from stream: "
1126 "notit-addr=%p, stream-addr=%p, "
1127 "stream-class-addr=%p, "
1128 "stream-class-name=\"%s\", "
1129 "stream-class-id=%" PRId64,
1130 notit, notit->stream, notit->meta.stream_class,
1131 bt_stream_class_get_name(notit->meta.stream_class),
1132 bt_stream_class_get_id(notit->meta.stream_class));
1133
1134 /* Create packet */
1135 BT_ASSERT(notit->stream);
1136 packet = bt_packet_create(notit->stream);
1137 if (!packet) {
1138 BT_LOGE("Cannot create packet from stream: "
1139 "notit-addr=%p, stream-addr=%p, "
1140 "stream-class-addr=%p, "
1141 "stream-class-name=\"%s\", "
1142 "stream-class-id=%" PRId64,
1143 notit, notit->stream, notit->meta.stream_class,
1144 bt_stream_class_get_name(notit->meta.stream_class),
1145 bt_stream_class_get_id(notit->meta.stream_class));
1146 goto error;
1147 }
1148
1149 goto end;
1150
1151error:
1152 BT_PUT(packet);
1153 status = BT_NOTIF_ITER_STATUS_ERROR;
1154
1155end:
1156 BT_MOVE(notit->packet, packet);
1157 return status;
1158}
1159
e98a2d6e 1160static
50842bdc
PP
1161enum bt_notif_iter_status after_packet_header_state(
1162 struct bt_notif_iter *notit)
e98a2d6e 1163{
50842bdc 1164 enum bt_notif_iter_status status;
e98a2d6e
PP
1165
1166 status = set_current_stream_class(notit);
312c056a
PP
1167 if (status != BT_NOTIF_ITER_STATUS_OK) {
1168 goto end;
e98a2d6e
PP
1169 }
1170
312c056a
PP
1171 notit->state = STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN;
1172
1173end:
e98a2d6e
PP
1174 return status;
1175}
1176
1177static
50842bdc
PP
1178enum bt_notif_iter_status read_packet_context_begin_state(
1179 struct bt_notif_iter *notit)
e98a2d6e 1180{
50842bdc
PP
1181 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
1182 struct bt_field_type *packet_context_type;
e98a2d6e 1183
f6ccaed9 1184 BT_ASSERT(notit->meta.stream_class);
d1e46835 1185 packet_context_type = bt_stream_class_borrow_packet_context_field_type(
fdf0e7a0 1186 notit->meta.stream_class);
e98a2d6e 1187 if (!packet_context_type) {
fdf0e7a0
PP
1188 BT_LOGV("No packet packet context field type in stream class: continuing: "
1189 "notit-addr=%p, stream-class-addr=%p, "
1190 "stream-class-name=\"%s\", stream-class-id=%" PRId64,
1191 notit, notit->meta.stream_class,
50842bdc
PP
1192 bt_stream_class_get_name(notit->meta.stream_class),
1193 bt_stream_class_get_id(notit->meta.stream_class));
835b2d10 1194 notit->state = STATE_AFTER_STREAM_PACKET_CONTEXT;
e98a2d6e
PP
1195 goto end;
1196 }
1197
312c056a
PP
1198 /*
1199 * Create free packet context field from stream class. This
1200 * field is going to be moved to the packet once we create it.
1201 * We cannot create the packet now because a packet is created
1202 * from a stream, and this API must be able to return the packet
1203 * header and context fields without creating a stream
1204 * (bt_notif_iter_get_packet_header_context_fields()).
1205 */
1206 BT_ASSERT(!notit->packet_context_field);
1207 notit->packet_context_field =
1208 bt_stream_class_create_packet_context_field(
1209 notit->meta.stream_class);
1210 if (!notit->packet_context_field) {
1211 BT_LOGE_STR("Cannot create packet context field wrapper from stream class.");
1212 status = BT_NOTIF_ITER_STATUS_ERROR;
1213 goto end;
1214 }
1215
1216 notit->dscopes.stream_packet_context =
1217 bt_packet_context_field_borrow_field(notit->packet_context_field);
1218 BT_ASSERT(notit->dscopes.stream_packet_context);
fdf0e7a0
PP
1219 BT_LOGV("Decoding packet context field: "
1220 "notit-addr=%p, stream-class-addr=%p, "
1221 "stream-class-name=\"%s\", stream-class-id=%" PRId64 ", "
1222 "ft-addr=%p",
1223 notit, notit->meta.stream_class,
50842bdc
PP
1224 bt_stream_class_get_name(notit->meta.stream_class),
1225 bt_stream_class_get_id(notit->meta.stream_class),
fdf0e7a0 1226 packet_context_type);
e98a2d6e 1227 status = read_dscope_begin_state(notit, packet_context_type,
fdf0e7a0
PP
1228 STATE_AFTER_STREAM_PACKET_CONTEXT,
1229 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
312c056a 1230 notit->dscopes.stream_packet_context);
fdf0e7a0
PP
1231 if (status < 0) {
1232 BT_LOGW("Cannot decode packet context field: "
1233 "notit-addr=%p, stream-class-addr=%p, "
1234 "stream-class-name=\"%s\", "
1235 "stream-class-id=%" PRId64 ", ft-addr=%p",
1236 notit, notit->meta.stream_class,
50842bdc
PP
1237 bt_stream_class_get_name(notit->meta.stream_class),
1238 bt_stream_class_get_id(notit->meta.stream_class),
fdf0e7a0
PP
1239 packet_context_type);
1240 }
e98a2d6e
PP
1241
1242end:
e98a2d6e
PP
1243 return status;
1244}
1245
1246static
50842bdc
PP
1247enum bt_notif_iter_status read_packet_context_continue_state(
1248 struct bt_notif_iter *notit)
e98a2d6e
PP
1249{
1250 return read_dscope_continue_state(notit,
78586d8a 1251 STATE_AFTER_STREAM_PACKET_CONTEXT);
e98a2d6e
PP
1252}
1253
78586d8a 1254static
50842bdc
PP
1255enum bt_notif_iter_status set_current_packet_content_sizes(
1256 struct bt_notif_iter *notit)
e98a2d6e 1257{
50842bdc
PP
1258 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
1259 struct bt_field *packet_size_field = NULL;
1260 struct bt_field *content_size_field = NULL;
97755805 1261 uint64_t content_size = -1ULL, packet_size = -1ULL;
e98a2d6e 1262
89b08333
MD
1263 if (!notit->dscopes.stream_packet_context) {
1264 goto end;
1265 }
e98a2d6e 1266
312c056a 1267 packet_size_field = bt_field_structure_borrow_field_by_name(
fdf0e7a0 1268 notit->dscopes.stream_packet_context, "packet_size");
312c056a 1269 content_size_field = bt_field_structure_borrow_field_by_name(
fdf0e7a0 1270 notit->dscopes.stream_packet_context, "content_size");
e98a2d6e 1271 if (packet_size_field) {
3dca2276 1272 int ret = bt_field_integer_unsigned_get_value(
fdf0e7a0 1273 packet_size_field, &packet_size);
e98a2d6e 1274
f6ccaed9 1275 BT_ASSERT(ret == 0);
e98a2d6e 1276 if (packet_size == 0) {
fdf0e7a0
PP
1277 BT_LOGW("Invalid packet size: packet context field indicates packet size is zero: "
1278 "notit-addr=%p, packet-context-field-addr=%p",
1279 notit, notit->dscopes.stream_packet_context);
50842bdc 1280 status = BT_NOTIF_ITER_STATUS_ERROR;
e98a2d6e
PP
1281 goto end;
1282 } else if ((packet_size % 8) != 0) {
fdf0e7a0
PP
1283 BT_LOGW("Invalid packet size: packet context field indicates packet size is not a multiple of 8: "
1284 "notit-addr=%p, packet-context-field-addr=%p, "
1285 "packet-size=%" PRIu64,
1286 notit, notit->dscopes.stream_packet_context,
1287 packet_size);
50842bdc 1288 status = BT_NOTIF_ITER_STATUS_ERROR;
e98a2d6e
PP
1289 goto end;
1290 }
1291 }
78586d8a 1292
e98a2d6e 1293 if (content_size_field) {
3dca2276 1294 int ret = bt_field_integer_unsigned_get_value(
e98a2d6e 1295 content_size_field, &content_size);
78586d8a 1296
f6ccaed9 1297 BT_ASSERT(ret == 0);
e98a2d6e
PP
1298 } else {
1299 content_size = packet_size;
1300 }
1301
fdf0e7a0
PP
1302 if (content_size > packet_size) {
1303 BT_LOGW("Invalid packet or content size: packet context field indicates content size is greater than packet size: "
1304 "notit-addr=%p, packet-context-field-addr=%p, "
1305 "packet-size=%" PRIu64 ", content-size=%" PRIu64,
1306 notit, notit->dscopes.stream_packet_context,
1307 packet_size, content_size);
50842bdc 1308 status = BT_NOTIF_ITER_STATUS_ERROR;
fdf0e7a0
PP
1309 goto end;
1310 }
1311
97755805
MD
1312 if (packet_size != -1ULL) {
1313 notit->cur_packet_size = packet_size;
1314 } else {
1315 /*
1316 * Use the content size as packet size indicator if the
1317 * packet size field is missing. This means there is no
1318 * padding in this stream.
1319 */
1320 notit->cur_packet_size = content_size;
1321 }
e98a2d6e 1322 notit->cur_content_size = content_size;
fdf0e7a0
PP
1323 BT_LOGV("Set current packet and content sizes: "
1324 "notit-addr=%p, packet-size=%" PRIu64 ", content-size=%" PRIu64,
1325 notit, packet_size, content_size);
e98a2d6e 1326end:
e98a2d6e
PP
1327 return status;
1328}
1329
1330static
50842bdc
PP
1331enum bt_notif_iter_status after_packet_context_state(
1332 struct bt_notif_iter *notit)
e98a2d6e 1333{
50842bdc 1334 enum bt_notif_iter_status status;
e98a2d6e
PP
1335
1336 status = set_current_packet_content_sizes(notit);
50842bdc 1337 if (status == BT_NOTIF_ITER_STATUS_OK) {
f42867e2
PP
1338 if (notit->stream_begin_emitted) {
1339 notit->state = STATE_EMIT_NOTIF_NEW_PACKET;
1340 } else {
1341 notit->state = STATE_EMIT_NOTIF_NEW_STREAM;
1342 }
e98a2d6e
PP
1343 }
1344
1345 return status;
1346}
1347
1348static
50842bdc
PP
1349enum bt_notif_iter_status read_event_header_begin_state(
1350 struct bt_notif_iter *notit)
e98a2d6e 1351{
50842bdc
PP
1352 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
1353 struct bt_field_type *event_header_type = NULL;
e98a2d6e 1354
174e773b
PP
1355 /* Reset the position of the last event header */
1356 notit->buf.last_eh_at = notit->buf.at;
1357
e98a2d6e
PP
1358 /* Check if we have some content left */
1359 if (notit->cur_content_size >= 0) {
1360 if (packet_at(notit) == notit->cur_content_size) {
1361 /* No more events! */
fdf0e7a0
PP
1362 BT_LOGV("Reached end of packet: notit-addr=%p, "
1363 "cur=%zu", notit, packet_at(notit));
e98a2d6e
PP
1364 notit->state = STATE_EMIT_NOTIF_END_OF_PACKET;
1365 goto end;
1366 } else if (packet_at(notit) > notit->cur_content_size) {
1367 /* That's not supposed to happen */
fdf0e7a0 1368 BT_LOGV("Before decoding event header field: cursor is passed the packet's content: "
1974687e 1369 "notit-addr=%p, content-size=%" PRId64 ", "
fdf0e7a0
PP
1370 "cur=%zu", notit, notit->cur_content_size,
1371 packet_at(notit));
50842bdc 1372 status = BT_NOTIF_ITER_STATUS_ERROR;
e98a2d6e
PP
1373 goto end;
1374 }
1375 }
1376
312c056a
PP
1377 release_event_dscopes(notit);
1378 BT_ASSERT(notit->meta.stream_class);
d1e46835 1379 event_header_type = bt_stream_class_borrow_event_header_field_type(
e98a2d6e
PP
1380 notit->meta.stream_class);
1381 if (!event_header_type) {
835b2d10 1382 notit->state = STATE_AFTER_STREAM_EVENT_HEADER;
e98a2d6e
PP
1383 goto end;
1384 }
1385
312c056a
PP
1386 BT_ASSERT(!notit->event_header_field);
1387 notit->event_header_field = bt_stream_class_create_event_header_field(
1388 notit->meta.stream_class);
1389 if (!notit->event_header_field) {
1390 BT_LOGE_STR("Cannot create event header field wrapper from trace.");
1391 status = BT_NOTIF_ITER_STATUS_ERROR;
1392 goto end;
1393 }
1394
1395 notit->dscopes.stream_event_header =
1396 bt_event_header_field_borrow_field(notit->event_header_field);
1397 BT_ASSERT(notit->dscopes.stream_event_header);
fdf0e7a0
PP
1398 BT_LOGV("Decoding event header field: "
1399 "notit-addr=%p, stream-class-addr=%p, "
1400 "stream-class-name=\"%s\", stream-class-id=%" PRId64 ", "
1401 "ft-addr=%p",
1402 notit, notit->meta.stream_class,
50842bdc
PP
1403 bt_stream_class_get_name(notit->meta.stream_class),
1404 bt_stream_class_get_id(notit->meta.stream_class),
fdf0e7a0 1405 event_header_type);
e98a2d6e
PP
1406 status = read_dscope_begin_state(notit, event_header_type,
1407 STATE_AFTER_STREAM_EVENT_HEADER,
1408 STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE,
312c056a 1409 notit->dscopes.stream_event_header);
fdf0e7a0
PP
1410 if (status < 0) {
1411 BT_LOGW("Cannot decode event header field: "
1412 "notit-addr=%p, stream-class-addr=%p, "
1413 "stream-class-name=\"%s\", "
1414 "stream-class-id=%" PRId64 ", ft-addr=%p",
1415 notit, notit->meta.stream_class,
50842bdc
PP
1416 bt_stream_class_get_name(notit->meta.stream_class),
1417 bt_stream_class_get_id(notit->meta.stream_class),
fdf0e7a0
PP
1418 event_header_type);
1419 }
e98a2d6e 1420
d1e46835 1421end:
e98a2d6e
PP
1422 return status;
1423}
1424
1425static
50842bdc
PP
1426enum bt_notif_iter_status read_event_header_continue_state(
1427 struct bt_notif_iter *notit)
e98a2d6e
PP
1428{
1429 return read_dscope_continue_state(notit,
1430 STATE_AFTER_STREAM_EVENT_HEADER);
1431}
1432
1433static inline
50842bdc 1434enum bt_notif_iter_status set_current_event_class(struct bt_notif_iter *notit)
e98a2d6e
PP
1435{
1436 /*
1437 * The assert() calls in this function are okay because it is
1438 * assumed here that all the metadata objects have been
1439 * validated for CTF correctness before decoding actual streams.
1440 */
1441
50842bdc
PP
1442 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
1443 struct bt_field_type *event_header_type;
1444 struct bt_field_type *id_field_type = NULL;
1445 struct bt_field_type *v_field_type = NULL;
e98a2d6e
PP
1446 uint64_t event_id = -1ULL;
1447 int ret;
1448
d1e46835 1449 event_header_type = bt_stream_class_borrow_event_header_field_type(
e98a2d6e
PP
1450 notit->meta.stream_class);
1451 if (!event_header_type) {
fdf0e7a0
PP
1452 /*
1453 * No event header, therefore no event class ID field,
1454 * therefore only one event class.
1455 */
1456 goto single_event_class;
e98a2d6e
PP
1457 }
1458
1459 /* Is there any "id"/"v" field in the event header? */
312c056a 1460 BT_ASSERT(bt_field_type_is_structure(event_header_type));
d1e46835 1461 id_field_type = bt_field_type_structure_borrow_field_type_by_name(
e98a2d6e 1462 event_header_type, "id");
d1e46835 1463 v_field_type = bt_field_type_structure_borrow_field_type_by_name(
e98a2d6e 1464 event_header_type, "v");
f6ccaed9 1465 BT_ASSERT(notit->dscopes.stream_event_header);
e98a2d6e
PP
1466 if (v_field_type) {
1467 /*
1468 * _ _____ _____
1469 * | | |_ _|_ _| __ __ _
1470 * | | | | | || '_ \ / _` |
1471 * | |___| | | || | | | (_| | S P E C I A L
1472 * |_____|_| |_||_| |_|\__, | C A S E ™
1473 * |___/
1474 */
50842bdc
PP
1475 struct bt_field *v_field = NULL;
1476 struct bt_field *v_struct_field = NULL;
1477 struct bt_field *v_struct_id_field = NULL;
e98a2d6e
PP
1478
1479 // TODO: optimalize!
312c056a 1480 v_field = bt_field_structure_borrow_field_by_name(
e98a2d6e 1481 notit->dscopes.stream_event_header, "v");
f6ccaed9 1482 BT_ASSERT(v_field);
e98a2d6e
PP
1483
1484 v_struct_field =
312c056a 1485 bt_field_variant_borrow_current_field(v_field);
e98a2d6e
PP
1486 if (!v_struct_field) {
1487 goto end_v_field_type;
1488 }
1489
1490 // TODO: optimalize!
312c056a
PP
1491 v_struct_id_field = bt_field_structure_borrow_field_by_name(
1492 v_struct_field, "id");
e98a2d6e
PP
1493 if (!v_struct_id_field) {
1494 goto end_v_field_type;
1495 }
1496
50842bdc 1497 if (bt_field_is_integer(v_struct_id_field)) {
3dca2276 1498 ret = bt_field_integer_unsigned_get_value(
fdf0e7a0
PP
1499 v_struct_id_field, &event_id);
1500 if (ret) {
1501 BT_LOGV("Cannot get value of unsigned integer field (`id`): continuing: "
1502 "notit=%p, field-addr=%p",
1503 notit, v_struct_id_field);
1504 event_id = -1ULL;
1505 }
e98a2d6e 1506 }
e98a2d6e
PP
1507 }
1508
312c056a 1509end_v_field_type:
e98a2d6e
PP
1510 if (id_field_type && event_id == -1ULL) {
1511 /* Check "id" field */
50842bdc 1512 struct bt_field *id_field = NULL;
6606e9c1 1513 int ret_get_value = 0;
e98a2d6e
PP
1514
1515 // TODO: optimalize!
312c056a 1516 id_field = bt_field_structure_borrow_field_by_name(
e98a2d6e 1517 notit->dscopes.stream_event_header, "id");
fdf0e7a0
PP
1518 if (!id_field) {
1519 goto check_event_id;
1520 }
e98a2d6e 1521
312c056a
PP
1522 ret_get_value = bt_field_integer_unsigned_get_value(
1523 id_field, &event_id);
f6ccaed9 1524 BT_ASSERT(ret_get_value == 0);
e98a2d6e
PP
1525 }
1526
fdf0e7a0 1527check_event_id:
e98a2d6e 1528 if (event_id == -1ULL) {
fdf0e7a0 1529single_event_class:
e98a2d6e 1530 /* Event ID not found: single event? */
f6ccaed9 1531 BT_ASSERT(bt_stream_class_get_event_class_count(
e98a2d6e
PP
1532 notit->meta.stream_class) == 1);
1533 event_id = 0;
1534 }
1535
fdf0e7a0
PP
1536 BT_LOGV("Found event class ID to use: notit-addr=%p, "
1537 "stream-class-addr=%p, stream-class-name=\"%s\", "
1538 "stream-class-id=%" PRId64 ", "
1539 "event-class-id=%" PRIu64,
1540 notit, notit->meta.stream_class,
50842bdc
PP
1541 bt_stream_class_get_name(notit->meta.stream_class),
1542 bt_stream_class_get_id(notit->meta.stream_class),
fdf0e7a0 1543 event_id);
d1e46835 1544 notit->meta.event_class = bt_stream_class_borrow_event_class_by_id(
e98a2d6e
PP
1545 notit->meta.stream_class, event_id);
1546 if (!notit->meta.event_class) {
fdf0e7a0
PP
1547 BT_LOGW("No event class with ID of event class ID to use in stream class: "
1548 "notit-addr=%p, stream-class-addr=%p, "
1549 "stream-class-name=\"%s\", "
1550 "stream-class-id=%" PRId64 ", "
1551 "event-class-id=%" PRIu64,
1552 notit, notit->meta.stream_class,
50842bdc
PP
1553 bt_stream_class_get_name(notit->meta.stream_class),
1554 bt_stream_class_get_id(notit->meta.stream_class),
fdf0e7a0 1555 event_id);
50842bdc 1556 status = BT_NOTIF_ITER_STATUS_ERROR;
e98a2d6e
PP
1557 goto end;
1558 }
1559
fdf0e7a0
PP
1560 BT_LOGV("Set current event class: "
1561 "notit-addr=%p, event-class-addr=%p, "
1562 "event-class-name=\"%s\", event-class-id=%" PRId64,
1563 notit, notit->meta.event_class,
50842bdc
PP
1564 bt_event_class_get_name(notit->meta.event_class),
1565 bt_event_class_get_id(notit->meta.event_class));
fdf0e7a0 1566
e98a2d6e 1567end:
e98a2d6e
PP
1568 return status;
1569}
1570
312c056a
PP
1571static inline
1572enum bt_notif_iter_status set_current_event_notification(
1573 struct bt_notif_iter *notit)
1574{
1575 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
1576 struct bt_notification *notif = NULL;
1577
1578 BT_ASSERT(notit->meta.event_class);
1579 BT_ASSERT(notit->packet);
1580 BT_LOGV("Creating event notification from event class and packet: "
1581 "notit-addr=%p, ec-addr=%p, ec-name=\"%s\", packet-addr=%p",
1582 notit, notit->meta.event_class,
1583 bt_event_class_get_name(notit->meta.event_class),
1584 notit->packet);
1585 notif = bt_notification_event_create(notit->meta.event_class,
1586 notit->packet, notit->meta.cc_prio_map);
1587 if (!notif) {
1588 BT_LOGE("Cannot create event notification: "
1589 "notit-addr=%p, ec-addr=%p, ec-name=\"%s\", "
1590 "packet-addr=%p",
1591 notit, notit->meta.event_class,
1592 bt_event_class_get_name(notit->meta.event_class),
1593 notit->packet);
1594 goto error;
1595 }
1596
1597 goto end;
1598
1599error:
1600 BT_PUT(notif);
1601 status = BT_NOTIF_ITER_STATUS_ERROR;
1602
1603end:
1604 BT_MOVE(notit->event_notif, notif);
1605 return status;
1606}
1607
e98a2d6e 1608static
50842bdc
PP
1609enum bt_notif_iter_status after_event_header_state(
1610 struct bt_notif_iter *notit)
e98a2d6e 1611{
50842bdc 1612 enum bt_notif_iter_status status;
e98a2d6e 1613
e98a2d6e 1614 status = set_current_event_class(notit);
50842bdc 1615 if (status != BT_NOTIF_ITER_STATUS_OK) {
e98a2d6e
PP
1616 goto end;
1617 }
1618
312c056a
PP
1619 status = set_current_event_notification(notit);
1620 if (status != BT_NOTIF_ITER_STATUS_OK) {
1621 goto end;
1622 }
1623
1624 notit->event = bt_notification_event_borrow_event(notit->event_notif);
1625 BT_ASSERT(notit->event);
1626
1627 if (notit->event_header_field) {
1628 int ret;
1629
1630 BT_ASSERT(notit->event);
1631 ret = bt_event_move_header(notit->event,
1632 notit->event_header_field);
1633
1634 if (ret) {
1635 status = BT_NOTIF_ITER_STATUS_ERROR;
1636 goto end;
1637 }
1638
1639 notit->event_header_field = NULL;
1640
1641 /*
1642 * At this point notit->dscopes.stream_event_header has
1643 * the same value as the event header field within
1644 * notit->event.
1645 */
1646 BT_ASSERT(bt_event_borrow_header(notit->event) ==
1647 notit->dscopes.stream_event_header);
1648 }
1649
e98a2d6e
PP
1650 notit->state = STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN;
1651
1652end:
1653 return status;
1654}
1655
1656static
50842bdc
PP
1657enum bt_notif_iter_status read_stream_event_context_begin_state(
1658 struct bt_notif_iter *notit)
e98a2d6e 1659{
50842bdc
PP
1660 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
1661 struct bt_field_type *stream_event_context_type;
e98a2d6e 1662
3dca2276 1663 stream_event_context_type =
d1e46835 1664 bt_stream_class_borrow_event_context_field_type(
3dca2276 1665 notit->meta.stream_class);
e98a2d6e 1666 if (!stream_event_context_type) {
835b2d10 1667 notit->state = STATE_DSCOPE_EVENT_CONTEXT_BEGIN;
e98a2d6e
PP
1668 goto end;
1669 }
1670
312c056a
PP
1671 BT_ASSERT(!notit->dscopes.stream_event_context);
1672 notit->dscopes.stream_event_context =
1673 bt_event_borrow_stream_event_context(notit->event);
1674 BT_ASSERT(notit->dscopes.stream_event_context);
fdf0e7a0
PP
1675 BT_LOGV("Decoding stream event context field: "
1676 "notit-addr=%p, stream-class-addr=%p, "
1677 "stream-class-name=\"%s\", stream-class-id=%" PRId64 ", "
1678 "ft-addr=%p",
1679 notit, notit->meta.stream_class,
50842bdc
PP
1680 bt_stream_class_get_name(notit->meta.stream_class),
1681 bt_stream_class_get_id(notit->meta.stream_class),
fdf0e7a0 1682 stream_event_context_type);
e98a2d6e
PP
1683 status = read_dscope_begin_state(notit, stream_event_context_type,
1684 STATE_DSCOPE_EVENT_CONTEXT_BEGIN,
1685 STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE,
312c056a 1686 notit->dscopes.stream_event_context);
fdf0e7a0
PP
1687 if (status < 0) {
1688 BT_LOGW("Cannot decode stream event context field: "
1689 "notit-addr=%p, stream-class-addr=%p, "
1690 "stream-class-name=\"%s\", "
1691 "stream-class-id=%" PRId64 ", ft-addr=%p",
1692 notit, notit->meta.stream_class,
50842bdc
PP
1693 bt_stream_class_get_name(notit->meta.stream_class),
1694 bt_stream_class_get_id(notit->meta.stream_class),
fdf0e7a0
PP
1695 stream_event_context_type);
1696 }
e98a2d6e
PP
1697
1698end:
e98a2d6e
PP
1699 return status;
1700}
1701
1702static
50842bdc
PP
1703enum bt_notif_iter_status read_stream_event_context_continue_state(
1704 struct bt_notif_iter *notit)
e98a2d6e
PP
1705{
1706 return read_dscope_continue_state(notit,
1707 STATE_DSCOPE_EVENT_CONTEXT_BEGIN);
1708}
1709
1710static
50842bdc
PP
1711enum bt_notif_iter_status read_event_context_begin_state(
1712 struct bt_notif_iter *notit)
e98a2d6e 1713{
50842bdc
PP
1714 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
1715 struct bt_field_type *event_context_type;
e98a2d6e 1716
d1e46835 1717 event_context_type = bt_event_class_borrow_context_field_type(
e98a2d6e
PP
1718 notit->meta.event_class);
1719 if (!event_context_type) {
835b2d10 1720 notit->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN;
e98a2d6e
PP
1721 goto end;
1722 }
fdf0e7a0 1723
312c056a
PP
1724 BT_ASSERT(!notit->dscopes.event_context);
1725 notit->dscopes.event_context = bt_event_borrow_context(notit->event);
1726 BT_ASSERT(notit->dscopes.event_context);
fdf0e7a0
PP
1727 BT_LOGV("Decoding event context field: "
1728 "notit-addr=%p, event-class-addr=%p, "
1729 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
1730 "ft-addr=%p",
1731 notit, notit->meta.event_class,
50842bdc
PP
1732 bt_event_class_get_name(notit->meta.event_class),
1733 bt_event_class_get_id(notit->meta.event_class),
fdf0e7a0 1734 event_context_type);
e98a2d6e
PP
1735 status = read_dscope_begin_state(notit, event_context_type,
1736 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
1737 STATE_DSCOPE_EVENT_CONTEXT_CONTINUE,
312c056a 1738 notit->dscopes.event_context);
fdf0e7a0
PP
1739 if (status < 0) {
1740 BT_LOGW("Cannot decode event context field: "
1741 "notit-addr=%p, event-class-addr=%p, "
1742 "event-class-name=\"%s\", "
1743 "event-class-id=%" PRId64 ", ft-addr=%p",
1744 notit, notit->meta.event_class,
50842bdc
PP
1745 bt_event_class_get_name(notit->meta.event_class),
1746 bt_event_class_get_id(notit->meta.event_class),
fdf0e7a0
PP
1747 event_context_type);
1748 }
e98a2d6e
PP
1749
1750end:
e98a2d6e
PP
1751 return status;
1752}
1753
1754static
50842bdc
PP
1755enum bt_notif_iter_status read_event_context_continue_state(
1756 struct bt_notif_iter *notit)
e98a2d6e
PP
1757{
1758 return read_dscope_continue_state(notit,
1759 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN);
1760}
1761
1762static
50842bdc
PP
1763enum bt_notif_iter_status read_event_payload_begin_state(
1764 struct bt_notif_iter *notit)
e98a2d6e 1765{
50842bdc
PP
1766 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
1767 struct bt_field_type *event_payload_type;
e98a2d6e 1768
d1e46835 1769 event_payload_type = bt_event_class_borrow_payload_field_type(
e98a2d6e
PP
1770 notit->meta.event_class);
1771 if (!event_payload_type) {
835b2d10 1772 notit->state = STATE_EMIT_NOTIF_EVENT;
e98a2d6e
PP
1773 goto end;
1774 }
1775
312c056a
PP
1776 BT_ASSERT(!notit->dscopes.event_payload);
1777 notit->dscopes.event_payload = bt_event_borrow_payload(notit->event);
1778 BT_ASSERT(notit->dscopes.event_payload);
fdf0e7a0
PP
1779 BT_LOGV("Decoding event payload field: "
1780 "notit-addr=%p, event-class-addr=%p, "
1781 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
1782 "ft-addr=%p",
1783 notit, notit->meta.event_class,
50842bdc
PP
1784 bt_event_class_get_name(notit->meta.event_class),
1785 bt_event_class_get_id(notit->meta.event_class),
fdf0e7a0 1786 event_payload_type);
e98a2d6e
PP
1787 status = read_dscope_begin_state(notit, event_payload_type,
1788 STATE_EMIT_NOTIF_EVENT,
1789 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE,
312c056a 1790 notit->dscopes.event_payload);
fdf0e7a0
PP
1791 if (status < 0) {
1792 BT_LOGW("Cannot decode event payload field: "
1793 "notit-addr=%p, event-class-addr=%p, "
1794 "event-class-name=\"%s\", "
1795 "event-class-id=%" PRId64 ", ft-addr=%p",
1796 notit, notit->meta.event_class,
50842bdc
PP
1797 bt_event_class_get_name(notit->meta.event_class),
1798 bt_event_class_get_id(notit->meta.event_class),
fdf0e7a0
PP
1799 event_payload_type);
1800 }
e98a2d6e
PP
1801
1802end:
e98a2d6e
PP
1803 return status;
1804}
1805
1806static
50842bdc
PP
1807enum bt_notif_iter_status read_event_payload_continue_state(
1808 struct bt_notif_iter *notit)
e98a2d6e
PP
1809{
1810 return read_dscope_continue_state(notit, STATE_EMIT_NOTIF_EVENT);
1811}
1812
1813static
50842bdc
PP
1814enum bt_notif_iter_status skip_packet_padding_state(
1815 struct bt_notif_iter *notit)
e98a2d6e 1816{
50842bdc 1817 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
e98a2d6e
PP
1818 size_t bits_to_skip;
1819
f6ccaed9 1820 BT_ASSERT(notit->cur_packet_size > 0);
e98a2d6e
PP
1821 bits_to_skip = notit->cur_packet_size - packet_at(notit);
1822 if (bits_to_skip == 0) {
1823 notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
1824 goto end;
1825 } else {
1826 size_t bits_to_consume;
fdf0e7a0
PP
1827
1828 BT_LOGV("Trying to skip %zu bits of padding: notit-addr=%p, size=%zu",
1829 bits_to_skip, notit, bits_to_skip);
e98a2d6e 1830 status = buf_ensure_available_bits(notit);
50842bdc 1831 if (status != BT_NOTIF_ITER_STATUS_OK) {
e98a2d6e
PP
1832 goto end;
1833 }
1834
1835 bits_to_consume = MIN(buf_available_bits(notit), bits_to_skip);
fdf0e7a0
PP
1836 BT_LOGV("Skipping %zu bits of padding: notit-addr=%p, size=%zu",
1837 bits_to_consume, notit, bits_to_consume);
e98a2d6e
PP
1838 buf_consume_bits(notit, bits_to_consume);
1839 bits_to_skip = notit->cur_packet_size - packet_at(notit);
1840 if (bits_to_skip == 0) {
1841 notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
1842 goto end;
1843 }
1844 }
1845
1846end:
1847 return status;
1848}
1849
1850static inline
50842bdc 1851enum bt_notif_iter_status handle_state(struct bt_notif_iter *notit)
e98a2d6e 1852{
50842bdc 1853 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
fdf0e7a0 1854 const enum state state = notit->state;
e98a2d6e 1855
fdf0e7a0
PP
1856 BT_LOGV("Handling state: notit-addr=%p, state=%s",
1857 notit, state_string(state));
e98a2d6e
PP
1858
1859 // TODO: optimalize!
fdf0e7a0 1860 switch (state) {
e98a2d6e
PP
1861 case STATE_INIT:
1862 notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
1863 break;
1864 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN:
1865 status = read_packet_header_begin_state(notit);
1866 break;
1867 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE:
1868 status = read_packet_header_continue_state(notit);
1869 break;
1870 case STATE_AFTER_TRACE_PACKET_HEADER:
1871 status = after_packet_header_state(notit);
1872 break;
1873 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN:
1874 status = read_packet_context_begin_state(notit);
1875 break;
1876 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE:
1877 status = read_packet_context_continue_state(notit);
1878 break;
1879 case STATE_AFTER_STREAM_PACKET_CONTEXT:
1880 status = after_packet_context_state(notit);
1881 break;
f42867e2
PP
1882 case STATE_EMIT_NOTIF_NEW_STREAM:
1883 notit->state = STATE_EMIT_NOTIF_NEW_PACKET;
1884 break;
e98a2d6e
PP
1885 case STATE_EMIT_NOTIF_NEW_PACKET:
1886 notit->state = STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN;
1887 break;
1888 case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN:
1889 status = read_event_header_begin_state(notit);
1890 break;
1891 case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE:
1892 status = read_event_header_continue_state(notit);
1893 break;
1894 case STATE_AFTER_STREAM_EVENT_HEADER:
1895 status = after_event_header_state(notit);
1896 break;
1897 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN:
1898 status = read_stream_event_context_begin_state(notit);
1899 break;
1900 case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE:
1901 status = read_stream_event_context_continue_state(notit);
1902 break;
1903 case STATE_DSCOPE_EVENT_CONTEXT_BEGIN:
1904 status = read_event_context_begin_state(notit);
1905 break;
1906 case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE:
1907 status = read_event_context_continue_state(notit);
1908 break;
1909 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN:
1910 status = read_event_payload_begin_state(notit);
1911 break;
1912 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE:
1913 status = read_event_payload_continue_state(notit);
1914 break;
1915 case STATE_EMIT_NOTIF_EVENT:
1916 notit->state = STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN;
1917 break;
1918 case STATE_SKIP_PACKET_PADDING:
1919 status = skip_packet_padding_state(notit);
1920 break;
1921 case STATE_EMIT_NOTIF_END_OF_PACKET:
1922 notit->state = STATE_SKIP_PACKET_PADDING;
1923 break;
fdf0e7a0
PP
1924 default:
1925 BT_LOGD("Unknown CTF plugin notification iterator state: "
1926 "notit-addr=%p, state=%d", notit, notit->state);
1927 abort();
e98a2d6e
PP
1928 }
1929
fdf0e7a0
PP
1930 BT_LOGV("Handled state: notit-addr=%p, status=%s, "
1931 "prev-state=%s, cur-state=%s",
50842bdc 1932 notit, bt_notif_iter_status_string(status),
fdf0e7a0 1933 state_string(state), state_string(notit->state));
e98a2d6e
PP
1934 return status;
1935}
1936
2cf1d51e
JG
1937/**
1938 * Resets the internal state of a CTF notification iterator.
2cf1d51e 1939 */
f42867e2 1940BT_HIDDEN
50842bdc 1941void bt_notif_iter_reset(struct bt_notif_iter *notit)
e98a2d6e 1942{
f6ccaed9 1943 BT_ASSERT(notit);
fdf0e7a0 1944 BT_LOGD("Resetting notification iterator: addr=%p", notit);
e98a2d6e 1945 stack_clear(notit->stack);
d1e46835
PP
1946 notit->meta.stream_class = NULL;
1947 notit->meta.event_class = NULL;
e98a2d6e 1948 BT_PUT(notit->packet);
af87daef 1949 BT_PUT(notit->stream);
312c056a
PP
1950 BT_PUT(notit->event_notif);
1951 release_all_dscopes(notit);
1952 notit->cur_dscope_field = NULL;
1953
1954 if (notit->packet_header_field) {
1955 bt_packet_header_field_release(notit->packet_header_field);
1956 notit->packet_header_field = NULL;
1957 }
1958
1959 if (notit->packet_context_field) {
1960 bt_packet_context_field_release(notit->packet_context_field);
1961 notit->packet_context_field = NULL;
1962 }
1963
1964 if (notit->event_header_field) {
1965 bt_event_header_field_release(notit->event_header_field);
1966 notit->event_header_field = NULL;
1967 }
1968
e98a2d6e
PP
1969 notit->buf.addr = NULL;
1970 notit->buf.sz = 0;
1971 notit->buf.at = 0;
2b186c3e 1972 notit->buf.last_eh_at = SIZE_MAX;
e98a2d6e
PP
1973 notit->buf.packet_offset = 0;
1974 notit->state = STATE_INIT;
1975 notit->cur_content_size = -1;
1976 notit->cur_packet_size = -1;
9e0c8dbb 1977 notit->cur_packet_offset = -1;
f42867e2 1978 notit->stream_begin_emitted = false;
312c056a 1979 notit->cur_timestamp_end = NULL;
e98a2d6e
PP
1980}
1981
2cf1d51e 1982static
50842bdc 1983int bt_notif_iter_switch_packet(struct bt_notif_iter *notit)
2cf1d51e
JG
1984{
1985 int ret = 0;
1986
115de887
PP
1987 /*
1988 * We don't put the stream class here because we need to make
1989 * sure that all the packets processed by the same notification
1990 * iterator refer to the same stream class (the first one).
1991 */
f6ccaed9 1992 BT_ASSERT(notit);
312c056a 1993
9e0c8dbb
JG
1994 if (notit->cur_packet_size != -1) {
1995 notit->cur_packet_offset += notit->cur_packet_size;
1996 }
312c056a 1997
9e0c8dbb
JG
1998 BT_LOGV("Switching packet: notit-addr=%p, cur=%zu, "
1999 "packet-offset=%" PRId64, notit, notit->buf.at,
2000 notit->cur_packet_offset);
2cf1d51e 2001 stack_clear(notit->stack);
d1e46835 2002 notit->meta.event_class = NULL;
2cf1d51e 2003 BT_PUT(notit->packet);
312c056a
PP
2004 BT_PUT(notit->event_notif);
2005 notit->cur_timestamp_end = NULL;
2006 release_all_dscopes(notit);
2007 notit->cur_dscope_field = NULL;
2cf1d51e
JG
2008
2009 /*
2010 * Adjust current buffer so that addr points to the beginning of the new
2011 * packet.
2012 */
2013 if (notit->buf.addr) {
2014 size_t consumed_bytes = (size_t) (notit->buf.at / CHAR_BIT);
2015
2016 /* Packets are assumed to start on a byte frontier. */
2017 if (notit->buf.at % CHAR_BIT) {
fdf0e7a0
PP
2018 BT_LOGW("Cannot switch packet: current position is not a multiple of 8: "
2019 "notit-addr=%p, cur=%zu", notit, notit->buf.at);
2cf1d51e
JG
2020 ret = -1;
2021 goto end;
2022 }
2023
2024 notit->buf.addr += consumed_bytes;
2025 notit->buf.sz -= consumed_bytes;
2026 notit->buf.at = 0;
2027 notit->buf.packet_offset = 0;
fdf0e7a0
PP
2028 BT_LOGV("Adjusted buffer: addr=%p, size=%zu",
2029 notit->buf.addr, notit->buf.sz);
2cf1d51e
JG
2030 }
2031
2032 notit->cur_content_size = -1;
2033 notit->cur_packet_size = -1;
5f870343 2034 notit->cur_sc_field_path_cache = NULL;
fdf0e7a0 2035
2cf1d51e
JG
2036end:
2037 return ret;
2038}
2039
e98a2d6e 2040static
312c056a 2041struct bt_field *borrow_next_field(struct bt_notif_iter *notit)
e98a2d6e 2042{
50842bdc
PP
2043 struct bt_field *next_field = NULL;
2044 struct bt_field *base_field;
2045 struct bt_field_type *base_type;
e98a2d6e
PP
2046 size_t index;
2047
f6ccaed9 2048 BT_ASSERT(!stack_empty(notit->stack));
e98a2d6e
PP
2049 index = stack_top(notit->stack)->index;
2050 base_field = stack_top(notit->stack)->base;
f6ccaed9 2051 BT_ASSERT(base_field);
d1e46835 2052 base_type = bt_field_borrow_type(base_field);
f6ccaed9 2053 BT_ASSERT(base_type);
e98a2d6e 2054
50842bdc
PP
2055 switch (bt_field_type_get_type_id(base_type)) {
2056 case BT_FIELD_TYPE_ID_STRUCT:
f42867e2 2057 {
312c056a 2058 next_field = bt_field_structure_borrow_field_by_index(
e98a2d6e
PP
2059 base_field, index);
2060 break;
f42867e2 2061 }
50842bdc 2062 case BT_FIELD_TYPE_ID_ARRAY:
312c056a 2063 next_field = bt_field_array_borrow_field(base_field, index);
e98a2d6e 2064 break;
50842bdc 2065 case BT_FIELD_TYPE_ID_SEQUENCE:
312c056a 2066 next_field = bt_field_sequence_borrow_field(base_field, index);
e98a2d6e 2067 break;
50842bdc 2068 case BT_FIELD_TYPE_ID_VARIANT:
312c056a 2069 next_field = bt_field_variant_borrow_current_field(base_field);
e98a2d6e
PP
2070 break;
2071 default:
fdf0e7a0
PP
2072 BT_LOGF("Unknown base field type ID: "
2073 "notit-addr=%p, ft-addr=%p, ft-id=%s",
2074 notit, base_type,
3dca2276 2075 bt_common_field_type_id_string(
50842bdc 2076 bt_field_type_get_type_id(base_type)));
0fbb9a9f 2077 abort();
e98a2d6e
PP
2078 }
2079
e98a2d6e
PP
2080 return next_field;
2081}
2082
c44c3e70 2083static
312c056a
PP
2084void update_clock_state(uint64_t *state, struct bt_field *value_field,
2085 struct bt_field_type *value_type)
c44c3e70 2086{
c44c3e70
JG
2087 uint64_t requested_new_value;
2088 uint64_t requested_new_value_mask;
2089 uint64_t cur_value_masked;
2090 int requested_new_value_size;
2091 int ret;
2092
f6ccaed9
PP
2093 BT_ASSERT(value_type);
2094 BT_ASSERT(bt_field_type_is_integer(value_type));
c44c3e70 2095 requested_new_value_size =
50842bdc 2096 bt_field_type_integer_get_size(value_type);
f6ccaed9 2097 BT_ASSERT(requested_new_value_size > 0);
3dca2276 2098 ret = bt_field_integer_unsigned_get_value(value_field,
c44c3e70 2099 &requested_new_value);
f6ccaed9 2100 BT_ASSERT(!ret);
c44c3e70
JG
2101
2102 /*
2103 * Special case for a 64-bit new value, which is the limit
2104 * of a clock value as of this version: overwrite the
2105 * current value directly.
2106 */
2107 if (requested_new_value_size == 64) {
2108 *state = requested_new_value;
2109 goto end;
2110 }
2111
2112 requested_new_value_mask = (1ULL << requested_new_value_size) - 1;
2113 cur_value_masked = *state & requested_new_value_mask;
2114
2115 if (requested_new_value < cur_value_masked) {
2116 /*
2117 * It looks like a wrap happened on the number of bits
2118 * of the requested new value. Assume that the clock
2119 * value wrapped only one time.
2120 */
2121 *state += requested_new_value_mask + 1;
2122 }
2123
2124 /* Clear the low bits of the current clock value. */
2125 *state &= ~requested_new_value_mask;
2126
2127 /* Set the low bits of the current clock value. */
2128 *state |= requested_new_value;
d1e46835 2129
c44c3e70 2130end:
fdf0e7a0
PP
2131 BT_LOGV("Updated clock's value from integer field's value: "
2132 "value=%" PRIu64, *state);
c44c3e70
JG
2133}
2134
2135static
50842bdc
PP
2136enum bt_btr_status update_clock(struct bt_notif_iter *notit,
2137 struct bt_field *int_field)
c44c3e70 2138{
ac0c6bdd 2139 gboolean clock_class_found;
8cb1fb66 2140 uint64_t *clock_state = NULL;
50842bdc
PP
2141 struct bt_field_type *int_field_type = NULL;
2142 enum bt_btr_status ret = BT_BTR_STATUS_OK;
2143 struct bt_clock_class *clock_class = NULL;
c44c3e70 2144
d1e46835 2145 int_field_type = bt_field_borrow_type(int_field);
f6ccaed9 2146 BT_ASSERT(int_field_type);
312c056a
PP
2147
2148 if (bt_field_type_is_enumeration(int_field_type)) {
2149 int_field_type =
2150 bt_field_type_enumeration_borrow_container_field_type(
2151 int_field_type);
2152 }
2153
d1e46835 2154 clock_class = bt_field_type_integer_borrow_mapped_clock_class(
f45bfe88 2155 int_field_type);
ac0c6bdd 2156 if (likely(!clock_class)) {
f45bfe88 2157 goto end;
c44c3e70
JG
2158 }
2159
ac0c6bdd 2160 clock_class_found = g_hash_table_lookup_extended(notit->clock_states,
fdf0e7a0 2161 clock_class, NULL, (gpointer) &clock_state);
8cb1fb66 2162 if (!clock_class_found) {
c44c3e70
JG
2163 clock_state = g_new0(uint64_t, 1);
2164 if (!clock_state) {
fdf0e7a0 2165 BT_LOGE_STR("Failed to allocate a uint64_t.");
50842bdc 2166 ret = BT_BTR_STATUS_ENOMEM;
c44c3e70
JG
2167 goto end;
2168 }
fdf0e7a0 2169
d1e46835 2170 g_hash_table_insert(notit->clock_states, clock_class,
fdf0e7a0 2171 clock_state);
c44c3e70
JG
2172 }
2173
2174 /* Update the clock's state. */
fdf0e7a0
PP
2175 BT_LOGV("Updating notification iterator's clock's value from integer field: "
2176 "notit-addr=%p, clock-class-addr=%p, "
2177 "clock-class-name=\"%s\", value=%" PRIu64,
2178 notit, clock_class,
50842bdc 2179 bt_clock_class_get_name(clock_class), *clock_state);
312c056a 2180 update_clock_state(clock_state, int_field, int_field_type);
d1e46835 2181
c44c3e70 2182end:
c44c3e70
JG
2183 return ret;
2184}
2185
e98a2d6e 2186static
50842bdc
PP
2187enum bt_btr_status btr_unsigned_int_common(uint64_t value,
2188 struct bt_field_type *type, void *data,
312c056a 2189 struct bt_field **out_field)
50842bdc
PP
2190{
2191 enum bt_btr_status status = BT_BTR_STATUS_OK;
2192 struct bt_field *field = NULL;
50842bdc 2193 struct bt_notif_iter *notit = data;
e98a2d6e
PP
2194 int ret;
2195
fdf0e7a0
PP
2196 BT_LOGV("Common unsigned integer function called from BTR: "
2197 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2198 "ft-id=%s, value=%" PRIu64,
2199 notit, notit->btr, type,
3dca2276 2200 bt_common_field_type_id_string(
50842bdc 2201 bt_field_type_get_type_id(type)),
fdf0e7a0 2202 value);
312c056a 2203 field = borrow_next_field(notit);
e98a2d6e 2204 if (!field) {
312c056a 2205 BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
50842bdc 2206 status = BT_BTR_STATUS_ERROR;
312c056a 2207 goto end;
e98a2d6e
PP
2208 }
2209
312c056a
PP
2210 BT_ASSERT(bt_field_is_integer(field) || bt_field_is_enumeration(field));
2211 ret = bt_field_integer_unsigned_set_value(field, value);
f6ccaed9 2212 BT_ASSERT(ret == 0);
e98a2d6e 2213 stack_top(notit->stack)->index++;
312c056a 2214 *out_field = field;
fdf0e7a0 2215
312c056a 2216end:
e98a2d6e
PP
2217 return status;
2218}
2219
5f870343 2220static
50842bdc
PP
2221enum bt_btr_status btr_timestamp_end_cb(void *value,
2222 struct bt_field_type *type, void *data)
5f870343 2223{
50842bdc
PP
2224 enum bt_btr_status status;
2225 struct bt_field *field = NULL;
2226 struct bt_notif_iter *notit = data;
312c056a 2227 uint64_t uvalue = *((uint64_t *) value);
5f870343 2228
fdf0e7a0
PP
2229 BT_LOGV("`timestamp_end` unsigned integer function called from BTR: "
2230 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2231 "ft-id=%s",
2232 notit, notit->btr, type,
3dca2276 2233 bt_common_field_type_id_string(
50842bdc 2234 bt_field_type_get_type_id(type)));
5f870343 2235
312c056a
PP
2236 status = btr_unsigned_int_common(uvalue, type, data, &field);
2237
2238 /* Set as the current packet's end timestamp field */
2239 notit->cur_timestamp_end = field;
5f870343
JG
2240 return status;
2241}
2242
e98a2d6e 2243static
50842bdc
PP
2244enum bt_btr_status btr_unsigned_int_cb(uint64_t value,
2245 struct bt_field_type *type, void *data)
5f870343 2246{
50842bdc
PP
2247 struct bt_notif_iter *notit = data;
2248 enum bt_btr_status status = BT_BTR_STATUS_OK;
2249 struct bt_field *field = NULL;
5f870343
JG
2250 struct field_cb_override *override;
2251
fdf0e7a0
PP
2252 BT_LOGV("Unsigned integer function called from BTR: "
2253 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2254 "ft-id=%s, value=%" PRIu64,
2255 notit, notit->btr, type,
3dca2276 2256 bt_common_field_type_id_string(
50842bdc 2257 bt_field_type_get_type_id(type)),
fdf0e7a0
PP
2258 value);
2259 override = g_hash_table_lookup(notit->field_overrides, type);
5f870343 2260 if (unlikely(override)) {
fdf0e7a0 2261 /* Override function logs errors */
5f870343
JG
2262 status = override->func(&value, type, override->data);
2263 goto end;
2264 }
2265
2266 status = btr_unsigned_int_common(value, type, data, &field);
50842bdc 2267 if (status != BT_BTR_STATUS_OK) {
fdf0e7a0 2268 /* btr_unsigned_int_common() logs errors */
5f870343
JG
2269 goto end;
2270 }
2271
f45bfe88 2272 status = update_clock(notit, field);
312c056a 2273
5f870343
JG
2274end:
2275 return status;
2276}
2277
2278static
50842bdc
PP
2279enum bt_btr_status btr_signed_int_cb(int64_t value,
2280 struct bt_field_type *type, void *data)
e98a2d6e 2281{
50842bdc
PP
2282 enum bt_btr_status status = BT_BTR_STATUS_OK;
2283 struct bt_field *field = NULL;
50842bdc 2284 struct bt_notif_iter *notit = data;
e98a2d6e
PP
2285 int ret;
2286
fdf0e7a0
PP
2287 BT_LOGV("Signed integer function called from BTR: "
2288 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2289 "ft-id=%s, value=%" PRId64,
2290 notit, notit->btr, type,
3dca2276 2291 bt_common_field_type_id_string(
50842bdc 2292 bt_field_type_get_type_id(type)),
fdf0e7a0 2293 value);
312c056a 2294 field = borrow_next_field(notit);
e98a2d6e 2295 if (!field) {
312c056a 2296 BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
50842bdc 2297 status = BT_BTR_STATUS_ERROR;
312c056a 2298 goto end;
e98a2d6e
PP
2299 }
2300
312c056a
PP
2301 BT_ASSERT(bt_field_is_integer(field) || bt_field_is_enumeration(field));
2302 ret = bt_field_integer_signed_set_value(field, value);
2303 BT_ASSERT(ret == 0);
e98a2d6e 2304 stack_top(notit->stack)->index++;
fdf0e7a0 2305
312c056a 2306end:
e98a2d6e
PP
2307 return status;
2308}
2309
2310static
50842bdc
PP
2311enum bt_btr_status btr_floating_point_cb(double value,
2312 struct bt_field_type *type, void *data)
e98a2d6e 2313{
50842bdc
PP
2314 enum bt_btr_status status = BT_BTR_STATUS_OK;
2315 struct bt_field *field = NULL;
2316 struct bt_notif_iter *notit = data;
e98a2d6e
PP
2317 int ret;
2318
fdf0e7a0
PP
2319 BT_LOGV("Floating point number function called from BTR: "
2320 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2321 "ft-id=%s, value=%f",
2322 notit, notit->btr, type,
3dca2276 2323 bt_common_field_type_id_string(
50842bdc 2324 bt_field_type_get_type_id(type)),
fdf0e7a0 2325 value);
312c056a 2326 field = borrow_next_field(notit);
e98a2d6e 2327 if (!field) {
312c056a 2328 BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
50842bdc 2329 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
2330 goto end;
2331 }
2332
50842bdc 2333 ret = bt_field_floating_point_set_value(field, value);
f6ccaed9 2334 BT_ASSERT(!ret);
e98a2d6e
PP
2335 stack_top(notit->stack)->index++;
2336
2337end:
e98a2d6e
PP
2338 return status;
2339}
2340
2341static
50842bdc
PP
2342enum bt_btr_status btr_string_begin_cb(
2343 struct bt_field_type *type, void *data)
e98a2d6e 2344{
50842bdc
PP
2345 enum bt_btr_status status = BT_BTR_STATUS_OK;
2346 struct bt_field *field = NULL;
2347 struct bt_notif_iter *notit = data;
e98a2d6e
PP
2348 int ret;
2349
fdf0e7a0
PP
2350 BT_LOGV("String (beginning) function called from BTR: "
2351 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2352 "ft-id=%s",
2353 notit, notit->btr, type,
3dca2276 2354 bt_common_field_type_id_string(
50842bdc 2355 bt_field_type_get_type_id(type)));
312c056a 2356 field = borrow_next_field(notit);
e98a2d6e 2357 if (!field) {
fdf0e7a0 2358 BT_LOGW("Cannot get next field: notit-addr=%p", notit);
50842bdc 2359 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
2360 goto end;
2361 }
2362
312c056a
PP
2363 ret = bt_field_string_clear(field);
2364 BT_ASSERT(ret == 0);
2365
e98a2d6e
PP
2366 /*
2367 * Push on stack. Not a compound type per se, but we know that only
2368 * btr_string_cb() may be called between this call and a subsequent
2369 * call to btr_string_end_cb().
2370 */
2371 ret = stack_push(notit->stack, field);
2372 if (ret) {
fdf0e7a0
PP
2373 BT_LOGE("Cannot push string field on stack: "
2374 "notit-addr=%p, field-addr=%p", notit, field);
50842bdc 2375 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
2376 goto end;
2377 }
2378
2379end:
e98a2d6e
PP
2380 return status;
2381}
2382
2383static
50842bdc
PP
2384enum bt_btr_status btr_string_cb(const char *value,
2385 size_t len, struct bt_field_type *type, void *data)
e98a2d6e 2386{
50842bdc
PP
2387 enum bt_btr_status status = BT_BTR_STATUS_OK;
2388 struct bt_field *field = NULL;
2389 struct bt_notif_iter *notit = data;
e98a2d6e
PP
2390 int ret;
2391
fdf0e7a0
PP
2392 BT_LOGV("String (substring) function called from BTR: "
2393 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2394 "ft-id=%s, string-length=%zu",
2395 notit, notit->btr, type,
3dca2276 2396 bt_common_field_type_id_string(
50842bdc 2397 bt_field_type_get_type_id(type)),
fdf0e7a0 2398 len);
e98a2d6e 2399 field = stack_top(notit->stack)->base;
f6ccaed9 2400 BT_ASSERT(field);
e98a2d6e 2401
312c056a 2402 /* Append current substring */
50842bdc 2403 ret = bt_field_string_append_len(field, value, len);
e98a2d6e 2404 if (ret) {
fdf0e7a0
PP
2405 BT_LOGE("Cannot append substring to string field's value: "
2406 "notit-addr=%p, field-addr=%p, string-length=%zu, "
2407 "ret=%d", notit, field, len, ret);
50842bdc 2408 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
2409 goto end;
2410 }
2411
2412end:
2413 return status;
2414}
2415
2416static
50842bdc
PP
2417enum bt_btr_status btr_string_end_cb(
2418 struct bt_field_type *type, void *data)
e98a2d6e 2419{
50842bdc 2420 struct bt_notif_iter *notit = data;
e98a2d6e 2421
fdf0e7a0
PP
2422 BT_LOGV("String (end) function called from BTR: "
2423 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2424 "ft-id=%s",
2425 notit, notit->btr, type,
3dca2276 2426 bt_common_field_type_id_string(
50842bdc 2427 bt_field_type_get_type_id(type)));
fdf0e7a0 2428
e98a2d6e
PP
2429 /* Pop string field */
2430 stack_pop(notit->stack);
2431
2432 /* Go to next field */
2433 stack_top(notit->stack)->index++;
50842bdc 2434 return BT_BTR_STATUS_OK;
e98a2d6e
PP
2435}
2436
50842bdc
PP
2437enum bt_btr_status btr_compound_begin_cb(
2438 struct bt_field_type *type, void *data)
e98a2d6e 2439{
50842bdc
PP
2440 enum bt_btr_status status = BT_BTR_STATUS_OK;
2441 struct bt_notif_iter *notit = data;
2442 struct bt_field *field;
e98a2d6e
PP
2443 int ret;
2444
fdf0e7a0
PP
2445 BT_LOGV("Compound (beginning) function called from BTR: "
2446 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2447 "ft-id=%s",
2448 notit, notit->btr, type,
3dca2276 2449 bt_common_field_type_id_string(
50842bdc 2450 bt_field_type_get_type_id(type)));
fdf0e7a0 2451
312c056a 2452 /* Borrow field */
e98a2d6e 2453 if (stack_empty(notit->stack)) {
312c056a
PP
2454 /* Root: already set by read_dscope_begin_state() */
2455 field = notit->cur_dscope_field;
e98a2d6e 2456 } else {
312c056a 2457 field = borrow_next_field(notit);
fdf0e7a0 2458 if (!field) {
312c056a 2459 BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
50842bdc 2460 status = BT_BTR_STATUS_ERROR;
fdf0e7a0
PP
2461 goto end;
2462 }
e98a2d6e
PP
2463 }
2464
2465 /* Push field */
f6ccaed9 2466 BT_ASSERT(field);
e98a2d6e
PP
2467 ret = stack_push(notit->stack, field);
2468 if (ret) {
fdf0e7a0
PP
2469 BT_LOGE("Cannot push compound field onto the stack: "
2470 "notit-addr=%p, ft-addr=%p, ft-id=%s, ret=%d",
2471 notit, type,
3dca2276 2472 bt_common_field_type_id_string(
50842bdc 2473 bt_field_type_get_type_id(type)),
fdf0e7a0 2474 ret);
50842bdc 2475 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
2476 goto end;
2477 }
2478
2479end:
e98a2d6e
PP
2480 return status;
2481}
2482
50842bdc
PP
2483enum bt_btr_status btr_compound_end_cb(
2484 struct bt_field_type *type, void *data)
e98a2d6e 2485{
50842bdc 2486 struct bt_notif_iter *notit = data;
e98a2d6e 2487
fdf0e7a0
PP
2488 BT_LOGV("Compound (end) function called from BTR: "
2489 "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
2490 "ft-id=%s",
2491 notit, notit->btr, type,
3dca2276 2492 bt_common_field_type_id_string(
50842bdc 2493 bt_field_type_get_type_id(type)));
f6ccaed9 2494 BT_ASSERT(!stack_empty(notit->stack));
e98a2d6e
PP
2495
2496 /* Pop stack */
2497 stack_pop(notit->stack);
2498
2499 /* If the stack is not empty, increment the base's index */
2500 if (!stack_empty(notit->stack)) {
2501 stack_top(notit->stack)->index++;
2502 }
2503
50842bdc 2504 return BT_BTR_STATUS_OK;
e98a2d6e
PP
2505}
2506
2507static
50842bdc
PP
2508struct bt_field *resolve_field(struct bt_notif_iter *notit,
2509 struct bt_field_path *path)
e98a2d6e 2510{
50842bdc 2511 struct bt_field *field = NULL;
e98a2d6e
PP
2512 unsigned int i;
2513
fdf0e7a0 2514 if (BT_LOG_ON_VERBOSE) {
50842bdc 2515 GString *gstr = bt_field_path_string(path);
fdf0e7a0
PP
2516
2517 BT_LOGV("Resolving field path: notit-addr=%p, field-path=\"%s\"",
2518 notit, gstr ? gstr->str : NULL);
2519
2520 if (gstr) {
2521 g_string_free(gstr, TRUE);
2522 }
2523 }
2524
50842bdc
PP
2525 switch (bt_field_path_get_root_scope(path)) {
2526 case BT_SCOPE_TRACE_PACKET_HEADER:
e98a2d6e
PP
2527 field = notit->dscopes.trace_packet_header;
2528 break;
50842bdc 2529 case BT_SCOPE_STREAM_PACKET_CONTEXT:
e98a2d6e
PP
2530 field = notit->dscopes.stream_packet_context;
2531 break;
50842bdc 2532 case BT_SCOPE_STREAM_EVENT_HEADER:
e98a2d6e
PP
2533 field = notit->dscopes.stream_event_header;
2534 break;
50842bdc 2535 case BT_SCOPE_STREAM_EVENT_CONTEXT:
e98a2d6e
PP
2536 field = notit->dscopes.stream_event_context;
2537 break;
50842bdc 2538 case BT_SCOPE_EVENT_CONTEXT:
e98a2d6e
PP
2539 field = notit->dscopes.event_context;
2540 break;
50842bdc 2541 case BT_SCOPE_EVENT_FIELDS:
e98a2d6e
PP
2542 field = notit->dscopes.event_payload;
2543 break;
2544 default:
fdf0e7a0
PP
2545 BT_LOGF("Cannot resolve field path: unknown scope: "
2546 "notit-addr=%p, root-scope=%s",
3dca2276 2547 notit, bt_common_scope_string(
50842bdc 2548 bt_field_path_get_root_scope(path)));
fdf0e7a0 2549 abort();
e98a2d6e
PP
2550 }
2551
2552 if (!field) {
fdf0e7a0
PP
2553 BT_LOGW("Cannot resolve field path: root field not found: "
2554 "notit-addr=%p, root-scope=%s",
3dca2276 2555 notit, bt_common_scope_string(
50842bdc 2556 bt_field_path_get_root_scope(path)));
e98a2d6e
PP
2557 goto end;
2558 }
2559
50842bdc
PP
2560 for (i = 0; i < bt_field_path_get_index_count(path); ++i) {
2561 struct bt_field *next_field = NULL;
2562 struct bt_field_type *field_type;
2563 int index = bt_field_path_get_index(path, i);
e98a2d6e 2564
d1e46835 2565 field_type = bt_field_borrow_type(field);
f6ccaed9 2566 BT_ASSERT(field_type);
e98a2d6e 2567
312c056a
PP
2568 if (bt_field_type_is_structure(field_type)) {
2569 next_field = bt_field_structure_borrow_field_by_index(
e98a2d6e 2570 field, index);
312c056a 2571 } else if (bt_field_type_is_variant(field_type)) {
e98a2d6e 2572 next_field =
312c056a 2573 bt_field_variant_borrow_current_field(field);
e98a2d6e
PP
2574 }
2575
312c056a 2576 field = NULL;
e98a2d6e
PP
2577
2578 if (!next_field) {
fdf0e7a0
PP
2579 BT_LOGW("Cannot find next field: "
2580 "notit-addr=%p, ft-addr=%p, ft-id=%s, index=%d",
2581 notit, field_type,
3dca2276 2582 bt_common_field_type_id_string(
50842bdc 2583 bt_field_type_get_type_id(field_type)),
fdf0e7a0 2584 index);
e98a2d6e
PP
2585 goto end;
2586 }
2587
2588 /* Move next field -> field */
312c056a 2589 field = next_field;
e98a2d6e
PP
2590 }
2591
2592end:
2593 return field;
2594}
2595
2596static
50842bdc 2597int64_t btr_get_sequence_length_cb(struct bt_field_type *type, void *data)
e98a2d6e
PP
2598{
2599 int64_t ret = -1;
2600 int iret;
50842bdc
PP
2601 struct bt_field *seq_field;
2602 struct bt_field_path *field_path;
2603 struct bt_notif_iter *notit = data;
2604 struct bt_field *length_field = NULL;
e98a2d6e
PP
2605 uint64_t length;
2606
d1e46835 2607 field_path = bt_field_type_sequence_borrow_length_field_path(type);
f6ccaed9 2608 BT_ASSERT(field_path);
2cf1d51e
JG
2609 length_field = resolve_field(notit, field_path);
2610 if (!length_field) {
fdf0e7a0
PP
2611 BT_LOGW("Cannot resolve sequence field type's length field path: "
2612 "notit-addr=%p, ft-addr=%p",
2613 notit, type);
e98a2d6e
PP
2614 goto end;
2615 }
2616
3dca2276 2617 iret = bt_field_integer_unsigned_get_value(length_field, &length);
e98a2d6e 2618 if (iret) {
fdf0e7a0
PP
2619 BT_LOGE("Cannot get value of sequence length field: "
2620 "notit-addr=%p, field-addr=%p",
2621 notit, length_field);
e98a2d6e
PP
2622 goto end;
2623 }
2624
fdf0e7a0 2625 seq_field = stack_top(notit->stack)->base;
312c056a 2626 iret = bt_field_sequence_set_length(seq_field, length);
2cf1d51e 2627 if (iret) {
fdf0e7a0
PP
2628 BT_LOGE("Cannot set sequence field's length field: "
2629 "notit-addr=%p, seq-field-addr=%p, "
312c056a
PP
2630 "length=%" PRIu64,
2631 notit, seq_field, length);
2cf1d51e
JG
2632 goto end;
2633 }
fdf0e7a0 2634
e98a2d6e
PP
2635 ret = (int64_t) length;
2636
2637end:
e98a2d6e
PP
2638 return ret;
2639}
2640
2641static
5ae32b51 2642struct bt_field_type *btr_borrow_variant_field_type_cb(
50842bdc 2643 struct bt_field_type *type, void *data)
e98a2d6e 2644{
312c056a 2645 int ret;
50842bdc
PP
2646 struct bt_field_path *path;
2647 struct bt_notif_iter *notit = data;
2648 struct bt_field *var_field;
2649 struct bt_field *tag_field = NULL;
312c056a
PP
2650 struct bt_field_type *tag_ft = NULL;
2651 struct bt_field_type *tag_int_ft = NULL;
50842bdc
PP
2652 struct bt_field *selected_field = NULL;
2653 struct bt_field_type *selected_field_type = NULL;
e98a2d6e 2654
d1e46835 2655 path = bt_field_type_variant_borrow_tag_field_path(type);
f6ccaed9 2656 BT_ASSERT(path);
e98a2d6e
PP
2657 tag_field = resolve_field(notit, path);
2658 if (!tag_field) {
fdf0e7a0
PP
2659 BT_LOGW("Cannot resolve variant field type's tag field path: "
2660 "notit-addr=%p, ft-addr=%p",
2661 notit, type);
e98a2d6e
PP
2662 goto end;
2663 }
2664
2665 /*
2666 * We found the enumeration tag field instance which should be
2667 * able to select a current field for this variant. This
2668 * callback function we're in is called _after_
2669 * compound_begin(), so the current stack top's base field is
312c056a
PP
2670 * the variant field in question. We set the variant field's tag
2671 * here and then get the current (selected) field thanks to this
2672 * tag field's value. This current field will also provide us
2673 * with its type. Then, this current field will remain the
2674 * current selected one until the next callback function call
2675 * which is used to fill it.
e98a2d6e 2676 */
fdf0e7a0 2677 var_field = stack_top(notit->stack)->base;
312c056a
PP
2678 tag_ft = bt_field_borrow_type(tag_field);
2679 tag_int_ft = bt_field_type_enumeration_borrow_container_field_type(
2680 tag_ft);
2681
2682 if (bt_field_type_integer_is_signed(tag_int_ft)) {
2683 int64_t tag_value;
2684
2685 ret = bt_field_integer_signed_get_value(tag_field, &tag_value);
2686 BT_ASSERT(ret == 0);
2687 ret = bt_field_variant_set_tag_signed(var_field, tag_value);
2688 BT_ASSERT(ret == 0);
2689 } else {
2690 uint64_t tag_value;
2691
2692 ret = bt_field_integer_unsigned_get_value(tag_field,
2693 &tag_value);
2694 BT_ASSERT(ret == 0);
2695 ret = bt_field_variant_set_tag_unsigned(var_field, tag_value);
2696 BT_ASSERT(ret == 0);
2697 }
2698
2699 selected_field = bt_field_variant_borrow_current_field(var_field);
e98a2d6e 2700 if (!selected_field) {
312c056a
PP
2701 BT_LOGW("Cannot borrow variant field's current field: "
2702 "notit-addr=%p, var-field-addr=%p",
2703 notit, var_field);
e98a2d6e
PP
2704 goto end;
2705 }
2706
5ae32b51 2707 selected_field_type = bt_field_borrow_type(selected_field);
e98a2d6e
PP
2708
2709end:
e98a2d6e
PP
2710 return selected_field_type;
2711}
2712
1556a1af 2713static
312c056a 2714int set_event_clocks(struct bt_notif_iter *notit)
1556a1af
JG
2715{
2716 int ret;
2717 GHashTableIter iter;
50842bdc 2718 struct bt_clock_class *clock_class;
1556a1af
JG
2719 uint64_t *clock_state;
2720
2721 g_hash_table_iter_init(&iter, notit->clock_states);
2722
ac0c6bdd 2723 while (g_hash_table_iter_next(&iter, (gpointer) &clock_class,
312c056a 2724 (gpointer) &clock_state)) {
50842bdc 2725 struct bt_clock_value *clock_value;
1556a1af 2726
312c056a
PP
2727 clock_value = bt_event_borrow_clock_value(notit->event,
2728 clock_class);
1556a1af 2729 if (!clock_value) {
312c056a 2730 BT_LOGE("Cannot borrow clock value from event with given clock class: "
fdf0e7a0
PP
2731 "notit-addr=%p, clock-class-addr=%p, "
2732 "clock-class-name=\"%s\"",
2733 notit, clock_class,
50842bdc 2734 bt_clock_class_get_name(clock_class));
1556a1af
JG
2735 ret = -1;
2736 goto end;
2737 }
af87daef 2738
312c056a
PP
2739 ret = bt_clock_value_set_value(clock_value, *clock_state);
2740 BT_ASSERT(ret == 0);
af87daef
PP
2741 }
2742
312c056a 2743 ret = 0;
af87daef 2744end:
af87daef
PP
2745 return ret;
2746}
2747
f42867e2
PP
2748static
2749void notify_new_stream(struct bt_notif_iter *notit,
2750 struct bt_notification **notification)
2751{
312c056a 2752 enum bt_notif_iter_status status;
f42867e2 2753 struct bt_notification *ret = NULL;
f42867e2 2754
312c056a
PP
2755 status = set_current_stream(notit);
2756 if (status != BT_NOTIF_ITER_STATUS_OK) {
2757 BT_PUT(ret);
f42867e2
PP
2758 goto end;
2759 }
2760
2761 BT_ASSERT(notit->stream);
2762 ret = bt_notification_stream_begin_create(notit->stream);
2763 if (!ret) {
2764 BT_LOGE("Cannot create stream beginning notification: "
2765 "notit-addr=%p, stream-addr=%p",
2766 notit, notit->stream);
2767 return;
2768 }
2769
2770end:
2771 *notification = ret;
2772}
2773
2774static
2775void notify_end_of_stream(struct bt_notif_iter *notit,
2776 struct bt_notification **notification)
2777{
2778 struct bt_notification *ret;
2779
2780 if (!notit->stream) {
2781 BT_LOGE("Cannot create stream for stream notification: "
2782 "notit-addr=%p", notit);
2783 return;
2784 }
2785
2786 ret = bt_notification_stream_end_create(notit->stream);
2787 if (!ret) {
2788 BT_LOGE("Cannot create stream beginning notification: "
2789 "notit-addr=%p, stream-addr=%p",
2790 notit, notit->stream);
2791 return;
2792 }
2793 *notification = ret;
2794}
2795
78586d8a 2796static
50842bdc 2797void notify_new_packet(struct bt_notif_iter *notit,
78586d8a 2798 struct bt_notification **notification)
e98a2d6e 2799{
312c056a
PP
2800 int ret;
2801 enum bt_notif_iter_status status;
2802 struct bt_notification *notif = NULL;
e98a2d6e 2803
312c056a
PP
2804 status = set_current_packet(notit);
2805 if (status != BT_NOTIF_ITER_STATUS_OK) {
2806 goto end;
e98a2d6e
PP
2807 }
2808
312c056a
PP
2809 BT_ASSERT(notit->packet);
2810
2811 if (notit->packet_header_field) {
2812 ret = bt_packet_move_header(notit->packet,
2813 notit->packet_header_field);
2814 if (ret) {
2815 goto end;
2816 }
2817
2818 notit->packet_header_field = NULL;
2819
2820 /*
2821 * At this point notit->dscopes.trace_packet_header has
2822 * the same value as the packet header field within
2823 * notit->packet.
2824 */
2825 BT_ASSERT(bt_packet_borrow_header(notit->packet) ==
2826 notit->dscopes.trace_packet_header);
2827 }
2828
2829 if (notit->packet_context_field) {
2830 ret = bt_packet_move_context(notit->packet,
2831 notit->packet_context_field);
2832 if (ret) {
2833 goto end;
2834 }
2835
2836 notit->packet_context_field = NULL;
2837
2838 /*
2839 * At this point notit->dscopes.trace_packet_header has
2840 * the same value as the packet header field within
2841 * notit->packet.
2842 */
2843 BT_ASSERT(bt_packet_borrow_context(notit->packet) ==
2844 notit->dscopes.stream_packet_context);
2845 }
2846
2847 notif = bt_notification_packet_begin_create(notit->packet);
2848 if (!notif) {
fdf0e7a0
PP
2849 BT_LOGE("Cannot create packet beginning notification: "
2850 "notit-addr=%p, packet-addr=%p",
2851 notit, notit->packet);
78586d8a
JG
2852 return;
2853 }
312c056a
PP
2854
2855end:
2856 *notification = notif;
e98a2d6e
PP
2857}
2858
78586d8a 2859static
50842bdc 2860void notify_end_of_packet(struct bt_notif_iter *notit,
78586d8a 2861 struct bt_notification **notification)
e98a2d6e 2862{
312c056a 2863 struct bt_notification *notif;
e98a2d6e 2864
e98a2d6e 2865 if (!notit->packet) {
78586d8a 2866 return;
e98a2d6e
PP
2867 }
2868
312c056a
PP
2869 notif = bt_notification_packet_end_create(notit->packet);
2870 if (!notif) {
fdf0e7a0
PP
2871 BT_LOGE("Cannot create packet end notification: "
2872 "notit-addr=%p, packet-addr=%p",
2873 notit, notit->packet);
78586d8a
JG
2874 return;
2875 }
e98a2d6e 2876
312c056a
PP
2877 BT_PUT(notit->packet);
2878 *notification = notif;
e98a2d6e
PP
2879}
2880
5f870343 2881static
50842bdc 2882void init_trace_field_path_cache(struct bt_trace *trace,
5f870343
JG
2883 struct trace_field_path_cache *trace_field_path_cache)
2884{
2885 int stream_id = -1;
2886 int stream_instance_id = -1;
2887 int i, count;
50842bdc 2888 struct bt_field_type *packet_header = NULL;
5f870343 2889
d1e46835 2890 packet_header = bt_trace_borrow_packet_header_field_type(trace);
5f870343
JG
2891 if (!packet_header) {
2892 goto end;
2893 }
2894
50842bdc 2895 if (!bt_field_type_is_structure(packet_header)) {
5f870343
JG
2896 goto end;
2897 }
2898
50842bdc 2899 count = bt_field_type_structure_get_field_count(packet_header);
f6ccaed9 2900 BT_ASSERT(count >= 0);
5f870343
JG
2901
2902 for (i = 0; (i < count && (stream_id == -1 || stream_instance_id == -1)); i++) {
2903 int ret;
2904 const char *field_name;
2905
d1e46835
PP
2906 ret = bt_field_type_structure_borrow_field_by_index(
2907 packet_header, &field_name, NULL, i);
5f870343 2908 if (ret) {
fdf0e7a0
PP
2909 BT_LOGE("Cannot get structure field's field: "
2910 "field-addr=%p, index=%d",
2911 packet_header, i);
5f870343
JG
2912 goto end;
2913 }
2914
2915 if (stream_id == -1 && !strcmp(field_name, "stream_id")) {
2916 stream_id = i;
2917 } else if (stream_instance_id == -1 &&
2918 !strcmp(field_name, "stream_instance_id")) {
2919 stream_instance_id = i;
2920 }
2921 }
fdf0e7a0 2922
5f870343
JG
2923end:
2924 trace_field_path_cache->stream_id = stream_id;
2925 trace_field_path_cache->stream_instance_id = stream_instance_id;
5f870343
JG
2926}
2927
c44c3e70 2928BT_HIDDEN
50842bdc 2929struct bt_notif_iter *bt_notif_iter_create(struct bt_trace *trace,
e98a2d6e 2930 size_t max_request_sz,
50842bdc 2931 struct bt_notif_iter_medium_ops medops, void *data)
e98a2d6e 2932{
50842bdc
PP
2933 struct bt_notif_iter *notit = NULL;
2934 struct bt_btr_cbs cbs = {
e98a2d6e
PP
2935 .types = {
2936 .signed_int = btr_signed_int_cb,
2937 .unsigned_int = btr_unsigned_int_cb,
2938 .floating_point = btr_floating_point_cb,
2939 .string_begin = btr_string_begin_cb,
2940 .string = btr_string_cb,
2941 .string_end = btr_string_end_cb,
2942 .compound_begin = btr_compound_begin_cb,
2943 .compound_end = btr_compound_end_cb,
2944 },
2945 .query = {
2946 .get_sequence_length = btr_get_sequence_length_cb,
5ae32b51 2947 .borrow_variant_field_type = btr_borrow_variant_field_type_cb,
e98a2d6e
PP
2948 },
2949 };
2950
f6ccaed9
PP
2951 BT_ASSERT(trace);
2952 BT_ASSERT(medops.request_bytes);
312c056a 2953 BT_ASSERT(medops.borrow_stream);
fdf0e7a0
PP
2954 BT_LOGD("Creating CTF plugin notification iterator: "
2955 "trace-addr=%p, trace-name=\"%s\", max-request-size=%zu, "
2956 "data=%p",
50842bdc
PP
2957 trace, bt_trace_get_name(trace), max_request_sz, data);
2958 notit = g_new0(struct bt_notif_iter, 1);
e98a2d6e 2959 if (!notit) {
fdf0e7a0 2960 BT_LOGE_STR("Failed to allocate one CTF plugin notification iterator.");
e98a2d6e
PP
2961 goto end;
2962 }
c44c3e70 2963 notit->clock_states = g_hash_table_new_full(g_direct_hash,
d1e46835 2964 g_direct_equal, NULL, g_free);
c44c3e70 2965 if (!notit->clock_states) {
fdf0e7a0 2966 BT_LOGE_STR("Failed to allocate a GHashTable.");
c44c3e70
JG
2967 goto error;
2968 }
d1e46835 2969 notit->meta.trace = trace;
e98a2d6e
PP
2970 notit->medium.medops = medops;
2971 notit->medium.max_request_sz = max_request_sz;
2972 notit->medium.data = data;
e98a2d6e
PP
2973 notit->stack = stack_new(notit);
2974 if (!notit->stack) {
fdf0e7a0 2975 BT_LOGE_STR("Failed to create field stack.");
c44c3e70 2976 goto error;
e98a2d6e
PP
2977 }
2978
50842bdc 2979 notit->btr = bt_btr_create(cbs, notit);
e98a2d6e 2980 if (!notit->btr) {
fdf0e7a0 2981 BT_LOGE_STR("Failed to create binary type reader (BTR).");
c44c3e70 2982 goto error;
e98a2d6e
PP
2983 }
2984
50842bdc 2985 bt_notif_iter_reset(notit);
5f870343
JG
2986 init_trace_field_path_cache(trace, &notit->trace_field_path_cache);
2987 notit->sc_field_path_caches = g_hash_table_new_full(g_direct_hash,
d1e46835 2988 g_direct_equal, NULL, g_free);
5f870343 2989 if (!notit->sc_field_path_caches) {
fdf0e7a0 2990 BT_LOGE_STR("Failed to allocate a GHashTable.");
5f870343
JG
2991 goto error;
2992 }
2993
2994 notit->field_overrides = g_hash_table_new_full(g_direct_hash,
d1e46835 2995 g_direct_equal, NULL, g_free);
5f870343 2996 if (!notit->field_overrides) {
fdf0e7a0 2997 BT_LOGE_STR("Failed to allocate a GHashTable.");
5f870343
JG
2998 goto error;
2999 }
3000
fdf0e7a0
PP
3001 BT_LOGD("Created CTF plugin notification iterator: "
3002 "trace-addr=%p, trace-name=\"%s\", max-request-size=%zu, "
3003 "data=%p, notit-addr=%p",
50842bdc 3004 trace, bt_trace_get_name(trace), max_request_sz, data,
fdf0e7a0 3005 notit);
9e0c8dbb 3006 notit->cur_packet_offset = 0;
fdf0e7a0 3007
e98a2d6e
PP
3008end:
3009 return notit;
fdf0e7a0 3010
c44c3e70 3011error:
50842bdc 3012 bt_notif_iter_destroy(notit);
c44c3e70
JG
3013 notit = NULL;
3014 goto end;
e98a2d6e
PP
3015}
3016
50842bdc 3017void bt_notif_iter_destroy(struct bt_notif_iter *notit)
e98a2d6e 3018{
e98a2d6e 3019 BT_PUT(notit->packet);
af87daef 3020 BT_PUT(notit->stream);
312c056a
PP
3021 BT_PUT(notit->meta.cc_prio_map);
3022 release_all_dscopes(notit);
e98a2d6e 3023
fdf0e7a0
PP
3024 BT_LOGD("Destroying CTF plugin notification iterator: addr=%p", notit);
3025
e98a2d6e 3026 if (notit->stack) {
fdf0e7a0 3027 BT_LOGD_STR("Destroying field stack.");
e98a2d6e
PP
3028 stack_destroy(notit->stack);
3029 }
3030
3031 if (notit->btr) {
fdf0e7a0 3032 BT_LOGD("Destroying BTR: btr-addr=%p", notit->btr);
50842bdc 3033 bt_btr_destroy(notit->btr);
e98a2d6e
PP
3034 }
3035
c44c3e70
JG
3036 if (notit->clock_states) {
3037 g_hash_table_destroy(notit->clock_states);
3038 }
5f870343
JG
3039
3040 if (notit->sc_field_path_caches) {
3041 g_hash_table_destroy(notit->sc_field_path_caches);
3042 }
3043
3044 if (notit->field_overrides) {
3045 g_hash_table_destroy(notit->field_overrides);
3046 }
fdf0e7a0 3047
e98a2d6e
PP
3048 g_free(notit);
3049}
3050
50842bdc
PP
3051enum bt_notif_iter_status bt_notif_iter_get_next_notification(
3052 struct bt_notif_iter *notit,
0982a26d 3053 struct bt_clock_class_priority_map *cc_prio_map,
78586d8a 3054 struct bt_notification **notification)
e98a2d6e 3055{
312c056a 3056 int ret;
50842bdc 3057 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
e98a2d6e 3058
f6ccaed9
PP
3059 BT_ASSERT(notit);
3060 BT_ASSERT(notification);
e98a2d6e 3061
312c056a
PP
3062 if (cc_prio_map != notit->meta.cc_prio_map) {
3063 bt_put(notit->meta.cc_prio_map);
3064 notit->meta.cc_prio_map = bt_get(cc_prio_map);
3065 }
3066
f42867e2
PP
3067 if (notit->state == STATE_DONE) {
3068 status = BT_NOTIF_ITER_STATUS_EOF;
3069 goto end;
3070 }
3071
fdf0e7a0
PP
3072 BT_LOGV("Getting next notification: notit-addr=%p, cc-prio-map-addr=%p",
3073 notit, cc_prio_map);
3074
e98a2d6e
PP
3075 while (true) {
3076 status = handle_state(notit);
50842bdc
PP
3077 if (status == BT_NOTIF_ITER_STATUS_AGAIN) {
3078 BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_AGAIN.");
7cdc2bab
MD
3079 goto end;
3080 }
312c056a 3081
50842bdc
PP
3082 if (status != BT_NOTIF_ITER_STATUS_OK) {
3083 if (status == BT_NOTIF_ITER_STATUS_EOF) {
f42867e2
PP
3084 enum state next_state = notit->state;
3085
50842bdc 3086 BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_EOF.");
f42867e2
PP
3087
3088 if (notit->packet) {
312c056a
PP
3089 notify_end_of_packet(notit,
3090 notification);
f42867e2 3091 } else {
312c056a
PP
3092 notify_end_of_stream(notit,
3093 notification);
f42867e2
PP
3094 next_state = STATE_DONE;
3095 }
3096
3097 if (!*notification) {
3098 status = BT_NOTIF_ITER_STATUS_ERROR;
3099 goto end;
3100 }
3101
3102 status = BT_NOTIF_ITER_STATUS_OK;
3103 notit->state = next_state;
e98a2d6e 3104 } else {
fdf0e7a0
PP
3105 BT_LOGW("Cannot handle state: "
3106 "notit-addr=%p, state=%s",
3107 notit, state_string(notit->state));
e98a2d6e 3108 }
312c056a 3109
e98a2d6e
PP
3110 goto end;
3111 }
3112
3113 switch (notit->state) {
f42867e2
PP
3114 case STATE_EMIT_NOTIF_NEW_STREAM:
3115 /* notify_new_stream() logs errors */
3116 notify_new_stream(notit, notification);
3117 if (!*notification) {
3118 status = BT_NOTIF_ITER_STATUS_ERROR;
3119 }
3120 notit->stream_begin_emitted = true;
3121 goto end;
e98a2d6e 3122 case STATE_EMIT_NOTIF_NEW_PACKET:
fdf0e7a0 3123 /* notify_new_packet() logs errors */
e98a2d6e
PP
3124 notify_new_packet(notit, notification);
3125 if (!*notification) {
50842bdc 3126 status = BT_NOTIF_ITER_STATUS_ERROR;
e98a2d6e 3127 }
312c056a 3128
e98a2d6e
PP
3129 goto end;
3130 case STATE_EMIT_NOTIF_EVENT:
312c056a
PP
3131 BT_ASSERT(notit->event_notif);
3132 ret = set_event_clocks(notit);
3133 if (ret) {
50842bdc 3134 status = BT_NOTIF_ITER_STATUS_ERROR;
312c056a 3135 goto end;
e98a2d6e 3136 }
312c056a
PP
3137
3138 BT_MOVE(*notification, notit->event_notif);
e98a2d6e
PP
3139 goto end;
3140 case STATE_EMIT_NOTIF_END_OF_PACKET:
5f870343
JG
3141 /* Update clock with timestamp_end field. */
3142 if (notit->cur_timestamp_end) {
50842bdc 3143 enum bt_btr_status btr_status;
5f870343 3144
f45bfe88
PP
3145 btr_status = update_clock(notit,
3146 notit->cur_timestamp_end);
50842bdc 3147 if (btr_status != BT_BTR_STATUS_OK) {
fdf0e7a0
PP
3148 BT_LOGW("Cannot update stream's clock value: "
3149 "notit-addr=%p", notit);
50842bdc 3150 status = BT_NOTIF_ITER_STATUS_ERROR;
5f870343
JG
3151 goto end;
3152 }
3153 }
3154
fdf0e7a0 3155 /* notify_end_of_packet() logs errors */
e98a2d6e
PP
3156 notify_end_of_packet(notit, notification);
3157 if (!*notification) {
50842bdc 3158 status = BT_NOTIF_ITER_STATUS_ERROR;
e98a2d6e 3159 }
312c056a 3160
e98a2d6e
PP
3161 goto end;
3162 default:
3163 /* Non-emitting state: continue */
3164 break;
3165 }
3166 }
3167
3168end:
3169 return status;
3170}
87187cbf
PP
3171
3172BT_HIDDEN
312c056a 3173enum bt_notif_iter_status bt_notif_iter_borrow_packet_header_context_fields(
50842bdc
PP
3174 struct bt_notif_iter *notit,
3175 struct bt_field **packet_header_field,
3176 struct bt_field **packet_context_field)
87187cbf 3177{
9e0c8dbb 3178 int ret;
50842bdc 3179 enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
87187cbf 3180
f6ccaed9 3181 BT_ASSERT(notit);
87187cbf
PP
3182
3183 if (notit->state == STATE_EMIT_NOTIF_NEW_PACKET) {
3184 /* We're already there */
3185 goto set_fields;
3186 }
3187
3188 while (true) {
3189 status = handle_state(notit);
50842bdc
PP
3190 if (status == BT_NOTIF_ITER_STATUS_AGAIN) {
3191 BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_AGAIN.");
87187cbf
PP
3192 goto end;
3193 }
50842bdc
PP
3194 if (status != BT_NOTIF_ITER_STATUS_OK) {
3195 if (status == BT_NOTIF_ITER_STATUS_EOF) {
3196 BT_LOGV_STR("Medium returned BT_NOTIF_ITER_STATUS_EOF.");
87187cbf 3197 } else {
fdf0e7a0
PP
3198 BT_LOGW("Cannot handle state: "
3199 "notit-addr=%p, state=%s",
3200 notit, state_string(notit->state));
87187cbf
PP
3201 }
3202 goto end;
3203 }
3204
3205 switch (notit->state) {
3206 case STATE_EMIT_NOTIF_NEW_PACKET:
3207 /*
3208 * Packet header and context fields are
3209 * potentially decoded (or they don't exist).
3210 */
3211 goto set_fields;
3212 case STATE_INIT:
f42867e2 3213 case STATE_EMIT_NOTIF_NEW_STREAM:
87187cbf
PP
3214 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN:
3215 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE:
3216 case STATE_AFTER_TRACE_PACKET_HEADER:
3217 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN:
3218 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE:
3219 case STATE_AFTER_STREAM_PACKET_CONTEXT:
3220 /* Non-emitting state: continue */
3221 break;
3222 default:
3223 /*
3224 * We should never get past the
3225 * STATE_EMIT_NOTIF_NEW_PACKET state.
3226 */
fdf0e7a0
PP
3227 BT_LOGF("Unexpected state: notit-addr=%p, state=%s",
3228 notit, state_string(notit->state));
0fbb9a9f 3229 abort();
87187cbf
PP
3230 }
3231 }
3232
3233set_fields:
312c056a
PP
3234 ret = set_current_packet_content_sizes(notit);
3235 if (ret) {
3236 status = BT_NOTIF_ITER_STATUS_ERROR;
3237 goto end;
3238 }
3239
87187cbf 3240 if (packet_header_field) {
312c056a 3241 *packet_header_field = notit->dscopes.trace_packet_header;
87187cbf
PP
3242 }
3243
3244 if (packet_context_field) {
312c056a 3245 *packet_context_field = notit->dscopes.stream_packet_context;
87187cbf
PP
3246 }
3247
3248end:
3249 return status;
3250}
6de92955
PP
3251
3252BT_HIDDEN
50842bdc 3253void bt_notif_iter_set_medops_data(struct bt_notif_iter *notit,
6de92955
PP
3254 void *medops_data)
3255{
f6ccaed9 3256 BT_ASSERT(notit);
6de92955
PP
3257 notit->medium.data = medops_data;
3258}
9e0c8dbb
JG
3259
3260BT_HIDDEN
50842bdc
PP
3261enum bt_notif_iter_status bt_notif_iter_seek(
3262 struct bt_notif_iter *notit, off_t offset)
9e0c8dbb 3263{
50842bdc
PP
3264 enum bt_notif_iter_status ret = BT_NOTIF_ITER_STATUS_OK;
3265 enum bt_notif_iter_medium_status medium_status;
9e0c8dbb 3266
f6ccaed9 3267 BT_ASSERT(notit);
9e0c8dbb
JG
3268 if (offset < 0) {
3269 BT_LOGE("Cannot seek to negative offset: offset=%jd", offset);
50842bdc 3270 ret = BT_NOTIF_ITER_STATUS_INVAL;
9e0c8dbb
JG
3271 goto end;
3272 }
3273
3274 if (!notit->medium.medops.seek) {
50842bdc 3275 ret = BT_NOTIF_ITER_STATUS_UNSUPPORTED;
9e0c8dbb
JG
3276 BT_LOGD("Aborting seek as the iterator's underlying media does not implement seek support.");
3277 goto end;
3278 }
3279
3280 medium_status = notit->medium.medops.seek(
50842bdc 3281 BT_NOTIF_ITER_SEEK_WHENCE_SET, offset,
9e0c8dbb 3282 notit->medium.data);
50842bdc
PP
3283 if (medium_status != BT_NOTIF_ITER_MEDIUM_STATUS_OK) {
3284 if (medium_status == BT_NOTIF_ITER_MEDIUM_STATUS_EOF) {
3285 ret = BT_NOTIF_ITER_STATUS_EOF;
9e0c8dbb 3286 } else {
50842bdc 3287 ret = BT_NOTIF_ITER_STATUS_ERROR;
9e0c8dbb
JG
3288 goto end;
3289 }
3290 }
3291
50842bdc 3292 bt_notif_iter_reset(notit);
9e0c8dbb
JG
3293 notit->cur_packet_offset = offset;
3294end:
3295 return ret;
3296}
3297
3298BT_HIDDEN
50842bdc
PP
3299off_t bt_notif_iter_get_current_packet_offset(
3300 struct bt_notif_iter *notit)
9e0c8dbb 3301{
f6ccaed9 3302 BT_ASSERT(notit);
9e0c8dbb
JG
3303 return notit->cur_packet_offset;
3304}
3305
3306BT_HIDDEN
50842bdc
PP
3307off_t bt_notif_iter_get_current_packet_size(
3308 struct bt_notif_iter *notit)
9e0c8dbb 3309{
f6ccaed9 3310 BT_ASSERT(notit);
9e0c8dbb
JG
3311 return notit->cur_packet_size;
3312}
This page took 0.209377 seconds and 4 git commands to generate.