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