#define _LGPL_SOURCE
#include <algorithm>
+#include <exception>
#include <inttypes.h>
#include <stdio.h>
#include <sys/stat.h>
#include <urcu/list.h>
#include <urcu/uatomic.h>
-#include <common/buffer-view.h>
-#include <common/common.h>
-#include <common/compat/string.h>
-#include <common/defaults.h>
-#include <common/dynamic-buffer.h>
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <common/relayd/relayd.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/string-utils/string-utils.h>
-#include <common/trace-chunk.h>
-#include <common/utils.h>
-
+#include <common/buffer-view.hpp>
+#include <common/common.hpp>
+#include <common/compat/string.hpp>
+#include <common/defaults.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/kernel-ctl/kernel-ctl.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/relayd/relayd.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/string-utils/string-utils.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/utils.hpp>
+#include <lttng/action/action-internal.hpp>
#include <lttng/action/action.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/channel-internal.h>
+#include <lttng/channel-internal.hpp>
#include <lttng/channel.h>
+#include <lttng/condition/condition-internal.hpp>
#include <lttng/condition/condition.h>
-#include <lttng/error-query-internal.h>
-#include <lttng/event-internal.h>
-#include <lttng/location-internal.h>
-#include <lttng/rotate-internal.h>
-#include <lttng/session-descriptor-internal.h>
-#include <lttng/session-internal.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <lttng/userspace-probe-internal.h>
-
-#include "agent-thread.h"
-#include "agent.h"
-#include "buffer-registry.h"
-#include "channel.h"
-#include "cmd.h"
-#include "consumer.h"
-#include "event-notifier-error-accounting.h"
-#include "event.h"
-#include "health-sessiond.h"
-#include "kernel-consumer.h"
-#include "kernel.h"
-#include "lttng-sessiond.h"
-#include "lttng-syscall.h"
-#include "notification-thread-commands.h"
-#include "notification-thread.h"
-#include "rotate.h"
-#include "rotation-thread.h"
-#include "session.h"
-#include "timer.h"
-#include "tracker.h"
-#include "utils.h"
+#include <lttng/condition/event-rule-matches-internal.hpp>
+#include <lttng/condition/event-rule-matches.h>
+#include <lttng/error-query-internal.hpp>
+#include <lttng/event-internal.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/location-internal.hpp>
+#include <lttng/lttng-error.h>
+#include <lttng/rotate-internal.hpp>
+#include <lttng/session-descriptor-internal.hpp>
+#include <lttng/session-internal.hpp>
+#include <lttng/tracker.h>
+#include <lttng/trigger/trigger-internal.hpp>
+#include <lttng/userspace-probe-internal.hpp>
+
+#include "agent-thread.hpp"
+#include "agent.hpp"
+#include "buffer-registry.hpp"
+#include "channel.hpp"
+#include "cmd.hpp"
+#include "consumer.hpp"
+#include "event-notifier-error-accounting.hpp"
+#include "event.hpp"
+#include "health-sessiond.hpp"
+#include "kernel-consumer.hpp"
+#include "kernel.hpp"
+#include "lttng-sessiond.hpp"
+#include "lttng-syscall.hpp"
+#include "notification-thread-commands.hpp"
+#include "notification-thread.hpp"
+#include "rotate.hpp"
+#include "rotation-thread.hpp"
+#include "session.hpp"
+#include "timer.hpp"
+#include "tracker.hpp"
+#include "utils.hpp"
/* Sleep for 100ms between each check for the shm path's deletion. */
#define SESSION_DESTROY_SHM_PATH_CHECK_DELAY_US 100000
+namespace lsu = lttng::sessiond::ust;
+
+static enum lttng_error_code wait_on_path(void *path);
+
+namespace {
struct cmd_destroy_session_reply_context {
int reply_sock_fd;
bool implicit_rotation_on_destroy;
enum lttng_error_code destruction_status;
};
-static enum lttng_error_code wait_on_path(void *path);
-
/*
* Command completion handler that is used by the destroy command
* when a session that has a non-default shm_path is being destroyed.
*
* See comment in cmd_destroy_session() for the rationale.
*/
-static struct destroy_completion_handler {
+struct destroy_completion_handler {
struct cmd_completion_handler handler;
char shm_path[member_sizeof(struct ltt_session, shm_path)];
} destroy_completion_handler = {
.shm_path = { 0 },
};
-static struct cmd_completion_handler *current_completion_handler;
-
/*
* Used to keep a unique index for each relayd socket created where this value
* is associated with streams on the consumer so it can match the right relayd
* to send to. It must be accessed with the relayd_net_seq_idx_lock
* held.
*/
-static pthread_mutex_t relayd_net_seq_idx_lock = PTHREAD_MUTEX_INITIALIZER;
-static uint64_t relayd_net_seq_idx;
+pthread_mutex_t relayd_net_seq_idx_lock = PTHREAD_MUTEX_INITIALIZER;
+uint64_t relayd_net_seq_idx;
+} /* namespace */
+static struct cmd_completion_handler *current_completion_handler;
static int validate_ust_event_name(const char *);
static int cmd_enable_event_internal(struct ltt_session *session,
const struct lttng_domain *domain,
struct lttng_bytecode *filter,
struct lttng_event_exclusion *exclusion,
int wpipe);
-static int cmd_enable_channel_internal(struct ltt_session *session,
+static enum lttng_error_code cmd_enable_channel_internal(
+ struct ltt_session *session,
const struct lttng_domain *domain,
const struct lttng_channel *_attr,
int wpipe);
* On success, the relayd_sock pointer is set to the created socket.
* Else, it remains untouched and an LTTng error code is returned.
*/
-static enum lttng_error_code create_connect_relayd(struct lttng_uri *uri,
- struct lttcomm_relayd_sock **relayd_sock,
- struct consumer_output *consumer)
+static lttng_error_code create_connect_relayd(
+ struct lttng_uri *uri, struct lttcomm_relayd_sock **relayd_sock)
{
int ret;
enum lttng_error_code status = LTTNG_OK;
/* Create socket for control stream. */
if (uri->stype == LTTNG_STREAM_CONTROL) {
- uint64_t result_flags;
-
DBG3("Creating relayd stream socket from URI");
/* Check relayd version */
status = LTTNG_ERR_RELAYD_CONNECT_FAIL;
goto close_sock;
}
- consumer->relay_major_version = rsock->major;
- consumer->relay_minor_version = rsock->minor;
- ret = relayd_get_configuration(rsock, 0,
- &result_flags);
- if (ret < 0) {
- ERR("Unable to get relayd configuration");
- status = LTTNG_ERR_RELAYD_CONNECT_FAIL;
- goto close_sock;
- }
- if (result_flags & LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED) {
- consumer->relay_allows_clear = true;
- }
} else if (uri->stype == LTTNG_STREAM_DATA) {
DBG3("Creating relayd data socket from URI");
} else {
*
* 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(unsigned int session_id,
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 *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)
+ bool session_name_contains_creation_time,
+ struct lttcomm_relayd_sock& rsock)
{
int ret;
- struct lttcomm_relayd_sock *rsock = NULL;
- enum lttng_error_code status;
-
- /* Connect to relayd and make version check if uri is the control. */
- status = create_connect_relayd(relayd_uri, &rsock, consumer);
- if (status != LTTNG_OK) {
- goto relayd_comm_error;
- }
- LTTNG_ASSERT(rsock);
+ enum lttng_error_code status = LTTNG_OK;
/* Set the network sequence index if not set. */
if (consumer->net_seq_index == (uint64_t) -1ULL) {
}
/* 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);
+ 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);
if (ret < 0) {
status = LTTNG_ERR_ENABLE_CONSUMER_FAIL;
- goto close_sock;
+ goto error;
}
/* Flag that the corresponding socket was sent. */
consumer_sock->data_sock_sent = 1;
}
- /*
- * Close socket which was dup on the consumer side. The session daemon does
- * NOT keep track of the relayd socket(s) once transfer to the consumer.
- */
-
-close_sock:
+error:
if (status != LTTNG_OK) {
/*
* The consumer output for this session should not be used anymore
*/
consumer->enabled = 0;
}
- (void) relayd_close(rsock);
- free(rsock);
-relayd_comm_error:
return status;
}
+static bool is_trace_format_configuration_supported(
+ uint64_t supported_trace_format, lttng::trace_format_descriptor& trace_format)
+{
+ static const std::unordered_map<enum lttng_trace_format_descriptor_type,
+ enum lttcomm_relayd_configuration_trace_format_flag>
+ mapping = {
+ {LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1,
+ LTTCOMM_RELAYD_CONFIGURATION_TRACE_FORMAT_SUPPORTED_CTF1},
+ {LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2,
+ LTTCOMM_RELAYD_CONFIGURATION_TRACE_FORMAT_SUPPORTED_CTF2},
+ };
+
+ auto it = mapping.find(trace_format.type());
+ if (it == mapping.end()) {
+ return false;
+ }
+
+ if (!(supported_trace_format & it->second)) {
+ return false;
+ }
+
+ return true;
+}
+
/*
* Send both relayd sockets to a specific consumer and domain. This is a
* helper function to facilitate sending the information to the consumer for a
*
* Returns LTTNG_OK, or an LTTng error code on failure.
*/
-static enum lttng_error_code send_consumer_relayd_sockets(
- unsigned int session_id, struct consumer_output *consumer,
- struct consumer_socket *sock, 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)
+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 uint64_t *current_chunk_id)
{
enum lttng_error_code status = LTTNG_OK;
+ struct lttcomm_relayd_sock *control_sock = nullptr;
+ struct lttcomm_relayd_sock *data_sock = nullptr;
LTTNG_ASSERT(consumer);
LTTNG_ASSERT(sock);
/* Sending control relayd socket. */
if (!sock->control_sock_sent) {
- status = send_consumer_relayd_socket(session_id,
- &consumer->dst.net.control, consumer, sock,
- session_name, hostname, base_path, session_live_timer,
- current_chunk_id, session_creation_time,
- session_name_contains_creation_time);
+ int ret;
+ uint64_t result_flags = 0;
+ uint64_t supported_trace_format = 0;
+ /* Connect to relayd and make version check if uri is the control. */
+ status = create_connect_relayd(&consumer->dst.net.control, &control_sock);
+ if (status != LTTNG_OK) {
+ goto error;
+ }
+ LTTNG_ASSERT(control_sock);
+
+ consumer->relay_major_version = control_sock->major;
+ consumer->relay_minor_version = control_sock->minor;
+
+ ret = relayd_get_configuration(control_sock, 0, result_flags, nullptr);
+ if (ret < 0) {
+ ERR("Unable to get relayd configuration");
+ status = LTTNG_ERR_RELAYD_CONNECT_FAIL;
+ goto error;
+ }
+
+ if (result_flags & LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED) {
+ consumer->relay_allows_clear = true;
+ }
+
+ if (!is_trace_format_configuration_supported(
+ supported_trace_format, *session.trace_format)) {
+ ERR("Relayd does not support the requested trace format");
+ status = LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_RELAY_DAEMON;
+ 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);
+
if (status != LTTNG_OK) {
goto error;
}
/* Sending data relayd socket. */
if (!sock->data_sock_sent) {
- status = send_consumer_relayd_socket(session_id,
- &consumer->dst.net.data, consumer, sock,
- session_name, hostname, base_path, session_live_timer,
- current_chunk_id, session_creation_time,
- session_name_contains_creation_time);
+ /* Connect to relayd and make version check if uri is the control. */
+ status = create_connect_relayd(&consumer->dst.net.data, &data_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);
+
if (status != LTTNG_OK) {
goto error;
}
}
error:
+ if (control_sock != nullptr) {
+ relayd_close(control_sock);
+ free(control_sock);
+ }
+
+ if (data_sock != nullptr) {
+ relayd_close(data_sock);
+ free(data_sock);
+ }
+
return status;
}
if (usess && usess->consumer && usess->consumer->type == CONSUMER_DST_NET
&& usess->consumer->enabled) {
/* For each consumer socket, send relayd sockets */
- cds_lfht_for_each_entry(usess->consumer->socks->ht, &iter.iter,
- socket, node.node) {
+ 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->id,
- usess->consumer, socket,
- session->name, session->hostname,
+ ret = send_consumer_relayd_sockets(*session, usess->consumer, socket,
session->base_path,
- session->live_timer,
- current_chunk_id.is_set ? ¤t_chunk_id.value : NULL,
- session->creation_time,
- session->name_contains_creation_time);
+ current_chunk_id.is_set ? ¤t_chunk_id.value : NULL);
pthread_mutex_unlock(socket->lock);
if (ret != LTTNG_OK) {
goto error;
if (ksess && ksess->consumer && ksess->consumer->type == CONSUMER_DST_NET
&& ksess->consumer->enabled) {
- cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter,
- socket, node.node) {
+ 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->id,
- ksess->consumer, socket,
- session->name, session->hostname,
+ ret = send_consumer_relayd_sockets(*session, ksess->consumer, socket,
session->base_path,
- session->live_timer,
- current_chunk_id.is_set ? ¤t_chunk_id.value : NULL,
- session->creation_time,
- session->name_contains_creation_time);
+ current_chunk_id.is_set ? ¤t_chunk_id.value : NULL);
pthread_mutex_unlock(socket->lock);
if (ret != LTTNG_OK) {
goto error;
return ret;
}
-static int cmd_enable_channel_internal(struct ltt_session *session,
+static enum lttng_error_code kernel_domain_check_trace_format_requirements(
+ const lttng::trace_format_descriptor& descriptor)
+{
+ enum lttng_error_code ret_code = LTTNG_OK;
+ switch (descriptor.type()) {
+ case LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1:
+ /* Supported by all kernel tracer. */
+ break;
+ case LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2:
+ if (!kernel_supports_ctf2()) {
+ ret_code = LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_KERNEL_TRACER;
+ }
+ break;
+ default:
+ abort();
+ }
+ return ret_code;
+}
+
+static enum lttng_error_code cmd_enable_channel_internal(
+ struct ltt_session *session,
const struct lttng_domain *domain,
const struct lttng_channel *_attr,
int wpipe)
{
- int ret;
+ enum lttng_error_code ret_code;
struct ltt_ust_session *usess = session->ust_session;
struct lttng_ht *chan_ht;
size_t len;
attr = lttng_channel_copy(_attr);
if (!attr) {
- ret = -LTTNG_ERR_NOMEM;
+ ret_code = LTTNG_ERR_NOMEM;
goto end;
}
/* Validate channel name */
if (attr->name[0] == '.' ||
memchr(attr->name, '/', len) != NULL) {
- ret = LTTNG_ERR_INVALID_CHANNEL_NAME;
+ ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME;
goto end;
}
attr->name, session->name);
lttng_channel_set_monitor_timer_interval(attr, 0);
}
+
+ ret_code = kernel_domain_check_trace_format_requirements(*session->trace_format);
+ if (ret_code != LTTNG_OK) {
+ WARN("Kernel tracer does not support the configured trace format of session '%s'",
+ session->name);
+ goto error;
+ }
break;
}
case LTTNG_DOMAIN_UST:
case LTTNG_DOMAIN_PYTHON:
if (!agent_tracing_is_enabled()) {
DBG("Attempted to enable a channel in an agent domain but the agent thread is not running");
- ret = LTTNG_ERR_AGENT_TRACING_DISABLED;
+ ret_code = LTTNG_ERR_AGENT_TRACING_DISABLED;
goto error;
}
break;
default:
- ret = LTTNG_ERR_UNKNOWN_DOMAIN;
+ ret_code = LTTNG_ERR_UNKNOWN_DOMAIN;
goto error;
}
* some point in time before. The tracer does not allow it.
*/
if (session->has_been_started) {
- ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
+ ret_code = LTTNG_ERR_TRACE_ALREADY_STARTED;
goto error;
}
/* Enforce mmap output for snapshot sessions. */
attr->attr.output = LTTNG_EVENT_MMAP;
}
- ret = channel_kernel_create(
+ ret_code = channel_kernel_create(
session->kernel_session, attr, wpipe);
if (attr->name[0] != '\0') {
session->kernel_session->has_non_default_channel = 1;
}
} else {
- ret = channel_kernel_enable(session->kernel_session, kchan);
+ ret_code = channel_kernel_enable(session->kernel_session, kchan);
}
- if (ret != LTTNG_OK) {
+ if (ret_code != LTTNG_OK) {
goto error;
}
if (domain->type == LTTNG_DOMAIN_JUL) {
if (strncmp(attr->name, DEFAULT_JUL_CHANNEL_NAME,
LTTNG_SYMBOL_NAME_LEN)) {
- ret = LTTNG_ERR_INVALID_CHANNEL_NAME;
+ ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME;
goto error;
}
} else if (domain->type == LTTNG_DOMAIN_LOG4J) {
if (strncmp(attr->name, DEFAULT_LOG4J_CHANNEL_NAME,
LTTNG_SYMBOL_NAME_LEN)) {
- ret = LTTNG_ERR_INVALID_CHANNEL_NAME;
+ ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME;
goto error;
}
} else if (domain->type == LTTNG_DOMAIN_PYTHON) {
if (strncmp(attr->name, DEFAULT_PYTHON_CHANNEL_NAME,
LTTNG_SYMBOL_NAME_LEN)) {
- ret = LTTNG_ERR_INVALID_CHANNEL_NAME;
+ ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME;
goto error;
}
}
* some point in time before. The tracer does not allow it.
*/
if (session->has_been_started) {
- ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
+ ret_code = LTTNG_ERR_TRACE_ALREADY_STARTED;
goto error;
}
- ret = channel_ust_create(usess, attr, domain->buf_type);
+ ret_code = channel_ust_create(usess, attr, domain->buf_type);
if (attr->name[0] != '\0') {
usess->has_non_default_channel = 1;
}
} else {
- ret = channel_ust_enable(usess, uchan);
+ ret_code = channel_ust_enable(usess, uchan);
}
break;
}
default:
- ret = LTTNG_ERR_UNKNOWN_DOMAIN;
+ ret_code = LTTNG_ERR_UNKNOWN_DOMAIN;
goto error;
}
- if (ret == LTTNG_OK && attr->attr.output != LTTNG_EVENT_MMAP) {
+ if (ret_code == LTTNG_OK && attr->attr.output != LTTNG_EVENT_MMAP) {
session->has_non_mmap_channel = true;
}
error:
rcu_read_unlock();
end:
lttng_channel_destroy(attr);
- return ret;
+ return ret_code;
}
enum lttng_error_code cmd_process_attr_tracker_get_tracking_policy(
ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
goto error;
}
- /* break is _not_ missing here. */
}
+ /* fall through */
case LTTNG_DOMAIN_UST:
{
struct ltt_ust_session *usess = session->ust_session;
}
}
if (filter) {
- filter_a = (lttng_bytecode *) zmalloc(sizeof(*filter_a) + filter->len);
+ filter_a = zmalloc<lttng_bytecode>(sizeof(*filter_a) + filter->len);
if (!filter_a) {
free(filter_expression_a);
ret = LTTNG_ERR_FATAL;
struct lttng_bytecode)
+ filter->len;
- filter_copy = (lttng_bytecode *) zmalloc(filter_size);
+ filter_copy = zmalloc<lttng_bytecode>(filter_size);
if (!filter_copy) {
ret = LTTNG_ERR_NOMEM;
goto error;
goto error;
}
- session->active = 1;
+ session->active = true;
session->rotated_after_last_stop = false;
session->cleared_after_last_stop = false;
if (session->output_traces && !session->current_trace_chunk) {
error:
if (ret == LTTNG_OK) {
/* Flag this after a successful start. */
- session->has_been_started |= 1;
+ session->has_been_started = true;
} else {
- session->active = 0;
+ session->active = false;
/* Restore initial state on error. */
session->rotated_after_last_stop =
session_rotated_after_last_stop;
const char *session_name;
struct ltt_session *new_session = NULL;
enum lttng_session_descriptor_status descriptor_status;
+ const lttng_trace_format_descriptor *trace_format_descriptor = NULL;
+ lttng::trace_format_descriptor::uptr trace_format_descriptor_ptr;
session_lock_list();
if (home_path) {
goto end;
}
- ret_code = session_create(session_name, creds->uid, creds->gid,
+ descriptor_status = lttng_session_descriptor_get_trace_format_descriptor(
+ descriptor, &trace_format_descriptor);
+ if (descriptor_status != LTTNG_SESSION_DESCRIPTOR_STATUS_OK) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ try {
+ trace_format_descriptor_ptr =
+ reinterpret_cast<const lttng::trace_format_descriptor *>(
+ trace_format_descriptor)
+ ->clone();
+ } catch (std::exception& e) {
+ ERR("%s", e.what());
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ ret_code = session_create(session_name, creds->uid, creds->gid, trace_format_descriptor_ptr,
&new_session);
if (ret_code != LTTNG_OK) {
goto end;
}
+ ret_code = notification_thread_command_add_session(the_notification_thread_handle,
+ new_session->id, new_session->name, new_session->uid, new_session->gid);
+ if (ret_code != LTTNG_OK) {
+ goto end;
+ }
+
+ /* Announce the session's destruction to the notification thread when it is destroyed. */
+ ret = session_add_destroy_notifier(
+ new_session,
+ [](const struct ltt_session *session,
+ void *user_data __attribute__((unused))) {
+ (void) notification_thread_command_remove_session(
+ the_notification_thread_handle, session->id);
+ },
+ NULL);
+ if (ret) {
+ PERROR("Failed to add notification thread command to session's destroy notifiers: session name = %s",
+ new_session->name);
+ ret = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
if (!session_name) {
ret = lttng_session_descriptor_set_session_name(descriptor,
new_session->name);
.cmd_header_size =
sizeof(struct lttcomm_session_destroy_command_header),
.data_size = 0,
+ .fd_count = 0,
};
size_t payload_size_before_location;
struct cmd_destroy_session_reply_context *reply_context = NULL;
if (sock_fd) {
- reply_context = (cmd_destroy_session_reply_context *) zmalloc(sizeof(*reply_context));
+ reply_context = zmalloc<cmd_destroy_session_reply_context>();
if (!reply_context) {
ret = LTTNG_ERR_NOMEM;
goto end;
}
+
reply_context->reply_sock_fd = *sock_fd;
}
goto error;
}
- socket->lock = (pthread_mutex_t *) zmalloc(sizeof(pthread_mutex_t));
+ socket->lock = zmalloc<pthread_mutex_t>();
if (socket->lock == NULL) {
PERROR("zmalloc pthread mutex");
ret = LTTNG_ERR_FATAL;
goto error;
}
+
pthread_mutex_init(socket->lock, NULL);
socket->registered = 1;
goto end;
}
- *domains = (lttng_domain *) zmalloc(nb_dom * sizeof(struct lttng_domain));
+ *domains = calloc<lttng_domain>(nb_dom);
if (*domains == NULL) {
ret = LTTNG_ERR_FATAL;
goto error;
* The session list lock MUST be acquired before calling this function. Use
* session_lock_list() and session_unlock_list().
*/
-void cmd_list_lttng_sessions(struct lttng_session *sessions,
- size_t session_count, uid_t uid, gid_t gid)
+enum lttng_error_code cmd_list_lttng_sessions(
+ struct lttng_payload *reply_payload, uid_t uid, gid_t gid)
{
- int ret;
- unsigned int i = 0;
+ int buffer_resize_ret;
+ enum lttng_error_code ret_code = LTTNG_OK;
+ struct lttcomm_list_command_header reply_command_header = {};
+ size_t reply_command_header_offset;
struct ltt_session *session;
struct ltt_session_list *list = session_get_list();
- struct lttng_session_extended *extended =
- (typeof(extended)) (&sessions[session_count]);
+ int ret;
+ unsigned int i = 0;
+
+ assert(reply_payload);
+
+ /* Reserve space for command reply header. */
+ reply_command_header_offset = reply_payload->buffer.size;
+ buffer_resize_ret = lttng_dynamic_buffer_set_size(&reply_payload->buffer,
+ reply_command_header_offset + sizeof(struct lttcomm_list_command_header));
+ if (buffer_resize_ret) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto error;
+ }
DBG("Getting all available session for UID %d GID %d",
uid, gid);
- /*
- * Iterate over session list and append data after the control struct in
- * the buffer.
- */
+
cds_list_for_each_entry(session, &list->head, list) {
+ struct lttng_session tmp_session = {};
+ struct lttng_session_extended tmp_extended = {};
+
+ tmp_session.extended.ptr = &tmp_extended;
+
if (!session_get(session)) {
continue;
}
if (session->consumer->type == CONSUMER_DST_NET ||
(ksess && ksess->consumer->type == CONSUMER_DST_NET) ||
(usess && usess->consumer->type == CONSUMER_DST_NET)) {
- ret = build_network_session_path(sessions[i].path,
- sizeof(sessions[i].path), session);
+ ret = build_network_session_path(
+ tmp_session.path, sizeof(tmp_session.path), session);
} else {
- ret = snprintf(sessions[i].path, sizeof(sessions[i].path), "%s",
+ ret = snprintf(tmp_session.path, sizeof(tmp_session.path), "%s",
session->consumer->dst.session_root_path);
}
if (ret < 0) {
continue;
}
- strncpy(sessions[i].name, session->name, NAME_MAX);
- sessions[i].name[NAME_MAX - 1] = '\0';
- sessions[i].enabled = session->active;
- sessions[i].snapshot_mode = session->snapshot_mode;
- sessions[i].live_timer_interval = session->live_timer;
- extended[i].creation_time.value = (uint64_t) session->creation_time;
- extended[i].creation_time.is_set = 1;
+ strncpy(tmp_session.name, session->name, NAME_MAX);
+ tmp_session.name[NAME_MAX - 1] = '\0';
+ tmp_session.enabled = session->active;
+ tmp_session.snapshot_mode = session->snapshot_mode;
+ tmp_session.live_timer_interval = session->live_timer;
+ LTTNG_OPTIONAL_SET(&tmp_extended.creation_time, (uint64_t) session->creation_time);
+ ret = lttng_session_serialize(&tmp_session, reply_payload);
+ if (ret) {
+ ret_code = LTTNG_ERR_FATAL;
+ goto error;
+ }
i++;
session_put(session);
}
+
+ if (i > UINT32_MAX) {
+ ret_code = LTTNG_ERR_OVERFLOW;
+ goto error;
+ }
+
+ /* Update command reply header. */
+ reply_command_header.count = (uint32_t) i;
+ memcpy(reply_payload->buffer.data + reply_command_header_offset, &reply_command_header,
+ sizeof(reply_command_header));
+ ret_code = LTTNG_OK;
+error:
+ return ret_code;
}
/*
goto end;
}
- list = (lttng_snapshot_output *) zmalloc(session->snapshot.nb_output * sizeof(*list));
+ list = calloc<lttng_snapshot_output>(session->snapshot.nb_output);
if (!list) {
ret = -LTTNG_ERR_NOMEM;
goto end;
return ret;
}
-static
-int clear_metadata_file(int fd)
-{
- int ret;
- off_t lseek_ret;
-
- lseek_ret = lseek(fd, 0, SEEK_SET);
- if (lseek_ret < 0) {
- PERROR("lseek");
- ret = -1;
- goto end;
- }
-
- ret = ftruncate(fd, 0);
- if (ret < 0) {
- PERROR("ftruncate");
- goto end;
- }
-
-end:
- return ret;
-}
-
-static
-int ust_regenerate_metadata(struct ltt_ust_session *usess)
-{
- int ret = 0;
- struct buffer_reg_uid *uid_reg = NULL;
- struct buffer_reg_session *session_reg = NULL;
-
- rcu_read_lock();
- cds_list_for_each_entry(uid_reg, &usess->buffer_reg_uid_list, lnode) {
- struct ust_registry_session *registry;
- struct ust_registry_channel *chan;
- struct lttng_ht_iter iter_chan;
-
- session_reg = uid_reg->registry;
- registry = session_reg->reg.ust;
-
- pthread_mutex_lock(®istry->lock);
- registry->metadata_len_sent = 0;
- memset(registry->metadata, 0, registry->metadata_alloc_len);
- registry->metadata_len = 0;
- registry->metadata_version++;
- if (registry->metadata_fd > 0) {
- /* Clear the metadata file's content. */
- ret = clear_metadata_file(registry->metadata_fd);
- if (ret) {
- pthread_mutex_unlock(®istry->lock);
- goto end;
- }
- }
-
- ret = ust_metadata_session_statedump(registry, NULL,
- registry->major, registry->minor);
- if (ret) {
- pthread_mutex_unlock(®istry->lock);
- ERR("Failed to generate session metadata (err = %d)",
- ret);
- goto end;
- }
- cds_lfht_for_each_entry(registry->channels->ht, &iter_chan.iter,
- chan, node.node) {
- struct ust_registry_event *event;
- struct lttng_ht_iter iter_event;
-
- ret = ust_metadata_channel_statedump(registry, chan);
- if (ret) {
- pthread_mutex_unlock(®istry->lock);
- ERR("Failed to generate channel metadata "
- "(err = %d)", ret);
- goto end;
- }
- cds_lfht_for_each_entry(chan->ht->ht, &iter_event.iter,
- event, node.node) {
- ret = ust_metadata_event_statedump(registry,
- chan, event);
- if (ret) {
- pthread_mutex_unlock(®istry->lock);
- ERR("Failed to generate event metadata "
- "(err = %d)", ret);
- goto end;
- }
- }
- }
- pthread_mutex_unlock(®istry->lock);
- }
-
-end:
- rcu_read_unlock();
- return ret;
-}
-
/*
* Command LTTNG_REGENERATE_METADATA from the lttng-ctl library.
*
}
if (session->ust_session) {
- ret = ust_regenerate_metadata(session->ust_session);
+ ret = trace_ust_regenerate_metadata(session->ust_session);
if (ret < 0) {
ERR("Failed to regenerate the UST metadata");
goto end;
* snapshot output.
*/
rcu_read_lock();
- cds_lfht_for_each_entry(output->socks->ht, &iter.iter,
- socket, node.node) {
+ cds_lfht_for_each_entry (output->socks->ht, &iter.iter, socket, node.node) {
pthread_mutex_lock(socket->lock);
- status = send_consumer_relayd_sockets(session->id,
- output, socket,
- session->name, session->hostname,
- base_path,
- session->live_timer,
- current_chunk_id.is_set ? ¤t_chunk_id.value : NULL,
- session->creation_time,
- session->name_contains_creation_time);
+ status = send_consumer_relayd_sockets(*session, output, socket, base_path,
+ current_chunk_id.is_set ? ¤t_chunk_id.value : NULL);
pthread_mutex_unlock(socket->lock);
if (status != LTTNG_OK) {
rcu_read_unlock();
chunk_being_archived = NULL;
if (!quiet_rotation) {
ret = notification_thread_command_session_rotation_ongoing(
- the_notification_thread_handle, session->name,
- session->uid, session->gid,
+ the_notification_thread_handle, session->id,
ongoing_rotation_chunk_id);
if (ret != LTTNG_OK) {
ERR("Failed to notify notification thread that a session rotation is ongoing for session %s",