Update the automatic mapping of specific fields to clock classes when
no explicit mapping is found in the integer field type to follow this:
| 0 CCs | 1 CC | 2+ CCs
--------------------------------------------------------------------
FT is mapped | Unreachable | OK as is | OK as is
FT is not mapped | Map to auto 1 GHz | Map to single CC | Error
The (FT is not mapped, 0 CC) cell follows Babeltrace 1's behaviour: when
a special timestamp field is found in the packet context
(`timestamp_begin` or `timestamp_end`) or event header (`timestamp`)
scope, when this timestamp field is not explicitly mapped to a clock
class, and when there's no clock class at this point in the trace, then
create an automatic, 1 GHz clock class and, in this case, name it
`default`. Map the field to this implicit 1 GHz clock class. See
section 8 ("Clocks") of CTF v1.8.2.
Cell (FT is not mapped, 0 CC) is a fix for old versions of LTTng, and
cell (FT is not mapped, 1 CC) is a fix for old versions of CTF writer.
Cell (FT is not mapped, 2+ CCs) is an error because we wouldn't know
which clock class to automatically map the field to.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
struct ctf_metadata_decoder_config default_config = {
.clock_class_offset_s = 0,
.clock_class_offset_ns = 0,
struct ctf_metadata_decoder_config default_config = {
.clock_class_offset_s = 0,
.clock_class_offset_ns = 0,
BT_LOGD("Creating CTF metadata decoder: "
"clock-class-offset-s=%" PRId64 ", "
BT_LOGD("Creating CTF metadata decoder: "
"clock-class-offset-s=%" PRId64 ", "
- "clock-class-offset-ns=%" PRId64 ", "
- "strict=%d, name=\"%s\"",
+ "clock-class-offset-ns=%" PRId64 ", name=\"%s\"",
config->clock_class_offset_s, config->clock_class_offset_ns,
config->clock_class_offset_s, config->clock_class_offset_ns,
if (!mdec) {
BT_LOGE_STR("Failed to allocate one CTF metadata decoder.");
if (!mdec) {
BT_LOGE_STR("Failed to allocate one CTF metadata decoder.");
BT_LOGD("Creating CTF metadata decoder: "
"clock-class-offset-s=%" PRId64 ", "
"clock-class-offset-ns=%" PRId64 ", "
BT_LOGD("Creating CTF metadata decoder: "
"clock-class-offset-s=%" PRId64 ", "
"clock-class-offset-ns=%" PRId64 ", "
- "strict=%d, name=\"%s\", addr=%p",
+ "name=\"%s\", addr=%p",
config->clock_class_offset_s, config->clock_class_offset_ns,
config->clock_class_offset_s, config->clock_class_offset_ns,
- config->strict, name, mdec);
struct ctf_metadata_decoder_config {
int64_t clock_class_offset_s;
int64_t clock_class_offset_ns;
struct ctf_metadata_decoder_config {
int64_t clock_class_offset_s;
int64_t clock_class_offset_ns;
-int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
- struct bt_ctf_field_type *packet_context_field_type,
- const char **field_names)
+int auto_map_field_to_trace_clock_class(struct ctx *ctx,
+ struct bt_ctf_field_type *ft)
- _BT_CTF_FIELD_TYPE_INIT(ft);
- struct bt_ctf_clock_class *clock_class = NULL;
+ struct bt_ctf_clock_class *clock_class_to_map_to = NULL;
struct bt_ctf_clock_class *mapped_clock_class = NULL;
int ret = 0;
struct bt_ctf_clock_class *mapped_clock_class = NULL;
int ret = 0;
- const char **field_name;
+ int64_t clock_class_count;
+
+ if (!ft || !bt_ctf_field_type_is_integer(ft)) {
+ goto end;
+ }
+
+ mapped_clock_class =
+ bt_ctf_field_type_integer_get_mapped_clock_class(ft);
+ if (mapped_clock_class) {
+ goto end;
+ }
+
+ clock_class_count = bt_ctf_trace_get_clock_class_count(ctx->trace);
+ assert(clock_class_count >= 0);
+
+ switch (clock_class_count) {
+ case 0:
+ /*
+ * No clock class exists in the trace at this
+ * point. Create an implicit one at 1 GHz,
+ * named `default`, and use this clock class.
+ */
+ clock_class_to_map_to = bt_ctf_clock_class_create("default");
+ if (!clock_class_to_map_to) {
+ BT_LOGE_STR("Cannot create a clock class.");
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctf_clock_class_set_frequency(clock_class_to_map_to,
+ 1000000000);
+ assert(ret == 0);
- if (ctx->decoder_config.strict) {
+ ret = bt_ctf_trace_add_clock_class(ctx->trace,
+ clock_class_to_map_to);
+ if (ret) {
+ BT_LOGE_STR("Cannot add clock class to trace.");
+ goto end;
+ }
+ break;
+ case 1:
+ /*
+ * Only one clock class exists in the trace at
+ * this point: use this one.
+ */
+ clock_class_to_map_to =
+ bt_ctf_trace_get_clock_class_by_index(ctx->trace, 0);
+ assert(clock_class_to_map_to);
+ break;
+ default:
+ /*
+ * Timestamp field not mapped to a clock class
+ * and there's more than one clock class in the
+ * trace: this is an error.
+ */
+ BT_LOGE_STR("Timestamp field found with no mapped clock class, "
+ "but there's more than one clock class in the trace at this point.");
+ ret = -1;
- if (!packet_context_field_type) {
+ assert(clock_class_to_map_to);
+ ret = bt_ctf_field_type_integer_set_mapped_clock_class(ft,
+ clock_class_to_map_to);
+ if (ret) {
+ BT_LOGE("Cannot map field type's field to trace's clock class: "
+ "clock-class-name=\"%s\", ret=%d",
+ bt_ctf_clock_class_get_name(clock_class_to_map_to),
+ ret);
- if (!bt_ctf_field_type_is_structure(packet_context_field_type)) {
+end:
+ bt_put(clock_class_to_map_to);
+ bt_put(mapped_clock_class);
+ return ret;
+}
+
+static
+int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
+ struct bt_ctf_field_type *root_ft, const char *field_name)
+{
+ int ret = 0;
+ int64_t i, count;
+
+ if (!root_ft) {
- if (bt_ctf_trace_get_clock_class_count(ctx->trace) != 1) {
+ if (!bt_ctf_field_type_is_structure(root_ft) &&
+ !bt_ctf_field_type_is_variant(root_ft)) {
- clock_class = bt_ctf_trace_get_clock_class_by_index(ctx->trace, 0);
- assert(clock_class);
+ if (bt_ctf_field_type_is_structure(root_ft)) {
+ count = bt_ctf_field_type_structure_get_field_count(root_ft);
+ } else {
+ count = bt_ctf_field_type_variant_get_field_count(root_ft);
+ }
- for (field_name = field_names; *field_name; field_name++) {
- ft = bt_ctf_field_type_structure_get_field_type_by_name(
- packet_context_field_type, *field_name);
- if (ft && bt_ctf_field_type_is_integer(ft)) {
- mapped_clock_class =
- bt_ctf_field_type_integer_get_mapped_clock_class(ft);
+ for (i = 0; i < count; i++) {
+ _BT_CTF_FIELD_TYPE_INIT(ft);
+ const char *name;
- if (!mapped_clock_class) {
- ret = bt_ctf_field_type_integer_set_mapped_clock_class(
- ft, clock_class);
- if (ret) {
- BT_LOGE("Cannot map field type's field to trace's clock class: "
- "field-name=\"%s\", ret=%d",
- *field_name, ret);
- goto end;
- }
+ if (bt_ctf_field_type_is_structure(root_ft)) {
+ ret = bt_ctf_field_type_structure_get_field_by_index(
+ root_ft, &name, &ft, i);
+ } else if (bt_ctf_field_type_is_variant(root_ft)) {
+ ret = bt_ctf_field_type_variant_get_field_by_index(
+ root_ft, &name, &ft, i);
+ }
+
+ assert(ret == 0);
+
+ if (strcmp(name, field_name) == 0) {
+ ret = auto_map_field_to_trace_clock_class(ctx, ft);
+ if (ret) {
+ BT_LOGE("Cannot automatically map field to trace's clock class: "
+ "field-name=\"%s\"", field_name);
+ bt_put(ft);
+ goto end;
- BT_PUT(mapped_clock_class);
- BT_PUT(ft);
+ ret = auto_map_fields_to_trace_clock_class(ctx, ft, field_name);
+ bt_put(ft);
+ if (ret) {
+ BT_LOGE("Cannot automatically map structure or variant field type's fields to trace's clock class: "
+ "field-name=\"%s\", root-field-name=\"%s\"",
+ field_name, name);
+ goto end;
+ }
- bt_put(mapped_clock_class);
- bt_put(clock_class);
- bt_put(ft);
_SET(set, _STREAM_ID_SET);
} else if (!strcmp(left, "event.header")) {
_SET(set, _STREAM_ID_SET);
} else if (!strcmp(left, "event.header")) {
- const char *field_names[] = {
- "timestamp",
- "ts",
- NULL,
- };
-
if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
_BT_LOGE_NODE(node,
"Duplicate `event.header` entry in stream class.");
if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
_BT_LOGE_NODE(node,
"Duplicate `event.header` entry in stream class.");
assert(decl);
ret = auto_map_fields_to_trace_clock_class(ctx,
assert(decl);
ret = auto_map_fields_to_trace_clock_class(ctx,
if (ret) {
_BT_LOGE_NODE(node,
if (ret) {
_BT_LOGE_NODE(node,
- "Cannot automatically map specific event header field type fields to trace's clock class.");
+ "Cannot automatically map specific event header field type fields named `timestamp` to trace's clock class.");
_SET(set, _STREAM_EVENT_CONTEXT_SET);
} else if (!strcmp(left, "packet.context")) {
_SET(set, _STREAM_EVENT_CONTEXT_SET);
} else if (!strcmp(left, "packet.context")) {
- const char *field_names[] = {
- "timestamp_begin",
- "timestamp_end",
- NULL,
- };
-
if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
_BT_LOGE_NODE(node,
"Duplicate `packet.context` entry in stream class.");
if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
_BT_LOGE_NODE(node,
"Duplicate `packet.context` entry in stream class.");
assert(decl);
ret = auto_map_fields_to_trace_clock_class(ctx,
assert(decl);
ret = auto_map_fields_to_trace_clock_class(ctx,
+ decl, "timestamp_begin");
+ if (ret) {
+ _BT_LOGE_NODE(node,
+ "Cannot automatically map specific packet context field type fields named `timestamp_begin` to trace's clock class.");
+ goto error;
+ }
+
+ ret = auto_map_fields_to_trace_clock_class(ctx,
+ decl, "timestamp_end");
if (ret) {
_BT_LOGE_NODE(node,
if (ret) {
_BT_LOGE_NODE(node,
- "Cannot automatically map specific packet context field type fields to trace's clock class.");
+ "Cannot automatically map specific packet context field type fields named `timestamp_end` to trace's clock class.");
- if (!ctx->decoder_config.strict) {
- if (strcmp(left, "tracer_name") == 0) {
- if (strncmp(right, "lttng", 5) == 0) {
- BT_LOGI("Non-strict mode: detected LTTng trace from `%s` environment value: "
- "tracer-name=\"%s\"",
- left, right);
- ctx->is_lttng = 1;
- }
+ if (strcmp(left, "tracer_name") == 0) {
+ if (strncmp(right, "lttng", 5) == 0) {
+ BT_LOGI("Detected LTTng trace from `%s` environment value: "
+ "tracer-name=\"%s\"",
+ left, right);
+ ctx->is_lttng = 1;
- value = bt_value_map_get(params, "strict-metadata");
- if (value) {
- bt_bool strict;
-
- if (!bt_value_is_bool(value)) {
- BT_LOGE("strict-metadata should be a boolean");
- goto error;
- }
- ret = bt_value_bool_get(value, &strict);
- assert(ret == 0);
- ctf_fs->metadata_config.strict = !!strict;
- BT_PUT(value);
- }
-
ctf_fs->port_data = g_ptr_array_new_with_free_func(port_data_destroy);
if (!ctf_fs->port_data) {
goto error;
ctf_fs->port_data = g_ptr_array_new_with_free_func(port_data_destroy);
if (!ctf_fs->port_data) {
goto error;
struct ctf_metadata_decoder_config decoder_config = {
.clock_class_offset_s = config->clock_class_offset_s,
.clock_class_offset_ns = config->clock_class_offset_ns,
struct ctf_metadata_decoder_config decoder_config = {
.clock_class_offset_s = config->clock_class_offset_s,
.clock_class_offset_ns = config->clock_class_offset_ns,
- .strict = config->strict,
};
file = get_file(ctf_fs_trace->path->str);
};
file = get_file(ctf_fs_trace->path->str);
struct ctf_fs_metadata_config {
int64_t clock_class_offset_s;
int64_t clock_class_offset_ns;
struct ctf_fs_metadata_config {
int64_t clock_class_offset_s;
int64_t clock_class_offset_ns;