*/
#define _LGPL_SOURCE
-#include <stdint.h>
-#include <string.h>
+#include <inttypes.h>
+#include <limits.h>
#include <stdarg.h>
+#include <stdint.h>
#include <stdio.h>
-#include <limits.h>
+#include <string.h>
#include <unistd.h>
-#include <inttypes.h>
+#include <vector>
+
#include <common/common.hpp>
+#include <common/exception.hpp>
#include <common/time.hpp>
-#include <vector>
+#include <common/uuid.hpp>
-#include "ust-registry.hpp"
-#include "ust-clock.hpp"
#include "ust-app.hpp"
-
-#define NR_CLOCK_OFFSET_SAMPLES 10
-
-namespace {
-struct offset_sample {
- /* correlation offset */
- int64_t offset;
- /* lower is better */
- uint64_t measure_delta;
-};
-} /* namespace */
+#include "ust-clock.hpp"
+#include "ust-registry.hpp"
static
-int _lttng_field_statedump(struct ust_registry_session *session,
+int _lttng_field_statedump(ust_registry_session *session,
const struct lttng_ust_ctl_field *fields, size_t nr_fields,
size_t *iter_field, size_t nesting);
* 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)
+ssize_t metadata_reserve(ust_registry_session *session, size_t len)
{
- size_t new_len = session->metadata_len + 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;
+ size_t old_alloc_len = session->_metadata_alloc_len;
ssize_t ret;
if (new_alloc_len > (UINT32_MAX >> 1))
new_alloc_len =
std::max<size_t>(1U << get_count_order(new_alloc_len), old_alloc_len << 1);
- newptr = (char *) realloc(session->metadata, new_alloc_len);
+ newptr = (char *) realloc(session->_metadata, new_alloc_len);
if (!newptr)
return -ENOMEM;
- session->metadata = newptr;
+ 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;
+ 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;
+ ret = session->_metadata_len;
+ session->_metadata_len += len;
return ret;
}
static
-int metadata_file_append(struct ust_registry_session *session,
+int metadata_file_append(ust_registry_session *session,
const char *str, size_t len)
{
ssize_t written;
- if (session->metadata_fd < 0) {
+ if (session->_metadata_fd < 0) {
return 0;
}
/* Write to metadata file */
- written = lttng_write(session->metadata_fd, str, len);
+ written = lttng_write(session->_metadata_fd, str, len);
if (written != len) {
return -1;
}
* protects us from concurrent writes.
*/
static ATTR_FORMAT_PRINTF(2, 3)
-int lttng_metadata_printf(struct ust_registry_session *session,
+int lttng_metadata_printf(ust_registry_session *session,
const char *fmt, ...)
{
char *str = NULL;
ret = offset;
goto end;
}
- memcpy(&session->metadata[offset], str, len);
+ memcpy(&session->_metadata[offset], str, len);
ret = metadata_file_append(session, str, len);
if (ret) {
PERROR("Error appending to metadata file");
}
static
-int print_tabs(struct ust_registry_session *session, size_t nesting)
+int print_tabs(ust_registry_session *session, size_t nesting)
{
size_t i;
}
static
-int print_escaped_ctf_string(struct ust_registry_session *session, const char *string)
+int print_escaped_ctf_string(ust_registry_session *session, const char *string)
{
int ret = 0;
size_t i;
/* Called with session registry mutex held. */
static
-int ust_metadata_enum_statedump(struct ust_registry_session *session,
+int ust_metadata_enum_statedump(ust_registry_session *session,
const char *enum_name,
uint64_t enum_id,
const struct lttng_ust_ctl_integer_type *container_type,
}
static
-int _lttng_variant_statedump(struct ust_registry_session *session,
+int _lttng_variant_statedump(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,
}
static
-int _lttng_field_statedump(struct ust_registry_session *session,
+int _lttng_field_statedump(ust_registry_session *session,
const struct lttng_ust_ctl_field *fields, size_t nr_fields,
size_t *iter_field, size_t nesting)
{
}
field = &fields[*iter_field];
- if (session->byte_order == BIG_ENDIAN) {
+ if (session->_byte_order == BIG_ENDIAN) {
bo_reverse = bo_le;
} else {
bo_reverse = bo_be;
}
static
-int _lttng_context_metadata_statedump(struct ust_registry_session *session,
+int _lttng_context_metadata_statedump(ust_registry_session *session,
size_t nr_ctx_fields,
struct lttng_ust_ctl_field *ctx)
{
}
static
-int _lttng_fields_metadata_statedump(struct ust_registry_session *session,
+int _lttng_fields_metadata_statedump(ust_registry_session *session,
struct ust_registry_event *event)
{
int ret = 0;
/*
* Should be called with session registry mutex held.
*/
-int ust_metadata_event_statedump(struct ust_registry_session *session,
+int ust_metadata_event_statedump(ust_registry_session *session,
struct ust_registry_channel *chan,
struct ust_registry_event *event)
{
*
* RCU read lock must be held by the caller.
*/
-int ust_metadata_channel_statedump(struct ust_registry_session *session,
+int ust_metadata_channel_statedump(ust_registry_session *session,
struct ust_registry_channel *chan)
{
int ret;
}
static
-int _lttng_stream_packet_context_declare(struct ust_registry_session *session)
+int _lttng_stream_packet_context_declare(ust_registry_session *session)
{
return lttng_metadata_printf(session,
"struct packet_context {\n"
* id 65535 is reserved to indicate an extended header.
*/
static
-int _lttng_event_header_declare(struct ust_registry_session *session)
+int _lttng_event_header_declare(ust_registry_session *session)
{
return lttng_metadata_printf(session,
"struct event_header_compact {\n"
" } extended;\n"
" } v;\n"
"} align(%u);\n\n",
- session->uint32_t_alignment,
- session->uint16_t_alignment
+ 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 print_metadata_session_information(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);
+ session = session_find_by_id(registry->_tracing_id);
if (!session) {
ret = -1;
goto error;
}
static
-int print_metadata_app_information(struct ust_registry_session *registry,
- struct ust_app *app)
+int print_metadata_app_information(ust_registry_session *registry)
{
- int ret;
- char datetime[ISO8601_STR_LEN];
-
- if (!app) {
- ret = 0;
- goto end;
+ if (registry->get_buffering_scheme() != LTTNG_BUFFER_PER_PID) {
+ return 0;
}
- ret = time_to_iso8601_str(
- app->registration_time, datetime, sizeof(datetime));
+ const auto *per_pid_session = static_cast<const ust_registry_session_per_pid *>(registry);
+
+ char datetime[ISO8601_STR_LEN];
+ int ret = time_to_iso8601_str(
+ per_pid_session->_app_creation_time, datetime, sizeof(datetime));
if (ret) {
- goto end;
+ return ret;
}
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:
+ " tracer_patchlevel = %u;\n"
+ " vpid = %d;\n"
+ " procname = \"%s\";\n"
+ " vpid_datetime = \"%s\";\n",
+ per_pid_session->_tracer_patch_level_version, (int) per_pid_session->_vpid,
+ per_pid_session->_procname.c_str(), datetime);
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)
+int ust_metadata_session_statedump(ust_registry_session *session)
{
- char uuid_s[LTTNG_UUID_STR_LEN],
- clock_uuid_s[LTTNG_UUID_STR_LEN];
int ret = 0;
+ char trace_uuid_str[LTTNG_UUID_STR_LEN];
LTTNG_ASSERT(session);
- lttng_uuid_to_str(session->uuid, uuid_s);
+ lttng_uuid_to_str(session->_uuid, trace_uuid_str);
/* For crash ABI */
ret = lttng_metadata_printf(session,
" 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,
+ 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"
+ trace_uuid_str,
+ session->_byte_order == BIG_ENDIAN ? "be" : "le"
);
if (ret) {
goto end;
" 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);
+ session->_app_tracer_version_major, session->_app_tracer_version_minor,
+ session->get_buffering_scheme() == LTTNG_BUFFER_PER_PID ? "pid" : "uid",
+ session->get_buffering_scheme() == LTTNG_BUFFER_PER_PID ?
+ (int) static_cast<ust_registry_session_per_pid *>(session)->_vpid :
+ (int) static_cast<ust_registry_session_per_uid *>(session)->_tracing_uid,
+ session->_bits_per_long);
if (ret) {
goto end;
}
* If per-application registry, we can output extra information
* about the application.
*/
- ret = print_metadata_app_information(session, app);
+ ret = print_metadata_app_information(session);
if (ret) {
goto end;
}
goto end;
}
- ret = lttng_metadata_printf(session,
- "clock {\n"
- " name = \"%s\";\n",
- trace_clock_name()
- );
- if (ret) {
- goto end;
- }
+ try {
+ const lttng::ust::clock_attributes_sample clock;
- if (!trace_clock_uuid(clock_uuid_s)) {
ret = lttng_metadata_printf(session,
- " uuid = \"%s\";\n",
- clock_uuid_s
- );
+ "clock {\n"
+ " name = \"%s\";\n",
+ clock._name.c_str());
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;
- }
+ if (clock._uuid) {
+ char clock_uuid_str[LTTNG_UUID_STR_LEN];
- 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) {
+ lttng_uuid_to_str(*clock._uuid, clock_uuid_str);
+ ret = lttng_metadata_printf(
+ session, " uuid = \"%s\";\n", clock_uuid_str);
+ 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",
+ clock._description.c_str(), clock._frequency, 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",
+ clock._name.c_str(), session->_uint32_t_alignment,
+ clock._name.c_str(), session->_uint64_t_alignment,
+ clock._name.c_str());
+ if (ret) {
+ goto end;
+ }
+ } catch (const std::exception &ex) {
+ ERR("Failed to serialize clock description: %s", ex.what());
+ ret = -1;
goto end;
}