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