X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-field-convert.cpp;h=74c41939e3c218a3ce291040d9f49ca253f51cf6;hb=9efff7e744f4b4b3fbe37de5fece3b59fdeb4b00;hp=4911db0e5b6a7e198e5ec82653486d956515b9c7;hpb=833eb34299bd3c6614c4ce755ecb871dcfb769b5;p=deliverable%2Flttng-tools.git diff --git a/src/bin/lttng-sessiond/ust-field-convert.cpp b/src/bin/lttng-sessiond/ust-field-convert.cpp index 4911db0e5..74c41939e 100644 --- a/src/bin/lttng-sessiond/ust-field-convert.cpp +++ b/src/bin/lttng-sessiond/ust-field-convert.cpp @@ -38,7 +38,7 @@ public: }; /* Used to publish fields on which a field being decoded has an implicit dependency. */ -using publish_field_fn = std::function; +using publish_field_fn = std::function; /* Look-up field from a field location. */ using lookup_field_fn = std::function; @@ -510,7 +510,7 @@ lst::type::cuptr create_sequence_nestable_type_from_ust_ctl_fields( /* Validate existence of length field (throws if not found). */ const auto &length_field = lookup_field(length_field_location); const auto *integer_selector_field = - dynamic_cast(length_field.type_.get()); + dynamic_cast(&length_field.get_type()); if (!integer_selector_field) { LTTNG_THROW_PROTOCOL_ERROR("Invalid selector field type referenced from sequence: expected integer or enumeration"); } @@ -567,6 +567,57 @@ lst::type::cuptr create_structure_field_from_ust_ctl_fields(const lttng_ust_ctl_ return lttng::make_unique(alignment, lst::structure_type::fields()); } +template +typename lst::variant_type::choices create_typed_variant_choices( + const lttng_ust_ctl_field *current, + const lttng_ust_ctl_field *end, + const session_attributes& session_attributes, + const lttng_ust_ctl_field **next_ust_ctl_field, + lookup_field_fn lookup_field, + lst::field_location::root lookup_root, + lst::field_location::elements& current_field_location_elements, + unsigned int choice_count, + const lst::field& selector_field) +{ + typename lst::variant_type::choices choices; + const auto& typed_enumeration = static_cast< + const lst::typed_enumeration_type&>( + selector_field.get_type()); + + for (unsigned int i = 0; i < choice_count; i++) { + create_field_from_ust_ctl_fields( + current, end, session_attributes, next_ust_ctl_field, + [&choices, typed_enumeration, &selector_field]( + lst::field::uptr field) { + /* + * Find the enumeration mapping that matches the + * field's name. + */ + const auto mapping_it = std::find_if( + typed_enumeration._mappings->begin(), + typed_enumeration._mappings->end(), + [&field](const typename std::remove_reference< + decltype(typed_enumeration)>::type:: + mapping& mapping) { + return mapping.name == field->name; + }); + + if (mapping_it == typed_enumeration._mappings->end()) { + LTTNG_THROW_PROTOCOL_ERROR(fmt::format( + "Invalid variant choice: `{}` does not match any mapping in `{}` enumeration", + field->name, selector_field.name)); + } + + choices.emplace_back(*mapping_it, field->move_type()); + }, + lookup_field, lookup_root, current_field_location_elements); + + current = *next_ust_ctl_field; + } + + return choices; +} + lst::type::cuptr create_variant_field_from_ust_ctl_fields(const lttng_ust_ctl_field *current, const lttng_ust_ctl_field *end, const session_attributes& session_attributes, @@ -607,27 +658,37 @@ lst::type::cuptr create_variant_field_from_ust_ctl_fields(const lttng_ust_ctl_fi /* Validate existence of selector field (throws if not found). */ const auto &selector_field = lookup_field(selector_field_location); - const auto *integer_selector_field = dynamic_cast(selector_field.type_.get()); - if (!integer_selector_field) { - LTTNG_THROW_PROTOCOL_ERROR("Invalid selector field type referenced from variant: expected integer or enumeration"); + const auto *enumeration_selector_type = + dynamic_cast(&selector_field.get_type()); + if (!enumeration_selector_type) { + LTTNG_THROW_PROTOCOL_ERROR("Invalid selector field type referenced from variant: expected enumeration"); } + const bool selector_is_signed = enumeration_selector_type->signedness_ == + lst::integer_type::signedness::SIGNED; + /* Choices follow. next_ust_ctl_field is updated as needed. */ - lst::variant_type::choices choices; - for (unsigned int i = 0; i < choice_count; i++) { - create_field_from_ust_ctl_fields( - current, end, session_attributes, next_ust_ctl_field, - [&choices](lst::field::cuptr field) { - choices.emplace_back(std::move(field)); - }, - lookup_field, - lookup_root, current_field_location_elements); + if (selector_is_signed) { + lst::variant_type:: + choices choices = create_typed_variant_choices(current, + end, session_attributes, next_ust_ctl_field, + lookup_field, lookup_root, + current_field_location_elements, choice_count, + selector_field); + + return lttng::make_unique>( + alignment, std::move(selector_field_location), std::move(choices)); + } else { + lst::variant_type:: + choices choices = create_typed_variant_choices(current, + end, session_attributes, next_ust_ctl_field, + lookup_field, lookup_root, + current_field_location_elements, choice_count, + selector_field); - current = *next_ust_ctl_field; + return lttng::make_unique>( + alignment, std::move(selector_field_location), std::move(choices)); } - - return lttng::make_unique( - alignment, std::move(selector_field_location), std::move(choices)); } lst::type::cuptr create_type_from_ust_ctl_fields(const lttng_ust_ctl_field *current,