lib: decouple variant FC option names from selector FC mapping names
This patch makes the options of a variant field class (FC) which has a
selector have their own range set, decoupled from any mapping of the
selector FC.
Motivation and solution
=======================
In CTF 1.8, structure FC member and variant FC option names which start
with `_` in the metadata stream must be "unescaped" by removing the `_`
prefix. For example:
struct {
string _salut;
string meow;
};
`_salut` becomes `salut` in trace IR, while `meow` stays `meow`.
CTF 1.8.2 specifies:
> Fields starting with an underscore should have their leading
> underscore removed by the CTF trace readers.
Here, we interpret "should" as "must" because Babeltrace 1, Trace
Compass, and other CTF consumers honor this recommandation.
It is not specified, however, that this strategy applies to enumeration
FC mapping labels. For example:
enum {
_SALUT,
MEOW,
};
In Babeltrace 1 (`text` output format and API), `_SALUT` and `MEOW`
remain as is, so Babeltrace 2 should do the same.
There's an issue however when an enumeration FC is used as a tag, or
selector, for a variant FC:
enum {
_salut,
_meow,
} tag;
variant <tag> {
string _salut;
int _meow;
};
This is valid TSDL 1.8, but once in trace IR, the enumeration FC mapping
labels need to stay as is, while the variant FC option names need to be
unescaped. Once in trace IR, the equivalent would be:
enum {
_salut,
_meow,
} tag;
variant <tag> {
string salut;
int meow;
};
Before this patch, this is not valid because, when a variant FC has a
selector FC, the option and mapping names must match exactly: we don't
want to bring this CTF-specific escaping logic into the CTF-agnostic
API.
The current hack to avoid this, performed by `src.ctf.fs`, is to also
unescape the mapping names, so as to get:
enum {
salut,
meow,
} tag;
variant <tag> {
string salut;
int meow;
};
However, this makes Babeltrace 2 not behave like Babeltrace 1 because
the enumeration FC mapping names are different. For example, the
`sink.text.pretty` outputs differ for the same CTF trace.
The solution brought by this patch to fix this issue is to make the
options of a variant FC have their own range set. Using the example
above, the layout in trace IR becomes:
enum {
_salut,
_meow,
} tag;
variant <tag> {
string salut {0};
int meow {1};
};
where `{0}` and `{1}` are the range sets associated to the option.
Here's another example:
enum {
_salut,
_meow = 12,
coucou = 17 ... 45,
_meow = 1 ... 5,
} tag;
variant <tag> {
string salut {0};
int meow {1 ... 5, 12};
int coucou[5] {17 ... 45};
};
This change allows `src.ctf.fs` to keep the enumeration FC mapping names
as is while properly escaping the variant FC option names.
Library changes
===============
The simple variant field class type is replaced with three new variant
field class types:
Variant without a selector:
You can create a variant FC without a selector FC, just like before,
with bt_field_class_variant_create(), passing `NULL` as the
`selector_field_class` parameter.
The field class's type is
`BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR`.
You can use bt_field_class_variant_without_selector_append_option()
to append an option (name and FC) to a variant FC without a
selector.
You can use bt_field_class_variant_borrow_option_by_index_const()
and bt_field_class_variant_borrow_option_by_name_const() to borrow
a variant FC (base) option from a variant FC without a selector.
Variant with a selector:
You can create a variant FC with a specific selector FC with
bt_field_class_variant_create().
The selector FC must be an _integer_ FC. This is less strict than
before: because each option has its own range set, the selector FC
does not need to be an enumeration FC. It can be an enumeration FC,
but there's no association between its mapping names and the variant
FC option names.
The field class types are
`BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR` and
`BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR`.
There's an unsigned and a signed type to make the API typing more
strict: a variant FC with an unsigned selector has specific option
objects from which you can borrow unsigned integer range sets.
You can use
bt_field_class_variant_with_unsigned_selector_append_option() and
bt_field_class_variant_with_signed_selector_append_option() to
append an option (name, FC, and range set) to a variant FC with a
selector.
You can use
bt_field_class_variant_with_unsigned_selector_borrow_option_by_index_const(),
bt_field_class_variant_with_unsigned_selector_borrow_option_by_name_const(),
bt_field_class_variant_with_signed_selector_borrow_option_by_index_const(),
or
bt_field_class_variant_with_signed_selector_borrow_option_by_name_const()
to borrow a variant FC with a selector option from a variant FC
with a selector.
The option object's type is either
`bt_field_class_variant_with_unsigned_selector_option` or
`bt_field_class_variant_with_signed_selector_option`. You can
convert it to a base option (to get its name and borrow its field
class) with
bt_field_class_variant_with_unsigned_selector_option_as_option_const()
or
bt_field_class_variant_with_signed_selector_option_as_option_const().
You can borrow the ranges of a variant FC with a selector option
with
bt_field_class_variant_with_unsigned_selector_option_borrow_ranges_const()
or
bt_field_class_variant_with_signed_selector_option_borrow_ranges_const().
You can use
bt_field_class_variant_with_selector_borrow_selector_field_path_const()
to borrow the selector field path from a variant FC with a selector.
I also added the following functions for convenience:
* bt_field_variant_borrow_selected_class_option_const()
* bt_field_variant_with_unsigned_selector_borrow_selected_class_option_const()
* bt_field_variant_with_signed_selector_borrow_selected_class_option_const()
For consistency, bt_field_variant_select_option_field() is renamed to
bt_field_variant_select_option_field_by_index().
This patch also makes an enumeration FC mapping contain an integer range
set object. This was planned anyway, and not doing it here would have
meant to duplicate and adapt code for the variant FC option ranges, for
example in `sink.text.details` to sort the ranges of a range set.
This means that bt_field_class_unsigned_enumeration_map_range() and
bt_field_class_signed_enumeration_map_range() are replaced with
bt_field_class_unsigned_enumeration_add_mapping() and
bt_field_class_signed_enumeration_add_mapping() which accept resp.
unsigned and signed integer range sets.
This also means that
bt_field_class_enumeration_mapping_get_range_count(),
bt_field_class_unsigned_enumeration_mapping_get_range_by_index(), and
bt_field_class_signed_enumeration_mapping_get_range_by_index() are
replaced with
bt_field_class_unsigned_enumeration_mapping_borrow_ranges_const() and
bt_field_class_signed_enumeration_mapping_borrow_ranges_const().
Because I needed it when adapting the project's plugins, I also added
the following functions for convenience:
* bt_field_class_unsigned_enumeration_borrow_mapping_by_label_const()
* bt_field_class_signed_enumeration_borrow_mapping_by_label_const()
Noteworthy plugin changes
=========================
`src.ctf.fs`:
* Enumeration FC mapping names are not unescaped anymore: they are
kept as is.
* A CTF IR named FC contains the original name and the escaped name.
The original name is used to find the ranges of a variant FC
option in the selector FC as the mapping names are not escaped
anymore, so they potentially do not match the variant FC option
names.
* When translating a CTF IR variant FC to a trace IR variant FC, the
trace IR selector (enumeration) FC's integer range set references
are reused directly to append the corresponding variant FC
options.
`sink.ctf.fs`:
* Enumeration FC mapping names are not escaped anymore: they are
kept as is.
* If a variant FC has a selector, then for each option, the
component finds the corresponding mapping in the selector FC _by
range set_ to know whether or not to escape the option name.
This is because this must work (from `src.ctf.fs`):
enum {
salut,
_meow,
} tag;
variant <tag> {
string salut;
int _meow;
};
Once in trace IR, the `_meow` option becomes `meow`, but the
`_meow` mapping keeps its original name. However, we know that,
for `src.ctf.fs`, the range sets match exactly. For the `meow`
option, the corresponding mapping is `_meow` because they both
have the range set with the single range [1, 1]. In that case,
when going back to TSDL, `sink.ctf.fs` writes `_meow` for the
option name, while `salut` remains `salut`.
I added new `sink.ctf.fs` tests, with new succeeding CTF traces,
to verify that the component works as expected with those specific
cases.
If there's any issue when doing this, `sink.ctf.fs` falls back to
creating a dedicated selector FC for the variant FC. For example,
in trace IR, this is totally valid:
enum {
a = 2,
b = 5,
d = 8,
} tag;
variant <tag> {
string a {2};
int b {11};
int c[22] {15 ... 19};
};
because there's no association between mapping names and option
names. This too:
int tag;
variant <tag> {
string a {2};
int b {11};
int c[22] {15 ... 19};
};
Those specimens cannot be translated to TSDL 1.8 however.
* Because of changes in the way TSDL identifers are protected and
validated, clock class names are not systematically escaped if
it's not needed. Therefore the clock class name `default` remains
`default`; it does not become `_default` like before.
`sink.text.details`:
* Variant FC option ranges are written next to the option's name:
var: Variant (unsigned selector) (3 options, Selector field path [Event payload: 0]):
COSSETTE: [0]: String
_PELCHAT: [1]: String
VOISINE: [2] [5, 19]: String
* Enumeration FC mapping ranges are written next to the option's
name instead of having one per line. I find this is more compact
and easier to read as mappings typically do not contain a lot of
ranges:
tag: Unsigned enumeration (8-bit, Base 10, 3 mappings):
COSSETTE: [0]
VOISINE: [2] [5, 19]
__PELCHAT: [1]
Python bindings changes
=======================
Essentially, the `bt2` Python package is updated to match the library's
API changes:
* `_EnumerationFieldClassMapping` is not a set anymore: it has
a `ranges` property (which is a set).
* _EnumerationFieldClass.map_range() is replaced with
_EnumerationFieldClass.add_mapping() to which you pass an integer
range set.
* _EnumerationFieldClass.labels_for_value() is replaced with
_EnumerationFieldClass.mappings_for_value() to get mappings instead of
simple labels.
* _EnumerationFieldClass.__getitem__() now uses
bt_field_class_unsigned_enumeration_borrow_mapping_by_label_const()
or
bt_field_class_signed_enumeration_borrow_mapping_by_label_const().
* The new `_VariantFieldClassWithSelectorOption` object inherits
`_VariantFieldClassOption`, adding a `ranges` property.
* With a `_VariantFieldClass`, you can borrow base options
(`_VariantFieldClassOption`) to get their names and field classes.
* The new types `_VariantFieldClassWithoutSelector`,
`_VariantFieldClassWithUnsignedSelector`, and
`_VariantFieldClassWithSignedSelector` are analogous to the new
types in the library's API.
You can create them with
_TraceClass.create_variant_field_class_without_selector() and
_TraceClass.create_variant_field_class_with_selector(). The selector
FC object must be an instance of `_IntegerFieldClass`.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: I084b03ea816ff8bee03ef5315c24fa24cfe74d80
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1717
Tested-by: jenkins <jenkins@lttng.org>
54 files changed:
This page took 0.035906 seconds and 4 git commands to generate.