clock-class.hpp clock-class.cpp \
event-class.hpp event-class.cpp \
stream-class.hpp stream-class.cpp \
- trace-class.hpp trace-class.cpp
+ trace-class.hpp trace-class.cpp \
+ consumer-destination-type.hpp \
+ consumer-output.hpp \
+ snapshot-output.hpp
if HAVE_LIBLTTNG_UST_CTL
liblttng_sessiond_common_la_SOURCES += trace-ust.cpp ust-registry.cpp ust-app.cpp \
/* Check if this trigger allowed to interect with a given session. */
static bool is_trigger_allowed_for_session(const struct lttng_trigger *trigger,
- struct ltt_session *session)
+ const ltt_session::locked_ref& session)
{
bool is_allowed = false;
const struct lttng_credentials session_creds = {
}
/*
- * Mind the order of the declaration of list_lock vs target_session:
+ * Mind the order of the declaration of list_lock vs session:
* the session list lock must always be released _after_ the release of
* a session's reference (the destruction of a ref/locked_ref) to ensure
* since the reference's release may unpublish the session from the list of
* sessions.
*/
const auto list_lock = lttng::sessiond::lock_session_list();
- ltt_session::locked_ref session;
-
try {
- session = ltt_session::find_locked_session(
+ const auto session = ltt_session::find_locked_session(
LTTNG_OPTIONAL_GET(item->context.session_id));
+
+ if (session->destroyed) {
+ DBG("Session `%s` with id = %" PRIu64
+ " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`",
+ session->name,
+ session->id,
+ get_action_name(action),
+ get_trigger_name(work_item->trigger));
+ return 0;
+ }
+
+ if (!is_trigger_allowed_for_session(work_item->trigger, session)) {
+ return 0;
+ }
+
+ cmd_ret = (lttng_error_code) cmd_start_trace(session);
+ switch (cmd_ret) {
+ case LTTNG_OK:
+ DBG("Successfully started session `%s` on behalf of trigger `%s`",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ case LTTNG_ERR_TRACE_ALREADY_STARTED:
+ DBG("Attempted to start session `%s` on behalf of trigger `%s` but it was already started",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ default:
+ WARN("Failed to start session `%s` on behalf of trigger `%s`: %s",
+ session_name,
+ get_trigger_name(work_item->trigger),
+ lttng_strerror(-cmd_ret));
+ lttng_action_increase_execution_failure_count(action);
+ break;
+ }
} catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
DBG_FMT("Failed to execution trigger action: {}, action=`{}`, trigger_name=`{}`, location='{}'",
ex.what(),
get_trigger_name(work_item->trigger),
ex.source_location);
lttng_action_increase_execution_failure_count(action);
- return 0;
- }
-
- if (session->destroyed) {
- DBG("Session `%s` with id = %" PRIu64
- " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`",
- session->name,
- session->id,
- get_action_name(action),
- get_trigger_name(work_item->trigger));
- return 0;
- }
-
- if (!is_trigger_allowed_for_session(work_item->trigger, session.get())) {
- return 0;
- }
-
- cmd_ret = (lttng_error_code) cmd_start_trace(session.get());
- switch (cmd_ret) {
- case LTTNG_OK:
- DBG("Successfully started session `%s` on behalf of trigger `%s`",
- session_name,
- get_trigger_name(work_item->trigger));
- break;
- case LTTNG_ERR_TRACE_ALREADY_STARTED:
- DBG("Attempted to start session `%s` on behalf of trigger `%s` but it was already started",
- session_name,
- get_trigger_name(work_item->trigger));
- break;
- default:
- WARN("Failed to start session `%s` on behalf of trigger `%s`: %s",
- session_name,
- get_trigger_name(work_item->trigger),
- lttng_strerror(-cmd_ret));
- lttng_action_increase_execution_failure_count(action);
- break;
}
return 0;
}
/*
- * Mind the order of the declaration of list_lock vs target_session:
+ * Mind the order of the declaration of list_lock vs session:
* the session list lock must always be released _after_ the release of
* a session's reference (the destruction of a ref/locked_ref) to ensure
* since the reference's release may unpublish the session from the list of
* sessions.
*/
const auto list_lock = lttng::sessiond::lock_session_list();
- ltt_session::locked_ref session;
try {
- session = ltt_session::find_locked_session(
+ const auto session = ltt_session::find_locked_session(
LTTNG_OPTIONAL_GET(item->context.session_id));
+
+ if (session->destroyed) {
+ DBG("Session `%s` with id = %" PRIu64
+ " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`",
+ session->name,
+ session->id,
+ get_action_name(action),
+ get_trigger_name(work_item->trigger));
+ return 0;
+ }
+
+ if (!is_trigger_allowed_for_session(work_item->trigger, session)) {
+ return 0;
+ }
+
+ cmd_ret = (lttng_error_code) cmd_stop_trace(session);
+ switch (cmd_ret) {
+ case LTTNG_OK:
+ DBG("Successfully stopped session `%s` on behalf of trigger `%s`",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ case LTTNG_ERR_TRACE_ALREADY_STOPPED:
+ DBG("Attempted to stop session `%s` on behalf of trigger `%s` but it was already stopped",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ default:
+ WARN("Failed to stop session `%s` on behalf of trigger `%s`: %s",
+ session_name,
+ get_trigger_name(work_item->trigger),
+ lttng_strerror(-cmd_ret));
+ lttng_action_increase_execution_failure_count(action);
+ break;
+ }
} catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
DBG_FMT("Failed to execution trigger action: {}, action=`{}`, trigger_name=`{}`, location='{}'",
ex.what(),
get_trigger_name(work_item->trigger),
ex.source_location);
lttng_action_increase_execution_failure_count(action);
- return 0;
- }
-
- if (session->destroyed) {
- DBG("Session `%s` with id = %" PRIu64
- " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`",
- session->name,
- session->id,
- get_action_name(action),
- get_trigger_name(work_item->trigger));
- return 0;
- }
-
- if (!is_trigger_allowed_for_session(work_item->trigger, session.get())) {
- return 0;
- }
-
- cmd_ret = (lttng_error_code) cmd_stop_trace(session.get());
- switch (cmd_ret) {
- case LTTNG_OK:
- DBG("Successfully stopped session `%s` on behalf of trigger `%s`",
- session_name,
- get_trigger_name(work_item->trigger));
- break;
- case LTTNG_ERR_TRACE_ALREADY_STOPPED:
- DBG("Attempted to stop session `%s` on behalf of trigger `%s` but it was already stopped",
- session_name,
- get_trigger_name(work_item->trigger));
- break;
- default:
- WARN("Failed to stop session `%s` on behalf of trigger `%s`: %s",
- session_name,
- get_trigger_name(work_item->trigger),
- lttng_strerror(-cmd_ret));
- lttng_action_increase_execution_failure_count(action);
- break;
}
return 0;
}
/*
- * Mind the order of the declaration of list_lock vs target_session:
+ * Mind the order of the declaration of list_lock vs session:
* the session list lock must always be released _after_ the release of
* a session's reference (the destruction of a ref/locked_ref) to ensure
* since the reference's release may unpublish the session from the list of
* sessions.
*/
const auto list_lock = lttng::sessiond::lock_session_list();
- ltt_session::locked_ref session;
-
try {
- session = ltt_session::find_locked_session(
+ const auto session = ltt_session::find_locked_session(
LTTNG_OPTIONAL_GET(item->context.session_id));
+
+ if (session->destroyed) {
+ DBG("Session `%s` with id = %" PRIu64
+ " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`",
+ session->name,
+ session->id,
+ get_action_name(action),
+ get_trigger_name(work_item->trigger));
+ return 0;
+ }
+
+ if (!is_trigger_allowed_for_session(work_item->trigger, session)) {
+ return 0;
+ }
+
+ cmd_ret = (lttng_error_code) cmd_rotate_session(
+ session, nullptr, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED);
+ switch (cmd_ret) {
+ case LTTNG_OK:
+ DBG("Successfully started rotation of session `%s` on behalf of trigger `%s`",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ case LTTNG_ERR_ROTATION_PENDING:
+ DBG("Attempted to start a rotation of session `%s` on behalf of trigger `%s` but a rotation is already ongoing",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ lttng_action_increase_execution_failure_count(action);
+ break;
+ case LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP:
+ case LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR:
+ DBG("Attempted to start a rotation of session `%s` on behalf of trigger `%s` but a rotation has already been completed since the last stop or clear",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ default:
+ WARN("Failed to start a rotation of session `%s` on behalf of trigger `%s`: %s",
+ session_name,
+ get_trigger_name(work_item->trigger),
+ lttng_strerror(-cmd_ret));
+ lttng_action_increase_execution_failure_count(action);
+ break;
+ }
} catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
DBG_FMT("Failed to execution trigger action: {}, action=`{}`, trigger_name=`{}`, location='{}'",
ex.what(),
get_trigger_name(work_item->trigger),
ex.source_location);
lttng_action_increase_execution_failure_count(action);
- return 0;
- }
-
- if (session->destroyed) {
- DBG("Session `%s` with id = %" PRIu64
- " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`",
- session->name,
- session->id,
- get_action_name(action),
- get_trigger_name(work_item->trigger));
- return 0;
- }
-
- if (!is_trigger_allowed_for_session(work_item->trigger, session.get())) {
- return 0;
- }
-
- cmd_ret = (lttng_error_code) cmd_rotate_session(
- session.get(), nullptr, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED);
- switch (cmd_ret) {
- case LTTNG_OK:
- DBG("Successfully started rotation of session `%s` on behalf of trigger `%s`",
- session_name,
- get_trigger_name(work_item->trigger));
- break;
- case LTTNG_ERR_ROTATION_PENDING:
- DBG("Attempted to start a rotation of session `%s` on behalf of trigger `%s` but a rotation is already ongoing",
- session_name,
- get_trigger_name(work_item->trigger));
- lttng_action_increase_execution_failure_count(action);
- break;
- case LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP:
- case LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR:
- DBG("Attempted to start a rotation of session `%s` on behalf of trigger `%s` but a rotation has already been completed since the last stop or clear",
- session_name,
- get_trigger_name(work_item->trigger));
- break;
- default:
- WARN("Failed to start a rotation of session `%s` on behalf of trigger `%s`: %s",
- session_name,
- get_trigger_name(work_item->trigger),
- lttng_strerror(-cmd_ret));
- lttng_action_increase_execution_failure_count(action);
- break;
}
return 0;
* sessions.
*/
const auto list_lock = lttng::sessiond::lock_session_list();
- ltt_session::locked_ref session;
-
try {
- session = ltt_session::find_locked_session(
+ const auto session = ltt_session::find_locked_session(
LTTNG_OPTIONAL_GET(item->context.session_id));
+
+ if (session->destroyed) {
+ DBG("Session `%s` with id = %" PRIu64
+ " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`",
+ session->name,
+ session->id,
+ get_action_name(action),
+ get_trigger_name(work_item->trigger));
+ return 0;
+ }
+
+ if (!is_trigger_allowed_for_session(work_item->trigger, session)) {
+ return 0;
+ }
+
+ cmd_ret = (lttng_error_code) cmd_snapshot_record(session, snapshot_output, 0);
+ switch (cmd_ret) {
+ case LTTNG_OK:
+ DBG("Successfully recorded snapshot of session `%s` on behalf of trigger `%s`",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ default:
+ WARN("Failed to record snapshot of session `%s` on behalf of trigger `%s`: %s",
+ session_name,
+ get_trigger_name(work_item->trigger),
+ lttng_strerror(-cmd_ret));
+ lttng_action_increase_execution_failure_count(action);
+ break;
+ }
+
} catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
DBG_FMT("Failed to execution trigger action: {}, action=`{}`, trigger_name=`{}`, location='{}'",
ex.what(),
get_trigger_name(work_item->trigger),
ex.source_location);
lttng_action_increase_execution_failure_count(action);
- return 0;
- }
-
- if (session->destroyed) {
- DBG("Session `%s` with id = %" PRIu64
- " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`",
- session->name,
- session->id,
- get_action_name(action),
- get_trigger_name(work_item->trigger));
- return 0;
- }
-
- if (!is_trigger_allowed_for_session(work_item->trigger, session.get())) {
- return 0;
- }
-
- cmd_ret = (lttng_error_code) cmd_snapshot_record(session.get(), snapshot_output, 0);
- switch (cmd_ret) {
- case LTTNG_OK:
- DBG("Successfully recorded snapshot of session `%s` on behalf of trigger `%s`",
- session_name,
- get_trigger_name(work_item->trigger));
- break;
- default:
- WARN("Failed to record snapshot of session `%s` on behalf of trigger `%s`: %s",
- session_name,
- get_trigger_name(work_item->trigger),
- lttng_strerror(-cmd_ret));
- lttng_action_increase_execution_failure_count(action);
- break;
}
return 0;
};
} /* namespace */
-static void cmd_clear_session_reply(const struct ltt_session *session, void *_reply_context)
+static void cmd_clear_session_reply(const ltt_session::locked_ref& session, void *_reply_context)
{
int ret;
ssize_t comm_ret;
free(_reply_context);
}
-int cmd_clear_session(struct ltt_session *session, int *sock_fd)
+int cmd_clear_session(const ltt_session::locked_ref& session, int *sock_fd)
{
int ret = LTTNG_OK;
struct cmd_clear_session_reply_context *reply_context = nullptr;
#include "session.hpp"
-int cmd_clear_session(struct ltt_session *session, int *sock_fd);
+int cmd_clear_session(const ltt_session::locked_ref& session, int *sock_fd);
#endif /* CLEAT_H */
* function also applies the right modification on a per domain basis for the
* trace files destination directory.
*/
-static int copy_session_consumer(int domain, struct ltt_session *session)
+static int copy_session_consumer(int domain, const ltt_session::locked_ref& session)
{
int ret;
const char *dir_name;
struct consumer_output *consumer;
- LTTNG_ASSERT(session);
LTTNG_ASSERT(session->consumer);
switch (domain) {
/*
* Create an UST session and add it to the session ust list.
*/
-static int create_ust_session(struct ltt_session *session, const struct lttng_domain *domain)
+static int create_ust_session(const ltt_session::locked_ref& session,
+ const struct lttng_domain *domain)
{
int ret;
struct ltt_ust_session *lus = nullptr;
- LTTNG_ASSERT(session);
LTTNG_ASSERT(domain);
LTTNG_ASSERT(session->consumer);
/*
* Create a kernel tracer session then create the default channel.
*/
-static int create_kernel_session(struct ltt_session *session)
+static int create_kernel_session(const ltt_session::locked_ref& session)
{
int ret;
static unsigned int lttng_sessions_count(uid_t uid, gid_t gid __attribute__((unused)))
{
unsigned int i = 0;
- struct ltt_session *session;
+ struct ltt_session *raw_session_ptr;
const struct ltt_session_list *session_list = session_get_list();
DBG("Counting number of available session for UID %d", uid);
- cds_list_for_each_entry (session, &session_list->head, list) {
- if (!session_get(session)) {
- continue;
- }
- session_lock(session);
+ cds_list_for_each_entry (raw_session_ptr, &session_list->head, list) {
+ auto session = [raw_session_ptr]() {
+ session_get(raw_session_ptr);
+ raw_session_ptr->lock();
+ return ltt_session::locked_ref(*raw_session_ptr);
+ }();
+
/* Only count the sessions the user can control. */
if (session_access_ok(session, uid) && !session->destroyed) {
i++;
}
- session_unlock(session);
- session_put(session);
}
+
return i;
}
std::unique_lock<std::mutex> list_lock;
/*
* A locked_ref is typically "never null" (hence its name). However, due to the
- * structure of this function, target_session remains null for commands that don't
+ * structure of this function, target_session remains unset for commands that don't
* have a target session.
*/
- ltt_session::locked_ref target_session;
+ nonstd::optional<ltt_session::locked_ref> target_session;
/* Commands that DO NOT need a session. */
switch (cmd_ctx->lsm.cmd_type) {
*/
list_lock = lttng::sessiond::lock_session_list();
try {
- target_session =
- ltt_session::find_locked_session(cmd_ctx->lsm.session.name);
+ target_session.emplace(
+ ltt_session::find_locked_session(cmd_ctx->lsm.session.name));
} catch (...) {
std::throw_with_nested(lttng::ctl::error(
fmt::format(
case LTTCOMM_SESSIOND_COMMAND_DISABLE_EVENT:
switch (cmd_ctx->lsm.domain.type) {
case LTTNG_DOMAIN_KERNEL:
- if (!target_session->kernel_session) {
+ if (!(*target_session)->kernel_session) {
return LTTNG_ERR_NO_CHANNEL;
}
break;
case LTTNG_DOMAIN_LOG4J:
case LTTNG_DOMAIN_PYTHON:
case LTTNG_DOMAIN_UST:
- if (!target_session->ust_session) {
+ if (!(*target_session)->ust_session) {
return LTTNG_ERR_NO_CHANNEL;
goto error;
}
/* Need a session for kernel command */
if (need_tracing_session) {
- if (target_session->kernel_session == nullptr) {
- ret = create_kernel_session(target_session.get());
+ if ((*target_session)->kernel_session == nullptr) {
+ ret = create_kernel_session(*target_session);
if (ret != LTTNG_OK) {
ret = LTTNG_ERR_KERN_SESS_FAIL;
goto error;
* the consumer output of the session if exist.
*/
ret = consumer_create_socket(&the_kconsumer_data,
- target_session->kernel_session->consumer);
+ (*target_session)->kernel_session->consumer);
if (ret < 0) {
goto error;
}
if (need_tracing_session) {
/* Create UST session if none exist. */
- if (target_session->ust_session == nullptr) {
+ if ((*target_session)->ust_session == nullptr) {
lttng_domain domain = cmd_ctx->lsm.domain;
- ret = create_ust_session(target_session.get(), &domain);
+ ret = create_ust_session(*target_session, &domain);
if (ret != LTTNG_OK) {
goto error;
}
* since it was set above and can ONLY be set in this thread.
*/
ret = consumer_create_socket(&the_ustconsumer64_data,
- target_session->ust_session->consumer);
+ (*target_session)->ust_session->consumer);
if (ret < 0) {
goto error;
}
* since it was set above and can ONLY be set in this thread.
*/
ret = consumer_create_socket(&the_ustconsumer32_data,
- target_session->ust_session->consumer);
+ (*target_session)->ust_session->consumer);
if (ret < 0) {
goto error;
}
* The root user can interact with all sessions.
*/
if (need_tracing_session) {
- if (!session_access_ok(target_session.get(),
- LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds)) ||
- target_session->destroyed) {
+ if (!session_access_ok(*target_session, LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds)) ||
+ (*target_session)->destroyed) {
ret = LTTNG_ERR_EPERM;
goto error;
}
* Setup relayd if not done yet. If the relayd information was already
* sent to the consumer, this call will gracefully return.
*/
- ret = cmd_setup_relayd(target_session.get());
+ ret = cmd_setup_relayd(*target_session);
if (ret != LTTNG_OK) {
goto error;
}
}
ret = cmd_add_context(
- cmd_ctx, target_session, event_context, the_kernel_poll_pipe[1]);
+ cmd_ctx, *target_session, event_context, the_kernel_poll_pipe[1]);
lttng_event_context_destroy(event_context);
break;
}
case LTTCOMM_SESSIOND_COMMAND_DISABLE_CHANNEL:
{
- ret = cmd_disable_channel(target_session.get(),
+ ret = cmd_disable_channel(*target_session,
cmd_ctx->lsm.domain.type,
cmd_ctx->lsm.u.disable.channel_name);
break;
}
case LTTCOMM_SESSIOND_COMMAND_ENABLE_CHANNEL:
{
- ret = cmd_enable_channel(cmd_ctx, target_session, *sock, the_kernel_poll_pipe[1]);
+ ret = cmd_enable_channel(cmd_ctx, *target_session, *sock, the_kernel_poll_pipe[1]);
break;
}
case LTTCOMM_SESSIOND_COMMAND_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE:
if (add_value) {
ret = cmd_process_attr_tracker_inclusion_set_add_value(
- target_session.get(), domain_type, process_attr, value);
+ *target_session, domain_type, process_attr, value);
} else {
ret = cmd_process_attr_tracker_inclusion_set_remove_value(
- target_session.get(), domain_type, process_attr, value);
+ *target_session, domain_type, process_attr, value);
}
process_attr_value_destroy(value);
error_add_remove_tracker_value:
.process_attr_tracker_get_tracking_policy.process_attr;
ret = cmd_process_attr_tracker_get_tracking_policy(
- target_session.get(), domain_type, process_attr, &tracking_policy);
+ *target_session, domain_type, process_attr, &tracking_policy);
if (ret != LTTNG_OK) {
goto error;
}
.process_attr_tracker_set_tracking_policy.process_attr;
ret = cmd_process_attr_tracker_set_tracking_policy(
- target_session.get(), domain_type, process_attr, tracking_policy);
+ *target_session, domain_type, process_attr, tracking_policy);
if (ret != LTTNG_OK) {
goto error;
}
cmd_ctx->lsm.u.process_attr_tracker_get_inclusion_set.process_attr;
ret = cmd_process_attr_tracker_get_inclusion_set(
- target_session.get(), domain_type, process_attr, &values);
+ *target_session, domain_type, process_attr, &values);
if (ret != LTTNG_OK) {
goto error;
}
*/
ret = cmd_ctx->lsm.cmd_type == LTTCOMM_SESSIOND_COMMAND_ENABLE_EVENT ?
cmd_enable_event(cmd_ctx,
- target_session,
+ *target_session,
event,
filter_expression,
exclusions,
bytecode,
the_kernel_poll_pipe[1]) :
cmd_disable_event(cmd_ctx,
- target_session,
+ *target_session,
event,
filter_expression,
bytecode,
goto error;
}
- ret = cmd_set_consumer_uri(target_session.get(), nb_uri, uris);
+ ret = cmd_set_consumer_uri(*target_session, nb_uri, uris);
free(uris);
if (ret != LTTNG_OK) {
goto error;
* enabled time or size-based rotations, we have to make sure
* the kernel tracer supports it.
*/
- if (!target_session->has_been_started && target_session->kernel_session &&
- (target_session->rotate_timer_period || target_session->rotate_size) &&
+ if (!(*target_session)->has_been_started && (*target_session)->kernel_session &&
+ ((*target_session)->rotate_timer_period || (*target_session)->rotate_size) &&
!check_rotate_compatible()) {
DBG("Kernel tracer version is not compatible with the rotation feature");
ret = LTTNG_ERR_ROTATION_WRONG_VERSION;
goto error;
}
- ret = cmd_start_trace(target_session.get());
+ ret = cmd_start_trace(*target_session);
break;
}
case LTTCOMM_SESSIOND_COMMAND_STOP_TRACE:
{
- ret = cmd_stop_trace(target_session.get());
+ ret = cmd_stop_trace(*target_session);
break;
}
case LTTCOMM_SESSIOND_COMMAND_DESTROY_SESSION:
{
- ret = cmd_destroy_session(target_session.get(), sock);
+ ret = cmd_destroy_session(*target_session, sock);
break;
}
case LTTCOMM_SESSIOND_COMMAND_LIST_DOMAINS:
ssize_t nb_dom;
struct lttng_domain *domains = nullptr;
- nb_dom = cmd_list_domains(target_session.get(), &domains);
+ nb_dom = cmd_list_domains(*target_session, &domains);
if (nb_dom < 0) {
/* Return value is a negative lttng_error_code. */
ret = -nb_dom;
original_payload_size = cmd_ctx->reply_payload.buffer.size;
ret_code = cmd_list_channels(
- cmd_ctx->lsm.domain.type, target_session.get(), &cmd_ctx->reply_payload);
+ cmd_ctx->lsm.domain.type, *target_session, &cmd_ctx->reply_payload);
if (ret_code != LTTNG_OK) {
ret = (int) ret_code;
goto error;
original_payload_size = cmd_ctx->reply_payload.buffer.size;
ret_code = cmd_list_events(cmd_ctx->lsm.domain.type,
- target_session.get(),
+ *target_session,
cmd_ctx->lsm.u.list.channel_name,
&cmd_ctx->reply_payload);
if (ret_code != LTTNG_OK) {
goto error;
}
- ret = cmd_register_consumer(target_session.get(),
- cmd_ctx->lsm.domain.type,
- cmd_ctx->lsm.u.reg.path,
- cdata);
+ ret = cmd_register_consumer(
+ *target_session, cmd_ctx->lsm.domain.type, cmd_ctx->lsm.u.reg.path, cdata);
break;
}
case LTTCOMM_SESSIOND_COMMAND_KERNEL_TRACER_STATUS:
int pending_ret;
uint8_t pending_ret_byte;
- pending_ret = cmd_data_pending(target_session.get());
+ pending_ret = cmd_data_pending(*target_session);
/*
* FIXME
struct lttcomm_lttng_output_id reply;
lttng_snapshot_output output = cmd_ctx->lsm.u.snapshot_output.output;
- ret = cmd_snapshot_add_output(target_session.get(), &output, &snapshot_id);
+ ret = cmd_snapshot_add_output(*target_session, &output, &snapshot_id);
if (ret != LTTNG_OK) {
goto error;
}
case LTTCOMM_SESSIOND_COMMAND_SNAPSHOT_DEL_OUTPUT:
{
lttng_snapshot_output output = cmd_ctx->lsm.u.snapshot_output.output;
- ret = cmd_snapshot_del_output(target_session.get(), &output);
+ ret = cmd_snapshot_del_output(*target_session, &output);
break;
}
case LTTCOMM_SESSIOND_COMMAND_SNAPSHOT_LIST_OUTPUT:
ssize_t nb_output;
struct lttng_snapshot_output *outputs = nullptr;
- nb_output = cmd_snapshot_list_outputs(target_session.get(), &outputs);
+ nb_output = cmd_snapshot_list_outputs(*target_session, &outputs);
if (nb_output < 0) {
ret = -nb_output;
goto error;
case LTTCOMM_SESSIOND_COMMAND_SNAPSHOT_RECORD:
{
lttng_snapshot_output output = cmd_ctx->lsm.u.snapshot_record.output;
- ret = cmd_snapshot_record(target_session.get(), &output, 0); // RFC: set to zero
- // since it's ignored
- // by
- // cmd_snapshot_record
+ ret = cmd_snapshot_record(*target_session, &output, 0); // RFC: set to zero
+ // since it's ignored
+ // by
+ // cmd_snapshot_record
break;
}
case LTTCOMM_SESSIOND_COMMAND_CREATE_SESSION_EXT:
}
case LTTCOMM_SESSIOND_COMMAND_SET_SESSION_SHM_PATH:
{
- ret = cmd_set_session_shm_path(target_session.get(),
+ ret = cmd_set_session_shm_path(*target_session,
cmd_ctx->lsm.u.set_shm_path.shm_path);
break;
}
case LTTCOMM_SESSIOND_COMMAND_REGENERATE_METADATA:
{
- ret = cmd_regenerate_metadata(target_session.get());
+ ret = cmd_regenerate_metadata(*target_session);
break;
}
case LTTCOMM_SESSIOND_COMMAND_REGENERATE_STATEDUMP:
{
- ret = cmd_regenerate_statedump(target_session.get());
+ ret = cmd_regenerate_statedump(*target_session);
break;
}
case LTTCOMM_SESSIOND_COMMAND_REGISTER_TRIGGER:
{
struct lttng_rotate_session_return rotate_return;
- DBG("Client rotate session \"%s\"", target_session->name);
+ DBG("Client rotate session \"%s\"", (*target_session)->name);
memset(&rotate_return, 0, sizeof(rotate_return));
- if (target_session->kernel_session && !check_rotate_compatible()) {
+ if ((*target_session)->kernel_session && !check_rotate_compatible()) {
DBG("Kernel tracer version is not compatible with the rotation feature");
ret = LTTNG_ERR_ROTATION_WRONG_VERSION;
goto error;
}
- ret = cmd_rotate_session(target_session.get(),
+ ret = cmd_rotate_session(*target_session,
&rotate_return,
false,
LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED);
struct lttng_rotation_get_info_return get_info_return;
memset(&get_info_return, 0, sizeof(get_info_return));
- ret = cmd_rotate_get_info(target_session.get(),
+ ret = cmd_rotate_get_info(*target_session,
&get_info_return,
cmd_ctx->lsm.u.get_rotation_info.rotation_id);
if (ret < 0) {
enum lttng_rotation_schedule_type schedule_type;
uint64_t value;
- if (target_session->kernel_session && !check_rotate_compatible()) {
+ if ((*target_session)->kernel_session && !check_rotate_compatible()) {
DBG("Kernel tracer version does not support session rotations");
ret = LTTNG_ERR_ROTATION_WRONG_VERSION;
goto error;
value = cmd_ctx->lsm.u.rotation_set_schedule.value;
ret = cmd_rotation_set_schedule(
- target_session.get(), set_schedule, schedule_type, value);
+ *target_session, set_schedule, schedule_type, value);
if (ret != LTTNG_OK) {
goto error;
}
{
lttng_session_list_schedules_return schedules;
- schedules.periodic.set = !!target_session->rotate_timer_period;
- schedules.periodic.value = target_session->rotate_timer_period;
- schedules.size.set = !!target_session->rotate_size;
- schedules.size.value = target_session->rotate_size;
+ schedules.periodic.set = !!(*target_session)->rotate_timer_period;
+ schedules.periodic.value = (*target_session)->rotate_timer_period;
+ schedules.size.set = !!(*target_session)->rotate_size;
+ schedules.size.value = (*target_session)->rotate_size;
setup_lttng_msg_no_cmd_header(cmd_ctx, &schedules, sizeof(schedules));
}
case LTTCOMM_SESSIOND_COMMAND_CLEAR_SESSION:
{
- ret = cmd_clear_session(target_session.get(), sock);
+ ret = cmd_clear_session(*target_session, sock);
break;
}
case LTTCOMM_SESSIOND_COMMAND_LIST_TRIGGERS:
#include "buffer-registry.hpp"
#include "channel.hpp"
#include "cmd.hpp"
+#include "consumer-output.hpp"
#include "consumer.hpp"
#include "event-notifier-error-accounting.hpp"
#include "event.hpp"
* Create a session path used by list_lttng_sessions for the case that the
* session consumer is on the network.
*/
-static int build_network_session_path(char *dst, size_t size, struct ltt_session *session)
+static int
+build_network_session_path(char *dst, size_t size, const ltt_session::locked_ref& session)
{
int ret, kdata_port, udata_port;
struct lttng_uri *kuri = nullptr, *uuri = nullptr, *uri = nullptr;
char tmp_uurl[PATH_MAX], tmp_urls[PATH_MAX];
- LTTNG_ASSERT(session);
LTTNG_ASSERT(dst);
memset(tmp_urls, 0, sizeof(tmp_urls));
* Get run-time attributes if the session has been started (discarded events,
* lost packets).
*/
-static int get_kernel_runtime_stats(struct ltt_session *session,
+static int get_kernel_runtime_stats(const ltt_session::locked_ref& session,
struct ltt_kernel_channel *kchan,
uint64_t *discarded_events,
uint64_t *lost_packets)
* Get run-time attributes if the session has been started (discarded events,
* lost packets).
*/
-static int get_ust_runtime_stats(struct ltt_session *session,
+static int get_ust_runtime_stats(const ltt_session::locked_ref& session,
struct ltt_ust_channel *uchan,
uint64_t *discarded_events,
uint64_t *lost_packets)
* Add URI so the consumer output object. Set the correct path depending on the
* domain adding the default trace directory.
*/
-static enum lttng_error_code add_uri_to_consumer(const struct ltt_session *session,
+static enum lttng_error_code add_uri_to_consumer(const ltt_session::locked_ref& session,
struct consumer_output *consumer,
struct lttng_uri *uri,
enum lttng_domain_type domain)
* the relayd and send them to the right domain consumer. Consumer type MUST be
* network.
*/
-int cmd_setup_relayd(struct ltt_session *session)
+int cmd_setup_relayd(const ltt_session::locked_ref& session)
{
int ret = LTTNG_OK;
struct ltt_ust_session *usess;
struct lttng_ht_iter iter;
LTTNG_OPTIONAL(uint64_t) current_chunk_id = {};
- LTTNG_ASSERT(session);
-
usess = session->ust_session;
ksess = session->kernel_session;
/*
* Command LTTNG_DISABLE_CHANNEL processed by the client thread.
*/
-int cmd_disable_channel(struct ltt_session *session,
+int cmd_disable_channel(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
char *channel_name)
{
int wpipe)
{
enum lttng_error_code ret_code;
- struct ltt_ust_session *usess = session.get()->ust_session;
+ struct ltt_ust_session *usess = session->ust_session;
struct lttng_ht *chan_ht;
size_t len;
struct lttng_channel *attr = nullptr;
* live timer does the same thing but sends also synchronisation
* beacons for inactive streams.
*/
- if (session.get()->live_timer > 0) {
- attr->attr.live_timer_interval = session.get()->live_timer;
+ if (session->live_timer > 0) {
+ attr->attr.live_timer_interval = session->live_timer;
attr->attr.switch_timer_interval = 0;
}
"Setting the monitor interval timer to 0 "
"(disabled) for channel '%s' of session '%s'",
attr->name,
- session.get()->name);
+ session->name);
lttng_channel_set_monitor_timer_interval(attr, 0);
}
break;
}
enum lttng_error_code
-cmd_process_attr_tracker_get_tracking_policy(struct ltt_session *session,
+cmd_process_attr_tracker_get_tracking_policy(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
enum lttng_tracking_policy *policy)
}
enum lttng_error_code
-cmd_process_attr_tracker_set_tracking_policy(struct ltt_session *session,
+cmd_process_attr_tracker_set_tracking_policy(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
enum lttng_tracking_policy policy)
}
enum lttng_error_code
-cmd_process_attr_tracker_inclusion_set_add_value(struct ltt_session *session,
+cmd_process_attr_tracker_inclusion_set_add_value(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
const struct process_attr_value *value)
}
enum lttng_error_code
-cmd_process_attr_tracker_inclusion_set_remove_value(struct ltt_session *session,
+cmd_process_attr_tracker_inclusion_set_remove_value(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
const struct process_attr_value *value)
}
enum lttng_error_code
-cmd_process_attr_tracker_get_inclusion_set(struct ltt_session *session,
+cmd_process_attr_tracker_get_inclusion_set(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
struct lttng_process_attr_values **values)
struct lttng_event_exclusion *exclusion)
{
int ret;
- ltt_session& session = *locked_session.get();
+ const ltt_session& session = *locked_session;
const char *event_name;
const char *channel_name = cmd_ctx->lsm.u.disable.channel_name;
const enum lttng_domain_type domain = cmd_ctx->lsm.domain.type;
{
int ret, chan_kern_created = 0, chan_ust_created = 0;
const enum lttng_domain_type domain = cmd_ctx->lsm.domain.type;
- const struct ltt_session& session = *locked_session.get();
+ const struct ltt_session& session = *locked_session;
const char *channel_name = cmd_ctx->lsm.u.context.channel_name;
/*
{
int ret = 0, channel_created = 0;
struct lttng_channel *attr = nullptr;
- ltt_session& session = *locked_session.get();
+ ltt_session& session = *locked_session;
LTTNG_ASSERT(event);
LTTNG_ASSERT(channel_name);
/*
* Command LTTNG_START_TRACE processed by the client thread.
- *
- * Called with session mutex held.
*/
-int cmd_start_trace(struct ltt_session *session)
+int cmd_start_trace(const ltt_session::locked_ref& session)
{
enum lttng_error_code ret;
unsigned long nb_chan = 0;
const bool session_rotated_after_last_stop = session->rotated_after_last_stop;
const bool session_cleared_after_last_stop = session->cleared_after_last_stop;
- LTTNG_ASSERT(session);
-
/* Ease our life a bit ;) */
ksession = session->kernel_session;
usess = session->ust_session;
/*
* Command LTTNG_STOP_TRACE processed by the client thread.
*/
-int cmd_stop_trace(struct ltt_session *session)
+int cmd_stop_trace(const ltt_session::locked_ref& session)
{
int ret;
struct ltt_kernel_session *ksession;
struct ltt_ust_session *usess;
- LTTNG_ASSERT(session);
-
DBG("Begin stop session \"%s\" (id %" PRIu64 ")", session->name, session->id);
/* Short cut */
ksession = session->kernel_session;
* Set the base_path of the session only if subdir of a control uris is set.
* Return LTTNG_OK on success, otherwise LTTNG_ERR_*.
*/
-static int
-set_session_base_path_from_uris(struct ltt_session *session, size_t nb_uri, struct lttng_uri *uris)
+static int set_session_base_path_from_uris(const ltt_session::locked_ref& session,
+ size_t nb_uri,
+ struct lttng_uri *uris)
{
int ret;
size_t i;
/*
* Command LTTNG_SET_CONSUMER_URI processed by the client thread.
*/
-int cmd_set_consumer_uri(struct ltt_session *session, size_t nb_uri, struct lttng_uri *uris)
+int cmd_set_consumer_uri(const ltt_session::locked_ref& session,
+ size_t nb_uri,
+ struct lttng_uri *uris)
{
int ret, i;
struct ltt_kernel_session *ksess = session->kernel_session;
struct ltt_ust_session *usess = session->ust_session;
- LTTNG_ASSERT(session);
LTTNG_ASSERT(uris);
LTTNG_ASSERT(nb_uri > 0);
}
static enum lttng_error_code
-set_session_output_from_descriptor(struct ltt_session *session,
+set_session_output_from_descriptor(const ltt_session::locked_ref& session,
const struct lttng_session_descriptor *descriptor)
{
int ret;
/* 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))) {
+ [new_session]() {
+ session_get(new_session);
+ new_session->lock();
+ return ltt_session::locked_ref(*new_session);
+ }(),
+ [](const ltt_session::locked_ref& session,
+ void *user_data __attribute__((unused))) {
(void) notification_thread_command_remove_session(
the_notification_thread_handle, session->id);
},
break;
}
- ret_code = set_session_output_from_descriptor(new_session, descriptor);
+ ret_code = set_session_output_from_descriptor(
+ [new_session]() {
+ session_get(new_session);
+ new_session->lock();
+ return ltt_session::locked_ref(*new_session);
+ }(),
+ descriptor);
if (ret_code != LTTNG_OK) {
goto end;
}
return ret_code;
}
-static void cmd_destroy_session_reply(const struct ltt_session *session, void *_reply_context)
+static void cmd_destroy_session_reply(const ltt_session::locked_ref& session, void *_reply_context)
{
int ret;
ssize_t comm_ret;
*
* Called with session lock held.
*/
-int cmd_destroy_session(struct ltt_session *session, int *sock_fd)
+int cmd_destroy_session(const ltt_session::locked_ref& session, int *sock_fd)
{
int ret;
enum lttng_error_code destruction_last_error = LTTNG_OK;
reply_context->reply_sock_fd = *sock_fd;
}
- /* Safety net */
- LTTNG_ASSERT(session);
-
DBG("Begin destroy session %s (id %" PRIu64 ")", session->name, session->id);
if (session->active) {
DBG("Session \"%s\" is active, attempting to stop it before destroying it",
* still holds a reference to the session, thus delaying its destruction
* _at least_ up to the point when that reference is released.
*/
- session_destroy(session);
+ session_destroy(&session.get());
if (reply_context) {
reply_context->destruction_status = destruction_last_error;
ret = session_add_destroy_notifier(
/*
* Command LTTNG_REGISTER_CONSUMER processed by the client thread.
*/
-int cmd_register_consumer(struct ltt_session *session,
+int cmd_register_consumer(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
const char *sock_path,
struct consumer_data *cdata)
int ret, sock;
struct consumer_socket *socket = nullptr;
- LTTNG_ASSERT(session);
LTTNG_ASSERT(cdata);
LTTNG_ASSERT(sock_path);
/*
* Command LTTNG_LIST_DOMAINS processed by the client thread.
*/
-ssize_t cmd_list_domains(struct ltt_session *session, struct lttng_domain **domains)
+ssize_t cmd_list_domains(const ltt_session::locked_ref& session, struct lttng_domain **domains)
{
int ret, index = 0;
ssize_t nb_dom = 0;
* Command LTTNG_LIST_CHANNELS processed by the client thread.
*/
enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain,
- struct ltt_session *session,
+ const ltt_session::locked_ref& session,
struct lttng_payload *payload)
{
int ret = 0;
size_t cmd_header_offset;
enum lttng_error_code ret_code;
- assert(session);
- assert(payload);
+ LTTNG_ASSERT(payload);
DBG("Listing channels for session %s", session->name);
* Command LTTNG_LIST_EVENTS processed by the client thread.
*/
enum lttng_error_code cmd_list_events(enum lttng_domain_type domain,
- struct ltt_session *session,
+ const ltt_session::locked_ref& session,
char *channel_name,
struct lttng_payload *reply_payload)
{
{
int ret;
unsigned int i = 0;
- struct ltt_session *session;
+ struct ltt_session *raw_session_ptr;
struct ltt_session_list *list = session_get_list();
struct lttng_session_extended *extended = (typeof(extended)) (&sessions[session_count]);
* Iterate over session list and append data after the control struct in
* the buffer.
*/
- cds_list_for_each_entry (session, &list->head, list) {
- if (!session_get(session)) {
- continue;
- }
+ cds_list_for_each_entry (raw_session_ptr, &list->head, list) {
+ auto session = [raw_session_ptr]() {
+ session_get(raw_session_ptr);
+ raw_session_ptr->lock();
+ return ltt_session::locked_ref(*raw_session_ptr);
+ }();
+
/*
* Only list the sessions the user can control.
*/
if (!session_access_ok(session, uid) || session->destroyed) {
- session_put(session);
continue;
}
}
if (ret < 0) {
PERROR("snprintf session path");
- session_put(session);
continue;
}
extended[i].creation_time.value = (uint64_t) session->creation_time;
extended[i].creation_time.is_set = 1;
i++;
- session_put(session);
}
}
* Command LTTNG_DATA_PENDING returning 0 if the data is NOT pending meaning
* ready for trace analysis (or any kind of reader) or else 1 for pending data.
*/
-int cmd_data_pending(struct ltt_session *session)
+int cmd_data_pending(const ltt_session::locked_ref& session)
{
int ret;
struct ltt_kernel_session *ksess = session->kernel_session;
struct ltt_ust_session *usess = session->ust_session;
- LTTNG_ASSERT(session);
-
DBG("Data pending for session %s", session->name);
/* Session MUST be stopped to ask for data availability. */
*
* Return LTTNG_OK on success or else a LTTNG_ERR code.
*/
-int cmd_snapshot_add_output(struct ltt_session *session,
+int cmd_snapshot_add_output(const ltt_session::locked_ref& session,
const struct lttng_snapshot_output *output,
uint32_t *id)
{
int ret;
struct snapshot_output *new_output;
- LTTNG_ASSERT(session);
LTTNG_ASSERT(output);
DBG("Cmd snapshot add output for session %s", session->name);
*
* Return LTTNG_OK on success or else a LTTNG_ERR code.
*/
-int cmd_snapshot_del_output(struct ltt_session *session, const struct lttng_snapshot_output *output)
+int cmd_snapshot_del_output(const ltt_session::locked_ref& session,
+ const struct lttng_snapshot_output *output)
{
int ret;
struct snapshot_output *sout = nullptr;
- LTTNG_ASSERT(session);
LTTNG_ASSERT(output);
lttng::urcu::read_lock_guard read_lock;
*
* Return the size of the newly allocated outputs or a negative LTTNG_ERR code.
*/
-ssize_t cmd_snapshot_list_outputs(struct ltt_session *session,
+ssize_t cmd_snapshot_list_outputs(const ltt_session::locked_ref& session,
struct lttng_snapshot_output **outputs)
{
int ret, idx = 0;
struct lttng_ht_iter iter;
struct snapshot_output *output;
- LTTNG_ASSERT(session);
LTTNG_ASSERT(outputs);
DBG("Cmd snapshot list outputs for session %s", session->name);
*
* Return 0 if the metadata can be generated, a LTTNG_ERR code otherwise.
*/
-static int check_regenerate_metadata_support(struct ltt_session *session)
+static int check_regenerate_metadata_support(const ltt_session::locked_ref& session)
{
int ret;
- LTTNG_ASSERT(session);
-
if (session->live_timer != 0) {
ret = LTTNG_ERR_LIVE_SESSION;
goto end;
*
* Return LTTNG_OK on success or else a LTTNG_ERR code.
*/
-int cmd_regenerate_metadata(struct ltt_session *session)
+int cmd_regenerate_metadata(const ltt_session::locked_ref& session)
{
int ret;
- LTTNG_ASSERT(session);
-
ret = check_regenerate_metadata_support(session);
if (ret) {
goto end;
*
* Return LTTNG_OK on success or else a LTTNG_ERR code.
*/
-int cmd_regenerate_statedump(struct ltt_session *session)
+int cmd_regenerate_statedump(const ltt_session::locked_ref& session)
{
int ret;
- LTTNG_ASSERT(session);
-
if (!session->active) {
ret = LTTNG_ERR_SESSION_NOT_STARTED;
goto end;
* Return LTTNG_OK on success or a LTTNG_ERR code.
*/
static enum lttng_error_code set_relayd_for_snapshot(struct consumer_output *output,
- const struct ltt_session *session)
+ const ltt_session::locked_ref& session)
{
enum lttng_error_code status = LTTNG_OK;
struct lttng_ht_iter iter;
const char *base_path;
LTTNG_ASSERT(output);
- LTTNG_ASSERT(session);
DBG2("Set relayd object from snapshot output");
*/
static enum lttng_error_code record_kernel_snapshot(struct ltt_kernel_session *ksess,
const struct consumer_output *output,
- const struct ltt_session *session,
uint64_t nb_packets_per_stream)
{
enum lttng_error_code status;
LTTNG_ASSERT(ksess);
LTTNG_ASSERT(output);
- LTTNG_ASSERT(session);
status = kernel_snapshot_record(ksess, output, nb_packets_per_stream);
return status;
*/
static enum lttng_error_code record_ust_snapshot(struct ltt_ust_session *usess,
const struct consumer_output *output,
- const struct ltt_session *session,
uint64_t nb_packets_per_stream)
{
enum lttng_error_code status;
LTTNG_ASSERT(usess);
LTTNG_ASSERT(output);
- LTTNG_ASSERT(session);
status = ust_app_snapshot_record(usess, output, nb_packets_per_stream);
return status;
}
-static uint64_t get_session_size_one_more_packet_per_stream(const struct ltt_session *session,
+static uint64_t get_session_size_one_more_packet_per_stream(const ltt_session::locked_ref& session,
uint64_t cur_nr_packets)
{
uint64_t tot_size = 0;
* an approximation: for instance, applications could appear/disappear
* in between this call and actually grabbing data.
*/
-static int64_t get_session_nb_packets_per_stream(const struct ltt_session *session,
+static int64_t get_session_nb_packets_per_stream(const ltt_session::locked_ref& session,
uint64_t max_size)
{
int64_t size_left;
return cur_nb_packets;
}
-static enum lttng_error_code snapshot_record(struct ltt_session *session,
+static enum lttng_error_code snapshot_record(const ltt_session::locked_ref& session,
const struct snapshot_output *snapshot_output)
{
int64_t nb_packets_per_stream;
if (session->kernel_session) {
ret_code = record_kernel_snapshot(session->kernel_session,
snapshot_kernel_consumer_output,
- session,
nb_packets_per_stream);
if (ret_code != LTTNG_OK) {
goto error_close_trace_chunk;
}
if (session->ust_session) {
- ret_code = record_ust_snapshot(session->ust_session,
- snapshot_ust_consumer_output,
- session,
- nb_packets_per_stream);
+ ret_code = record_ust_snapshot(
+ session->ust_session, snapshot_ust_consumer_output, nb_packets_per_stream);
if (ret_code != LTTNG_OK) {
goto error_close_trace_chunk;
}
*
* Return LTTNG_OK on success or else a LTTNG_ERR code.
*/
-int cmd_snapshot_record(struct ltt_session *session,
+int cmd_snapshot_record(const ltt_session::locked_ref& session,
const struct lttng_snapshot_output *output,
int wait __attribute__((unused)))
{
char datetime[16];
struct snapshot_output *tmp_output = nullptr;
- LTTNG_ASSERT(session);
LTTNG_ASSERT(output);
DBG("Cmd snapshot record for session %s", session->name);
/*
* Command LTTNG_SET_SESSION_SHM_PATH processed by the client thread.
*/
-int cmd_set_session_shm_path(struct ltt_session *session, const char *shm_path)
+int cmd_set_session_shm_path(const ltt_session::locked_ref& session, const char *shm_path)
{
- /* Safety net */
- LTTNG_ASSERT(session);
-
/*
* Can only set shm path before session is started.
*/
*
* Returns LTTNG_OK on success or else a negative LTTng error code.
*/
-int cmd_rotate_session(struct ltt_session *session,
+int cmd_rotate_session(const ltt_session::locked_ref& session,
struct lttng_rotate_session_return *rotate_return,
bool quiet_rotation,
enum lttng_trace_chunk_command_type command)
bool failed_to_rotate = false;
enum lttng_error_code rotation_fail_code = LTTNG_OK;
- LTTNG_ASSERT(session);
-
if (!session->has_been_started) {
cmd_ret = LTTNG_ERR_START_SESSION_ONCE;
goto end;
ret = (cmd_ret == LTTNG_OK) ? cmd_ret : -((int) cmd_ret);
return ret;
error:
- if (session_reset_rotation_state(*session, LTTNG_ROTATION_STATE_ERROR)) {
+ if (session_reset_rotation_state(session, LTTNG_ROTATION_STATE_ERROR)) {
ERR("Failed to reset rotation state of session \"%s\"", session->name);
}
goto end;
*
* Return LTTNG_OK on success or else an LTTNG_ERR code.
*/
-int cmd_rotate_get_info(struct ltt_session *session,
+int cmd_rotate_get_info(const ltt_session::locked_ref& session,
struct lttng_rotation_get_info_return *info_return,
uint64_t rotation_id)
{
*
* Return LTTNG_OK on success or else a positive LTTNG_ERR code.
*/
-int cmd_rotation_set_schedule(struct ltt_session *session,
+int cmd_rotation_set_schedule(const ltt_session::locked_ref& session,
bool activate,
enum lttng_rotation_schedule_type schedule_type,
uint64_t new_value)
int ret;
uint64_t *parameter_value;
- LTTNG_ASSERT(session);
-
DBG("Cmd rotate set schedule session %s", session->name);
if (session->live_timer || !session->output_traces) {
#include "lttng-sessiond.hpp"
#include "lttng/tracker.h"
#include "session.hpp"
+#include "snapshot-output.hpp"
#include <common/tracker.hpp>
enum lttng_error_code cmd_create_session(struct command_ctx *cmd_ctx,
int sock,
struct lttng_session_descriptor **return_descriptor);
-int cmd_destroy_session(struct ltt_session *session, int *sock_fd);
+int cmd_destroy_session(const ltt_session::locked_ref& session, int *sock_fd);
/* Channel commands */
-int cmd_disable_channel(struct ltt_session *session,
+int cmd_disable_channel(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
char *channel_name);
int cmd_enable_channel(struct command_ctx *cmd_ctx,
/* Process attribute tracker commands */
enum lttng_error_code
-cmd_process_attr_tracker_get_tracking_policy(struct ltt_session *session,
+cmd_process_attr_tracker_get_tracking_policy(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
enum lttng_tracking_policy *policy);
enum lttng_error_code
-cmd_process_attr_tracker_set_tracking_policy(struct ltt_session *session,
+cmd_process_attr_tracker_set_tracking_policy(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
enum lttng_tracking_policy policy);
enum lttng_error_code
-cmd_process_attr_tracker_inclusion_set_add_value(struct ltt_session *session,
+cmd_process_attr_tracker_inclusion_set_add_value(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
const struct process_attr_value *value);
enum lttng_error_code
-cmd_process_attr_tracker_inclusion_set_remove_value(struct ltt_session *session,
+cmd_process_attr_tracker_inclusion_set_remove_value(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
const struct process_attr_value *value);
enum lttng_error_code
-cmd_process_attr_tracker_get_inclusion_set(struct ltt_session *session,
+cmd_process_attr_tracker_get_inclusion_set(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
struct lttng_process_attr_values **values);
int wpipe);
/* Trace session action commands */
-int cmd_start_trace(struct ltt_session *session);
-int cmd_stop_trace(struct ltt_session *session);
+int cmd_start_trace(const ltt_session::locked_ref& session);
+int cmd_stop_trace(const ltt_session::locked_ref& session);
/* Consumer commands */
-int cmd_register_consumer(struct ltt_session *session,
+int cmd_register_consumer(const ltt_session::locked_ref& session,
enum lttng_domain_type domain,
const char *sock_path,
struct consumer_data *cdata);
-int cmd_set_consumer_uri(struct ltt_session *session, size_t nb_uri, struct lttng_uri *uris);
-int cmd_setup_relayd(struct ltt_session *session);
+int cmd_set_consumer_uri(const ltt_session::locked_ref& session,
+ size_t nb_uri,
+ struct lttng_uri *uris);
+int cmd_setup_relayd(const ltt_session::locked_ref& session);
/* Listing commands */
-ssize_t cmd_list_domains(struct ltt_session *session, struct lttng_domain **domains);
+ssize_t cmd_list_domains(const ltt_session::locked_ref& session, struct lttng_domain **domains);
enum lttng_error_code cmd_list_events(enum lttng_domain_type domain,
- struct ltt_session *session,
+ const ltt_session::locked_ref& session,
char *channel_name,
struct lttng_payload *payload);
enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain,
- struct ltt_session *session,
+ const ltt_session::locked_ref& session,
struct lttng_payload *payload);
-void cmd_list_lttng_sessions(struct lttng_session *sessions,
- size_t session_count,
- uid_t uid,
- gid_t gid);
+void cmd_list_lttng_sessions(lttng_session *sessions, size_t session_count, uid_t uid, gid_t gid);
enum lttng_error_code cmd_list_tracepoint_fields(enum lttng_domain_type domain,
struct lttng_payload *reply);
enum lttng_error_code cmd_list_tracepoints(enum lttng_domain_type domain,
struct lttng_payload *reply_payload);
-ssize_t cmd_snapshot_list_outputs(struct ltt_session *session,
+ssize_t cmd_snapshot_list_outputs(const ltt_session::locked_ref& session,
struct lttng_snapshot_output **outputs);
enum lttng_error_code cmd_list_syscalls(struct lttng_payload *reply_payload);
-int cmd_data_pending(struct ltt_session *session);
+int cmd_data_pending(const ltt_session::locked_ref& session);
enum lttng_error_code cmd_kernel_tracer_status(enum lttng_kernel_tracer_status *status);
/* Snapshot */
-int cmd_snapshot_add_output(struct ltt_session *session,
+int cmd_snapshot_add_output(const ltt_session::locked_ref& session,
const struct lttng_snapshot_output *output,
uint32_t *id);
-int cmd_snapshot_del_output(struct ltt_session *session,
+int cmd_snapshot_del_output(const ltt_session::locked_ref& session,
const struct lttng_snapshot_output *output);
-int cmd_snapshot_record(struct ltt_session *session,
+int cmd_snapshot_record(const ltt_session::locked_ref& session,
const struct lttng_snapshot_output *output,
int wait);
-int cmd_set_session_shm_path(struct ltt_session *session, const char *shm_path);
-int cmd_regenerate_metadata(struct ltt_session *session);
-int cmd_regenerate_statedump(struct ltt_session *session);
+int cmd_set_session_shm_path(const ltt_session::locked_ref& session, const char *shm_path);
+int cmd_regenerate_metadata(const ltt_session::locked_ref& session);
+int cmd_regenerate_statedump(const ltt_session::locked_ref& session);
lttng::ctl::trigger
cmd_register_trigger(const struct lttng_credentials *cmd_creds,
struct lttng_error_query_results **_results,
struct notification_thread_handle *notification_thread);
-int cmd_rotate_session(struct ltt_session *session,
+int cmd_rotate_session(const ltt_session::locked_ref& session,
struct lttng_rotate_session_return *rotate_return,
bool quiet_rotation,
enum lttng_trace_chunk_command_type command);
-int cmd_rotate_get_info(struct ltt_session *session,
+int cmd_rotate_get_info(const ltt_session::locked_ref& session,
struct lttng_rotation_get_info_return *info_return,
uint64_t rotate_id);
-int cmd_rotation_set_schedule(struct ltt_session *session,
+int cmd_rotation_set_schedule(const ltt_session::locked_ref& session,
bool activate,
enum lttng_rotation_schedule_type schedule_type,
uint64_t value);
--- /dev/null
+/*
+ * Copyright (C) 2024 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CONSUMER_DESTINATION_TYPE_HPP
+#define LTTNG_CONSUMER_DESTINATION_TYPE_HPP
+
+enum consumer_dst_type {
+ CONSUMER_DST_LOCAL,
+ CONSUMER_DST_NET,
+};
+
+#endif /* LTTNG_CONSUMER_DESTINATION_TYPE_HPP */
--- /dev/null
+/*
+ * Copyright (C) 2024 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CONSUMER_OUTPUT_HPP
+#define LTTNG_CONSUMER_OUTPUT_HPP
+
+#include "session.hpp"
+
+int consumer_set_network_uri(const ltt_session::locked_ref& session,
+ struct consumer_output *obj,
+ struct lttng_uri *uri);
+
+#endif /* LTTNG_CONSUMER_OUTPUT_HPP */
*/
#define _LGPL_SOURCE
+#include "consumer-output.hpp"
#include "consumer.hpp"
#include "health-sessiond.hpp"
#include "lttng-sessiond.hpp"
* Return 0 on success. Return 1 if the URI were equal. Else, negative value on
* error.
*/
-int consumer_set_network_uri(const struct ltt_session *session,
+int consumer_set_network_uri(const ltt_session::locked_ref& session,
struct consumer_output *output,
struct lttng_uri *uri)
{
#ifndef _CONSUMER_H
#define _CONSUMER_H
+#include "consumer-destination-type.hpp"
#include "snapshot.hpp"
#include <common/consumer/consumer.hpp>
struct snapshot;
struct snapshot_output;
-struct ltt_session;
/*
* Needed until we use C++14, where std::max is constexpr.
return l > r ? l : r;
}
-enum consumer_dst_type {
- CONSUMER_DST_LOCAL,
- CONSUMER_DST_NET,
-};
-
enum consumer_trace_chunk_exists_status {
CONSUMER_TRACE_CHUNK_EXISTS_STATUS_EXISTS_LOCAL,
CONSUMER_TRACE_CHUNK_EXISTS_STATUS_EXISTS_REMOTE,
struct consumer_output *consumer_copy_output(struct consumer_output *obj);
void consumer_output_get(struct consumer_output *obj);
void consumer_output_put(struct consumer_output *obj);
-int consumer_set_network_uri(const struct ltt_session *session,
- struct consumer_output *obj,
- struct lttng_uri *uri);
+
int consumer_send_fds(struct consumer_socket *sock, const int *fds, size_t nb_fd);
int consumer_send_msg(struct consumer_socket *sock, const struct lttcomm_consumer_msg *msg);
int consumer_send_stream(struct consumer_socket *sock,
err = 0;
goto error;
}
-
}
} while (node != nullptr);
bool is_local_trace;
size_t consumer_path_offset = 0;
lttng::urcu::read_lock_guard read_lock;
- ltt_session::ref session;
/* Safety net */
LTTNG_ASSERT(channel);
health_code_update();
try {
- session = ltt_session::find_session(ksession->id);
+ const auto session = ltt_session::find_session(ksession->id);
+
+ ASSERT_SESSION_LIST_LOCKED();
+
+ status = notification_thread_command_add_channel(
+ the_notification_thread_handle,
+ session->id,
+ channel->channel->name,
+ channel->key,
+ LTTNG_DOMAIN_KERNEL,
+ channel->channel->attr.subbuf_size * channel->channel->attr.num_subbuf);
} catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
ERR_FMT("Fatal error during the creation of a kernel channel: {}, location='{}'",
ex.what(),
abort();
}
- ASSERT_LOCKED(session->_lock);
- ASSERT_SESSION_LIST_LOCKED();
-
- status = notification_thread_command_add_channel(the_notification_thread_handle,
- session->id,
- channel->channel->name,
- channel->key,
- LTTNG_DOMAIN_KERNEL,
- channel->channel->attr.subbuf_size *
- channel->channel->attr.num_subbuf);
if (status != LTTNG_OK) {
ret = -1;
goto error;
* Create a new kernel session, register it to the kernel tracer and add it to
* the session daemon session.
*/
-int kernel_create_session(struct ltt_session *session)
+int kernel_create_session(const ltt_session::locked_ref& session)
{
int ret;
struct ltt_kernel_session *lks;
- LTTNG_ASSERT(session);
-
/* Allocate data structure */
lks = trace_kernel_create_session();
if (lks == nullptr) {
*
* Return LTTNG_OK on success or else an LTTng error code.
*/
-enum lttng_error_code kernel_rotate_session(struct ltt_session *session)
+enum lttng_error_code kernel_rotate_session(const ltt_session::locked_ref& session)
{
int ret;
enum lttng_error_code status = LTTNG_OK;
*
* Return LTTNG_OK on success or else an LTTng error code.
*/
-enum lttng_error_code kernel_clear_session(struct ltt_session *session)
+enum lttng_error_code kernel_clear_session(const ltt_session::locked_ref& session)
{
int ret;
enum lttng_error_code status = LTTNG_OK;
#define KERNEL_EVENT_INIT_LIST_SIZE 64
int kernel_add_channel_context(struct ltt_kernel_channel *chan, struct ltt_kernel_context *ctx);
-int kernel_create_session(struct ltt_session *session);
+int kernel_create_session(const ltt_session::locked_ref& session);
int kernel_create_channel(struct ltt_kernel_session *session, struct lttng_channel *chan);
int kernel_create_event(struct lttng_event *ev,
struct ltt_kernel_channel *channel,
const struct consumer_output *output,
uint64_t nb_packets_per_stream);
int kernel_syscall_mask(int chan_fd, char **syscall_mask, uint32_t *nr_bits);
-enum lttng_error_code kernel_rotate_session(struct ltt_session *session);
-enum lttng_error_code kernel_clear_session(struct ltt_session *session);
+enum lttng_error_code kernel_rotate_session(const ltt_session::locked_ref& session);
+enum lttng_error_code kernel_clear_session(const ltt_session::locked_ref& session);
int init_kernel_workarounds();
int kernel_supports_ring_buffer_snapshot_sample_positions();
static void destroy_all_sessions_and_wait()
{
- struct ltt_session *session, *tmp;
+ struct ltt_session *raw_session_ptr, *tmp;
struct ltt_session_list *session_list;
DBG("Initiating destruction of all sessions");
}
/* Initiate the destruction of all sessions. */
- cds_list_for_each_entry_safe (session, tmp, &session_list->head, list) {
- if (!session_get(session)) {
- continue;
- }
+ cds_list_for_each_entry_safe (raw_session_ptr, tmp, &session_list->head, list) {
+ const auto session = [raw_session_ptr]() {
+ session_get(raw_session_ptr);
+ raw_session_ptr->lock();
+ return ltt_session::locked_ref(*raw_session_ptr);
+ }();
- session_lock(session);
if (session->destroyed) {
- goto unlock_session;
+ continue;
}
+
(void) cmd_stop_trace(session);
(void) cmd_destroy_session(session, nullptr);
- unlock_session:
- session_unlock(session);
- session_put(session);
}
/* Wait for the destruction of all sessions to complete. */
return exists;
}
-void check_session_rotation_pending_on_consumers(ltt_session& session, bool& _rotation_completed)
+void check_session_rotation_pending_on_consumers(const ltt_session::locked_ref& session,
+ bool& _rotation_completed)
{
int ret = 0;
struct consumer_socket *socket;
enum lttng_trace_chunk_status chunk_status;
lttng::urcu::read_lock_guard read_lock;
- LTTNG_ASSERT(session.chunk_being_archived);
+ LTTNG_ASSERT(session->chunk_being_archived);
/*
* Check for a local pending rotation on all consumers (32-bit
* user space, 64-bit user space, and kernel).
*/
- if (!session.ust_session) {
+ if (!session->ust_session) {
goto skip_ust;
}
cds_lfht_for_each_entry (
- session.ust_session->consumer->socks->ht, &iter, socket, node.node) {
- relayd_id = session.ust_session->consumer->type == CONSUMER_DST_LOCAL ?
+ session->ust_session->consumer->socks->ht, &iter, socket, node.node) {
+ relayd_id = session->ust_session->consumer->type == CONSUMER_DST_LOCAL ?
-1ULL :
- session.ust_session->consumer->net_seq_index;
+ session->ust_session->consumer->net_seq_index;
lttng::pthread::lock_guard socket_lock(*socket->lock);
ret = consumer_trace_chunk_exists(socket,
relayd_id,
- session.id,
- session.chunk_being_archived,
+ session->id,
+ session->chunk_being_archived,
&exists_status);
if (ret) {
ERR("Error occurred while checking rotation status on consumer daemon");
}
skip_ust:
- if (!session.kernel_session) {
+ if (!session->kernel_session) {
goto skip_kernel;
}
cds_lfht_for_each_entry (
- session.kernel_session->consumer->socks->ht, &iter, socket, node.node) {
+ session->kernel_session->consumer->socks->ht, &iter, socket, node.node) {
lttng::pthread::lock_guard socket_lock(*socket->lock);
- relayd_id = session.kernel_session->consumer->type == CONSUMER_DST_LOCAL ?
+ relayd_id = session->kernel_session->consumer->type == CONSUMER_DST_LOCAL ?
-1ULL :
- session.kernel_session->consumer->net_seq_index;
+ session->kernel_session->consumer->net_seq_index;
ret = consumer_trace_chunk_exists(socket,
relayd_id,
- session.id,
- session.chunk_being_archived,
+ session->id,
+ session->chunk_being_archived,
&exists_status);
if (ret) {
ERR("Error occurred while checking rotation status on consumer daemon");
if (!chunk_exists_on_peer) {
uint64_t chunk_being_archived_id;
- chunk_status = lttng_trace_chunk_get_id(session.chunk_being_archived,
+ chunk_status = lttng_trace_chunk_get_id(session->chunk_being_archived,
&chunk_being_archived_id);
LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK);
DBG("Rotation of trace archive %" PRIu64
" of session \"%s\" is complete on all consumers",
chunk_being_archived_id,
- session.name);
+ session->name);
}
_rotation_completed = !chunk_exists_on_peer;
if (ret) {
ret = session_reset_rotation_state(session, LTTNG_ROTATION_STATE_ERROR);
if (ret) {
- ERR("Failed to reset rotation state of session \"%s\"", session.name);
+ ERR("Failed to reset rotation state of session \"%s\"", session->name);
}
}
}
* Should only return non-zero in the event of a fatal error. Doing so will
* shutdown the thread.
*/
-int check_session_rotation_pending(ltt_session& session,
+int check_session_rotation_pending(const ltt_session::locked_ref& session,
notification_thread_handle& notification_thread_handle)
{
int ret;
const char *archived_chunk_name;
uint64_t chunk_being_archived_id;
- if (!session.chunk_being_archived) {
+ if (!session->chunk_being_archived) {
ret = 0;
goto end;
}
chunk_status =
- lttng_trace_chunk_get_id(session.chunk_being_archived, &chunk_being_archived_id);
+ lttng_trace_chunk_get_id(session->chunk_being_archived, &chunk_being_archived_id);
LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK);
DBG("Checking for pending rotation on session \"%s\", trace archive %" PRIu64,
- session.name,
+ session->name,
chunk_being_archived_id);
/*
}
check_session_rotation_pending_on_consumers(session, rotation_completed);
- if (!rotation_completed || session.rotation_state == LTTNG_ROTATION_STATE_ERROR) {
+ if (!rotation_completed || session->rotation_state == LTTNG_ROTATION_STATE_ERROR) {
goto check_ongoing_rotation;
}
* rotations can start now.
*/
chunk_status = lttng_trace_chunk_get_name(
- session.chunk_being_archived, &archived_chunk_name, nullptr);
+ session->chunk_being_archived, &archived_chunk_name, nullptr);
LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK);
- free(session.last_archived_chunk_name);
- session.last_archived_chunk_name = strdup(archived_chunk_name);
- if (!session.last_archived_chunk_name) {
+ free(session->last_archived_chunk_name);
+ session->last_archived_chunk_name = strdup(archived_chunk_name);
+ if (!session->last_archived_chunk_name) {
PERROR("Failed to duplicate archived chunk name");
}
session_reset_rotation_state(session, LTTNG_ROTATION_STATE_COMPLETED);
- if (!session.quiet_rotation) {
- location = session_get_trace_archive_location(&session);
+ if (!session->quiet_rotation) {
+ location = session_get_trace_archive_location(session);
ret = notification_thread_command_session_rotation_completed(
¬ification_thread_handle,
- session.id,
- session.last_archived_chunk_id.value,
+ session->id,
+ session->last_archived_chunk_id.value,
location);
lttng_trace_archive_location_put(location);
if (ret != LTTNG_OK) {
ERR("Failed to notify notification thread of completed rotation for session %s",
- session.name);
+ session->name);
}
}
ret = 0;
check_ongoing_rotation:
- if (session.rotation_state == LTTNG_ROTATION_STATE_ONGOING) {
- chunk_status = lttng_trace_chunk_get_id(session.chunk_being_archived,
+ if (session->rotation_state == LTTNG_ROTATION_STATE_ONGOING) {
+ chunk_status = lttng_trace_chunk_get_id(session->chunk_being_archived,
&chunk_being_archived_id);
LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK);
DBG("Rotation of trace archive %" PRIu64 " is still pending for session %s",
chunk_being_archived_id,
- session.name);
- ret = timer_session_rotation_pending_check_start(&session,
+ session->name);
+ ret = timer_session_rotation_pending_check_start(session,
DEFAULT_ROTATE_PENDING_TIMER);
if (ret) {
ERR("Failed to re-enable rotation pending timer");
}
/* Call with the session and session_list locks held. */
-int launch_session_rotation(ltt_session& session)
+void launch_session_rotation(const ltt_session::locked_ref& session)
{
int ret;
- struct lttng_rotate_session_return rotation_return;
- DBG("Launching scheduled time-based rotation on session \"%s\"", session.name);
+ DBG_FMT("Launching scheduled time-based rotation: session_name='{}'", session->name);
ASSERT_SESSION_LIST_LOCKED();
- ASSERT_LOCKED(session._lock);
- ret = cmd_rotate_session(&session,
- &rotation_return,
- false,
- LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED);
- if (ret == LTTNG_OK) {
- DBG("Scheduled time-based rotation successfully launched on session \"%s\"",
- session.name);
+ ret = cmd_rotate_session(
+ session, nullptr, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED);
+ if (ret != LTTNG_OK) {
+ LTTNG_THROW_CTL(fmt::format("Failed to launch session rotation: session_name={}",
+ session->name),
+ static_cast<lttng_error_code>(ret));
} else {
/* Don't consider errors as fatal. */
- DBG("Scheduled time-based rotation aborted for session %s: %s",
- session.name,
- lttng_strerror(ret));
+ DBG_FMT("Scheduled time-based rotation aborted session_name=`{}`, error='{}'",
+ session->name,
+ lttng_strerror(ret));
}
-
- return 0;
}
int run_job(const rotation_thread_job& job,
- ltt_session& session,
+ const ltt_session::locked_ref& session,
notification_thread_handle& notification_thread_handle)
{
- int ret;
+ int ret = 0;
switch (job.type) {
case ls::rotation_thread_job_type::SCHEDULED_ROTATION:
- ret = launch_session_rotation(session);
+ try {
+ launch_session_rotation(session);
+ DBG("Scheduled time-based rotation successfully launched on session \"%s\"",
+ session->name);
+ } catch (const lttng::ctl::error& ctl_ex) {
+ /* Don't consider errors as fatal. */
+ DBG("Scheduled time-based rotation aborted for session %s: %s",
+ session->name,
+ lttng_strerror(ctl_ex.code()));
+ }
break;
case ls::rotation_thread_job_type::CHECK_PENDING_ROTATION:
ret = check_session_rotation_pending(session, notification_thread_handle);
/* locked_ref will unlock the session and release the ref held by the job. */
session_lock(job->session);
- auto session = ltt_session::locked_ref(job->session);
+ auto session = ltt_session::locked_ref(*job->session);
- if (run_job(*job, *session, _notification_thread_handle)) {
+ if (run_job(*job, session, _notification_thread_handle)) {
return;
}
}
* sessions.
*/
const auto list_lock = lttng::sessiond::lock_session_list();
- ltt_session::locked_ref session;
try {
- session = ltt_session::find_locked_session(condition_session_name);
+ const auto session = ltt_session::find_locked_session(condition_session_name);
+
+ if (!lttng_trigger_is_equal(session->rotate_trigger,
+ lttng_notification_get_const_trigger(¬ification))) {
+ DBG("Notification does not originate from the internal size-based scheduled rotation trigger, skipping");
+ return;
+ }
+
+ unsubscribe_session_consumed_size_rotation(*session);
+
+ ret = cmd_rotate_session(
+ session, nullptr, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED);
+ if (ret != LTTNG_OK) {
+ switch (ret) {
+ case LTTNG_OK:
+ break;
+ case -LTTNG_ERR_ROTATION_PENDING:
+ DBG("Rotate already pending, subscribe to the next threshold value");
+ break;
+ case -LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP:
+ DBG("Rotation already happened since last stop, subscribe to the next threshold value");
+ break;
+ case -LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR:
+ DBG("Rotation already happened since last stop and clear, subscribe to the next threshold value");
+ break;
+ default:
+ LTTNG_THROW_CTL("Failed to rotate on consumed size notification",
+ static_cast<lttng_error_code>(-ret));
+ }
+ }
+
+ subscribe_session_consumed_size_rotation(*session, consumed + session->rotate_size);
} catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
DBG_FMT("Failed to find session while handling notification: notification_type={}, session name=`{}`",
lttng_condition_type_str(condition_type),
*/
return;
}
-
- if (!lttng_trigger_is_equal(session->rotate_trigger,
- lttng_notification_get_const_trigger(¬ification))) {
- DBG("Notification does not originate from the internal size-based scheduled rotation trigger, skipping");
- return;
- }
-
- unsubscribe_session_consumed_size_rotation(*session);
-
- ret = cmd_rotate_session(
- session.get(), nullptr, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED);
- switch (ret) {
- case LTTNG_OK:
- break;
- case -LTTNG_ERR_ROTATION_PENDING:
- DBG("Rotate already pending, subscribe to the next threshold value");
- break;
- case -LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP:
- DBG("Rotation already happened since last stop, subscribe to the next threshold value");
- break;
- case -LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR:
- DBG("Rotation already happened since last stop and clear, subscribe to the next threshold value");
- break;
- default:
- LTTNG_THROW_CTL("Failed to rotate on consumed size notification",
- static_cast<lttng_error_code>(-ret));
- }
-
- subscribe_session_consumed_size_rotation(*session, consumed + session->rotate_size);
}
void ls::rotation_thread::_handle_notification_channel_activity()
}
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
-static int save_kernel_session(struct config_writer *writer, struct ltt_session *session)
+static int save_kernel_session(struct config_writer *writer, const ltt_session::locked_ref& session)
{
int ret;
struct ltt_kernel_channel *kchan;
LTTNG_ASSERT(writer);
- LTTNG_ASSERT(session);
ret = config_writer_write_element_string(
writer, config_element_type, config_domain_type_kernel);
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
static int save_process_attr_tracker(struct config_writer *writer,
- struct ltt_session *sess,
+ const ltt_session::locked_ref& session,
int domain,
enum lttng_process_attr process_attr)
{
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
{
- tracker = kernel_get_process_attr_tracker(sess->kernel_session, process_attr);
+ tracker = kernel_get_process_attr_tracker(session->kernel_session, process_attr);
LTTNG_ASSERT(tracker);
break;
}
case LTTNG_DOMAIN_UST:
{
- tracker = trace_ust_get_process_attr_tracker(sess->ust_session, process_attr);
+ tracker = trace_ust_get_process_attr_tracker(session->ust_session, process_attr);
LTTNG_ASSERT(tracker);
break;
}
}
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
-static int
-save_process_attr_trackers(struct config_writer *writer, struct ltt_session *sess, int domain)
+static int save_process_attr_trackers(struct config_writer *writer,
+ const ltt_session::locked_ref& session,
+ int domain)
{
int ret;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_PROCESS_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_PROCESS_ID);
if (ret != LTTNG_OK) {
goto end;
}
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
if (ret != LTTNG_OK) {
goto end;
}
- ret = save_process_attr_tracker(writer, sess, domain, LTTNG_PROCESS_ATTR_USER_ID);
+ ret = save_process_attr_tracker(
+ writer, session, domain, LTTNG_PROCESS_ATTR_USER_ID);
if (ret != LTTNG_OK) {
goto end;
}
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
if (ret != LTTNG_OK) {
goto end;
}
- ret = save_process_attr_tracker(writer, sess, domain, LTTNG_PROCESS_ATTR_GROUP_ID);
+ ret = save_process_attr_tracker(
+ writer, session, domain, LTTNG_PROCESS_ATTR_GROUP_ID);
if (ret != LTTNG_OK) {
goto end;
}
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
if (ret != LTTNG_OK) {
goto end;
}
break;
case LTTNG_DOMAIN_UST:
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
if (ret != LTTNG_OK) {
goto end;
}
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
if (ret != LTTNG_OK) {
goto end;
}
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
if (ret != LTTNG_OK) {
goto end;
}
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
static int save_ust_domain(struct config_writer *writer,
- struct ltt_session *session,
+ const ltt_session::locked_ref& session,
enum lttng_domain_type domain)
{
int ret;
const char *config_domain_name;
LTTNG_ASSERT(writer);
- LTTNG_ASSERT(session);
ret = config_writer_open_element(writer, config_element_domain);
if (ret) {
}
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
-static int save_domains(struct config_writer *writer, struct ltt_session *session)
+static int save_domains(struct config_writer *writer, const ltt_session::locked_ref& session)
{
int ret = LTTNG_OK;
LTTNG_ASSERT(writer);
- LTTNG_ASSERT(session);
if (!session->kernel_session && !session->ust_session) {
goto end;
}
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
-static int save_session_output(struct config_writer *writer, struct ltt_session *session)
+static int save_session_output(struct config_writer *writer, const ltt_session::locked_ref& session)
{
int ret;
LTTNG_ASSERT(writer);
- LTTNG_ASSERT(session);
if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
(!session->snapshot_mode && !session->consumer)) {
}
static int save_session_rotation_schedules(struct config_writer *writer,
- struct ltt_session *session)
+ const ltt_session::locked_ref& session)
{
int ret;
*
* Return LTTNG_OK on success else a LTTNG_ERR* code.
*/
-static int save_session(struct ltt_session *session,
+static int save_session(const ltt_session::locked_ref& session,
struct lttng_save_session_attr *attr,
lttng_sock_cred *creds)
{
const char *provided_path;
int file_open_flags = O_CREAT | O_WRONLY | O_TRUNC;
- LTTNG_ASSERT(session);
LTTNG_ASSERT(attr);
LTTNG_ASSERT(creds);
int cmd_save_sessions(struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
{
- int ret;
- const char *session_name;
-
const auto list_lock = lttng::sessiond::lock_session_list();
+ const auto session_name = lttng_save_session_attr_get_session_name(attr);
- session_name = lttng_save_session_attr_get_session_name(attr);
if (session_name) {
-
/*
- * Mind the order of the declaration of list_lock vs session:
- * the session list lock must always be released _after_ the release of
- * a session's reference (the destruction of a ref/locked_ref) to ensure
- * since the reference's release may unpublish the session from the list of
- * sessions.
- */
- ltt_session::locked_ref session;
-
+ * Mind the order of the declaration of list_lock vs session:
+ * the session list lock must always be released _after_ the release of
+ * a session's reference (the destruction of a ref/locked_ref) to ensure
+ * since the reference's release may unpublish the session from the list of
+ * sessions.
+ */
try {
- session = ltt_session::find_locked_session(session_name);
+ const auto session = ltt_session::find_locked_session(session_name);
+ const auto save_ret = save_session(session, attr, creds);
+ if (save_ret != LTTNG_OK) {
+ return save_ret;
+ }
} catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
WARN_FMT("Failed to save session: {} {}", ex.what(), ex.source_location);
- ret = LTTNG_ERR_SESS_NOT_FOUND;
- return ret;
- }
-
- ret = save_session(session.get(), attr, creds);
- if (ret != LTTNG_OK) {
- return ret;
+ return LTTNG_ERR_SESS_NOT_FOUND;
}
} else {
struct ltt_session_list *list = session_get_list();
- struct ltt_session *session;
+ struct ltt_session *raw_session_ptr;
+
+ cds_list_for_each_entry (raw_session_ptr, &list->head, list) {
+ auto session = [raw_session_ptr]() {
+ session_get(raw_session_ptr);
+ raw_session_ptr->lock();
+ return ltt_session::locked_ref(*raw_session_ptr);
+ }();
+ const auto save_ret = save_session(session, attr, creds);
- cds_list_for_each_entry (session, &list->head, list) {
- if (!session_get(session)) {
- continue;
- }
- session_lock(session);
- ret = save_session(session, attr, creds);
- session_unlock(session);
- session_put(session);
/* Don't abort if we don't have the required permissions. */
- if (ret != LTTNG_OK && ret != LTTNG_ERR_EPERM) {
- return ret;
+ if (save_ret != LTTNG_OK && save_ret != LTTNG_ERR_EPERM) {
+ return save_ret;
}
}
}
/*
* 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)
+enum consumer_dst_type session_get_consumer_destination_type(const ltt_session::locked_ref& session)
{
/*
* The output information is duplicated in both of those session types.
/*
* 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 *session_get_net_consumer_hostname(const ltt_session::locked_ref& session)
{
const char *hostname = nullptr;
const struct consumer_output *output;
/*
* 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,
+void session_get_net_consumer_ports(const ltt_session::locked_ref& session,
uint16_t *control_port,
uint16_t *data_port)
{
/*
* Get the location of the latest trace archive produced by a rotation.
- *
- * The caller must hold the session lock.
*/
struct lttng_trace_archive_location *
-session_get_trace_archive_location(const struct ltt_session *session)
+session_get_trace_archive_location(const ltt_session::locked_ref& session)
{
int ret;
struct lttng_trace_archive_location *location = nullptr;
session->unlock();
}
-void ltt_session::_const_session_unlock(const ltt_session &session)
+void ltt_session::_const_session_unlock(const ltt_session& session)
{
pthread_mutex_unlock(&session._lock);
}
-static int _session_set_trace_chunk_no_lock_check(struct ltt_session *session,
+static int _session_set_trace_chunk_no_lock_check(const ltt_session::locked_ref& session,
struct lttng_trace_chunk *new_trace_chunk,
struct lttng_trace_chunk **_current_trace_chunk)
{
}
struct lttng_trace_chunk *
-session_create_new_trace_chunk(const struct ltt_session *session,
+session_create_new_trace_chunk(const ltt_session::locked_ref& session,
const struct consumer_output *consumer_output_override,
const char *session_base_path_override,
const char *chunk_name_override)
goto end;
}
-int session_close_trace_chunk(struct ltt_session *session,
+int session_close_trace_chunk(const ltt_session::locked_ref& session,
struct lttng_trace_chunk *trace_chunk,
enum lttng_trace_chunk_command_type close_command,
char *closed_trace_chunk_path)
* daemon as the same "offset" in a metadata stream will no longer point
* to the same content.
*/
-static enum lttng_error_code session_kernel_open_packets(struct ltt_session *session)
+static enum lttng_error_code session_kernel_open_packets(const ltt_session::locked_ref& session)
{
enum lttng_error_code ret = LTTNG_OK;
struct consumer_socket *socket;
return ret;
}
-enum lttng_error_code session_open_packets(struct ltt_session *session)
+enum lttng_error_code session_open_packets(const ltt_session::locked_ref& session)
{
enum lttng_error_code ret = LTTNG_OK;
*
* Must be called with the session lock held.
*/
-int session_set_trace_chunk(struct ltt_session *session,
+int session_set_trace_chunk(const ltt_session::locked_ref& session,
struct lttng_trace_chunk *new_trace_chunk,
struct lttng_trace_chunk **current_trace_chunk)
{
session, new_trace_chunk, current_trace_chunk);
}
-static void session_notify_destruction(const struct ltt_session *session)
+static void session_notify_destruction(const ltt_session::locked_ref& session)
{
size_t i;
- const size_t count = lttng_dynamic_array_get_count(&session->destroy_notifiers);
+ const auto count = lttng_dynamic_array_get_count(&session->destroy_notifiers);
for (i = 0; i < count; i++) {
const struct ltt_session_destroy_notifier_element *element =
/*
* Fire each clear notifier once, and remove them from the array.
*/
-void session_notify_clear(ltt_session& session)
+void session_notify_clear(const ltt_session::locked_ref& session)
{
size_t i;
- const size_t count = lttng_dynamic_array_get_count(&session.clear_notifiers);
+ const auto count = lttng_dynamic_array_get_count(&session->clear_notifiers);
for (i = 0; i < count; i++) {
const struct ltt_session_clear_notifier_element *element =
(ltt_session_clear_notifier_element *) lttng_dynamic_array_get_element(
- &session.clear_notifiers, i);
+ &session->clear_notifiers, i);
- element->notifier(&session, element->user_data);
+ element->notifier(session, element->user_data);
}
- lttng_dynamic_array_clear(&session.clear_notifiers);
+ lttng_dynamic_array_clear(&session->clear_notifiers);
}
static void session_release(struct urcu_ref *ref)
snapshot_destroy(&session->snapshot);
- pthread_mutex_destroy(&session->_lock);
-
if (session_published) {
ASSERT_SESSION_LIST_LOCKED();
del_session_list(session);
del_session_ht(session);
}
- session_notify_destruction(session);
+
+ /*
+ * The notifiers make use of free-functions that expect a locked reference to a session.
+ * To create such a reference, we need to acquire the lock and acquire a reference (increase
+ * the ref-count). To ensure the release of the reference does not re-cross the zero value,
+ * set the refcount to a tombstone value.
+ */
+ session->ref_count.refcount = 0xDEAD5E55;
+ session_notify_destruction([session]() {
+ session_lock(session);
+ session_get(session);
+ return ltt_session::locked_ref(*session);
+ }());
+
+ pthread_mutex_destroy(&session->_lock);
consumer_output_put(session->consumer);
kernel_free_session(ksess);
session_put(session);
}
-int session_add_destroy_notifier(struct ltt_session *session,
+int session_add_destroy_notifier(const ltt_session::locked_ref& session,
ltt_session_destroy_notifier notifier,
void *user_data)
{
return lttng_dynamic_array_add_element(&session->destroy_notifiers, &element);
}
-int session_add_clear_notifier(struct ltt_session *session,
+int session_add_clear_notifier(const ltt_session::locked_ref& session,
ltt_session_clear_notifier notifier,
void *user_data)
{
* Check if the UID matches the session. Root user has access to all
* sessions.
*/
-bool session_access_ok(struct ltt_session *session, uid_t uid)
+bool session_access_ok(const ltt_session::locked_ref& session, uid_t uid)
{
- LTTNG_ASSERT(session);
return (uid == session->uid) || uid == 0;
}
*
* Must be called with the session and session_list locks held.
*/
-int session_reset_rotation_state(ltt_session& session, enum lttng_rotation_state result)
+int session_reset_rotation_state(const ltt_session::locked_ref& session,
+ enum lttng_rotation_state result)
{
int ret = 0;
ASSERT_SESSION_LIST_LOCKED();
- ASSERT_LOCKED(session._lock);
- session.rotation_state = result;
- if (session.rotation_pending_check_timer_enabled) {
+ session->rotation_state = result;
+ if (session->rotation_pending_check_timer_enabled) {
ret = timer_session_rotation_pending_check_stop(session);
}
- if (session.chunk_being_archived) {
+ if (session->chunk_being_archived) {
uint64_t chunk_id;
enum lttng_trace_chunk_status chunk_status;
- chunk_status = lttng_trace_chunk_get_id(session.chunk_being_archived, &chunk_id);
+ chunk_status = lttng_trace_chunk_get_id(session->chunk_being_archived, &chunk_id);
LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK);
- LTTNG_OPTIONAL_SET(&session.last_archived_chunk_id, chunk_id);
- lttng_trace_chunk_put(session.chunk_being_archived);
- session.chunk_being_archived = nullptr;
+ LTTNG_OPTIONAL_SET(&session->last_archived_chunk_id, chunk_id);
+ lttng_trace_chunk_put(session->chunk_being_archived);
+ session->chunk_being_archived = nullptr;
/*
* Fire the clear reply notifiers if we are completing a clear
* rotation.
* session.
*/
session_lock(session);
- return ltt_session::locked_ref(session);
+ return ltt_session::locked_ref(*session);
}
ltt_session::locked_ref ltt_session::find_locked_session(lttng::c_string_view name)
}
session_lock(session);
- return ltt_session::locked_ref(session);
+ return ltt_session::locked_ref(*session);
}
ltt_session::const_locked_ref ltt_session::find_locked_const_session(ltt_session::id_t id)
}
session_lock(session);
- return ltt_session::const_locked_ref(session);
+ return ltt_session::const_locked_ref(*session);
}
ltt_session::const_locked_ref ltt_session::find_locked_const_session(lttng::c_string_view name)
}
session_lock(session);
- return ltt_session::const_locked_ref(session);
+ return ltt_session::const_locked_ref(*session);
}
ltt_session::ref ltt_session::find_session(ltt_session::id_t id)
LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id);
}
- return ltt_session::ref(session);
+ return ltt_session::ref(*session);
}
ltt_session::ref ltt_session::find_session(lttng::c_string_view name)
LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name.data());
}
- return ltt_session::ref(session);
+ return ltt_session::ref(*session);
}
ltt_session::const_ref ltt_session::find_const_session(ltt_session::id_t id)
LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id);
}
- return ltt_session::const_ref(session);
+ return ltt_session::const_ref(*session);
}
ltt_session::const_ref ltt_session::find_const_session(lttng::c_string_view name)
LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name.data());
}
- return ltt_session::const_ref(session);
+ return ltt_session::const_ref(*session);
}
void ltt_session::_const_session_put(const ltt_session *session)
#include <common/hashtable/hashtable.hpp>
#include <common/make-unique-wrapper.hpp>
#include <common/pthread-lock.hpp>
+#include <common/reference.hpp>
#include <lttng/location.h>
#include <lttng/lttng-error.h>
struct ltt_ust_session;
-using ltt_session_destroy_notifier = void (*)(const struct ltt_session *, void *);
-using ltt_session_clear_notifier = void (*)(const struct ltt_session *, void *);
-
struct ltt_session;
struct ltt_session_list;
#define LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id) \
throw lttng::sessiond::exceptions::session_not_found_error(id, LTTNG_SOURCE_LOCATION())
-void session_destroy(struct ltt_session *session);
-int session_add_destroy_notifier(struct ltt_session *session,
- ltt_session_destroy_notifier notifier,
- void *user_data);
-
-int session_add_clear_notifier(struct ltt_session *session,
- ltt_session_clear_notifier notifier,
- void *user_data);
-void session_notify_clear(ltt_session& session);
-
-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 lttng_trace_archive_location *
-session_get_trace_archive_location(const struct ltt_session *session);
-
-struct ltt_session_list *session_get_list();
-void session_list_wait_empty(std::unique_lock<std::mutex> list_lock);
-
-bool session_access_ok(struct ltt_session *session, uid_t uid);
-
-int session_reset_rotation_state(ltt_session& session, enum lttng_rotation_state result);
-
-/* Create a new trace chunk object from the session's configuration. */
-struct lttng_trace_chunk *
-session_create_new_trace_chunk(const struct ltt_session *session,
- const struct consumer_output *consumer_output_override,
- const char *session_base_path_override,
- const char *chunk_name_override);
-
-/*
- * Set `new_trace_chunk` as the session's current trace chunk. A reference
- * to `new_trace_chunk` is acquired by the session. The chunk is created
- * on remote peers (consumer and relay daemons).
- *
- * A reference to the session's current trace chunk is returned through
- * `current_session_trace_chunk` on success.
- */
-int session_set_trace_chunk(struct ltt_session *session,
- struct lttng_trace_chunk *new_trace_chunk,
- struct lttng_trace_chunk **current_session_trace_chunk);
-
-/*
- * Close a chunk on the remote peers of a session. Has no effect on the
- * ltt_session itself.
- */
-int session_close_trace_chunk(struct ltt_session *session,
- struct lttng_trace_chunk *trace_chunk,
- enum lttng_trace_chunk_command_type close_command,
- char *path);
-
-/* Open a packet in all channels of a given session. */
-enum lttng_error_code session_open_packets(struct ltt_session *session);
-
-bool session_output_supports_trace_chunks(const struct ltt_session *session);
-
-/*
- * Sample the id of a session looked up via its name.
- * Here the term "sampling" hint the caller that this return the id at a given
- * point in time with no guarantee that the session for which the id was
- * sampled still exist at that point.
- *
- * Return 0 when the session is not found,
- * Return 1 when the session is found and set `id`.
- */
-bool sample_session_id_by_name(const char *name, uint64_t *id);
-
/*
* Tracing session list
*
static void _locked_session_release(ltt_session *session);
static void _locked_const_session_release(const ltt_session *session);
static void _const_session_put(const ltt_session *session);
- static void _const_session_unlock(const ltt_session &session);
+ static void _const_session_unlock(const ltt_session& session);
public:
- using locked_ref =
- std::unique_ptr<ltt_session,
- lttng::memory::create_deleter_class<
- ltt_session,
- ltt_session::_locked_session_release>::deleter>;
- using ref = std::unique_ptr<
+ using locked_ref = lttng::non_copyable_reference<
+ ltt_session,
+ lttng::memory::create_deleter_class<ltt_session,
+ ltt_session::_locked_session_release>::deleter>;
+ using ref = lttng::non_copyable_reference<
ltt_session,
lttng::memory::create_deleter_class<ltt_session, session_put>::deleter>;
- using const_locked_ref =
- std::unique_ptr<const ltt_session,
- lttng::memory::create_deleter_class<
- const ltt_session,
- ltt_session::_locked_const_session_release>::deleter>;
- using const_ref = std::unique_ptr<
+ using const_locked_ref = lttng::non_copyable_reference<
+ const ltt_session,
+ lttng::memory::create_deleter_class<
+ const ltt_session,
+ ltt_session::_locked_const_session_release>::deleter>;
+ using const_ref = lttng::non_copyable_reference<
const ltt_session,
- lttng::memory::create_deleter_class<const ltt_session, ltt_session::_const_session_put>::deleter>;
+ lttng::memory::create_deleter_class<const ltt_session,
+ ltt_session::_const_session_put>::deleter>;
void lock() const noexcept;
void unlock() const noexcept;
struct lttng_dynamic_array clear_notifiers;
/* Session base path override. Set non-null. */
char *base_path;
-
-
};
+/*
+ * Destruction notifiers are invoked in an exclusive context. There is no need for the session to be
+ * locked nor for a reference to be acquired.
+ */
+using ltt_session_destroy_notifier = void (*)(const ltt_session::locked_ref&, void *);
+using ltt_session_clear_notifier = void (*)(const ltt_session::locked_ref&, void *);
+
namespace lttng {
namespace sessiond {
}
/* NOLINTEND(google-explicit-constructor) */
- explicit query_parameter(ltt_session::id_t id_) : type(query_type::BY_ID), parameter(id_)
+ explicit query_parameter(ltt_session::id_t id_) :
+ type(query_type::BY_ID), parameter(id_)
{
}
} /* namespace sessiond */
} /* namespace lttng */
+void session_destroy(struct ltt_session *session);
+int session_add_destroy_notifier(const ltt_session::locked_ref& session,
+ ltt_session_destroy_notifier notifier,
+ void *user_data);
+
+int session_add_clear_notifier(const ltt_session::locked_ref& session,
+ ltt_session_clear_notifier notifier,
+ void *user_data);
+void session_notify_clear(const ltt_session::locked_ref& session);
+
+enum consumer_dst_type
+session_get_consumer_destination_type(const ltt_session::locked_ref& session);
+const char *session_get_net_consumer_hostname(const ltt_session::locked_ref& session);
+void session_get_net_consumer_ports(const ltt_session::locked_ref& session,
+ uint16_t *control_port,
+ uint16_t *data_port);
+struct lttng_trace_archive_location *
+session_get_trace_archive_location(const ltt_session::locked_ref& session);
+
+struct ltt_session_list *session_get_list();
+void session_list_wait_empty(std::unique_lock<std::mutex> list_lock);
+
+bool session_access_ok(const ltt_session::locked_ref& session, uid_t uid);
+
+int session_reset_rotation_state(const ltt_session::locked_ref& session,
+ enum lttng_rotation_state result);
+
+/* Create a new trace chunk object from the session's configuration. */
+struct lttng_trace_chunk *
+session_create_new_trace_chunk(const ltt_session::locked_ref& session,
+ const struct consumer_output *consumer_output_override,
+ const char *session_base_path_override,
+ const char *chunk_name_override);
+
+/*
+ * Set `new_trace_chunk` as the session's current trace chunk. A reference
+ * to `new_trace_chunk` is acquired by the session. The chunk is created
+ * on remote peers (consumer and relay daemons).
+ *
+ * A reference to the session's current trace chunk is returned through
+ * `current_session_trace_chunk` on success.
+ */
+int session_set_trace_chunk(const ltt_session::locked_ref& session,
+ struct lttng_trace_chunk *new_trace_chunk,
+ struct lttng_trace_chunk **current_session_trace_chunk);
+
+/*
+ * Close a chunk on the remote peers of a session. Has no effect on the
+ * ltt_session itself.
+ */
+int session_close_trace_chunk(const ltt_session::locked_ref& session,
+ struct lttng_trace_chunk *trace_chunk,
+ enum lttng_trace_chunk_command_type close_command,
+ char *path);
+
+/* Open a packet in all channels of a given session. */
+enum lttng_error_code session_open_packets(const ltt_session::locked_ref& session);
+
+bool session_output_supports_trace_chunks(const struct ltt_session *session);
+
+/*
+ * Sample the id of a session looked up via its name.
+ * Here the term "sampling" hint the caller that this return the id at a given
+ * point in time with no guarantee that the session for which the id was
+ * sampled still exist at that point.
+ *
+ * Return 0 when the session is not found,
+ * Return 1 when the session is found and set `id`.
+ */
+bool sample_session_id_by_name(const char *name, uint64_t *id);
+
#endif /* _LTT_SESSION_H */
--- /dev/null
+/*
+ * Copyright (C) 2024 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_SNAPSHOT_OUTPUT_HPP
+#define LTTNG_SNAPSHOT_OUTPUT_HPP
+
+int snapshot_output_init(const ltt_session::locked_ref& session,
+ uint64_t max_size,
+ const char *name,
+ const char *ctrl_url,
+ const char *data_url,
+ struct consumer_output *consumer,
+ struct snapshot_output *output,
+ struct snapshot *snapshot);
+int snapshot_output_init_with_uri(const ltt_session::locked_ref& session,
+ uint64_t max_size,
+ const char *name,
+ struct lttng_uri *uris,
+ size_t nb_uri,
+ struct consumer_output *consumer,
+ struct snapshot_output *output,
+ struct snapshot *snapshot);
+
+#endif /* LTTNG_SNAPSHOT_OUTPUT_HPP */
*/
#define _LGPL_SOURCE
+#include "consumer-output.hpp"
+#include "snapshot-output.hpp"
#include "snapshot.hpp"
#include "utils.hpp"
*
* Return 0 on success or else a negative value.
*/
-static int output_init(const struct ltt_session *session,
+static int output_init(const ltt_session::locked_ref& session,
uint64_t max_size,
const char *name,
struct lttng_uri *uris,
*
* Return 0 on success or else a negative value.
*/
-int snapshot_output_init_with_uri(const struct ltt_session *session,
+int snapshot_output_init_with_uri(const ltt_session::locked_ref& session,
uint64_t max_size,
const char *name,
struct lttng_uri *uris,
*
* Return 0 on success or else a negative value.
*/
-int snapshot_output_init(const struct ltt_session *session,
+int snapshot_output_init(const ltt_session::locked_ref& session,
uint64_t max_size,
const char *name,
const char *ctrl_url,
#include <stdint.h>
struct consumer_output;
-struct ltt_session;
struct snapshot_output {
uint32_t id;
/* Snapshot output object. */
struct snapshot_output *snapshot_output_alloc();
void snapshot_output_destroy(struct snapshot_output *obj);
-int snapshot_output_init(const struct ltt_session *session,
- uint64_t max_size,
- const char *name,
- const char *ctrl_url,
- const char *data_url,
- struct consumer_output *consumer,
- struct snapshot_output *output,
- struct snapshot *snapshot);
-int snapshot_output_init_with_uri(const struct ltt_session *session,
- uint64_t max_size,
- const char *name,
- struct lttng_uri *uris,
- size_t nb_uri,
- struct consumer_output *consumer,
- struct snapshot_output *output,
- struct snapshot *snapshot);
+
struct snapshot_output *snapshot_find_output_by_id(uint32_t id, struct snapshot *snapshot);
struct snapshot_output *snapshot_find_output_by_name(const char *name, struct snapshot *snapshot);
return ret;
}
-int timer_session_rotation_pending_check_start(struct ltt_session *session,
+int timer_session_rotation_pending_check_start(const ltt_session::locked_ref& session,
unsigned int interval_us)
{
int ret;
- if (!session_get(session)) {
+ if (!session_get(&session.get())) {
ret = -1;
goto end;
}
+
DBG("Enabling session rotation pending check timer on session %" PRIu64, session->id);
/*
* We arm this timer in a one-shot mode so we don't have to disable it
* no need to go through the whole signal teardown scheme everytime.
*/
ret = timer_start(&session->rotation_pending_check_timer,
- session,
+ &session.get(),
interval_us,
LTTNG_SESSIOND_SIG_PENDING_ROTATION_CHECK,
/* one-shot */ true);
}
/*
- * Call with session and session_list locks held.
+ * Call with session_list lock held.
*/
-int timer_session_rotation_pending_check_stop(ltt_session& session)
+int timer_session_rotation_pending_check_stop(const ltt_session::locked_ref& session)
{
int ret;
- LTTNG_ASSERT(session.rotation_pending_check_timer_enabled);
+ LTTNG_ASSERT(session->rotation_pending_check_timer_enabled);
- DBG("Disabling session rotation pending check timer on session %" PRIu64, session.id);
- ret = timer_stop(&session.rotation_pending_check_timer,
+ DBG("Disabling session rotation pending check timer on session %" PRIu64, session->id);
+ ret = timer_stop(&session->rotation_pending_check_timer,
LTTNG_SESSIOND_SIG_PENDING_ROTATION_CHECK);
if (ret == -1) {
ERR("Failed to stop rotate_pending_check timer");
} else {
- session.rotation_pending_check_timer_enabled = false;
+ session->rotation_pending_check_timer_enabled = false;
/*
* The timer's reference to the session can be released safely.
*/
- session_put(&session);
+ session_put(&session.get());
}
return ret;
}
/*
- * Call with session and session_list locks held.
+ * Call with session_list lock held.
*/
-int timer_session_rotation_schedule_timer_start(struct ltt_session *session,
+int timer_session_rotation_schedule_timer_start(const ltt_session::locked_ref& session,
unsigned int interval_us)
{
int ret;
- if (!session_get(session)) {
+ if (!session_get(&session.get())) {
ret = -1;
goto end;
}
interval_us,
USEC_UNIT);
ret = timer_start(&session->rotation_schedule_timer,
- session,
+ &session.get(),
interval_us,
LTTNG_SESSIOND_SIG_SCHEDULED_ROTATION,
/* one-shot */ false);
/*
* Call with session and session_list locks held.
*/
-int timer_session_rotation_schedule_timer_stop(struct ltt_session *session)
+int timer_session_rotation_schedule_timer_stop(const ltt_session::locked_ref& session)
{
int ret = 0;
- LTTNG_ASSERT(session);
-
if (!session->rotation_schedule_timer_enabled) {
goto end;
}
session->rotation_schedule_timer_enabled = false;
/* The timer's reference to the session can be released safely. */
- session_put(session);
+ session_put(&session.get());
ret = 0;
end:
return ret;
int timer_signal_init();
/* Start a session's rotation pending check timer (one-shot mode). */
-int timer_session_rotation_pending_check_start(struct ltt_session *session,
+int timer_session_rotation_pending_check_start(const ltt_session::locked_ref& session,
unsigned int interval_us);
/* Stop a session's rotation pending check timer. */
-int timer_session_rotation_pending_check_stop(ltt_session& session);
+int timer_session_rotation_pending_check_stop(const ltt_session::locked_ref& session);
/* Start a session's rotation schedule timer. */
-int timer_session_rotation_schedule_timer_start(struct ltt_session *session,
+int timer_session_rotation_schedule_timer_start(const ltt_session::locked_ref& session,
unsigned int interval_us);
/* Stop a session's rotation schedule timer. */
-int timer_session_rotation_schedule_timer_stop(struct ltt_session *session);
+int timer_session_rotation_schedule_timer_stop(const ltt_session::locked_ref& session);
bool launch_timer_thread(struct timer_thread_parameters *timer_thread_parameters);
lttng::urcu::read_lock_guard read_lock;
- ltt_session::ref session;
try {
- session = ltt_session::find_session(ua_chan->session->tracing_id);
+ const auto session = ltt_session::find_session(ua_chan->session->tracing_id);
+
+ if (!session->ust_session) {
+ /*
+ * Not finding the session is not an error because there are
+ * multiple ways the channels can be torn down.
+ *
+ * 1) The session daemon can initiate the destruction of the
+ * ust app session after receiving a destroy command or
+ * during its shutdown/teardown.
+ * 2) The application, since we are in per-pid tracing, is
+ * unregistering and tearing down its ust app session.
+ *
+ * Both paths are protected by the session list lock which
+ * ensures that the accounting of lost packets and discarded
+ * events is done exactly once. The session is then unpublished
+ * from the session list, resulting in this condition.
+ */
+ return;
+ }
+
+ if (ua_chan->attr.overwrite) {
+ consumer_get_lost_packets(ua_chan->session->tracing_id,
+ ua_chan->key,
+ session->ust_session->consumer,
+ &lost);
+ } else {
+ consumer_get_discarded_events(ua_chan->session->tracing_id,
+ ua_chan->key,
+ session->ust_session->consumer,
+ &discarded);
+ }
+ uchan = trace_ust_find_channel_by_name(session->ust_session->domain_global.channels,
+ ua_chan->name);
+ if (!uchan) {
+ ERR("Missing UST channel to store discarded counters");
+ return;
+ }
} catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
DBG_FMT("Failed to save per-pid lost/discarded counters: {}, location='{}'",
ex.what(),
ex.source_location);
- }
-
- if (!session || !session->ust_session) {
- /*
- * Not finding the session is not an error because there are
- * multiple ways the channels can be torn down.
- *
- * 1) The session daemon can initiate the destruction of the
- * ust app session after receiving a destroy command or
- * during its shutdown/teardown.
- * 2) The application, since we are in per-pid tracing, is
- * unregistering and tearing down its ust app session.
- *
- * Both paths are protected by the session list lock which
- * ensures that the accounting of lost packets and discarded
- * events is done exactly once. The session is then unpublished
- * from the session list, resulting in this condition.
- */
- return;
- }
-
- if (ua_chan->attr.overwrite) {
- consumer_get_lost_packets(ua_chan->session->tracing_id,
- ua_chan->key,
- session->ust_session->consumer,
- &lost);
- } else {
- consumer_get_discarded_events(ua_chan->session->tracing_id,
- ua_chan->key,
- session->ust_session->consumer,
- &discarded);
- }
- uchan = trace_ust_find_channel_by_name(session->ust_session->domain_global.channels,
- ua_chan->name);
- if (!uchan) {
- ERR("Missing UST channel to store discarded counters");
return;
}
int ret;
struct buffer_reg_uid *reg_uid;
struct buffer_reg_channel *buf_reg_chan;
- ltt_session::ref session;
enum lttng_error_code notification_ret;
LTTNG_ASSERT(app);
DBG("UST app creating channel %s with per UID buffers", ua_chan->name);
+ /* Guaranteed to exist; will not throw. */
+ const auto session = ltt_session::find_session(ua_sess->tracing_id);
+ ASSERT_SESSION_LIST_LOCKED();
+
reg_uid = buffer_reg_uid_find(usess->id, app->abi.bits_per_long, app->uid);
/*
* The session creation handles the creation of this global registry
goto error;
}
- /* Guaranteed to exist; will not throw. */
- session = ltt_session::find_session(ua_sess->tracing_id);
- ASSERT_LOCKED(session->_lock);
- ASSERT_SESSION_LIST_LOCKED();
-
/*
* Create the buffers on the consumer side. This call populates the
* ust app channel object with all streams and data object.
int ret;
lsu::registry_session *registry;
enum lttng_error_code cmd_ret;
- ltt_session::ref session;
uint64_t chan_reg_key;
LTTNG_ASSERT(app);
/* The UST app session lock is held, registry shall not be null. */
LTTNG_ASSERT(registry);
+ /* Guaranteed to exist; will not throw. */
+ const auto session = ltt_session::find_session(ua_sess->tracing_id);
+ ASSERT_LOCKED(session->_lock);
+ ASSERT_SESSION_LIST_LOCKED();
+
/* Create and add a new channel registry to session. */
try {
registry->add_channel(ua_chan->key);
goto error;
}
- /* Guaranteed to exist; will not throw. */
- session = ltt_session::find_session(ua_sess->tracing_id);
- ASSERT_LOCKED(session->_lock);
- ASSERT_SESSION_LIST_LOCKED();
-
/* Create and get channel on the consumer side. */
ret = do_consumer_create_channel(usess, ua_sess, ua_chan, app->abi.bits_per_long, registry);
if (ret < 0) {
int ret = 0;
struct ust_app_channel *metadata;
struct consumer_socket *socket;
- ltt_session::ref session;
LTTNG_ASSERT(ua_sess);
LTTNG_ASSERT(app);
/* The UST app session is held registry shall not be null. */
LTTNG_ASSERT(locked_registry);
+ /* Guaranteed to exist; will not throw. */
+ const auto session = ltt_session::find_session(ua_sess->tracing_id);
+ ASSERT_LOCKED(session->_lock);
+ ASSERT_SESSION_LIST_LOCKED();
+
/* Metadata already exists for this registry or it was closed previously */
if (locked_registry->_metadata_key || locked_registry->_metadata_closed) {
ret = 0;
*/
locked_registry->_metadata_key = metadata->key;
- /* Guaranteed to exist; will not throw. */
- session = ltt_session::find_session(ua_sess->tracing_id);
- ASSERT_LOCKED(session->_lock);
- ASSERT_SESSION_LIST_LOCKED();
-
/*
* Ask the metadata channel creation to the consumer. The metadata object
* will be created by the consumer and kept their. However, the stream is
*
* Return LTTNG_OK on success or else an LTTng error code.
*/
-enum lttng_error_code ust_app_rotate_session(struct ltt_session *session)
+enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& session)
{
int ret;
enum lttng_error_code cmd_ret = LTTNG_OK;
*
* Return LTTNG_OK on success or else an LTTng error code.
*/
-enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
+enum lttng_error_code ust_app_clear_session(const ltt_session::locked_ref& session)
{
int ret;
enum lttng_error_code cmd_ret = LTTNG_OK;
* daemon as the same "offset" in a metadata stream will no longer point
* to the same content.
*/
-enum lttng_error_code ust_app_open_packets(struct ltt_session *session)
+enum lttng_error_code ust_app_open_packets(const ltt_session::locked_ref& session)
{
enum lttng_error_code ret = LTTNG_OK;
struct lttng_ht_iter iter;
uint64_t *discarded,
uint64_t *lost);
int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess);
-enum lttng_error_code ust_app_rotate_session(struct ltt_session *session);
+enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& session);
enum lttng_error_code ust_app_create_channel_subdirectories(const struct ltt_ust_session *session);
int ust_app_release_object(struct ust_app *app, struct lttng_ust_abi_object_data *data);
-enum lttng_error_code ust_app_clear_session(struct ltt_session *session);
-enum lttng_error_code ust_app_open_packets(struct ltt_session *session);
+enum lttng_error_code ust_app_clear_session(const ltt_session::locked_ref& session);
+enum lttng_error_code ust_app_open_packets(const ltt_session::locked_ref& session);
int ust_app_setup_event_notifier_group(struct ust_app *app);
return 0;
}
-static inline enum lttng_error_code ust_app_rotate_session(struct ltt_session *session
+static inline enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& session
__attribute__((unused)))
{
return LTTNG_ERR_UNK;
return 0;
}
-static inline enum lttng_error_code ust_app_clear_session(struct ltt_session *session
+static inline enum lttng_error_code ust_app_clear_session(const ltt_session::locked_ref& session
__attribute__((unused)))
{
return LTTNG_ERR_UNK;
}
-static inline enum lttng_error_code ust_app_open_packets(struct ltt_session *session
+static inline enum lttng_error_code ust_app_open_packets(const ltt_session::locked_ref& session
__attribute__((unused)))
{
return LTTNG_ERR_UNK;
return match;
}
-const char *session_get_base_path(const struct ltt_session *session)
+const char *session_get_base_path(const ltt_session::locked_ref& session)
{
return consumer_output_get_base_path(session->consumer);
}
#ifndef _LTT_UTILS_H
#define _LTT_UTILS_H
+#include "session.hpp"
+
struct lttng_ht;
-struct ltt_session;
struct consumer_output;
const char *get_home_dir();
int b_loglevel_type,
int b_loglevel_value,
int loglevel_all_type);
-const char *session_get_base_path(const struct ltt_session *session);
+const char *session_get_base_path(const ltt_session::locked_ref& session);
const char *consumer_output_get_base_path(const struct consumer_output *output);
#endif /* _LTT_UTILS_H */
#include <sstream>
-lttng::cli::no_default_session_error::no_default_session_error(const lttng::source_location &location) :
+lttng::cli::no_default_session_error::no_default_session_error(
+ const lttng::source_location& location) :
runtime_error(fmt::format("No default session found in `{}/.lttngrc`",
- utils_get_home_dir() ?: "LTTNG_HOME"),
+ utils_get_home_dir() ?: "LTTNG_HOME"),
location)
{
}
#include <stdexcept>
#include <string>
-#define LTTNG_THROW_CLI_NO_DEFAULT_SESSION() \
- throw lttng::cli::no_default_session_error( \
- LTTNG_SOURCE_LOCATION())
+#define LTTNG_THROW_CLI_NO_DEFAULT_SESSION() \
+ throw lttng::cli::no_default_session_error(LTTNG_SOURCE_LOCATION())
namespace lttng {
namespace cli {
log-level-rule.cpp \
make-unique.hpp \
make-unique-wrapper.hpp \
+ meta-helpers.hpp \
mi-lttng.cpp mi-lttng.hpp \
notification.cpp \
payload.cpp payload.hpp \
pthread-lock.hpp \
random.cpp random.hpp \
readwrite.cpp readwrite.hpp \
+ reference.hpp \
runas.cpp runas.hpp \
scope-exit.hpp \
session-descriptor.cpp \
lttng::posix_error::posix_error(const std::string& msg,
unsigned int errno_code,
const lttng::source_location& location) :
- std::system_error(errno_code, std::generic_category()),
- lttng::runtime_error(msg, location)
+ std::system_error(errno_code, std::generic_category()), lttng::runtime_error(msg, location)
{
}
}
lttng::allocation_failure::allocation_failure(const std::string& msg,
-std::size_t allocation_size_,
- const lttng::source_location& location) :
+ std::size_t allocation_size_,
+ const lttng::source_location& location) :
lttng::runtime_error(msg, location), allocation_size(allocation_size_)
{
}
#define LTTNG_MAKE_UNIQUE_WRAPPER_H
#include <common/macros.hpp>
+#include <common/meta-helpers.hpp>
#include <memory>
*/
namespace memory {
-template <typename WrappedType, void (*DeleterFunction)(WrappedType *)>
-struct create_deleter_class {
- struct deleter {
- void operator()(WrappedType *instance) const
- {
- DeleterFunction(instance);
- }
- };
-
- std::unique_ptr<WrappedType, deleter> operator()(WrappedType *instance) const
- {
- return std::unique_ptr<WrappedType, deleter>(instance);
- }
-};
-
/*
* 'free' is a utility function for use with make_unique_wrapper. It makes it easier to
* wrap raw pointers that have to be deleted with `free`. Using libc's 'free' as
--- /dev/null
+/*
+ * Copyright (C) 2024 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_META_HELPERS_HPP
+#define LTTNG_META_HELPERS_HPP
+
+#include <memory>
+
+/*
+ * Collection of meta-programming helpers.
+ *
+ * @see type-traits.hpp
+ */
+namespace lttng {
+namespace memory {
+template <typename WrappedType, void (*DeleterFunction)(WrappedType *)>
+struct create_deleter_class {
+ struct deleter {
+ void operator()(WrappedType *instance) const
+ {
+ DeleterFunction(instance);
+ }
+ };
+
+ std::unique_ptr<WrappedType, deleter> operator()(WrappedType *instance) const
+ {
+ return std::unique_ptr<WrappedType, deleter>(instance);
+ }
+};
+} /* namespace memory */
+} /* namespace lttng */
+
+#endif /* LTTNG_META_HELPERS_HPP */
--- /dev/null
+/*
+ * Copyright (C) 2024 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_REFERENCE_H
+#define LTTNG_REFERENCE_H
+
+#include <algorithm>
+#include <utility>
+
+namespace lttng {
+
+template <typename ReferencedType, typename CustomDeleter>
+class non_copyable_reference {
+public:
+ explicit non_copyable_reference(ReferencedType& instance) noexcept : _value(&instance)
+ {
+ }
+
+ non_copyable_reference(non_copyable_reference&& other) noexcept : _value(other._value)
+ {
+ other._value = nullptr;
+ }
+
+ non_copyable_reference() = delete;
+ non_copyable_reference(const non_copyable_reference&) = delete;
+ non_copyable_reference& operator=(non_copyable_reference&&) = delete;
+ non_copyable_reference& operator=(const non_copyable_reference&) = delete;
+
+ ReferencedType& get() const noexcept
+ {
+ return *_value;
+ }
+
+ ReferencedType *operator->() const noexcept
+ {
+ return _value;
+ }
+
+ ReferencedType& operator*() const noexcept
+ {
+ return *_value;
+ }
+
+ ~non_copyable_reference()
+ {
+ if (!_value) {
+ return;
+ }
+
+ typename CustomDeleter::deleter del;
+ del(_value);
+ }
+
+private:
+ ReferencedType *_value = nullptr;
+};
+
+} /* namespace lttng */
+
+#endif /* LTTNG_REFERENCE_H */
/*
* Test deletion of 1 session
*/
-static int destroy_one_session(struct ltt_session *session)
+static int destroy_one_session(ltt_session::ref session)
{
int ret;
char session_name[NAME_MAX];
strncpy(session_name, session->name, sizeof(session_name));
session_name[sizeof(session_name) - 1] = '\0';
- session_destroy(session);
- session_put(session);
+ /* Reference of the session list. */
+ ltt_session *weak_session_ptr = &session.get();
+ {
+ /* Drop the reference that stems from the look-up. */
+ const ltt_session::ref reference_to_drop = std::move(session);
+ }
+
+ session_destroy(weak_session_ptr);
ret = find_session_name(session_name);
if (ret < 0) {
* sessions.
*/
const auto list_lock = lttng::sessiond::lock_session_list();
- ltt_session::ref session;
try {
- session = ltt_session::find_session(SESSION1);
- } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
- }
-
- ok(session, "Validating session: session found");
+ const auto session = ltt_session::find_session(SESSION1);
+ pass("Validating session: session found");
- if (session) {
ok(session->kernel_session == nullptr && strlen(session->name),
"Validating session: basic sanity check");
- } else {
+
+ session->lock();
+ session->unlock();
+ } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
+ fail("Validating session: session found");
skip(1, "Skipping session validation check as session was not found");
- return;
}
-
- session->lock();
- session->unlock();
}
static void test_destroy_session()
* sessions.
*/
const auto list_lock = lttng::sessiond::lock_session_list();
- ltt_session::ref session;
try {
- session = ltt_session::find_session(SESSION1);
- } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
- }
+ auto session = ltt_session::find_session(SESSION1);
- ok(session, "Destroying session: session found");
+ pass("Destroying session: session found");
- if (session) {
- ok(destroy_one_session(session.release()) == 0,
+ ok(destroy_one_session(std::move(session)) == 0,
"Destroying session: %s destroyed",
SESSION1);
- } else {
+
+ } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
+ fail("Destroying session: session found");
skip(1, "Skipping session destruction as it was not found");
}
}
const auto list_lock = lttng::sessiond::lock_session_list();
for (i = 0; i < MAX_SESSIONS; i++) {
cds_list_for_each_entry_safe (iter, tmp, &session_list->head, list) {
- LTTNG_ASSERT(session_get(iter));
- ret = destroy_one_session(iter);
+ ret = destroy_one_session([iter]() {
+ session_get(iter);
+ return ltt_session::ref(*iter);
+ }());
+
if (ret < 0) {
diag("session %d destroy failed", i);
++failed;