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