From dd73d57bb95fae31161ca0781108d166082a06f5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Sat, 7 Apr 2018 16:07:56 -0400 Subject: [PATCH] Extend the rotation API to provide network trace archive locations MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The current lttng-ctl rotation API does not allow a user to differentiate between a network or local trace archive location. The API currently only provides a "path" which is absolute when a local rotation is completed, and relative (to an unknown location) when the trace is streamed to a relay daemon. This change introduces the lttng_trace_archive_location interface to express these locations unambiguously. It is currently only used by the rotation control API, but the intention is to also use it for future interfaces which need to express a location description. Signed-off-by: Jérémie Galarneau --- include/lttng/rotate-internal.h | 26 +++++-- include/lttng/rotation.h | 13 ++-- src/bin/lttng-sessiond/cmd.c | 49 ++++++++++++- src/bin/lttng-sessiond/session.c | 69 ++++++++++++++++++ src/bin/lttng-sessiond/session.h | 9 +++ src/bin/lttng/commands/rotate.c | 116 +++++++++++++++++++++++++++++-- src/lib/lttng-ctl/rotate.c | 59 +++++++++++----- 7 files changed, 302 insertions(+), 39 deletions(-) diff --git a/include/lttng/rotate-internal.h b/include/lttng/rotate-internal.h index f5e4dc950..74c85b0b6 100644 --- a/include/lttng/rotate-internal.h +++ b/include/lttng/rotate-internal.h @@ -69,10 +69,7 @@ struct lttng_rotation_handle { * Where the rotated (readable) trace has been stored when the * rotation is completed. */ - struct { - bool is_set; - char path[LTTNG_PATH_MAX]; - } archive_location; + struct lttng_trace_archive_location *archive_location; }; /* @@ -89,7 +86,26 @@ struct lttng_rotate_session_return { struct lttng_rotation_get_info_return { /* Represents values defined in enum lttng_rotation_state. */ int32_t status; - char path[LTTNG_PATH_MAX]; + /* Represents values defined in enum lttng_rotation_state. */ + uint8_t location_type; + union { + struct { + char absolute_path[LTTNG_PATH_MAX]; + } LTTNG_PACKED local; + struct { + char host[LTTNG_HOST_NAME_MAX]; + /* + * Represents values defined in + * enum lttng_trace_archive_location_relay_protocol_type. + */ + uint8_t protocol; + struct { + uint16_t control; + uint16_t data; + } LTTNG_PACKED ports; + char relative_path[LTTNG_PATH_MAX]; + } LTTNG_PACKED relay; + } location; } LTTNG_PACKED; /* For the LTTNG_SESSION_GET_CURRENT_OUTPUT command. */ diff --git a/include/lttng/rotation.h b/include/lttng/rotation.h index 0b4b2ad2f..dbc0183da 100644 --- a/include/lttng/rotation.h +++ b/include/lttng/rotation.h @@ -20,6 +20,7 @@ #define LTTNG_ROTATION_H #include +#include #ifdef __cplusplus extern "C" { @@ -162,16 +163,14 @@ extern enum lttng_rotation_status lttng_rotation_handle_get_state( * Get the location of the rotation's resulting archive. * * The rotation must be completed in order for this call to succeed. - * The path returned is owned by the rotation handle. + * The location returned remains owned by the rotation handle. * - * Note that path will not be set in case of error, or if the session - * rotation has expired. - * - * FIXME: Return an lttng_location object instead of a path. + * Note that location will not be set in case of error, or if the session + * rotation handle has expired. */ -extern enum lttng_rotation_status lttng_rotation_handle_get_completed_archive_location( +extern enum lttng_rotation_status lttng_rotation_handle_get_archive_location( struct lttng_rotation_handle *rotation_handle, - const char **path); + const struct lttng_trace_archive_location **location); /* * Destroy an lttng_rotate_session handle. diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index e0a8db9b2..534f191a8 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -4635,16 +4635,59 @@ int cmd_rotate_get_info(struct ltt_session *session, rotation_id, session->name); break; case LTTNG_ROTATION_STATE_COMPLETED: - ret = lttng_strncpy(info_return->path, + { + char *current_tracing_path_reply; + size_t current_tracing_path_reply_len; + + switch (session_get_consumer_destination_type(session)) { + case CONSUMER_DST_LOCAL: + current_tracing_path_reply = + info_return->location.local.absolute_path; + current_tracing_path_reply_len = + sizeof(info_return->location.local.absolute_path); + info_return->location_type = + (uint8_t) LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL; + break; + case CONSUMER_DST_NET: + current_tracing_path_reply = + info_return->location.relay.relative_path; + current_tracing_path_reply_len = + sizeof(info_return->location.relay.relative_path); + /* Currently the only supported relay protocol. */ + info_return->location.relay.protocol = + (uint8_t) LTTNG_TRACE_ARCHIVE_LOCATION_RELAY_PROTOCOL_TYPE_TCP; + + ret = lttng_strncpy(info_return->location.relay.host, + session_get_net_consumer_hostname(session), + sizeof(info_return->location.relay.host)); + if (ret) { + ERR("Failed to host name to rotate_get_info reply"); + info_return->status = LTTNG_ROTATION_STATUS_ERROR; + ret = -LTTNG_ERR_UNK; + goto end; + } + + session_get_net_consumer_ports(session, + &info_return->location.relay.ports.control, + &info_return->location.relay.ports.data); + info_return->location_type = + (uint8_t) LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY; + break; + default: + abort(); + } + ret = lttng_strncpy(current_tracing_path_reply, session->rotation_chunk.current_rotate_path, - sizeof(info_return->path)); + current_tracing_path_reply_len); if (ret) { - ERR("Failed to copy active tracing path to rotate_get_info reply"); + ERR("Failed to copy current tracing path to rotate_get_info reply"); info_return->status = LTTNG_ROTATION_STATUS_ERROR; ret = -LTTNG_ERR_UNK; goto end; } + break; + } case LTTNG_ROTATION_STATE_ERROR: DBG("Reporting that an error occurred during rotation %" PRIu64 " of session %s", rotation_id, session->name); diff --git a/src/bin/lttng-sessiond/session.c b/src/bin/lttng-sessiond/session.c index 2b7d65eaa..01cdfdc00 100644 --- a/src/bin/lttng-sessiond/session.c +++ b/src/bin/lttng-sessiond/session.c @@ -31,6 +31,7 @@ #include "session.h" #include "utils.h" +#include "trace-ust.h" /* * NOTES: @@ -141,6 +142,74 @@ void session_unlock_list(void) pthread_mutex_unlock(<t_session_list.lock); } +/* + * Get the session's consumer destination type. + * + * The caller must hold the session lock. + */ +enum consumer_dst_type session_get_consumer_destination_type( + const struct ltt_session *session) +{ + /* + * The output information is duplicated in both of those session types. + * Hence, it doesn't matter from which it is retrieved. However, it is + * possible for only one of them to be set. + */ + return session->kernel_session ? + session->kernel_session->consumer->type : + session->ust_session->consumer->type; +} + +/* + * Get the session's consumer network hostname. + * The caller must ensure that the destination is of type "net". + * + * The caller must hold the session lock. + */ +const char *session_get_net_consumer_hostname(const struct ltt_session *session) +{ + const char *hostname = NULL; + const struct consumer_output *output; + + output = session->kernel_session ? + session->kernel_session->consumer : + session->ust_session->consumer; + + /* + * hostname is assumed to be the same for both control and data + * connections. + */ + switch (output->dst.net.control.dtype) { + case LTTNG_DST_IPV4: + hostname = output->dst.net.control.dst.ipv4; + break; + case LTTNG_DST_IPV6: + hostname = output->dst.net.control.dst.ipv6; + break; + default: + abort(); + } + return hostname; +} + +/* + * Get the session's consumer network control and data ports. + * The caller must ensure that the destination is of type "net". + * + * The caller must hold the session lock. + */ +void session_get_net_consumer_ports(const struct ltt_session *session, + uint16_t *control_port, uint16_t *data_port) +{ + const struct consumer_output *output; + + output = session->kernel_session ? + session->kernel_session->consumer : + session->ust_session->consumer; + *control_port = output->dst.net.control.port; + *data_port = output->dst.net.data.port; +} + /* * Allocate the ltt_sessions_ht_by_id HT. * diff --git a/src/bin/lttng-sessiond/session.h b/src/bin/lttng-sessiond/session.h index ab9b1a9a4..b8c789081 100644 --- a/src/bin/lttng-sessiond/session.h +++ b/src/bin/lttng-sessiond/session.h @@ -27,6 +27,7 @@ #include "snapshot.h" #include "trace-kernel.h" +#include "consumer.h" struct ltt_ust_session; @@ -202,6 +203,14 @@ void session_lock_list(void); void session_unlock(struct ltt_session *session); void session_unlock_list(void); +enum consumer_dst_type session_get_consumer_destination_type( + const struct ltt_session *session); +const char *session_get_net_consumer_hostname( + const struct ltt_session *session); +void session_get_net_consumer_ports( + const struct ltt_session *session, + uint16_t *control_port, uint16_t *data_port); + struct ltt_session *session_find_by_name(const char *name); struct ltt_session *session_find_by_id(uint64_t id); struct ltt_session_list *session_get_list(void); diff --git a/src/bin/lttng/commands/rotate.c b/src/bin/lttng/commands/rotate.c index 5a00d6994..05e55bf3c 100644 --- a/src/bin/lttng/commands/rotate.c +++ b/src/bin/lttng/commands/rotate.c @@ -32,6 +32,7 @@ #include "../command.h" #include +#include static char *opt_session_name; static int opt_no_wait; @@ -100,6 +101,111 @@ end: return ret; } +static int output_trace_archive_location( + const struct lttng_trace_archive_location *location, + const char *session_name) +{ + int ret = 0; + enum lttng_trace_archive_location_type location_type; + enum lttng_trace_archive_location_status status; + bool printed_location = false; + + location_type = lttng_trace_archive_location_get_type(location); + + _MSG("Trace chunk archive for session %s is now readable", + session_name); + switch (location_type) { + case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL: + { + const char *absolute_path; + + status = lttng_trace_archive_location_local_get_absolute_path( + location, &absolute_path); + if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) { + ret = -1; + goto end; + } + MSG(" at %s", absolute_path); + ret = mi_output_rotate("completed", absolute_path, + session_name); + if (ret) { + goto end; + } + printed_location = true; + break; + } + case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY: + { + uint16_t control_port, data_port; + const char *host, *relative_path, *protocol_str; + enum lttng_trace_archive_location_relay_protocol_type protocol; + + /* Fetch all relay location parameters. */ + status = lttng_trace_archive_location_relay_get_protocol_type( + location, &protocol); + if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) { + ret = -1; + goto end; + } + + status = lttng_trace_archive_location_relay_get_host( + location, &host); + if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) { + ret = -1; + goto end; + } + + status = lttng_trace_archive_location_relay_get_control_port( + location, &control_port); + if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) { + ret = -1; + goto end; + } + + status = lttng_trace_archive_location_relay_get_data_port( + location, &data_port); + if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) { + ret = -1; + goto end; + } + + status = lttng_trace_archive_location_relay_get_relative_path( + location, &relative_path); + if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) { + ret = -1; + goto end; + } + + switch (protocol) { + case LTTNG_TRACE_ARCHIVE_LOCATION_RELAY_PROTOCOL_TYPE_TCP: + protocol_str = "tcp"; + break; + default: + protocol_str = "unknown"; + break; + } + + MSG(" on relay %s://%s/%s [control port %" PRIu16 ", data port %" + PRIu16 "]", protocol_str, host, + relative_path, control_port, data_port); + printed_location = true; + ret = mi_output_rotate("completed", relative_path, + session_name); + if (ret) { + goto end; + } + break; + } + default: + break; + } +end: + if (!printed_location) { + MSG(" at an unknown location"); + } + return ret; +} + static int rotate_tracing(char *session_name) { int ret; @@ -176,17 +282,15 @@ static int rotate_tracing(char *session_name) switch (rotation_state) { case LTTNG_ROTATION_STATE_COMPLETED: { - const char *path; + const struct lttng_trace_archive_location *location; - rotation_status = lttng_rotation_handle_get_completed_archive_location( - handle, &path); + rotation_status = lttng_rotation_handle_get_archive_location( + handle, &location); if (rotation_status != LTTNG_ROTATION_STATUS_OK) { ERR("Failed to retrieve the rotation's completed chunk archive location"); goto error; } - MSG("Trace chunk archive for session %s is now readable at %s", - session_name, path); - ret = mi_output_rotate("completed", path, session_name); + ret = output_trace_archive_location(location, session_name); if (ret) { goto error; } diff --git a/src/lib/lttng-ctl/rotate.c b/src/lib/lttng-ctl/rotate.c index 4b7c2f916..bdce8d857 100644 --- a/src/lib/lttng-ctl/rotate.c +++ b/src/lib/lttng-ctl/rotate.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -155,13 +156,39 @@ void lttng_rotation_schedule_attr_set_size( attr->size = size; } +static +struct lttng_trace_archive_location * +create_trace_archive_location_from_get_info( + const struct lttng_rotation_get_info_return *info) +{ + struct lttng_trace_archive_location *location; + + switch (info->location_type) { + case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL: + location = lttng_trace_archive_location_local_create( + info->location.local.absolute_path); + break; + case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY: + location = lttng_trace_archive_location_relay_create( + info->location.relay.host, + info->location.relay.protocol, + info->location.relay.ports.control, + info->location.relay.ports.data, + info->location.relay.relative_path); + break; + default: + location = NULL; + break; + } + return location; +} + enum lttng_rotation_status lttng_rotation_handle_get_state( struct lttng_rotation_handle *rotation_handle, enum lttng_rotation_state *state) { enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK; struct lttng_rotation_get_info_return *info = NULL; - int ret; if (!rotation_handle || !state) { status = LTTNG_ROTATION_STATUS_INVALID; @@ -174,7 +201,7 @@ enum lttng_rotation_status lttng_rotation_handle_get_state( } *state = (enum lttng_rotation_state) info->status; - if (rotation_handle->archive_location.is_set || + if (rotation_handle->archive_location || *state != LTTNG_ROTATION_STATE_COMPLETED) { /* * The path is only provided by the sessiond once @@ -187,35 +214,32 @@ enum lttng_rotation_status lttng_rotation_handle_get_state( * Cache the location since the rotation may expire before the user * has a chance to query it. */ - ret = lttng_strncpy(rotation_handle->archive_location.path, - info->path, - sizeof(rotation_handle->archive_location.path)); - if (ret) { + rotation_handle->archive_location = + create_trace_archive_location_from_get_info(info); + if (!rotation_handle->archive_location) { status = LTTNG_ROTATION_STATUS_ERROR; goto end; } - rotation_handle->archive_location.is_set = true; end: free(info); return status; } -enum lttng_rotation_status lttng_rotation_handle_get_completed_archive_location( +enum lttng_rotation_status lttng_rotation_handle_get_archive_location( struct lttng_rotation_handle *rotation_handle, - const char **path) + const struct lttng_trace_archive_location **location) { - int ret; enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK; struct lttng_rotation_get_info_return *info = NULL; - if (!rotation_handle || !path) { + if (!rotation_handle || !location) { status = LTTNG_ROTATION_STATUS_INVALID; goto end; } /* Use the cached location we got from a previous query. */ - if (rotation_handle->archive_location.is_set) { - *path = rotation_handle->archive_location.path; + if (rotation_handle->archive_location) { + *location = rotation_handle->archive_location; goto end; } @@ -230,14 +254,12 @@ enum lttng_rotation_status lttng_rotation_handle_get_completed_archive_location( goto end; } - ret = lttng_strncpy(rotation_handle->archive_location.path, - info->path, - sizeof(rotation_handle->archive_location.path)); - if (ret) { + rotation_handle->archive_location = + create_trace_archive_location_from_get_info(info); + if (!rotation_handle->archive_location) { status = LTTNG_ROTATION_STATUS_ERROR; goto end; } - rotation_handle->archive_location.is_set = true; end: free(info); return status; @@ -246,6 +268,7 @@ end: void lttng_rotation_handle_destroy( struct lttng_rotation_handle *rotation_handle) { + lttng_trace_archive_location_destroy(rotation_handle->archive_location); free(rotation_handle); } -- 2.34.1