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