X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-metadata.c;fp=src%2Fbin%2Flttng-sessiond%2Fust-metadata.c;h=0000000000000000000000000000000000000000;hp=7110662c744b99508a04932864ed15d718e92d59;hb=7966af5763c4aaca39df9bbfa9277ff15715c720;hpb=3a5f70173aa04d11ccb22694d5d31a702cad33ab diff --git a/src/bin/lttng-sessiond/ust-metadata.c b/src/bin/lttng-sessiond/ust-metadata.c deleted file mode 100644 index 7110662c7..000000000 --- a/src/bin/lttng-sessiond/ust-metadata.c +++ /dev/null @@ -1,1344 +0,0 @@ -/* - * Copyright (C) 2010-2013 Mathieu Desnoyers - * - * SPDX-License-Identifier: GPL-2.0-only - * - */ - -#define _LGPL_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ust-registry.h" -#include "ust-clock.h" -#include "ust-app.h" - -#ifndef max_t -#define max_t(type, a, b) ((type) ((a) > (b) ? (a) : (b))) -#endif - -#define NR_CLOCK_OFFSET_SAMPLES 10 - -struct offset_sample { - int64_t offset; /* correlation offset */ - uint64_t measure_delta; /* lower is better */ -}; - -static -int _lttng_field_statedump(struct ust_registry_session *session, - const struct lttng_ust_ctl_field *fields, size_t nr_fields, - size_t *iter_field, size_t nesting); - -static inline -int get_count_order(unsigned int count) -{ - int order; - - order = lttng_fls(count) - 1; - if (count & (count - 1)) { - order++; - } - LTTNG_ASSERT(order >= 0); - return order; -} - -/* - * Returns offset where to write in metadata array, or negative error value on error. - */ -static -ssize_t metadata_reserve(struct ust_registry_session *session, size_t len) -{ - size_t new_len = session->metadata_len + len; - size_t new_alloc_len = new_len; - size_t old_alloc_len = session->metadata_alloc_len; - ssize_t ret; - - if (new_alloc_len > (UINT32_MAX >> 1)) - return -EINVAL; - if ((old_alloc_len << 1) > (UINT32_MAX >> 1)) - return -EINVAL; - - if (new_alloc_len > old_alloc_len) { - char *newptr; - - new_alloc_len = - max_t(size_t, 1U << get_count_order(new_alloc_len), old_alloc_len << 1); - newptr = realloc(session->metadata, new_alloc_len); - if (!newptr) - return -ENOMEM; - session->metadata = newptr; - /* We zero directly the memory from start of allocation. */ - memset(&session->metadata[old_alloc_len], 0, new_alloc_len - old_alloc_len); - session->metadata_alloc_len = new_alloc_len; - } - ret = session->metadata_len; - session->metadata_len += len; - return ret; -} - -static -int metadata_file_append(struct ust_registry_session *session, - const char *str, size_t len) -{ - ssize_t written; - - if (session->metadata_fd < 0) { - return 0; - } - /* Write to metadata file */ - written = lttng_write(session->metadata_fd, str, len); - if (written != len) { - return -1; - } - return 0; -} - -/* - * We have exclusive access to our metadata buffer (protected by the - * ust_lock), so we can do racy operations such as looking for - * remaining space left in packet and write, since mutual exclusion - * protects us from concurrent writes. - */ -static -int lttng_metadata_printf(struct ust_registry_session *session, - const char *fmt, ...) -{ - char *str = NULL; - size_t len; - va_list ap; - ssize_t offset; - int ret; - - va_start(ap, fmt); - ret = vasprintf(&str, fmt, ap); - va_end(ap); - if (ret < 0) - return -ENOMEM; - - len = strlen(str); - offset = metadata_reserve(session, len); - if (offset < 0) { - ret = offset; - goto end; - } - memcpy(&session->metadata[offset], str, len); - ret = metadata_file_append(session, str, len); - if (ret) { - PERROR("Error appending to metadata file"); - goto end; - } - DBG3("Append to metadata: \"%s\"", str); - ret = 0; - -end: - free(str); - return ret; -} - -static -int print_tabs(struct ust_registry_session *session, size_t nesting) -{ - size_t i; - - for (i = 0; i < nesting; i++) { - int ret; - - ret = lttng_metadata_printf(session, " "); - if (ret) { - return ret; - } - } - return 0; -} - -static -void sanitize_ctf_identifier(char *out, const char *in) -{ - size_t i; - - for (i = 0; i < LTTNG_UST_ABI_SYM_NAME_LEN; i++) { - switch (in[i]) { - case '.': - case '$': - case ':': - out[i] = '_'; - break; - default: - out[i] = in[i]; - } - } -} - -static -int print_escaped_ctf_string(struct ust_registry_session *session, const char *string) -{ - int ret = 0; - size_t i; - char cur; - - i = 0; - cur = string[i]; - while (cur != '\0') { - switch (cur) { - case '\n': - ret = lttng_metadata_printf(session, "%s", "\\n"); - break; - case '\\': - case '"': - ret = lttng_metadata_printf(session, "%c", '\\'); - if (ret) { - goto error; - } - /* We still print the current char */ - /* Fallthrough */ - default: - ret = lttng_metadata_printf(session, "%c", cur); - break; - } - - if (ret) { - goto error; - } - - cur = string[++i]; - } -error: - return ret; -} - -/* Called with session registry mutex held. */ -static -int ust_metadata_enum_statedump(struct ust_registry_session *session, - const char *enum_name, - uint64_t enum_id, - const struct lttng_ust_ctl_integer_type *container_type, - const char *field_name, size_t *iter_field, size_t nesting) -{ - struct ust_registry_enum *reg_enum; - const struct lttng_ust_ctl_enum_entry *entries; - size_t nr_entries; - int ret = 0; - size_t i; - char identifier[LTTNG_UST_ABI_SYM_NAME_LEN]; - - rcu_read_lock(); - reg_enum = ust_registry_lookup_enum_by_id(session, enum_name, enum_id); - rcu_read_unlock(); - /* reg_enum can still be used because session registry mutex is held. */ - if (!reg_enum) { - ret = -ENOENT; - goto end; - } - entries = reg_enum->entries; - nr_entries = reg_enum->nr_entries; - - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n", - container_type->size, - container_type->alignment, - container_type->signedness, - (container_type->encoding == lttng_ust_ctl_encode_none) - ? "none" - : (container_type->encoding == lttng_ust_ctl_encode_UTF8) - ? "UTF8" - : "ASCII", - container_type->base); - if (ret) { - goto end; - } - nesting++; - /* Dump all entries */ - for (i = 0; i < nr_entries; i++) { - const struct lttng_ust_ctl_enum_entry *entry = &entries[i]; - int j, len; - - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "\""); - if (ret) { - goto end; - } - len = strlen(entry->string); - /* Escape the character '"' */ - for (j = 0; j < len; j++) { - char c = entry->string[j]; - - switch (c) { - case '"': - ret = lttng_metadata_printf(session, - "\\\""); - break; - case '\\': - ret = lttng_metadata_printf(session, - "\\\\"); - break; - default: - ret = lttng_metadata_printf(session, - "%c", c); - break; - } - if (ret) { - goto end; - } - } - ret = lttng_metadata_printf(session, "\""); - if (ret) { - goto end; - } - - if (entry->u.extra.options & - LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) { - ret = lttng_metadata_printf(session, ",\n"); - if (ret) { - goto end; - } - } else { - ret = lttng_metadata_printf(session, - " = "); - if (ret) { - goto end; - } - - if (entry->start.signedness) { - ret = lttng_metadata_printf(session, - "%lld", (long long) entry->start.value); - } else { - ret = lttng_metadata_printf(session, - "%llu", entry->start.value); - } - if (ret) { - goto end; - } - - if (entry->start.signedness == entry->end.signedness && - entry->start.value == - entry->end.value) { - ret = lttng_metadata_printf(session, ",\n"); - } else { - if (entry->end.signedness) { - ret = lttng_metadata_printf(session, - " ... %lld,\n", - (long long) entry->end.value); - } else { - ret = lttng_metadata_printf(session, - " ... %llu,\n", - entry->end.value); - } - } - if (ret) { - goto end; - } - } - } - nesting--; - sanitize_ctf_identifier(identifier, field_name); - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, "} _%s;\n", - identifier); -end: - (*iter_field)++; - return ret; -} - -static -int _lttng_variant_statedump(struct ust_registry_session *session, - uint32_t nr_choices, const char *tag_name, - uint32_t alignment, - const struct lttng_ust_ctl_field *fields, size_t nr_fields, - size_t *iter_field, size_t nesting) -{ - const struct lttng_ust_ctl_field *variant = &fields[*iter_field]; - uint32_t i; - int ret; - char identifier[LTTNG_UST_ABI_SYM_NAME_LEN]; - - if (variant->type.atype != lttng_ust_ctl_atype_variant) { - ret = -EINVAL; - goto end; - } - (*iter_field)++; - sanitize_ctf_identifier(identifier, tag_name); - if (alignment) { - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "struct { } align(%u) _%s_padding;\n", - alignment * CHAR_BIT, - variant->name); - if (ret) { - goto end; - } - } - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "variant <_%s> {\n", - identifier); - if (ret) { - goto end; - } - - for (i = 0; i < nr_choices; i++) { - if (*iter_field >= nr_fields) { - ret = -EOVERFLOW; - goto end; - } - ret = _lttng_field_statedump(session, - fields, nr_fields, - iter_field, nesting + 1); - if (ret) { - goto end; - } - } - sanitize_ctf_identifier(identifier, variant->name); - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "} _%s;\n", - identifier); - if (ret) { - goto end; - } -end: - return ret; -} - -static -int _lttng_field_statedump(struct ust_registry_session *session, - const struct lttng_ust_ctl_field *fields, size_t nr_fields, - size_t *iter_field, size_t nesting) -{ - int ret = 0; - const char *bo_be = " byte_order = be;"; - const char *bo_le = " byte_order = le;"; - const char *bo_native = ""; - const char *bo_reverse; - const struct lttng_ust_ctl_field *field; - - if (*iter_field >= nr_fields) { - ret = -EOVERFLOW; - goto end; - } - field = &fields[*iter_field]; - - if (session->byte_order == BIG_ENDIAN) { - bo_reverse = bo_le; - } else { - bo_reverse = bo_be; - } - - switch (field->type.atype) { - case lttng_ust_ctl_atype_integer: - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n", - field->type.u.integer.size, - field->type.u.integer.alignment, - field->type.u.integer.signedness, - (field->type.u.integer.encoding == lttng_ust_ctl_encode_none) - ? "none" - : (field->type.u.integer.encoding == lttng_ust_ctl_encode_UTF8) - ? "UTF8" - : "ASCII", - field->type.u.integer.base, - field->type.u.integer.reverse_byte_order ? bo_reverse : bo_native, - field->name); - (*iter_field)++; - break; - case lttng_ust_ctl_atype_enum: - ret = ust_metadata_enum_statedump(session, - field->type.u.legacy.basic.enumeration.name, - field->type.u.legacy.basic.enumeration.id, - &field->type.u.legacy.basic.enumeration.container_type, - field->name, iter_field, nesting); - break; - case lttng_ust_ctl_atype_float: - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n", - field->type.u._float.exp_dig, - field->type.u._float.mant_dig, - field->type.u._float.alignment, - field->type.u._float.reverse_byte_order ? bo_reverse : bo_native, - field->name); - (*iter_field)++; - break; - case lttng_ust_ctl_atype_array: - { - const struct lttng_ust_ctl_basic_type *elem_type; - - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - elem_type = &field->type.u.legacy.array.elem_type; - /* Only integers are currently supported in arrays. */ - if (elem_type->atype != lttng_ust_ctl_atype_integer) { - ret = -EINVAL; - goto end; - } - ret = lttng_metadata_printf(session, - "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n", - elem_type->u.basic.integer.size, - elem_type->u.basic.integer.alignment, - elem_type->u.basic.integer.signedness, - (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none) - ? "none" - : (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8) - ? "UTF8" - : "ASCII", - elem_type->u.basic.integer.base, - elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native, - field->name, field->type.u.legacy.array.length); - (*iter_field)++; - break; - } - case lttng_ust_ctl_atype_array_nestable: - { - uint32_t array_length; - const struct lttng_ust_ctl_field *array_nestable; - const struct lttng_ust_ctl_type *elem_type; - - array_length = field->type.u.array_nestable.length; - (*iter_field)++; - - if (*iter_field >= nr_fields) { - ret = -EOVERFLOW; - goto end; - } - array_nestable = &fields[*iter_field]; - elem_type = &array_nestable->type; - - /* Only integers are currently supported in arrays. */ - if (elem_type->atype != lttng_ust_ctl_atype_integer) { - ret = -EINVAL; - goto end; - } - - if (field->type.u.array_nestable.alignment) { - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "struct { } align(%u) _%s_padding;\n", - field->type.u.array_nestable.alignment * CHAR_BIT, - field->name); - if (ret) { - goto end; - } - } - - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n", - elem_type->u.integer.size, - elem_type->u.integer.alignment, - elem_type->u.integer.signedness, - (elem_type->u.integer.encoding == lttng_ust_ctl_encode_none) - ? "none" - : (elem_type->u.integer.encoding == lttng_ust_ctl_encode_UTF8) - ? "UTF8" - : "ASCII", - elem_type->u.integer.base, - elem_type->u.integer.reverse_byte_order ? bo_reverse : bo_native, - field->name, array_length); - (*iter_field)++; - break; - } - case lttng_ust_ctl_atype_sequence: - { - const struct lttng_ust_ctl_basic_type *elem_type; - const struct lttng_ust_ctl_basic_type *length_type; - - elem_type = &field->type.u.legacy.sequence.elem_type; - length_type = &field->type.u.legacy.sequence.length_type; - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - - /* Only integers are currently supported in sequences. */ - if (elem_type->atype != lttng_ust_ctl_atype_integer) { - ret = -EINVAL; - goto end; - } - - ret = lttng_metadata_printf(session, - "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n", - length_type->u.basic.integer.size, - (unsigned int) length_type->u.basic.integer.alignment, - length_type->u.basic.integer.signedness, - (length_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none) - ? "none" - : ((length_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8) - ? "UTF8" - : "ASCII"), - length_type->u.basic.integer.base, - length_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native, - field->name); - if (ret) { - goto end; - } - - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n", - elem_type->u.basic.integer.size, - (unsigned int) elem_type->u.basic.integer.alignment, - elem_type->u.basic.integer.signedness, - (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none) - ? "none" - : ((elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8) - ? "UTF8" - : "ASCII"), - elem_type->u.basic.integer.base, - elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native, - field->name, - field->name); - (*iter_field)++; - break; - } - case lttng_ust_ctl_atype_sequence_nestable: - { - const struct lttng_ust_ctl_field *sequence_nestable; - const struct lttng_ust_ctl_type *elem_type; - - (*iter_field)++; - if (*iter_field >= nr_fields) { - ret = -EOVERFLOW; - goto end; - } - sequence_nestable = &fields[*iter_field]; - elem_type = &sequence_nestable->type; - - /* Only integers are currently supported in sequences. */ - if (elem_type->atype != lttng_ust_ctl_atype_integer) { - ret = -EINVAL; - goto end; - } - - if (field->type.u.sequence_nestable.alignment) { - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "struct { } align(%u) _%s_padding;\n", - field->type.u.sequence_nestable.alignment * CHAR_BIT, - field->name); - if (ret) { - goto end; - } - } - - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ _%s ];\n", - elem_type->u.integer.size, - (unsigned int) elem_type->u.integer.alignment, - elem_type->u.integer.signedness, - (elem_type->u.integer.encoding == lttng_ust_ctl_encode_none) - ? "none" - : ((elem_type->u.integer.encoding == lttng_ust_ctl_encode_UTF8) - ? "UTF8" - : "ASCII"), - elem_type->u.integer.base, - elem_type->u.integer.reverse_byte_order ? bo_reverse : bo_native, - field->name, - field->type.u.sequence_nestable.length_name); - (*iter_field)++; - break; - } - case lttng_ust_ctl_atype_string: - /* Default encoding is UTF8 */ - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "string%s _%s;\n", - field->type.u.string.encoding == lttng_ust_ctl_encode_ASCII ? - " { encoding = ASCII; }" : "", - field->name); - (*iter_field)++; - break; - case lttng_ust_ctl_atype_variant: - ret = _lttng_variant_statedump(session, - field->type.u.legacy.variant.nr_choices, - field->type.u.legacy.variant.tag_name, - 0, - fields, nr_fields, iter_field, nesting); - if (ret) { - goto end; - } - break; - case lttng_ust_ctl_atype_variant_nestable: - ret = _lttng_variant_statedump(session, - field->type.u.variant_nestable.nr_choices, - field->type.u.variant_nestable.tag_name, - field->type.u.variant_nestable.alignment, - fields, nr_fields, iter_field, nesting); - if (ret) { - goto end; - } - break; - case lttng_ust_ctl_atype_struct: - if (field->type.u.legacy._struct.nr_fields != 0) { - /* Currently only 0-length structures are supported. */ - ret = -EINVAL; - goto end; - } - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - ret = lttng_metadata_printf(session, - "struct {} _%s;\n", - field->name); - (*iter_field)++; - break; - case lttng_ust_ctl_atype_struct_nestable: - if (field->type.u.struct_nestable.nr_fields != 0) { - /* Currently only 0-length structures are supported. */ - ret = -EINVAL; - goto end; - } - ret = print_tabs(session, nesting); - if (ret) { - goto end; - } - if (field->type.u.struct_nestable.alignment) { - ret = lttng_metadata_printf(session, - "struct {} align(%u) _%s;\n", - field->type.u.struct_nestable.alignment * CHAR_BIT, - field->name); - if (ret) { - goto end; - } - } else { - ret = lttng_metadata_printf(session, - "struct {} _%s;\n", - field->name); - } - (*iter_field)++; - break; - case lttng_ust_ctl_atype_enum_nestable: - { - const struct lttng_ust_ctl_field *container_field; - const struct lttng_ust_ctl_type *container_type; - - (*iter_field)++; - if (*iter_field >= nr_fields) { - ret = -EOVERFLOW; - goto end; - } - container_field = &fields[*iter_field]; - container_type = &container_field->type; - - /* Only integers are supported as container types. */ - if (container_type->atype != lttng_ust_ctl_atype_integer) { - ret = -EINVAL; - goto end; - } - ret = ust_metadata_enum_statedump(session, - field->type.u.enum_nestable.name, - field->type.u.enum_nestable.id, - &container_type->u.integer, - field->name, iter_field, nesting); - break; - } - default: - ret = -EINVAL; - } -end: - return ret; -} - -static -int _lttng_context_metadata_statedump(struct ust_registry_session *session, - size_t nr_ctx_fields, - struct lttng_ust_ctl_field *ctx) -{ - int ret = 0; - size_t i = 0; - - if (!ctx) - return 0; - for (;;) { - if (i >= nr_ctx_fields) { - break; - } - ret = _lttng_field_statedump(session, ctx, - nr_ctx_fields, &i, 2); - if (ret) { - break; - } - } - return ret; -} - -static -int _lttng_fields_metadata_statedump(struct ust_registry_session *session, - struct ust_registry_event *event) -{ - int ret = 0; - size_t i = 0; - - for (;;) { - if (i >= event->nr_fields) { - break; - } - ret = _lttng_field_statedump(session, event->fields, - event->nr_fields, &i, 2); - if (ret) { - break; - } - } - return ret; -} - -/* - * Should be called with session registry mutex held. - */ -int ust_metadata_event_statedump(struct ust_registry_session *session, - struct ust_registry_channel *chan, - struct ust_registry_event *event) -{ - int ret = 0; - - /* Don't dump metadata events */ - if (chan->chan_id == -1U) - return 0; - - ret = lttng_metadata_printf(session, - "event {\n" - " name = \"%s\";\n" - " id = %u;\n" - " stream_id = %u;\n", - event->name, - event->id, - chan->chan_id); - if (ret) { - goto end; - } - - ret = lttng_metadata_printf(session, - " loglevel = %d;\n", - event->loglevel_value); - if (ret) { - goto end; - } - - if (event->model_emf_uri) { - ret = lttng_metadata_printf(session, - " model.emf.uri = \"%s\";\n", - event->model_emf_uri); - if (ret) { - goto end; - } - } - - ret = lttng_metadata_printf(session, - " fields := struct {\n" - ); - if (ret) { - goto end; - } - - ret = _lttng_fields_metadata_statedump(session, event); - if (ret) { - goto end; - } - - ret = lttng_metadata_printf(session, - " };\n" - "};\n\n"); - if (ret) { - goto end; - } - event->metadata_dumped = 1; - -end: - return ret; -} - -/* - * Should be called with session registry mutex held. - */ -int ust_metadata_channel_statedump(struct ust_registry_session *session, - struct ust_registry_channel *chan) -{ - int ret = 0; - - /* Don't dump metadata events */ - if (chan->chan_id == -1U) - return 0; - - if (!chan->header_type) - return -EINVAL; - - ret = lttng_metadata_printf(session, - "stream {\n" - " id = %u;\n" - " event.header := %s;\n" - " packet.context := struct packet_context;\n", - chan->chan_id, - chan->header_type == LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT ? - "struct event_header_compact" : - "struct event_header_large"); - if (ret) { - goto end; - } - - if (chan->ctx_fields) { - ret = lttng_metadata_printf(session, - " event.context := struct {\n"); - if (ret) { - goto end; - } - } - ret = _lttng_context_metadata_statedump(session, - chan->nr_ctx_fields, - chan->ctx_fields); - if (ret) { - goto end; - } - if (chan->ctx_fields) { - ret = lttng_metadata_printf(session, - " };\n"); - if (ret) { - goto end; - } - } - - ret = lttng_metadata_printf(session, - "};\n\n"); - /* Flag success of metadata dump. */ - chan->metadata_dumped = 1; - -end: - return ret; -} - -static -int _lttng_stream_packet_context_declare(struct ust_registry_session *session) -{ - return lttng_metadata_printf(session, - "struct packet_context {\n" - " uint64_clock_monotonic_t timestamp_begin;\n" - " uint64_clock_monotonic_t timestamp_end;\n" - " uint64_t content_size;\n" - " uint64_t packet_size;\n" - " uint64_t packet_seq_num;\n" - " unsigned long events_discarded;\n" - " uint32_t cpu_id;\n" - "};\n\n" - ); -} - -/* - * Compact header: - * id: range: 0 - 30. - * id 31 is reserved to indicate an extended header. - * - * Large header: - * id: range: 0 - 65534. - * id 65535 is reserved to indicate an extended header. - */ -static -int _lttng_event_header_declare(struct ust_registry_session *session) -{ - return lttng_metadata_printf(session, - "struct event_header_compact {\n" - " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n" - " variant {\n" - " struct {\n" - " uint27_clock_monotonic_t timestamp;\n" - " } compact;\n" - " struct {\n" - " uint32_t id;\n" - " uint64_clock_monotonic_t timestamp;\n" - " } extended;\n" - " } v;\n" - "} align(%u);\n" - "\n" - "struct event_header_large {\n" - " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n" - " variant {\n" - " struct {\n" - " uint32_clock_monotonic_t timestamp;\n" - " } compact;\n" - " struct {\n" - " uint32_t id;\n" - " uint64_clock_monotonic_t timestamp;\n" - " } extended;\n" - " } v;\n" - "} align(%u);\n\n", - session->uint32_t_alignment, - session->uint16_t_alignment - ); -} - -/* - * The offset between monotonic and realtime clock can be negative if - * the system sets the REALTIME clock to 0 after boot. - */ -static -int measure_single_clock_offset(struct offset_sample *sample) -{ - uint64_t monotonic_avg, monotonic[2], measure_delta, realtime; - uint64_t tcf = trace_clock_freq(); - struct timespec rts = { 0, 0 }; - int ret; - - monotonic[0] = trace_clock_read64(); - ret = lttng_clock_gettime(CLOCK_REALTIME, &rts); - if (ret < 0) { - return ret; - } - monotonic[1] = trace_clock_read64(); - measure_delta = monotonic[1] - monotonic[0]; - if (measure_delta > sample->measure_delta) { - /* - * Discard value if it took longer to read than the best - * sample so far. - */ - return 0; - } - monotonic_avg = (monotonic[0] + monotonic[1]) >> 1; - realtime = (uint64_t) rts.tv_sec * tcf; - if (tcf == NSEC_PER_SEC) { - realtime += rts.tv_nsec; - } else { - realtime += (uint64_t) rts.tv_nsec * tcf / NSEC_PER_SEC; - } - sample->offset = (int64_t) realtime - monotonic_avg; - sample->measure_delta = measure_delta; - return 0; -} - -/* - * Approximation of NTP time of day to clock monotonic correlation, - * taken at start of trace. Keep the measurement that took the less time - * to complete, thus removing imprecision caused by preemption. - * May return a negative offset. - */ -static -int64_t measure_clock_offset(void) -{ - int i; - struct offset_sample offset_best_sample = { - .offset = 0, - .measure_delta = UINT64_MAX, - }; - - for (i = 0; i < NR_CLOCK_OFFSET_SAMPLES; i++) { - if (measure_single_clock_offset(&offset_best_sample)) { - return 0; - } - } - return offset_best_sample.offset; -} - -static -int print_metadata_session_information(struct ust_registry_session *registry) -{ - int ret; - struct ltt_session *session = NULL; - char creation_datetime[ISO8601_STR_LEN]; - - rcu_read_lock(); - session = session_find_by_id(registry->tracing_id); - if (!session) { - ret = -1; - goto error; - } - - /* Print the trace name */ - ret = lttng_metadata_printf(registry, " trace_name = \""); - if (ret) { - goto error; - } - - /* - * This is necessary since the creation time is present in the session - * name when it is generated. - */ - if (session->has_auto_generated_name) { - ret = print_escaped_ctf_string(registry, DEFAULT_SESSION_NAME); - } else { - ret = print_escaped_ctf_string(registry, session->name); - } - if (ret) { - goto error; - } - - ret = lttng_metadata_printf(registry, "\";\n"); - if (ret) { - goto error; - } - - /* Prepare creation time */ - ret = time_to_iso8601_str(session->creation_time, creation_datetime, - sizeof(creation_datetime)); - if (ret) { - goto error; - } - - /* Output the reste of the information */ - ret = lttng_metadata_printf(registry, - " trace_creation_datetime = \"%s\";\n" - " hostname = \"%s\";\n", - creation_datetime, session->hostname); - if (ret) { - goto error; - } - -error: - if (session) { - session_put(session); - } - rcu_read_unlock(); - return ret; -} - -static -int print_metadata_app_information(struct ust_registry_session *registry, - struct ust_app *app) -{ - int ret; - char datetime[ISO8601_STR_LEN]; - - if (!app) { - ret = 0; - goto end; - } - - ret = time_to_iso8601_str( - app->registration_time, datetime, sizeof(datetime)); - if (ret) { - goto end; - } - - ret = lttng_metadata_printf(registry, - " tracer_patchlevel = %u;\n" - " vpid = %d;\n" - " procname = \"%s\";\n" - " vpid_datetime = \"%s\";\n", - app->version.patchlevel, (int) app->pid, app->name, - datetime); - -end: - return ret; -} - -/* - * Should be called with session registry mutex held. - */ -int ust_metadata_session_statedump(struct ust_registry_session *session, - struct ust_app *app, - uint32_t major, - uint32_t minor) -{ - char uuid_s[LTTNG_UUID_STR_LEN], - clock_uuid_s[LTTNG_UUID_STR_LEN]; - int ret = 0; - - LTTNG_ASSERT(session); - - lttng_uuid_to_str(session->uuid, uuid_s); - - /* For crash ABI */ - ret = lttng_metadata_printf(session, - "/* CTF %u.%u */\n\n", - CTF_SPEC_MAJOR, - CTF_SPEC_MINOR); - if (ret) { - goto end; - } - - ret = lttng_metadata_printf(session, - "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n" - "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n" - "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n" - "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n" - "typealias integer { size = %u; align = %u; signed = false; } := unsigned long;\n" - "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n" - "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n" - "\n" - "trace {\n" - " major = %u;\n" - " minor = %u;\n" - " uuid = \"%s\";\n" - " byte_order = %s;\n" - " packet.header := struct {\n" - " uint32_t magic;\n" - " uint8_t uuid[16];\n" - " uint32_t stream_id;\n" - " uint64_t stream_instance_id;\n" - " };\n" - "};\n\n", - session->uint8_t_alignment, - session->uint16_t_alignment, - session->uint32_t_alignment, - session->uint64_t_alignment, - session->bits_per_long, - session->long_alignment, - CTF_SPEC_MAJOR, - CTF_SPEC_MINOR, - uuid_s, - session->byte_order == BIG_ENDIAN ? "be" : "le" - ); - if (ret) { - goto end; - } - - ret = lttng_metadata_printf(session, - "env {\n" - " domain = \"ust\";\n" - " tracer_name = \"lttng-ust\";\n" - " tracer_major = %u;\n" - " tracer_minor = %u;\n" - " tracer_buffering_scheme = \"%s\";\n" - " tracer_buffering_id = %u;\n" - " architecture_bit_width = %u;\n", - major, - minor, - app ? "pid" : "uid", - app ? (int) app->pid : (int) session->tracing_uid, - session->bits_per_long); - if (ret) { - goto end; - } - - ret = print_metadata_session_information(session); - if (ret) { - goto end; - } - - /* - * If per-application registry, we can output extra information - * about the application. - */ - ret = print_metadata_app_information(session, app); - if (ret) { - goto end; - } - - ret = lttng_metadata_printf(session, - "};\n\n" - ); - if (ret) { - goto end; - } - - ret = lttng_metadata_printf(session, - "clock {\n" - " name = \"%s\";\n", - trace_clock_name() - ); - if (ret) { - goto end; - } - - if (!trace_clock_uuid(clock_uuid_s)) { - ret = lttng_metadata_printf(session, - " uuid = \"%s\";\n", - clock_uuid_s - ); - if (ret) { - goto end; - } - } - - ret = lttng_metadata_printf(session, - " description = \"%s\";\n" - " freq = %" PRIu64 "; /* Frequency, in Hz */\n" - " /* clock value offset from Epoch is: offset * (1/freq) */\n" - " offset = %" PRId64 ";\n" - "};\n\n", - trace_clock_description(), - trace_clock_freq(), - measure_clock_offset() - ); - if (ret) { - goto end; - } - - ret = lttng_metadata_printf(session, - "typealias integer {\n" - " size = 27; align = 1; signed = false;\n" - " map = clock.%s.value;\n" - "} := uint27_clock_monotonic_t;\n" - "\n" - "typealias integer {\n" - " size = 32; align = %u; signed = false;\n" - " map = clock.%s.value;\n" - "} := uint32_clock_monotonic_t;\n" - "\n" - "typealias integer {\n" - " size = 64; align = %u; signed = false;\n" - " map = clock.%s.value;\n" - "} := uint64_clock_monotonic_t;\n\n", - trace_clock_name(), - session->uint32_t_alignment, - trace_clock_name(), - session->uint64_t_alignment, - trace_clock_name() - ); - if (ret) { - goto end; - } - - ret = _lttng_stream_packet_context_declare(session); - if (ret) { - goto end; - } - - ret = _lttng_event_header_declare(session); - if (ret) { - goto end; - } - -end: - return ret; -}