src.ctf.fs: make ctf_msg_iter_create return a unique_ptr
[babeltrace.git] / src / plugins / ctf / common / src / msg-iter / msg-iter.cpp
CommitLineData
e98a2d6e 1/*
0235b0db 2 * SPDX-License-Identifier: MIT
06a626b8 3 *
44c440bc
PP
4 * Copyright (c) 2015-2018 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2018 Philippe Proulx <pproulx@efficios.com>
e98a2d6e 6 *
0235b0db 7 * Babeltrace - CTF message iterator
e98a2d6e
PP
8 */
9
c802cacb
SM
10#include <stddef.h>
11#include <stdint.h>
12#include <stdio.h>
c802cacb 13
578e048b 14#include "common/assert.h"
578e048b 15#include "common/common.h"
0f5c5d5c
SM
16#include "cpp-common/bt2c/fmt.hpp"
17#include "cpp-common/bt2c/logging.hpp"
18#include "cpp-common/vendor/fmt/format.h"
e98a2d6e 19
087cd0f5 20#include "../bfcr/bfcr.hpp"
c802cacb 21#include "msg-iter.hpp"
e98a2d6e
PP
22
23/* A visit stack entry */
4164020e
SM
24struct stack_entry
25{
26 /*
27 * Current base field, one of:
28 *
29 * * string
30 * * structure
31 * * array
32 * * sequence
33 * * variant
34 *
35 * Field is borrowed.
36 */
37 bt_field *base;
38
39 /* Index of next field to set */
40 size_t index;
e98a2d6e
PP
41};
42
43/* Visit stack */
4164020e
SM
44struct stack
45{
46 struct ctf_msg_iter *msg_it;
ea14c7dd 47
4164020e
SM
48 /* Entries (struct stack_entry) */
49 GArray *entries;
afe86a06 50
4164020e
SM
51 /* Number of active entries */
52 size_t size;
e98a2d6e
PP
53};
54
55/* State */
4164020e
SM
56enum state
57{
58 STATE_INIT,
59 STATE_SWITCH_PACKET,
60 STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN,
61 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
62 STATE_AFTER_TRACE_PACKET_HEADER,
63 STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN,
64 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
65 STATE_AFTER_STREAM_PACKET_CONTEXT,
66 STATE_EMIT_MSG_STREAM_BEGINNING,
67 STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS,
68 STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS,
69 STATE_EMIT_MSG_DISCARDED_EVENTS,
70 STATE_EMIT_MSG_DISCARDED_PACKETS,
71 STATE_EMIT_MSG_PACKET_BEGINNING,
72 STATE_DSCOPE_EVENT_HEADER_BEGIN,
73 STATE_DSCOPE_EVENT_HEADER_CONTINUE,
74 STATE_AFTER_EVENT_HEADER,
75 STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN,
76 STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE,
77 STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN,
78 STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE,
79 STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
80 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE,
81 STATE_EMIT_MSG_EVENT,
82 STATE_EMIT_QUEUED_MSG_EVENT,
83 STATE_SKIP_PACKET_PADDING,
84 STATE_EMIT_MSG_PACKET_END_MULTI,
85 STATE_EMIT_MSG_PACKET_END_SINGLE,
86 STATE_EMIT_QUEUED_MSG_PACKET_END,
87 STATE_CHECK_EMIT_MSG_STREAM_END,
88 STATE_EMIT_MSG_STREAM_END,
89 STATE_DONE,
e98a2d6e
PP
90};
91
0f5c5d5c
SM
92static __attribute__((used)) const char *format_as(state state)
93{
94 switch (state) {
95 case STATE_INIT:
96 return "STATE_INIT";
97
98 case STATE_SWITCH_PACKET:
99 return "STATE_SWITCH_PACKET";
100
101 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN:
102 return "STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN";
103
104 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE:
105 return "STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE";
106
107 case STATE_AFTER_TRACE_PACKET_HEADER:
108 return "STATE_AFTER_TRACE_PACKET_HEADER";
109
110 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN:
111 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN";
112
113 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE:
114 return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE";
115
116 case STATE_AFTER_STREAM_PACKET_CONTEXT:
117 return "STATE_AFTER_STREAM_PACKET_CONTEXT";
118
119 case STATE_EMIT_MSG_STREAM_BEGINNING:
120 return "STATE_EMIT_MSG_STREAM_BEGINNING";
121
122 case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS:
123 return "STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS";
124
125 case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS:
126 return "STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS";
127
128 case STATE_EMIT_MSG_DISCARDED_EVENTS:
129 return "STATE_EMIT_MSG_DISCARDED_EVENTS";
130
131 case STATE_EMIT_MSG_DISCARDED_PACKETS:
132 return "STATE_EMIT_MSG_DISCARDED_PACKETS";
133
134 case STATE_EMIT_MSG_PACKET_BEGINNING:
135 return "STATE_EMIT_MSG_PACKET_BEGINNING";
136
137 case STATE_DSCOPE_EVENT_HEADER_BEGIN:
138 return "STATE_DSCOPE_EVENT_HEADER_BEGIN";
139
140 case STATE_DSCOPE_EVENT_HEADER_CONTINUE:
141 return "STATE_DSCOPE_EVENT_HEADER_CONTINUE";
142
143 case STATE_AFTER_EVENT_HEADER:
144 return "STATE_AFTER_EVENT_HEADER";
145
146 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN:
147 return "STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN";
148
149 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE:
150 return "STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE";
151
152 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN:
153 return "STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN";
154
155 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE:
156 return "STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE";
157
158 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN:
159 return "STATE_DSCOPE_EVENT_PAYLOAD_BEGIN";
160
161 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE:
162 return "STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE";
163
164 case STATE_EMIT_MSG_EVENT:
165 return "STATE_EMIT_MSG_EVENT";
166
167 case STATE_EMIT_QUEUED_MSG_EVENT:
168 return "STATE_EMIT_QUEUED_MSG_EVENT";
169
170 case STATE_SKIP_PACKET_PADDING:
171 return "STATE_SKIP_PACKET_PADDING";
172
173 case STATE_EMIT_MSG_PACKET_END_MULTI:
174 return "STATE_EMIT_MSG_PACKET_END_MULTI";
175
176 case STATE_EMIT_MSG_PACKET_END_SINGLE:
177 return "STATE_EMIT_MSG_PACKET_END_SINGLE";
178
179 case STATE_EMIT_QUEUED_MSG_PACKET_END:
180 return "STATE_EMIT_QUEUED_MSG_PACKET_END";
181
182 case STATE_CHECK_EMIT_MSG_STREAM_END:
183 return "STATE_CHECK_EMIT_MSG_STREAM_END";
184
185 case STATE_EMIT_MSG_STREAM_END:
186 return "STATE_EMIT_MSG_STREAM_END";
187
188 case STATE_DONE:
189 return "STATE_DONE";
190 }
191
192 bt_common_abort();
193}
194
4164020e
SM
195struct end_of_packet_snapshots
196{
afb0f12b
SM
197 uint64_t discarded_events = 0;
198 uint64_t packets = 0;
199 uint64_t beginning_clock = 0;
200 uint64_t end_clock = 0;
495490c5
PP
201};
202
d6e69534 203/* CTF message iterator */
4164020e
SM
204struct ctf_msg_iter
205{
0f5c5d5c
SM
206 explicit ctf_msg_iter(bt2c::Logger loggerParam) noexcept : logger {std::move(loggerParam)}
207 {
208 }
209
4164020e 210 /* Visit stack */
afb0f12b 211 struct stack *stack = nullptr;
4164020e
SM
212
213 /* Current message iterator to create messages (weak) */
afb0f12b 214 bt_self_message_iterator *self_msg_iter = nullptr;
4164020e
SM
215
216 /*
217 * True if library objects are unavailable during the decoding and
218 * should not be created/used.
219 */
afb0f12b 220 bool dry_run = false;
4164020e
SM
221
222 /*
223 * Current dynamic scope field pointer.
224 *
225 * This is set by read_dscope_begin_state() and contains the
226 * value of one of the pointers in `dscopes` below.
227 */
afb0f12b 228 bt_field *cur_dscope_field = nullptr;
4164020e
SM
229
230 /*
231 * True if we're done filling a string field from a text
232 * array/sequence payload.
233 */
afb0f12b 234 bool done_filling_string = false;
4164020e
SM
235
236 /* Trace and classes */
237 /* True to set IR fields */
afb0f12b 238 bool set_ir_fields = false;
4164020e
SM
239
240 struct
241 {
afb0f12b
SM
242 struct ctf_trace_class *tc = nullptr;
243 struct ctf_stream_class *sc = nullptr;
244 struct ctf_event_class *ec = nullptr;
4164020e
SM
245 } meta;
246
247 /* Current packet (NULL if not created yet) */
afb0f12b 248 bt_packet *packet = nullptr;
4164020e
SM
249
250 /* Current stream (NULL if not set yet) */
afb0f12b 251 bt_stream *stream = nullptr;
4164020e
SM
252
253 /* Current event (NULL if not created yet) */
afb0f12b 254 bt_event *event = nullptr;
4164020e
SM
255
256 /* Current event message (NULL if not created yet) */
afb0f12b 257 bt_message *event_msg = nullptr;
4164020e
SM
258
259 /*
260 * True if we need to emit a packet beginning message before we emit
261 * the next event message or the packet end message.
262 */
afb0f12b 263 bool emit_delayed_packet_beginning_msg = false;
4164020e
SM
264
265 /*
266 * True if this is the first packet we are reading, and therefore if we
267 * should emit a stream beginning message.
268 */
afb0f12b 269 bool emit_stream_beginning_message = false;
4164020e
SM
270
271 /*
272 * True if we need to emit a stream end message at the end of the
273 * current stream. A live stream may never receive any data and thus
274 * never send a stream beginning message which removes the need to emit
275 * a stream end message.
276 */
afb0f12b 277 bool emit_stream_end_message = false;
4164020e
SM
278
279 /* Database of current dynamic scopes */
280 struct
281 {
afb0f12b
SM
282 bt_field *stream_packet_context = nullptr;
283 bt_field *event_common_context = nullptr;
284 bt_field *event_spec_context = nullptr;
285 bt_field *event_payload = nullptr;
4164020e
SM
286 } dscopes;
287
288 /* Current state */
afb0f12b 289 enum state state = STATE_INIT;
4164020e
SM
290
291 /* Current medium buffer data */
292 struct
293 {
294 /* Last address provided by medium */
afb0f12b 295 const uint8_t *addr = nullptr;
4164020e
SM
296
297 /* Buffer size provided by medium (bytes) */
afb0f12b 298 size_t sz = 0;
4164020e
SM
299
300 /* Offset within whole packet of addr (bits) */
afb0f12b 301 size_t packet_offset = 0;
4164020e
SM
302
303 /* Current position from addr (bits) */
afb0f12b 304 size_t at = 0;
4164020e
SM
305
306 /* Position of the last event header from addr (bits) */
afb0f12b 307 size_t last_eh_at = 0;
4164020e
SM
308 } buf;
309
310 /* Binary type reader */
afb0f12b 311 struct bt_bfcr *bfcr = nullptr;
4164020e
SM
312
313 /* Current medium data */
314 struct
315 {
316 struct ctf_msg_iter_medium_ops medops;
afb0f12b
SM
317 size_t max_request_sz = 0;
318 void *data = nullptr;
4164020e
SM
319 } medium;
320
321 /* Current packet size (bits) (-1 if unknown) */
afb0f12b 322 int64_t cur_exp_packet_total_size = 0;
4164020e
SM
323
324 /* Current content size (bits) (-1 if unknown) */
afb0f12b 325 int64_t cur_exp_packet_content_size = 0;
4164020e
SM
326
327 /* Current stream class ID */
afb0f12b 328 int64_t cur_stream_class_id = 0;
4164020e
SM
329
330 /* Current event class ID */
afb0f12b 331 int64_t cur_event_class_id = 0;
4164020e
SM
332
333 /* Current data stream ID */
afb0f12b 334 int64_t cur_data_stream_id = 0;
4164020e
SM
335
336 /*
337 * Offset, in the underlying media, of the current packet's
338 * start (-1 if unknown).
339 */
afb0f12b 340 off_t cur_packet_offset = 0;
4164020e
SM
341
342 /* Default clock's current value */
afb0f12b 343 uint64_t default_clock_snapshot = 0;
44c440bc 344
4164020e
SM
345 /* End of current packet snapshots */
346 struct end_of_packet_snapshots snapshots;
347
348 /* End of previous packet snapshots */
349 struct end_of_packet_snapshots prev_packet_snapshots;
350
351 /* Stored values (for sequence lengths, variant tags) */
afb0f12b 352 GArray *stored_values = nullptr;
4164020e 353
0f5c5d5c 354 bt2c::Logger logger;
e98a2d6e
PP
355};
356
4164020e
SM
357static struct stack *stack_new(struct ctf_msg_iter *msg_it)
358{
4164020e
SM
359 struct stack *stack = NULL;
360
361 stack = g_new0(struct stack, 1);
362 if (!stack) {
0f5c5d5c 363 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, "Failed to allocate one stack.");
4164020e
SM
364 goto error;
365 }
366
367 stack->msg_it = msg_it;
368 stack->entries = g_array_new(FALSE, TRUE, sizeof(struct stack_entry));
369 if (!stack->entries) {
0f5c5d5c 370 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, "Failed to allocate a GArray.");
4164020e
SM
371 goto error;
372 }
373
0f5c5d5c
SM
374 BT_CPPLOGD_SPEC(msg_it->logger, "Created stack: msg-it-addr={}, stack-addr={}",
375 fmt::ptr(msg_it), fmt::ptr(stack));
4164020e 376 goto end;
fdf0e7a0 377
e98a2d6e 378error:
4164020e
SM
379 g_free(stack);
380 stack = NULL;
44c440bc
PP
381
382end:
4164020e 383 return stack;
e98a2d6e
PP
384}
385
4164020e 386static void stack_destroy(struct stack *stack)
e98a2d6e 387{
4164020e 388 struct ctf_msg_iter *msg_it;
ea14c7dd 389
4164020e
SM
390 BT_ASSERT_DBG(stack);
391 msg_it = stack->msg_it;
0f5c5d5c 392 BT_CPPLOGD_SPEC(msg_it->logger, "Destroying stack: addr={}", fmt::ptr(stack));
afe86a06 393
4164020e
SM
394 if (stack->entries) {
395 g_array_free(stack->entries, TRUE);
396 }
afe86a06 397
4164020e 398 g_free(stack);
e98a2d6e
PP
399}
400
4164020e 401static void stack_push(struct stack *stack, bt_field *base)
e98a2d6e 402{
4164020e
SM
403 struct stack_entry *entry;
404 struct ctf_msg_iter *msg_it;
e98a2d6e 405
4164020e
SM
406 BT_ASSERT_DBG(stack);
407 msg_it = stack->msg_it;
408 BT_ASSERT_DBG(base);
0f5c5d5c
SM
409 BT_CPPLOGT_SPEC(msg_it->logger,
410 "Pushing base field on stack: stack-addr={}, "
411 "stack-size-before={}, stack-size-after={}",
412 fmt::ptr(stack), stack->size, stack->size + 1);
afe86a06 413
4164020e
SM
414 if (stack->entries->len == stack->size) {
415 g_array_set_size(stack->entries, stack->size + 1);
416 }
e98a2d6e 417
d50d46f3 418 entry = &bt_g_array_index(stack->entries, struct stack_entry, stack->size);
4164020e
SM
419 entry->base = base;
420 entry->index = 0;
421 stack->size++;
e98a2d6e
PP
422}
423
4164020e 424static inline unsigned int stack_size(struct stack *stack)
e98a2d6e 425{
4164020e
SM
426 BT_ASSERT_DBG(stack);
427 return stack->size;
e98a2d6e
PP
428}
429
4164020e 430static void stack_pop(struct stack *stack)
e98a2d6e 431{
4164020e 432 struct ctf_msg_iter *msg_it;
ea14c7dd 433
4164020e
SM
434 BT_ASSERT_DBG(stack);
435 BT_ASSERT_DBG(stack_size(stack));
436 msg_it = stack->msg_it;
0f5c5d5c
SM
437 BT_CPPLOGT_SPEC(msg_it->logger,
438 "Popping from stack: "
439 "stack-addr={}, stack-size-before={}, stack-size-after={}",
440 fmt::ptr(stack), stack->size, stack->size - 1);
4164020e 441 stack->size--;
e98a2d6e
PP
442}
443
4164020e 444static inline struct stack_entry *stack_top(struct stack *stack)
e98a2d6e 445{
4164020e
SM
446 BT_ASSERT_DBG(stack);
447 BT_ASSERT_DBG(stack_size(stack));
d50d46f3 448 return &bt_g_array_index(stack->entries, struct stack_entry, stack->size - 1);
e98a2d6e
PP
449}
450
4164020e 451static inline bool stack_empty(struct stack *stack)
e98a2d6e 452{
4164020e 453 return stack_size(stack) == 0;
e98a2d6e
PP
454}
455
4164020e 456static void stack_clear(struct stack *stack)
e98a2d6e 457{
4164020e
SM
458 BT_ASSERT_DBG(stack);
459 stack->size = 0;
e98a2d6e
PP
460}
461
4164020e
SM
462static inline enum ctf_msg_iter_status
463msg_iter_status_from_m_status(enum ctf_msg_iter_medium_status m_status)
e98a2d6e 464{
4164020e
SM
465 /* They are the same */
466 return (ctf_msg_iter_status) m_status;
e98a2d6e
PP
467}
468
4164020e 469static inline size_t buf_size_bits(struct ctf_msg_iter *msg_it)
e98a2d6e 470{
4164020e 471 return msg_it->buf.sz * 8;
e98a2d6e
PP
472}
473
4164020e 474static inline size_t buf_available_bits(struct ctf_msg_iter *msg_it)
e98a2d6e 475{
4164020e 476 return buf_size_bits(msg_it) - msg_it->buf.at;
e98a2d6e
PP
477}
478
4164020e 479static inline size_t packet_at(struct ctf_msg_iter *msg_it)
e98a2d6e 480{
4164020e 481 return msg_it->buf.packet_offset + msg_it->buf.at;
e98a2d6e
PP
482}
483
4164020e 484static inline void buf_consume_bits(struct ctf_msg_iter *msg_it, size_t incr)
e98a2d6e 485{
0f5c5d5c
SM
486 BT_CPPLOGT_SPEC(msg_it->logger, "Advancing cursor: msg-it-addr={}, cur-before={}, cur-after={}",
487 fmt::ptr(msg_it), msg_it->buf.at, msg_it->buf.at + incr);
4164020e 488 msg_it->buf.at += incr;
e98a2d6e
PP
489}
490
4164020e 491static enum ctf_msg_iter_status request_medium_bytes(struct ctf_msg_iter *msg_it)
e98a2d6e 492{
4164020e
SM
493 uint8_t *buffer_addr = NULL;
494 size_t buffer_sz = 0;
495 enum ctf_msg_iter_medium_status m_status;
496
0f5c5d5c
SM
497 BT_CPPLOGD_SPEC(msg_it->logger,
498 "Calling user function (request bytes): msg-it-addr={}, "
499 "request-size={}",
500 fmt::ptr(msg_it), msg_it->medium.max_request_sz);
4164020e
SM
501 m_status = msg_it->medium.medops.request_bytes(msg_it->medium.max_request_sz, &buffer_addr,
502 &buffer_sz, msg_it->medium.data);
0f5c5d5c
SM
503 BT_CPPLOGD_SPEC(msg_it->logger, "User function returned: status={}, buf-addr={}, buf-size={}",
504 m_status, fmt::ptr(buffer_addr), buffer_sz);
4164020e
SM
505 if (m_status == CTF_MSG_ITER_MEDIUM_STATUS_OK) {
506 BT_ASSERT(buffer_sz != 0);
e98a2d6e 507
4164020e
SM
508 /* New packet offset is old one + old size (in bits) */
509 msg_it->buf.packet_offset += buf_size_bits(msg_it);
e98a2d6e 510
4164020e
SM
511 /* Restart at the beginning of the new medium buffer */
512 msg_it->buf.at = 0;
513 msg_it->buf.last_eh_at = SIZE_MAX;
e98a2d6e 514
4164020e
SM
515 /* New medium buffer size */
516 msg_it->buf.sz = buffer_sz;
e98a2d6e 517
4164020e
SM
518 /* New medium buffer address */
519 msg_it->buf.addr = buffer_addr;
e98a2d6e 520
0f5c5d5c
SM
521 BT_CPPLOGD_SPEC(msg_it->logger,
522 "User function returned new bytes: "
523 "packet-offset={}, cur={}, size={}, addr={}",
524 msg_it->buf.packet_offset, msg_it->buf.at, msg_it->buf.sz,
525 fmt::ptr(msg_it->buf.addr));
526 BT_CPPLOGT_MEM_SPEC(msg_it->logger, buffer_addr, buffer_sz,
527 "Returned bytes at {}:", fmt::ptr(buffer_addr));
4164020e
SM
528 } else if (m_status == CTF_MSG_ITER_MEDIUM_STATUS_EOF) {
529 /*
530 * User returned end of stream: validate that we're not
531 * in the middle of a packet header, packet context, or
532 * event.
533 */
534 if (msg_it->cur_exp_packet_total_size >= 0) {
535 if (packet_at(msg_it) == msg_it->cur_exp_packet_total_size) {
536 goto end;
537 }
538 } else {
539 if (packet_at(msg_it) == 0) {
540 goto end;
541 }
fdf0e7a0 542
4164020e
SM
543 if (msg_it->buf.last_eh_at != SIZE_MAX && msg_it->buf.at == msg_it->buf.last_eh_at) {
544 goto end;
545 }
546 }
0684124b 547
4164020e 548 /* All other states are invalid */
0f5c5d5c
SM
549 BT_CPPLOGE_APPEND_CAUSE_SPEC(
550 msg_it->logger,
551 "User function returned {}, but message iterator is in an unexpected state: "
552 "state={}, cur-packet-size={}, cur={}, "
553 "packet-cur={}, last-eh-at={}",
554 m_status, msg_it->state, msg_it->cur_exp_packet_total_size, msg_it->buf.at,
555 packet_at(msg_it), msg_it->buf.last_eh_at);
4164020e
SM
556 m_status = CTF_MSG_ITER_MEDIUM_STATUS_ERROR;
557 } else if (m_status < 0) {
0f5c5d5c
SM
558 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
559 "User function failed: "
560 "status={}",
561 m_status);
4164020e 562 }
e98a2d6e 563
df0139b8 564end:
4164020e
SM
565 return msg_iter_status_from_m_status(m_status);
566}
567
568static inline enum ctf_msg_iter_status buf_ensure_available_bits(struct ctf_msg_iter *msg_it)
569{
570 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
571
572 if (G_UNLIKELY(buf_available_bits(msg_it) == 0)) {
573 /*
574 * This _cannot_ return CTF_MSG_ITER_STATUS_OK
575 * _and_ no bits.
576 */
577 status = request_medium_bytes(msg_it);
578 }
579
580 return status;
581}
582
583static enum ctf_msg_iter_status
584read_dscope_begin_state(struct ctf_msg_iter *msg_it, struct ctf_field_class *dscope_fc,
585 enum state done_state, enum state continue_state, bt_field *dscope_field)
586{
587 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
588 enum bt_bfcr_status bfcr_status;
589 size_t consumed_bits;
590
591 msg_it->cur_dscope_field = dscope_field;
0f5c5d5c
SM
592 BT_CPPLOGT_SPEC(msg_it->logger, "Starting BFCR: msg-it-addr={}, bfcr-addr={}, fc-addr={}",
593 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(dscope_fc));
4164020e
SM
594 consumed_bits = bt_bfcr_start(msg_it->bfcr, dscope_fc, msg_it->buf.addr, msg_it->buf.at,
595 packet_at(msg_it), msg_it->buf.sz, &bfcr_status);
0f5c5d5c 596 BT_CPPLOGT_SPEC(msg_it->logger, "BFCR consumed bits: size={}", consumed_bits);
4164020e
SM
597
598 switch (bfcr_status) {
599 case BT_BFCR_STATUS_OK:
600 /* Field class was read completely */
0f5c5d5c 601 BT_CPPLOGT_STR_SPEC(msg_it->logger, "Field was completely decoded.");
4164020e
SM
602 msg_it->state = done_state;
603 break;
604 case BT_BFCR_STATUS_EOF:
0f5c5d5c 605 BT_CPPLOGT_STR_SPEC(msg_it->logger, "BFCR needs more data to decode field completely.");
4164020e
SM
606 msg_it->state = continue_state;
607 break;
608 default:
0f5c5d5c
SM
609 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
610 "BFCR failed to start: msg-it-addr={}, bfcr-addr={}, "
611 "status={}",
612 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), bfcr_status);
4164020e
SM
613 status = CTF_MSG_ITER_STATUS_ERROR;
614 goto end;
615 }
616
617 /* Consume bits now since we know we're not in an error state */
618 buf_consume_bits(msg_it, consumed_bits);
e98a2d6e
PP
619
620end:
4164020e
SM
621 return status;
622}
623
624static enum ctf_msg_iter_status read_dscope_continue_state(struct ctf_msg_iter *msg_it,
625 enum state done_state)
626{
627 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
628 enum bt_bfcr_status bfcr_status;
629 size_t consumed_bits;
630
0f5c5d5c
SM
631 BT_CPPLOGT_SPEC(msg_it->logger, "Continuing BFCR: msg-it-addr={}, bfcr-addr={}",
632 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr));
4164020e
SM
633
634 status = buf_ensure_available_bits(msg_it);
635 if (status != CTF_MSG_ITER_STATUS_OK) {
636 if (status < 0) {
0f5c5d5c
SM
637 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
638 "Cannot ensure that buffer has at least one byte: "
639 "msg-addr={}, status={}",
640 fmt::ptr(msg_it), status);
4164020e 641 } else {
0f5c5d5c
SM
642 BT_CPPLOGT_SPEC(msg_it->logger,
643 "Cannot ensure that buffer has at least one byte: "
644 "msg-addr={}, status={}",
645 fmt::ptr(msg_it), status);
4164020e
SM
646 }
647
648 goto end;
649 }
650
651 consumed_bits = bt_bfcr_continue(msg_it->bfcr, msg_it->buf.addr, msg_it->buf.sz, &bfcr_status);
0f5c5d5c 652 BT_CPPLOGT_SPEC(msg_it->logger, "BFCR consumed bits: size={}", consumed_bits);
4164020e
SM
653
654 switch (bfcr_status) {
655 case BT_BFCR_STATUS_OK:
656 /* Type was read completely. */
0f5c5d5c 657 BT_CPPLOGT_STR_SPEC(msg_it->logger, "Field was completely decoded.");
4164020e
SM
658 msg_it->state = done_state;
659 break;
660 case BT_BFCR_STATUS_EOF:
661 /* Stay in this continue state. */
0f5c5d5c 662 BT_CPPLOGT_STR_SPEC(msg_it->logger, "BFCR needs more data to decode field completely.");
4164020e
SM
663 break;
664 default:
0f5c5d5c
SM
665 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
666 "BFCR failed to continue: msg-it-addr={}, bfcr-addr={}, "
667 "status={}",
668 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), bfcr_status);
4164020e
SM
669 status = CTF_MSG_ITER_STATUS_ERROR;
670 goto end;
671 }
672
673 /* Consume bits now since we know we're not in an error state. */
674 buf_consume_bits(msg_it, consumed_bits);
e98a2d6e 675end:
4164020e
SM
676 return status;
677}
678
679static void release_event_dscopes(struct ctf_msg_iter *msg_it)
680{
681 msg_it->dscopes.event_common_context = NULL;
682 msg_it->dscopes.event_spec_context = NULL;
683 msg_it->dscopes.event_payload = NULL;
684}
685
686static void release_all_dscopes(struct ctf_msg_iter *msg_it)
687{
688 msg_it->dscopes.stream_packet_context = NULL;
689
690 release_event_dscopes(msg_it);
691}
692
693static enum ctf_msg_iter_status switch_packet_state(struct ctf_msg_iter *msg_it)
694{
695 enum ctf_msg_iter_status status;
4164020e
SM
696
697 /*
698 * We don't put the stream class here because we need to make
699 * sure that all the packets processed by the same message
700 * iterator refer to the same stream class (the first one).
701 */
702 BT_ASSERT(msg_it);
703
704 if (msg_it->cur_exp_packet_total_size != -1) {
705 msg_it->cur_packet_offset += msg_it->cur_exp_packet_total_size;
706 }
707
0f5c5d5c
SM
708 BT_CPPLOGD_SPEC(msg_it->logger,
709 "Switching packet: msg-it-addr={}, cur={}, "
710 "packet-offset={}",
711 fmt::ptr(msg_it), msg_it->buf.at, msg_it->cur_packet_offset);
4164020e
SM
712 stack_clear(msg_it->stack);
713 msg_it->meta.ec = NULL;
714 BT_PACKET_PUT_REF_AND_RESET(msg_it->packet);
715 BT_MESSAGE_PUT_REF_AND_RESET(msg_it->event_msg);
716 release_all_dscopes(msg_it);
717 msg_it->cur_dscope_field = NULL;
718
719 if (msg_it->medium.medops.switch_packet) {
720 enum ctf_msg_iter_medium_status medium_status;
721
722 medium_status = msg_it->medium.medops.switch_packet(msg_it->medium.data);
723 if (medium_status == CTF_MSG_ITER_MEDIUM_STATUS_EOF) {
724 /* No more packets. */
725 msg_it->state = STATE_CHECK_EMIT_MSG_STREAM_END;
726 status = CTF_MSG_ITER_STATUS_OK;
727 goto end;
728 } else if (medium_status != CTF_MSG_ITER_MEDIUM_STATUS_OK) {
729 status = msg_iter_status_from_m_status(medium_status);
730 goto end;
731 }
732
733 /*
734 * After the packet switch, the medium might want to give us a
735 * different buffer for the new packet.
736 */
737 status = request_medium_bytes(msg_it);
738 if (status != CTF_MSG_ITER_STATUS_OK) {
739 goto end;
740 }
741 }
742
743 /*
744 * Adjust current buffer so that addr points to the beginning of the new
745 * packet.
746 */
747 if (msg_it->buf.addr) {
748 size_t consumed_bytes = (size_t) (msg_it->buf.at / CHAR_BIT);
749
750 /* Packets are assumed to start on a byte frontier. */
751 if (msg_it->buf.at % CHAR_BIT) {
0f5c5d5c
SM
752 BT_CPPLOGE_APPEND_CAUSE_SPEC(
753 msg_it->logger,
4164020e 754 "Cannot switch packet: current position is not a multiple of 8: "
0f5c5d5c
SM
755 "msg-it-addr={}, cur={}",
756 fmt::ptr(msg_it), msg_it->buf.at);
4164020e
SM
757 status = CTF_MSG_ITER_STATUS_ERROR;
758 goto end;
759 }
760
761 msg_it->buf.addr += consumed_bytes;
762 msg_it->buf.sz -= consumed_bytes;
763 msg_it->buf.at = 0;
764 msg_it->buf.packet_offset = 0;
0f5c5d5c
SM
765 BT_CPPLOGD_SPEC(msg_it->logger, "Adjusted buffer: addr={}, size={}",
766 fmt::ptr(msg_it->buf.addr), msg_it->buf.sz);
4164020e
SM
767 }
768
769 msg_it->cur_exp_packet_content_size = -1;
770 msg_it->cur_exp_packet_total_size = -1;
771 msg_it->cur_stream_class_id = -1;
772 msg_it->cur_event_class_id = -1;
773 msg_it->cur_data_stream_id = -1;
774 msg_it->prev_packet_snapshots = msg_it->snapshots;
775 msg_it->snapshots.discarded_events = UINT64_C(-1);
776 msg_it->snapshots.packets = UINT64_C(-1);
777 msg_it->snapshots.beginning_clock = UINT64_C(-1);
778 msg_it->snapshots.end_clock = UINT64_C(-1);
779 msg_it->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
780
781 status = CTF_MSG_ITER_STATUS_OK;
44269abb 782end:
4164020e
SM
783 return status;
784}
785
786static enum ctf_msg_iter_status read_packet_header_begin_state(struct ctf_msg_iter *msg_it)
787{
788 struct ctf_field_class *packet_header_fc = NULL;
4164020e
SM
789 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
790
791 /*
792 * Make sure at least one bit is available for this packet. An
793 * empty packet is impossible. If we reach the end of the medium
794 * at this point, then it's considered the end of the stream.
795 */
796 status = buf_ensure_available_bits(msg_it);
797 switch (status) {
798 case CTF_MSG_ITER_STATUS_OK:
799 break;
800 case CTF_MSG_ITER_STATUS_EOF:
801 status = CTF_MSG_ITER_STATUS_OK;
802 msg_it->state = STATE_CHECK_EMIT_MSG_STREAM_END;
803 goto end;
804 default:
805 goto end;
806 }
807
808 /* Packet header class is common to the whole trace class. */
809 packet_header_fc = msg_it->meta.tc->packet_header_fc;
810 if (!packet_header_fc) {
811 msg_it->state = STATE_AFTER_TRACE_PACKET_HEADER;
812 goto end;
813 }
814
815 msg_it->cur_stream_class_id = -1;
816 msg_it->cur_event_class_id = -1;
817 msg_it->cur_data_stream_id = -1;
0f5c5d5c
SM
818 BT_CPPLOGD_SPEC(msg_it->logger,
819 "Decoding packet header field: "
820 "msg-it-addr={}, trace-class-addr={}, fc-addr={}",
821 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.tc), fmt::ptr(packet_header_fc));
4164020e
SM
822 status = read_dscope_begin_state(msg_it, packet_header_fc, STATE_AFTER_TRACE_PACKET_HEADER,
823 STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE, NULL);
824 if (status < 0) {
0f5c5d5c
SM
825 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
826 "Cannot decode packet header field: "
827 "msg-it-addr={}, trace-class-addr={}, "
828 "fc-addr={}",
829 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.tc),
830 fmt::ptr(packet_header_fc));
4164020e 831 }
d1e46835 832
e98a2d6e 833end:
4164020e
SM
834 return status;
835}
836
837static enum ctf_msg_iter_status read_packet_header_continue_state(struct ctf_msg_iter *msg_it)
838{
839 return read_dscope_continue_state(msg_it, STATE_AFTER_TRACE_PACKET_HEADER);
840}
841
842static inline enum ctf_msg_iter_status set_current_stream_class(struct ctf_msg_iter *msg_it)
843{
844 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
845 struct ctf_stream_class *new_stream_class = NULL;
846
847 if (msg_it->cur_stream_class_id == -1) {
848 /*
849 * No current stream class ID field, therefore only one
850 * stream class.
851 */
852 if (msg_it->meta.tc->stream_classes->len != 1) {
0f5c5d5c
SM
853 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
854 "Need exactly one stream class since there's "
855 "no stream class ID field: "
856 "msg-it-addr={}",
857 fmt::ptr(msg_it));
4164020e
SM
858 status = CTF_MSG_ITER_STATUS_ERROR;
859 goto end;
860 }
861
862 new_stream_class = (ctf_stream_class *) msg_it->meta.tc->stream_classes->pdata[0];
863 msg_it->cur_stream_class_id = new_stream_class->id;
864 }
865
866 new_stream_class =
867 ctf_trace_class_borrow_stream_class_by_id(msg_it->meta.tc, msg_it->cur_stream_class_id);
868 if (!new_stream_class) {
0f5c5d5c
SM
869 BT_CPPLOGE_APPEND_CAUSE_SPEC(
870 msg_it->logger,
4164020e 871 "No stream class with ID of stream class ID to use in trace class: "
0f5c5d5c
SM
872 "msg-it-addr={}, stream-class-id={}, "
873 "trace-class-addr={}",
874 fmt::ptr(msg_it), msg_it->cur_stream_class_id, fmt::ptr(msg_it->meta.tc));
4164020e
SM
875 status = CTF_MSG_ITER_STATUS_ERROR;
876 goto end;
877 }
878
879 if (msg_it->meta.sc) {
880 if (new_stream_class != msg_it->meta.sc) {
0f5c5d5c
SM
881 BT_CPPLOGE_APPEND_CAUSE_SPEC(
882 msg_it->logger,
4164020e 883 "Two packets refer to two different stream classes within the same packet sequence: "
0f5c5d5c
SM
884 "msg-it-addr={}, prev-stream-class-addr={}, "
885 "prev-stream-class-id={}, "
886 "next-stream-class-addr={}, "
887 "next-stream-class-id={}, "
888 "trace-addr={}",
889 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id,
890 fmt::ptr(new_stream_class), new_stream_class->id, fmt::ptr(msg_it->meta.tc));
4164020e
SM
891 status = CTF_MSG_ITER_STATUS_ERROR;
892 goto end;
893 }
894 } else {
895 msg_it->meta.sc = new_stream_class;
896 }
897
0f5c5d5c
SM
898 BT_CPPLOGD_SPEC(msg_it->logger,
899 "Set current stream class: "
900 "msg-it-addr={}, stream-class-addr={}, "
901 "stream-class-id={}",
902 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id);
d1e46835 903
e98a2d6e 904end:
4164020e
SM
905 return status;
906}
907
908static inline enum ctf_msg_iter_status set_current_stream(struct ctf_msg_iter *msg_it)
909{
910 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
911 bt_stream *stream = NULL;
912
0f5c5d5c
SM
913 BT_CPPLOGD_SPEC(msg_it->logger,
914 "Calling user function (get stream): msg-it-addr={}, "
915 "stream-class-addr={}, stream-class-id={}",
916 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id);
4164020e
SM
917 stream = msg_it->medium.medops.borrow_stream(msg_it->meta.sc->ir_sc, msg_it->cur_data_stream_id,
918 msg_it->medium.data);
919 bt_stream_get_ref(stream);
0f5c5d5c 920 BT_CPPLOGD_SPEC(msg_it->logger, "User function returned: stream-addr={}", fmt::ptr(stream));
4164020e 921 if (!stream) {
0f5c5d5c
SM
922 BT_CPPLOGE_APPEND_CAUSE_SPEC(
923 msg_it->logger,
4164020e
SM
924 "User function failed to return a stream object for the given stream class.");
925 status = CTF_MSG_ITER_STATUS_ERROR;
926 goto end;
927 }
928
929 if (msg_it->stream && stream != msg_it->stream) {
0f5c5d5c
SM
930 BT_CPPLOGE_APPEND_CAUSE_SPEC(
931 msg_it->logger,
4164020e
SM
932 "User function returned a different stream than the previous one for the same sequence of packets.");
933 status = CTF_MSG_ITER_STATUS_ERROR;
934 goto end;
935 }
936
937 BT_STREAM_MOVE_REF(msg_it->stream, stream);
312c056a
PP
938
939end:
4164020e
SM
940 bt_stream_put_ref(stream);
941 return status;
942}
943
944static inline enum ctf_msg_iter_status set_current_packet(struct ctf_msg_iter *msg_it)
945{
946 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
947 bt_packet *packet = NULL;
948
0f5c5d5c
SM
949 BT_CPPLOGD_SPEC(msg_it->logger,
950 "Creating packet from stream: "
951 "msg-it-addr={}, stream-addr={}, "
952 "stream-class-addr={}, "
953 "stream-class-id={}",
954 fmt::ptr(msg_it), fmt::ptr(msg_it->stream), fmt::ptr(msg_it->meta.sc),
955 msg_it->meta.sc->id);
4164020e
SM
956
957 /* Create packet */
958 BT_ASSERT(msg_it->stream);
959 packet = bt_packet_create(msg_it->stream);
960 if (!packet) {
0f5c5d5c
SM
961 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
962 "Cannot create packet from stream: "
963 "msg-it-addr={}, stream-addr={}, "
964 "stream-class-addr={}, "
965 "stream-class-id={}",
966 fmt::ptr(msg_it), fmt::ptr(msg_it->stream),
967 fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id);
4164020e
SM
968 goto error;
969 }
970
971 goto end;
312c056a
PP
972
973error:
4164020e
SM
974 BT_PACKET_PUT_REF_AND_RESET(packet);
975 status = CTF_MSG_ITER_STATUS_ERROR;
312c056a
PP
976
977end:
4164020e
SM
978 BT_PACKET_MOVE_REF(msg_it->packet, packet);
979 return status;
312c056a
PP
980}
981
4164020e 982static enum ctf_msg_iter_status after_packet_header_state(struct ctf_msg_iter *msg_it)
e98a2d6e 983{
4164020e 984 enum ctf_msg_iter_status status;
e98a2d6e 985
4164020e
SM
986 status = set_current_stream_class(msg_it);
987 if (status != CTF_MSG_ITER_STATUS_OK) {
988 goto end;
989 }
e98a2d6e 990
4164020e
SM
991 if (!msg_it->dry_run) {
992 status = set_current_stream(msg_it);
993 if (status != CTF_MSG_ITER_STATUS_OK) {
994 goto end;
995 }
bc0ae364 996
4164020e
SM
997 status = set_current_packet(msg_it);
998 if (status != CTF_MSG_ITER_STATUS_OK) {
999 goto end;
1000 }
1001 }
bc0ae364 1002
4164020e 1003 msg_it->state = STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN;
312c056a 1004
4164020e 1005 status = CTF_MSG_ITER_STATUS_OK;
bc0ae364 1006
312c056a 1007end:
4164020e
SM
1008 return status;
1009}
1010
1011static enum ctf_msg_iter_status read_packet_context_begin_state(struct ctf_msg_iter *msg_it)
1012{
1013 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
1014 struct ctf_field_class *packet_context_fc;
1015
1016 BT_ASSERT(msg_it->meta.sc);
1017 packet_context_fc = msg_it->meta.sc->packet_context_fc;
1018 if (!packet_context_fc) {
0f5c5d5c
SM
1019 BT_CPPLOGD_SPEC(msg_it->logger,
1020 "No packet packet context field class in stream class: continuing: "
1021 "msg-it-addr={}, stream-class-addr={}, "
1022 "stream-class-id={}",
1023 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id);
4164020e
SM
1024 msg_it->state = STATE_AFTER_STREAM_PACKET_CONTEXT;
1025 goto end;
1026 }
1027
1028 if (packet_context_fc->in_ir && !msg_it->dry_run) {
1029 BT_ASSERT(!msg_it->dscopes.stream_packet_context);
1030 BT_ASSERT(msg_it->packet);
1031 msg_it->dscopes.stream_packet_context = bt_packet_borrow_context_field(msg_it->packet);
1032 BT_ASSERT(msg_it->dscopes.stream_packet_context);
1033 }
1034
0f5c5d5c
SM
1035 BT_CPPLOGD_SPEC(msg_it->logger,
1036 "Decoding packet context field: "
1037 "msg-it-addr={}, stream-class-addr={}, "
1038 "stream-class-id={}, fc-addr={}",
1039 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id,
1040 fmt::ptr(packet_context_fc));
4164020e
SM
1041 status = read_dscope_begin_state(msg_it, packet_context_fc, STATE_AFTER_STREAM_PACKET_CONTEXT,
1042 STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
1043 msg_it->dscopes.stream_packet_context);
1044 if (status < 0) {
0f5c5d5c
SM
1045 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
1046 "Cannot decode packet context field: "
1047 "msg-it-addr={}, stream-class-addr={}, "
1048 "stream-class-id={}, fc-addr={}",
1049 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc),
1050 msg_it->meta.sc->id, fmt::ptr(packet_context_fc));
4164020e 1051 }
e98a2d6e
PP
1052
1053end:
4164020e
SM
1054 return status;
1055}
1056
1057static enum ctf_msg_iter_status read_packet_context_continue_state(struct ctf_msg_iter *msg_it)
1058{
1059 return read_dscope_continue_state(msg_it, STATE_AFTER_STREAM_PACKET_CONTEXT);
1060}
1061
1062static enum ctf_msg_iter_status set_current_packet_content_sizes(struct ctf_msg_iter *msg_it)
1063{
1064 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
1065
1066 if (msg_it->cur_exp_packet_total_size == -1) {
1067 if (msg_it->cur_exp_packet_content_size != -1) {
1068 msg_it->cur_exp_packet_total_size = msg_it->cur_exp_packet_content_size;
1069 }
1070 } else {
1071 if (msg_it->cur_exp_packet_content_size == -1) {
1072 msg_it->cur_exp_packet_content_size = msg_it->cur_exp_packet_total_size;
1073 }
1074 }
1075
1076 BT_ASSERT(
1077 (msg_it->cur_exp_packet_total_size >= 0 && msg_it->cur_exp_packet_content_size >= 0) ||
1078 (msg_it->cur_exp_packet_total_size < 0 && msg_it->cur_exp_packet_content_size < 0));
1079
1080 if (msg_it->cur_exp_packet_content_size > msg_it->cur_exp_packet_total_size) {
0f5c5d5c
SM
1081 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1082 msg_it->logger,
1083 "Invalid packet or content size: "
1084 "content size is greater than packet size: "
1085 "msg-it-addr={}, packet-context-field-addr={}, "
1086 "packet-size={}, content-size={}",
1087 fmt::ptr(msg_it), fmt::ptr(msg_it->dscopes.stream_packet_context),
1088 msg_it->cur_exp_packet_total_size, msg_it->cur_exp_packet_content_size);
4164020e
SM
1089 status = CTF_MSG_ITER_STATUS_ERROR;
1090 goto end;
1091 }
1092
0f5c5d5c
SM
1093 BT_CPPLOGD_SPEC(msg_it->logger,
1094 "Set current packet and content sizes: "
1095 "msg-it-addr={}, packet-size={}, content-size={}",
1096 fmt::ptr(msg_it), msg_it->cur_exp_packet_total_size,
1097 msg_it->cur_exp_packet_content_size);
fc917f65 1098
e98a2d6e 1099end:
4164020e 1100 return status;
e98a2d6e
PP
1101}
1102
4164020e 1103static enum ctf_msg_iter_status after_packet_context_state(struct ctf_msg_iter *msg_it)
e98a2d6e 1104{
4164020e 1105 enum ctf_msg_iter_status status;
e98a2d6e 1106
4164020e
SM
1107 status = set_current_packet_content_sizes(msg_it);
1108 if (status != CTF_MSG_ITER_STATUS_OK) {
1109 goto end;
1110 }
e22b45d0 1111
4164020e
SM
1112 if (msg_it->emit_stream_beginning_message) {
1113 msg_it->state = STATE_EMIT_MSG_STREAM_BEGINNING;
1114 } else {
1115 msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS;
1116 }
e98a2d6e 1117
e22b45d0 1118end:
4164020e
SM
1119 return status;
1120}
1121
1122static enum ctf_msg_iter_status read_event_header_begin_state(struct ctf_msg_iter *msg_it)
1123{
1124 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
1125 struct ctf_field_class *event_header_fc = NULL;
1126
1127 /* Reset the position of the last event header */
1128 msg_it->buf.last_eh_at = msg_it->buf.at;
1129 msg_it->cur_event_class_id = -1;
1130
1131 /* Check if we have some content left */
1132 if (msg_it->cur_exp_packet_content_size >= 0) {
1133 if (G_UNLIKELY(packet_at(msg_it) == msg_it->cur_exp_packet_content_size)) {
1134 /* No more events! */
0f5c5d5c
SM
1135 BT_CPPLOGD_SPEC(msg_it->logger,
1136 "Reached end of packet: msg-it-addr={}, "
1137 "cur={}",
1138 fmt::ptr(msg_it), packet_at(msg_it));
4164020e
SM
1139 msg_it->state = STATE_EMIT_MSG_PACKET_END_MULTI;
1140 goto end;
1141 } else if (G_UNLIKELY(packet_at(msg_it) > msg_it->cur_exp_packet_content_size)) {
1142 /* That's not supposed to happen */
0f5c5d5c
SM
1143 BT_CPPLOGD_SPEC(
1144 msg_it->logger,
4164020e 1145 "Before decoding event header field: cursor is passed the packet's content: "
0f5c5d5c
SM
1146 "msg-it-addr={}, content-size={}, "
1147 "cur={}",
1148 fmt::ptr(msg_it), msg_it->cur_exp_packet_content_size, packet_at(msg_it));
4164020e
SM
1149 status = CTF_MSG_ITER_STATUS_ERROR;
1150 goto end;
1151 }
1152 } else {
1153 /*
1154 * "Infinite" content: we're done when the medium has
1155 * nothing else for us.
1156 */
1157 status = buf_ensure_available_bits(msg_it);
1158 switch (status) {
1159 case CTF_MSG_ITER_STATUS_OK:
1160 break;
1161 case CTF_MSG_ITER_STATUS_EOF:
1162 status = CTF_MSG_ITER_STATUS_OK;
1163 msg_it->state = STATE_EMIT_MSG_PACKET_END_SINGLE;
1164 goto end;
1165 default:
1166 goto end;
1167 }
1168 }
1169
1170 release_event_dscopes(msg_it);
1171 BT_ASSERT(msg_it->meta.sc);
1172 event_header_fc = msg_it->meta.sc->event_header_fc;
1173 if (!event_header_fc) {
1174 msg_it->state = STATE_AFTER_EVENT_HEADER;
1175 goto end;
1176 }
1177
0f5c5d5c
SM
1178 BT_CPPLOGD_SPEC(msg_it->logger,
1179 "Decoding event header field: "
1180 "msg-it-addr={}, stream-class-addr={}, "
1181 "stream-class-id={}, "
1182 "fc-addr={}",
1183 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id,
1184 fmt::ptr(event_header_fc));
4164020e
SM
1185 status = read_dscope_begin_state(msg_it, event_header_fc, STATE_AFTER_EVENT_HEADER,
1186 STATE_DSCOPE_EVENT_HEADER_CONTINUE, NULL);
1187 if (status < 0) {
0f5c5d5c
SM
1188 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
1189 "Cannot decode event header field: "
1190 "msg-it-addr={}, stream-class-addr={}, "
1191 "stream-class-id={}, fc-addr={}",
1192 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc),
1193 msg_it->meta.sc->id, fmt::ptr(event_header_fc));
4164020e 1194 }
e98a2d6e 1195
d1e46835 1196end:
4164020e
SM
1197 return status;
1198}
1199
1200static enum ctf_msg_iter_status read_event_header_continue_state(struct ctf_msg_iter *msg_it)
1201{
1202 return read_dscope_continue_state(msg_it, STATE_AFTER_EVENT_HEADER);
1203}
1204
1205static inline enum ctf_msg_iter_status set_current_event_class(struct ctf_msg_iter *msg_it)
1206{
1207 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
1208
1209 struct ctf_event_class *new_event_class = NULL;
1210
1211 if (msg_it->cur_event_class_id == -1) {
1212 /*
1213 * No current event class ID field, therefore only one
1214 * event class.
1215 */
1216 if (msg_it->meta.sc->event_classes->len != 1) {
0f5c5d5c
SM
1217 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1218 msg_it->logger,
4164020e 1219 "Need exactly one event class since there's no event class ID field: "
0f5c5d5c
SM
1220 "msg-it-addr={}",
1221 fmt::ptr(msg_it));
4164020e
SM
1222 status = CTF_MSG_ITER_STATUS_ERROR;
1223 goto end;
1224 }
1225
1226 new_event_class = (ctf_event_class *) msg_it->meta.sc->event_classes->pdata[0];
1227 msg_it->cur_event_class_id = new_event_class->id;
1228 }
1229
1230 new_event_class =
1231 ctf_stream_class_borrow_event_class_by_id(msg_it->meta.sc, msg_it->cur_event_class_id);
1232 if (!new_event_class) {
0f5c5d5c
SM
1233 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1234 msg_it->logger,
4164020e 1235 "No event class with ID of event class ID to use in stream class: "
0f5c5d5c
SM
1236 "msg-it-addr={}, stream-class-id={}, "
1237 "event-class-id={}, "
1238 "trace-class-addr={}",
1239 fmt::ptr(msg_it), msg_it->meta.sc->id, msg_it->cur_event_class_id,
1240 fmt::ptr(msg_it->meta.tc));
4164020e
SM
1241 status = CTF_MSG_ITER_STATUS_ERROR;
1242 goto end;
1243 }
1244
1245 msg_it->meta.ec = new_event_class;
0f5c5d5c
SM
1246 BT_CPPLOGD_SPEC(msg_it->logger,
1247 "Set current event class: "
1248 "msg-it-addr={}, event-class-addr={}, "
1249 "event-class-id={}, "
1250 "event-class-name=\"{}\"",
1251 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), msg_it->meta.ec->id,
1252 msg_it->meta.ec->name->str);
fdf0e7a0 1253
e98a2d6e 1254end:
4164020e
SM
1255 return status;
1256}
1257
1258static inline enum ctf_msg_iter_status set_current_event_message(struct ctf_msg_iter *msg_it)
1259{
1260 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
1261 bt_message *msg = NULL;
1262
1263 BT_ASSERT_DBG(msg_it->meta.ec);
1264 BT_ASSERT_DBG(msg_it->packet);
0f5c5d5c
SM
1265 BT_CPPLOGD_SPEC(msg_it->logger,
1266 "Creating event message from event class and packet: "
1267 "msg-it-addr={}, ec-addr={}, ec-name=\"{}\", packet-addr={}",
1268 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), msg_it->meta.ec->name->str,
1269 fmt::ptr(msg_it->packet));
4164020e
SM
1270 BT_ASSERT_DBG(msg_it->self_msg_iter);
1271 BT_ASSERT_DBG(msg_it->meta.sc);
1272
1273 if (bt_stream_class_borrow_default_clock_class(msg_it->meta.sc->ir_sc)) {
1274 msg = bt_message_event_create_with_packet_and_default_clock_snapshot(
1275 msg_it->self_msg_iter, msg_it->meta.ec->ir_ec, msg_it->packet,
1276 msg_it->default_clock_snapshot);
1277 } else {
1278 msg = bt_message_event_create_with_packet(msg_it->self_msg_iter, msg_it->meta.ec->ir_ec,
1279 msg_it->packet);
1280 }
1281
1282 if (!msg) {
0f5c5d5c
SM
1283 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
1284 "Cannot create event message: "
1285 "msg-it-addr={}, ec-addr={}, ec-name=\"{}\", "
1286 "packet-addr={}",
1287 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec),
1288 msg_it->meta.ec->name->str, fmt::ptr(msg_it->packet));
4164020e
SM
1289 goto error;
1290 }
1291
1292 goto end;
312c056a
PP
1293
1294error:
4164020e
SM
1295 BT_MESSAGE_PUT_REF_AND_RESET(msg);
1296 status = CTF_MSG_ITER_STATUS_ERROR;
312c056a
PP
1297
1298end:
4164020e
SM
1299 BT_MESSAGE_MOVE_REF(msg_it->event_msg, msg);
1300 return status;
312c056a
PP
1301}
1302
4164020e 1303static enum ctf_msg_iter_status after_event_header_state(struct ctf_msg_iter *msg_it)
e98a2d6e 1304{
4164020e 1305 enum ctf_msg_iter_status status;
e98a2d6e 1306
4164020e
SM
1307 status = set_current_event_class(msg_it);
1308 if (status != CTF_MSG_ITER_STATUS_OK) {
1309 goto end;
1310 }
e98a2d6e 1311
4164020e
SM
1312 if (G_UNLIKELY(msg_it->dry_run)) {
1313 goto next_state;
1314 }
de24a43f 1315
4164020e
SM
1316 status = set_current_event_message(msg_it);
1317 if (status != CTF_MSG_ITER_STATUS_OK) {
1318 goto end;
1319 }
312c056a 1320
4164020e
SM
1321 msg_it->event = bt_message_event_borrow_event(msg_it->event_msg);
1322 BT_ASSERT_DBG(msg_it->event);
de24a43f
FD
1323
1324next_state:
4164020e 1325 msg_it->state = STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN;
e98a2d6e
PP
1326
1327end:
4164020e
SM
1328 return status;
1329}
1330
1331static enum ctf_msg_iter_status read_event_common_context_begin_state(struct ctf_msg_iter *msg_it)
1332{
1333 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
1334 struct ctf_field_class *event_common_context_fc;
1335
1336 event_common_context_fc = msg_it->meta.sc->event_common_context_fc;
1337 if (!event_common_context_fc) {
1338 msg_it->state = STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN;
1339 goto end;
1340 }
1341
1342 if (event_common_context_fc->in_ir && !msg_it->dry_run) {
1343 BT_ASSERT_DBG(!msg_it->dscopes.event_common_context);
1344 msg_it->dscopes.event_common_context = bt_event_borrow_common_context_field(msg_it->event);
1345 BT_ASSERT_DBG(msg_it->dscopes.event_common_context);
1346 }
1347
0f5c5d5c
SM
1348 BT_CPPLOGT_SPEC(msg_it->logger,
1349 "Decoding event common context field: "
1350 "msg-it-addr={}, stream-class-addr={}, "
1351 "stream-class-id={}, "
1352 "fc-addr={}",
1353 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id,
1354 fmt::ptr(event_common_context_fc));
4164020e
SM
1355 status = read_dscope_begin_state(
1356 msg_it, event_common_context_fc, STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN,
1357 STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE, msg_it->dscopes.event_common_context);
1358 if (status < 0) {
0f5c5d5c
SM
1359 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
1360 "Cannot decode event common context field: "
1361 "msg-it-addr={}, stream-class-addr={}, "
1362 "stream-class-id={}, fc-addr={}",
1363 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc),
1364 msg_it->meta.sc->id, fmt::ptr(event_common_context_fc));
4164020e 1365 }
e98a2d6e
PP
1366
1367end:
4164020e
SM
1368 return status;
1369}
1370
1371static enum ctf_msg_iter_status
1372read_event_common_context_continue_state(struct ctf_msg_iter *msg_it)
1373{
1374 return read_dscope_continue_state(msg_it, STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN);
1375}
1376
1377static enum ctf_msg_iter_status read_event_spec_context_begin_state(struct ctf_msg_iter *msg_it)
1378{
1379 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
1380 struct ctf_field_class *event_spec_context_fc;
1381
1382 event_spec_context_fc = msg_it->meta.ec->spec_context_fc;
1383 if (!event_spec_context_fc) {
1384 msg_it->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN;
1385 goto end;
1386 }
1387
1388 if (event_spec_context_fc->in_ir && !msg_it->dry_run) {
1389 BT_ASSERT_DBG(!msg_it->dscopes.event_spec_context);
1390 msg_it->dscopes.event_spec_context = bt_event_borrow_specific_context_field(msg_it->event);
1391 BT_ASSERT_DBG(msg_it->dscopes.event_spec_context);
1392 }
1393
0f5c5d5c
SM
1394 BT_CPPLOGT_SPEC(msg_it->logger,
1395 "Decoding event specific context field: "
1396 "msg-it-addr={}, event-class-addr={}, "
1397 "event-class-name=\"{}\", event-class-id={}, "
1398 "fc-addr={}",
1399 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), msg_it->meta.ec->name->str,
1400 msg_it->meta.ec->id, fmt::ptr(event_spec_context_fc));
4164020e
SM
1401 status = read_dscope_begin_state(
1402 msg_it, event_spec_context_fc, STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
1403 STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE, msg_it->dscopes.event_spec_context);
1404 if (status < 0) {
0f5c5d5c
SM
1405 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
1406 "Cannot decode event specific context field: "
1407 "msg-it-addr={}, event-class-addr={}, "
1408 "event-class-name=\"{}\", "
1409 "event-class-id={}, fc-addr={}",
1410 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec),
1411 msg_it->meta.ec->name->str, msg_it->meta.ec->id,
1412 fmt::ptr(event_spec_context_fc));
4164020e 1413 }
e98a2d6e
PP
1414
1415end:
4164020e
SM
1416 return status;
1417}
1418
1419static enum ctf_msg_iter_status read_event_spec_context_continue_state(struct ctf_msg_iter *msg_it)
1420{
1421 return read_dscope_continue_state(msg_it, STATE_DSCOPE_EVENT_PAYLOAD_BEGIN);
1422}
1423
1424static enum ctf_msg_iter_status read_event_payload_begin_state(struct ctf_msg_iter *msg_it)
1425{
1426 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
1427 struct ctf_field_class *event_payload_fc;
1428
1429 event_payload_fc = msg_it->meta.ec->payload_fc;
1430 if (!event_payload_fc) {
1431 msg_it->state = STATE_EMIT_MSG_EVENT;
1432 goto end;
1433 }
1434
1435 if (event_payload_fc->in_ir && !msg_it->dry_run) {
1436 BT_ASSERT_DBG(!msg_it->dscopes.event_payload);
1437 msg_it->dscopes.event_payload = bt_event_borrow_payload_field(msg_it->event);
1438 BT_ASSERT_DBG(msg_it->dscopes.event_payload);
1439 }
1440
0f5c5d5c
SM
1441 BT_CPPLOGT_SPEC(msg_it->logger,
1442 "Decoding event payload field: "
1443 "msg-it-addr={}, event-class-addr={}, "
1444 "event-class-name=\"{}\", event-class-id={}, "
1445 "fc-addr={}",
1446 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), msg_it->meta.ec->name->str,
1447 msg_it->meta.ec->id, fmt::ptr(event_payload_fc));
4164020e
SM
1448 status =
1449 read_dscope_begin_state(msg_it, event_payload_fc, STATE_EMIT_MSG_EVENT,
1450 STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE, msg_it->dscopes.event_payload);
1451 if (status < 0) {
0f5c5d5c
SM
1452 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
1453 "Cannot decode event payload field: "
1454 "msg-it-addr={}, event-class-addr={}, "
1455 "event-class-name=\"{}\", "
1456 "event-class-id={}, fc-addr={}",
1457 fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec),
1458 msg_it->meta.ec->name->str, msg_it->meta.ec->id,
1459 fmt::ptr(event_payload_fc));
4164020e 1460 }
e98a2d6e
PP
1461
1462end:
4164020e
SM
1463 return status;
1464}
1465
1466static enum ctf_msg_iter_status read_event_payload_continue_state(struct ctf_msg_iter *msg_it)
1467{
1468 return read_dscope_continue_state(msg_it, STATE_EMIT_MSG_EVENT);
1469}
1470
1471static enum ctf_msg_iter_status skip_packet_padding_state(struct ctf_msg_iter *msg_it)
1472{
1473 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
1474 size_t bits_to_skip;
1475 const enum state next_state = STATE_SWITCH_PACKET;
1476
1477 BT_ASSERT(msg_it->cur_exp_packet_total_size > 0);
1478 bits_to_skip = msg_it->cur_exp_packet_total_size - packet_at(msg_it);
1479 if (bits_to_skip == 0) {
1480 msg_it->state = next_state;
1481 goto end;
1482 } else {
1483 size_t bits_to_consume;
1484
0f5c5d5c
SM
1485 BT_CPPLOGD_SPEC(msg_it->logger,
1486 "Trying to skip {} bits of padding: msg-it-addr={}, size={}", bits_to_skip,
1487 fmt::ptr(msg_it), bits_to_skip);
4164020e
SM
1488 status = buf_ensure_available_bits(msg_it);
1489 if (status != CTF_MSG_ITER_STATUS_OK) {
1490 goto end;
1491 }
1492
1493 bits_to_consume = MIN(buf_available_bits(msg_it), bits_to_skip);
0f5c5d5c
SM
1494 BT_CPPLOGD_SPEC(msg_it->logger, "Skipping {} bits of padding: msg-it-addr={}, size={}",
1495 bits_to_consume, fmt::ptr(msg_it), bits_to_consume);
4164020e
SM
1496 buf_consume_bits(msg_it, bits_to_consume);
1497 bits_to_skip = msg_it->cur_exp_packet_total_size - packet_at(msg_it);
1498 if (bits_to_skip == 0) {
1499 msg_it->state = next_state;
1500 goto end;
1501 }
1502 }
e98a2d6e
PP
1503
1504end:
4164020e
SM
1505 return status;
1506}
1507
1508static enum ctf_msg_iter_status check_emit_msg_discarded_events(struct ctf_msg_iter *msg_it)
1509{
1510 msg_it->state = STATE_EMIT_MSG_DISCARDED_EVENTS;
1511
1512 if (!msg_it->meta.sc->has_discarded_events) {
1513 msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS;
1514 goto end;
1515 }
1516
1517 if (msg_it->prev_packet_snapshots.discarded_events == UINT64_C(-1)) {
1518 if (msg_it->snapshots.discarded_events == 0 ||
1519 msg_it->snapshots.discarded_events == UINT64_C(-1)) {
1520 /*
1521 * Stream's first packet with no discarded
1522 * events or no information about discarded
1523 * events: do not emit.
1524 */
1525 msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS;
1526 }
1527 } else {
1528 /*
1529 * If the previous packet has a value for this counter,
1530 * then this counter is defined for the whole stream.
1531 */
1532 BT_ASSERT(msg_it->snapshots.discarded_events != UINT64_C(-1));
1533
1534 if (msg_it->snapshots.discarded_events - msg_it->prev_packet_snapshots.discarded_events ==
1535 0) {
1536 /*
1537 * No discarded events since previous packet: do
1538 * not emit.
1539 */
1540 msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS;
1541 }
1542 }
495490c5 1543
afd45274 1544end:
4164020e
SM
1545 return CTF_MSG_ITER_STATUS_OK;
1546}
1547
1548static enum ctf_msg_iter_status check_emit_msg_discarded_packets(struct ctf_msg_iter *msg_it)
1549{
1550 msg_it->state = STATE_EMIT_MSG_DISCARDED_PACKETS;
1551
1552 if (!msg_it->meta.sc->has_discarded_packets) {
1553 msg_it->state = STATE_EMIT_MSG_PACKET_BEGINNING;
1554 goto end;
1555 }
1556
1557 if (msg_it->prev_packet_snapshots.packets == UINT64_C(-1)) {
1558 /*
1559 * Stream's first packet or no information about
1560 * discarded packets: do not emit. In other words, if
1561 * this is the first packet and its sequence number is
1562 * not 0, do not consider that packets were previously
1563 * lost: we might be reading a partial stream (LTTng
1564 * snapshot for example).
1565 */
1566 msg_it->state = STATE_EMIT_MSG_PACKET_BEGINNING;
1567 } else {
1568 /*
1569 * If the previous packet has a value for this counter,
1570 * then this counter is defined for the whole stream.
1571 */
1572 BT_ASSERT(msg_it->snapshots.packets != UINT64_C(-1));
1573
1574 if (msg_it->snapshots.packets - msg_it->prev_packet_snapshots.packets <= 1) {
1575 /*
1576 * No discarded packets since previous packet:
1577 * do not emit.
1578 */
1579 msg_it->state = STATE_EMIT_MSG_PACKET_BEGINNING;
1580 }
1581 }
495490c5 1582
afd45274 1583end:
4164020e
SM
1584 return CTF_MSG_ITER_STATUS_OK;
1585}
1586
1587static inline enum state check_emit_msg_stream_end(struct ctf_msg_iter *msg_it)
1588{
1589 enum state next_state;
1590
1591 if (msg_it->emit_stream_end_message) {
1592 next_state = STATE_EMIT_MSG_STREAM_END;
1593 } else {
1594 next_state = STATE_DONE;
1595 }
1596
1597 return next_state;
1598}
1599
1600static inline enum ctf_msg_iter_status handle_state(struct ctf_msg_iter *msg_it)
1601{
1602 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
1603 const enum state state = msg_it->state;
1604
0f5c5d5c
SM
1605 BT_CPPLOGT_SPEC(msg_it->logger, "Handling state: msg-it-addr={}, state={}", fmt::ptr(msg_it),
1606 state);
4164020e
SM
1607
1608 // TODO: optimalize!
1609 switch (state) {
1610 case STATE_INIT:
1611 msg_it->state = STATE_SWITCH_PACKET;
1612 break;
1613 case STATE_SWITCH_PACKET:
1614 status = switch_packet_state(msg_it);
1615 break;
1616 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN:
1617 status = read_packet_header_begin_state(msg_it);
1618 break;
1619 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE:
1620 status = read_packet_header_continue_state(msg_it);
1621 break;
1622 case STATE_AFTER_TRACE_PACKET_HEADER:
1623 status = after_packet_header_state(msg_it);
1624 break;
1625 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN:
1626 status = read_packet_context_begin_state(msg_it);
1627 break;
1628 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE:
1629 status = read_packet_context_continue_state(msg_it);
1630 break;
1631 case STATE_AFTER_STREAM_PACKET_CONTEXT:
1632 status = after_packet_context_state(msg_it);
1633 break;
1634 case STATE_EMIT_MSG_STREAM_BEGINNING:
1635 msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS;
1636 break;
1637 case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS:
1638 status = check_emit_msg_discarded_events(msg_it);
1639 break;
1640 case STATE_EMIT_MSG_DISCARDED_EVENTS:
1641 msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS;
1642 break;
1643 case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS:
1644 status = check_emit_msg_discarded_packets(msg_it);
1645 break;
1646 case STATE_EMIT_MSG_DISCARDED_PACKETS:
1647 msg_it->state = STATE_EMIT_MSG_PACKET_BEGINNING;
1648 break;
1649 case STATE_EMIT_MSG_PACKET_BEGINNING:
1650 msg_it->state = STATE_DSCOPE_EVENT_HEADER_BEGIN;
1651 break;
1652 case STATE_DSCOPE_EVENT_HEADER_BEGIN:
1653 status = read_event_header_begin_state(msg_it);
1654 break;
1655 case STATE_DSCOPE_EVENT_HEADER_CONTINUE:
1656 status = read_event_header_continue_state(msg_it);
1657 break;
1658 case STATE_AFTER_EVENT_HEADER:
1659 status = after_event_header_state(msg_it);
1660 break;
1661 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN:
1662 status = read_event_common_context_begin_state(msg_it);
1663 break;
1664 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE:
1665 status = read_event_common_context_continue_state(msg_it);
1666 break;
1667 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN:
1668 status = read_event_spec_context_begin_state(msg_it);
1669 break;
1670 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE:
1671 status = read_event_spec_context_continue_state(msg_it);
1672 break;
1673 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN:
1674 status = read_event_payload_begin_state(msg_it);
1675 break;
1676 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE:
1677 status = read_event_payload_continue_state(msg_it);
1678 break;
1679 case STATE_EMIT_MSG_EVENT:
1680 msg_it->state = STATE_DSCOPE_EVENT_HEADER_BEGIN;
1681 break;
1682 case STATE_EMIT_QUEUED_MSG_EVENT:
1683 msg_it->state = STATE_EMIT_MSG_EVENT;
1684 break;
1685 case STATE_SKIP_PACKET_PADDING:
1686 status = skip_packet_padding_state(msg_it);
1687 break;
1688 case STATE_EMIT_MSG_PACKET_END_MULTI:
1689 msg_it->state = STATE_SKIP_PACKET_PADDING;
1690 break;
1691 case STATE_EMIT_MSG_PACKET_END_SINGLE:
1692 msg_it->state = STATE_EMIT_MSG_STREAM_END;
1693 break;
1694 case STATE_EMIT_QUEUED_MSG_PACKET_END:
1695 msg_it->state = STATE_EMIT_MSG_PACKET_END_SINGLE;
1696 break;
1697 case STATE_CHECK_EMIT_MSG_STREAM_END:
1698 msg_it->state = check_emit_msg_stream_end(msg_it);
1699 break;
1700 case STATE_EMIT_MSG_STREAM_END:
1701 msg_it->state = STATE_DONE;
1702 break;
1703 case STATE_DONE:
1704 break;
1705 default:
0f5c5d5c
SM
1706 BT_CPPLOGF_SPEC(msg_it->logger,
1707 "Unknown CTF plugin message iterator state: "
1708 "msg-it-addr={}, state={}",
1709 fmt::ptr(msg_it), msg_it->state);
4164020e
SM
1710 bt_common_abort();
1711 }
1712
0f5c5d5c
SM
1713 BT_CPPLOGT_SPEC(msg_it->logger,
1714 "Handled state: msg-it-addr={}, status={}, "
1715 "prev-state={}, cur-state={}",
1716 fmt::ptr(msg_it), status, state, msg_it->state);
4164020e 1717 return status;
e98a2d6e
PP
1718}
1719
18a1979b 1720void ctf_msg_iter_reset_for_next_stream_file(struct ctf_msg_iter *msg_it)
3adcb386 1721{
4164020e 1722 BT_ASSERT(msg_it);
0f5c5d5c 1723 BT_CPPLOGD_SPEC(msg_it->logger, "Resetting message iterator: addr={}", fmt::ptr(msg_it));
4164020e
SM
1724 stack_clear(msg_it->stack);
1725 msg_it->meta.sc = NULL;
1726 msg_it->meta.ec = NULL;
1727 BT_PACKET_PUT_REF_AND_RESET(msg_it->packet);
1728 BT_STREAM_PUT_REF_AND_RESET(msg_it->stream);
1729 BT_MESSAGE_PUT_REF_AND_RESET(msg_it->event_msg);
1730 release_all_dscopes(msg_it);
1731 msg_it->cur_dscope_field = NULL;
1732
1733 msg_it->buf.addr = NULL;
1734 msg_it->buf.sz = 0;
1735 msg_it->buf.at = 0;
1736 msg_it->buf.last_eh_at = SIZE_MAX;
1737 msg_it->buf.packet_offset = 0;
1738 msg_it->state = STATE_INIT;
1739 msg_it->cur_exp_packet_content_size = -1;
1740 msg_it->cur_exp_packet_total_size = -1;
1741 msg_it->cur_packet_offset = -1;
1742 msg_it->cur_event_class_id = -1;
1743 msg_it->snapshots.beginning_clock = UINT64_C(-1);
1744 msg_it->snapshots.end_clock = UINT64_C(-1);
495490c5
PP
1745}
1746
1747/**
1748 * Resets the internal state of a CTF message iterator.
1749 */
18a1979b 1750void ctf_msg_iter_reset(struct ctf_msg_iter *msg_it)
495490c5 1751{
4164020e
SM
1752 ctf_msg_iter_reset_for_next_stream_file(msg_it);
1753 msg_it->cur_stream_class_id = -1;
1754 msg_it->cur_data_stream_id = -1;
1755 msg_it->snapshots.discarded_events = UINT64_C(-1);
1756 msg_it->snapshots.packets = UINT64_C(-1);
1757 msg_it->prev_packet_snapshots.discarded_events = UINT64_C(-1);
1758 msg_it->prev_packet_snapshots.packets = UINT64_C(-1);
1759 msg_it->prev_packet_snapshots.beginning_clock = UINT64_C(-1);
1760 msg_it->prev_packet_snapshots.end_clock = UINT64_C(-1);
1761 msg_it->emit_stream_beginning_message = true;
1762 msg_it->emit_stream_end_message = false;
1763}
1764
1765static bt_field *borrow_next_field(struct ctf_msg_iter *msg_it)
1766{
1767 bt_field *next_field = NULL;
1768 bt_field *base_field;
1769 const bt_field_class *base_fc;
1770 bt_field_class_type base_fc_type;
1771 size_t index;
1772
1773 BT_ASSERT_DBG(!stack_empty(msg_it->stack));
1774 index = stack_top(msg_it->stack)->index;
1775 base_field = stack_top(msg_it->stack)->base;
1776 BT_ASSERT_DBG(base_field);
1777 base_fc = bt_field_borrow_class_const(base_field);
1778 BT_ASSERT_DBG(base_fc);
1779 base_fc_type = bt_field_class_get_type(base_fc);
1780
1781 if (base_fc_type == BT_FIELD_CLASS_TYPE_STRUCTURE) {
1782 BT_ASSERT_DBG(index < bt_field_class_structure_get_member_count(
1783 bt_field_borrow_class_const(base_field)));
1784 next_field = bt_field_structure_borrow_member_field_by_index(base_field, index);
1785 } else if (bt_field_class_type_is(base_fc_type, BT_FIELD_CLASS_TYPE_ARRAY)) {
1786 BT_ASSERT_DBG(index < bt_field_array_get_length(base_field));
1787 next_field = bt_field_array_borrow_element_field_by_index(base_field, index);
1788 } else if (bt_field_class_type_is(base_fc_type, BT_FIELD_CLASS_TYPE_VARIANT)) {
1789 BT_ASSERT_DBG(index == 0);
1790 next_field = bt_field_variant_borrow_selected_option_field(base_field);
1791 } else {
1792 bt_common_abort();
1793 }
1794
1795 BT_ASSERT_DBG(next_field);
1796 return next_field;
1797}
1798
1799static void update_default_clock(struct ctf_msg_iter *msg_it, uint64_t new_val,
1800 uint64_t new_val_size)
1801{
1802 uint64_t new_val_mask;
1803 uint64_t cur_value_masked;
1804
1805 BT_ASSERT_DBG(new_val_size > 0);
1806
1807 /*
1808 * Special case for a 64-bit new value, which is the limit
1809 * of a clock value as of this version: overwrite the
1810 * current value directly.
1811 */
1812 if (new_val_size == 64) {
1813 msg_it->default_clock_snapshot = new_val;
1814 goto end;
1815 }
1816
1817 new_val_mask = (1ULL << new_val_size) - 1;
1818 cur_value_masked = msg_it->default_clock_snapshot & new_val_mask;
1819
1820 if (new_val < cur_value_masked) {
1821 /*
1822 * It looks like a wrap happened on the number of bits
1823 * of the requested new value. Assume that the clock
1824 * value wrapped only one time.
1825 */
1826 msg_it->default_clock_snapshot += new_val_mask + 1;
1827 }
1828
1829 /* Clear the low bits of the current clock value. */
1830 msg_it->default_clock_snapshot &= ~new_val_mask;
1831
1832 /* Set the low bits of the current clock value. */
1833 msg_it->default_clock_snapshot |= new_val;
d1e46835 1834
c44c3e70 1835end:
0f5c5d5c
SM
1836 BT_CPPLOGT_SPEC(msg_it->logger,
1837 "Updated default clock's value from integer field's value: "
1838 "value={}",
1839 msg_it->default_clock_snapshot);
4164020e
SM
1840}
1841
839df1da
SM
1842/*
1843 * Ensure the message iterator's `stored_values` array is large enough to
e7401568 1844 * accommodate `storing_index`.
839df1da
SM
1845 *
1846 * We may need more slots in the array than initially allocated if more
1847 * metadata arrives along the way.
1848 */
1849static void ensure_stored_values_size(ctf_msg_iter *msg_it, uint64_t storing_index)
1850{
1851 if (G_UNLIKELY(storing_index >= msg_it->stored_values->len)) {
1852 g_array_set_size(msg_it->stored_values, msg_it->meta.tc->stored_value_count);
1853 }
1854}
1855
4164020e
SM
1856static enum bt_bfcr_status bfcr_unsigned_int_cb(uint64_t value, struct ctf_field_class *fc,
1857 void *data)
1858{
1859 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
4164020e
SM
1860 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
1861
1862 bt_field *field = NULL;
4164020e 1863
0f5c5d5c
SM
1864 BT_CPPLOGT_SPEC(msg_it->logger,
1865 "Unsigned integer function called from BFCR: "
1866 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
1867 "fc-type={}, fc-in-ir={}, value={}",
1868 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir,
1869 value);
4164020e 1870
ab003dc0
SM
1871 ctf_field_class_int *int_fc = ctf_field_class_as_int(fc);
1872
4164020e
SM
1873 if (G_LIKELY(int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE)) {
1874 goto update_def_clock;
1875 }
1876
1877 switch (int_fc->meaning) {
1878 case CTF_FIELD_CLASS_MEANING_EVENT_CLASS_ID:
1879 msg_it->cur_event_class_id = value;
1880 break;
1881 case CTF_FIELD_CLASS_MEANING_DATA_STREAM_ID:
1882 msg_it->cur_data_stream_id = value;
1883 break;
1884 case CTF_FIELD_CLASS_MEANING_PACKET_BEGINNING_TIME:
1885 msg_it->snapshots.beginning_clock = value;
1886 break;
1887 case CTF_FIELD_CLASS_MEANING_PACKET_END_TIME:
1888 msg_it->snapshots.end_clock = value;
1889 break;
1890 case CTF_FIELD_CLASS_MEANING_STREAM_CLASS_ID:
1891 msg_it->cur_stream_class_id = value;
1892 break;
1893 case CTF_FIELD_CLASS_MEANING_MAGIC:
1894 if (value != 0xc1fc1fc1) {
0f5c5d5c
SM
1895 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
1896 "Invalid CTF magic number: msg-it-addr={}, magic={}",
1897 fmt::ptr(msg_it), value);
4164020e
SM
1898 status = BT_BFCR_STATUS_ERROR;
1899 goto end;
1900 }
1901
1902 break;
1903 case CTF_FIELD_CLASS_MEANING_PACKET_COUNTER_SNAPSHOT:
1904 msg_it->snapshots.packets = value;
1905 break;
1906 case CTF_FIELD_CLASS_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT:
1907 msg_it->snapshots.discarded_events = value;
1908 break;
1909 case CTF_FIELD_CLASS_MEANING_EXP_PACKET_TOTAL_SIZE:
1910 msg_it->cur_exp_packet_total_size = value;
1911 break;
1912 case CTF_FIELD_CLASS_MEANING_EXP_PACKET_CONTENT_SIZE:
1913 msg_it->cur_exp_packet_content_size = value;
1914 break;
1915 default:
1916 bt_common_abort();
1917 }
c44c3e70 1918
44c440bc 1919update_def_clock:
4164020e
SM
1920 if (G_UNLIKELY(int_fc->mapped_clock_class)) {
1921 update_default_clock(msg_it, value, int_fc->base.size);
1922 }
1923
1924 if (G_UNLIKELY(int_fc->storing_index >= 0)) {
839df1da 1925 ensure_stored_values_size(msg_it, int_fc->storing_index);
d50d46f3 1926 bt_g_array_index(msg_it->stored_values, uint64_t, (uint64_t) int_fc->storing_index) = value;
4164020e
SM
1927 }
1928
1929 if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) {
1930 goto end;
1931 }
1932
1933 field = borrow_next_field(msg_it);
1934 BT_ASSERT_DBG(field);
1935 BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc);
1936 BT_ASSERT_DBG(bt_field_class_type_is(bt_field_get_class_type(field),
1937 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER));
1938 bt_field_integer_unsigned_set_value(field, value);
1939 stack_top(msg_it->stack)->index++;
fdf0e7a0 1940
312c056a 1941end:
4164020e
SM
1942 return status;
1943}
1944
1945static enum bt_bfcr_status bfcr_unsigned_int_char_cb(uint64_t value, struct ctf_field_class *fc,
1946 void *data)
1947{
1948 int ret;
1949 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
4164020e
SM
1950 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
1951 bt_field *string_field = NULL;
4164020e
SM
1952 char str[2] = {'\0', '\0'};
1953
0f5c5d5c
SM
1954 BT_CPPLOGT_SPEC(msg_it->logger,
1955 "Unsigned integer character function called from BFCR: "
1956 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
1957 "fc-type={}, fc-in-ir={}, value={}",
1958 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir,
1959 value);
ab003dc0
SM
1960
1961 ctf_field_class_int *int_fc = ctf_field_class_as_int(fc);
4164020e
SM
1962 BT_ASSERT_DBG(int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE);
1963 BT_ASSERT_DBG(!int_fc->mapped_clock_class);
1964 BT_ASSERT_DBG(int_fc->storing_index < 0);
1965
1966 if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) {
1967 goto end;
1968 }
1969
1970 if (msg_it->done_filling_string) {
1971 goto end;
1972 }
1973
1974 if (value == 0) {
1975 msg_it->done_filling_string = true;
1976 goto end;
1977 }
1978
1979 string_field = stack_top(msg_it->stack)->base;
1980 BT_ASSERT_DBG(bt_field_get_class_type(string_field) == BT_FIELD_CLASS_TYPE_STRING);
1981
1982 /* Append character */
1983 str[0] = (char) value;
1984 ret = bt_field_string_append_with_length(string_field, str, 1);
1985 if (ret) {
0f5c5d5c
SM
1986 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
1987 "Cannot append character to string field's value: "
1988 "msg-it-addr={}, field-addr={}, ret={}",
1989 fmt::ptr(msg_it), fmt::ptr(string_field), ret);
4164020e
SM
1990 status = BT_BFCR_STATUS_ERROR;
1991 goto end;
1992 }
312c056a 1993
5f870343 1994end:
4164020e 1995 return status;
5f870343
JG
1996}
1997
4164020e 1998static enum bt_bfcr_status bfcr_signed_int_cb(int64_t value, struct ctf_field_class *fc, void *data)
e98a2d6e 1999{
4164020e
SM
2000 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
2001 bt_field *field = NULL;
2002 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
e98a2d6e 2003
0f5c5d5c
SM
2004 BT_CPPLOGT_SPEC(msg_it->logger,
2005 "Signed integer function called from BFCR: "
2006 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2007 "fc-type={}, fc-in-ir={}, value={}",
2008 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir,
2009 value);
ab003dc0
SM
2010
2011 ctf_field_class_int *int_fc = ctf_field_class_as_int(fc);
4164020e 2012 BT_ASSERT_DBG(int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE);
44c440bc 2013
4164020e 2014 if (G_UNLIKELY(int_fc->storing_index >= 0)) {
839df1da 2015 ensure_stored_values_size(msg_it, int_fc->storing_index);
d50d46f3 2016 bt_g_array_index(msg_it->stored_values, uint64_t, (uint64_t) int_fc->storing_index) =
4164020e
SM
2017 (uint64_t) value;
2018 }
44c440bc 2019
4164020e
SM
2020 if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) {
2021 goto end;
2022 }
e98a2d6e 2023
4164020e
SM
2024 field = borrow_next_field(msg_it);
2025 BT_ASSERT_DBG(field);
2026 BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc);
2027 BT_ASSERT_DBG(
2028 bt_field_class_type_is(bt_field_get_class_type(field), BT_FIELD_CLASS_TYPE_SIGNED_INTEGER));
2029 bt_field_integer_signed_set_value(field, value);
2030 stack_top(msg_it->stack)->index++;
fdf0e7a0 2031
312c056a 2032end:
4164020e 2033 return status;
e98a2d6e
PP
2034}
2035
4164020e
SM
2036static enum bt_bfcr_status bfcr_floating_point_cb(double value, struct ctf_field_class *fc,
2037 void *data)
e98a2d6e 2038{
4164020e
SM
2039 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
2040 bt_field *field = NULL;
2041 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
2042 bt_field_class_type type;
e98a2d6e 2043
0f5c5d5c
SM
2044 BT_CPPLOGT_SPEC(msg_it->logger,
2045 "Floating point number function called from BFCR: "
2046 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2047 "fc-type={}, fc-in-ir={}, value={}",
2048 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir,
2049 value);
41693723 2050
4164020e
SM
2051 if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) {
2052 goto end;
2053 }
41693723 2054
4164020e
SM
2055 field = borrow_next_field(msg_it);
2056 type = bt_field_get_class_type(field);
2057 BT_ASSERT_DBG(field);
2058 BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc);
2059 BT_ASSERT_DBG(bt_field_class_type_is(type, BT_FIELD_CLASS_TYPE_REAL));
fe4df857 2060
4164020e
SM
2061 if (type == BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL) {
2062 bt_field_real_single_precision_set_value(field, (float) value);
2063 } else {
2064 bt_field_real_double_precision_set_value(field, value);
2065 }
2066 stack_top(msg_it->stack)->index++;
41693723
PP
2067
2068end:
4164020e 2069 return status;
e98a2d6e
PP
2070}
2071
4164020e 2072static enum bt_bfcr_status bfcr_string_begin_cb(struct ctf_field_class *fc, void *data)
e98a2d6e 2073{
4164020e
SM
2074 bt_field *field = NULL;
2075 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
e98a2d6e 2076
0f5c5d5c
SM
2077 BT_CPPLOGT_SPEC(msg_it->logger,
2078 "String (beginning) function called from BFCR: "
2079 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2080 "fc-type={}, fc-in-ir={}",
2081 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir);
e98a2d6e 2082
4164020e
SM
2083 if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) {
2084 goto end;
2085 }
41693723 2086
4164020e
SM
2087 field = borrow_next_field(msg_it);
2088 BT_ASSERT_DBG(field);
2089 BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc);
2090 BT_ASSERT_DBG(bt_field_get_class_type(field) == BT_FIELD_CLASS_TYPE_STRING);
2091 bt_field_string_clear(field);
312c056a 2092
4164020e
SM
2093 /*
2094 * Push on stack. Not a compound class per se, but we know that
2095 * only bfcr_string_cb() may be called between this call and a
2096 * subsequent call to bfcr_string_end_cb().
2097 */
2098 stack_push(msg_it->stack, field);
41693723
PP
2099
2100end:
4164020e
SM
2101 return BT_BFCR_STATUS_OK;
2102}
2103
2104static enum bt_bfcr_status bfcr_string_cb(const char *value, size_t len, struct ctf_field_class *fc,
2105 void *data)
2106{
2107 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
2108 bt_field *field = NULL;
2109 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
4164020e
SM
2110 int ret;
2111
0f5c5d5c
SM
2112 BT_CPPLOGT_SPEC(msg_it->logger,
2113 "String (substring) function called from BFCR: "
2114 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2115 "fc-type={}, fc-in-ir={}, string-length={}",
2116 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir,
2117 len);
4164020e
SM
2118
2119 if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) {
2120 goto end;
2121 }
2122
2123 field = stack_top(msg_it->stack)->base;
2124 BT_ASSERT_DBG(field);
2125
2126 /* Append current substring */
2127 ret = bt_field_string_append_with_length(field, value, len);
2128 if (ret) {
0f5c5d5c
SM
2129 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2130 "Cannot append substring to string field's value: "
2131 "msg-it-addr={}, field-addr={}, string-length={}, "
2132 "ret={}",
2133 fmt::ptr(msg_it), fmt::ptr(field), len, ret);
4164020e
SM
2134 status = BT_BFCR_STATUS_ERROR;
2135 goto end;
2136 }
e98a2d6e
PP
2137
2138end:
4164020e 2139 return status;
e98a2d6e
PP
2140}
2141
4164020e 2142static enum bt_bfcr_status bfcr_string_end_cb(struct ctf_field_class *fc, void *data)
e98a2d6e 2143{
4164020e 2144 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
e98a2d6e 2145
0f5c5d5c
SM
2146 BT_CPPLOGT_SPEC(msg_it->logger,
2147 "String (end) function called from BFCR: "
2148 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2149 "fc-type={}, fc-in-ir={}",
2150 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir);
41693723 2151
4164020e
SM
2152 if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) {
2153 goto end;
2154 }
fdf0e7a0 2155
4164020e
SM
2156 /* Pop string field */
2157 stack_pop(msg_it->stack);
e98a2d6e 2158
4164020e
SM
2159 /* Go to next field */
2160 stack_top(msg_it->stack)->index++;
41693723
PP
2161
2162end:
4164020e
SM
2163 return BT_BFCR_STATUS_OK;
2164}
2165
2166static enum bt_bfcr_status bfcr_compound_begin_cb(struct ctf_field_class *fc, void *data)
2167{
2168 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
2169 bt_field *field;
2170
0f5c5d5c
SM
2171 BT_CPPLOGT_SPEC(msg_it->logger,
2172 "Compound (beginning) function called from BFCR: "
2173 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2174 "fc-type={}, fc-in-ir={}",
2175 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir);
4164020e
SM
2176
2177 if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) {
2178 goto end;
2179 }
2180
2181 /* Borrow field */
2182 if (stack_empty(msg_it->stack)) {
2183 /* Root: already set by read_dscope_begin_state() */
2184 field = msg_it->cur_dscope_field;
2185 } else {
2186 field = borrow_next_field(msg_it);
2187 BT_ASSERT_DBG(field);
2188 }
2189
2190 /* Push field */
2191 BT_ASSERT_DBG(field);
2192 BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc);
2193 stack_push(msg_it->stack, field);
2194
2195 /*
2196 * Change BFCR "unsigned int" callback if it's a text
2197 * array/sequence.
2198 */
2199 if (fc->type == CTF_FIELD_CLASS_TYPE_ARRAY || fc->type == CTF_FIELD_CLASS_TYPE_SEQUENCE) {
2200 ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(fc);
2201
2202 if (array_fc->is_text) {
2203 BT_ASSERT_DBG(bt_field_get_class_type(field) == BT_FIELD_CLASS_TYPE_STRING);
2204 msg_it->done_filling_string = false;
2205 bt_field_string_clear(field);
2206 bt_bfcr_set_unsigned_int_cb(msg_it->bfcr, bfcr_unsigned_int_char_cb);
2207 }
2208 }
e98a2d6e
PP
2209
2210end:
4164020e 2211 return BT_BFCR_STATUS_OK;
e98a2d6e
PP
2212}
2213
4164020e 2214static enum bt_bfcr_status bfcr_compound_end_cb(struct ctf_field_class *fc, void *data)
e98a2d6e 2215{
4164020e 2216 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
e98a2d6e 2217
0f5c5d5c
SM
2218 BT_CPPLOGT_SPEC(msg_it->logger,
2219 "Compound (end) function called from BFCR: "
2220 "msg-it-addr={}, bfcr-addr={}, fc-addr={}, "
2221 "fc-type={}, fc-in-ir={}",
2222 fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir);
e98a2d6e 2223
4164020e
SM
2224 if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) {
2225 goto end;
2226 }
e98a2d6e 2227
4164020e
SM
2228 BT_ASSERT_DBG(!stack_empty(msg_it->stack));
2229 BT_ASSERT_DBG(bt_field_borrow_class_const(stack_top(msg_it->stack)->base) == fc->ir_fc);
e98a2d6e 2230
4164020e
SM
2231 /*
2232 * Reset BFCR "unsigned int" callback if it's a text
2233 * array/sequence.
2234 */
2235 if (fc->type == CTF_FIELD_CLASS_TYPE_ARRAY || fc->type == CTF_FIELD_CLASS_TYPE_SEQUENCE) {
2236 ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(fc);
44c440bc 2237
4164020e
SM
2238 if (array_fc->is_text) {
2239 BT_ASSERT_DBG(bt_field_get_class_type(stack_top(msg_it->stack)->base) ==
2240 BT_FIELD_CLASS_TYPE_STRING);
2241 bt_bfcr_set_unsigned_int_cb(msg_it->bfcr, bfcr_unsigned_int_cb);
2242 }
2243 }
e98a2d6e 2244
4164020e
SM
2245 /* Pop stack */
2246 stack_pop(msg_it->stack);
e98a2d6e 2247
4164020e
SM
2248 /* If the stack is not empty, increment the base's index */
2249 if (!stack_empty(msg_it->stack)) {
2250 stack_top(msg_it->stack)->index++;
2251 }
e98a2d6e
PP
2252
2253end:
4164020e
SM
2254 return BT_BFCR_STATUS_OK;
2255}
2256
2257static int64_t bfcr_get_sequence_length_cb(struct ctf_field_class *fc, void *data)
2258{
2259 bt_field *seq_field;
2260 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
4164020e
SM
2261 struct ctf_field_class_sequence *seq_fc = ctf_field_class_as_sequence(fc);
2262 int64_t length;
2263 int ret;
2264
d50d46f3
SM
2265 length =
2266 (uint64_t) bt_g_array_index(msg_it->stored_values, uint64_t, seq_fc->stored_length_index);
4164020e
SM
2267
2268 if (G_UNLIKELY(msg_it->dry_run)) {
2269 goto end;
2270 }
2271
2272 seq_field = stack_top(msg_it->stack)->base;
2273 BT_ASSERT_DBG(seq_field);
2274
2275 /*
2276 * bfcr_get_sequence_length_cb() also gets called back for a
2277 * text sequence, but the destination field is a string field.
2278 * Only set the field's sequence length if the destination field
2279 * is a sequence field.
2280 */
2281 if (!seq_fc->base.is_text) {
2282 BT_ASSERT_DBG(bt_field_class_type_is(bt_field_get_class_type(seq_field),
2283 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY));
2284 ret = bt_field_array_dynamic_set_length(seq_field, (uint64_t) length);
2285 if (ret) {
0f5c5d5c
SM
2286 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2287 "Cannot set dynamic array field's length field: "
2288 "msg-it-addr={}, field-addr={}, "
2289 "length={}",
2290 fmt::ptr(msg_it), fmt::ptr(seq_field), length);
4164020e
SM
2291 length = -1;
2292 }
2293 }
fdf0e7a0 2294
de24a43f 2295end:
4164020e
SM
2296 return length;
2297}
2298
2299static struct ctf_field_class *
2300bfcr_borrow_variant_selected_field_class_cb(struct ctf_field_class *fc, void *data)
2301{
2302 int ret;
2303 uint64_t i;
2304 int64_t option_index = -1;
2305 ctf_msg_iter *msg_it = (ctf_msg_iter *) data;
2306 ctf_field_class_variant *var_fc = ctf_field_class_as_variant(fc);
2307 struct ctf_named_field_class *selected_option = NULL;
4164020e
SM
2308 struct ctf_field_class *ret_fc = NULL;
2309 union
2310 {
2311 uint64_t u;
2312 int64_t i;
2313 } tag;
2314
2315 /* Get variant's tag */
d50d46f3 2316 tag.u = bt_g_array_index(msg_it->stored_values, uint64_t, var_fc->stored_tag_index);
4164020e
SM
2317
2318 /*
2319 * Check each range to find the selected option's index.
2320 */
2321 if (var_fc->tag_fc->base.is_signed) {
2322 for (i = 0; i < var_fc->ranges->len; i++) {
2323 struct ctf_field_class_variant_range *range =
2324 ctf_field_class_variant_borrow_range_by_index(var_fc, i);
2325
2326 if (tag.i >= range->range.lower.i && tag.i <= range->range.upper.i) {
2327 option_index = (int64_t) range->option_index;
2328 break;
2329 }
2330 }
2331 } else {
2332 for (i = 0; i < var_fc->ranges->len; i++) {
2333 struct ctf_field_class_variant_range *range =
2334 ctf_field_class_variant_borrow_range_by_index(var_fc, i);
2335
2336 if (tag.u >= range->range.lower.u && tag.u <= range->range.upper.u) {
2337 option_index = (int64_t) range->option_index;
2338 break;
2339 }
2340 }
2341 }
2342
2343 if (option_index < 0) {
0f5c5d5c
SM
2344 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2345 "Cannot find variant field class's option: "
2346 "msg-it-addr={}, var-fc-addr={}, u-tag={}, "
2347 "i-tag={}",
2348 fmt::ptr(msg_it), fmt::ptr(var_fc), tag.u, tag.i);
4164020e
SM
2349 ret_fc = NULL;
2350 goto end;
2351 }
2352
2353 selected_option =
2354 ctf_field_class_variant_borrow_option_by_index(var_fc, (uint64_t) option_index);
2355
2356 if (selected_option->fc->in_ir && !msg_it->dry_run) {
2357 bt_field *var_field = stack_top(msg_it->stack)->base;
2358
2359 ret = bt_field_variant_select_option_by_index(var_field, option_index);
2360 if (ret) {
0f5c5d5c
SM
2361 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2362 "Cannot select variant field's option field: "
2363 "msg-it-addr={}, var-field-addr={}, "
2364 "opt-index={}",
2365 fmt::ptr(msg_it), fmt::ptr(var_field), option_index);
4164020e
SM
2366 ret_fc = NULL;
2367 goto end;
2368 }
2369 }
2370
2371 ret_fc = selected_option->fc;
e22b45d0 2372
af87daef 2373end:
4164020e 2374 return ret_fc;
44c440bc
PP
2375}
2376
4164020e 2377static bt_message *create_msg_stream_beginning(struct ctf_msg_iter *msg_it)
f42867e2 2378{
4164020e 2379 bt_message *msg;
f42867e2 2380
4164020e
SM
2381 BT_ASSERT(msg_it->stream);
2382 BT_ASSERT(msg_it->self_msg_iter);
2383 msg = bt_message_stream_beginning_create(msg_it->self_msg_iter, msg_it->stream);
2384 if (!msg) {
0f5c5d5c
SM
2385 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2386 "Cannot create stream beginning message: "
2387 "msg-it-addr={}, stream-addr={}",
2388 fmt::ptr(msg_it), fmt::ptr(msg_it->stream));
4164020e 2389 }
f42867e2 2390
4164020e 2391 return msg;
f42867e2
PP
2392}
2393
4164020e 2394static bt_message *create_msg_stream_end(struct ctf_msg_iter *msg_it)
f42867e2 2395{
4164020e 2396 bt_message *msg;
f42867e2 2397
4164020e 2398 if (!msg_it->stream) {
0f5c5d5c
SM
2399 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2400 "Cannot create stream end message because stream is NULL: "
2401 "msg-it-addr={}",
2402 fmt::ptr(msg_it));
4164020e
SM
2403 msg = NULL;
2404 goto end;
2405 }
f42867e2 2406
4164020e
SM
2407 BT_ASSERT(msg_it->self_msg_iter);
2408 msg = bt_message_stream_end_create(msg_it->self_msg_iter, msg_it->stream);
2409 if (!msg) {
0f5c5d5c
SM
2410 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2411 "Cannot create stream end message: "
2412 "msg-it-addr={}, stream-addr={}",
2413 fmt::ptr(msg_it), fmt::ptr(msg_it->stream));
4164020e 2414 }
fc917f65 2415
308adb47 2416end:
4164020e
SM
2417 return msg;
2418}
2419
2420static bt_message *create_msg_packet_beginning(struct ctf_msg_iter *msg_it, bool use_default_cs)
2421{
4164020e
SM
2422 bt_message *msg;
2423 const bt_stream_class *sc = msg_it->meta.sc->ir_sc;
2424
2425 BT_ASSERT(msg_it->packet);
2426 BT_ASSERT(sc);
2427 BT_ASSERT(msg_it->self_msg_iter);
2428
2429 if (msg_it->meta.sc->packets_have_ts_begin) {
2430 BT_ASSERT(msg_it->snapshots.beginning_clock != UINT64_C(-1));
2431 uint64_t raw_cs_value;
2432
2433 /*
2434 * Either use the decoded packet `timestamp_begin` field or the
2435 * current stream's default clock_snapshot.
2436 */
2437 if (use_default_cs) {
2438 raw_cs_value = msg_it->default_clock_snapshot;
2439 } else {
2440 raw_cs_value = msg_it->snapshots.beginning_clock;
2441 }
2442
2443 msg = bt_message_packet_beginning_create_with_default_clock_snapshot(
2444 msg_it->self_msg_iter, msg_it->packet, raw_cs_value);
2445 } else {
2446 msg = bt_message_packet_beginning_create(msg_it->self_msg_iter, msg_it->packet);
2447 }
2448
2449 if (!msg) {
0f5c5d5c
SM
2450 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2451 "Cannot create packet beginning message: "
2452 "msg-it-addr={}, packet-addr={}",
2453 fmt::ptr(msg_it), fmt::ptr(msg_it->packet));
4164020e
SM
2454 goto end;
2455 }
312c056a 2456
e22b45d0 2457end:
4164020e
SM
2458 return msg;
2459}
2460
2461static bt_message *emit_delayed_packet_beg_msg(struct ctf_msg_iter *msg_it)
2462{
2463 bool packet_beg_ts_need_fix_up;
2464
2465 msg_it->emit_delayed_packet_beginning_msg = false;
2466
2467 /*
2468 * Only fix the packet's timestamp_begin if it's larger than the first
2469 * event of the packet. If there was no event in the packet, the
2470 * `default_clock_snapshot` field will be either equal or greater than
2471 * `snapshots.beginning_clock` so there is not fix needed.
2472 */
2473 packet_beg_ts_need_fix_up = msg_it->default_clock_snapshot < msg_it->snapshots.beginning_clock;
2474
2475 /* create_msg_packet_beginning() logs errors */
2476 return create_msg_packet_beginning(msg_it, packet_beg_ts_need_fix_up);
2477}
2478
2479static bt_message *create_msg_packet_end(struct ctf_msg_iter *msg_it)
2480{
2481 bt_message *msg;
2482 bool update_default_cs = true;
4164020e
SM
2483
2484 if (!msg_it->packet) {
2485 msg = NULL;
2486 goto end;
2487 }
2488
2489 /*
2490 * Check if we need to emit the delayed packet
2491 * beginning message instead of the packet end message.
2492 */
2493 if (G_UNLIKELY(msg_it->emit_delayed_packet_beginning_msg)) {
2494 msg = emit_delayed_packet_beg_msg(msg_it);
2495 /* Don't forget to emit the packet end message. */
2496 msg_it->state = STATE_EMIT_QUEUED_MSG_PACKET_END;
2497 goto end;
2498 }
2499
2500 /* Check if may be affected by lttng-crash timestamp_end quirk. */
2501 if (G_UNLIKELY(msg_it->meta.tc->quirks.lttng_crash)) {
2502 /*
2503 * Check if the `timestamp_begin` field is non-zero but
2504 * `timestamp_end` is zero. It means the trace is affected by
2505 * the lttng-crash packet `timestamp_end` quirk and must be
2506 * fixed up by omitting to update the default clock snapshot to
2507 * the `timestamp_end` as is typically done.
2508 */
2509 if (msg_it->snapshots.beginning_clock != 0 && msg_it->snapshots.end_clock == 0) {
2510 update_default_cs = false;
2511 }
2512 }
2513
2514 /*
2515 * Check if may be affected by lttng event-after-packet `timestamp_end`
2516 * quirk.
2517 */
2518 if (msg_it->meta.tc->quirks.lttng_event_after_packet) {
2519 /*
2520 * Check if `timestamp_end` is smaller then the current
2521 * default_clock_snapshot (which is set to the last event
2522 * decoded). It means the trace is affected by the lttng
2523 * `event-after-packet` packet `timestamp_end` quirk and must
2524 * be fixed up by omitting to update the default clock snapshot
2525 * to the `timestamp_end` as is typically done.
2526 */
2527 if (msg_it->snapshots.end_clock < msg_it->default_clock_snapshot) {
2528 update_default_cs = false;
2529 }
2530 }
2531
2532 /* Update default clock from packet's end time. */
2533 if (msg_it->snapshots.end_clock != UINT64_C(-1) && update_default_cs) {
2534 msg_it->default_clock_snapshot = msg_it->snapshots.end_clock;
2535 }
2536
2537 BT_ASSERT(msg_it->self_msg_iter);
2538
2539 if (msg_it->meta.sc->packets_have_ts_end) {
2540 BT_ASSERT(msg_it->snapshots.end_clock != UINT64_C(-1));
2541 msg = bt_message_packet_end_create_with_default_clock_snapshot(
2542 msg_it->self_msg_iter, msg_it->packet, msg_it->default_clock_snapshot);
2543 } else {
2544 msg = bt_message_packet_end_create(msg_it->self_msg_iter, msg_it->packet);
2545 }
2546
2547 if (!msg) {
0f5c5d5c
SM
2548 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2549 "Cannot create packet end message: "
2550 "msg-it-addr={}, packet-addr={}",
2551 fmt::ptr(msg_it), fmt::ptr(msg_it->packet));
4164020e
SM
2552 goto end;
2553 }
2554
2555 BT_PACKET_PUT_REF_AND_RESET(msg_it->packet);
308adb47
FD
2556
2557end:
4164020e
SM
2558 return msg;
2559}
2560
2561static bt_message *create_msg_discarded_events(struct ctf_msg_iter *msg_it)
2562{
2563 bt_message *msg;
4164020e
SM
2564 uint64_t beginning_raw_value = UINT64_C(-1);
2565 uint64_t end_raw_value = UINT64_C(-1);
2566
2567 BT_ASSERT(msg_it->self_msg_iter);
2568 BT_ASSERT(msg_it->stream);
2569 BT_ASSERT(msg_it->meta.sc->has_discarded_events);
2570
2571 if (msg_it->meta.sc->discarded_events_have_default_cs) {
2572 if (msg_it->prev_packet_snapshots.discarded_events == UINT64_C(-1)) {
2573 /*
2574 * We discarded events, but before (and possibly
2575 * including) the current packet: use this packet's time
2576 * range, and do not have a specific count.
2577 */
2578 beginning_raw_value = msg_it->snapshots.beginning_clock;
2579 end_raw_value = msg_it->snapshots.end_clock;
2580 } else {
2581 beginning_raw_value = msg_it->prev_packet_snapshots.end_clock;
2582 end_raw_value = msg_it->snapshots.end_clock;
2583 }
2584
2585 BT_ASSERT(beginning_raw_value != UINT64_C(-1));
2586 BT_ASSERT(end_raw_value != UINT64_C(-1));
2587 msg = bt_message_discarded_events_create_with_default_clock_snapshots(
2588 msg_it->self_msg_iter, msg_it->stream, beginning_raw_value, end_raw_value);
2589 } else {
2590 msg = bt_message_discarded_events_create(msg_it->self_msg_iter, msg_it->stream);
2591 }
2592
2593 if (!msg) {
0f5c5d5c
SM
2594 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2595 "Cannot create discarded events message: "
2596 "msg-it-addr={}, stream-addr={}",
2597 fmt::ptr(msg_it), fmt::ptr(msg_it->stream));
4164020e
SM
2598 goto end;
2599 }
2600
2601 if (msg_it->prev_packet_snapshots.discarded_events != UINT64_C(-1)) {
2602 bt_message_discarded_events_set_count(msg,
2603 msg_it->snapshots.discarded_events -
2604 msg_it->prev_packet_snapshots.discarded_events);
2605 }
495490c5 2606
308adb47 2607end:
4164020e
SM
2608 return msg;
2609}
2610
2611static bt_message *create_msg_discarded_packets(struct ctf_msg_iter *msg_it)
2612{
2613 bt_message *msg;
4164020e
SM
2614
2615 BT_ASSERT(msg_it->self_msg_iter);
2616 BT_ASSERT(msg_it->stream);
2617 BT_ASSERT(msg_it->meta.sc->has_discarded_packets);
2618 BT_ASSERT(msg_it->prev_packet_snapshots.packets != UINT64_C(-1));
2619
2620 if (msg_it->meta.sc->discarded_packets_have_default_cs) {
2621 BT_ASSERT(msg_it->prev_packet_snapshots.end_clock != UINT64_C(-1));
2622 BT_ASSERT(msg_it->snapshots.beginning_clock != UINT64_C(-1));
2623 msg = bt_message_discarded_packets_create_with_default_clock_snapshots(
2624 msg_it->self_msg_iter, msg_it->stream, msg_it->prev_packet_snapshots.end_clock,
2625 msg_it->snapshots.beginning_clock);
2626 } else {
2627 msg = bt_message_discarded_packets_create(msg_it->self_msg_iter, msg_it->stream);
2628 }
2629
2630 if (!msg) {
0f5c5d5c
SM
2631 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2632 "Cannot create discarded packets message: "
2633 "msg-it-addr={}, stream-addr={}",
2634 fmt::ptr(msg_it), fmt::ptr(msg_it->stream));
4164020e
SM
2635 goto end;
2636 }
2637
2638 bt_message_discarded_packets_set_count(msg, msg_it->snapshots.packets -
2639 msg_it->prev_packet_snapshots.packets - 1);
308adb47
FD
2640
2641end:
4164020e 2642 return msg;
495490c5
PP
2643}
2644
657f1bd6
SM
2645ctf_msg_iter_up ctf_msg_iter_create(struct ctf_trace_class *tc, size_t max_request_sz,
2646 struct ctf_msg_iter_medium_ops medops, void *data,
2647 bt_self_message_iterator *self_msg_iter,
2648 const bt2c::Logger& parentLogger)
4164020e 2649{
4164020e
SM
2650 struct bt_bfcr_cbs cbs = {
2651 .classes =
2652 {
2653 .signed_int = bfcr_signed_int_cb,
2654 .unsigned_int = bfcr_unsigned_int_cb,
2655 .floating_point = bfcr_floating_point_cb,
2656 .string_begin = bfcr_string_begin_cb,
2657 .string = bfcr_string_cb,
2658 .string_end = bfcr_string_end_cb,
2659 .compound_begin = bfcr_compound_begin_cb,
2660 .compound_end = bfcr_compound_end_cb,
2661 },
2662 .query =
2663 {
2664 .get_sequence_length = bfcr_get_sequence_length_cb,
2665 .borrow_variant_selected_field_class = bfcr_borrow_variant_selected_field_class_cb,
2666 },
2667 };
2668
2669 BT_ASSERT(tc);
2670 BT_ASSERT(medops.request_bytes);
2671 BT_ASSERT(medops.borrow_stream);
2672 BT_ASSERT(max_request_sz > 0);
2673
0f5c5d5c
SM
2674 bt2c::Logger logger {parentLogger, "PLUGIN/CTF/MSG-ITER"};
2675 BT_CPPLOGD_SPEC(logger,
2676 "Creating CTF plugin message iterator: "
2677 "trace-addr={}, max-request-size={}, "
2678 "data={}, log-level={}",
2679 fmt::ptr(tc), max_request_sz, fmt::ptr(data), logger.level());
afb0f12b 2680
657f1bd6 2681 ctf_msg_iter_up msg_it {new ctf_msg_iter {std::move(logger)}};
4164020e 2682 msg_it->self_msg_iter = self_msg_iter;
4164020e
SM
2683 msg_it->meta.tc = tc;
2684 msg_it->medium.medops = medops;
2685 msg_it->medium.max_request_sz = max_request_sz;
2686 msg_it->medium.data = data;
657f1bd6 2687 msg_it->stack = stack_new(msg_it.get());
4164020e
SM
2688 msg_it->stored_values = g_array_new(FALSE, TRUE, sizeof(uint64_t));
2689 g_array_set_size(msg_it->stored_values, tc->stored_value_count);
2690
2691 if (!msg_it->stack) {
0f5c5d5c 2692 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, "Failed to create field stack.");
4164020e
SM
2693 goto error;
2694 }
2695
657f1bd6 2696 msg_it->bfcr = bt_bfcr_create(cbs, msg_it.get(), msg_it->logger);
4164020e 2697 if (!msg_it->bfcr) {
0f5c5d5c
SM
2698 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2699 "Failed to create binary class reader (BFCR).");
4164020e
SM
2700 goto error;
2701 }
2702
657f1bd6 2703 ctf_msg_iter_reset(msg_it.get());
0f5c5d5c
SM
2704 BT_CPPLOGD_SPEC(msg_it->logger,
2705 "Created CTF plugin message iterator: "
2706 "trace-addr={}, max-request-size={}, "
2707 "data={}, msg-it-addr={}, log-level={}",
2708 fmt::ptr(tc), max_request_sz, fmt::ptr(data), fmt::ptr(msg_it),
2709 msg_it->logger.level());
4164020e 2710 msg_it->cur_packet_offset = 0;
fdf0e7a0 2711
e98a2d6e 2712end:
4164020e 2713 return msg_it;
fdf0e7a0 2714
c44c3e70 2715error:
657f1bd6 2716 msg_it.reset();
4164020e 2717 goto end;
e98a2d6e
PP
2718}
2719
18a1979b 2720void ctf_msg_iter_destroy(struct ctf_msg_iter *msg_it)
e98a2d6e 2721{
4164020e
SM
2722 BT_PACKET_PUT_REF_AND_RESET(msg_it->packet);
2723 BT_STREAM_PUT_REF_AND_RESET(msg_it->stream);
2724 release_all_dscopes(msg_it);
2725
0f5c5d5c
SM
2726 BT_CPPLOGD_SPEC(msg_it->logger, "Destroying CTF plugin message iterator: addr={}",
2727 fmt::ptr(msg_it));
4164020e
SM
2728
2729 if (msg_it->stack) {
0f5c5d5c 2730 BT_CPPLOGD_STR_SPEC(msg_it->logger, "Destroying field stack.");
4164020e
SM
2731 stack_destroy(msg_it->stack);
2732 }
2733
2734 if (msg_it->bfcr) {
0f5c5d5c 2735 BT_CPPLOGD_SPEC(msg_it->logger, "Destroying BFCR: bfcr-addr={}", fmt::ptr(msg_it->bfcr));
4164020e
SM
2736 bt_bfcr_destroy(msg_it->bfcr);
2737 }
2738
2739 if (msg_it->stored_values) {
2740 g_array_free(msg_it->stored_values, TRUE);
2741 }
2742
afb0f12b 2743 delete msg_it;
4164020e
SM
2744}
2745
657f1bd6
SM
2746void ctf_msg_iter_deleter::operator()(ctf_msg_iter *iter) noexcept
2747{
2748 ctf_msg_iter_destroy(iter);
2749}
2750
4164020e
SM
2751enum ctf_msg_iter_status ctf_msg_iter_get_next_message(struct ctf_msg_iter *msg_it,
2752 const bt_message **message)
2753{
2754 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
2755
2756 BT_ASSERT_DBG(msg_it);
2757 BT_ASSERT_DBG(message);
0f5c5d5c 2758 BT_CPPLOGD_SPEC(msg_it->logger, "Getting next message: msg-it-addr={}", fmt::ptr(msg_it));
4164020e
SM
2759
2760 while (true) {
2761 status = handle_state(msg_it);
2762 if (G_UNLIKELY(status == CTF_MSG_ITER_STATUS_AGAIN)) {
0f5c5d5c 2763 BT_CPPLOGD_STR_SPEC(msg_it->logger, "Medium returned CTF_MSG_ITER_STATUS_AGAIN.");
4164020e
SM
2764 goto end;
2765 } else if (G_UNLIKELY(status != CTF_MSG_ITER_STATUS_OK)) {
0f5c5d5c
SM
2766 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2767 "Cannot handle state: msg-it-addr={}, state={}",
2768 fmt::ptr(msg_it), msg_it->state);
4164020e
SM
2769 goto end;
2770 }
2771
2772 switch (msg_it->state) {
2773 case STATE_EMIT_MSG_EVENT:
2774 BT_ASSERT_DBG(msg_it->event_msg);
2775
2776 /*
2777 * Check if we need to emit the delayed packet
2778 * beginning message instead of the event message.
2779 */
2780 if (G_UNLIKELY(msg_it->emit_delayed_packet_beginning_msg)) {
2781 *message = emit_delayed_packet_beg_msg(msg_it);
2782 if (!*message) {
2783 status = CTF_MSG_ITER_STATUS_ERROR;
2784 }
2785
2786 /*
2787 * Don't forget to emit the event message of
2788 * the event record that was just decoded.
2789 */
2790 msg_it->state = STATE_EMIT_QUEUED_MSG_EVENT;
2791
2792 } else {
2793 *message = msg_it->event_msg;
2794 msg_it->event_msg = NULL;
2795 }
2796 goto end;
2797 case STATE_EMIT_MSG_DISCARDED_EVENTS:
e7401568 2798 /* create_msg_discarded_events() logs errors */
4164020e
SM
2799 *message = create_msg_discarded_events(msg_it);
2800
2801 if (!*message) {
2802 status = CTF_MSG_ITER_STATUS_ERROR;
2803 }
2804
2805 goto end;
2806 case STATE_EMIT_MSG_DISCARDED_PACKETS:
e7401568 2807 /* create_msg_discarded_packets() logs errors */
4164020e
SM
2808 *message = create_msg_discarded_packets(msg_it);
2809
2810 if (!*message) {
2811 status = CTF_MSG_ITER_STATUS_ERROR;
2812 }
2813
2814 goto end;
2815 case STATE_EMIT_MSG_PACKET_BEGINNING:
2816 if (G_UNLIKELY(msg_it->meta.tc->quirks.barectf_event_before_packet)) {
2817 msg_it->emit_delayed_packet_beginning_msg = true;
2818 /*
2819 * There is no message to return yet as this
2820 * packet beginning message is delayed until we
2821 * decode the first event message of the
2822 * packet.
2823 */
2824 break;
2825 } else {
2826 /* create_msg_packet_beginning() logs errors */
2827 *message = create_msg_packet_beginning(msg_it, false);
2828 if (!*message) {
2829 status = CTF_MSG_ITER_STATUS_ERROR;
2830 }
2831 }
2832
2833 goto end;
2834 case STATE_EMIT_MSG_PACKET_END_SINGLE:
2835 case STATE_EMIT_MSG_PACKET_END_MULTI:
2836 /* create_msg_packet_end() logs errors */
2837 *message = create_msg_packet_end(msg_it);
2838
2839 if (!*message) {
2840 status = CTF_MSG_ITER_STATUS_ERROR;
2841 }
2842
2843 goto end;
2844 case STATE_EMIT_MSG_STREAM_BEGINNING:
2845 /* create_msg_stream_beginning() logs errors */
2846 *message = create_msg_stream_beginning(msg_it);
2847 msg_it->emit_stream_beginning_message = false;
2848 msg_it->emit_stream_end_message = true;
2849
2850 if (!*message) {
2851 status = CTF_MSG_ITER_STATUS_ERROR;
2852 }
2853
2854 goto end;
2855 case STATE_EMIT_MSG_STREAM_END:
2856 /* create_msg_stream_end() logs errors */
2857 *message = create_msg_stream_end(msg_it);
2858 msg_it->emit_stream_end_message = false;
2859
2860 if (!*message) {
2861 status = CTF_MSG_ITER_STATUS_ERROR;
2862 }
2863
2864 goto end;
2865 case STATE_DONE:
2866 status = CTF_MSG_ITER_STATUS_EOF;
2867 goto end;
2868 default:
2869 /* Non-emitting state: continue */
2870 break;
2871 }
2872 }
e98a2d6e
PP
2873
2874end:
4164020e
SM
2875 return status;
2876}
2877
2878static enum ctf_msg_iter_status decode_until_state(struct ctf_msg_iter *msg_it,
2879 enum state target_state_1,
2880 enum state target_state_2)
2881{
2882 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
4164020e
SM
2883
2884 BT_ASSERT_DBG(msg_it);
2885
2886 do {
2887 /*
2888 * Check if we reached the state at which we want to stop
2889 * decoding.
2890 */
2891 if (msg_it->state == target_state_1 || msg_it->state == target_state_2) {
2892 goto end;
2893 }
2894
2895 status = handle_state(msg_it);
2896 if (G_UNLIKELY(status == CTF_MSG_ITER_STATUS_AGAIN)) {
0f5c5d5c 2897 BT_CPPLOGD_STR_SPEC(msg_it->logger, "Medium returned CTF_MSG_ITER_STATUS_AGAIN.");
4164020e
SM
2898 goto end;
2899 } else if (G_UNLIKELY(status != CTF_MSG_ITER_STATUS_OK)) {
0f5c5d5c
SM
2900 BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger,
2901 "Cannot handle state: msg-it-addr={}, state={}",
2902 fmt::ptr(msg_it), msg_it->state);
4164020e
SM
2903 goto end;
2904 }
2905
2906 switch (msg_it->state) {
2907 case STATE_INIT:
2908 case STATE_SWITCH_PACKET:
2909 case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN:
2910 case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE:
2911 case STATE_AFTER_TRACE_PACKET_HEADER:
2912 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN:
2913 case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE:
2914 case STATE_AFTER_STREAM_PACKET_CONTEXT:
2915 case STATE_EMIT_MSG_STREAM_BEGINNING:
2916 case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS:
2917 case STATE_EMIT_MSG_DISCARDED_EVENTS:
2918 case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS:
2919 case STATE_EMIT_MSG_DISCARDED_PACKETS:
2920 case STATE_EMIT_MSG_PACKET_BEGINNING:
2921 case STATE_DSCOPE_EVENT_HEADER_BEGIN:
2922 case STATE_DSCOPE_EVENT_HEADER_CONTINUE:
2923 case STATE_AFTER_EVENT_HEADER:
2924 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN:
2925 case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE:
2926 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN:
2927 case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE:
2928 case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN:
2929 case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE:
2930 case STATE_EMIT_MSG_EVENT:
2931 case STATE_EMIT_QUEUED_MSG_EVENT:
2932 case STATE_SKIP_PACKET_PADDING:
2933 case STATE_EMIT_MSG_PACKET_END_MULTI:
2934 case STATE_EMIT_MSG_PACKET_END_SINGLE:
2935 case STATE_EMIT_QUEUED_MSG_PACKET_END:
2936 case STATE_EMIT_MSG_STREAM_END:
2937 break;
2938 case STATE_DONE:
2939 /* fall-through */
2940 default:
2941 /* We should never get to the STATE_DONE state. */
0f5c5d5c
SM
2942 BT_CPPLOGF_SPEC(msg_it->logger, "Unexpected state: msg-it-addr={}, state={}",
2943 fmt::ptr(msg_it), msg_it->state);
4164020e
SM
2944 bt_common_abort();
2945 }
2946 } while (true);
87187cbf 2947
41693723 2948end:
4164020e 2949 return status;
3682dd06
FD
2950}
2951
4164020e 2952static enum ctf_msg_iter_status read_packet_header_context_fields(struct ctf_msg_iter *msg_it)
3682dd06 2953{
4164020e
SM
2954 int ret;
2955 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
3682dd06 2956
4164020e
SM
2957 status = decode_until_state(msg_it, STATE_EMIT_MSG_PACKET_BEGINNING, (state) -1);
2958 if (status != CTF_MSG_ITER_STATUS_OK) {
2959 goto end;
2960 }
3682dd06 2961
4164020e
SM
2962 ret = set_current_packet_content_sizes(msg_it);
2963 if (ret) {
2964 status = CTF_MSG_ITER_STATUS_ERROR;
2965 goto end;
2966 }
312c056a 2967
3682dd06 2968end:
4164020e 2969 return status;
87187cbf 2970}
6de92955 2971
4164020e 2972enum ctf_msg_iter_status ctf_msg_iter_seek(struct ctf_msg_iter *msg_it, off_t offset)
9e0c8dbb 2973{
4164020e
SM
2974 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
2975 enum ctf_msg_iter_medium_status medium_status;
9e0c8dbb 2976
4164020e
SM
2977 BT_ASSERT(msg_it);
2978 BT_ASSERT(offset >= 0);
2979 BT_ASSERT(msg_it->medium.medops.seek);
9e0c8dbb 2980
4164020e
SM
2981 medium_status = msg_it->medium.medops.seek(offset, msg_it->medium.data);
2982 if (medium_status != CTF_MSG_ITER_MEDIUM_STATUS_OK) {
2983 if (medium_status == CTF_MSG_ITER_MEDIUM_STATUS_EOF) {
2984 status = CTF_MSG_ITER_STATUS_EOF;
2985 } else {
2986 status = CTF_MSG_ITER_STATUS_ERROR;
2987 goto end;
2988 }
2989 }
9e0c8dbb 2990
4164020e
SM
2991 ctf_msg_iter_reset(msg_it);
2992 msg_it->cur_packet_offset = offset;
44c440bc 2993
9e0c8dbb 2994end:
4164020e 2995 return status;
9e0c8dbb
JG
2996}
2997
4164020e
SM
2998static enum ctf_msg_iter_status clock_snapshot_at_msg_iter_state(struct ctf_msg_iter *msg_it,
2999 enum state target_state_1,
3000 enum state target_state_2,
3001 uint64_t *clock_snapshot)
27f26617 3002{
4164020e 3003 enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK;
27f26617 3004
4164020e
SM
3005 BT_ASSERT_DBG(msg_it);
3006 BT_ASSERT_DBG(clock_snapshot);
3007 status = decode_until_state(msg_it, target_state_1, target_state_2);
3008 if (status != CTF_MSG_ITER_STATUS_OK) {
3009 goto end;
3010 }
27f26617 3011
4164020e 3012 *clock_snapshot = msg_it->default_clock_snapshot;
27f26617 3013end:
4164020e 3014 return status;
27f26617
FD
3015}
3016
4164020e
SM
3017enum ctf_msg_iter_status
3018ctf_msg_iter_curr_packet_first_event_clock_snapshot(struct ctf_msg_iter *msg_it,
3019 uint64_t *first_clock_snapshot)
27f26617 3020{
4164020e
SM
3021 return clock_snapshot_at_msg_iter_state(msg_it, STATE_AFTER_EVENT_HEADER, (state) -1,
3022 first_clock_snapshot);
27f26617
FD
3023}
3024
4164020e
SM
3025enum ctf_msg_iter_status
3026ctf_msg_iter_curr_packet_last_event_clock_snapshot(struct ctf_msg_iter *msg_it,
3027 uint64_t *last_clock_snapshot)
27f26617 3028{
4164020e
SM
3029 return clock_snapshot_at_msg_iter_state(msg_it, STATE_EMIT_MSG_PACKET_END_SINGLE,
3030 STATE_EMIT_MSG_PACKET_END_MULTI, last_clock_snapshot);
27f26617
FD
3031}
3032
4164020e
SM
3033enum ctf_msg_iter_status
3034ctf_msg_iter_get_packet_properties(struct ctf_msg_iter *msg_it,
3035 struct ctf_msg_iter_packet_properties *props)
3036{
3037 enum ctf_msg_iter_status status;
3038
3039 BT_ASSERT_DBG(msg_it);
3040 BT_ASSERT_DBG(props);
3041 status = read_packet_header_context_fields(msg_it);
3042 if (status != CTF_MSG_ITER_STATUS_OK) {
3043 goto end;
3044 }
3045
3046 props->exp_packet_total_size = msg_it->cur_exp_packet_total_size;
3047 props->exp_packet_content_size = msg_it->cur_exp_packet_content_size;
3048 props->stream_class_id = (uint64_t) msg_it->cur_stream_class_id;
3049 props->data_stream_id = msg_it->cur_data_stream_id;
3050 props->snapshots.discarded_events = msg_it->snapshots.discarded_events;
3051 props->snapshots.packets = msg_it->snapshots.packets;
3052 props->snapshots.beginning_clock = msg_it->snapshots.beginning_clock;
3053 props->snapshots.end_clock = msg_it->snapshots.end_clock;
41693723
PP
3054
3055end:
4164020e 3056 return status;
9e0c8dbb 3057}
fc917f65 3058
4164020e 3059void ctf_msg_iter_set_dry_run(struct ctf_msg_iter *msg_it, bool val)
de24a43f 3060{
4164020e 3061 msg_it->dry_run = val;
de24a43f 3062}
This page took 0.292649 seconds and 4 git commands to generate.