return _type;
}
+ enum relayd_trace_format relayd_type() const
+ {
+ switch (_type) {
+ case LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1:
+ return RELAYD_TRACE_FORMAT_CTF_1;
+ case LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2:
+ return RELAYD_TRACE_FORMAT_CTF_2;
+ default:
+ /* TODO/FIXME: throw??? */
+ abort();
+ }
+ }
virtual lttng_error_code mi_serialize(mi_writer *writer) const final;
virtual lttng_error_code config_serialize(config_writer *writer) const final;
virtual int serialize(lttng_payload *payload) const;
cmd-2-2.cpp cmd-2-2.hpp \
cmd-2-4.cpp cmd-2-4.hpp \
cmd-2-11.cpp cmd-2-11.hpp \
+ cmd-2-15.cpp cmd-2-15.hpp \
health-relayd.cpp health-relayd.hpp \
lttng-viewer-abi.hpp testpoint.hpp \
viewer-stream.hpp viewer-stream.cpp \
--- /dev/null
+/*
+ * Copyright (C) 2018 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <inttypes.h>
+
+#include <common/common.hpp>
+#include <common/sessiond-comm/relayd.hpp>
+
+#include <common/compat/endian.hpp>
+#include <common/compat/string.hpp>
+#include <lttng/constant.h>
+
+#include "cmd-2-15.hpp"
+#include "utils.hpp"
+
+int cmd_create_session_2_15(const struct lttng_buffer_view *payload,
+ char *session_name,
+ char *hostname,
+ char *base_path,
+ uint32_t *live_timer,
+ bool *snapshot,
+ uint64_t *id_sessiond,
+ lttng_uuid& sessiond_uuid,
+ bool *has_current_chunk,
+ uint64_t *current_chunk_id,
+ time_t *creation_time,
+ bool *session_name_contains_creation_time,
+ relayd_trace_format& trace_format)
+{
+ int ret;
+ struct lttcomm_relayd_create_session_2_15 header;
+ size_t header_len, received_names_size, offset;
+ struct lttng_buffer_view session_name_view;
+ struct lttng_buffer_view hostname_view;
+ struct lttng_buffer_view base_path_view;
+
+ header_len = sizeof(header);
+
+ if (payload->size < header_len) {
+ ERR("Unexpected payload size in \"cmd_create_session_2_15\": expected >= %zu bytes, got %zu bytes",
+ header_len, payload->size);
+ ret = -1;
+ goto error;
+ }
+ memcpy(&header, payload->data, header_len);
+
+ header.session_name_len = be32toh(header.session_name_len);
+ header.hostname_len = be32toh(header.hostname_len);
+ header.base_path_len = be32toh(header.base_path_len);
+ header.live_timer = be32toh(header.live_timer);
+ header.current_chunk_id.value = be64toh(header.current_chunk_id.value);
+ header.current_chunk_id.is_set = !!header.current_chunk_id.is_set;
+ header.creation_time = be64toh(header.creation_time);
+ header.session_id = be64toh(header.session_id);
+
+ std::copy(std::begin(header.sessiond_uuid), std::end(header.sessiond_uuid),
+ sessiond_uuid.begin());
+
+ received_names_size = header.session_name_len + header.hostname_len + header.base_path_len;
+ if (payload->size < header_len + received_names_size) {
+ ERR("Unexpected payload size in \"cmd_create_session_2_15\": expected >= %zu bytes, got %zu bytes",
+ header_len + received_names_size, payload->size);
+ ret = -1;
+ goto error;
+ }
+
+ /* Validate length against defined constant. */
+ if (header.session_name_len > LTTNG_NAME_MAX) {
+ ret = -ENAMETOOLONG;
+ ERR("Length of session name (%" PRIu32
+ " bytes) received in create_session command exceeds maximum length (%d bytes)",
+ header.session_name_len, LTTNG_NAME_MAX);
+ goto error;
+ } else if (header.session_name_len == 0) {
+ ret = -EINVAL;
+ ERR("Illegal session name length of 0 received");
+ goto error;
+ }
+ if (header.hostname_len > LTTNG_HOST_NAME_MAX) {
+ ret = -ENAMETOOLONG;
+ ERR("Length of hostname (%" PRIu32
+ " bytes) received in create_session command exceeds maximum length (%d bytes)",
+ header.hostname_len, LTTNG_HOST_NAME_MAX);
+ goto error;
+ }
+ if (header.base_path_len > LTTNG_PATH_MAX) {
+ ret = -ENAMETOOLONG;
+ ERR("Length of base_path (%" PRIu32
+ " bytes) received in create_session command exceeds maximum length (%d bytes)",
+ header.base_path_len, PATH_MAX);
+ goto error;
+ }
+
+ offset = header_len;
+ session_name_view = lttng_buffer_view_from_view(payload, offset, header.session_name_len);
+ if (!lttng_buffer_view_is_valid(&session_name_view)) {
+ ERR("Invalid payload in \"cmd_create_session_2_15\": buffer too short to contain session name");
+ ret = -1;
+ goto error;
+ }
+
+ offset += header.session_name_len;
+ hostname_view = lttng_buffer_view_from_view(payload, offset, header.hostname_len);
+ if (!lttng_buffer_view_is_valid(&hostname_view)) {
+ ERR("Invalid payload in \"cmd_create_session_2_15\": buffer too short to contain hostname");
+ ret = -1;
+ goto error;
+ }
+
+ offset += header.hostname_len;
+ base_path_view = lttng_buffer_view_from_view(payload, offset, header.base_path_len);
+ if (header.base_path_len > 0 && !lttng_buffer_view_is_valid(&base_path_view)) {
+ ERR("Invalid payload in \"cmd_create_session_2_15\": buffer too short to contain base path");
+ ret = -1;
+ goto error;
+ }
+
+ /* Validate that names are NULL terminated. */
+ if (session_name_view.data[session_name_view.size - 1] != '\0') {
+ ERR("cmd_create_session_2_15 session_name is invalid (not NULL terminated)");
+ ret = -1;
+ goto error;
+ }
+
+ if (hostname_view.data[hostname_view.size - 1] != '\0') {
+ ERR("cmd_create_session_2_15 hostname is invalid (not NULL terminated)");
+ ret = -1;
+ goto error;
+ }
+
+ if (base_path_view.size != 0 && base_path_view.data[base_path_view.size - 1] != '\0') {
+ ERR("cmd_create_session_2_15 base_path is invalid (not NULL terminated)");
+ ret = -1;
+ goto error;
+ }
+
+ /*
+ * Length and null-termination check are already performed.
+ * LTTNG_NAME_MAX, LTTNG_HOST_NAME_MAX, and LTTNG_PATH_MAX max sizes are
+ * expected.
+ */
+ strcpy(session_name, session_name_view.data);
+ strcpy(hostname, hostname_view.data);
+ strcpy(base_path, base_path_view.size ? base_path_view.data : "");
+
+ *live_timer = header.live_timer;
+ *snapshot = !!header.snapshot;
+ *current_chunk_id = header.current_chunk_id.value;
+ *has_current_chunk = header.current_chunk_id.is_set;
+ *creation_time = (time_t) header.creation_time;
+ *session_name_contains_creation_time = header.session_name_contains_creation_time;
+ *id_sessiond = header.session_id;
+ trace_format = static_cast<enum relayd_trace_format>(header.trace_format);
+
+ ret = 0;
+
+error:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2022 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef RELAYD_CMD_2_15_H
+#define RELAYD_CMD_2_15_H
+
+#include "lttng-relayd.hpp"
+#include <common/buffer-view.hpp>
+#include <common/uuid.hpp>
+#include <lttng/trace-format-descriptor-internal.hpp>
+
+int cmd_create_session_2_15(const struct lttng_buffer_view *payload,
+ char *session_name,
+ char *hostname,
+ char *base_path,
+ uint32_t *live_timer,
+ bool *snapshot,
+ uint64_t *id_sessiond,
+ lttng_uuid& sessiond_uuid,
+ bool *has_current_chunk,
+ uint64_t *current_chunk_id,
+ time_t *creation_time,
+ bool *session_name_contains_creation_time,
+ relayd_trace_format& trace_format);
+
+#endif /* RELAYD_CMD_2_15_H */
*/
#include "cmd-2-1.hpp"
+#include "cmd-2-11.hpp"
+#include "cmd-2-15.hpp"
#include "cmd-2-2.hpp"
#include "cmd-2-4.hpp"
-#include "cmd-2-11.hpp"
#endif /* RELAYD_CMD_H */
*/
#define _LGPL_SOURCE
+#include <algorithm>
+#include <ctype.h>
+#include <fcntl.h>
#include <getopt.h>
#include <grp.h>
+#include <inttypes.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <sys/resource.h>
-#include <inttypes.h>
+#include <unistd.h>
#include <urcu/futex.h>
-#include <urcu/uatomic.h>
#include <urcu/rculist.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <strings.h>
-#include <ctype.h>
-#include <algorithm>
+#include <urcu/uatomic.h>
-#include <lttng/lttng.h>
+#include <common/align.hpp>
+#include <common/buffer-view.hpp>
#include <common/common.hpp>
-#include <common/compat/poll.hpp>
-#include <common/compat/socket.hpp>
#include <common/compat/endian.hpp>
#include <common/compat/getenv.hpp>
-#include <common/defaults.hpp>
+#include <common/compat/poll.hpp>
+#include <common/compat/socket.hpp>
#include <common/daemonize.hpp>
+#include <common/defaults.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/fd-tracker/fd-tracker.hpp>
+#include <common/fd-tracker/utils.hpp>
#include <common/futex.hpp>
-#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/ini-config/ini-config.hpp>
+#include <common/path.hpp>
#include <common/sessiond-comm/inet.hpp>
#include <common/sessiond-comm/relayd.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/string-utils/format.hpp>
#include <common/uri.hpp>
#include <common/utils.hpp>
-#include <common/path.hpp>
-#include <common/align.hpp>
-#include <common/ini-config/ini-config.hpp>
-#include <common/dynamic-buffer.hpp>
-#include <common/buffer-view.hpp>
-#include <common/string-utils/format.hpp>
-#include <common/fd-tracker/fd-tracker.hpp>
-#include <common/fd-tracker/utils.hpp>
+#include <lttng/lttng.h>
+#include <lttng/trace-format-descriptor-internal.hpp>
#include "backward-compatibility-group-by.hpp"
#include "cmd.hpp"
*
* On success, send back the session id or else return a negative value.
*/
-static int relay_create_session(
- const struct lttcomm_relayd_hdr *recv_hdr __attribute__((unused)),
+static int relay_create_session(const struct lttcomm_relayd_hdr *recv_hdr __attribute__((unused)),
struct relay_connection *conn,
const struct lttng_buffer_view *payload)
{
int ret = 0;
+ enum lttng_error_code ret_code;
ssize_t send_ret;
struct relay_session *session = NULL;
- struct lttcomm_relayd_create_session_reply_2_11 reply = {};
+ lttcomm_relayd_create_session_reply_2_15 reply = {};
char session_name[LTTNG_NAME_MAX] = {};
char hostname[LTTNG_HOST_NAME_MAX] = {};
uint32_t live_timer = 0;
LTTNG_OPTIONAL(uint64_t) id_sessiond = {};
LTTNG_OPTIONAL(uint64_t) current_chunk_id = {};
LTTNG_OPTIONAL(time_t) creation_time = {};
+ /* The default trace format is CTF1 */
+ enum relayd_trace_format trace_format = RELAYD_TRACE_FORMAT_CTF_1;
+
struct lttng_dynamic_buffer reply_payload;
lttng_dynamic_buffer_init(&reply_payload);
ret = 0;
} else if (conn->minor >= 4 && conn->minor < 11) {
/* From 2.4 to 2.10 */
- ret = cmd_create_session_2_4(payload, session_name,
- hostname, &live_timer, &snapshot);
- } else {
+ ret = cmd_create_session_2_4(
+ payload, session_name, hostname, &live_timer, &snapshot);
+ } else if (conn->minor >= 11 && conn->minor < 15) {
+ /* From 2.11 to 2.15 */
bool has_current_chunk;
uint64_t current_chunk_id_value;
time_t creation_time_value;
if (lttng_uuid_is_nil(sessiond_uuid)) {
/* The nil UUID is reserved for pre-2.11 clients. */
ERR("Illegal nil UUID announced by peer in create session command");
- ret = -1;
+ ret_code = LTTNG_ERR_FATAL;
+ goto send_reply;
+ }
+ LTTNG_OPTIONAL_SET(&id_sessiond, id_sessiond_value);
+ LTTNG_OPTIONAL_SET(&creation_time, creation_time_value);
+ if (has_current_chunk) {
+ LTTNG_OPTIONAL_SET(¤t_chunk_id, current_chunk_id_value);
+ }
+ } else {
+ /* From 2.15 to ... */
+ bool has_current_chunk;
+ uint64_t current_chunk_id_value;
+ time_t creation_time_value;
+ uint64_t id_sessiond_value;
+
+ /* From 2.11 to ... */
+ ret = cmd_create_session_2_15(payload, session_name, hostname, base_path,
+ &live_timer, &snapshot, &id_sessiond_value, sessiond_uuid,
+ &has_current_chunk, ¤t_chunk_id_value, &creation_time_value,
+ &session_name_contains_creation_timestamp, trace_format);
+ if (lttng_uuid_is_nil(sessiond_uuid)) {
+ /* The nil UUID is reserved for pre-2.11 clients. */
+ ERR("Illegal nil UUID announced by peer in create session command");
+ ret_code = LTTNG_ERR_FATAL;
goto send_reply;
}
+
LTTNG_OPTIONAL_SET(&id_sessiond, id_sessiond_value);
LTTNG_OPTIONAL_SET(&creation_time, creation_time_value);
if (has_current_chunk) {
}
if (ret < 0) {
+ ret_code = LTTNG_ERR_FATAL;
+ goto send_reply;
+ }
+
+ /*
+ * Trace format check. TODO: move to a separate function or inside
+ * session create?
+ */
+ if (trace_format == RELAYD_TRACE_FORMAT_CTF_2 && !opt_allow_ctf2) {
+ ret_code = LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_RELAY_DAEMON;
goto send_reply;
}
- session = session_create(session_name, hostname, base_path, live_timer,
- snapshot, sessiond_uuid,
- id_sessiond.is_set ? &id_sessiond.value : NULL,
+ session = session_create(session_name, hostname, base_path, live_timer, snapshot,
+ sessiond_uuid, id_sessiond.is_set ? &id_sessiond.value : NULL,
current_chunk_id.is_set ? ¤t_chunk_id.value : NULL,
- creation_time.is_set ? &creation_time.value : NULL,
- conn->major, conn->minor,
- session_name_contains_creation_timestamp);
+ creation_time.is_set ? &creation_time.value : NULL, conn->major,
+ conn->minor, session_name_contains_creation_timestamp, trace_format);
if (!session) {
- ret = -1;
+ ret_code = LTTNG_ERR_FATAL;
goto send_reply;
}
+
LTTNG_ASSERT(!conn->session);
conn->session = session;
DBG("Created session %" PRIu64, session->id);
reply.generic.session_id = htobe64(session->id);
+ ret_code = LTTNG_OK;
send_reply:
- if (ret < 0) {
- reply.generic.ret_code = htobe32(LTTNG_ERR_FATAL);
- } else {
- reply.generic.ret_code = htobe32(LTTNG_OK);
- }
+ reply.generic.ret_code = htobe32(ret_code);
if (conn->minor < 11) {
/* From 2.1 to 2.10 */
goto end;
}
} else {
- const uint32_t output_path_length =
- session ? strlen(session->output_path) + 1 : 0;
+ /* From 2.11 to ... */
+ const uint32_t output_path_length = session ? strlen(session->output_path) + 1 : 0;
reply.output_path_length = htobe32(output_path_length);
ret = lttng_dynamic_buffer_append(
* Return allocated session or else NULL.
*/
struct relay_session *session_create(const char *session_name,
- const char *hostname, const char *base_path,
+ const char *hostname,
+ const char *base_path,
uint32_t live_timer,
bool snapshot,
const lttng_uuid& sessiond_uuid,
const time_t *creation_time,
uint32_t major,
uint32_t minor,
- bool session_name_contains_creation_time)
+ bool session_name_contains_creation_time,
+ enum relayd_trace_format trace_format)
{
int ret;
struct relay_session *session = NULL;
session->major = major;
session->minor = minor;
+ session->trace_format = trace_format;
session->live_timer = live_timer;
session->snapshot = snapshot;
*
*/
-#include <limits.h>
#include <inttypes.h>
+#include <limits.h>
#include <pthread.h>
#include <urcu/list.h>
#include <urcu/ref.h>
-#include <lttng/constant.h>
#include <common/hashtable/hashtable.hpp>
-#include <common/uuid.hpp>
-#include <common/trace-chunk.hpp>
#include <common/optional.hpp>
+#include <common/sessiond-comm/relayd.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/uuid.hpp>
+#include <lttng/constant.h>
/*
* Represents a session for the relay point of view
*/
bool ongoing_rotation;
struct lttng_directory_handle *output_directory;
+ enum relayd_trace_format trace_format;
struct rcu_head rcu_node; /* For call_rcu teardown. */
};
struct relay_session *session_create(const char *session_name,
- const char *hostname, const char *base_path,
+ const char *hostname,
+ const char *base_path,
uint32_t live_timer,
bool snapshot,
const lttng_uuid& sessiond_uuid,
const time_t *creation_time,
uint32_t major,
uint32_t minor,
- bool session_name_contains_creation_timestamp);
+ bool session_name_contains_creation_timestamp,
+ enum relayd_trace_format trace_format);
struct relay_session *session_get_by_id(uint64_t id);
bool session_get(struct relay_session *session);
void session_put(struct relay_session *session);
*
* Returns LTTNG_OK on success or an LTTng error code on failure.
*/
-static enum lttng_error_code send_consumer_relayd_socket(unsigned int session_id,
+static enum lttng_error_code send_consumer_relayd_socket(const struct ltt_session& session,
struct lttng_uri *relayd_uri,
struct consumer_output *consumer,
struct consumer_socket *consumer_sock,
- const char *session_name,
- const char *hostname,
- const char *base_path,
- int session_live_timer,
+ const char *base_path_override,
const uint64_t *current_chunk_id,
- time_t session_creation_time,
- bool session_name_contains_creation_time,
struct lttcomm_relayd_sock& rsock)
{
int ret;
/* Send relayd socket to consumer. */
ret = consumer_send_relayd_socket(consumer_sock, &rsock, consumer, relayd_uri->stype,
- session_id, session_name, hostname, base_path, session_live_timer,
- current_chunk_id, session_creation_time,
- session_name_contains_creation_time);
+ session, base_path_override, current_chunk_id);
if (ret < 0) {
status = LTTNG_ERR_ENABLE_CONSUMER_FAIL;
goto error;
static lttng_error_code send_consumer_relayd_sockets(const ltt_session& session,
struct consumer_output *consumer,
struct consumer_socket *sock,
- const char *base_path,
+ const char *base_path_override,
const uint64_t *current_chunk_id)
{
enum lttng_error_code status = LTTNG_OK;
goto error;
}
- status = send_consumer_relayd_socket(session.id, &consumer->dst.net.control,
- consumer, sock, session.name, session.hostname, base_path,
- session.live_timer, current_chunk_id, session.creation_time,
- session.name_contains_creation_time, *control_sock);
+ status = send_consumer_relayd_socket(session, &consumer->dst.net.control, consumer,
+ sock, base_path_override, current_chunk_id, *control_sock);
if (status != LTTNG_OK) {
goto error;
}
LTTNG_ASSERT(data_sock);
- status = send_consumer_relayd_socket(session.id, &consumer->dst.net.data, consumer,
- sock, session.name, session.hostname, base_path, session.live_timer,
- current_chunk_id, session.creation_time,
- session.name_contains_creation_time, *data_sock);
+ status = send_consumer_relayd_socket(session, &consumer->dst.net.data, consumer,
+ sock, base_path_override, current_chunk_id, *data_sock);
if (status != LTTNG_OK) {
goto error;
cds_lfht_for_each_entry (
usess->consumer->socks->ht, &iter.iter, socket, node.node) {
pthread_mutex_lock(socket->lock);
- ret = send_consumer_relayd_sockets(*session, usess->consumer, socket,
- session->base_path,
+ ret = send_consumer_relayd_sockets(*session, usess->consumer, socket, NULL,
current_chunk_id.is_set ? ¤t_chunk_id.value : NULL);
pthread_mutex_unlock(socket->lock);
if (ret != LTTNG_OK) {
cds_lfht_for_each_entry (
ksess->consumer->socks->ht, &iter.iter, socket, node.node) {
pthread_mutex_lock(socket->lock);
- ret = send_consumer_relayd_sockets(*session, ksess->consumer, socket,
- session->base_path,
+ ret = send_consumer_relayd_sockets(*session, ksess->consumer, socket, NULL,
current_chunk_id.is_set ? ¤t_chunk_id.value : NULL);
pthread_mutex_unlock(socket->lock);
if (ret != LTTNG_OK) {
struct lttng_ht_iter iter;
struct consumer_socket *socket;
LTTNG_OPTIONAL(uint64_t) current_chunk_id = {};
- const char *base_path;
+ const char *base_path_override = NULL;
LTTNG_ASSERT(output);
LTTNG_ASSERT(session);
* base path.
*/
if (output->dst.net.control.subdir[0] != '\0') {
- base_path = output->dst.net.control.subdir;
- } else {
- base_path = session->base_path;
+ base_path_override = output->dst.net.control.subdir;
}
/*
rcu_read_lock();
cds_lfht_for_each_entry (output->socks->ht, &iter.iter, socket, node.node) {
pthread_mutex_lock(socket->lock);
- status = send_consumer_relayd_sockets(*session, output, socket, base_path,
+ status = send_consumer_relayd_sockets(*session, output, socket, base_path_override,
current_chunk_id.is_set ? ¤t_chunk_id.value : NULL);
pthread_mutex_unlock(socket->lock);
if (status != LTTNG_OK) {
goto end;
}
- if (!(supported_trace_format & trace_format->relayd_type())) {
+ if (!is_trace_format_configuration_supported(
+ supported_trace_format, *trace_format)) {
ERR("Relayd does not support the requested trace format");
ret_code = LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_RELAY_DAEMON;
goto end;
* On success return positive value. On error, negative value.
*/
int consumer_send_relayd_socket(struct consumer_socket *consumer_sock,
- struct lttcomm_relayd_sock *rsock, struct consumer_output *consumer,
- enum lttng_stream_type type, uint64_t session_id,
- const char *session_name, const char *hostname,
- const char *base_path, int session_live_timer,
- const uint64_t *current_chunk_id, time_t session_creation_time,
- bool session_name_contains_creation_time)
+ struct lttcomm_relayd_sock *rsock,
+ struct consumer_output *consumer,
+ enum lttng_stream_type type,
+ const struct ltt_session& session,
+ const char *base_path_override,
+ const uint64_t *current_chunk_id)
{
int ret;
int fd;
LTTNG_ASSERT(consumer);
LTTNG_ASSERT(consumer_sock);
+ const char *base_path = base_path_override != NULL ? base_path_override : session.base_path;
+
memset(&msg, 0, sizeof(msg));
/* Bail out if consumer is disabled */
if (!consumer->enabled) {
char output_path[LTTNG_PATH_MAX] = {};
uint64_t relayd_session_id;
- ret = relayd_create_session(rsock, &relayd_session_id,
- session_name, hostname, base_path,
- session_live_timer, consumer->snapshot,
- session_id, the_sessiond_uuid, current_chunk_id,
- session_creation_time,
- session_name_contains_creation_time,
- output_path);
+ ret = relayd_create_session(rsock, &relayd_session_id, session.name,
+ session.hostname, base_path, session.live_timer, consumer->snapshot,
+ session.id, the_sessiond_uuid, current_chunk_id,
+ session.creation_time, session.name_contains_creation_time,
+ output_path, *session.trace_format);
if (ret < 0) {
/* Close the control socket. */
(void) relayd_close(rsock);
*/
msg.u.relayd_sock.net_index = consumer->net_seq_index;
msg.u.relayd_sock.type = type;
- msg.u.relayd_sock.session_id = session_id;
+ msg.u.relayd_sock.session_id = session.id;
msg.u.relayd_sock.major = rsock->major;
msg.u.relayd_sock.minor = rsock->minor;
msg.u.relayd_sock.relayd_socket_protocol = rsock->sock.proto;
int consumer_send_stream(struct consumer_socket *sock,
struct consumer_output *dst, struct lttcomm_consumer_msg *msg,
const int *fds, size_t nb_fd);
-int consumer_send_channel(struct consumer_socket *sock,
- struct lttcomm_consumer_msg *msg);
+int consumer_send_channel(struct consumer_socket *sock, struct lttcomm_consumer_msg *msg);
int consumer_send_relayd_socket(struct consumer_socket *consumer_sock,
- struct lttcomm_relayd_sock *rsock, struct consumer_output *consumer,
- enum lttng_stream_type type, uint64_t session_id,
- const char *session_name, const char *hostname,
- const char *base_path, int session_live_timer,
- const uint64_t *current_chunk_id, time_t session_creation_time,
- bool session_name_contains_creation_time);
-int consumer_send_channel_monitor_pipe(struct consumer_socket *consumer_sock,
- int pipe);
-int consumer_send_destroy_relayd(struct consumer_socket *sock,
- struct consumer_output *consumer);
+ struct lttcomm_relayd_sock *rsock,
+ struct consumer_output *consumer,
+ enum lttng_stream_type type,
+ const struct ltt_session& session,
+ const char *base_path_override,
+ const uint64_t *current_chunk_id);
+int consumer_send_channel_monitor_pipe(struct consumer_socket *consumer_sock, int pipe);
+int consumer_send_destroy_relayd(struct consumer_socket *sock, struct consumer_output *consumer);
int consumer_recv_status_reply(struct consumer_socket *sock);
int consumer_recv_status_channel(struct consumer_socket *sock,
uint64_t *key, unsigned int *stream_count);
#include <common/sessiond-comm/relayd.hpp>
#include <common/string-utils/format.hpp>
#include <common/trace-chunk.hpp>
+#include <lttng/trace-format-descriptor-internal.hpp>
#include "relayd.hpp"
return ret;
}
+/*
+ * Starting from 2.15, the trace format for the session is sent to lttng-relayd
+ * on creation.
+ * */
+static int relayd_create_session_2_15(struct lttcomm_relayd_sock *rsock,
+ const char *session_name,
+ const char *hostname,
+ const char *base_path,
+ int session_live_timer,
+ unsigned int snapshot,
+ uint64_t sessiond_session_id,
+ const lttng_uuid& sessiond_uuid,
+ const uint64_t *current_chunk_id,
+ time_t creation_time,
+ bool session_name_contains_creation_time,
+ lttcomm_relayd_create_session_reply_2_15 *reply,
+ char *output_path,
+ const lttng::trace_format_descriptor& trace_format)
+{
+ int ret;
+ struct lttcomm_relayd_create_session_2_15 *msg = NULL;
+ size_t session_name_len;
+ size_t hostname_len;
+ size_t base_path_len;
+ size_t msg_length;
+ char *dst;
+
+ if (!base_path) {
+ base_path = "";
+ }
+ /* The three names are sent with a '\0' delimiter between them. */
+ session_name_len = strlen(session_name) + 1;
+ hostname_len = strlen(hostname) + 1;
+ base_path_len = strlen(base_path) + 1;
+
+ msg_length = sizeof(*msg) + session_name_len + hostname_len + base_path_len;
+ msg = zmalloc<lttcomm_relayd_create_session_2_15>(msg_length);
+ if (!msg) {
+ PERROR("zmalloc create_session_2_11 command message");
+ ret = -1;
+ goto error;
+ }
+
+ LTTNG_ASSERT(session_name_len <= UINT32_MAX);
+ msg->session_name_len = htobe32(session_name_len);
+
+ LTTNG_ASSERT(hostname_len <= UINT32_MAX);
+ msg->hostname_len = htobe32(hostname_len);
+
+ LTTNG_ASSERT(base_path_len <= UINT32_MAX);
+ msg->base_path_len = htobe32(base_path_len);
+
+ dst = msg->names;
+ if (lttng_strncpy(dst, session_name, session_name_len)) {
+ ret = -1;
+ goto error;
+ }
+ dst += session_name_len;
+ if (lttng_strncpy(dst, hostname, hostname_len)) {
+ ret = -1;
+ goto error;
+ }
+ dst += hostname_len;
+ if (lttng_strncpy(dst, base_path, base_path_len)) {
+ ret = -1;
+ goto error;
+ }
+
+ msg->live_timer = htobe32(session_live_timer);
+ msg->snapshot = !!snapshot;
+
+ std::copy(sessiond_uuid.begin(), sessiond_uuid.end(), msg->sessiond_uuid);
+ msg->session_id = htobe64(sessiond_session_id);
+ msg->session_name_contains_creation_time = session_name_contains_creation_time;
+ msg->trace_format = (uint8_t) trace_format.relayd_type();
+ if (current_chunk_id) {
+ LTTNG_OPTIONAL_SET(&msg->current_chunk_id, htobe64(*current_chunk_id));
+ }
+
+ msg->creation_time = htobe64((uint64_t) creation_time);
+
+ /* Send command */
+ ret = send_command(rsock, RELAYD_CREATE_SESSION, msg, msg_length, 0);
+ if (ret < 0) {
+ goto error;
+ }
+ /* Receive response */
+ ret = recv_reply(rsock, reply, sizeof(*reply));
+ if (ret < 0) {
+ goto error;
+ }
+ reply->generic.session_id = be64toh(reply->generic.session_id);
+ reply->generic.ret_code = be32toh(reply->generic.ret_code);
+ reply->output_path_length = be32toh(reply->output_path_length);
+ if (reply->output_path_length >= LTTNG_PATH_MAX) {
+ ERR("Invalid session output path length in reply (%" PRIu32
+ " bytes) exceeds maximal allowed length (%d bytes)",
+ reply->output_path_length, LTTNG_PATH_MAX);
+ ret = -1;
+ goto error;
+ }
+ ret = recv_reply(rsock, output_path, reply->output_path_length);
+ if (ret < 0) {
+ goto error;
+ }
+error:
+ free(msg);
+ return ret;
+}
+
/*
* Starting from 2.11, RELAYD_CREATE_SESSION payload (session_name,
* hostname, and base_path) have no length restriction on the sender side.
*/
int relayd_create_session(struct lttcomm_relayd_sock *rsock,
uint64_t *relayd_session_id,
- const char *session_name, const char *hostname,
- const char *base_path, int session_live_timer,
- unsigned int snapshot, uint64_t sessiond_session_id,
+ const char *session_name,
+ const char *hostname,
+ const char *base_path,
+ int session_live_timer,
+ unsigned int snapshot,
+ uint64_t sessiond_session_id,
const lttng_uuid& sessiond_uuid,
const uint64_t *current_chunk_id,
- time_t creation_time, bool session_name_contains_creation_time,
- char *output_path)
+ time_t creation_time,
+ bool session_name_contains_creation_time,
+ char *output_path,
+ lttng::trace_format_descriptor& trace_format)
{
int ret;
- struct lttcomm_relayd_create_session_reply_2_11 reply = {};
+ lttcomm_relayd_create_session_reply_2_15 reply = {};
LTTNG_ASSERT(rsock);
LTTNG_ASSERT(relayd_session_id);
ret = relayd_create_session_2_1(rsock, &reply.generic);
} else if (rsock->minor >= 4 && rsock->minor < 11) {
/* From 2.4 to 2.10 */
- ret = relayd_create_session_2_4(rsock, session_name,
- hostname, session_live_timer, snapshot,
- &reply.generic);
+ ret = relayd_create_session_2_4(rsock, session_name, hostname, session_live_timer,
+ snapshot, &reply.generic);
+ } else if (rsock->minor < 15) {
+ /* From 2.11 to 2.14 */
+ ret = relayd_create_session_2_11(rsock, session_name, hostname, base_path,
+ session_live_timer, snapshot, sessiond_session_id, sessiond_uuid,
+ current_chunk_id, creation_time,
+ session_name_contains_creation_time, &reply, output_path);
} else {
- /* From 2.11 to ... */
- ret = relayd_create_session_2_11(rsock, session_name,
- hostname, base_path, session_live_timer, snapshot,
- sessiond_session_id, sessiond_uuid,
+ ret = relayd_create_session_2_15(rsock, session_name, hostname, base_path,
+ session_live_timer, snapshot, sessiond_session_id, sessiond_uuid,
current_chunk_id, creation_time,
- session_name_contains_creation_time,
- &reply, output_path);
+ session_name_contains_creation_time, &reply, output_path,
+ trace_format);
}
if (ret < 0) {
#ifndef _RELAYD_H
#define _RELAYD_H
-#include <unistd.h>
#include <stdbool.h>
+#include <unistd.h>
+#include <common/dynamic-array.hpp>
#include <common/sessiond-comm/relayd.hpp>
#include <common/sessiond-comm/sessiond-comm.hpp>
#include <common/trace-chunk.hpp>
-#include <common/dynamic-array.hpp>
+#include <lttng/trace-format-descriptor-internal.hpp>
struct relayd_stream_rotation_position {
uint64_t stream_id;
int relayd_close(struct lttcomm_relayd_sock *sock);
int relayd_create_session(struct lttcomm_relayd_sock *rsock,
uint64_t *relayd_session_id,
- const char *session_name, const char *hostname,
- const char *base_path, int session_live_timer,
- unsigned int snapshot, uint64_t sessiond_session_id,
+ const char *session_name,
+ const char *hostname,
+ const char *base_path,
+ int session_live_timer,
+ unsigned int snapshot,
+ uint64_t sessiond_session_id,
const lttng_uuid& sessiond_uuid,
const uint64_t *current_chunk_id,
- time_t creation_time, bool session_name_contains_creation_time,
- char *output_path);
-int relayd_add_stream(struct lttcomm_relayd_sock *sock, const char *channel_name,
- const char *domain_name, const char *pathname, uint64_t *stream_id,
- uint64_t tracefile_size, uint64_t tracefile_count,
+ time_t creation_time,
+ bool session_name_contains_creation_time,
+ char *output_path,
+ lttng::trace_format_descriptor& trace_format);
+int relayd_add_stream(struct lttcomm_relayd_sock *sock,
+ const char *channel_name,
+ const char *domain_name,
+ const char *pathname,
+ uint64_t *stream_id,
+ uint64_t tracefile_size,
+ uint64_t tracefile_count,
struct lttng_trace_chunk *trace_chunk);
int relayd_streams_sent(struct lttcomm_relayd_sock *rsock);
int relayd_send_close_stream(struct lttcomm_relayd_sock *sock, uint64_t stream_id,
char output_path[];
} LTTNG_PACKED;
+enum relayd_trace_format {
+ RELAYD_TRACE_FORMAT_CTF_1 = 0,
+ RELAYD_TRACE_FORMAT_CTF_2 = 1,
+};
+
+typedef struct lttcomm_relayd_create_session_reply_2_11 lttcomm_relayd_create_session_reply_2_15;
+
+struct lttcomm_relayd_create_session_2_15 {
+ uint32_t session_name_len;
+ uint32_t hostname_len;
+ /* Optional, set to 0 to indicate it is not user-specified. */
+ uint32_t base_path_len;
+ uint32_t live_timer;
+ uint8_t snapshot;
+ uint8_t session_name_contains_creation_time;
+ /* Sessiond instance UUID */
+ uint8_t sessiond_uuid[LTTNG_UUID_LEN];
+ /* Sessiond session id */
+ uint64_t session_id;
+ /* Session creation time, in seconds since UNIX Epoch. */
+ uint64_t creation_time;
+ /* Trace format: enum relayd_trace_format */
+ uint8_t trace_format;
+ LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED current_chunk_id;
+ /* Contains the session_name, hostname, base_path. */
+ char names[];
+} LTTNG_PACKED;
+
/*
* Used to ask the relay to reset the metadata trace file (regeneration).
* Send the new version of the metadata (starts at 0).