From: Simon Marchi Date: Tue, 21 May 2024 17:59:51 +0000 (-0400) Subject: ctf: remove now unused files X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=e05e78bf92c5a9f7fade4d170e2c166c7f6d4063;p=babeltrace.git ctf: remove now unused files Change-Id: Ib66be547edae247049f4d5b0a21233a7c68e0811 Reviewed-on: https://review.lttng.org/c/babeltrace/+/8649 Reviewed-by: Philippe Proulx Signed-off-by: Simon Marchi Reviewed-on: https://review.lttng.org/c/babeltrace/+/12748 --- diff --git a/src/Makefile.am b/src/Makefile.am index 48d24095..84826c2a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -305,23 +305,15 @@ plugins_ctf_common_metadata_libctf_ast_la_SOURCES = \ plugins/ctf/common/src/metadata/tsdl/parser-wrap.hpp \ plugins/ctf/common/src/metadata/tsdl/scanner.hpp \ plugins/ctf/common/src/metadata/tsdl/scanner-symbols.hpp \ - plugins/ctf/common/src/metadata/tsdl/decoder.cpp \ - plugins/ctf/common/src/metadata/tsdl/decoder.hpp \ - plugins/ctf/common/src/metadata/tsdl/decoder-packetized-file-stream-to-buf.cpp \ - plugins/ctf/common/src/metadata/tsdl/decoder-packetized-file-stream-to-buf.hpp \ plugins/ctf/common/src/metadata/tsdl/logging.hpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta.hpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta-visitors.hpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta-validate.cpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-meanings.cpp \ - plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-in-ir.cpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-default-clock-classes.cpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-text-array-sequence.cpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-alignments.cpp \ - plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-value-storing-indexes.cpp \ - plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-stream-class-config.cpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta-warn-meaningless-header-fields.cpp \ - plugins/ctf/common/src/metadata/tsdl/ctf-meta-translate.cpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta-resolve.cpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta-configure-ir-trace.cpp \ plugins/ctf/common/src/metadata/tsdl/ctf-meta-configure-ir-trace.hpp @@ -688,8 +680,6 @@ plugins_ctf_babeltrace_plugin_ctf_la_SOURCES = \ plugins/ctf/common/metadata/ctf-ir.cpp \ plugins/ctf/common/metadata/int-range.hpp \ plugins/ctf/common/metadata/int-range-set.hpp \ - plugins/ctf/common/src/bfcr/bfcr.cpp \ - plugins/ctf/common/src/bfcr/bfcr.hpp \ plugins/ctf/common/src/clk-cls-cfg.hpp \ plugins/ctf/common/src/item-seq/item.cpp \ plugins/ctf/common/src/item-seq/item.hpp \ @@ -735,8 +725,6 @@ plugins_ctf_babeltrace_plugin_ctf_la_SOURCES = \ plugins/ctf/common/src/metadata/tsdl/metadata-stream-decoder.hpp \ plugins/ctf/common/src/msg-iter.cpp \ plugins/ctf/common/src/msg-iter.hpp \ - plugins/ctf/common/src/msg-iter/msg-iter.cpp \ - plugins/ctf/common/src/msg-iter/msg-iter.hpp \ plugins/ctf/common/src/null-cp-finder.hpp \ plugins/ctf/common/src/pkt-props.cpp \ plugins/ctf/common/src/pkt-props.hpp \ diff --git a/src/plugins/ctf/common/src/bfcr/bfcr.cpp b/src/plugins/ctf/common/src/bfcr/bfcr.cpp deleted file mode 100644 index 4ee3548c..00000000 --- a/src/plugins/ctf/common/src/bfcr/bfcr.cpp +++ /dev/null @@ -1,1271 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation - * Copyright (c) 2015-2016 Philippe Proulx - * - * Babeltrace - CTF binary field class reader (BFCR) - */ - -#include "common/align.h" -#include "common/assert.h" -#include "common/common.h" -#include "compat/bitfield.h" -#include "cpp-common/bt2c/logging.hpp" -#include "cpp-common/vendor/fmt/format.h" - -#include "../metadata/tsdl/ctf-meta.hpp" -#include "bfcr.hpp" - -#define DIV8(_x) ((_x) >> 3) -#define BYTES_TO_BITS(_x) ((_x) *8) -#define BITS_TO_BYTES_FLOOR(_x) DIV8(_x) -#define BITS_TO_BYTES_CEIL(_x) DIV8((_x) + 7) -#define IN_BYTE_OFFSET(_at) ((_at) &7) - -/* A visit stack entry */ -struct stack_entry -{ - /* - * Current class of base field, one of: - * - * * Structure - * * Array - * * Sequence - * * Variant - */ - struct ctf_field_class *base_class; - - /* Length of base field (always 1 for a variant class) */ - int64_t base_len; - - /* Index of next field to read */ - int64_t index; -}; - -/* Visit stack */ -struct stack -{ - struct bt_bfcr *bfcr; - - /* Entries (struct stack_entry) */ - GArray *entries; - - /* Number of active entries */ - size_t size; -}; - -/* Reading states */ -enum bfcr_state -{ - BFCR_STATE_NEXT_FIELD, - BFCR_STATE_ALIGN_BASIC, - BFCR_STATE_ALIGN_COMPOUND, - BFCR_STATE_READ_BASIC_BEGIN, - BFCR_STATE_READ_BASIC_CONTINUE, - BFCR_STATE_DONE, -}; - -static const char *format_as(bfcr_state state) noexcept -{ - switch (state) { - case BFCR_STATE_NEXT_FIELD: - return "NEXT_FIELD"; - - case BFCR_STATE_ALIGN_BASIC: - return "ALIGN_BASIC"; - - case BFCR_STATE_ALIGN_COMPOUND: - return "ALIGN_COMPOUND"; - - case BFCR_STATE_READ_BASIC_BEGIN: - return "READ_BASIC_BEGIN"; - - case BFCR_STATE_READ_BASIC_CONTINUE: - return "READ_BASIC_CONTINUE"; - - case BFCR_STATE_DONE: - return "DONE"; - } - - bt_common_abort(); -} - -/* Binary class reader */ -struct bt_bfcr -{ - explicit bt_bfcr(const bt2c::Logger& parentLogger) : logger {parentLogger, "PLUGIN/CTF/BFCR"} - { - } - - bt2c::Logger logger; - - /* BFCR stack */ - struct stack *stack = nullptr; - - /* Current basic field class */ - struct ctf_field_class *cur_basic_field_class = nullptr; - - /* Current state */ - enum bfcr_state state = static_cast(0); - - /* - * Last basic field class's byte order. - * - * This is used to detect errors since two contiguous basic - * classes for which the common boundary is not the boundary of - * a byte cannot have different byte orders. - * - * This is set to CTF_BYTE_ORDER_UNKNOWN on reset and when the last - * basic field class was a string class. - */ - enum ctf_byte_order last_bo = CTF_BYTE_ORDER_UNKNOWN; - - /* Current byte order (copied to last_bo after a successful read) */ - enum ctf_byte_order cur_bo = CTF_BYTE_ORDER_UNKNOWN; - - /* Stitch buffer infos */ - struct - { - /* Stitch buffer */ - uint8_t buf[16] {}; - - /* Offset, within stitch buffer, of first bit */ - size_t offset = 0; - - /* Length (bits) of data in stitch buffer from offset */ - size_t at = 0; - } stitch; - - /* User buffer infos */ - struct - { - /* Address */ - const uint8_t *addr = nullptr; - - /* Offset of data from address (bits) */ - size_t offset = 0; - - /* Current position from offset (bits) */ - size_t at = 0; - - /* Offset of offset within whole packet (bits) */ - size_t packet_offset = 0; - - /* Data size in buffer (bits) */ - size_t sz = 0; - - /* Buffer size (bytes) */ - size_t buf_sz = 0; - } buf; - - /* User stuff */ - struct - { - /* Callback functions */ - bt_bfcr_cbs cbs {}; - - /* Private data */ - void *data = nullptr; - } user; -}; - -static struct stack *stack_new(struct bt_bfcr *bfcr) -{ - struct stack *stack = NULL; - - stack = g_new0(struct stack, 1); - if (!stack) { - BT_CPPLOGE_SPEC(bfcr->logger, "Failed to allocate one stack."); - goto error; - } - - stack->bfcr = bfcr; - stack->entries = g_array_new(FALSE, TRUE, sizeof(struct stack_entry)); - if (!stack->entries) { - BT_CPPLOGE_SPEC(bfcr->logger, "Failed to allocate a GArray."); - goto error; - } - - BT_CPPLOGD_SPEC(bfcr->logger, "Created stack: addr={}", fmt::ptr(stack)); - return stack; - -error: - g_free(stack); - return NULL; -} - -static void stack_destroy(struct stack *stack) -{ - struct bt_bfcr *bfcr; - - if (!stack) { - return; - } - - bfcr = stack->bfcr; - BT_CPPLOGD_SPEC(bfcr->logger, "Destroying stack: addr={}", fmt::ptr(stack)); - - if (stack->entries) { - g_array_free(stack->entries, TRUE); - } - - g_free(stack); -} - -static int stack_push(struct stack *stack, struct ctf_field_class *base_class, size_t base_len) -{ - struct stack_entry *entry; - struct bt_bfcr *bfcr; - - BT_ASSERT_DBG(stack); - BT_ASSERT_DBG(base_class); - bfcr = stack->bfcr; - BT_CPPLOGT_SPEC(bfcr->logger, - "Pushing field class on stack: stack-addr={}, " - "fc-addr={}, fc-type={}, base-length={}, " - "stack-size-before={}, stack-size-after={}", - fmt::ptr(stack), fmt::ptr(base_class), (int) base_class->type, base_len, - stack->size, stack->size + 1); - - if (stack->entries->len == stack->size) { - g_array_set_size(stack->entries, stack->size + 1); - } - - entry = &bt_g_array_index(stack->entries, struct stack_entry, stack->size); - entry->base_class = base_class; - entry->base_len = base_len; - entry->index = 0; - stack->size++; - return 0; -} - -static inline int64_t get_compound_field_class_length(struct bt_bfcr *bfcr, - struct ctf_field_class *fc) -{ - int64_t length; - - switch (fc->type) { - case CTF_FIELD_CLASS_TYPE_STRUCT: - { - ctf_field_class_struct *struct_fc = ctf_field_class_as_struct(fc); - - length = (int64_t) struct_fc->members->len; - break; - } - case CTF_FIELD_CLASS_TYPE_VARIANT: - { - /* Variant field classes always "contain" a single class */ - length = 1; - break; - } - case CTF_FIELD_CLASS_TYPE_ARRAY: - { - struct ctf_field_class_array *array_fc = ctf_field_class_as_array(fc); - - length = (int64_t) array_fc->length; - break; - } - case CTF_FIELD_CLASS_TYPE_SEQUENCE: - length = bfcr->user.cbs.query.get_sequence_length(fc, bfcr->user.data); - break; - default: - bt_common_abort(); - } - - return length; -} - -static int stack_push_with_len(struct bt_bfcr *bfcr, struct ctf_field_class *base_class) -{ - int ret; - int64_t length = get_compound_field_class_length(bfcr, base_class); - - if (length < 0) { - BT_CPPLOGW_SPEC(bfcr->logger, - "Cannot get compound field class's field count: " - "bfcr-addr={}, fc-addr={}, fc-type={}", - fmt::ptr(bfcr), fmt::ptr(base_class), (int) base_class->type); - ret = BT_BFCR_STATUS_ERROR; - goto end; - } - - ret = stack_push(bfcr->stack, base_class, (size_t) length); - -end: - return ret; -} - -static inline unsigned int stack_size(struct stack *stack) -{ - BT_ASSERT_DBG(stack); - return stack->size; -} - -static void stack_pop(struct stack *stack) -{ - struct bt_bfcr *bfcr; - - BT_ASSERT_DBG(stack); - BT_ASSERT_DBG(stack_size(stack)); - bfcr = stack->bfcr; - BT_CPPLOGT_SPEC(bfcr->logger, - "Popping from stack: " - "stack-addr={}, stack-size-before={}, stack-size-after={}", - fmt::ptr(stack), stack->entries->len, stack->entries->len - 1); - stack->size--; -} - -static inline bool stack_empty(struct stack *stack) -{ - return stack_size(stack) == 0; -} - -static void stack_clear(struct stack *stack) -{ - BT_ASSERT_DBG(stack); - stack->size = 0; -} - -static inline struct stack_entry *stack_top(struct stack *stack) -{ - BT_ASSERT_DBG(stack); - BT_ASSERT_DBG(stack_size(stack)); - return &bt_g_array_index(stack->entries, struct stack_entry, stack->size - 1); -} - -static inline size_t available_bits(struct bt_bfcr *bfcr) -{ - return bfcr->buf.sz - bfcr->buf.at; -} - -static inline void consume_bits(struct bt_bfcr *bfcr, size_t incr) -{ - BT_CPPLOGT_SPEC(bfcr->logger, "Advancing cursor: bfcr-addr={}, cur-before={}, cur-after={}", - fmt::ptr(bfcr), bfcr->buf.at, bfcr->buf.at + incr); - bfcr->buf.at += incr; -} - -static inline bool has_enough_bits(struct bt_bfcr *bfcr, size_t sz) -{ - return available_bits(bfcr) >= sz; -} - -static inline bool at_least_one_bit_left(struct bt_bfcr *bfcr) -{ - return has_enough_bits(bfcr, 1); -} - -static inline size_t packet_at(struct bt_bfcr *bfcr) -{ - return bfcr->buf.packet_offset + bfcr->buf.at; -} - -static inline size_t buf_at_from_addr(struct bt_bfcr *bfcr) -{ - /* - * Considering this: - * - * ====== offset ===== (17) - * - * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx - * ^ - * addr (0) ==== at ==== (12) - * - * We want this: - * - * =============================== (29) - */ - return bfcr->buf.offset + bfcr->buf.at; -} - -static void stitch_reset(struct bt_bfcr *bfcr) -{ - bfcr->stitch.offset = 0; - bfcr->stitch.at = 0; -} - -static inline size_t stitch_at_from_addr(struct bt_bfcr *bfcr) -{ - return bfcr->stitch.offset + bfcr->stitch.at; -} - -static void stitch_append_from_buf(struct bt_bfcr *bfcr, size_t sz) -{ - size_t stitch_byte_at; - size_t buf_byte_at; - size_t nb_bytes; - - if (sz == 0) { - return; - } - - stitch_byte_at = BITS_TO_BYTES_FLOOR(stitch_at_from_addr(bfcr)); - buf_byte_at = BITS_TO_BYTES_FLOOR(buf_at_from_addr(bfcr)); - nb_bytes = BITS_TO_BYTES_CEIL(sz); - BT_ASSERT(nb_bytes > 0); - BT_ASSERT(bfcr->buf.addr); - memcpy(&bfcr->stitch.buf[stitch_byte_at], &bfcr->buf.addr[buf_byte_at], nb_bytes); - bfcr->stitch.at += sz; - consume_bits(bfcr, sz); -} - -static void stitch_append_from_remaining_buf(struct bt_bfcr *bfcr) -{ - stitch_append_from_buf(bfcr, available_bits(bfcr)); -} - -static void stitch_set_from_remaining_buf(struct bt_bfcr *bfcr) -{ - stitch_reset(bfcr); - bfcr->stitch.offset = IN_BYTE_OFFSET(buf_at_from_addr(bfcr)); - stitch_append_from_remaining_buf(bfcr); -} - -static inline void read_unsigned_bitfield(struct bt_bfcr *bfcr, const uint8_t *buf, size_t at, - unsigned int field_size, enum ctf_byte_order bo, - uint64_t *v) -{ - switch (bo) { - case CTF_BYTE_ORDER_BIG: - bt_bitfield_read_be(buf, uint8_t, at, field_size, v); - break; - case CTF_BYTE_ORDER_LITTLE: - bt_bitfield_read_le(buf, uint8_t, at, field_size, v); - break; - default: - bt_common_abort(); - } - - BT_CPPLOGT_SPEC(bfcr->logger, "Read unsigned bit array: cur={}, size={}, bo={}, val={}", at, - field_size, (int) bo, *v); -} - -static inline void read_signed_bitfield(struct bt_bfcr *bfcr, const uint8_t *buf, size_t at, - unsigned int field_size, enum ctf_byte_order bo, int64_t *v) -{ - switch (bo) { - case CTF_BYTE_ORDER_BIG: - bt_bitfield_read_be(buf, uint8_t, at, field_size, v); - break; - case CTF_BYTE_ORDER_LITTLE: - bt_bitfield_read_le(buf, uint8_t, at, field_size, v); - break; - default: - bt_common_abort(); - } - - BT_CPPLOGT_SPEC(bfcr->logger, "Read signed bit array: cur={}, size={}, bo={}, val={}", at, - field_size, (int) bo, *v); -} - -typedef enum bt_bfcr_status (*read_basic_and_call_cb_t)(struct bt_bfcr *, const uint8_t *, size_t); - -static inline enum bt_bfcr_status validate_contiguous_bo(struct bt_bfcr *bfcr, - enum ctf_byte_order next_bo) -{ - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - - /* Always valid when at a byte boundary */ - if (packet_at(bfcr) % 8 == 0) { - goto end; - } - - /* Always valid if last byte order is unknown */ - if (bfcr->last_bo == CTF_BYTE_ORDER_UNKNOWN) { - goto end; - } - - /* Always valid if next byte order is unknown */ - if (next_bo == CTF_BYTE_ORDER_UNKNOWN) { - goto end; - } - - /* Make sure last byte order is compatible with the next byte order */ - switch (bfcr->last_bo) { - case CTF_BYTE_ORDER_BIG: - if (next_bo != CTF_BYTE_ORDER_BIG) { - status = BT_BFCR_STATUS_ERROR; - } - break; - case CTF_BYTE_ORDER_LITTLE: - if (next_bo != CTF_BYTE_ORDER_LITTLE) { - status = BT_BFCR_STATUS_ERROR; - } - break; - default: - status = BT_BFCR_STATUS_ERROR; - } - -end: - if (status < 0) { - BT_CPPLOGW_SPEC(bfcr->logger, - "Cannot read bit array: two different byte orders not at a byte boundary: " - "bfcr-addr={}, last-bo={}, next-bo={}", - fmt::ptr(bfcr), (int) bfcr->last_bo, (int) next_bo); - } - - return status; -} - -static enum bt_bfcr_status read_basic_float_and_call_cb(struct bt_bfcr *bfcr, const uint8_t *buf, - size_t at) -{ - double dblval; - unsigned int field_size; - enum ctf_byte_order bo; - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - ctf_field_class_float *fc = ctf_field_class_as_float(bfcr->cur_basic_field_class); - - BT_ASSERT_DBG(fc); - field_size = fc->base.size; - bo = fc->base.byte_order; - bfcr->cur_bo = bo; - - switch (field_size) { - case 32: - { - uint64_t v; - union - { - uint32_t u; - float f; - } f32; - - read_unsigned_bitfield(bfcr, buf, at, field_size, bo, &v); - f32.u = (uint32_t) v; - dblval = (double) f32.f; - break; - } - case 64: - { - union - { - uint64_t u; - double d; - } f64; - - read_unsigned_bitfield(bfcr, buf, at, field_size, bo, &f64.u); - dblval = f64.d; - break; - } - default: - /* Only 32-bit and 64-bit fields are supported currently */ - bt_common_abort(); - } - - BT_CPPLOGT_SPEC(bfcr->logger, "Read floating point number value: bfcr={}, cur={}, val={}", - fmt::ptr(bfcr), at, dblval); - - if (bfcr->user.cbs.classes.floating_point) { - BT_CPPLOGT_SPEC(bfcr->logger, "Calling user function (floating point number)."); - status = bfcr->user.cbs.classes.floating_point(dblval, bfcr->cur_basic_field_class, - bfcr->user.data); - BT_CPPLOGT_SPEC(bfcr->logger, "User function returned: status={}", status); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, "User function failed: bfcr-addr={}, status={}", - fmt::ptr(bfcr), status); - } - } - - return status; -} - -static inline enum bt_bfcr_status read_basic_int_and_call_cb(struct bt_bfcr *bfcr, - const uint8_t *buf, size_t at) -{ - unsigned int field_size; - enum ctf_byte_order bo; - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - ctf_field_class_int *fc = ctf_field_class_as_int(bfcr->cur_basic_field_class); - - field_size = fc->base.size; - bo = fc->base.byte_order; - - /* - * Update current byte order now because we could be reading - * the integer value of an enumeration class, and thus we know - * here the actual supporting integer class's byte order. - */ - bfcr->cur_bo = bo; - - if (fc->is_signed) { - int64_t v; - - read_signed_bitfield(bfcr, buf, at, field_size, bo, &v); - - if (bfcr->user.cbs.classes.signed_int) { - BT_CPPLOGT_SPEC(bfcr->logger, "Calling user function (signed integer)."); - status = - bfcr->user.cbs.classes.signed_int(v, bfcr->cur_basic_field_class, bfcr->user.data); - BT_CPPLOGT_SPEC(bfcr->logger, "User function returned: status={}", status); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, - "User function failed: " - "bfcr-addr={}, status={}", - fmt::ptr(bfcr), status); - } - } - } else { - uint64_t v; - - read_unsigned_bitfield(bfcr, buf, at, field_size, bo, &v); - - if (bfcr->user.cbs.classes.unsigned_int) { - BT_CPPLOGT_SPEC(bfcr->logger, "Calling user function (unsigned integer)."); - status = bfcr->user.cbs.classes.unsigned_int(v, bfcr->cur_basic_field_class, - bfcr->user.data); - BT_CPPLOGT_SPEC(bfcr->logger, "User function returned: status={}", status); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, - "User function failed: " - "bfcr-addr={}, status={}", - fmt::ptr(bfcr), status); - } - } - } - - return status; -} - -static inline enum bt_bfcr_status -read_bit_array_class_and_call_continue(struct bt_bfcr *bfcr, - read_basic_and_call_cb_t read_basic_and_call_cb) -{ - size_t available; - size_t needed_bits; - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - ctf_field_class_bit_array *fc = ctf_field_class_as_bit_array(bfcr->cur_basic_field_class); - - if (!at_least_one_bit_left(bfcr)) { - BT_CPPLOGT_SPEC(bfcr->logger, "Reached end of data: bfcr-addr={}", fmt::ptr(bfcr)); - status = BT_BFCR_STATUS_EOF; - goto end; - } - - available = available_bits(bfcr); - needed_bits = fc->size - bfcr->stitch.at; - BT_CPPLOGT_SPEC(bfcr->logger, - "Continuing basic field decoding: " - "bfcr-addr={}, field-size={}, needed-size={}, " - "available-size={}", - fmt::ptr(bfcr), fc->size, needed_bits, available); - if (needed_bits <= available) { - /* We have all the bits; append to stitch, then decode */ - stitch_append_from_buf(bfcr, needed_bits); - status = read_basic_and_call_cb(bfcr, bfcr->stitch.buf, bfcr->stitch.offset); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, - "Cannot read basic field: " - "bfcr-addr={}, fc-addr={}, status={}", - fmt::ptr(bfcr), fmt::ptr(bfcr->cur_basic_field_class), status); - goto end; - } - - if (stack_empty(bfcr->stack)) { - /* Root is a basic class */ - bfcr->state = BFCR_STATE_DONE; - } else { - /* Go to next field */ - stack_top(bfcr->stack)->index++; - bfcr->state = BFCR_STATE_NEXT_FIELD; - bfcr->last_bo = bfcr->cur_bo; - } - goto end; - } - - /* We are here; it means we don't have enough data to decode this */ - BT_CPPLOGT_SPEC(bfcr->logger, - "Not enough data to read the next basic field: appending to stitch buffer."); - stitch_append_from_remaining_buf(bfcr); - status = BT_BFCR_STATUS_EOF; - -end: - return status; -} - -static inline enum bt_bfcr_status -read_bit_array_class_and_call_begin(struct bt_bfcr *bfcr, - read_basic_and_call_cb_t read_basic_and_call_cb) -{ - size_t available; - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - ctf_field_class_bit_array *fc = ctf_field_class_as_bit_array(bfcr->cur_basic_field_class); - - if (!at_least_one_bit_left(bfcr)) { - BT_CPPLOGT_SPEC(bfcr->logger, "Reached end of data: bfcr-addr={}", fmt::ptr(bfcr)); - status = BT_BFCR_STATUS_EOF; - goto end; - } - - status = validate_contiguous_bo(bfcr, fc->byte_order); - if (status != BT_BFCR_STATUS_OK) { - /* validate_contiguous_bo() logs errors */ - goto end; - } - - available = available_bits(bfcr); - - if (fc->size <= available) { - /* We have all the bits; decode and set now */ - BT_ASSERT_DBG(bfcr->buf.addr); - status = read_basic_and_call_cb(bfcr, bfcr->buf.addr, buf_at_from_addr(bfcr)); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, - "Cannot read basic field: " - "bfcr-addr={}, fc-addr={}, status={}", - fmt::ptr(bfcr), fmt::ptr(bfcr->cur_basic_field_class), status); - goto end; - } - - consume_bits(bfcr, fc->size); - - if (stack_empty(bfcr->stack)) { - /* Root is a basic class */ - bfcr->state = BFCR_STATE_DONE; - } else { - /* Go to next field */ - stack_top(bfcr->stack)->index++; - bfcr->state = BFCR_STATE_NEXT_FIELD; - bfcr->last_bo = bfcr->cur_bo; - } - - goto end; - } - - /* We are here; it means we don't have enough data to decode this */ - BT_CPPLOGT_SPEC(bfcr->logger, - "Not enough data to read the next basic field: setting stitch buffer."); - stitch_set_from_remaining_buf(bfcr); - bfcr->state = BFCR_STATE_READ_BASIC_CONTINUE; - status = BT_BFCR_STATUS_EOF; - -end: - return status; -} - -static inline enum bt_bfcr_status read_basic_int_class_and_call_begin(struct bt_bfcr *bfcr) -{ - return read_bit_array_class_and_call_begin(bfcr, read_basic_int_and_call_cb); -} - -static inline enum bt_bfcr_status read_basic_int_class_and_call_continue(struct bt_bfcr *bfcr) -{ - return read_bit_array_class_and_call_continue(bfcr, read_basic_int_and_call_cb); -} - -static inline enum bt_bfcr_status read_basic_float_class_and_call_begin(struct bt_bfcr *bfcr) -{ - return read_bit_array_class_and_call_begin(bfcr, read_basic_float_and_call_cb); -} - -static inline enum bt_bfcr_status read_basic_float_class_and_call_continue(struct bt_bfcr *bfcr) -{ - return read_bit_array_class_and_call_continue(bfcr, read_basic_float_and_call_cb); -} - -static inline enum bt_bfcr_status read_basic_string_class_and_call(struct bt_bfcr *bfcr, bool begin) -{ - size_t buf_at_bytes; - const uint8_t *result; - size_t available_bytes; - const uint8_t *first_chr; - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - - if (!at_least_one_bit_left(bfcr)) { - BT_CPPLOGT_SPEC(bfcr->logger, "Reached end of data: bfcr-addr={}", fmt::ptr(bfcr)); - status = BT_BFCR_STATUS_EOF; - goto end; - } - - BT_ASSERT_DBG(buf_at_from_addr(bfcr) % 8 == 0); - available_bytes = BITS_TO_BYTES_FLOOR(available_bits(bfcr)); - buf_at_bytes = BITS_TO_BYTES_FLOOR(buf_at_from_addr(bfcr)); - BT_ASSERT_DBG(bfcr->buf.addr); - first_chr = &bfcr->buf.addr[buf_at_bytes]; - result = (const uint8_t *) memchr(first_chr, '\0', available_bytes); - - if (begin && bfcr->user.cbs.classes.string_begin) { - BT_CPPLOGT_SPEC(bfcr->logger, "Calling user function (string, beginning)."); - status = bfcr->user.cbs.classes.string_begin(bfcr->cur_basic_field_class, bfcr->user.data); - BT_CPPLOGT_SPEC(bfcr->logger, "User function returned: status={}", status); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, "User function failed: bfcr-addr={}, status={}", - fmt::ptr(bfcr), status); - goto end; - } - } - - if (!result) { - /* No null character yet */ - if (bfcr->user.cbs.classes.string) { - BT_CPPLOGT_SPEC(bfcr->logger, "Calling user function (substring)."); - status = bfcr->user.cbs.classes.string((const char *) first_chr, available_bytes, - bfcr->cur_basic_field_class, bfcr->user.data); - BT_CPPLOGT_SPEC(bfcr->logger, "User function returned: status={}", status); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, - "User function failed: " - "bfcr-addr={}, status={}", - fmt::ptr(bfcr), status); - goto end; - } - } - - consume_bits(bfcr, BYTES_TO_BITS(available_bytes)); - bfcr->state = BFCR_STATE_READ_BASIC_CONTINUE; - status = BT_BFCR_STATUS_EOF; - } else { - /* Found the null character */ - size_t result_len = (size_t) (result - first_chr); - - if (bfcr->user.cbs.classes.string && result_len) { - BT_CPPLOGT_SPEC(bfcr->logger, "Calling user function (substring)."); - status = bfcr->user.cbs.classes.string((const char *) first_chr, result_len, - bfcr->cur_basic_field_class, bfcr->user.data); - BT_CPPLOGT_SPEC(bfcr->logger, "User function returned: status={}", status); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, - "User function failed: " - "bfcr-addr={}, status={}", - fmt::ptr(bfcr), status); - goto end; - } - } - - if (bfcr->user.cbs.classes.string_end) { - BT_CPPLOGT_SPEC(bfcr->logger, "Calling user function (string, end)."); - status = - bfcr->user.cbs.classes.string_end(bfcr->cur_basic_field_class, bfcr->user.data); - BT_CPPLOGT_SPEC(bfcr->logger, "User function returned: status={}", status); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, - "User function failed: " - "bfcr-addr={}, status={}", - fmt::ptr(bfcr), status); - goto end; - } - } - - consume_bits(bfcr, BYTES_TO_BITS(result_len + 1)); - - if (stack_empty(bfcr->stack)) { - /* Root is a basic class */ - bfcr->state = BFCR_STATE_DONE; - } else { - /* Go to next field */ - stack_top(bfcr->stack)->index++; - bfcr->state = BFCR_STATE_NEXT_FIELD; - bfcr->last_bo = bfcr->cur_bo; - } - } - -end: - return status; -} - -static inline enum bt_bfcr_status read_basic_begin_state(struct bt_bfcr *bfcr) -{ - enum bt_bfcr_status status; - - BT_ASSERT_DBG(bfcr->cur_basic_field_class); - - switch (bfcr->cur_basic_field_class->type) { - case CTF_FIELD_CLASS_TYPE_INT: - case CTF_FIELD_CLASS_TYPE_ENUM: - status = read_basic_int_class_and_call_begin(bfcr); - break; - case CTF_FIELD_CLASS_TYPE_FLOAT: - status = read_basic_float_class_and_call_begin(bfcr); - break; - case CTF_FIELD_CLASS_TYPE_STRING: - status = read_basic_string_class_and_call(bfcr, true); - break; - default: - bt_common_abort(); - } - - return status; -} - -static inline enum bt_bfcr_status read_basic_continue_state(struct bt_bfcr *bfcr) -{ - enum bt_bfcr_status status; - - BT_ASSERT_DBG(bfcr->cur_basic_field_class); - - switch (bfcr->cur_basic_field_class->type) { - case CTF_FIELD_CLASS_TYPE_INT: - case CTF_FIELD_CLASS_TYPE_ENUM: - status = read_basic_int_class_and_call_continue(bfcr); - break; - case CTF_FIELD_CLASS_TYPE_FLOAT: - status = read_basic_float_class_and_call_continue(bfcr); - break; - case CTF_FIELD_CLASS_TYPE_STRING: - status = read_basic_string_class_and_call(bfcr, false); - break; - default: - bt_common_abort(); - } - - return status; -} - -static inline size_t bits_to_skip_to_align_to(struct bt_bfcr *bfcr, size_t align) -{ - size_t aligned_packet_at; - - aligned_packet_at = BT_ALIGN(packet_at(bfcr), align); - return aligned_packet_at - packet_at(bfcr); -} - -static inline enum bt_bfcr_status align_class_state(struct bt_bfcr *bfcr, - struct ctf_field_class *field_class, - enum bfcr_state next_state) -{ - unsigned int field_alignment; - size_t skip_bits; - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - - /* Get field's alignment */ - field_alignment = field_class->alignment; - - /* - * 0 means "undefined" for variants; what we really want is 1 - * (always aligned) - */ - BT_ASSERT_DBG(field_alignment >= 1); - - /* Compute how many bits we need to skip */ - skip_bits = bits_to_skip_to_align_to(bfcr, (size_t) field_alignment); - - /* Nothing to skip? aligned */ - if (skip_bits == 0) { - bfcr->state = next_state; - goto end; - } - - /* Make sure there's at least one bit left */ - if (!at_least_one_bit_left(bfcr)) { - status = BT_BFCR_STATUS_EOF; - goto end; - } - - /* Consume as many bits as possible in what's left */ - consume_bits(bfcr, MIN(available_bits(bfcr), skip_bits)); - - /* Are we done now? */ - skip_bits = bits_to_skip_to_align_to(bfcr, field_alignment); - if (skip_bits == 0) { - /* Yes: go to next state */ - bfcr->state = next_state; - goto end; - } else { - /* No: need more data */ - BT_CPPLOGT_SPEC(bfcr->logger, "Reached end of data when aligning: bfcr-addr={}", - fmt::ptr(bfcr)); - status = BT_BFCR_STATUS_EOF; - } - -end: - return status; -} - -static inline enum bt_bfcr_status next_field_state(struct bt_bfcr *bfcr) -{ - int ret; - struct stack_entry *top; - struct ctf_field_class *next_field_class = NULL; - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - - if (stack_empty(bfcr->stack)) { - goto end; - } - - top = stack_top(bfcr->stack); - - /* Are we done with this base class? */ - while (top->index == top->base_len) { - if (bfcr->user.cbs.classes.compound_end) { - BT_CPPLOGT_SPEC(bfcr->logger, "Calling user function (compound, end)."); - status = bfcr->user.cbs.classes.compound_end(top->base_class, bfcr->user.data); - BT_CPPLOGT_SPEC(bfcr->logger, "User function returned: status={}", status); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, "User function failed: bfcr-addr={}, status={}", - fmt::ptr(bfcr), status); - goto end; - } - } - - stack_pop(bfcr->stack); - - /* Are we done with the root class? */ - if (stack_empty(bfcr->stack)) { - bfcr->state = BFCR_STATE_DONE; - goto end; - } - - top = stack_top(bfcr->stack); - top->index++; - } - - /* Get next field's class */ - switch (top->base_class->type) { - case CTF_FIELD_CLASS_TYPE_STRUCT: - next_field_class = ctf_field_class_struct_borrow_member_by_index( - ctf_field_class_as_struct(top->base_class), (uint64_t) top->index) - ->fc; - break; - case CTF_FIELD_CLASS_TYPE_ARRAY: - case CTF_FIELD_CLASS_TYPE_SEQUENCE: - { - ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(top->base_class); - - next_field_class = array_fc->elem_fc; - break; - } - case CTF_FIELD_CLASS_TYPE_VARIANT: - /* Variant classes are dynamic: the user should know! */ - next_field_class = bfcr->user.cbs.query.borrow_variant_selected_field_class( - top->base_class, bfcr->user.data); - break; - default: - break; - } - - if (!next_field_class) { - BT_CPPLOGW_SPEC(bfcr->logger, - "Cannot get the field class of the next field: " - "bfcr-addr={}, base-fc-addr={}, base-fc-type={}, index={}", - fmt::ptr(bfcr), fmt::ptr(top->base_class), (int) top->base_class->type, - top->index); - status = BT_BFCR_STATUS_ERROR; - goto end; - } - - if (next_field_class->is_compound) { - if (bfcr->user.cbs.classes.compound_begin) { - BT_CPPLOGT_SPEC(bfcr->logger, "Calling user function (compound, begin)."); - status = bfcr->user.cbs.classes.compound_begin(next_field_class, bfcr->user.data); - BT_CPPLOGT_SPEC(bfcr->logger, "User function returned: status={}", status); - if (status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, "User function failed: bfcr-addr={}, status={}", - fmt::ptr(bfcr), status); - goto end; - } - } - - ret = stack_push_with_len(bfcr, next_field_class); - if (ret) { - /* stack_push_with_len() logs errors */ - status = BT_BFCR_STATUS_ERROR; - goto end; - } - - /* Next state: align a compound class */ - bfcr->state = BFCR_STATE_ALIGN_COMPOUND; - } else { - /* Replace current basic field class */ - BT_CPPLOGT_SPEC(bfcr->logger, - "Replacing current basic field class: " - "bfcr-addr={}, cur-basic-fc-addr={}, " - "next-basic-fc-addr={}", - fmt::ptr(bfcr), fmt::ptr(bfcr->cur_basic_field_class), - fmt::ptr(next_field_class)); - bfcr->cur_basic_field_class = next_field_class; - - /* Next state: align a basic class */ - bfcr->state = BFCR_STATE_ALIGN_BASIC; - } - -end: - return status; -} - -static inline enum bt_bfcr_status handle_state(struct bt_bfcr *bfcr) -{ - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - - BT_CPPLOGT_SPEC(bfcr->logger, "Handling state: bfcr-addr={}, state={}", fmt::ptr(bfcr), - bfcr->state); - - switch (bfcr->state) { - case BFCR_STATE_NEXT_FIELD: - status = next_field_state(bfcr); - break; - case BFCR_STATE_ALIGN_BASIC: - status = align_class_state(bfcr, bfcr->cur_basic_field_class, BFCR_STATE_READ_BASIC_BEGIN); - break; - case BFCR_STATE_ALIGN_COMPOUND: - status = align_class_state(bfcr, stack_top(bfcr->stack)->base_class, BFCR_STATE_NEXT_FIELD); - break; - case BFCR_STATE_READ_BASIC_BEGIN: - status = read_basic_begin_state(bfcr); - break; - case BFCR_STATE_READ_BASIC_CONTINUE: - status = read_basic_continue_state(bfcr); - break; - case BFCR_STATE_DONE: - break; - } - - BT_CPPLOGT_SPEC(bfcr->logger, "Handled state: bfcr-addr={}, status={}", fmt::ptr(bfcr), status); - return status; -} - -struct bt_bfcr *bt_bfcr_create(struct bt_bfcr_cbs cbs, void *data, const bt2c::Logger& logger) -{ - BT_CPPLOGD_SPEC(logger, "Creating binary field class reader (BFCR)."); - - bt_bfcr *bfcr = new bt_bfcr {logger}; - bfcr->stack = stack_new(bfcr); - if (!bfcr->stack) { - BT_CPPLOGE_SPEC(bfcr->logger, "Cannot create BFCR's stack."); - bt_bfcr_destroy(bfcr); - bfcr = NULL; - goto end; - } - - bfcr->state = BFCR_STATE_NEXT_FIELD; - bfcr->user.cbs = cbs; - bfcr->user.data = data; - BT_CPPLOGD_SPEC(bfcr->logger, "Created BFCR: addr={}", fmt::ptr(bfcr)); - -end: - return bfcr; -} - -void bt_bfcr_destroy(struct bt_bfcr *bfcr) -{ - if (bfcr->stack) { - stack_destroy(bfcr->stack); - } - - BT_CPPLOGD_SPEC(bfcr->logger, "Destroying BFCR: addr={}", fmt::ptr(bfcr)); - delete bfcr; -} - -static void reset(struct bt_bfcr *bfcr) -{ - BT_CPPLOGD_SPEC(bfcr->logger, "Resetting BFCR: addr={}", fmt::ptr(bfcr)); - stack_clear(bfcr->stack); - stitch_reset(bfcr); - bfcr->buf.addr = NULL; - bfcr->last_bo = CTF_BYTE_ORDER_UNKNOWN; -} - -static void update_packet_offset(struct bt_bfcr *bfcr) -{ - BT_CPPLOGT_SPEC(bfcr->logger, - "Updating packet offset for next call: " - "bfcr-addr={}, cur-packet-offset={}, next-packet-offset={}", - fmt::ptr(bfcr), bfcr->buf.packet_offset, - bfcr->buf.packet_offset + bfcr->buf.at); - bfcr->buf.packet_offset += bfcr->buf.at; -} - -size_t bt_bfcr_start(struct bt_bfcr *bfcr, struct ctf_field_class *cls, const uint8_t *buf, - size_t offset, size_t packet_offset, size_t sz, enum bt_bfcr_status *status) -{ - BT_ASSERT_DBG(bfcr); - BT_ASSERT_DBG(BYTES_TO_BITS(sz) >= offset); - reset(bfcr); - bfcr->buf.addr = buf; - bfcr->buf.offset = offset; - bfcr->buf.at = 0; - bfcr->buf.packet_offset = packet_offset; - bfcr->buf.buf_sz = sz; - bfcr->buf.sz = BYTES_TO_BITS(sz) - offset; - *status = BT_BFCR_STATUS_OK; - - BT_CPPLOGT_SPEC(bfcr->logger, - "Starting decoding: bfcr-addr={}, fc-addr={}, " - "buf-addr={}, buf-size={}, offset={}, " - "packet-offset={}", - fmt::ptr(bfcr), fmt::ptr(cls), fmt::ptr(buf), sz, offset, packet_offset); - - /* Set root class */ - if (cls->is_compound) { - /* Compound class: push on visit stack */ - int stack_ret; - - if (bfcr->user.cbs.classes.compound_begin) { - BT_CPPLOGT_SPEC(bfcr->logger, "Calling user function (compound, begin)."); - *status = bfcr->user.cbs.classes.compound_begin(cls, bfcr->user.data); - BT_CPPLOGT_SPEC(bfcr->logger, "User function returned: status={}", *status); - if (*status != BT_BFCR_STATUS_OK) { - BT_CPPLOGW_SPEC(bfcr->logger, "User function failed: bfcr-addr={}, status={}", - fmt::ptr(bfcr), *status); - goto end; - } - } - - stack_ret = stack_push_with_len(bfcr, cls); - if (stack_ret) { - /* stack_push_with_len() logs errors */ - *status = BT_BFCR_STATUS_ERROR; - goto end; - } - - bfcr->state = BFCR_STATE_ALIGN_COMPOUND; - } else { - /* Basic class: set as current basic class */ - bfcr->cur_basic_field_class = cls; - bfcr->state = BFCR_STATE_ALIGN_BASIC; - } - - /* Run the machine! */ - BT_CPPLOGT_SPEC(bfcr->logger, "Running the state machine."); - - while (true) { - *status = handle_state(bfcr); - if (*status != BT_BFCR_STATUS_OK || bfcr->state == BFCR_STATE_DONE) { - break; - } - } - - /* Update packet offset for next time */ - update_packet_offset(bfcr); - -end: - return bfcr->buf.at; -} - -size_t bt_bfcr_continue(struct bt_bfcr *bfcr, const uint8_t *buf, size_t sz, - enum bt_bfcr_status *status) -{ - BT_ASSERT_DBG(bfcr); - BT_ASSERT_DBG(buf); - BT_ASSERT_DBG(sz > 0); - bfcr->buf.addr = buf; - bfcr->buf.offset = 0; - bfcr->buf.at = 0; - bfcr->buf.buf_sz = sz; - bfcr->buf.sz = BYTES_TO_BITS(sz); - *status = BT_BFCR_STATUS_OK; - - BT_CPPLOGT_SPEC(bfcr->logger, "Continuing decoding: bfcr-addr={}, buf-addr={}, buf-size={}", - fmt::ptr(bfcr), fmt::ptr(buf), sz); - - /* Continue running the machine */ - BT_CPPLOGT_SPEC(bfcr->logger, "Running the state machine."); - - while (true) { - *status = handle_state(bfcr); - if (*status != BT_BFCR_STATUS_OK || bfcr->state == BFCR_STATE_DONE) { - break; - } - } - - /* Update packet offset for next time */ - update_packet_offset(bfcr); - return bfcr->buf.at; -} - -void bt_bfcr_set_unsigned_int_cb(struct bt_bfcr *bfcr, bt_bfcr_unsigned_int_cb_func cb) -{ - BT_ASSERT_DBG(bfcr); - BT_ASSERT_DBG(cb); - bfcr->user.cbs.classes.unsigned_int = cb; -} diff --git a/src/plugins/ctf/common/src/bfcr/bfcr.hpp b/src/plugins/ctf/common/src/bfcr/bfcr.hpp deleted file mode 100644 index f43f2109..00000000 --- a/src/plugins/ctf/common/src/bfcr/bfcr.hpp +++ /dev/null @@ -1,358 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation - * Copyright (c) 2015-2016 Philippe Proulx - * - * Babeltrace - CTF binary field class reader (BFCR) - */ - -#ifndef BABELTRACE_PLUGINS_CTF_COMMON_SRC_BFCR_BFCR_HPP -#define BABELTRACE_PLUGINS_CTF_COMMON_SRC_BFCR_BFCR_HPP - -#include -#include - -#include - -#include "cpp-common/vendor/fmt/format.h" /* IWYU pragma: keep */ - -#include "../metadata/tsdl/ctf-meta.hpp" - -namespace bt2c { - -class Logger; - -} /* namespace bt2c */ - -/** - * @file bfcr.h - * - * Event-driven CTF binary field class reader (BFCR). - * - * This is a common, internal API used by CTF source plugins. It allows - * a binary CTF IR field class to be decoded from user-provided buffers. - * As the class is decoded (and, possibly, its nested classes), - * registered user callback functions are called. - * - * This API is only concerned with reading one CTF class at a time from - * one or more buffer of bytes. It does not know CTF dynamic scopes, - * events, or streams. Sequence lengths and selected variant classes are - * requested to the user when needed. - */ - -/** - * Binary class reader API status codes. - */ -enum bt_bfcr_status -{ - /** Out of memory. */ - BT_BFCR_STATUS_ENOMEM = -5, - /** - * The binary stream reader reached the end of the user-provided - * buffer, but data is still needed to finish decoding the - * requested class. - * - * The user needs to call bt_bfcr_continue() as long as - * #BT_BFCR_STATUS_EOF is returned to complete the decoding - * process of a given class. - */ - BT_BFCR_STATUS_EOF = 1, - - /** Invalid argument. */ - BT_BFCR_STATUS_INVAL = -3, - - /** General error. */ - BT_BFCR_STATUS_ERROR = -1, - - /** Everything okay. */ - BT_BFCR_STATUS_OK = 0, -}; - -inline const char *format_as(bt_bfcr_status status) noexcept -{ - switch (status) { - case BT_BFCR_STATUS_ENOMEM: - return "BT_BFCR_STATUS_ENOMEM"; - - case BT_BFCR_STATUS_EOF: - return "BT_BFCR_STATUS_EOF"; - - case BT_BFCR_STATUS_INVAL: - return "BT_BFCR_STATUS_INVAL"; - - case BT_BFCR_STATUS_ERROR: - return "BT_BFCR_STATUS_ERROR"; - - case BT_BFCR_STATUS_OK: - return "BT_BFCR_STATUS_OK"; - break; - } - - bt_common_abort(); -} - -typedef enum bt_bfcr_status (*bt_bfcr_unsigned_int_cb_func)(uint64_t, struct ctf_field_class *, - void *); - -/* - * Field class reader user callback functions. - */ -struct bt_bfcr_cbs -{ - /** - * Field class callback functions. - * - * This CTF binary class reader is event-driven. The following - * functions are called during the decoding process, either when - * a compound class begins/ends, or when a basic class is - * completely decoded (along with its value). - * - * Each function also receives the CTF field class associated - * with the call, and user data (registered to the class reader - * calling them). - * - * Actual trace IR fields are \em not created here; this would - * be the responsibility of a class reader's user (the provider - * of those callback functions). - * - * All the class callback functions return one of the following - * values: - * - * - #BT_BFCR_STATUS_OK: Everything is okay; - * continue the decoding process. - * - #BT_BFCR_STATUS_ERROR: General error (reported - * to class reader's user). - * - * Any member of this structure may be set to \c NULL, should - * a specific message be not needed. - */ - struct - { - /** - * Called when a signed integer class is completely - * decoded. This could also be the supporting signed - * integer class of an enumeration class (\p class will - * indicate this). - * - * @param value Signed integer value - * @param class Integer or enumeration class - * @param data User data - * @returns #BT_BFCR_STATUS_OK or - * #BT_BFCR_STATUS_ERROR - */ - enum bt_bfcr_status (*signed_int)(int64_t value, struct ctf_field_class *cls, void *data); - - /** - * Called when an unsigned integer class is completely - * decoded. This could also be the supporting signed - * integer class of an enumeration class (\p class will - * indicate this). - * - * @param value Unsigned integer value - * @param class Integer or enumeration class - * @param data User data - * @returns #BT_BFCR_STATUS_OK or - * #BT_BFCR_STATUS_ERROR - */ - bt_bfcr_unsigned_int_cb_func unsigned_int; - - /** - * Called when a floating point number class is - * completely decoded. - * - * @param value Floating point number value - * @param class Floating point number class - * @param data User data - * @returns #BT_BFCR_STATUS_OK or - * #BT_BFCR_STATUS_ERROR - */ - enum bt_bfcr_status (*floating_point)(double value, struct ctf_field_class *cls, - void *data); - - /** - * Called when a string class begins. - * - * All the following user callback function calls will - * be made to bt_bfcr_cbs::classes::string(), each of - * them providing one substring of the complete string - * class's value. - * - * @param class Beginning string class - * @param data User data - * @returns #BT_BFCR_STATUS_OK or - * #BT_BFCR_STATUS_ERROR - */ - enum bt_bfcr_status (*string_begin)(struct ctf_field_class *cls, void *data); - - /** - * Called when a string class's substring is decoded - * (between a call to bt_bfcr_cbs::classes::string_begin() - * and a call to bt_bfcr_cbs::classes::string_end()). - * - * @param value String value (\em not null-terminated) - * @param len String value length - * @param class String class - * @param data User data - * @returns #BT_BFCR_STATUS_OK or - * #BT_BFCR_STATUS_ERROR - */ - enum bt_bfcr_status (*string)(const char *value, size_t len, struct ctf_field_class *cls, - void *data); - - /** - * Called when a string class ends. - * - * @param class Ending string class - * @param data User data - * @returns #BT_BFCR_STATUS_OK or - * #BT_BFCR_STATUS_ERROR - */ - enum bt_bfcr_status (*string_end)(struct ctf_field_class *cls, void *data); - - /** - * Called when a compound class begins. - * - * All the following class callback function calls will - * signal sequential elements of this compound class, - * until the next corresponding - * bt_bfcr_cbs::classes::compound_end() is called. - * - * If \p class is a variant class, then only one class - * callback function call will follow before the call to - * bt_bfcr_cbs::classes::compound_end(). This single - * call indicates the selected class of this variant - * class. - * - * @param class Beginning compound class - * @param data User data - * @returns #BT_BFCR_STATUS_OK or - * #BT_BFCR_STATUS_ERROR - */ - enum bt_bfcr_status (*compound_begin)(struct ctf_field_class *cls, void *data); - - /** - * Called when a compound class ends. - * - * @param class Ending compound class - * @param data User data - * @returns #BT_BFCR_STATUS_OK or - * #BT_BFCR_STATUS_ERROR - */ - enum bt_bfcr_status (*compound_end)(struct ctf_field_class *cls, void *data); - } classes; - - /** - * Query callback functions are used when the class reader needs - * dynamic information, i.e. a sequence class's current length - * or a variant class's current selected class. - * - * Both functions need to be set unless it is known that no - * sequences or variants will have to be decoded. - */ - struct - { - /** - * Called to query the current length of a given sequence - * class. - * - * @param class Sequence class - * @param data User data - * @returns Sequence length or - * #BT_BFCR_STATUS_ERROR on error - */ - int64_t (*get_sequence_length)(struct ctf_field_class *cls, void *data); - - /** - * Called to query the current selected class of a given - * variant class. - * - * @param class Variant class - * @param data User data - * @returns Current selected class (owned by - * this) or \c NULL on error - */ - struct ctf_field_class *(*borrow_variant_selected_field_class)(struct ctf_field_class *cls, - void *data); - } query; -}; - -/** - * Creates a CTF binary class reader. - * - * @param cbs User callback functions - * @param data User data (passed to user callback functions) - * @returns New binary class reader on success, or \c NULL on error - */ -struct bt_bfcr *bt_bfcr_create(struct bt_bfcr_cbs cbs, void *data, const bt2c::Logger& logger); - -/** - * Destroys a CTF binary class reader, freeing all internal resources. - * - * @param bfcr Binary class reader - */ -void bt_bfcr_destroy(struct bt_bfcr *bfcr); - -/** - * Decodes a given CTF class from a buffer of bytes. - * - * The number of \em bits consumed by this function is returned. - * - * The \p status output parameter is where a status is written, amongst - * the following: - * - * - #BT_BFCR_STATUS_OK: Decoding is done. - * - #BT_BFCR_STATUS_EOF: The end of the buffer was reached, - * but more data is needed to finish the decoding process of the - * requested class. The user needs to call bt_bfcr_continue() - * as long as #BT_BFCR_STATUS_EOF is returned to complete the - * decoding process of the original class. - * - #BT_BFCR_STATUS_INVAL: Invalid argument. - * - #BT_BFCR_STATUS_ERROR: General error. - * - * Calling this function resets the class reader's internal state. If - * #BT_BFCR_STATUS_EOF is returned, bt_bfcr_continue() needs to - * be called next, \em not bt_bfcr_decode(). - * - * @param bfcr Binary class reader - * @param class Field class to decode - * @param buf Buffer - * @param offset Offset of first bit from \p buf (bits) - * @param packet_offset Offset of \p offset within the CTF - * binary packet containing \p class (bits) - * @param sz Size of buffer in bytes (from \p buf) - * @param status Returned status (see description above) - * @returns Number of consumed bits - */ -size_t bt_bfcr_start(struct bt_bfcr *bfcr, struct ctf_field_class *cls, const uint8_t *buf, - size_t offset, size_t packet_offset, size_t sz, enum bt_bfcr_status *status); - -/** - * Continues the decoding process a given CTF class. - * - * The number of bits consumed by this function is returned. - * - * The \p status output parameter is where a status is placed, amongst - * the following: - * - * - #BT_BFCR_STATUS_OK: decoding is done. - * - #BT_BFCR_STATUS_EOF: the end of the buffer was reached, - * but more data is needed to finish the decoding process of the - * requested class. The user needs to call bt_bfcr_continue() - * as long as #BT_BFCR_STATUS_EOF is returned to complete the - * decoding process of the original class. - * - #BT_BFCR_STATUS_INVAL: invalid argument. - * - #BT_BFCR_STATUS_ERROR: general error. - * - * @param bfcr Binary class reader - * @param buf Buffer - * @param sz Size of buffer in bytes (from \p offset) - * @param status Returned status (see description above) - * @returns Number of consumed bits - */ -size_t bt_bfcr_continue(struct bt_bfcr *bfcr, const uint8_t *buf, size_t sz, - enum bt_bfcr_status *status); - -void bt_bfcr_set_unsigned_int_cb(struct bt_bfcr *bfcr, bt_bfcr_unsigned_int_cb_func cb); - -#endif /* BABELTRACE_PLUGINS_CTF_COMMON_SRC_BFCR_BFCR_HPP */ diff --git a/src/plugins/ctf/common/src/metadata/tsdl/ast.hpp b/src/plugins/ctf/common/src/metadata/tsdl/ast.hpp index 356d9719..d17db5ac 100644 --- a/src/plugins/ctf/common/src/metadata/tsdl/ast.hpp +++ b/src/plugins/ctf/common/src/metadata/tsdl/ast.hpp @@ -17,8 +17,6 @@ #include "common/assert.h" #include "common/list.h" -#include "cpp-common/bt2/self-component-port.hpp" -#include "cpp-common/bt2/trace-ir.hpp" #include "cpp-common/bt2c/logging.hpp" #include "cpp-common/vendor/fmt/format.h" /* IWYU pragma: keep */ @@ -483,11 +481,8 @@ struct ctf_visitor_generate_ir { using UP = std::unique_ptr; - explicit ctf_visitor_generate_ir( - const bt2::OptionalBorrowedObject selfCompParam, - bt2c::Logger loggerParam) noexcept : - logger {std::move(loggerParam)}, - selfComp {selfCompParam} + explicit ctf_visitor_generate_ir(const bt2c::Logger& parentLogger) : + logger {parentLogger, "PLUGIN/CTF/VISITOR-GENERATE-IR"} { } @@ -495,11 +490,6 @@ struct ctf_visitor_generate_ir bt2c::Logger logger; - bt2::OptionalBorrowedObject selfComp; - - /* Trace IR trace class being filled (owned by this) */ - bt2::TraceClass::Shared trace_class; - /* CTF meta trace being filled (owned by this) */ struct ctf_trace_class *ctf_tc = nullptr; @@ -513,15 +503,7 @@ struct ctf_visitor_generate_ir bool is_lttng = false; }; -ctf_visitor_generate_ir::UP -ctf_visitor_generate_ir_create(const bt2::OptionalBorrowedObject selfComp, - const bt2c::Logger& parentLogger); - -bt2::TraceClass::Shared -ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir *visitor); - -struct ctf_trace_class * -ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir *visitor); +ctf_visitor_generate_ir::UP ctf_visitor_generate_ir_create(const bt2c::Logger& parentLogger); int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, struct ctf_node *node); @@ -574,12 +556,6 @@ error: return g_string_free(str, TRUE); } -#ifndef BT_COMP_LOG_CUR_LVL -# define BT_AST_LOG_LEVEL_UNUSED_ATTR __attribute__((unused)) -#else -# define BT_AST_LOG_LEVEL_UNUSED_ATTR -#endif - static inline int ctf_ast_get_unary_uuid(struct bt_list_head *head, bt_uuid_t uuid, const bt2c::Logger& logger) { diff --git a/src/plugins/ctf/common/src/metadata/tsdl/ctf-1-metadata-stream-parser.cpp b/src/plugins/ctf/common/src/metadata/tsdl/ctf-1-metadata-stream-parser.cpp index 84cd326f..7500fad1 100644 --- a/src/plugins/ctf/common/src/metadata/tsdl/ctf-1-metadata-stream-parser.cpp +++ b/src/plugins/ctf/common/src/metadata/tsdl/ctf-1-metadata-stream-parser.cpp @@ -694,7 +694,7 @@ Ctf1MetadataStreamParser::Ctf1MetadataStreamParser( const bt2c::Logger& parentLogger) : MetadataStreamParser {selfComp, clkClsCfg}, _mLogger {parentLogger, "PLUGIN/CTF/CTF-1-META-STREAM-PARSER"}, - _mOrigCtfIrGenerator {ctf_visitor_generate_ir_create({}, _mLogger)}, + _mOrigCtfIrGenerator {ctf_visitor_generate_ir_create(_mLogger)}, _mScanner {ctf_scanner_alloc(_mLogger)}, _mStreamDecoder {_mLogger} { } diff --git a/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-translate.cpp b/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-translate.cpp deleted file mode 100644 index 9b3992a3..00000000 --- a/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-translate.cpp +++ /dev/null @@ -1,656 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright 2018 Philippe Proulx - */ - -#include -#include - -#include - -#include "common/assert.h" - -#include "ctf-meta-visitors.hpp" - -namespace ctf { - -struct MetaTranslateCtx -{ - bt2::OptionalBorrowedObject selfComp; - bt_trace_class *ir_tc; - bt_stream_class *ir_sc; - struct ctf_trace_class *tc; - struct ctf_stream_class *sc; - struct ctf_event_class *ec; - enum ctf_scope scope; -}; - -} /* namespace ctf */ - -static inline bt_field_class *ctf_field_class_to_ir(ctf::MetaTranslateCtx *ctx, - struct ctf_field_class *fc); - -static inline void ctf_field_class_int_set_props(struct ctf_field_class_int *fc, - bt_field_class *ir_fc) -{ - bt_field_class_integer_set_field_value_range(ir_fc, fc->base.size); - bt_field_class_integer_set_preferred_display_base(ir_fc, fc->disp_base); -} - -static inline bt_field_class *ctf_field_class_int_to_ir(ctf::MetaTranslateCtx *ctx, - struct ctf_field_class_int *fc) -{ - bt_field_class *ir_fc; - - if (fc->is_signed) { - ir_fc = bt_field_class_integer_signed_create(ctx->ir_tc); - } else { - ir_fc = bt_field_class_integer_unsigned_create(ctx->ir_tc); - } - - BT_ASSERT(ir_fc); - ctf_field_class_int_set_props(fc, ir_fc); - return ir_fc; -} - -static inline bt_field_class *ctf_field_class_enum_to_ir(ctf::MetaTranslateCtx *ctx, - struct ctf_field_class_enum *fc) -{ - int ret; - bt_field_class *ir_fc; - uint64_t i; - - if (fc->base.is_signed) { - ir_fc = bt_field_class_enumeration_signed_create(ctx->ir_tc); - } else { - ir_fc = bt_field_class_enumeration_unsigned_create(ctx->ir_tc); - } - - BT_ASSERT(ir_fc); - ctf_field_class_int_set_props(&fc->base, ir_fc); - - for (i = 0; i < fc->mappings->len; i++) { - struct ctf_field_class_enum_mapping *mapping = - ctf_field_class_enum_borrow_mapping_by_index(fc, i); - bt_integer_range_set_signed *range_set_signed = NULL; - bt_integer_range_set_unsigned *range_set_unsigned = NULL; - uint64_t range_i; - - if (fc->base.is_signed) { - range_set_signed = bt_integer_range_set_signed_create(); - BT_ASSERT(range_set_signed); - } else { - range_set_unsigned = bt_integer_range_set_unsigned_create(); - BT_ASSERT(range_set_unsigned); - } - - for (range_i = 0; range_i < mapping->ranges->len; range_i++) { - struct ctf_range *range = - ctf_field_class_enum_mapping_borrow_range_by_index(mapping, range_i); - - if (fc->base.is_signed) { - ret = bt_integer_range_set_signed_add_range(range_set_signed, range->lower.i, - range->upper.i); - } else { - ret = bt_integer_range_set_unsigned_add_range(range_set_unsigned, range->lower.u, - range->upper.u); - } - - BT_ASSERT(ret == 0); - } - - if (fc->base.is_signed) { - ret = bt_field_class_enumeration_signed_add_mapping(ir_fc, mapping->label->str, - range_set_signed); - BT_INTEGER_RANGE_SET_SIGNED_PUT_REF_AND_RESET(range_set_signed); - } else { - ret = bt_field_class_enumeration_unsigned_add_mapping(ir_fc, mapping->label->str, - range_set_unsigned); - BT_INTEGER_RANGE_SET_UNSIGNED_PUT_REF_AND_RESET(range_set_unsigned); - } - - BT_ASSERT(ret == 0); - } - - return ir_fc; -} - -static inline bt_field_class *ctf_field_class_float_to_ir(ctf::MetaTranslateCtx *ctx, - struct ctf_field_class_float *fc) -{ - bt_field_class *ir_fc; - - if (fc->base.size == 32) { - ir_fc = bt_field_class_real_single_precision_create(ctx->ir_tc); - } else { - ir_fc = bt_field_class_real_double_precision_create(ctx->ir_tc); - } - BT_ASSERT(ir_fc); - - return ir_fc; -} - -static inline bt_field_class *ctf_field_class_string_to_ir(ctf::MetaTranslateCtx *ctx) -{ - bt_field_class *ir_fc = bt_field_class_string_create(ctx->ir_tc); - - BT_ASSERT(ir_fc); - return ir_fc; -} - -static inline void translate_struct_field_class_members(ctf::MetaTranslateCtx *ctx, - struct ctf_field_class_struct *fc, - bt_field_class *ir_fc, bool, - struct ctf_field_class_struct *) -{ - uint64_t i; - int ret; - - for (i = 0; i < fc->members->len; i++) { - struct ctf_named_field_class *named_fc = - ctf_field_class_struct_borrow_member_by_index(fc, i); - bt_field_class *member_ir_fc; - const char *name = named_fc->name->str; - - if (!named_fc->fc->in_ir) { - continue; - } - - member_ir_fc = ctf_field_class_to_ir(ctx, named_fc->fc); - BT_ASSERT(member_ir_fc); - ret = bt_field_class_structure_append_member(ir_fc, name, member_ir_fc); - BT_ASSERT(ret == 0); - bt_field_class_put_ref(member_ir_fc); - } -} - -static inline bt_field_class *ctf_field_class_struct_to_ir(ctf::MetaTranslateCtx *ctx, - struct ctf_field_class_struct *fc) -{ - bt_field_class *ir_fc = bt_field_class_structure_create(ctx->ir_tc); - - BT_ASSERT(ir_fc); - translate_struct_field_class_members(ctx, fc, ir_fc, false, NULL); - return ir_fc; -} - -static inline bt_field_class *borrow_ir_fc_from_field_path(ctf::MetaTranslateCtx *ctx, - struct ctf_field_path *field_path) -{ - bt_field_class *ir_fc = NULL; - struct ctf_field_class *fc = - ctf_field_path_borrow_field_class(field_path, ctx->tc, ctx->sc, ctx->ec); - - BT_ASSERT(fc); - - if (fc->in_ir) { - ir_fc = fc->ir_fc; - } - - return ir_fc; -} - -static inline const bt_field_class_enumeration_mapping * -find_ir_enum_field_class_mapping_by_label(const bt_field_class *fc, const char *label, - bool is_signed) -{ - const bt_field_class_enumeration_mapping *mapping = NULL; - uint64_t i; - - for (i = 0; i < bt_field_class_enumeration_get_mapping_count(fc); i++) { - const bt_field_class_enumeration_mapping *this_mapping; - const bt_field_class_enumeration_signed_mapping *signed_this_mapping = NULL; - const bt_field_class_enumeration_unsigned_mapping *unsigned_this_mapping = NULL; - - if (is_signed) { - signed_this_mapping = - bt_field_class_enumeration_signed_borrow_mapping_by_index_const(fc, i); - BT_ASSERT(signed_this_mapping); - this_mapping = - bt_field_class_enumeration_signed_mapping_as_mapping_const(signed_this_mapping); - } else { - unsigned_this_mapping = - bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(fc, i); - BT_ASSERT(unsigned_this_mapping); - this_mapping = - bt_field_class_enumeration_unsigned_mapping_as_mapping_const(unsigned_this_mapping); - } - - BT_ASSERT(this_mapping); - - if (strcmp(bt_field_class_enumeration_mapping_get_label(this_mapping), label) == 0) { - mapping = this_mapping; - goto end; - } - } - -end: - return mapping; -} - -static inline bt_field_class *ctf_field_class_variant_to_ir(ctf::MetaTranslateCtx *ctx, - struct ctf_field_class_variant *fc) -{ - int ret; - bt_field_class *ir_fc; - uint64_t i; - bt_field_class *ir_tag_fc = NULL; - - if (fc->tag_path.root != CTF_SCOPE_PACKET_HEADER && - fc->tag_path.root != CTF_SCOPE_EVENT_HEADER) { - ir_tag_fc = borrow_ir_fc_from_field_path(ctx, &fc->tag_path); - BT_ASSERT(ir_tag_fc); - } - - ir_fc = bt_field_class_variant_create(ctx->ir_tc, ir_tag_fc); - BT_ASSERT(ir_fc); - - for (i = 0; i < fc->options->len; i++) { - struct ctf_named_field_class *named_fc = - ctf_field_class_variant_borrow_option_by_index(fc, i); - bt_field_class *option_ir_fc; - - BT_ASSERT(named_fc->fc->in_ir); - option_ir_fc = ctf_field_class_to_ir(ctx, named_fc->fc); - BT_ASSERT(option_ir_fc); - - if (ir_tag_fc) { - /* - * At this point the trace IR selector - * (enumeration) field class already exists if - * the variant is tagged (`ir_tag_fc`). This one - * already contains range sets for its mappings, - * so we just reuse the same, finding them by - * matching a variant field class's option's - * _original_ name (with a leading underscore, - * possibly) with a selector field class's - * mapping name. - */ - if (fc->tag_fc->base.is_signed) { - const bt_field_class_enumeration_signed_mapping *mapping = - (bt_field_class_enumeration_signed_mapping *) - find_ir_enum_field_class_mapping_by_label(ir_tag_fc, - named_fc->orig_name->str, true); - const bt_integer_range_set_signed *range_set; - - BT_ASSERT(mapping); - range_set = bt_field_class_enumeration_signed_mapping_borrow_ranges_const(mapping); - BT_ASSERT(range_set); - ret = bt_field_class_variant_with_selector_field_integer_signed_append_option( - ir_fc, named_fc->name->str, option_ir_fc, range_set); - } else { - const bt_field_class_enumeration_unsigned_mapping *mapping = - (bt_field_class_enumeration_unsigned_mapping *) - find_ir_enum_field_class_mapping_by_label(ir_tag_fc, - named_fc->orig_name->str, false); - const bt_integer_range_set_unsigned *range_set; - - BT_ASSERT(mapping); - range_set = - bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(mapping); - BT_ASSERT(range_set); - ret = bt_field_class_variant_with_selector_field_integer_unsigned_append_option( - ir_fc, named_fc->name->str, option_ir_fc, range_set); - } - } else { - ret = bt_field_class_variant_without_selector_append_option(ir_fc, named_fc->name->str, - option_ir_fc); - } - - BT_ASSERT(ret == 0); - bt_field_class_put_ref(option_ir_fc); - } - - return ir_fc; -} - -static inline bt_field_class *ctf_field_class_array_to_ir(ctf::MetaTranslateCtx *ctx, - struct ctf_field_class_array *fc) -{ - bt_field_class *ir_fc; - bt_field_class *elem_ir_fc; - - if (fc->base.is_text) { - ir_fc = bt_field_class_string_create(ctx->ir_tc); - BT_ASSERT(ir_fc); - goto end; - } - - elem_ir_fc = ctf_field_class_to_ir(ctx, fc->base.elem_fc); - BT_ASSERT(elem_ir_fc); - ir_fc = bt_field_class_array_static_create(ctx->ir_tc, elem_ir_fc, fc->length); - BT_ASSERT(ir_fc); - bt_field_class_put_ref(elem_ir_fc); - -end: - return ir_fc; -} - -static inline bt_field_class *ctf_field_class_sequence_to_ir(ctf::MetaTranslateCtx *ctx, - struct ctf_field_class_sequence *fc) -{ - bt_field_class *ir_fc; - bt_field_class *elem_ir_fc; - bt_field_class *length_fc = NULL; - - if (fc->base.is_text) { - ir_fc = bt_field_class_string_create(ctx->ir_tc); - BT_ASSERT(ir_fc); - goto end; - } - - elem_ir_fc = ctf_field_class_to_ir(ctx, fc->base.elem_fc); - BT_ASSERT(elem_ir_fc); - - if (fc->length_path.root != CTF_SCOPE_PACKET_HEADER && - fc->length_path.root != CTF_SCOPE_EVENT_HEADER) { - length_fc = borrow_ir_fc_from_field_path(ctx, &fc->length_path); - BT_ASSERT(length_fc); - } - - ir_fc = bt_field_class_array_dynamic_create(ctx->ir_tc, elem_ir_fc, length_fc); - BT_ASSERT(ir_fc); - bt_field_class_put_ref(elem_ir_fc); - BT_ASSERT(ir_fc); - -end: - return ir_fc; -} - -static inline bt_field_class *ctf_field_class_to_ir(ctf::MetaTranslateCtx *ctx, - struct ctf_field_class *fc) -{ - bt_field_class *ir_fc = NULL; - - BT_ASSERT(fc); - BT_ASSERT(fc->in_ir); - - switch (fc->type) { - case CTF_FIELD_CLASS_TYPE_INT: - ir_fc = ctf_field_class_int_to_ir(ctx, ctf_field_class_as_int(fc)); - break; - case CTF_FIELD_CLASS_TYPE_ENUM: - ir_fc = ctf_field_class_enum_to_ir(ctx, ctf_field_class_as_enum(fc)); - break; - case CTF_FIELD_CLASS_TYPE_FLOAT: - ir_fc = ctf_field_class_float_to_ir(ctx, ctf_field_class_as_float(fc)); - break; - case CTF_FIELD_CLASS_TYPE_STRING: - ir_fc = ctf_field_class_string_to_ir(ctx); - break; - case CTF_FIELD_CLASS_TYPE_STRUCT: - ir_fc = ctf_field_class_struct_to_ir(ctx, ctf_field_class_as_struct(fc)); - break; - case CTF_FIELD_CLASS_TYPE_ARRAY: - ir_fc = ctf_field_class_array_to_ir(ctx, ctf_field_class_as_array(fc)); - break; - case CTF_FIELD_CLASS_TYPE_SEQUENCE: - ir_fc = ctf_field_class_sequence_to_ir(ctx, ctf_field_class_as_sequence(fc)); - break; - case CTF_FIELD_CLASS_TYPE_VARIANT: - ir_fc = ctf_field_class_variant_to_ir(ctx, ctf_field_class_as_variant(fc)); - break; - default: - bt_common_abort(); - } - - fc->ir_fc = ir_fc; - return ir_fc; -} - -static inline bool -ctf_field_class_struct_has_immediate_member_in_ir(struct ctf_field_class_struct *fc) -{ - uint64_t i; - bool has_immediate_member_in_ir = false; - - /* - * If the structure field class has no members at all, then it - * was an empty structure in the beginning, so leave it existing - * and empty. - */ - if (fc->members->len == 0) { - has_immediate_member_in_ir = true; - goto end; - } - - for (i = 0; i < fc->members->len; i++) { - struct ctf_named_field_class *named_fc = - ctf_field_class_struct_borrow_member_by_index(fc, i); - - if (named_fc->fc->in_ir) { - has_immediate_member_in_ir = true; - goto end; - } - } - -end: - return has_immediate_member_in_ir; -} - -static inline bt_field_class *scope_ctf_field_class_to_ir(ctf::MetaTranslateCtx *ctx) -{ - bt_field_class *ir_fc = NULL; - struct ctf_field_class *fc = NULL; - - switch (ctx->scope) { - case CTF_SCOPE_PACKET_CONTEXT: - fc = ctx->sc->packet_context_fc; - break; - case CTF_SCOPE_EVENT_COMMON_CONTEXT: - fc = ctx->sc->event_common_context_fc; - break; - case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT: - fc = ctx->ec->spec_context_fc; - break; - case CTF_SCOPE_EVENT_PAYLOAD: - fc = ctx->ec->payload_fc; - break; - default: - bt_common_abort(); - } - - if (fc && ctf_field_class_struct_has_immediate_member_in_ir(ctf_field_class_as_struct(fc))) { - ir_fc = ctf_field_class_to_ir(ctx, fc); - } - - return ir_fc; -} - -static inline void ctf_event_class_to_ir(ctf::MetaTranslateCtx *ctx) -{ - int ret; - bt_event_class *ir_ec = NULL; - bt_field_class *ir_fc; - - BT_ASSERT(ctx->ec); - - if (ctx->ec->is_translated) { - ir_ec = bt_stream_class_borrow_event_class_by_id(ctx->ir_sc, ctx->ec->id); - BT_ASSERT(ir_ec); - goto end; - } - - ir_ec = bt_event_class_create_with_id(ctx->ir_sc, ctx->ec->id); - BT_ASSERT(ir_ec); - bt_event_class_put_ref(ir_ec); - ctx->scope = CTF_SCOPE_EVENT_SPECIFIC_CONTEXT; - ir_fc = scope_ctf_field_class_to_ir(ctx); - if (ir_fc) { - ret = bt_event_class_set_specific_context_field_class(ir_ec, ir_fc); - BT_ASSERT(ret == 0); - bt_field_class_put_ref(ir_fc); - } - - ctx->scope = CTF_SCOPE_EVENT_PAYLOAD; - ir_fc = scope_ctf_field_class_to_ir(ctx); - if (ir_fc) { - ret = bt_event_class_set_payload_field_class(ir_ec, ir_fc); - BT_ASSERT(ret == 0); - bt_field_class_put_ref(ir_fc); - } - - if (ctx->ec->name->len > 0) { - ret = bt_event_class_set_name(ir_ec, ctx->ec->name->str); - BT_ASSERT(ret == 0); - } - - if (ctx->ec->emf_uri->len > 0) { - ret = bt_event_class_set_emf_uri(ir_ec, ctx->ec->emf_uri->str); - BT_ASSERT(ret == 0); - } - - if (ctx->ec->is_log_level_set) { - bt_event_class_set_log_level(ir_ec, ctx->ec->log_level); - } - - ctx->ec->is_translated = true; - ctx->ec->ir_ec = ir_ec; - -end: - return; -} - -static inline void ctf_stream_class_to_ir(ctf::MetaTranslateCtx *ctx) -{ - int ret; - bt_field_class *ir_fc; - - BT_ASSERT(ctx->sc); - - if (ctx->sc->is_translated) { - ctx->ir_sc = bt_trace_class_borrow_stream_class_by_id(ctx->ir_tc, ctx->sc->id); - BT_ASSERT(ctx->ir_sc); - goto end; - } - - ctx->ir_sc = bt_stream_class_create_with_id(ctx->ir_tc, ctx->sc->id); - BT_ASSERT(ctx->ir_sc); - bt_stream_class_put_ref(ctx->ir_sc); - - if (ctx->sc->default_clock_class) { - BT_ASSERT(ctx->sc->default_clock_class->ir_cc); - ret = bt_stream_class_set_default_clock_class(ctx->ir_sc, - ctx->sc->default_clock_class->ir_cc); - BT_ASSERT(ret == 0); - } - - bt_stream_class_set_supports_packets(ctx->ir_sc, BT_TRUE, ctx->sc->packets_have_ts_begin, - ctx->sc->packets_have_ts_end); - bt_stream_class_set_supports_discarded_events(ctx->ir_sc, ctx->sc->has_discarded_events, - ctx->sc->discarded_events_have_default_cs); - bt_stream_class_set_supports_discarded_packets(ctx->ir_sc, ctx->sc->has_discarded_packets, - ctx->sc->discarded_packets_have_default_cs); - ctx->scope = CTF_SCOPE_PACKET_CONTEXT; - ir_fc = scope_ctf_field_class_to_ir(ctx); - if (ir_fc) { - ret = bt_stream_class_set_packet_context_field_class(ctx->ir_sc, ir_fc); - BT_ASSERT(ret == 0); - bt_field_class_put_ref(ir_fc); - } - - ctx->scope = CTF_SCOPE_EVENT_COMMON_CONTEXT; - ir_fc = scope_ctf_field_class_to_ir(ctx); - if (ir_fc) { - ret = bt_stream_class_set_event_common_context_field_class(ctx->ir_sc, ir_fc); - BT_ASSERT(ret == 0); - bt_field_class_put_ref(ir_fc); - } - - bt_stream_class_set_assigns_automatic_event_class_id(ctx->ir_sc, BT_FALSE); - bt_stream_class_set_assigns_automatic_stream_id(ctx->ir_sc, BT_FALSE); - - ctx->sc->is_translated = true; - ctx->sc->ir_sc = ctx->ir_sc; - -end: - return; -} - -static inline void ctf_clock_class_to_ir(bt_clock_class *ir_cc, struct ctf_clock_class *cc) -{ - int ret; - - if (strlen(cc->name->str) > 0) { - ret = bt_clock_class_set_name(ir_cc, cc->name->str); - BT_ASSERT(ret == 0); - } - - if (strlen(cc->description->str) > 0) { - ret = bt_clock_class_set_description(ir_cc, cc->description->str); - BT_ASSERT(ret == 0); - } - - bt_clock_class_set_frequency(ir_cc, cc->frequency); - bt_clock_class_set_precision(ir_cc, cc->precision); - bt_clock_class_set_offset(ir_cc, cc->offset_seconds, cc->offset_cycles); - - if (cc->has_uuid) { - bt_clock_class_set_uuid(ir_cc, cc->uuid); - } - - bt_clock_class_set_origin_is_unix_epoch(ir_cc, cc->is_absolute); -} - -static inline int ctf_trace_class_to_ir(ctf::MetaTranslateCtx *ctx) -{ - int ret = 0; - uint64_t i; - - BT_ASSERT(ctx->tc); - BT_ASSERT(ctx->ir_tc); - - if (ctx->tc->is_translated) { - goto end; - } - - for (i = 0; i < ctx->tc->clock_classes->len; i++) { - ctf_clock_class *cc = (ctf_clock_class *) ctx->tc->clock_classes->pdata[i]; - - cc->ir_cc = bt_clock_class_create(ctx->selfComp->libObjPtr()); - ctf_clock_class_to_ir(cc->ir_cc, cc); - } - - bt_trace_class_set_assigns_automatic_stream_class_id(ctx->ir_tc, BT_FALSE); - ctx->tc->is_translated = true; - ctx->tc->ir_tc = ctx->ir_tc; - -end: - return ret; -} - -int ctf_trace_class_translate(const bt2::OptionalBorrowedObject selfComp, - bt_trace_class *ir_tc, struct ctf_trace_class *tc) -{ - int ret = 0; - uint64_t i; - ctf::MetaTranslateCtx ctx = {}; - - ctx.selfComp = selfComp; - ctx.tc = tc; - ctx.ir_tc = ir_tc; - ret = ctf_trace_class_to_ir(&ctx); - if (ret) { - goto end; - } - - for (i = 0; i < tc->stream_classes->len; i++) { - uint64_t j; - ctx.sc = (ctf_stream_class *) tc->stream_classes->pdata[i]; - - ctf_stream_class_to_ir(&ctx); - - for (j = 0; j < ctx.sc->event_classes->len; j++) { - ctx.ec = (ctf_event_class *) ctx.sc->event_classes->pdata[j]; - - ctf_event_class_to_ir(&ctx); - ctx.ec = NULL; - } - - ctx.sc = NULL; - } - -end: - return ret; -} diff --git a/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-in-ir.cpp b/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-in-ir.cpp deleted file mode 100644 index c7902383..00000000 --- a/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-in-ir.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright 2018 Philippe Proulx - */ - -#include -#include -#include - -#include "common/assert.h" -#include "compat/glib.h" - -#include "ctf-meta-visitors.hpp" - -static void force_update_field_class_in_ir(struct ctf_field_class *fc, bool in_ir) -{ - uint64_t i; - - if (!fc) { - goto end; - } - - fc->in_ir = in_ir; - - switch (fc->type) { - case CTF_FIELD_CLASS_TYPE_STRUCT: - { - struct ctf_field_class_struct *struct_fc = ctf_field_class_as_struct(fc); - - for (i = 0; i < struct_fc->members->len; i++) { - struct ctf_named_field_class *named_fc = - ctf_field_class_struct_borrow_member_by_index(struct_fc, i); - - force_update_field_class_in_ir(named_fc->fc, in_ir); - } - - break; - } - case CTF_FIELD_CLASS_TYPE_VARIANT: - { - struct ctf_named_field_class *named_fc; - struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(fc); - - for (i = 0; i < var_fc->options->len; i++) { - named_fc = ctf_field_class_variant_borrow_option_by_index(var_fc, i); - - force_update_field_class_in_ir(named_fc->fc, in_ir); - } - - break; - } - case CTF_FIELD_CLASS_TYPE_ARRAY: - case CTF_FIELD_CLASS_TYPE_SEQUENCE: - { - struct ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(fc); - - force_update_field_class_in_ir(array_fc->elem_fc, in_ir); - break; - } - default: - break; - } - -end: - return; -} - -static void update_field_class_in_ir(struct ctf_field_class *fc, GHashTable *ft_dependents) -{ - int64_t i; - - if (!fc) { - goto end; - } - - switch (fc->type) { - case CTF_FIELD_CLASS_TYPE_INT: - case CTF_FIELD_CLASS_TYPE_ENUM: - { - struct ctf_field_class_int *int_fc = ctf_field_class_as_int(fc); - - /* - * Conditions to be in trace IR; one of: - * - * 1. Does NOT have a mapped clock class AND does not - * have a special meaning. - * 2. Another field class depends on it. - */ - if ((!int_fc->mapped_clock_class && int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE) || - bt_g_hash_table_contains(ft_dependents, fc)) { - fc->in_ir = true; - } - - break; - } - case CTF_FIELD_CLASS_TYPE_STRUCT: - { - struct ctf_field_class_struct *struct_fc = ctf_field_class_as_struct(fc); - - /* - * Make it part of IR if it's empty because it was - * originally empty. - */ - if (struct_fc->members->len == 0) { - fc->in_ir = true; - } - - /* Reverse order */ - for (i = (int64_t) struct_fc->members->len - 1; i >= 0; i--) { - struct ctf_named_field_class *named_fc = - ctf_field_class_struct_borrow_member_by_index(struct_fc, i); - - update_field_class_in_ir(named_fc->fc, ft_dependents); - - if (named_fc->fc->in_ir) { - /* At least one member is part of IR */ - fc->in_ir = true; - } - } - - break; - } - case CTF_FIELD_CLASS_TYPE_VARIANT: - { - struct ctf_named_field_class *named_fc; - struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(fc); - - /* - * Reverse order, although it is not important for this - * loop because a field class within a variant field - * type's option cannot depend on a field class in - * another option of the same variant field class. - */ - for (i = (int64_t) var_fc->options->len - 1; i >= 0; i--) { - named_fc = ctf_field_class_variant_borrow_option_by_index(var_fc, i); - - update_field_class_in_ir(named_fc->fc, ft_dependents); - - if (named_fc->fc->in_ir) { - /* At least one option is part of IR */ - fc->in_ir = true; - } - } - - if (fc->in_ir) { - /* - * At least one option will make it to IR. In - * this case, make all options part of IR - * because the variant's tag could still select - * (dynamically) a removed option. This can mean - * having an empty structure as an option, for - * example, but at least all the options are - * selectable. - */ - for (i = 0; i < var_fc->options->len; i++) { - ctf_field_class_variant_borrow_option_by_index(var_fc, i)->fc->in_ir = true; - } - - /* - * This variant field class is part of IR and - * depends on a tag field class (which must also - * be part of IR). - */ - g_hash_table_insert(ft_dependents, var_fc->tag_fc, var_fc->tag_fc); - } - - break; - } - case CTF_FIELD_CLASS_TYPE_ARRAY: - case CTF_FIELD_CLASS_TYPE_SEQUENCE: - { - struct ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(fc); - - update_field_class_in_ir(array_fc->elem_fc, ft_dependents); - fc->in_ir = array_fc->elem_fc->in_ir; - - if (fc->type == CTF_FIELD_CLASS_TYPE_ARRAY) { - struct ctf_field_class_array *arr_fc = ctf_field_class_as_array(fc); - - assert(arr_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE || - arr_fc->meaning == CTF_FIELD_CLASS_MEANING_UUID); - - /* - * UUID field class: nothing depends on this, so - * it's not part of IR. - */ - if (arr_fc->meaning == CTF_FIELD_CLASS_MEANING_UUID) { - fc->in_ir = false; - array_fc->elem_fc->in_ir = false; - } - } else if (fc->type == CTF_FIELD_CLASS_TYPE_SEQUENCE) { - if (fc->in_ir) { - struct ctf_field_class_sequence *seq_fc = ctf_field_class_as_sequence(fc); - - /* - * This sequence field class is part of - * IR and depends on a length field class - * (which must also be part of IR). - */ - g_hash_table_insert(ft_dependents, seq_fc->length_fc, seq_fc->length_fc); - } - } - - break; - } - default: - fc->in_ir = true; - break; - } - -end: - return; -} - -/* - * Scopes and field classes are processed in reverse order because we need - * to know if a given integer field class has dependents (sequence or - * variant field classes) when we reach it. Dependents can only be located - * after the length/tag field class in the metadata tree. - */ -int ctf_trace_class_update_in_ir(struct ctf_trace_class *ctf_tc) -{ - int ret = 0; - uint64_t i; - - GHashTable *ft_dependents = g_hash_table_new(g_direct_hash, g_direct_equal); - - BT_ASSERT(ft_dependents); - - for (i = 0; i < ctf_tc->stream_classes->len; i++) { - ctf_stream_class *sc = (ctf_stream_class *) ctf_tc->stream_classes->pdata[i]; - uint64_t j; - - for (j = 0; j < sc->event_classes->len; j++) { - ctf_event_class *ec = (ctf_event_class *) sc->event_classes->pdata[j]; - - if (ec->is_translated) { - continue; - } - - update_field_class_in_ir(ec->payload_fc, ft_dependents); - update_field_class_in_ir(ec->spec_context_fc, ft_dependents); - } - - if (!sc->is_translated) { - update_field_class_in_ir(sc->event_common_context_fc, ft_dependents); - force_update_field_class_in_ir(sc->event_header_fc, false); - update_field_class_in_ir(sc->packet_context_fc, ft_dependents); - } - } - - if (!ctf_tc->is_translated) { - force_update_field_class_in_ir(ctf_tc->packet_header_fc, false); - } - - g_hash_table_destroy(ft_dependents); - return ret; -} diff --git a/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-stream-class-config.cpp b/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-stream-class-config.cpp deleted file mode 100644 index a8f5add6..00000000 --- a/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-stream-class-config.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright 2019 Philippe Proulx - */ - -#include - -#include "ctf-meta-visitors.hpp" - -int ctf_trace_class_update_stream_class_config(struct ctf_trace_class *ctf_tc) -{ - struct ctf_field_class_int *int_fc; - uint64_t i; - - for (i = 0; i < ctf_tc->stream_classes->len; i++) { - struct ctf_stream_class *sc = (ctf_stream_class *) ctf_tc->stream_classes->pdata[i]; - - if (sc->is_translated) { - continue; - } - - if (!sc->packet_context_fc) { - continue; - } - - int_fc = ctf_field_class_struct_borrow_member_int_field_class_by_name( - ctf_field_class_as_struct(sc->packet_context_fc), "timestamp_begin"); - if (int_fc && int_fc->meaning == CTF_FIELD_CLASS_MEANING_PACKET_BEGINNING_TIME) { - sc->packets_have_ts_begin = true; - } - - int_fc = ctf_field_class_struct_borrow_member_int_field_class_by_name( - ctf_field_class_as_struct(sc->packet_context_fc), "timestamp_end"); - if (int_fc && int_fc->meaning == CTF_FIELD_CLASS_MEANING_PACKET_END_TIME) { - sc->packets_have_ts_end = true; - } - - int_fc = ctf_field_class_struct_borrow_member_int_field_class_by_name( - ctf_field_class_as_struct(sc->packet_context_fc), "events_discarded"); - if (int_fc && int_fc->meaning == CTF_FIELD_CLASS_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT) { - sc->has_discarded_events = true; - } - - sc->discarded_events_have_default_cs = - sc->has_discarded_events && sc->packets_have_ts_begin && sc->packets_have_ts_end; - int_fc = ctf_field_class_struct_borrow_member_int_field_class_by_name( - ctf_field_class_as_struct(sc->packet_context_fc), "packet_seq_num"); - if (int_fc && int_fc->meaning == CTF_FIELD_CLASS_MEANING_PACKET_COUNTER_SNAPSHOT) { - sc->has_discarded_packets = true; - } - - sc->discarded_packets_have_default_cs = - sc->has_discarded_packets && sc->packets_have_ts_begin && sc->packets_have_ts_end; - } - - return 0; -} diff --git a/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-value-storing-indexes.cpp b/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-value-storing-indexes.cpp deleted file mode 100644 index 65e4c9fe..00000000 --- a/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta-update-value-storing-indexes.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright 2018 Philippe Proulx - */ - -#include -#include - -#include "common/assert.h" - -#include "ctf-meta-visitors.hpp" - -static int update_field_class_stored_value_index(struct ctf_field_class *fc, - struct ctf_trace_class *tc, - struct ctf_stream_class *sc, - struct ctf_event_class *ec) -{ - int ret = 0; - uint64_t i; - struct ctf_field_path *field_path = NULL; - struct ctf_field_class_int *tgt_fc = NULL; - uint64_t *stored_value_index = NULL; - - if (!fc) { - goto end; - } - - switch (fc->type) { - case CTF_FIELD_CLASS_TYPE_VARIANT: - { - ctf_field_class_variant *var_fc = ctf_field_class_as_variant(fc); - - field_path = &var_fc->tag_path; - stored_value_index = &var_fc->stored_tag_index; - tgt_fc = &var_fc->tag_fc->base; - break; - } - case CTF_FIELD_CLASS_TYPE_SEQUENCE: - { - struct ctf_field_class_sequence *seq_fc = ctf_field_class_as_sequence(fc); - - field_path = &seq_fc->length_path; - stored_value_index = &seq_fc->stored_length_index; - tgt_fc = seq_fc->length_fc; - break; - } - default: - break; - } - - if (field_path) { - BT_ASSERT(tgt_fc); - BT_ASSERT(tgt_fc->base.base.type == CTF_FIELD_CLASS_TYPE_INT || - tgt_fc->base.base.type == CTF_FIELD_CLASS_TYPE_ENUM); - if (tgt_fc->storing_index >= 0) { - /* Already storing its value */ - *stored_value_index = (uint64_t) tgt_fc->storing_index; - } else { - /* Not storing its value: allocate new index */ - tgt_fc->storing_index = tc->stored_value_count; - *stored_value_index = (uint64_t) tgt_fc->storing_index; - tc->stored_value_count++; - } - } - - switch (fc->type) { - case CTF_FIELD_CLASS_TYPE_STRUCT: - { - struct ctf_field_class_struct *struct_fc = ctf_field_class_as_struct(fc); - - for (i = 0; i < struct_fc->members->len; i++) { - struct ctf_named_field_class *named_fc = - ctf_field_class_struct_borrow_member_by_index(struct_fc, i); - - ret = update_field_class_stored_value_index(named_fc->fc, tc, sc, ec); - if (ret) { - goto end; - } - } - - break; - } - case CTF_FIELD_CLASS_TYPE_VARIANT: - { - struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(fc); - - for (i = 0; i < var_fc->options->len; i++) { - struct ctf_named_field_class *named_fc = - ctf_field_class_variant_borrow_option_by_index(var_fc, i); - - ret = update_field_class_stored_value_index(named_fc->fc, tc, sc, ec); - if (ret) { - goto end; - } - } - - break; - } - case CTF_FIELD_CLASS_TYPE_ARRAY: - case CTF_FIELD_CLASS_TYPE_SEQUENCE: - { - struct ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(fc); - - ret = update_field_class_stored_value_index(array_fc->elem_fc, tc, sc, ec); - if (ret) { - goto end; - } - - break; - } - default: - break; - } - -end: - return ret; -} - -int ctf_trace_class_update_value_storing_indexes(struct ctf_trace_class *ctf_tc) -{ - uint64_t i; - - if (!ctf_tc->is_translated) { - update_field_class_stored_value_index(ctf_tc->packet_header_fc, ctf_tc, NULL, NULL); - } - - for (i = 0; i < ctf_tc->stream_classes->len; i++) { - uint64_t j; - ctf_stream_class *sc = (ctf_stream_class *) ctf_tc->stream_classes->pdata[i]; - - if (!sc->is_translated) { - update_field_class_stored_value_index(sc->packet_context_fc, ctf_tc, sc, NULL); - update_field_class_stored_value_index(sc->event_header_fc, ctf_tc, sc, NULL); - update_field_class_stored_value_index(sc->event_common_context_fc, ctf_tc, sc, NULL); - } - - for (j = 0; j < sc->event_classes->len; j++) { - struct ctf_event_class *ec = (ctf_event_class *) sc->event_classes->pdata[j]; - - if (!ec->is_translated) { - update_field_class_stored_value_index(ec->spec_context_fc, ctf_tc, sc, ec); - update_field_class_stored_value_index(ec->payload_fc, ctf_tc, sc, ec); - } - } - } - - return 0; -} diff --git a/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta.hpp b/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta.hpp index 880e98fe..a97970c4 100644 --- a/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta.hpp +++ b/src/plugins/ctf/common/src/metadata/tsdl/ctf-meta.hpp @@ -379,8 +379,6 @@ struct ctf_trace_class /* Owned by this */ struct ctf_field_class *packet_header_fc; - uint64_t stored_value_count; - /* Array of `struct ctf_clock_class *` (owned by this) */ GPtrArray *clock_classes; @@ -391,16 +389,6 @@ struct ctf_trace_class GArray *env_entries; bool is_translated; - - /* Weak, set during translation */ - bt_trace_class *ir_tc; - - struct - { - bool lttng_crash; - bool lttng_event_after_packet; - bool barectf_event_before_packet; - } quirks; }; static inline ctf_field_class_bit_array *ctf_field_class_as_bit_array(ctf_field_class *fc) diff --git a/src/plugins/ctf/common/src/metadata/tsdl/decoder-packetized-file-stream-to-buf.cpp b/src/plugins/ctf/common/src/metadata/tsdl/decoder-packetized-file-stream-to-buf.cpp deleted file mode 100644 index b6de4d61..00000000 --- a/src/plugins/ctf/common/src/metadata/tsdl/decoder-packetized-file-stream-to-buf.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright 2016-2017 Philippe Proulx - */ - -#include -#include -#include - -#include "common/uuid.h" -#include "compat/memstream.h" - -#include "decoder-packetized-file-stream-to-buf.hpp" -#include "decoder.hpp" - -#define TSDL_MAGIC 0x75d11d57 - -struct packet_header -{ - uint32_t magic; - bt_uuid_t uuid; - uint32_t checksum; - uint32_t content_size; - uint32_t packet_size; - uint8_t compression_scheme; - uint8_t encryption_scheme; - uint8_t checksum_scheme; - uint8_t major; - uint8_t minor; -} __attribute__((__packed__)); - -static int decode_packet(FILE *in_fp, FILE *out_fp, int byte_order, bool *is_uuid_set, - uint8_t *uuid, const bt2c::Logger& logger) -{ - struct packet_header header; - size_t readlen, writelen, toread; - uint8_t buf[512 + 1]; /* + 1 for debug-mode \0 */ - int ret = 0; - const long offset = ftell(in_fp); - - if (offset < 0) { - BT_CPPLOGE_ERRNO_APPEND_CAUSE_SPEC(logger, "Failed to get current metadata file position", - "."); - goto error; - } - BT_CPPLOGD_SPEC(logger, "Decoding metadata packet: offset={}", offset); - readlen = fread(&header, sizeof(header), 1, in_fp); - if (feof(in_fp) != 0) { - BT_CPPLOGI_SPEC(logger, "Reached end of file: offset={}", ftell(in_fp)); - goto end; - } - if (readlen < 1) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Cannot decode metadata packet: offset={}", offset); - goto error; - } - - if (byte_order != BYTE_ORDER) { - header.magic = GUINT32_SWAP_LE_BE(header.magic); - header.checksum = GUINT32_SWAP_LE_BE(header.checksum); - header.content_size = GUINT32_SWAP_LE_BE(header.content_size); - header.packet_size = GUINT32_SWAP_LE_BE(header.packet_size); - } - - if (header.compression_scheme) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - logger, - "Metadata packet compression is not supported as of this version: " - "compression-scheme={}, offset={}", - (unsigned int) header.compression_scheme, offset); - goto error; - } - - if (header.encryption_scheme) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - logger, - "Metadata packet encryption is not supported as of this version: " - "encryption-scheme={}, offset={}", - (unsigned int) header.encryption_scheme, offset); - goto error; - } - - if (header.checksum || header.checksum_scheme) { - auto checksum = header.checksum; - - BT_CPPLOGE_APPEND_CAUSE_SPEC( - logger, - "Metadata packet checksum verification is not supported as of this version: " - "checksum-scheme={}, checksum={}, offset={}", - (unsigned int) header.checksum_scheme, checksum, offset); - goto error; - } - - if (!ctf_metadata_decoder_is_packet_version_valid(header.major, header.minor)) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, - "Invalid metadata packet version: " - "version={}.{}, offset={}", - header.major, header.minor, offset); - goto error; - } - - /* Set expected trace UUID if not set; otherwise validate it */ - if (is_uuid_set) { - if (!*is_uuid_set) { - bt_uuid_copy(uuid, header.uuid); - *is_uuid_set = true; - } else if (bt_uuid_compare(header.uuid, uuid)) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - logger, - "Metadata UUID mismatch between packets of the same stream: " - "packet-uuid=\"" BT_UUID_FMT "\", " - "expected-uuid=\"" BT_UUID_FMT "\", " - "offset={}", - BT_UUID_FMT_VALUES(header.uuid), BT_UUID_FMT_VALUES(uuid), offset); - goto error; - } - } - - if ((header.content_size / CHAR_BIT) < sizeof(header)) { - auto content_size = header.content_size; - - BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, - "Bad metadata packet content size: content-size={}, " - "offset={}", - content_size, offset); - goto error; - } - - toread = header.content_size / CHAR_BIT - sizeof(header); - - for (;;) { - size_t loop_read; - - loop_read = MIN(sizeof(buf) - 1, toread); - readlen = fread(buf, sizeof(uint8_t), loop_read, in_fp); - if (ferror(in_fp)) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, - "Cannot read metadata packet buffer: " - "offset={}, read-size={}", - ftell(in_fp), loop_read); - goto error; - } - if (readlen > loop_read) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, - "fread returned more byte than expected: " - "read-size-asked={}, read-size-returned={}", - loop_read, readlen); - goto error; - } - - writelen = fwrite(buf, sizeof(uint8_t), readlen, out_fp); - if (writelen < readlen || ferror(out_fp)) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, - "Cannot write decoded metadata text to buffer: " - "read-offset={}, write-size={}", - ftell(in_fp), readlen); - goto error; - } - - toread -= readlen; - if (toread == 0) { - int fseek_ret; - - /* Read leftover padding */ - toread = (header.packet_size - header.content_size) / CHAR_BIT; - fseek_ret = fseek(in_fp, toread, SEEK_CUR); - if (fseek_ret < 0) { - BT_CPPLOGW_SPEC(logger, "Missing padding at the end of the metadata stream."); - } - break; - } - } - - goto end; - -error: - ret = -1; - -end: - return ret; -} - -int ctf_metadata_decoder_packetized_file_stream_to_buf(FILE *fp, char **buf, int byte_order, - bool *is_uuid_set, uint8_t *uuid, - const bt2c::Logger& parentLogger) -{ - FILE *out_fp; - size_t size; - int ret = 0; - int tret; - size_t packet_index = 0; - bt2c::Logger logger {parentLogger, "PLUGIN/CTF/META/DECODER-DECODE-PACKET"}; - - out_fp = bt_open_memstream(buf, &size); - if (!out_fp) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Cannot open memory stream: {}.", strerror(errno)); - goto error; - } - - for (;;) { - if (feof(fp) != 0) { - break; - } - - tret = decode_packet(fp, out_fp, byte_order, is_uuid_set, uuid, logger); - if (tret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Cannot decode packet: index={}", packet_index); - goto error; - } - - packet_index++; - } - - /* Make sure the whole string ends with a null character */ - tret = fputc('\0', out_fp); - if (tret == EOF) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Cannot append '\\0' to the decoded metadata buffer."); - goto error; - } - - /* Close stream, which also flushes the buffer */ - ret = bt_close_memstream(buf, &size, out_fp); - /* - * See fclose(3). Further access to out_fp after both success - * and error, even through another bt_close_memstream(), results - * in undefined behavior. Nullify out_fp to ensure we don't - * fclose it twice on error. - */ - out_fp = NULL; - if (ret < 0) { - BT_CPPLOGE_ERRNO_APPEND_CAUSE_SPEC(logger, "Cannot close memory stream", "."); - goto error; - } - - goto end; - -error: - ret = -1; - - if (out_fp) { - if (bt_close_memstream(buf, &size, out_fp)) { - BT_CPPLOGE_ERRNO_SPEC(logger, "Cannot close memory stream", "."); - } - } - - if (*buf) { - free(*buf); - *buf = NULL; - } - -end: - return ret; -} diff --git a/src/plugins/ctf/common/src/metadata/tsdl/decoder-packetized-file-stream-to-buf.hpp b/src/plugins/ctf/common/src/metadata/tsdl/decoder-packetized-file-stream-to-buf.hpp deleted file mode 100644 index b0d544c2..00000000 --- a/src/plugins/ctf/common/src/metadata/tsdl/decoder-packetized-file-stream-to-buf.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright 2019 Efficios Inc. - */ - -#ifndef BABELTRACE_PLUGINS_CTF_COMMON_SRC_METADATA_TSDL_DECODER_PACKETIZED_FILE_STREAM_TO_BUF_HPP -#define BABELTRACE_PLUGINS_CTF_COMMON_SRC_METADATA_TSDL_DECODER_PACKETIZED_FILE_STREAM_TO_BUF_HPP - -#include - -#include - -#include - -namespace bt2c { - -class Logger; - -} /* namespace bt2c */ - -int ctf_metadata_decoder_packetized_file_stream_to_buf(FILE *fp, char **buf, int byte_order, - bool *is_uuid_set, uint8_t *uuid, - const bt2c::Logger& parentLogger); - -#endif /* BABELTRACE_PLUGINS_CTF_COMMON_SRC_METADATA_TSDL_DECODER_PACKETIZED_FILE_STREAM_TO_BUF_HPP */ diff --git a/src/plugins/ctf/common/src/metadata/tsdl/decoder.cpp b/src/plugins/ctf/common/src/metadata/tsdl/decoder.cpp deleted file mode 100644 index 2aa7b24b..00000000 --- a/src/plugins/ctf/common/src/metadata/tsdl/decoder.cpp +++ /dev/null @@ -1,444 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright 2016-2017 Philippe Proulx - */ - -#include -#include -#include - -#include "common/assert.h" -#include "common/uuid.h" -#include "compat/memstream.h" -#include "cpp-common/vendor/fmt/format.h" - -#include "ast.hpp" -#include "decoder-packetized-file-stream-to-buf.hpp" -#include "decoder.hpp" -#include "parser-wrap.hpp" -#include "scanner.hpp" - -#define TSDL_MAGIC 0x75d11d57 - -struct ctf_metadata_decoder -{ - explicit ctf_metadata_decoder(const bt2c::Logger& parentLogger) : - logger {parentLogger, "PLUGIN/CTF/META/DECODER"}, config {logger} - { - } - - bt2c::Logger logger; - struct ctf_scanner *scanner = nullptr; - GString *text = nullptr; - ctf_visitor_generate_ir::UP visitor; - bt_uuid_t uuid {}; - bool is_uuid_set = false; - int bo = 0; - struct ctf_metadata_decoder_config config; - bool has_checked_plaintext_signature = false; -}; - -struct packet_header -{ - uint32_t magic; - bt_uuid_t uuid; - uint32_t checksum; - uint32_t content_size; - uint32_t packet_size; - uint8_t compression_scheme; - uint8_t encryption_scheme; - uint8_t checksum_scheme; - uint8_t major; - uint8_t minor; -} __attribute__((__packed__)); - -int ctf_metadata_decoder_is_packetized(FILE *fp, bool *is_packetized, int *byte_order, - const bt2c::Logger& logger) -{ - uint32_t magic; - size_t len; - int ret = 0; - - *is_packetized = false; - len = fread(&magic, sizeof(magic), 1, fp); - if (len != 1) { - BT_CPPLOGI_SPEC( - logger, - "Cannot read first metadata packet header: assuming the stream is not packetized."); - ret = -1; - goto end; - } - - if (byte_order) { - if (magic == TSDL_MAGIC) { - *is_packetized = true; - *byte_order = BYTE_ORDER; - } else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) { - *is_packetized = true; - *byte_order = BYTE_ORDER == BIG_ENDIAN ? LITTLE_ENDIAN : BIG_ENDIAN; - } - } - -end: - rewind(fp); - - return ret; -} - -ctf_metadata_decoder_up -ctf_metadata_decoder_create(const struct ctf_metadata_decoder_config *config) -{ - BT_ASSERT(config); - BT_CPPLOGD_SPEC(config->logger, "Creating CTF metadata decoder"); - - ctf_metadata_decoder *mdec = new ctf_metadata_decoder {config->logger}; - mdec->scanner = ctf_scanner_alloc(mdec->logger); - if (!mdec->scanner) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, - "Cannot allocate a metadata lexical scanner: " - "mdec-addr={}", - fmt::ptr(mdec)); - goto error; - } - - mdec->text = g_string_new(NULL); - if (!mdec->text) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, - "Failed to allocate one GString: " - "mdec-addr={}", - fmt::ptr(mdec)); - goto error; - } - - mdec->bo = -1; - mdec->config = *config; - mdec->visitor = ctf_visitor_generate_ir_create(config->self_comp, config->logger); - if (!mdec->visitor) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, - "Failed to create a CTF IR metadata AST visitor: " - "mdec-addr={}", - fmt::ptr(mdec)); - goto error; - } - - BT_CPPLOGD_SPEC(mdec->logger, "Created CTF metadata decoder: addr={}", fmt::ptr(mdec)); - goto end; - -error: - ctf_metadata_decoder_destroy(mdec); - mdec = NULL; - -end: - return ctf_metadata_decoder_up {mdec}; -} - -void ctf_metadata_decoder_destroy(struct ctf_metadata_decoder *mdec) -{ - if (!mdec) { - return; - } - - if (mdec->scanner) { - ctf_scanner_free(mdec->scanner); - } - - if (mdec->text) { - g_string_free(mdec->text, TRUE); - } - - BT_CPPLOGD_SPEC(mdec->logger, "Destroying CTF metadata decoder: addr={}", fmt::ptr(mdec)); - - delete mdec; -} - -void ctf_metadata_decoder_deleter::operator()(ctf_metadata_decoder *decoder) -{ - ctf_metadata_decoder_destroy(decoder); -} - -enum ctf_metadata_decoder_status -ctf_metadata_decoder_append_content(struct ctf_metadata_decoder *mdec, FILE *fp) -{ - enum ctf_metadata_decoder_status status = CTF_METADATA_DECODER_STATUS_OK; - int ret; - char *buf = NULL; - bool close_fp = false; - long start_pos = -1; - bool is_packetized; - - BT_ASSERT(mdec); - ret = ctf_metadata_decoder_is_packetized(fp, &is_packetized, &mdec->bo, mdec->logger); - if (ret) { - status = CTF_METADATA_DECODER_STATUS_ERROR; - goto end; - } - - if (is_packetized) { - BT_CPPLOGI_SPEC(mdec->logger, "Metadata stream is packetized: mdec-addr={}", - fmt::ptr(mdec)); - ret = ctf_metadata_decoder_packetized_file_stream_to_buf( - fp, &buf, mdec->bo, &mdec->is_uuid_set, mdec->uuid, mdec->logger); - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - mdec->logger, - "Cannot decode packetized metadata packets to metadata text: " - "mdec-addr={}, ret={}", - fmt::ptr(mdec), ret); - status = CTF_METADATA_DECODER_STATUS_ERROR; - goto end; - } - - if (strlen(buf) == 0) { - /* An empty metadata packet is OK. */ - goto end; - } - - /* Convert the real file pointer to a memory file pointer */ - fp = bt_fmemopen(buf, strlen(buf), "rb"); - close_fp = true; - if (!fp) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, - "Cannot memory-open metadata buffer: {}: " - "mdec-addr={}", - strerror(errno), fmt::ptr(mdec)); - status = CTF_METADATA_DECODER_STATUS_ERROR; - goto end; - } - } else if (!mdec->has_checked_plaintext_signature) { - unsigned int major, minor; - ssize_t nr_items; - const long init_pos = ftell(fp); - - BT_CPPLOGI_SPEC(mdec->logger, "Metadata stream is plain text: mdec-addr={}", - fmt::ptr(mdec)); - - if (init_pos < 0) { - BT_CPPLOGE_ERRNO_APPEND_CAUSE_SPEC(mdec->logger, "Failed to get current file position", - "."); - status = CTF_METADATA_DECODER_STATUS_ERROR; - goto end; - } - - /* Check text-only metadata header and version */ - nr_items = fscanf(fp, "/* CTF %10u.%10u", &major, &minor); - if (nr_items < 2) { - BT_CPPLOGW_SPEC( - mdec->logger, - "Missing \"/* CTF major.minor\" signature in plain text metadata file stream: " - "mdec-addr={}", - fmt::ptr(mdec)); - } - - BT_CPPLOGI_SPEC(mdec->logger, "Found metadata stream version in signature: version={}.{}", - major, minor); - - if (!ctf_metadata_decoder_is_packet_version_valid(major, minor)) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, - "Invalid metadata version found in plain text signature: " - "version={}.{}, mdec-addr={}", - major, minor, fmt::ptr(mdec)); - status = CTF_METADATA_DECODER_STATUS_INVAL_VERSION; - goto end; - } - - if (fseek(fp, init_pos, SEEK_SET)) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - mdec->logger, - "Cannot seek metadata file stream to initial position: {}: " - "mdec-addr={}", - strerror(errno), fmt::ptr(mdec)); - status = CTF_METADATA_DECODER_STATUS_ERROR; - goto end; - } - - mdec->has_checked_plaintext_signature = true; - } - -#if YYDEBUG - if (mdec->logger.wouldLogT()) { - yydebug = 1; - } -#endif - - /* Save the file's position: we'll seek back to append the plain text */ - BT_ASSERT(fp); - - if (mdec->config.keep_plain_text) { - start_pos = ftell(fp); - } - - /* Append the metadata text content */ - ret = ctf_scanner_append_ast(mdec->scanner, fp); - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, - "Cannot create the metadata AST out of the metadata text: " - "mdec-addr={}", - fmt::ptr(mdec)); - status = CTF_METADATA_DECODER_STATUS_INCOMPLETE; - goto end; - } - - /* We know it's complete: append plain text */ - if (mdec->config.keep_plain_text) { - BT_ASSERT(start_pos != -1); - ret = fseek(fp, start_pos, SEEK_SET); - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, "Failed to seek file: ret={}, mdec-addr={}", - ret, fmt::ptr(mdec)); - status = CTF_METADATA_DECODER_STATUS_ERROR; - goto end; - } - - ret = bt_common_append_file_content_to_g_string(mdec->text, fp); - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, - "Failed to append to current plain text: " - "ret={}, mdec-addr={}", - ret, fmt::ptr(mdec)); - status = CTF_METADATA_DECODER_STATUS_ERROR; - goto end; - } - } - - ret = ctf_visitor_semantic_check(0, &mdec->scanner->ast->root, mdec->logger); - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, - "Validation of the metadata semantics failed: " - "mdec-addr={}", - fmt::ptr(mdec)); - status = CTF_METADATA_DECODER_STATUS_ERROR; - goto end; - } - - if (mdec->config.create_trace_class) { - ret = ctf_visitor_generate_ir_visit_node(mdec->visitor.get(), &mdec->scanner->ast->root); - switch (ret) { - case 0: - /* Success */ - break; - case -EINCOMPLETE: - BT_CPPLOGD_SPEC(mdec->logger, - "While visiting metadata AST: incomplete data: " - "mdec-addr={}", - fmt::ptr(mdec)); - status = CTF_METADATA_DECODER_STATUS_INCOMPLETE; - goto end; - default: - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, - "Failed to visit AST node to create CTF IR objects: " - "mdec-addr={}, ret={}", - fmt::ptr(mdec), ret); - status = CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR; - goto end; - } - } - -end: -#if YYDEBUG - yydebug = 0; -#endif - - if (fp && close_fp) { - if (fclose(fp)) { - BT_CPPLOGE_SPEC(mdec->logger, - "Cannot close metadata file stream: " - "mdec-addr={}", - fmt::ptr(mdec)); - } - } - - free(buf); - - return status; -} - -bt2::TraceClass::Shared ctf_metadata_decoder_get_ir_trace_class(struct ctf_metadata_decoder *mdec) -{ - BT_ASSERT_DBG(mdec); - BT_ASSERT_DBG(mdec->config.create_trace_class); - return ctf_visitor_generate_ir_get_ir_trace_class(mdec->visitor.get()); -} - -struct ctf_trace_class * -ctf_metadata_decoder_borrow_ctf_trace_class(struct ctf_metadata_decoder *mdec) -{ - BT_ASSERT_DBG(mdec); - BT_ASSERT_DBG(mdec->config.create_trace_class); - return ctf_visitor_generate_ir_borrow_ctf_trace_class(mdec->visitor.get()); -} - -const char *ctf_metadata_decoder_get_text(struct ctf_metadata_decoder *mdec) -{ - BT_ASSERT_DBG(mdec); - BT_ASSERT_DBG(mdec->config.keep_plain_text); - return mdec->text->str; -} - -static enum ctf_metadata_decoder_status find_uuid_in_trace_decl(struct ctf_metadata_decoder *mdec, - struct ctf_node *trace_node, - bt_uuid_t uuid) -{ - enum ctf_metadata_decoder_status status = CTF_METADATA_DECODER_STATUS_OK; - struct ctf_node *entry_node; - struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list; - char *left = NULL; - - bt_list_for_each_entry (entry_node, decl_list, siblings) { - if (entry_node->type == NODE_CTF_EXPRESSION) { - int ret; - - left = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.left); - if (!left) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, "Cannot concatenate unary strings."); - status = CTF_METADATA_DECODER_STATUS_ERROR; - goto end; - } - - if (strcmp(left, "uuid") == 0) { - ret = - ctf_ast_get_unary_uuid(&entry_node->u.ctf_expression.right, uuid, mdec->logger); - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(mdec->logger, "Invalid trace's `uuid` attribute."); - status = CTF_METADATA_DECODER_STATUS_ERROR; - goto end; - } - - goto end; - } - - g_free(left); - left = NULL; - } - } - - status = CTF_METADATA_DECODER_STATUS_NONE; - -end: - g_free(left); - return status; -} - -enum ctf_metadata_decoder_status -ctf_metadata_decoder_get_trace_class_uuid(struct ctf_metadata_decoder *mdec, bt_uuid_t uuid) -{ - enum ctf_metadata_decoder_status status = CTF_METADATA_DECODER_STATUS_INCOMPLETE; - struct ctf_node *root_node = &mdec->scanner->ast->root; - struct ctf_node *trace_node; - - if (!root_node) { - status = CTF_METADATA_DECODER_STATUS_INCOMPLETE; - goto end; - } - - trace_node = bt_list_entry(root_node->u.root.trace.next, struct ctf_node, siblings); - if (!trace_node) { - status = CTF_METADATA_DECODER_STATUS_INCOMPLETE; - goto end; - } - - status = find_uuid_in_trace_decl(mdec, trace_node, uuid); - -end: - return status; -} diff --git a/src/plugins/ctf/common/src/metadata/tsdl/decoder.hpp b/src/plugins/ctf/common/src/metadata/tsdl/decoder.hpp deleted file mode 100644 index 339cc253..00000000 --- a/src/plugins/ctf/common/src/metadata/tsdl/decoder.hpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright 2016-2017 Philippe Proulx - */ - -#ifndef BABELTRACE_PLUGINS_CTF_COMMON_SRC_METADATA_TSDL_DECODER_HPP -#define BABELTRACE_PLUGINS_CTF_COMMON_SRC_METADATA_TSDL_DECODER_HPP - -#include - -#include - -#include "common/uuid.h" -#include "cpp-common/bt2/trace-ir.hpp" -#include "cpp-common/bt2c/logging.hpp" -#include "cpp-common/vendor/fmt/format.h" /* IWYU pragma: keep */ - -#include "../../../src/clk-cls-cfg.hpp" - -/* A CTF metadata decoder object */ -struct ctf_metadata_decoder; - -/* CTF metadata decoder status */ -enum ctf_metadata_decoder_status -{ - CTF_METADATA_DECODER_STATUS_OK = 0, - CTF_METADATA_DECODER_STATUS_NONE = 1, - CTF_METADATA_DECODER_STATUS_ERROR = -1, - CTF_METADATA_DECODER_STATUS_INCOMPLETE = -2, - CTF_METADATA_DECODER_STATUS_INVAL_VERSION = -3, - CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR = -4, -}; - -inline const char *format_as(ctf_metadata_decoder_status status) noexcept -{ - switch (status) { - case CTF_METADATA_DECODER_STATUS_OK: - return "CTF_METADATA_DECODER_STATUS_OK"; - - case CTF_METADATA_DECODER_STATUS_NONE: - return "CTF_METADATA_DECODER_STATUS_NONE"; - - case CTF_METADATA_DECODER_STATUS_ERROR: - return "CTF_METADATA_DECODER_STATUS_ERROR"; - - case CTF_METADATA_DECODER_STATUS_INCOMPLETE: - return "CTF_METADATA_DECODER_STATUS_INCOMPLETE"; - - case CTF_METADATA_DECODER_STATUS_INVAL_VERSION: - return "CTF_METADATA_DECODER_STATUS_INVAL_VERSION"; - - case CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR: - return "CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR"; - } - - bt_common_abort(); -} - -/* Decoding configuration */ -struct ctf_metadata_decoder_config -{ - explicit ctf_metadata_decoder_config(const bt2c::Logger& parentLogger) : - logger {parentLogger, "PLUGIN/CTF/META/DECODER-CONFIG"} - { - } - - bt2c::Logger logger; - - /* Weak, used to create a bt_trace_class, if not nullptr. */ - bt_self_component *self_comp = nullptr; - - /* True to create trace class objects */ - bool create_trace_class = false; - - /* - * True to keep the plain text when content is appended with - * ctf_metadata_decoder_append_content(). - */ - bool keep_plain_text = false; -}; - -struct ctf_metadata_decoder_deleter -{ - void operator()(struct ctf_metadata_decoder *decoder); -}; - -using ctf_metadata_decoder_up = std::unique_ptr; - -/* - * Creates a CTF metadata decoder. - * - * Returns `NULL` on error. - */ -ctf_metadata_decoder_up -ctf_metadata_decoder_create(const struct ctf_metadata_decoder_config *config); - -/* - * Destroys a CTF metadata decoder that you created with - * ctf_metadata_decoder_create(). - */ -void ctf_metadata_decoder_destroy(struct ctf_metadata_decoder *metadata_decoder); - -/* - * Appends content to the metadata decoder. - * - * This function reads the metadata from the current position of `fp` - * until the end of this file stream. - * - * The metadata can be packetized or not. - * - * The metadata chunk needs to be complete and lexically scannable, that - * is, zero or more complete top-level blocks. If it's incomplete, this - * function returns `CTF_METADATA_DECODER_STATUS_INCOMPLETE`. If this - * function returns `CTF_METADATA_DECODER_STATUS_INCOMPLETE`, then you - * need to call it again with the _same_ metadata and more to make it - * complete. For example: - * - * First call: event { name = hell - * Second call: event { name = hello_world; ... }; - * - * If everything goes as expected, this function returns - * `CTF_METADATA_DECODER_STATUS_OK`. - */ -enum ctf_metadata_decoder_status -ctf_metadata_decoder_append_content(struct ctf_metadata_decoder *metadata_decoder, FILE *fp); - -/* - * Returns the trace IR trace class of this metadata decoder (new - * reference). - * - * Returns `NULL` if there's none yet or if the metadata decoder is not - * configured to create trace classes. - */ -bt2::TraceClass::Shared ctf_metadata_decoder_get_ir_trace_class(struct ctf_metadata_decoder *mdec); - -/* - * Returns the CTF IR trace class of this metadata decoder. - * - * Returns `NULL` if there's none yet or if the metadata decoder is not - * configured to create trace classes. - */ -struct ctf_trace_class * -ctf_metadata_decoder_borrow_ctf_trace_class(struct ctf_metadata_decoder *mdec); - -/* - * Checks whether or not a given metadata file stream `fp` is - * packetized, setting `is_packetized` accordingly on success. On - * success, also sets `*byte_order` to the byte order of the first - * packet. - */ -int ctf_metadata_decoder_is_packetized(FILE *fp, bool *is_packetized, int *byte_order, - const bt2c::Logger& logger); - -/* - * Returns the UUID of the decoder's trace class, if available. - * - * Returns: - * - * * `CTF_METADATA_DECODER_STATUS_OK`: success. - * * `CTF_METADATA_DECODER_STATUS_NONE`: no UUID. - * * `CTF_METADATA_DECODER_STATUS_INCOMPLETE`: missing metadata content. - */ -enum ctf_metadata_decoder_status -ctf_metadata_decoder_get_trace_class_uuid(struct ctf_metadata_decoder *mdec, bt_uuid_t uuid); - -/* - * Returns the metadata decoder's current metadata text. - */ -const char *ctf_metadata_decoder_get_text(struct ctf_metadata_decoder *mdec); - -static inline bool ctf_metadata_decoder_is_packet_version_valid(unsigned int major, - unsigned int minor) -{ - return major == 1 && minor == 8; -} - -#endif /* BABELTRACE_PLUGINS_CTF_COMMON_SRC_METADATA_TSDL_DECODER_HPP */ diff --git a/src/plugins/ctf/common/src/metadata/tsdl/visitor-generate-ir.cpp b/src/plugins/ctf/common/src/metadata/tsdl/visitor-generate-ir.cpp index 7000e634..c1449cbf 100644 --- a/src/plugins/ctf/common/src/metadata/tsdl/visitor-generate-ir.cpp +++ b/src/plugins/ctf/common/src/metadata/tsdl/visitor-generate-ir.cpp @@ -464,41 +464,23 @@ ctf_visitor_generate_ir::~ctf_visitor_generate_ir() } } -ctf_visitor_generate_ir::UP -ctf_visitor_generate_ir_create(const bt2::OptionalBorrowedObject selfComp, - const bt2c::Logger& logger) +ctf_visitor_generate_ir::UP ctf_visitor_generate_ir_create(const bt2c::Logger& parentLogger) { - ctf_visitor_generate_ir::UP ctx = bt2s::make_unique(selfComp, logger); - - if (selfComp) { - bt_trace_class *trace_class = bt_trace_class_create(selfComp->libObjPtr()); - if (!trace_class) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Cannot create empty trace class."); - goto error; - } - - ctx->trace_class = bt2::TraceClass::Shared::createWithoutRef(trace_class); - } + auto ctx = bt2s::make_unique(parentLogger); ctx->ctf_tc = ctf_trace_class_create(); if (!ctx->ctf_tc) { BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Cannot create CTF trace class."); - goto error; + return nullptr; } /* Root declaration scope */ ctx->current_scope = ctx_decl_scope_create(ctx.get(), NULL); if (!ctx->current_scope) { BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Cannot create declaration scope."); - goto error; + return nullptr; } - goto end; - -error: - ctx.reset(); - -end: return ctx; } @@ -730,10 +712,9 @@ end: return ret; } -static int get_unary_uuid(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *head, - bt_uuid_t uuid) +static int get_unary_uuid(struct bt_list_head *head, bt_uuid_t uuid, const bt2c::Logger& logger) { - return ctf_ast_get_unary_uuid(head, uuid, ctx->logger); + return ctf_ast_get_unary_uuid(head, uuid, logger); } static int get_boolean(struct ctf_visitor_generate_ir *ctx, struct ctf_node *unary_expr) @@ -2562,7 +2543,6 @@ static int visit_string_decl(struct ctf_visitor_generate_ir *ctx, struct bt_list int set = 0; int ret = 0; struct ctf_node *expression; - enum ctf_encoding encoding = CTF_ENCODING_UTF8; *string_decl = NULL; @@ -2609,9 +2589,9 @@ static int visit_string_decl(struct ctf_visitor_generate_ir *ctx, struct bt_list if (strcmp(s_right, "UTF8") == 0 || strcmp(s_right, "utf8") == 0 || strcmp(s_right, "utf-8") == 0 || strcmp(s_right, "UTF-8") == 0 || strcmp(s_right, "ASCII") == 0 || strcmp(s_right, "ascii") == 0) { - encoding = CTF_ENCODING_UTF8; + /* empty */ } else if (strcmp(s_right, "none") == 0) { - encoding = CTF_ENCODING_NONE; + /* empty */ } else { _BT_CPPLOGE_APPEND_CAUSE_NODE(right, "Invalid `encoding` attribute in string field class: " @@ -2634,7 +2614,6 @@ static int visit_string_decl(struct ctf_visitor_generate_ir *ctx, struct bt_list *string_decl = ctf_field_class_string_create(); BT_ASSERT(*string_decl); - (*string_decl)->encoding = encoding; return 0; error: @@ -3683,7 +3662,7 @@ static int visit_trace_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ct goto error; } - ret = get_unary_uuid(ctx, &node->u.ctf_expression.right, ctx->ctf_tc->uuid); + ret = get_unary_uuid(&node->u.ctf_expression.right, ctx->ctf_tc->uuid, ctx->logger); if (ret) { _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Invalid trace's `uuid` attribute."); goto error; @@ -4021,7 +4000,7 @@ static int visit_clock_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ct goto error; } - ret = get_unary_uuid(ctx, &entry_node->u.ctf_expression.right, uuid); + ret = get_unary_uuid(&entry_node->u.ctf_expression.right, uuid, ctx->logger); if (ret) { _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node, "Invalid clock class's `uuid` attribute."); goto error; @@ -4306,22 +4285,6 @@ end: return ret; } -bt2::TraceClass::Shared -ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir *ctx) -{ - BT_ASSERT_DBG(ctx); - - return ctx->trace_class; -} - -struct ctf_trace_class * -ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir *ctx) -{ - BT_ASSERT_DBG(ctx); - BT_ASSERT_DBG(ctx->ctf_tc); - return ctx->ctf_tc; -} - int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) { int ret = 0; @@ -4478,13 +4441,6 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *ctx, stru goto end; } - /* Update stream class configuration */ - ret = ctf_trace_class_update_stream_class_config(ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - /* Update text arrays and sequences */ ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc); if (ret) { @@ -4506,28 +4462,6 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *ctx, stru goto end; } - if (ctx->trace_class) { - /* - * Update "in IR" for field classes. - * - * If we have no IR trace class, then we'll have no way - * to create IR fields anyway, so we leave all the - * `in_ir` members false. - */ - ret = ctf_trace_class_update_in_ir(ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - } - - /* Update saved value indexes */ - ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - /* Validate what we have so far */ ret = ctf_trace_class_validate(ctx->ctf_tc, ctx->logger); if (ret) { @@ -4542,15 +4476,6 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *ctx, stru */ ctf_trace_class_warn_meaningless_header_fields(ctx->ctf_tc, ctx->logger); - if (ctx->trace_class) { - /* Copy new CTF metadata -> new IR metadata */ - ret = ctf_trace_class_translate(ctx->selfComp, ctx->trace_class->libObjPtr(), ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - } - end: return ret; } diff --git a/src/plugins/ctf/common/src/msg-iter/msg-iter.cpp b/src/plugins/ctf/common/src/msg-iter/msg-iter.cpp deleted file mode 100644 index 50a545bb..00000000 --- a/src/plugins/ctf/common/src/msg-iter/msg-iter.cpp +++ /dev/null @@ -1,3063 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright (c) 2015-2018 EfficiOS Inc. and Linux Foundation - * Copyright (c) 2015-2018 Philippe Proulx - * - * Babeltrace - CTF message iterator - */ - -#include -#include -#include - -#include "common/assert.h" -#include "common/common.h" -#include "cpp-common/bt2c/fmt.hpp" -#include "cpp-common/bt2c/logging.hpp" -#include "cpp-common/bt2c/make-span.hpp" -#include "cpp-common/vendor/fmt/format.h" - -#include "../bfcr/bfcr.hpp" -#include "msg-iter.hpp" - -/* A visit stack entry */ -struct stack_entry -{ - /* - * Current base field, one of: - * - * * string - * * structure - * * array - * * sequence - * * variant - * - * Field is borrowed. - */ - bt_field *base; - - /* Index of next field to set */ - size_t index; -}; - -/* Visit stack */ -struct stack -{ - struct ctf_msg_iter *msg_it; - - /* Entries (struct stack_entry) */ - GArray *entries; - - /* Number of active entries */ - size_t size; -}; - -/* State */ -enum state -{ - STATE_INIT, - STATE_SWITCH_PACKET, - STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN, - STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE, - STATE_AFTER_TRACE_PACKET_HEADER, - STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN, - STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE, - STATE_AFTER_STREAM_PACKET_CONTEXT, - STATE_EMIT_MSG_STREAM_BEGINNING, - STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS, - STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS, - STATE_EMIT_MSG_DISCARDED_EVENTS, - STATE_EMIT_MSG_DISCARDED_PACKETS, - STATE_EMIT_MSG_PACKET_BEGINNING, - STATE_DSCOPE_EVENT_HEADER_BEGIN, - STATE_DSCOPE_EVENT_HEADER_CONTINUE, - STATE_AFTER_EVENT_HEADER, - STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN, - STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE, - STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN, - STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE, - STATE_DSCOPE_EVENT_PAYLOAD_BEGIN, - STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE, - STATE_EMIT_MSG_EVENT, - STATE_EMIT_QUEUED_MSG_EVENT, - STATE_SKIP_PACKET_PADDING, - STATE_EMIT_MSG_PACKET_END_MULTI, - STATE_EMIT_MSG_PACKET_END_SINGLE, - STATE_EMIT_QUEUED_MSG_PACKET_END, - STATE_CHECK_EMIT_MSG_STREAM_END, - STATE_EMIT_MSG_STREAM_END, - STATE_DONE, -}; - -static __attribute__((used)) const char *format_as(state state) -{ - switch (state) { - case STATE_INIT: - return "STATE_INIT"; - - case STATE_SWITCH_PACKET: - return "STATE_SWITCH_PACKET"; - - case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN: - return "STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN"; - - case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE: - return "STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE"; - - case STATE_AFTER_TRACE_PACKET_HEADER: - return "STATE_AFTER_TRACE_PACKET_HEADER"; - - case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN: - return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN"; - - case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE: - return "STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE"; - - case STATE_AFTER_STREAM_PACKET_CONTEXT: - return "STATE_AFTER_STREAM_PACKET_CONTEXT"; - - case STATE_EMIT_MSG_STREAM_BEGINNING: - return "STATE_EMIT_MSG_STREAM_BEGINNING"; - - case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS: - return "STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS"; - - case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS: - return "STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS"; - - case STATE_EMIT_MSG_DISCARDED_EVENTS: - return "STATE_EMIT_MSG_DISCARDED_EVENTS"; - - case STATE_EMIT_MSG_DISCARDED_PACKETS: - return "STATE_EMIT_MSG_DISCARDED_PACKETS"; - - case STATE_EMIT_MSG_PACKET_BEGINNING: - return "STATE_EMIT_MSG_PACKET_BEGINNING"; - - case STATE_DSCOPE_EVENT_HEADER_BEGIN: - return "STATE_DSCOPE_EVENT_HEADER_BEGIN"; - - case STATE_DSCOPE_EVENT_HEADER_CONTINUE: - return "STATE_DSCOPE_EVENT_HEADER_CONTINUE"; - - case STATE_AFTER_EVENT_HEADER: - return "STATE_AFTER_EVENT_HEADER"; - - case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN: - return "STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN"; - - case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE: - return "STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE"; - - case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN: - return "STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN"; - - case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE: - return "STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE"; - - case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN: - return "STATE_DSCOPE_EVENT_PAYLOAD_BEGIN"; - - case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE: - return "STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE"; - - case STATE_EMIT_MSG_EVENT: - return "STATE_EMIT_MSG_EVENT"; - - case STATE_EMIT_QUEUED_MSG_EVENT: - return "STATE_EMIT_QUEUED_MSG_EVENT"; - - case STATE_SKIP_PACKET_PADDING: - return "STATE_SKIP_PACKET_PADDING"; - - case STATE_EMIT_MSG_PACKET_END_MULTI: - return "STATE_EMIT_MSG_PACKET_END_MULTI"; - - case STATE_EMIT_MSG_PACKET_END_SINGLE: - return "STATE_EMIT_MSG_PACKET_END_SINGLE"; - - case STATE_EMIT_QUEUED_MSG_PACKET_END: - return "STATE_EMIT_QUEUED_MSG_PACKET_END"; - - case STATE_CHECK_EMIT_MSG_STREAM_END: - return "STATE_CHECK_EMIT_MSG_STREAM_END"; - - case STATE_EMIT_MSG_STREAM_END: - return "STATE_EMIT_MSG_STREAM_END"; - - case STATE_DONE: - return "STATE_DONE"; - } - - bt_common_abort(); -} - -struct end_of_packet_snapshots -{ - uint64_t discarded_events = 0; - uint64_t packets = 0; - uint64_t beginning_clock = 0; - uint64_t end_clock = 0; -}; - -/* CTF message iterator */ -struct ctf_msg_iter -{ - explicit ctf_msg_iter(bt2c::Logger loggerParam) noexcept : logger {std::move(loggerParam)} - { - } - - /* Visit stack */ - struct stack *stack = nullptr; - - /* Current message iterator to create messages (weak) */ - bt_self_message_iterator *self_msg_iter = nullptr; - - /* - * True if library objects are unavailable during the decoding and - * should not be created/used. - */ - bool dry_run = false; - - /* - * Current dynamic scope field pointer. - * - * This is set by read_dscope_begin_state() and contains the - * value of one of the pointers in `dscopes` below. - */ - bt_field *cur_dscope_field = nullptr; - - /* - * True if we're done filling a string field from a text - * array/sequence payload. - */ - bool done_filling_string = false; - - /* Trace and classes */ - /* True to set IR fields */ - bool set_ir_fields = false; - - struct - { - struct ctf_trace_class *tc = nullptr; - struct ctf_stream_class *sc = nullptr; - struct ctf_event_class *ec = nullptr; - } meta; - - /* Current packet (NULL if not created yet) */ - bt_packet *packet = nullptr; - - /* Current stream (NULL if not set yet) */ - bt_stream *stream = nullptr; - - /* Current event (NULL if not created yet) */ - bt_event *event = nullptr; - - /* Current event message (NULL if not created yet) */ - bt_message *event_msg = nullptr; - - /* - * True if we need to emit a packet beginning message before we emit - * the next event message or the packet end message. - */ - bool emit_delayed_packet_beginning_msg = false; - - /* - * True if this is the first packet we are reading, and therefore if we - * should emit a stream beginning message. - */ - bool emit_stream_beginning_message = false; - - /* - * True if we need to emit a stream end message at the end of the - * current stream. A live stream may never receive any data and thus - * never send a stream beginning message which removes the need to emit - * a stream end message. - */ - bool emit_stream_end_message = false; - - /* Database of current dynamic scopes */ - struct - { - bt_field *stream_packet_context = nullptr; - bt_field *event_common_context = nullptr; - bt_field *event_spec_context = nullptr; - bt_field *event_payload = nullptr; - } dscopes; - - /* Current state */ - enum state state = STATE_INIT; - - /* Current medium buffer data */ - struct - { - /* Last address provided by medium */ - const uint8_t *addr = nullptr; - - /* Buffer size provided by medium (bytes) */ - size_t sz = 0; - - /* Offset within whole packet of addr (bits) */ - size_t packet_offset = 0; - - /* Current position from addr (bits) */ - size_t at = 0; - - /* Position of the last event header from addr (bits) */ - size_t last_eh_at = 0; - } buf; - - /* Binary type reader */ - struct bt_bfcr *bfcr = nullptr; - - /* Current medium data */ - struct - { - struct ctf_msg_iter_medium_ops medops; - size_t max_request_sz = 0; - void *data = nullptr; - } medium; - - /* Current packet size (bits) (-1 if unknown) */ - int64_t cur_exp_packet_total_size = 0; - - /* Current content size (bits) (-1 if unknown) */ - int64_t cur_exp_packet_content_size = 0; - - /* Current stream class ID */ - int64_t cur_stream_class_id = 0; - - /* Current event class ID */ - int64_t cur_event_class_id = 0; - - /* Current data stream ID */ - int64_t cur_data_stream_id = 0; - - /* - * Offset, in the underlying media, of the current packet's - * start (-1 if unknown). - */ - off_t cur_packet_offset = 0; - - /* Default clock's current value */ - uint64_t default_clock_snapshot = 0; - - /* End of current packet snapshots */ - struct end_of_packet_snapshots snapshots; - - /* End of previous packet snapshots */ - struct end_of_packet_snapshots prev_packet_snapshots; - - /* Stored values (for sequence lengths, variant tags) */ - GArray *stored_values = nullptr; - - bt2c::Logger logger; -}; - -static struct stack *stack_new(struct ctf_msg_iter *msg_it) -{ - struct stack *stack = NULL; - - stack = g_new0(struct stack, 1); - if (!stack) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, "Failed to allocate one stack."); - goto error; - } - - stack->msg_it = msg_it; - stack->entries = g_array_new(FALSE, TRUE, sizeof(struct stack_entry)); - if (!stack->entries) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, "Failed to allocate a GArray."); - goto error; - } - - BT_CPPLOGD_SPEC(msg_it->logger, "Created stack: msg-it-addr={}, stack-addr={}", - fmt::ptr(msg_it), fmt::ptr(stack)); - goto end; - -error: - g_free(stack); - stack = NULL; - -end: - return stack; -} - -static void stack_destroy(struct stack *stack) -{ - struct ctf_msg_iter *msg_it; - - BT_ASSERT_DBG(stack); - msg_it = stack->msg_it; - BT_CPPLOGD_SPEC(msg_it->logger, "Destroying stack: addr={}", fmt::ptr(stack)); - - if (stack->entries) { - g_array_free(stack->entries, TRUE); - } - - g_free(stack); -} - -static void stack_push(struct stack *stack, bt_field *base) -{ - struct stack_entry *entry; - struct ctf_msg_iter *msg_it; - - BT_ASSERT_DBG(stack); - msg_it = stack->msg_it; - BT_ASSERT_DBG(base); - BT_CPPLOGT_SPEC(msg_it->logger, - "Pushing base field on stack: stack-addr={}, " - "stack-size-before={}, stack-size-after={}", - fmt::ptr(stack), stack->size, stack->size + 1); - - if (stack->entries->len == stack->size) { - g_array_set_size(stack->entries, stack->size + 1); - } - - entry = &bt_g_array_index(stack->entries, struct stack_entry, stack->size); - entry->base = base; - entry->index = 0; - stack->size++; -} - -static inline unsigned int stack_size(struct stack *stack) -{ - BT_ASSERT_DBG(stack); - return stack->size; -} - -static void stack_pop(struct stack *stack) -{ - struct ctf_msg_iter *msg_it; - - BT_ASSERT_DBG(stack); - BT_ASSERT_DBG(stack_size(stack)); - msg_it = stack->msg_it; - BT_CPPLOGT_SPEC(msg_it->logger, - "Popping from stack: " - "stack-addr={}, stack-size-before={}, stack-size-after={}", - fmt::ptr(stack), stack->size, stack->size - 1); - stack->size--; -} - -static inline struct stack_entry *stack_top(struct stack *stack) -{ - BT_ASSERT_DBG(stack); - BT_ASSERT_DBG(stack_size(stack)); - return &bt_g_array_index(stack->entries, struct stack_entry, stack->size - 1); -} - -static inline bool stack_empty(struct stack *stack) -{ - return stack_size(stack) == 0; -} - -static void stack_clear(struct stack *stack) -{ - BT_ASSERT_DBG(stack); - stack->size = 0; -} - -static inline enum ctf_msg_iter_status -msg_iter_status_from_m_status(enum ctf_msg_iter_medium_status m_status) -{ - /* They are the same */ - return (ctf_msg_iter_status) m_status; -} - -static inline size_t buf_size_bits(struct ctf_msg_iter *msg_it) -{ - return msg_it->buf.sz * 8; -} - -static inline size_t buf_available_bits(struct ctf_msg_iter *msg_it) -{ - return buf_size_bits(msg_it) - msg_it->buf.at; -} - -static inline size_t packet_at(struct ctf_msg_iter *msg_it) -{ - return msg_it->buf.packet_offset + msg_it->buf.at; -} - -static inline void buf_consume_bits(struct ctf_msg_iter *msg_it, size_t incr) -{ - BT_CPPLOGT_SPEC(msg_it->logger, "Advancing cursor: msg-it-addr={}, cur-before={}, cur-after={}", - fmt::ptr(msg_it), msg_it->buf.at, msg_it->buf.at + incr); - msg_it->buf.at += incr; -} - -static enum ctf_msg_iter_status request_medium_bytes(struct ctf_msg_iter *msg_it) -{ - uint8_t *buffer_addr = NULL; - size_t buffer_sz = 0; - enum ctf_msg_iter_medium_status m_status; - - BT_CPPLOGD_SPEC(msg_it->logger, - "Calling user function (request bytes): msg-it-addr={}, " - "request-size={}", - fmt::ptr(msg_it), msg_it->medium.max_request_sz); - m_status = msg_it->medium.medops.request_bytes(msg_it->medium.max_request_sz, &buffer_addr, - &buffer_sz, msg_it->medium.data); - BT_CPPLOGD_SPEC(msg_it->logger, "User function returned: status={}, buf-addr={}, buf-size={}", - m_status, fmt::ptr(buffer_addr), buffer_sz); - if (m_status == CTF_MSG_ITER_MEDIUM_STATUS_OK) { - BT_ASSERT(buffer_sz != 0); - - /* New packet offset is old one + old size (in bits) */ - msg_it->buf.packet_offset += buf_size_bits(msg_it); - - /* Restart at the beginning of the new medium buffer */ - msg_it->buf.at = 0; - msg_it->buf.last_eh_at = SIZE_MAX; - - /* New medium buffer size */ - msg_it->buf.sz = buffer_sz; - - /* New medium buffer address */ - msg_it->buf.addr = buffer_addr; - - BT_CPPLOGD_SPEC(msg_it->logger, - "User function returned new bytes: " - "packet-offset={}, cur={}, size={}, addr={}", - msg_it->buf.packet_offset, msg_it->buf.at, msg_it->buf.sz, - fmt::ptr(msg_it->buf.addr)); - BT_CPPLOGT_MEM_SPEC(msg_it->logger, bt2c::makeSpan(buffer_addr, buffer_sz), - "Returned bytes at {}:", fmt::ptr(buffer_addr)); - } else if (m_status == CTF_MSG_ITER_MEDIUM_STATUS_EOF) { - /* - * User returned end of stream: validate that we're not - * in the middle of a packet header, packet context, or - * event. - */ - if (msg_it->cur_exp_packet_total_size >= 0) { - if (packet_at(msg_it) == msg_it->cur_exp_packet_total_size) { - goto end; - } - } else { - if (packet_at(msg_it) == 0) { - goto end; - } - - if (msg_it->buf.last_eh_at != SIZE_MAX && msg_it->buf.at == msg_it->buf.last_eh_at) { - goto end; - } - } - - /* All other states are invalid */ - BT_CPPLOGE_APPEND_CAUSE_SPEC( - msg_it->logger, - "User function returned {}, but message iterator is in an unexpected state: " - "state={}, cur-packet-size={}, cur={}, " - "packet-cur={}, last-eh-at={}", - m_status, msg_it->state, msg_it->cur_exp_packet_total_size, msg_it->buf.at, - packet_at(msg_it), msg_it->buf.last_eh_at); - m_status = CTF_MSG_ITER_MEDIUM_STATUS_ERROR; - } else if (m_status < 0) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "User function failed: " - "status={}", - m_status); - } - -end: - return msg_iter_status_from_m_status(m_status); -} - -static inline enum ctf_msg_iter_status buf_ensure_available_bits(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - - if (G_UNLIKELY(buf_available_bits(msg_it) == 0)) { - /* - * This _cannot_ return CTF_MSG_ITER_STATUS_OK - * _and_ no bits. - */ - status = request_medium_bytes(msg_it); - } - - return status; -} - -static enum ctf_msg_iter_status -read_dscope_begin_state(struct ctf_msg_iter *msg_it, struct ctf_field_class *dscope_fc, - enum state done_state, enum state continue_state, bt_field *dscope_field) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - enum bt_bfcr_status bfcr_status; - size_t consumed_bits; - - msg_it->cur_dscope_field = dscope_field; - BT_CPPLOGT_SPEC(msg_it->logger, "Starting BFCR: msg-it-addr={}, bfcr-addr={}, fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(dscope_fc)); - consumed_bits = bt_bfcr_start(msg_it->bfcr, dscope_fc, msg_it->buf.addr, msg_it->buf.at, - packet_at(msg_it), msg_it->buf.sz, &bfcr_status); - BT_CPPLOGT_SPEC(msg_it->logger, "BFCR consumed bits: size={}", consumed_bits); - - switch (bfcr_status) { - case BT_BFCR_STATUS_OK: - /* Field class was read completely */ - BT_CPPLOGT_SPEC(msg_it->logger, "Field was completely decoded."); - msg_it->state = done_state; - break; - case BT_BFCR_STATUS_EOF: - BT_CPPLOGT_SPEC(msg_it->logger, "BFCR needs more data to decode field completely."); - msg_it->state = continue_state; - break; - default: - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "BFCR failed to start: msg-it-addr={}, bfcr-addr={}, " - "status={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), bfcr_status); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - - /* Consume bits now since we know we're not in an error state */ - buf_consume_bits(msg_it, consumed_bits); - -end: - return status; -} - -static enum ctf_msg_iter_status read_dscope_continue_state(struct ctf_msg_iter *msg_it, - enum state done_state) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - enum bt_bfcr_status bfcr_status; - size_t consumed_bits; - - BT_CPPLOGT_SPEC(msg_it->logger, "Continuing BFCR: msg-it-addr={}, bfcr-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr)); - - status = buf_ensure_available_bits(msg_it); - if (status != CTF_MSG_ITER_STATUS_OK) { - if (status < 0) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot ensure that buffer has at least one byte: " - "msg-addr={}, status={}", - fmt::ptr(msg_it), status); - } else { - BT_CPPLOGT_SPEC(msg_it->logger, - "Cannot ensure that buffer has at least one byte: " - "msg-addr={}, status={}", - fmt::ptr(msg_it), status); - } - - goto end; - } - - consumed_bits = bt_bfcr_continue(msg_it->bfcr, msg_it->buf.addr, msg_it->buf.sz, &bfcr_status); - BT_CPPLOGT_SPEC(msg_it->logger, "BFCR consumed bits: size={}", consumed_bits); - - switch (bfcr_status) { - case BT_BFCR_STATUS_OK: - /* Type was read completely. */ - BT_CPPLOGT_SPEC(msg_it->logger, "Field was completely decoded."); - msg_it->state = done_state; - break; - case BT_BFCR_STATUS_EOF: - /* Stay in this continue state. */ - BT_CPPLOGT_SPEC(msg_it->logger, "BFCR needs more data to decode field completely."); - break; - default: - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "BFCR failed to continue: msg-it-addr={}, bfcr-addr={}, " - "status={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), bfcr_status); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - - /* Consume bits now since we know we're not in an error state. */ - buf_consume_bits(msg_it, consumed_bits); -end: - return status; -} - -static void release_event_dscopes(struct ctf_msg_iter *msg_it) -{ - msg_it->dscopes.event_common_context = NULL; - msg_it->dscopes.event_spec_context = NULL; - msg_it->dscopes.event_payload = NULL; -} - -static void release_all_dscopes(struct ctf_msg_iter *msg_it) -{ - msg_it->dscopes.stream_packet_context = NULL; - - release_event_dscopes(msg_it); -} - -static enum ctf_msg_iter_status switch_packet_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status; - - /* - * We don't put the stream class here because we need to make - * sure that all the packets processed by the same message - * iterator refer to the same stream class (the first one). - */ - BT_ASSERT(msg_it); - - if (msg_it->cur_exp_packet_total_size != -1) { - msg_it->cur_packet_offset += msg_it->cur_exp_packet_total_size; - } - - BT_CPPLOGD_SPEC(msg_it->logger, - "Switching packet: msg-it-addr={}, cur={}, " - "packet-offset={}", - fmt::ptr(msg_it), msg_it->buf.at, msg_it->cur_packet_offset); - stack_clear(msg_it->stack); - msg_it->meta.ec = NULL; - BT_PACKET_PUT_REF_AND_RESET(msg_it->packet); - BT_MESSAGE_PUT_REF_AND_RESET(msg_it->event_msg); - release_all_dscopes(msg_it); - msg_it->cur_dscope_field = NULL; - - if (msg_it->medium.medops.switch_packet) { - enum ctf_msg_iter_medium_status medium_status; - - medium_status = msg_it->medium.medops.switch_packet(msg_it->medium.data); - if (medium_status == CTF_MSG_ITER_MEDIUM_STATUS_EOF) { - /* No more packets. */ - msg_it->state = STATE_CHECK_EMIT_MSG_STREAM_END; - status = CTF_MSG_ITER_STATUS_OK; - goto end; - } else if (medium_status != CTF_MSG_ITER_MEDIUM_STATUS_OK) { - status = msg_iter_status_from_m_status(medium_status); - goto end; - } - - /* - * After the packet switch, the medium might want to give us a - * different buffer for the new packet. - */ - status = request_medium_bytes(msg_it); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - } - - /* - * Adjust current buffer so that addr points to the beginning of the new - * packet. - */ - if (msg_it->buf.addr) { - size_t consumed_bytes = (size_t) (msg_it->buf.at / CHAR_BIT); - - /* Packets are assumed to start on a byte frontier. */ - if (msg_it->buf.at % CHAR_BIT) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - msg_it->logger, - "Cannot switch packet: current position is not a multiple of 8: " - "msg-it-addr={}, cur={}", - fmt::ptr(msg_it), msg_it->buf.at); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - - msg_it->buf.addr += consumed_bytes; - msg_it->buf.sz -= consumed_bytes; - msg_it->buf.at = 0; - msg_it->buf.packet_offset = 0; - BT_CPPLOGD_SPEC(msg_it->logger, "Adjusted buffer: addr={}, size={}", - fmt::ptr(msg_it->buf.addr), msg_it->buf.sz); - } - - msg_it->cur_exp_packet_content_size = -1; - msg_it->cur_exp_packet_total_size = -1; - msg_it->cur_stream_class_id = -1; - msg_it->cur_event_class_id = -1; - msg_it->cur_data_stream_id = -1; - msg_it->prev_packet_snapshots = msg_it->snapshots; - msg_it->snapshots.discarded_events = UINT64_C(-1); - msg_it->snapshots.packets = UINT64_C(-1); - msg_it->snapshots.beginning_clock = UINT64_C(-1); - msg_it->snapshots.end_clock = UINT64_C(-1); - msg_it->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN; - - status = CTF_MSG_ITER_STATUS_OK; -end: - return status; -} - -static enum ctf_msg_iter_status read_packet_header_begin_state(struct ctf_msg_iter *msg_it) -{ - struct ctf_field_class *packet_header_fc = NULL; - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - - /* - * Make sure at least one bit is available for this packet. An - * empty packet is impossible. If we reach the end of the medium - * at this point, then it's considered the end of the stream. - */ - status = buf_ensure_available_bits(msg_it); - switch (status) { - case CTF_MSG_ITER_STATUS_OK: - break; - case CTF_MSG_ITER_STATUS_EOF: - status = CTF_MSG_ITER_STATUS_OK; - msg_it->state = STATE_CHECK_EMIT_MSG_STREAM_END; - goto end; - default: - goto end; - } - - /* Packet header class is common to the whole trace class. */ - packet_header_fc = msg_it->meta.tc->packet_header_fc; - if (!packet_header_fc) { - msg_it->state = STATE_AFTER_TRACE_PACKET_HEADER; - goto end; - } - - msg_it->cur_stream_class_id = -1; - msg_it->cur_event_class_id = -1; - msg_it->cur_data_stream_id = -1; - BT_CPPLOGD_SPEC(msg_it->logger, - "Decoding packet header field: " - "msg-it-addr={}, trace-class-addr={}, fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.tc), fmt::ptr(packet_header_fc)); - status = read_dscope_begin_state(msg_it, packet_header_fc, STATE_AFTER_TRACE_PACKET_HEADER, - STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE, NULL); - if (status < 0) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot decode packet header field: " - "msg-it-addr={}, trace-class-addr={}, " - "fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.tc), - fmt::ptr(packet_header_fc)); - } - -end: - return status; -} - -static enum ctf_msg_iter_status read_packet_header_continue_state(struct ctf_msg_iter *msg_it) -{ - return read_dscope_continue_state(msg_it, STATE_AFTER_TRACE_PACKET_HEADER); -} - -static inline enum ctf_msg_iter_status set_current_stream_class(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - struct ctf_stream_class *new_stream_class = NULL; - - if (msg_it->cur_stream_class_id == -1) { - /* - * No current stream class ID field, therefore only one - * stream class. - */ - if (msg_it->meta.tc->stream_classes->len != 1) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Need exactly one stream class since there's " - "no stream class ID field: " - "msg-it-addr={}", - fmt::ptr(msg_it)); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - - new_stream_class = (ctf_stream_class *) msg_it->meta.tc->stream_classes->pdata[0]; - msg_it->cur_stream_class_id = new_stream_class->id; - } - - new_stream_class = - ctf_trace_class_borrow_stream_class_by_id(msg_it->meta.tc, msg_it->cur_stream_class_id); - if (!new_stream_class) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - msg_it->logger, - "No stream class with ID of stream class ID to use in trace class: " - "msg-it-addr={}, stream-class-id={}, " - "trace-class-addr={}", - fmt::ptr(msg_it), msg_it->cur_stream_class_id, fmt::ptr(msg_it->meta.tc)); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - - if (msg_it->meta.sc) { - if (new_stream_class != msg_it->meta.sc) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - msg_it->logger, - "Two packets refer to two different stream classes within the same packet sequence: " - "msg-it-addr={}, prev-stream-class-addr={}, " - "prev-stream-class-id={}, " - "next-stream-class-addr={}, " - "next-stream-class-id={}, " - "trace-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id, - fmt::ptr(new_stream_class), new_stream_class->id, fmt::ptr(msg_it->meta.tc)); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - } else { - msg_it->meta.sc = new_stream_class; - } - - BT_CPPLOGD_SPEC(msg_it->logger, - "Set current stream class: " - "msg-it-addr={}, stream-class-addr={}, " - "stream-class-id={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id); - -end: - return status; -} - -static inline enum ctf_msg_iter_status set_current_stream(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - bt_stream *stream = NULL; - - BT_CPPLOGD_SPEC(msg_it->logger, - "Calling user function (get stream): msg-it-addr={}, " - "stream-class-addr={}, stream-class-id={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id); - stream = msg_it->medium.medops.borrow_stream(msg_it->meta.sc->ir_sc, msg_it->cur_data_stream_id, - msg_it->medium.data); - bt_stream_get_ref(stream); - BT_CPPLOGD_SPEC(msg_it->logger, "User function returned: stream-addr={}", fmt::ptr(stream)); - if (!stream) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - msg_it->logger, - "User function failed to return a stream object for the given stream class."); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - - if (msg_it->stream && stream != msg_it->stream) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - msg_it->logger, - "User function returned a different stream than the previous one for the same sequence of packets."); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - - BT_STREAM_MOVE_REF(msg_it->stream, stream); - -end: - bt_stream_put_ref(stream); - return status; -} - -static inline enum ctf_msg_iter_status set_current_packet(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - bt_packet *packet = NULL; - - BT_CPPLOGD_SPEC(msg_it->logger, - "Creating packet from stream: " - "msg-it-addr={}, stream-addr={}, " - "stream-class-addr={}, " - "stream-class-id={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->stream), fmt::ptr(msg_it->meta.sc), - msg_it->meta.sc->id); - - /* Create packet */ - BT_ASSERT(msg_it->stream); - packet = bt_packet_create(msg_it->stream); - if (!packet) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot create packet from stream: " - "msg-it-addr={}, stream-addr={}, " - "stream-class-addr={}, " - "stream-class-id={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->stream), - fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id); - goto error; - } - - goto end; - -error: - BT_PACKET_PUT_REF_AND_RESET(packet); - status = CTF_MSG_ITER_STATUS_ERROR; - -end: - BT_PACKET_MOVE_REF(msg_it->packet, packet); - return status; -} - -static enum ctf_msg_iter_status after_packet_header_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status; - - status = set_current_stream_class(msg_it); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - - if (!msg_it->dry_run) { - status = set_current_stream(msg_it); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - - status = set_current_packet(msg_it); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - } - - msg_it->state = STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN; - - status = CTF_MSG_ITER_STATUS_OK; - -end: - return status; -} - -static enum ctf_msg_iter_status read_packet_context_begin_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - struct ctf_field_class *packet_context_fc; - - BT_ASSERT(msg_it->meta.sc); - packet_context_fc = msg_it->meta.sc->packet_context_fc; - if (!packet_context_fc) { - BT_CPPLOGD_SPEC(msg_it->logger, - "No packet packet context field class in stream class: continuing: " - "msg-it-addr={}, stream-class-addr={}, " - "stream-class-id={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id); - msg_it->state = STATE_AFTER_STREAM_PACKET_CONTEXT; - goto end; - } - - if (packet_context_fc->in_ir && !msg_it->dry_run) { - BT_ASSERT(!msg_it->dscopes.stream_packet_context); - BT_ASSERT(msg_it->packet); - msg_it->dscopes.stream_packet_context = bt_packet_borrow_context_field(msg_it->packet); - BT_ASSERT(msg_it->dscopes.stream_packet_context); - } - - BT_CPPLOGD_SPEC(msg_it->logger, - "Decoding packet context field: " - "msg-it-addr={}, stream-class-addr={}, " - "stream-class-id={}, fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id, - fmt::ptr(packet_context_fc)); - status = read_dscope_begin_state(msg_it, packet_context_fc, STATE_AFTER_STREAM_PACKET_CONTEXT, - STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE, - msg_it->dscopes.stream_packet_context); - if (status < 0) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot decode packet context field: " - "msg-it-addr={}, stream-class-addr={}, " - "stream-class-id={}, fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), - msg_it->meta.sc->id, fmt::ptr(packet_context_fc)); - } - -end: - return status; -} - -static enum ctf_msg_iter_status read_packet_context_continue_state(struct ctf_msg_iter *msg_it) -{ - return read_dscope_continue_state(msg_it, STATE_AFTER_STREAM_PACKET_CONTEXT); -} - -static enum ctf_msg_iter_status set_current_packet_content_sizes(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - - if (msg_it->cur_exp_packet_total_size == -1) { - if (msg_it->cur_exp_packet_content_size != -1) { - msg_it->cur_exp_packet_total_size = msg_it->cur_exp_packet_content_size; - } - } else { - if (msg_it->cur_exp_packet_content_size == -1) { - msg_it->cur_exp_packet_content_size = msg_it->cur_exp_packet_total_size; - } - } - - BT_ASSERT( - (msg_it->cur_exp_packet_total_size >= 0 && msg_it->cur_exp_packet_content_size >= 0) || - (msg_it->cur_exp_packet_total_size < 0 && msg_it->cur_exp_packet_content_size < 0)); - - if (msg_it->cur_exp_packet_content_size > msg_it->cur_exp_packet_total_size) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - msg_it->logger, - "Invalid packet or content size: " - "content size is greater than packet size: " - "msg-it-addr={}, packet-context-field-addr={}, " - "packet-size={}, content-size={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->dscopes.stream_packet_context), - msg_it->cur_exp_packet_total_size, msg_it->cur_exp_packet_content_size); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - - BT_CPPLOGD_SPEC(msg_it->logger, - "Set current packet and content sizes: " - "msg-it-addr={}, packet-size={}, content-size={}", - fmt::ptr(msg_it), msg_it->cur_exp_packet_total_size, - msg_it->cur_exp_packet_content_size); - -end: - return status; -} - -static enum ctf_msg_iter_status after_packet_context_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status; - - status = set_current_packet_content_sizes(msg_it); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - - if (msg_it->emit_stream_beginning_message) { - msg_it->state = STATE_EMIT_MSG_STREAM_BEGINNING; - } else { - msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS; - } - -end: - return status; -} - -static enum ctf_msg_iter_status read_event_header_begin_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - struct ctf_field_class *event_header_fc = NULL; - - /* Reset the position of the last event header */ - msg_it->buf.last_eh_at = msg_it->buf.at; - msg_it->cur_event_class_id = -1; - - /* Check if we have some content left */ - if (msg_it->cur_exp_packet_content_size >= 0) { - if (G_UNLIKELY(packet_at(msg_it) == msg_it->cur_exp_packet_content_size)) { - /* No more events! */ - BT_CPPLOGD_SPEC(msg_it->logger, - "Reached end of packet: msg-it-addr={}, " - "cur={}", - fmt::ptr(msg_it), packet_at(msg_it)); - msg_it->state = STATE_EMIT_MSG_PACKET_END_MULTI; - goto end; - } else if (G_UNLIKELY(packet_at(msg_it) > msg_it->cur_exp_packet_content_size)) { - /* That's not supposed to happen */ - BT_CPPLOGD_SPEC( - msg_it->logger, - "Before decoding event header field: cursor is passed the packet's content: " - "msg-it-addr={}, content-size={}, " - "cur={}", - fmt::ptr(msg_it), msg_it->cur_exp_packet_content_size, packet_at(msg_it)); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - } else { - /* - * "Infinite" content: we're done when the medium has - * nothing else for us. - */ - status = buf_ensure_available_bits(msg_it); - switch (status) { - case CTF_MSG_ITER_STATUS_OK: - break; - case CTF_MSG_ITER_STATUS_EOF: - status = CTF_MSG_ITER_STATUS_OK; - msg_it->state = STATE_EMIT_MSG_PACKET_END_SINGLE; - goto end; - default: - goto end; - } - } - - release_event_dscopes(msg_it); - BT_ASSERT(msg_it->meta.sc); - event_header_fc = msg_it->meta.sc->event_header_fc; - if (!event_header_fc) { - msg_it->state = STATE_AFTER_EVENT_HEADER; - goto end; - } - - BT_CPPLOGD_SPEC(msg_it->logger, - "Decoding event header field: " - "msg-it-addr={}, stream-class-addr={}, " - "stream-class-id={}, " - "fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id, - fmt::ptr(event_header_fc)); - status = read_dscope_begin_state(msg_it, event_header_fc, STATE_AFTER_EVENT_HEADER, - STATE_DSCOPE_EVENT_HEADER_CONTINUE, NULL); - if (status < 0) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot decode event header field: " - "msg-it-addr={}, stream-class-addr={}, " - "stream-class-id={}, fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), - msg_it->meta.sc->id, fmt::ptr(event_header_fc)); - } - -end: - return status; -} - -static enum ctf_msg_iter_status read_event_header_continue_state(struct ctf_msg_iter *msg_it) -{ - return read_dscope_continue_state(msg_it, STATE_AFTER_EVENT_HEADER); -} - -static inline enum ctf_msg_iter_status set_current_event_class(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - - struct ctf_event_class *new_event_class = NULL; - - if (msg_it->cur_event_class_id == -1) { - /* - * No current event class ID field, therefore only one - * event class. - */ - if (msg_it->meta.sc->event_classes->len != 1) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - msg_it->logger, - "Need exactly one event class since there's no event class ID field: " - "msg-it-addr={}", - fmt::ptr(msg_it)); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - - new_event_class = (ctf_event_class *) msg_it->meta.sc->event_classes->pdata[0]; - msg_it->cur_event_class_id = new_event_class->id; - } - - new_event_class = - ctf_stream_class_borrow_event_class_by_id(msg_it->meta.sc, msg_it->cur_event_class_id); - if (!new_event_class) { - BT_CPPLOGE_APPEND_CAUSE_SPEC( - msg_it->logger, - "No event class with ID of event class ID to use in stream class: " - "msg-it-addr={}, stream-class-id={}, " - "event-class-id={}, " - "trace-class-addr={}", - fmt::ptr(msg_it), msg_it->meta.sc->id, msg_it->cur_event_class_id, - fmt::ptr(msg_it->meta.tc)); - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - - msg_it->meta.ec = new_event_class; - BT_CPPLOGD_SPEC(msg_it->logger, - "Set current event class: " - "msg-it-addr={}, event-class-addr={}, " - "event-class-id={}, " - "event-class-name=\"{}\"", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), msg_it->meta.ec->id, - msg_it->meta.ec->name->str); - -end: - return status; -} - -static inline enum ctf_msg_iter_status set_current_event_message(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - bt_message *msg = NULL; - - BT_ASSERT_DBG(msg_it->meta.ec); - BT_ASSERT_DBG(msg_it->packet); - BT_CPPLOGD_SPEC(msg_it->logger, - "Creating event message from event class and packet: " - "msg-it-addr={}, ec-addr={}, ec-name=\"{}\", packet-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), msg_it->meta.ec->name->str, - fmt::ptr(msg_it->packet)); - BT_ASSERT_DBG(msg_it->self_msg_iter); - BT_ASSERT_DBG(msg_it->meta.sc); - - if (bt_stream_class_borrow_default_clock_class(msg_it->meta.sc->ir_sc)) { - msg = bt_message_event_create_with_packet_and_default_clock_snapshot( - msg_it->self_msg_iter, msg_it->meta.ec->ir_ec, msg_it->packet, - msg_it->default_clock_snapshot); - } else { - msg = bt_message_event_create_with_packet(msg_it->self_msg_iter, msg_it->meta.ec->ir_ec, - msg_it->packet); - } - - if (!msg) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot create event message: " - "msg-it-addr={}, ec-addr={}, ec-name=\"{}\", " - "packet-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), - msg_it->meta.ec->name->str, fmt::ptr(msg_it->packet)); - goto error; - } - - goto end; - -error: - BT_MESSAGE_PUT_REF_AND_RESET(msg); - status = CTF_MSG_ITER_STATUS_ERROR; - -end: - BT_MESSAGE_MOVE_REF(msg_it->event_msg, msg); - return status; -} - -static enum ctf_msg_iter_status after_event_header_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status; - - status = set_current_event_class(msg_it); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - - if (G_UNLIKELY(msg_it->dry_run)) { - goto next_state; - } - - status = set_current_event_message(msg_it); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - - msg_it->event = bt_message_event_borrow_event(msg_it->event_msg); - BT_ASSERT_DBG(msg_it->event); - -next_state: - msg_it->state = STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN; - -end: - return status; -} - -static enum ctf_msg_iter_status read_event_common_context_begin_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - struct ctf_field_class *event_common_context_fc; - - event_common_context_fc = msg_it->meta.sc->event_common_context_fc; - if (!event_common_context_fc) { - msg_it->state = STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN; - goto end; - } - - if (event_common_context_fc->in_ir && !msg_it->dry_run) { - BT_ASSERT_DBG(!msg_it->dscopes.event_common_context); - msg_it->dscopes.event_common_context = bt_event_borrow_common_context_field(msg_it->event); - BT_ASSERT_DBG(msg_it->dscopes.event_common_context); - } - - BT_CPPLOGT_SPEC(msg_it->logger, - "Decoding event common context field: " - "msg-it-addr={}, stream-class-addr={}, " - "stream-class-id={}, " - "fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), msg_it->meta.sc->id, - fmt::ptr(event_common_context_fc)); - status = read_dscope_begin_state( - msg_it, event_common_context_fc, STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN, - STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE, msg_it->dscopes.event_common_context); - if (status < 0) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot decode event common context field: " - "msg-it-addr={}, stream-class-addr={}, " - "stream-class-id={}, fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.sc), - msg_it->meta.sc->id, fmt::ptr(event_common_context_fc)); - } - -end: - return status; -} - -static enum ctf_msg_iter_status -read_event_common_context_continue_state(struct ctf_msg_iter *msg_it) -{ - return read_dscope_continue_state(msg_it, STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN); -} - -static enum ctf_msg_iter_status read_event_spec_context_begin_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - struct ctf_field_class *event_spec_context_fc; - - event_spec_context_fc = msg_it->meta.ec->spec_context_fc; - if (!event_spec_context_fc) { - msg_it->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN; - goto end; - } - - if (event_spec_context_fc->in_ir && !msg_it->dry_run) { - BT_ASSERT_DBG(!msg_it->dscopes.event_spec_context); - msg_it->dscopes.event_spec_context = bt_event_borrow_specific_context_field(msg_it->event); - BT_ASSERT_DBG(msg_it->dscopes.event_spec_context); - } - - BT_CPPLOGT_SPEC(msg_it->logger, - "Decoding event specific context field: " - "msg-it-addr={}, event-class-addr={}, " - "event-class-name=\"{}\", event-class-id={}, " - "fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), msg_it->meta.ec->name->str, - msg_it->meta.ec->id, fmt::ptr(event_spec_context_fc)); - status = read_dscope_begin_state( - msg_it, event_spec_context_fc, STATE_DSCOPE_EVENT_PAYLOAD_BEGIN, - STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE, msg_it->dscopes.event_spec_context); - if (status < 0) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot decode event specific context field: " - "msg-it-addr={}, event-class-addr={}, " - "event-class-name=\"{}\", " - "event-class-id={}, fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), - msg_it->meta.ec->name->str, msg_it->meta.ec->id, - fmt::ptr(event_spec_context_fc)); - } - -end: - return status; -} - -static enum ctf_msg_iter_status read_event_spec_context_continue_state(struct ctf_msg_iter *msg_it) -{ - return read_dscope_continue_state(msg_it, STATE_DSCOPE_EVENT_PAYLOAD_BEGIN); -} - -static enum ctf_msg_iter_status read_event_payload_begin_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - struct ctf_field_class *event_payload_fc; - - event_payload_fc = msg_it->meta.ec->payload_fc; - if (!event_payload_fc) { - msg_it->state = STATE_EMIT_MSG_EVENT; - goto end; - } - - if (event_payload_fc->in_ir && !msg_it->dry_run) { - BT_ASSERT_DBG(!msg_it->dscopes.event_payload); - msg_it->dscopes.event_payload = bt_event_borrow_payload_field(msg_it->event); - BT_ASSERT_DBG(msg_it->dscopes.event_payload); - } - - BT_CPPLOGT_SPEC(msg_it->logger, - "Decoding event payload field: " - "msg-it-addr={}, event-class-addr={}, " - "event-class-name=\"{}\", event-class-id={}, " - "fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), msg_it->meta.ec->name->str, - msg_it->meta.ec->id, fmt::ptr(event_payload_fc)); - status = - read_dscope_begin_state(msg_it, event_payload_fc, STATE_EMIT_MSG_EVENT, - STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE, msg_it->dscopes.event_payload); - if (status < 0) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot decode event payload field: " - "msg-it-addr={}, event-class-addr={}, " - "event-class-name=\"{}\", " - "event-class-id={}, fc-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->meta.ec), - msg_it->meta.ec->name->str, msg_it->meta.ec->id, - fmt::ptr(event_payload_fc)); - } - -end: - return status; -} - -static enum ctf_msg_iter_status read_event_payload_continue_state(struct ctf_msg_iter *msg_it) -{ - return read_dscope_continue_state(msg_it, STATE_EMIT_MSG_EVENT); -} - -static enum ctf_msg_iter_status skip_packet_padding_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - size_t bits_to_skip; - const enum state next_state = STATE_SWITCH_PACKET; - - BT_ASSERT(msg_it->cur_exp_packet_total_size > 0); - bits_to_skip = msg_it->cur_exp_packet_total_size - packet_at(msg_it); - if (bits_to_skip == 0) { - msg_it->state = next_state; - goto end; - } else { - size_t bits_to_consume; - - BT_CPPLOGD_SPEC(msg_it->logger, - "Trying to skip {} bits of padding: msg-it-addr={}, size={}", bits_to_skip, - fmt::ptr(msg_it), bits_to_skip); - status = buf_ensure_available_bits(msg_it); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - - bits_to_consume = MIN(buf_available_bits(msg_it), bits_to_skip); - BT_CPPLOGD_SPEC(msg_it->logger, "Skipping {} bits of padding: msg-it-addr={}, size={}", - bits_to_consume, fmt::ptr(msg_it), bits_to_consume); - buf_consume_bits(msg_it, bits_to_consume); - bits_to_skip = msg_it->cur_exp_packet_total_size - packet_at(msg_it); - if (bits_to_skip == 0) { - msg_it->state = next_state; - goto end; - } - } - -end: - return status; -} - -static enum ctf_msg_iter_status check_emit_msg_discarded_events(struct ctf_msg_iter *msg_it) -{ - msg_it->state = STATE_EMIT_MSG_DISCARDED_EVENTS; - - if (!msg_it->meta.sc->has_discarded_events) { - msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS; - goto end; - } - - if (msg_it->prev_packet_snapshots.discarded_events == UINT64_C(-1)) { - if (msg_it->snapshots.discarded_events == 0 || - msg_it->snapshots.discarded_events == UINT64_C(-1)) { - /* - * Stream's first packet with no discarded - * events or no information about discarded - * events: do not emit. - */ - msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS; - } - } else { - /* - * If the previous packet has a value for this counter, - * then this counter is defined for the whole stream. - */ - BT_ASSERT(msg_it->snapshots.discarded_events != UINT64_C(-1)); - - if (msg_it->snapshots.discarded_events - msg_it->prev_packet_snapshots.discarded_events == - 0) { - /* - * No discarded events since previous packet: do - * not emit. - */ - msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS; - } - } - -end: - return CTF_MSG_ITER_STATUS_OK; -} - -static enum ctf_msg_iter_status check_emit_msg_discarded_packets(struct ctf_msg_iter *msg_it) -{ - msg_it->state = STATE_EMIT_MSG_DISCARDED_PACKETS; - - if (!msg_it->meta.sc->has_discarded_packets) { - msg_it->state = STATE_EMIT_MSG_PACKET_BEGINNING; - goto end; - } - - if (msg_it->prev_packet_snapshots.packets == UINT64_C(-1)) { - /* - * Stream's first packet or no information about - * discarded packets: do not emit. In other words, if - * this is the first packet and its sequence number is - * not 0, do not consider that packets were previously - * lost: we might be reading a partial stream (LTTng - * snapshot for example). - */ - msg_it->state = STATE_EMIT_MSG_PACKET_BEGINNING; - } else { - /* - * If the previous packet has a value for this counter, - * then this counter is defined for the whole stream. - */ - BT_ASSERT(msg_it->snapshots.packets != UINT64_C(-1)); - - if (msg_it->snapshots.packets - msg_it->prev_packet_snapshots.packets <= 1) { - /* - * No discarded packets since previous packet: - * do not emit. - */ - msg_it->state = STATE_EMIT_MSG_PACKET_BEGINNING; - } - } - -end: - return CTF_MSG_ITER_STATUS_OK; -} - -static inline enum state check_emit_msg_stream_end(struct ctf_msg_iter *msg_it) -{ - enum state next_state; - - if (msg_it->emit_stream_end_message) { - next_state = STATE_EMIT_MSG_STREAM_END; - } else { - next_state = STATE_DONE; - } - - return next_state; -} - -static inline enum ctf_msg_iter_status handle_state(struct ctf_msg_iter *msg_it) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - const enum state state = msg_it->state; - - BT_CPPLOGT_SPEC(msg_it->logger, "Handling state: msg-it-addr={}, state={}", fmt::ptr(msg_it), - state); - - // TODO: optimalize! - switch (state) { - case STATE_INIT: - msg_it->state = STATE_SWITCH_PACKET; - break; - case STATE_SWITCH_PACKET: - status = switch_packet_state(msg_it); - break; - case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN: - status = read_packet_header_begin_state(msg_it); - break; - case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE: - status = read_packet_header_continue_state(msg_it); - break; - case STATE_AFTER_TRACE_PACKET_HEADER: - status = after_packet_header_state(msg_it); - break; - case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN: - status = read_packet_context_begin_state(msg_it); - break; - case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE: - status = read_packet_context_continue_state(msg_it); - break; - case STATE_AFTER_STREAM_PACKET_CONTEXT: - status = after_packet_context_state(msg_it); - break; - case STATE_EMIT_MSG_STREAM_BEGINNING: - msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS; - break; - case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS: - status = check_emit_msg_discarded_events(msg_it); - break; - case STATE_EMIT_MSG_DISCARDED_EVENTS: - msg_it->state = STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS; - break; - case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS: - status = check_emit_msg_discarded_packets(msg_it); - break; - case STATE_EMIT_MSG_DISCARDED_PACKETS: - msg_it->state = STATE_EMIT_MSG_PACKET_BEGINNING; - break; - case STATE_EMIT_MSG_PACKET_BEGINNING: - msg_it->state = STATE_DSCOPE_EVENT_HEADER_BEGIN; - break; - case STATE_DSCOPE_EVENT_HEADER_BEGIN: - status = read_event_header_begin_state(msg_it); - break; - case STATE_DSCOPE_EVENT_HEADER_CONTINUE: - status = read_event_header_continue_state(msg_it); - break; - case STATE_AFTER_EVENT_HEADER: - status = after_event_header_state(msg_it); - break; - case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN: - status = read_event_common_context_begin_state(msg_it); - break; - case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE: - status = read_event_common_context_continue_state(msg_it); - break; - case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN: - status = read_event_spec_context_begin_state(msg_it); - break; - case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE: - status = read_event_spec_context_continue_state(msg_it); - break; - case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN: - status = read_event_payload_begin_state(msg_it); - break; - case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE: - status = read_event_payload_continue_state(msg_it); - break; - case STATE_EMIT_MSG_EVENT: - msg_it->state = STATE_DSCOPE_EVENT_HEADER_BEGIN; - break; - case STATE_EMIT_QUEUED_MSG_EVENT: - msg_it->state = STATE_EMIT_MSG_EVENT; - break; - case STATE_SKIP_PACKET_PADDING: - status = skip_packet_padding_state(msg_it); - break; - case STATE_EMIT_MSG_PACKET_END_MULTI: - msg_it->state = STATE_SKIP_PACKET_PADDING; - break; - case STATE_EMIT_MSG_PACKET_END_SINGLE: - msg_it->state = STATE_EMIT_MSG_STREAM_END; - break; - case STATE_EMIT_QUEUED_MSG_PACKET_END: - msg_it->state = STATE_EMIT_MSG_PACKET_END_SINGLE; - break; - case STATE_CHECK_EMIT_MSG_STREAM_END: - msg_it->state = check_emit_msg_stream_end(msg_it); - break; - case STATE_EMIT_MSG_STREAM_END: - msg_it->state = STATE_DONE; - break; - case STATE_DONE: - break; - default: - BT_CPPLOGF_SPEC(msg_it->logger, - "Unknown CTF plugin message iterator state: " - "msg-it-addr={}, state={}", - fmt::ptr(msg_it), msg_it->state); - bt_common_abort(); - } - - BT_CPPLOGT_SPEC(msg_it->logger, - "Handled state: msg-it-addr={}, status={}, " - "prev-state={}, cur-state={}", - fmt::ptr(msg_it), status, state, msg_it->state); - return status; -} - -void ctf_msg_iter_reset_for_next_stream_file(struct ctf_msg_iter *msg_it) -{ - BT_ASSERT(msg_it); - BT_CPPLOGD_SPEC(msg_it->logger, "Resetting message iterator: addr={}", fmt::ptr(msg_it)); - stack_clear(msg_it->stack); - msg_it->meta.sc = NULL; - msg_it->meta.ec = NULL; - BT_PACKET_PUT_REF_AND_RESET(msg_it->packet); - BT_STREAM_PUT_REF_AND_RESET(msg_it->stream); - BT_MESSAGE_PUT_REF_AND_RESET(msg_it->event_msg); - release_all_dscopes(msg_it); - msg_it->cur_dscope_field = NULL; - - msg_it->buf.addr = NULL; - msg_it->buf.sz = 0; - msg_it->buf.at = 0; - msg_it->buf.last_eh_at = SIZE_MAX; - msg_it->buf.packet_offset = 0; - msg_it->state = STATE_INIT; - msg_it->cur_exp_packet_content_size = -1; - msg_it->cur_exp_packet_total_size = -1; - msg_it->cur_packet_offset = -1; - msg_it->cur_event_class_id = -1; - msg_it->snapshots.beginning_clock = UINT64_C(-1); - msg_it->snapshots.end_clock = UINT64_C(-1); -} - -/** - * Resets the internal state of a CTF message iterator. - */ -void ctf_msg_iter_reset(struct ctf_msg_iter *msg_it) -{ - ctf_msg_iter_reset_for_next_stream_file(msg_it); - msg_it->cur_stream_class_id = -1; - msg_it->cur_data_stream_id = -1; - msg_it->snapshots.discarded_events = UINT64_C(-1); - msg_it->snapshots.packets = UINT64_C(-1); - msg_it->prev_packet_snapshots.discarded_events = UINT64_C(-1); - msg_it->prev_packet_snapshots.packets = UINT64_C(-1); - msg_it->prev_packet_snapshots.beginning_clock = UINT64_C(-1); - msg_it->prev_packet_snapshots.end_clock = UINT64_C(-1); - msg_it->emit_stream_beginning_message = true; - msg_it->emit_stream_end_message = false; -} - -static bt_field *borrow_next_field(struct ctf_msg_iter *msg_it) -{ - bt_field *next_field = NULL; - bt_field *base_field; - const bt_field_class *base_fc; - bt_field_class_type base_fc_type; - size_t index; - - BT_ASSERT_DBG(!stack_empty(msg_it->stack)); - index = stack_top(msg_it->stack)->index; - base_field = stack_top(msg_it->stack)->base; - BT_ASSERT_DBG(base_field); - base_fc = bt_field_borrow_class_const(base_field); - BT_ASSERT_DBG(base_fc); - base_fc_type = bt_field_class_get_type(base_fc); - - if (base_fc_type == BT_FIELD_CLASS_TYPE_STRUCTURE) { - BT_ASSERT_DBG(index < bt_field_class_structure_get_member_count( - bt_field_borrow_class_const(base_field))); - next_field = bt_field_structure_borrow_member_field_by_index(base_field, index); - } else if (bt_field_class_type_is(base_fc_type, BT_FIELD_CLASS_TYPE_ARRAY)) { - BT_ASSERT_DBG(index < bt_field_array_get_length(base_field)); - next_field = bt_field_array_borrow_element_field_by_index(base_field, index); - } else if (bt_field_class_type_is(base_fc_type, BT_FIELD_CLASS_TYPE_VARIANT)) { - BT_ASSERT_DBG(index == 0); - next_field = bt_field_variant_borrow_selected_option_field(base_field); - } else { - bt_common_abort(); - } - - BT_ASSERT_DBG(next_field); - return next_field; -} - -static void update_default_clock(struct ctf_msg_iter *msg_it, uint64_t new_val, - uint64_t new_val_size) -{ - uint64_t new_val_mask; - uint64_t cur_value_masked; - - BT_ASSERT_DBG(new_val_size > 0); - - /* - * Special case for a 64-bit new value, which is the limit - * of a clock value as of this version: overwrite the - * current value directly. - */ - if (new_val_size == 64) { - msg_it->default_clock_snapshot = new_val; - goto end; - } - - new_val_mask = (1ULL << new_val_size) - 1; - cur_value_masked = msg_it->default_clock_snapshot & new_val_mask; - - if (new_val < cur_value_masked) { - /* - * It looks like a wrap happened on the number of bits - * of the requested new value. Assume that the clock - * value wrapped only one time. - */ - msg_it->default_clock_snapshot += new_val_mask + 1; - } - - /* Clear the low bits of the current clock value. */ - msg_it->default_clock_snapshot &= ~new_val_mask; - - /* Set the low bits of the current clock value. */ - msg_it->default_clock_snapshot |= new_val; - -end: - BT_CPPLOGT_SPEC(msg_it->logger, - "Updated default clock's value from integer field's value: " - "value={}", - msg_it->default_clock_snapshot); -} - -/* - * Ensure the message iterator's `stored_values` array is large enough to - * accommodate `storing_index`. - * - * We may need more slots in the array than initially allocated if more - * metadata arrives along the way. - */ -static void ensure_stored_values_size(ctf_msg_iter *msg_it, uint64_t storing_index) -{ - if (G_UNLIKELY(storing_index >= msg_it->stored_values->len)) { - g_array_set_size(msg_it->stored_values, msg_it->meta.tc->stored_value_count); - } -} - -static enum bt_bfcr_status bfcr_unsigned_int_cb(uint64_t value, struct ctf_field_class *fc, - void *data) -{ - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - - bt_field *field = NULL; - - BT_CPPLOGT_SPEC(msg_it->logger, - "Unsigned integer function called from BFCR: " - "msg-it-addr={}, bfcr-addr={}, fc-addr={}, " - "fc-type={}, fc-in-ir={}, value={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir, - value); - - ctf_field_class_int *int_fc = ctf_field_class_as_int(fc); - - if (G_LIKELY(int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE)) { - goto update_def_clock; - } - - switch (int_fc->meaning) { - case CTF_FIELD_CLASS_MEANING_EVENT_CLASS_ID: - msg_it->cur_event_class_id = value; - break; - case CTF_FIELD_CLASS_MEANING_DATA_STREAM_ID: - msg_it->cur_data_stream_id = value; - break; - case CTF_FIELD_CLASS_MEANING_PACKET_BEGINNING_TIME: - msg_it->snapshots.beginning_clock = value; - break; - case CTF_FIELD_CLASS_MEANING_PACKET_END_TIME: - msg_it->snapshots.end_clock = value; - break; - case CTF_FIELD_CLASS_MEANING_STREAM_CLASS_ID: - msg_it->cur_stream_class_id = value; - break; - case CTF_FIELD_CLASS_MEANING_MAGIC: - if (value != 0xc1fc1fc1) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Invalid CTF magic number: msg-it-addr={}, magic={}", - fmt::ptr(msg_it), value); - status = BT_BFCR_STATUS_ERROR; - goto end; - } - - break; - case CTF_FIELD_CLASS_MEANING_PACKET_COUNTER_SNAPSHOT: - msg_it->snapshots.packets = value; - break; - case CTF_FIELD_CLASS_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT: - msg_it->snapshots.discarded_events = value; - break; - case CTF_FIELD_CLASS_MEANING_EXP_PACKET_TOTAL_SIZE: - msg_it->cur_exp_packet_total_size = value; - break; - case CTF_FIELD_CLASS_MEANING_EXP_PACKET_CONTENT_SIZE: - msg_it->cur_exp_packet_content_size = value; - break; - default: - bt_common_abort(); - } - -update_def_clock: - if (G_UNLIKELY(int_fc->mapped_clock_class)) { - update_default_clock(msg_it, value, int_fc->base.size); - } - - if (G_UNLIKELY(int_fc->storing_index >= 0)) { - ensure_stored_values_size(msg_it, int_fc->storing_index); - bt_g_array_index(msg_it->stored_values, uint64_t, (uint64_t) int_fc->storing_index) = value; - } - - if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) { - goto end; - } - - field = borrow_next_field(msg_it); - BT_ASSERT_DBG(field); - BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc); - BT_ASSERT_DBG(bt_field_class_type_is(bt_field_get_class_type(field), - BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER)); - bt_field_integer_unsigned_set_value(field, value); - stack_top(msg_it->stack)->index++; - -end: - return status; -} - -static enum bt_bfcr_status bfcr_unsigned_int_char_cb(uint64_t value, struct ctf_field_class *fc, - void *data) -{ - int ret; - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - bt_field *string_field = NULL; - char str[2] = {'\0', '\0'}; - - BT_CPPLOGT_SPEC(msg_it->logger, - "Unsigned integer character function called from BFCR: " - "msg-it-addr={}, bfcr-addr={}, fc-addr={}, " - "fc-type={}, fc-in-ir={}, value={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir, - value); - - ctf_field_class_int *int_fc = ctf_field_class_as_int(fc); - BT_ASSERT_DBG(int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE); - BT_ASSERT_DBG(!int_fc->mapped_clock_class); - BT_ASSERT_DBG(int_fc->storing_index < 0); - - if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) { - goto end; - } - - if (msg_it->done_filling_string) { - goto end; - } - - if (value == 0) { - msg_it->done_filling_string = true; - goto end; - } - - string_field = stack_top(msg_it->stack)->base; - BT_ASSERT_DBG(bt_field_get_class_type(string_field) == BT_FIELD_CLASS_TYPE_STRING); - - /* Append character */ - str[0] = (char) value; - ret = bt_field_string_append_with_length(string_field, str, 1); - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot append character to string field's value: " - "msg-it-addr={}, field-addr={}, ret={}", - fmt::ptr(msg_it), fmt::ptr(string_field), ret); - status = BT_BFCR_STATUS_ERROR; - goto end; - } - -end: - return status; -} - -static enum bt_bfcr_status bfcr_signed_int_cb(int64_t value, struct ctf_field_class *fc, void *data) -{ - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - bt_field *field = NULL; - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - - BT_CPPLOGT_SPEC(msg_it->logger, - "Signed integer function called from BFCR: " - "msg-it-addr={}, bfcr-addr={}, fc-addr={}, " - "fc-type={}, fc-in-ir={}, value={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir, - value); - - ctf_field_class_int *int_fc = ctf_field_class_as_int(fc); - BT_ASSERT_DBG(int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE); - - if (G_UNLIKELY(int_fc->storing_index >= 0)) { - ensure_stored_values_size(msg_it, int_fc->storing_index); - bt_g_array_index(msg_it->stored_values, uint64_t, (uint64_t) int_fc->storing_index) = - (uint64_t) value; - } - - if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) { - goto end; - } - - field = borrow_next_field(msg_it); - BT_ASSERT_DBG(field); - BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc); - BT_ASSERT_DBG( - bt_field_class_type_is(bt_field_get_class_type(field), BT_FIELD_CLASS_TYPE_SIGNED_INTEGER)); - bt_field_integer_signed_set_value(field, value); - stack_top(msg_it->stack)->index++; - -end: - return status; -} - -static enum bt_bfcr_status bfcr_floating_point_cb(double value, struct ctf_field_class *fc, - void *data) -{ - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - bt_field *field = NULL; - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - bt_field_class_type type; - - BT_CPPLOGT_SPEC(msg_it->logger, - "Floating point number function called from BFCR: " - "msg-it-addr={}, bfcr-addr={}, fc-addr={}, " - "fc-type={}, fc-in-ir={}, value={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir, - value); - - if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) { - goto end; - } - - field = borrow_next_field(msg_it); - type = bt_field_get_class_type(field); - BT_ASSERT_DBG(field); - BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc); - BT_ASSERT_DBG(bt_field_class_type_is(type, BT_FIELD_CLASS_TYPE_REAL)); - - if (type == BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL) { - bt_field_real_single_precision_set_value(field, (float) value); - } else { - bt_field_real_double_precision_set_value(field, value); - } - stack_top(msg_it->stack)->index++; - -end: - return status; -} - -static enum bt_bfcr_status bfcr_string_begin_cb(struct ctf_field_class *fc, void *data) -{ - bt_field *field = NULL; - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - - BT_CPPLOGT_SPEC(msg_it->logger, - "String (beginning) function called from BFCR: " - "msg-it-addr={}, bfcr-addr={}, fc-addr={}, " - "fc-type={}, fc-in-ir={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir); - - if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) { - goto end; - } - - field = borrow_next_field(msg_it); - BT_ASSERT_DBG(field); - BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc); - BT_ASSERT_DBG(bt_field_get_class_type(field) == BT_FIELD_CLASS_TYPE_STRING); - bt_field_string_clear(field); - - /* - * Push on stack. Not a compound class per se, but we know that - * only bfcr_string_cb() may be called between this call and a - * subsequent call to bfcr_string_end_cb(). - */ - stack_push(msg_it->stack, field); - -end: - return BT_BFCR_STATUS_OK; -} - -static enum bt_bfcr_status bfcr_string_cb(const char *value, size_t len, struct ctf_field_class *fc, - void *data) -{ - enum bt_bfcr_status status = BT_BFCR_STATUS_OK; - bt_field *field = NULL; - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - int ret; - - BT_CPPLOGT_SPEC(msg_it->logger, - "String (substring) function called from BFCR: " - "msg-it-addr={}, bfcr-addr={}, fc-addr={}, " - "fc-type={}, fc-in-ir={}, string-length={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir, - len); - - if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) { - goto end; - } - - field = stack_top(msg_it->stack)->base; - BT_ASSERT_DBG(field); - - /* Append current substring */ - ret = bt_field_string_append_with_length(field, value, len); - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot append substring to string field's value: " - "msg-it-addr={}, field-addr={}, string-length={}, " - "ret={}", - fmt::ptr(msg_it), fmt::ptr(field), len, ret); - status = BT_BFCR_STATUS_ERROR; - goto end; - } - -end: - return status; -} - -static enum bt_bfcr_status bfcr_string_end_cb(struct ctf_field_class *fc, void *data) -{ - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - - BT_CPPLOGT_SPEC(msg_it->logger, - "String (end) function called from BFCR: " - "msg-it-addr={}, bfcr-addr={}, fc-addr={}, " - "fc-type={}, fc-in-ir={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir); - - if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) { - goto end; - } - - /* Pop string field */ - stack_pop(msg_it->stack); - - /* Go to next field */ - stack_top(msg_it->stack)->index++; - -end: - return BT_BFCR_STATUS_OK; -} - -static enum bt_bfcr_status bfcr_compound_begin_cb(struct ctf_field_class *fc, void *data) -{ - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - bt_field *field; - - BT_CPPLOGT_SPEC(msg_it->logger, - "Compound (beginning) function called from BFCR: " - "msg-it-addr={}, bfcr-addr={}, fc-addr={}, " - "fc-type={}, fc-in-ir={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir); - - if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) { - goto end; - } - - /* Borrow field */ - if (stack_empty(msg_it->stack)) { - /* Root: already set by read_dscope_begin_state() */ - field = msg_it->cur_dscope_field; - } else { - field = borrow_next_field(msg_it); - BT_ASSERT_DBG(field); - } - - /* Push field */ - BT_ASSERT_DBG(field); - BT_ASSERT_DBG(bt_field_borrow_class_const(field) == fc->ir_fc); - stack_push(msg_it->stack, field); - - /* - * Change BFCR "unsigned int" callback if it's a text - * array/sequence. - */ - if (fc->type == CTF_FIELD_CLASS_TYPE_ARRAY || fc->type == CTF_FIELD_CLASS_TYPE_SEQUENCE) { - ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(fc); - - if (array_fc->is_text) { - BT_ASSERT_DBG(bt_field_get_class_type(field) == BT_FIELD_CLASS_TYPE_STRING); - msg_it->done_filling_string = false; - bt_field_string_clear(field); - bt_bfcr_set_unsigned_int_cb(msg_it->bfcr, bfcr_unsigned_int_char_cb); - } - } - -end: - return BT_BFCR_STATUS_OK; -} - -static enum bt_bfcr_status bfcr_compound_end_cb(struct ctf_field_class *fc, void *data) -{ - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - - BT_CPPLOGT_SPEC(msg_it->logger, - "Compound (end) function called from BFCR: " - "msg-it-addr={}, bfcr-addr={}, fc-addr={}, " - "fc-type={}, fc-in-ir={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->bfcr), fmt::ptr(fc), fc->type, fc->in_ir); - - if (G_UNLIKELY(!fc->in_ir || msg_it->dry_run)) { - goto end; - } - - BT_ASSERT_DBG(!stack_empty(msg_it->stack)); - BT_ASSERT_DBG(bt_field_borrow_class_const(stack_top(msg_it->stack)->base) == fc->ir_fc); - - /* - * Reset BFCR "unsigned int" callback if it's a text - * array/sequence. - */ - if (fc->type == CTF_FIELD_CLASS_TYPE_ARRAY || fc->type == CTF_FIELD_CLASS_TYPE_SEQUENCE) { - ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(fc); - - if (array_fc->is_text) { - BT_ASSERT_DBG(bt_field_get_class_type(stack_top(msg_it->stack)->base) == - BT_FIELD_CLASS_TYPE_STRING); - bt_bfcr_set_unsigned_int_cb(msg_it->bfcr, bfcr_unsigned_int_cb); - } - } - - /* Pop stack */ - stack_pop(msg_it->stack); - - /* If the stack is not empty, increment the base's index */ - if (!stack_empty(msg_it->stack)) { - stack_top(msg_it->stack)->index++; - } - -end: - return BT_BFCR_STATUS_OK; -} - -static int64_t bfcr_get_sequence_length_cb(struct ctf_field_class *fc, void *data) -{ - bt_field *seq_field; - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - struct ctf_field_class_sequence *seq_fc = ctf_field_class_as_sequence(fc); - int64_t length; - int ret; - - length = - (uint64_t) bt_g_array_index(msg_it->stored_values, uint64_t, seq_fc->stored_length_index); - - if (G_UNLIKELY(msg_it->dry_run)) { - goto end; - } - - seq_field = stack_top(msg_it->stack)->base; - BT_ASSERT_DBG(seq_field); - - /* - * bfcr_get_sequence_length_cb() also gets called back for a - * text sequence, but the destination field is a string field. - * Only set the field's sequence length if the destination field - * is a sequence field. - */ - if (!seq_fc->base.is_text) { - BT_ASSERT_DBG(bt_field_class_type_is(bt_field_get_class_type(seq_field), - BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY)); - ret = bt_field_array_dynamic_set_length(seq_field, (uint64_t) length); - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot set dynamic array field's length field: " - "msg-it-addr={}, field-addr={}, " - "length={}", - fmt::ptr(msg_it), fmt::ptr(seq_field), length); - length = -1; - } - } - -end: - return length; -} - -static struct ctf_field_class * -bfcr_borrow_variant_selected_field_class_cb(struct ctf_field_class *fc, void *data) -{ - int ret; - uint64_t i; - int64_t option_index = -1; - ctf_msg_iter *msg_it = (ctf_msg_iter *) data; - ctf_field_class_variant *var_fc = ctf_field_class_as_variant(fc); - struct ctf_named_field_class *selected_option = NULL; - struct ctf_field_class *ret_fc = NULL; - union - { - uint64_t u; - int64_t i; - } tag; - - /* Get variant's tag */ - tag.u = bt_g_array_index(msg_it->stored_values, uint64_t, var_fc->stored_tag_index); - - /* - * Check each range to find the selected option's index. - */ - if (var_fc->tag_fc->base.is_signed) { - for (i = 0; i < var_fc->ranges->len; i++) { - struct ctf_field_class_variant_range *range = - ctf_field_class_variant_borrow_range_by_index(var_fc, i); - - if (tag.i >= range->range.lower.i && tag.i <= range->range.upper.i) { - option_index = (int64_t) range->option_index; - break; - } - } - } else { - for (i = 0; i < var_fc->ranges->len; i++) { - struct ctf_field_class_variant_range *range = - ctf_field_class_variant_borrow_range_by_index(var_fc, i); - - if (tag.u >= range->range.lower.u && tag.u <= range->range.upper.u) { - option_index = (int64_t) range->option_index; - break; - } - } - } - - if (option_index < 0) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot find variant field class's option: " - "msg-it-addr={}, var-fc-addr={}, u-tag={}, " - "i-tag={}", - fmt::ptr(msg_it), fmt::ptr(var_fc), tag.u, tag.i); - ret_fc = NULL; - goto end; - } - - selected_option = - ctf_field_class_variant_borrow_option_by_index(var_fc, (uint64_t) option_index); - - if (selected_option->fc->in_ir && !msg_it->dry_run) { - bt_field *var_field = stack_top(msg_it->stack)->base; - - ret = bt_field_variant_select_option_by_index(var_field, option_index); - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot select variant field's option field: " - "msg-it-addr={}, var-field-addr={}, " - "opt-index={}", - fmt::ptr(msg_it), fmt::ptr(var_field), option_index); - ret_fc = NULL; - goto end; - } - } - - ret_fc = selected_option->fc; - -end: - return ret_fc; -} - -static bt_message *create_msg_stream_beginning(struct ctf_msg_iter *msg_it) -{ - bt_message *msg; - - BT_ASSERT(msg_it->stream); - BT_ASSERT(msg_it->self_msg_iter); - msg = bt_message_stream_beginning_create(msg_it->self_msg_iter, msg_it->stream); - if (!msg) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot create stream beginning message: " - "msg-it-addr={}, stream-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->stream)); - } - - return msg; -} - -static bt_message *create_msg_stream_end(struct ctf_msg_iter *msg_it) -{ - bt_message *msg; - - if (!msg_it->stream) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot create stream end message because stream is NULL: " - "msg-it-addr={}", - fmt::ptr(msg_it)); - msg = NULL; - goto end; - } - - BT_ASSERT(msg_it->self_msg_iter); - msg = bt_message_stream_end_create(msg_it->self_msg_iter, msg_it->stream); - if (!msg) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot create stream end message: " - "msg-it-addr={}, stream-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->stream)); - } - -end: - return msg; -} - -static bt_message *create_msg_packet_beginning(struct ctf_msg_iter *msg_it, bool use_default_cs) -{ - bt_message *msg; - const bt_stream_class *sc = msg_it->meta.sc->ir_sc; - - BT_ASSERT(msg_it->packet); - BT_ASSERT(sc); - BT_ASSERT(msg_it->self_msg_iter); - - if (msg_it->meta.sc->packets_have_ts_begin) { - BT_ASSERT(msg_it->snapshots.beginning_clock != UINT64_C(-1)); - uint64_t raw_cs_value; - - /* - * Either use the decoded packet `timestamp_begin` field or the - * current stream's default clock_snapshot. - */ - if (use_default_cs) { - raw_cs_value = msg_it->default_clock_snapshot; - } else { - raw_cs_value = msg_it->snapshots.beginning_clock; - } - - msg = bt_message_packet_beginning_create_with_default_clock_snapshot( - msg_it->self_msg_iter, msg_it->packet, raw_cs_value); - } else { - msg = bt_message_packet_beginning_create(msg_it->self_msg_iter, msg_it->packet); - } - - if (!msg) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot create packet beginning message: " - "msg-it-addr={}, packet-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->packet)); - goto end; - } - -end: - return msg; -} - -static bt_message *emit_delayed_packet_beg_msg(struct ctf_msg_iter *msg_it) -{ - bool packet_beg_ts_need_fix_up; - - msg_it->emit_delayed_packet_beginning_msg = false; - - /* - * Only fix the packet's timestamp_begin if it's larger than the first - * event of the packet. If there was no event in the packet, the - * `default_clock_snapshot` field will be either equal or greater than - * `snapshots.beginning_clock` so there is not fix needed. - */ - packet_beg_ts_need_fix_up = msg_it->default_clock_snapshot < msg_it->snapshots.beginning_clock; - - /* create_msg_packet_beginning() logs errors */ - return create_msg_packet_beginning(msg_it, packet_beg_ts_need_fix_up); -} - -static bt_message *create_msg_packet_end(struct ctf_msg_iter *msg_it) -{ - bt_message *msg; - bool update_default_cs = true; - - if (!msg_it->packet) { - msg = NULL; - goto end; - } - - /* - * Check if we need to emit the delayed packet - * beginning message instead of the packet end message. - */ - if (G_UNLIKELY(msg_it->emit_delayed_packet_beginning_msg)) { - msg = emit_delayed_packet_beg_msg(msg_it); - /* Don't forget to emit the packet end message. */ - msg_it->state = STATE_EMIT_QUEUED_MSG_PACKET_END; - goto end; - } - - /* Check if may be affected by lttng-crash timestamp_end quirk. */ - if (G_UNLIKELY(msg_it->meta.tc->quirks.lttng_crash)) { - /* - * Check if the `timestamp_begin` field is non-zero but - * `timestamp_end` is zero. It means the trace is affected by - * the lttng-crash packet `timestamp_end` quirk and must be - * fixed up by omitting to update the default clock snapshot to - * the `timestamp_end` as is typically done. - */ - if (msg_it->snapshots.beginning_clock != 0 && msg_it->snapshots.end_clock == 0) { - update_default_cs = false; - } - } - - /* - * Check if may be affected by lttng event-after-packet `timestamp_end` - * quirk. - */ - if (msg_it->meta.tc->quirks.lttng_event_after_packet) { - /* - * Check if `timestamp_end` is smaller then the current - * default_clock_snapshot (which is set to the last event - * decoded). It means the trace is affected by the lttng - * `event-after-packet` packet `timestamp_end` quirk and must - * be fixed up by omitting to update the default clock snapshot - * to the `timestamp_end` as is typically done. - */ - if (msg_it->snapshots.end_clock < msg_it->default_clock_snapshot) { - update_default_cs = false; - } - } - - /* Update default clock from packet's end time. */ - if (msg_it->snapshots.end_clock != UINT64_C(-1) && update_default_cs) { - msg_it->default_clock_snapshot = msg_it->snapshots.end_clock; - } - - BT_ASSERT(msg_it->self_msg_iter); - - if (msg_it->meta.sc->packets_have_ts_end) { - BT_ASSERT(msg_it->snapshots.end_clock != UINT64_C(-1)); - msg = bt_message_packet_end_create_with_default_clock_snapshot( - msg_it->self_msg_iter, msg_it->packet, msg_it->default_clock_snapshot); - } else { - msg = bt_message_packet_end_create(msg_it->self_msg_iter, msg_it->packet); - } - - if (!msg) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot create packet end message: " - "msg-it-addr={}, packet-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->packet)); - goto end; - } - - BT_PACKET_PUT_REF_AND_RESET(msg_it->packet); - -end: - return msg; -} - -static bt_message *create_msg_discarded_events(struct ctf_msg_iter *msg_it) -{ - bt_message *msg; - uint64_t beginning_raw_value = UINT64_C(-1); - uint64_t end_raw_value = UINT64_C(-1); - - BT_ASSERT(msg_it->self_msg_iter); - BT_ASSERT(msg_it->stream); - BT_ASSERT(msg_it->meta.sc->has_discarded_events); - - if (msg_it->meta.sc->discarded_events_have_default_cs) { - if (msg_it->prev_packet_snapshots.discarded_events == UINT64_C(-1)) { - /* - * We discarded events, but before (and possibly - * including) the current packet: use this packet's time - * range, and do not have a specific count. - */ - beginning_raw_value = msg_it->snapshots.beginning_clock; - end_raw_value = msg_it->snapshots.end_clock; - } else { - beginning_raw_value = msg_it->prev_packet_snapshots.end_clock; - end_raw_value = msg_it->snapshots.end_clock; - } - - BT_ASSERT(beginning_raw_value != UINT64_C(-1)); - BT_ASSERT(end_raw_value != UINT64_C(-1)); - msg = bt_message_discarded_events_create_with_default_clock_snapshots( - msg_it->self_msg_iter, msg_it->stream, beginning_raw_value, end_raw_value); - } else { - msg = bt_message_discarded_events_create(msg_it->self_msg_iter, msg_it->stream); - } - - if (!msg) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot create discarded events message: " - "msg-it-addr={}, stream-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->stream)); - goto end; - } - - if (msg_it->prev_packet_snapshots.discarded_events != UINT64_C(-1)) { - bt_message_discarded_events_set_count(msg, - msg_it->snapshots.discarded_events - - msg_it->prev_packet_snapshots.discarded_events); - } - -end: - return msg; -} - -static bt_message *create_msg_discarded_packets(struct ctf_msg_iter *msg_it) -{ - bt_message *msg; - - BT_ASSERT(msg_it->self_msg_iter); - BT_ASSERT(msg_it->stream); - BT_ASSERT(msg_it->meta.sc->has_discarded_packets); - BT_ASSERT(msg_it->prev_packet_snapshots.packets != UINT64_C(-1)); - - if (msg_it->meta.sc->discarded_packets_have_default_cs) { - BT_ASSERT(msg_it->prev_packet_snapshots.end_clock != UINT64_C(-1)); - BT_ASSERT(msg_it->snapshots.beginning_clock != UINT64_C(-1)); - msg = bt_message_discarded_packets_create_with_default_clock_snapshots( - msg_it->self_msg_iter, msg_it->stream, msg_it->prev_packet_snapshots.end_clock, - msg_it->snapshots.beginning_clock); - } else { - msg = bt_message_discarded_packets_create(msg_it->self_msg_iter, msg_it->stream); - } - - if (!msg) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot create discarded packets message: " - "msg-it-addr={}, stream-addr={}", - fmt::ptr(msg_it), fmt::ptr(msg_it->stream)); - goto end; - } - - bt_message_discarded_packets_set_count(msg, msg_it->snapshots.packets - - msg_it->prev_packet_snapshots.packets - 1); - -end: - return msg; -} - -ctf_msg_iter_up ctf_msg_iter_create(struct ctf_trace_class *tc, size_t max_request_sz, - struct ctf_msg_iter_medium_ops medops, void *data, - bt_self_message_iterator *self_msg_iter, - const bt2c::Logger& parentLogger) -{ - struct bt_bfcr_cbs cbs = { - .classes = - { - .signed_int = bfcr_signed_int_cb, - .unsigned_int = bfcr_unsigned_int_cb, - .floating_point = bfcr_floating_point_cb, - .string_begin = bfcr_string_begin_cb, - .string = bfcr_string_cb, - .string_end = bfcr_string_end_cb, - .compound_begin = bfcr_compound_begin_cb, - .compound_end = bfcr_compound_end_cb, - }, - .query = - { - .get_sequence_length = bfcr_get_sequence_length_cb, - .borrow_variant_selected_field_class = bfcr_borrow_variant_selected_field_class_cb, - }, - }; - - BT_ASSERT(tc); - BT_ASSERT(medops.request_bytes); - BT_ASSERT(medops.borrow_stream); - BT_ASSERT(max_request_sz > 0); - - bt2c::Logger logger {parentLogger, "PLUGIN/CTF/MSG-ITER"}; - BT_CPPLOGD_SPEC(logger, - "Creating CTF plugin message iterator: " - "trace-addr={}, max-request-size={}, " - "data={}, log-level={}", - fmt::ptr(tc), max_request_sz, fmt::ptr(data), logger.level()); - - ctf_msg_iter_up msg_it {new ctf_msg_iter {std::move(logger)}}; - msg_it->self_msg_iter = self_msg_iter; - msg_it->meta.tc = tc; - msg_it->medium.medops = medops; - msg_it->medium.max_request_sz = max_request_sz; - msg_it->medium.data = data; - msg_it->stack = stack_new(msg_it.get()); - msg_it->stored_values = g_array_new(FALSE, TRUE, sizeof(uint64_t)); - g_array_set_size(msg_it->stored_values, tc->stored_value_count); - - if (!msg_it->stack) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, "Failed to create field stack."); - goto error; - } - - msg_it->bfcr = bt_bfcr_create(cbs, msg_it.get(), msg_it->logger); - if (!msg_it->bfcr) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Failed to create binary class reader (BFCR)."); - goto error; - } - - ctf_msg_iter_reset(msg_it.get()); - BT_CPPLOGD_SPEC(msg_it->logger, - "Created CTF plugin message iterator: " - "trace-addr={}, max-request-size={}, " - "data={}, msg-it-addr={}, log-level={}", - fmt::ptr(tc), max_request_sz, fmt::ptr(data), fmt::ptr(msg_it), - msg_it->logger.level()); - msg_it->cur_packet_offset = 0; - -end: - return msg_it; - -error: - msg_it.reset(); - goto end; -} - -void ctf_msg_iter_destroy(struct ctf_msg_iter *msg_it) -{ - BT_PACKET_PUT_REF_AND_RESET(msg_it->packet); - BT_STREAM_PUT_REF_AND_RESET(msg_it->stream); - release_all_dscopes(msg_it); - - BT_CPPLOGD_SPEC(msg_it->logger, "Destroying CTF plugin message iterator: addr={}", - fmt::ptr(msg_it)); - - if (msg_it->stack) { - BT_CPPLOGD_SPEC(msg_it->logger, "Destroying field stack."); - stack_destroy(msg_it->stack); - } - - if (msg_it->bfcr) { - BT_CPPLOGD_SPEC(msg_it->logger, "Destroying BFCR: bfcr-addr={}", fmt::ptr(msg_it->bfcr)); - bt_bfcr_destroy(msg_it->bfcr); - } - - if (msg_it->stored_values) { - g_array_free(msg_it->stored_values, TRUE); - } - - delete msg_it; -} - -void ctf_msg_iter_deleter::operator()(ctf_msg_iter *iter) noexcept -{ - ctf_msg_iter_destroy(iter); -} - -enum ctf_msg_iter_status ctf_msg_iter_get_next_message(struct ctf_msg_iter *msg_it, - const bt_message **message) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - - BT_ASSERT_DBG(msg_it); - BT_ASSERT_DBG(message); - BT_CPPLOGD_SPEC(msg_it->logger, "Getting next message: msg-it-addr={}", fmt::ptr(msg_it)); - - while (true) { - status = handle_state(msg_it); - if (G_UNLIKELY(status == CTF_MSG_ITER_STATUS_AGAIN)) { - BT_CPPLOGD_SPEC(msg_it->logger, "Medium returned CTF_MSG_ITER_STATUS_AGAIN."); - goto end; - } else if (G_UNLIKELY(status != CTF_MSG_ITER_STATUS_OK)) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot handle state: msg-it-addr={}, state={}", - fmt::ptr(msg_it), msg_it->state); - goto end; - } - - switch (msg_it->state) { - case STATE_EMIT_MSG_EVENT: - BT_ASSERT_DBG(msg_it->event_msg); - - /* - * Check if we need to emit the delayed packet - * beginning message instead of the event message. - */ - if (G_UNLIKELY(msg_it->emit_delayed_packet_beginning_msg)) { - *message = emit_delayed_packet_beg_msg(msg_it); - if (!*message) { - status = CTF_MSG_ITER_STATUS_ERROR; - } - - /* - * Don't forget to emit the event message of - * the event record that was just decoded. - */ - msg_it->state = STATE_EMIT_QUEUED_MSG_EVENT; - - } else { - *message = msg_it->event_msg; - msg_it->event_msg = NULL; - } - goto end; - case STATE_EMIT_MSG_DISCARDED_EVENTS: - /* create_msg_discarded_events() logs errors */ - *message = create_msg_discarded_events(msg_it); - - if (!*message) { - status = CTF_MSG_ITER_STATUS_ERROR; - } - - goto end; - case STATE_EMIT_MSG_DISCARDED_PACKETS: - /* create_msg_discarded_packets() logs errors */ - *message = create_msg_discarded_packets(msg_it); - - if (!*message) { - status = CTF_MSG_ITER_STATUS_ERROR; - } - - goto end; - case STATE_EMIT_MSG_PACKET_BEGINNING: - if (G_UNLIKELY(msg_it->meta.tc->quirks.barectf_event_before_packet)) { - msg_it->emit_delayed_packet_beginning_msg = true; - /* - * There is no message to return yet as this - * packet beginning message is delayed until we - * decode the first event message of the - * packet. - */ - break; - } else { - /* create_msg_packet_beginning() logs errors */ - *message = create_msg_packet_beginning(msg_it, false); - if (!*message) { - status = CTF_MSG_ITER_STATUS_ERROR; - } - } - - goto end; - case STATE_EMIT_MSG_PACKET_END_SINGLE: - case STATE_EMIT_MSG_PACKET_END_MULTI: - /* create_msg_packet_end() logs errors */ - *message = create_msg_packet_end(msg_it); - - if (!*message) { - status = CTF_MSG_ITER_STATUS_ERROR; - } - - goto end; - case STATE_EMIT_MSG_STREAM_BEGINNING: - /* create_msg_stream_beginning() logs errors */ - *message = create_msg_stream_beginning(msg_it); - msg_it->emit_stream_beginning_message = false; - msg_it->emit_stream_end_message = true; - - if (!*message) { - status = CTF_MSG_ITER_STATUS_ERROR; - } - - goto end; - case STATE_EMIT_MSG_STREAM_END: - /* create_msg_stream_end() logs errors */ - *message = create_msg_stream_end(msg_it); - msg_it->emit_stream_end_message = false; - - if (!*message) { - status = CTF_MSG_ITER_STATUS_ERROR; - } - - goto end; - case STATE_DONE: - status = CTF_MSG_ITER_STATUS_EOF; - goto end; - default: - /* Non-emitting state: continue */ - break; - } - } - -end: - return status; -} - -static enum ctf_msg_iter_status decode_until_state(struct ctf_msg_iter *msg_it, - enum state target_state_1, - enum state target_state_2) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - - BT_ASSERT_DBG(msg_it); - - do { - /* - * Check if we reached the state at which we want to stop - * decoding. - */ - if (msg_it->state == target_state_1 || msg_it->state == target_state_2) { - goto end; - } - - status = handle_state(msg_it); - if (G_UNLIKELY(status == CTF_MSG_ITER_STATUS_AGAIN)) { - BT_CPPLOGD_SPEC(msg_it->logger, "Medium returned CTF_MSG_ITER_STATUS_AGAIN."); - goto end; - } else if (G_UNLIKELY(status != CTF_MSG_ITER_STATUS_OK)) { - BT_CPPLOGE_APPEND_CAUSE_SPEC(msg_it->logger, - "Cannot handle state: msg-it-addr={}, state={}", - fmt::ptr(msg_it), msg_it->state); - goto end; - } - - switch (msg_it->state) { - case STATE_INIT: - case STATE_SWITCH_PACKET: - case STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN: - case STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE: - case STATE_AFTER_TRACE_PACKET_HEADER: - case STATE_DSCOPE_STREAM_PACKET_CONTEXT_BEGIN: - case STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE: - case STATE_AFTER_STREAM_PACKET_CONTEXT: - case STATE_EMIT_MSG_STREAM_BEGINNING: - case STATE_CHECK_EMIT_MSG_DISCARDED_EVENTS: - case STATE_EMIT_MSG_DISCARDED_EVENTS: - case STATE_CHECK_EMIT_MSG_DISCARDED_PACKETS: - case STATE_EMIT_MSG_DISCARDED_PACKETS: - case STATE_EMIT_MSG_PACKET_BEGINNING: - case STATE_DSCOPE_EVENT_HEADER_BEGIN: - case STATE_DSCOPE_EVENT_HEADER_CONTINUE: - case STATE_AFTER_EVENT_HEADER: - case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN: - case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE: - case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN: - case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE: - case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN: - case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE: - case STATE_EMIT_MSG_EVENT: - case STATE_EMIT_QUEUED_MSG_EVENT: - case STATE_SKIP_PACKET_PADDING: - case STATE_EMIT_MSG_PACKET_END_MULTI: - case STATE_EMIT_MSG_PACKET_END_SINGLE: - case STATE_EMIT_QUEUED_MSG_PACKET_END: - case STATE_EMIT_MSG_STREAM_END: - break; - case STATE_DONE: - /* fall-through */ - default: - /* We should never get to the STATE_DONE state. */ - BT_CPPLOGF_SPEC(msg_it->logger, "Unexpected state: msg-it-addr={}, state={}", - fmt::ptr(msg_it), msg_it->state); - bt_common_abort(); - } - } while (true); - -end: - return status; -} - -static enum ctf_msg_iter_status read_packet_header_context_fields(struct ctf_msg_iter *msg_it) -{ - int ret; - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - - status = decode_until_state(msg_it, STATE_EMIT_MSG_PACKET_BEGINNING, (state) -1); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - - ret = set_current_packet_content_sizes(msg_it); - if (ret) { - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - -end: - return status; -} - -enum ctf_msg_iter_status ctf_msg_iter_seek(struct ctf_msg_iter *msg_it, off_t offset) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - enum ctf_msg_iter_medium_status medium_status; - - BT_ASSERT(msg_it); - BT_ASSERT(offset >= 0); - BT_ASSERT(msg_it->medium.medops.seek); - - medium_status = msg_it->medium.medops.seek(offset, msg_it->medium.data); - if (medium_status != CTF_MSG_ITER_MEDIUM_STATUS_OK) { - if (medium_status == CTF_MSG_ITER_MEDIUM_STATUS_EOF) { - status = CTF_MSG_ITER_STATUS_EOF; - } else { - status = CTF_MSG_ITER_STATUS_ERROR; - goto end; - } - } - - ctf_msg_iter_reset(msg_it); - msg_it->cur_packet_offset = offset; - -end: - return status; -} - -static enum ctf_msg_iter_status clock_snapshot_at_msg_iter_state(struct ctf_msg_iter *msg_it, - enum state target_state_1, - enum state target_state_2, - uint64_t *clock_snapshot) -{ - enum ctf_msg_iter_status status = CTF_MSG_ITER_STATUS_OK; - - BT_ASSERT_DBG(msg_it); - BT_ASSERT_DBG(clock_snapshot); - status = decode_until_state(msg_it, target_state_1, target_state_2); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - - *clock_snapshot = msg_it->default_clock_snapshot; -end: - return status; -} - -enum ctf_msg_iter_status -ctf_msg_iter_curr_packet_first_event_clock_snapshot(struct ctf_msg_iter *msg_it, - uint64_t *first_clock_snapshot) -{ - return clock_snapshot_at_msg_iter_state(msg_it, STATE_AFTER_EVENT_HEADER, (state) -1, - first_clock_snapshot); -} - -enum ctf_msg_iter_status -ctf_msg_iter_curr_packet_last_event_clock_snapshot(struct ctf_msg_iter *msg_it, - uint64_t *last_clock_snapshot) -{ - return clock_snapshot_at_msg_iter_state(msg_it, STATE_EMIT_MSG_PACKET_END_SINGLE, - STATE_EMIT_MSG_PACKET_END_MULTI, last_clock_snapshot); -} - -enum ctf_msg_iter_status -ctf_msg_iter_get_packet_properties(struct ctf_msg_iter *msg_it, - struct ctf_msg_iter_packet_properties *props) -{ - enum ctf_msg_iter_status status; - - BT_ASSERT_DBG(msg_it); - BT_ASSERT_DBG(props); - status = read_packet_header_context_fields(msg_it); - if (status != CTF_MSG_ITER_STATUS_OK) { - goto end; - } - - props->exp_packet_total_size = msg_it->cur_exp_packet_total_size; - props->exp_packet_content_size = msg_it->cur_exp_packet_content_size; - props->stream_class_id = (uint64_t) msg_it->cur_stream_class_id; - props->data_stream_id = msg_it->cur_data_stream_id; - props->snapshots.discarded_events = msg_it->snapshots.discarded_events; - props->snapshots.packets = msg_it->snapshots.packets; - props->snapshots.beginning_clock = msg_it->snapshots.beginning_clock; - props->snapshots.end_clock = msg_it->snapshots.end_clock; - -end: - return status; -} - -void ctf_msg_iter_set_dry_run(struct ctf_msg_iter *msg_it, bool val) -{ - msg_it->dry_run = val; -} diff --git a/src/plugins/ctf/common/src/msg-iter/msg-iter.hpp b/src/plugins/ctf/common/src/msg-iter/msg-iter.hpp deleted file mode 100644 index b375b0d8..00000000 --- a/src/plugins/ctf/common/src/msg-iter/msg-iter.hpp +++ /dev/null @@ -1,365 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation - * Copyright (c) 2015-2016 Philippe Proulx - * - * Babeltrace - CTF message iterator - */ - -#ifndef BABELTRACE_PLUGINS_CTF_COMMON_SRC_MSG_ITER_MSG_ITER_HPP -#define BABELTRACE_PLUGINS_CTF_COMMON_SRC_MSG_ITER_MSG_ITER_HPP - -#include -#include -#include - -#include - -#include "../metadata/tsdl/ctf-meta.hpp" - -namespace bt2c { - -class Logger; - -} /* namespace bt2c */ - -/** - * @file ctf-msg-iter.h - * - * CTF message iterator - * - * This is a common internal API used by CTF source plugins. It allows - * one to get messages from a user-provided medium. - */ - -/** - * Medium operations status codes. These use the same values as - * libbabeltrace2. - */ -enum ctf_msg_iter_medium_status -{ - /** - * End of file. - * - * The medium function called by the message iterator - * function reached the end of the file. - */ - CTF_MSG_ITER_MEDIUM_STATUS_EOF = 1, - - /** - * There is no data available right now, try again later. - */ - CTF_MSG_ITER_MEDIUM_STATUS_AGAIN = 11, - - /** General error. */ - CTF_MSG_ITER_MEDIUM_STATUS_ERROR = -1, - - /** Memory error. */ - CTF_MSG_ITER_MEDIUM_STATUS_MEMORY_ERROR = -12, - - /** Everything okay. */ - CTF_MSG_ITER_MEDIUM_STATUS_OK = 0, -}; - -inline const char *format_as(const ctf_msg_iter_medium_status status) noexcept -{ - switch (status) { - case CTF_MSG_ITER_MEDIUM_STATUS_EOF: - return "EOF"; - - case CTF_MSG_ITER_MEDIUM_STATUS_AGAIN: - return "AGAIN"; - - case CTF_MSG_ITER_MEDIUM_STATUS_ERROR: - return "ERROR"; - - case CTF_MSG_ITER_MEDIUM_STATUS_MEMORY_ERROR: - return "MEMORY_ERROR"; - - case CTF_MSG_ITER_MEDIUM_STATUS_OK: - return "OK"; - } - - bt_common_abort(); -} - -/** - * CTF message iterator API status code. - */ -enum ctf_msg_iter_status -{ - /** - * End of file. - * - * The medium function called by the message iterator - * function reached the end of the file. - */ - CTF_MSG_ITER_STATUS_EOF = CTF_MSG_ITER_MEDIUM_STATUS_EOF, - - /** - * There is no data available right now, try again later. - * - * Some condition resulted in the - * ctf_msg_iter_medium_ops::request_bytes() user function not - * having access to any data now. You should retry calling the - * last called message iterator function once the situation - * is resolved. - */ - CTF_MSG_ITER_STATUS_AGAIN = CTF_MSG_ITER_MEDIUM_STATUS_AGAIN, - - /** General error. */ - CTF_MSG_ITER_STATUS_ERROR = CTF_MSG_ITER_MEDIUM_STATUS_ERROR, - - /** Memory error. */ - CTF_MSG_ITER_STATUS_MEMORY_ERROR = CTF_MSG_ITER_MEDIUM_STATUS_MEMORY_ERROR, - - /** Everything okay. */ - CTF_MSG_ITER_STATUS_OK = CTF_MSG_ITER_MEDIUM_STATUS_OK, -}; - -inline const char *format_as(ctf_msg_iter_status status) noexcept -{ - switch (status) { - case CTF_MSG_ITER_STATUS_EOF: - return "EOF"; - - case CTF_MSG_ITER_STATUS_AGAIN: - return "AGAIN"; - - case CTF_MSG_ITER_STATUS_ERROR: - return "ERROR"; - - case CTF_MSG_ITER_STATUS_MEMORY_ERROR: - return "MEMORY_ERROR"; - - case CTF_MSG_ITER_STATUS_OK: - return "OK"; - } - - bt_common_abort(); -} - -/** - * Medium operations. - * - * Those user functions are called by the message iterator - * functions to request medium actions. - */ -struct ctf_msg_iter_medium_ops -{ - /** - * Returns the next byte buffer to be used by the binary file - * reader to deserialize binary data. - * - * This function \em must be defined. - * - * The purpose of this function is to return a buffer of bytes - * to the message iterator, of a maximum of \p request_sz - * bytes. If this function cannot return a buffer of at least - * \p request_sz bytes, it may return a smaller buffer. In - * either cases, \p buffer_sz must be set to the returned buffer - * size (in bytes). - * - * The returned buffer's ownership remains the medium, in that - * it won't be freed by the message iterator functions. The - * returned buffer won't be modified by the message - * iterator functions either. - * - * When this function is called for the first time for a given - * file, the offset within the file is considered to be 0. The - * next times this function is called, the returned buffer's - * byte offset within the complete file must be the previous - * offset plus the last returned value of \p buffer_sz by this - * medium. - * - * This function must return one of the following statuses: - * - * - #CTF_MSG_ITER_MEDIUM_STATUS_OK: Everything - * is okay, i.e. \p buffer_sz is set to a positive value - * reflecting the number of available bytes in the buffer - * starting at the address written in \p buffer_addr. - * - #CTF_MSG_ITER_MEDIUM_STATUS_AGAIN: No data is - * available right now. In this case, the message - * iterator function called by the user returns - * #CTF_MSG_ITER_STATUS_AGAIN, and it is the user's - * responsibility to make sure enough data becomes available - * before calling the \em same message iterator - * function again to continue the decoding process. - * - #CTF_MSG_ITER_MEDIUM_STATUS_EOF: The end of - * the file was reached, and no more data will ever be - * available for this file. In this case, the message - * iterator function called by the user returns - * #CTF_MSG_ITER_STATUS_EOF. This must \em not be - * returned when returning at least one byte of data to the - * caller, i.e. this must be returned when there's - * absolutely nothing left; should the request size be - * larger than what's left in the file, this function must - * return what's left, setting \p buffer_sz to the number of - * remaining bytes, and return - * #CTF_MSG_ITER_MEDIUM_STATUS_EOF on the \em following - * call. - * - #CTF_MSG_ITER_MEDIUM_STATUS_ERROR: A fatal - * error occurred during this operation. In this case, the - * message iterator function called by the user returns - * #CTF_MSG_ITER_STATUS_ERROR. - * - * If #CTF_MSG_ITER_MEDIUM_STATUS_OK is not returned, the - * values of \p buffer_sz and \p buffer_addr are \em ignored by - * the caller. - * - * @param request_sz Requested buffer size (bytes) - * @param buffer_addr Returned buffer address - * @param buffer_sz Returned buffer's size (bytes) - * @param data User data - * @returns Status code (see description above) - */ - enum ctf_msg_iter_medium_status (*request_bytes)(size_t request_sz, uint8_t **buffer_addr, - size_t *buffer_sz, void *data); - - /** - * Repositions the underlying stream's position. - * - * This *optional* method repositions the underlying stream - * to a given absolute position in the medium. - * - * @param offset Offset to use for the given directive - * @param data User data - * @returns One of #ctf_msg_iter_medium_status values - */ - enum ctf_msg_iter_medium_status (*seek)(off_t offset, void *data); - - /** - * Called when the message iterator wishes to inform the medium that it - * is about to start a new packet. - * - * After the iterator has called switch_packet, the following call to - * request_bytes must return the content at the start of the next - * packet. */ - enum ctf_msg_iter_medium_status (*switch_packet)(void *data); - - /** - * Returns a stream instance (weak reference) for the given - * stream class. - * - * This is called after a packet header is read, and the - * corresponding stream class is found by the message - * iterator. - * - * @param stream_class Stream class of the stream to get - * @param stream_id Stream (instance) ID of the stream - * to get (-1ULL if not available) - * @param data User data - * @returns Stream instance (weak reference) or - * \c NULL on error - */ - bt_stream *(*borrow_stream)(bt_stream_class *stream_class, int64_t stream_id, void *data); -}; - -/** CTF message iterator. */ -struct ctf_msg_iter; - -struct ctf_msg_iter_deleter -{ - void operator()(ctf_msg_iter *iter) noexcept; -}; - -using ctf_msg_iter_up = std::unique_ptr; - -/** - * Creates a CTF message iterator. - * - * Upon successful completion, the reference count of \p trace is - * incremented. - * - * @param trace Trace to read - * @param max_request_sz Maximum buffer size, in bytes, to - * request to - * ctf_msg_iter_medium_ops::request_bytes() - * at a time - * @param medops Medium operations - * @param medops_data User data (passed to medium operations) - * @returns New CTF message iterator on - * success, or \c NULL on error - */ -ctf_msg_iter_up ctf_msg_iter_create(struct ctf_trace_class *tc, size_t max_request_sz, - struct ctf_msg_iter_medium_ops medops, void *medops_data, - bt_self_message_iterator *self_msg_iter, - const bt2c::Logger& logger); - -/** - * Destroys a CTF message iterator, freeing all internal resources. - * - * The registered trace's reference count is decremented. - * - * @param msg_iter CTF message iterator - */ -void ctf_msg_iter_destroy(struct ctf_msg_iter *msg_iter); - -/** - * Returns the next message from a CTF message iterator. - * - * Upon successful completion, #CTF_MSG_ITER_STATUS_OK is - * returned, and the next message is written to \p msg. - * In this case, the caller is responsible for calling - * bt_message_put() on the returned message. - * - * If this function returns #CTF_MSG_ITER_STATUS_AGAIN, the caller - * should make sure that data becomes available to its medium, and - * call this function again, until another status is returned. - * - * @param msg_iter CTF message iterator - * @param message Returned message if the function's - * return value is #CTF_MSG_ITER_STATUS_OK - * @returns One of #ctf_msg_iter_status values - */ -enum ctf_msg_iter_status ctf_msg_iter_get_next_message(struct ctf_msg_iter *msg_it, - const bt_message **message); - -struct ctf_msg_iter_packet_properties -{ - int64_t exp_packet_total_size; - int64_t exp_packet_content_size; - uint64_t stream_class_id; - int64_t data_stream_id; - - struct - { - uint64_t discarded_events; - uint64_t packets; - uint64_t beginning_clock; - uint64_t end_clock; - } snapshots; -}; - -enum ctf_msg_iter_status -ctf_msg_iter_get_packet_properties(struct ctf_msg_iter *msg_it, - struct ctf_msg_iter_packet_properties *props); - -enum ctf_msg_iter_status -ctf_msg_iter_curr_packet_first_event_clock_snapshot(struct ctf_msg_iter *msg_it, - uint64_t *first_event_cs); - -enum ctf_msg_iter_status -ctf_msg_iter_curr_packet_last_event_clock_snapshot(struct ctf_msg_iter *msg_it, - uint64_t *last_event_cs); - -enum ctf_msg_iter_status ctf_msg_iter_seek(struct ctf_msg_iter *msg_it, off_t offset); - -/* - * Resets the iterator so that the next requested medium bytes are - * assumed to be the first bytes of a new stream. Depending on - * ctf_msg_iter_set_emit_stream_beginning_message(), the first message - * which this iterator emits after calling ctf_msg_iter_reset() is of - * type `CTF_MESSAGE_TYPE_STREAM_BEGINNING`. - */ -void ctf_msg_iter_reset(struct ctf_msg_iter *msg_it); - -/* - * Like ctf_msg_iter_reset(), but preserves stream-dependent state. - */ -void ctf_msg_iter_reset_for_next_stream_file(struct ctf_msg_iter *msg_it); - -void ctf_msg_iter_set_dry_run(struct ctf_msg_iter *msg_it, bool val); - -#endif /* BABELTRACE_PLUGINS_CTF_COMMON_SRC_MSG_ITER_MSG_ITER_HPP */ diff --git a/src/plugins/ctf/fs-src/fs.cpp b/src/plugins/ctf/fs-src/fs.cpp index 6b1b3377..a1e5a599 100644 --- a/src/plugins/ctf/fs-src/fs.cpp +++ b/src/plugins/ctf/fs-src/fs.cpp @@ -27,7 +27,6 @@ #include "../common/src/metadata/ctf-ir.hpp" #include "../common/src/metadata/tsdl/ctf-meta-configure-ir-trace.hpp" #include "../common/src/msg-iter.hpp" -#include "../common/src/msg-iter/msg-iter.hpp" #include "../common/src/pkt-props.hpp" #include "data-stream-file.hpp" #include "file.hpp" diff --git a/src/plugins/ctf/lttng-live/data-stream.cpp b/src/plugins/ctf/lttng-live/data-stream.cpp index 2adf305e..b385df90 100644 --- a/src/plugins/ctf/lttng-live/data-stream.cpp +++ b/src/plugins/ctf/lttng-live/data-stream.cpp @@ -9,8 +9,6 @@ #include -#include - #include #include "common/assert.h"