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