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