The code iterating over the various data channel keys of the userspace domain is
relatively complex and repeated in many places. It is refactored to provide an
iterator that can be used in those various places.
Change-Id: I560484f63757b5da0313dd651724bbea9bbd6867
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
ust-consumer.cpp ust-consumer.hpp notify-apps.cpp \
ust-clock-class.hpp ust-clock-class.cpp \
agent-thread.cpp agent-thread.hpp \
- ust-field-convert.cpp ust-field-convert.hpp \
+ ust-field-convert.cpp ust-field-quirks.hpp \
ust-sigbus.cpp \
ust-registry-session.cpp ust-registry-session.hpp \
ust-registry-event.cpp ust-registry-event.hpp \
/* Indexed by session id. */
struct lttng_ht_node_u64 node;
- /* Node of a linked list used to teardown object at a destroy session. */
+ /* Node of the ust session's buffer_reg_uid_list. */
struct cds_list_head lnode;
char root_shm_path[PATH_MAX];
auto session = [raw_session_ptr]() {
session_get(raw_session_ptr);
raw_session_ptr->lock();
- return ltt_session::locked_ref(*raw_session_ptr);
+ return ltt_session::make_locked_ref(*raw_session_ptr);
}();
/* Only count the sessions the user can control. */
[new_session]() {
session_get(new_session);
new_session->lock();
- return ltt_session::locked_ref(*new_session);
+ return ltt_session::make_locked_ref(*new_session);
}(),
[](const ltt_session::locked_ref& session,
void *user_data __attribute__((unused))) {
[new_session]() {
session_get(new_session);
new_session->lock();
- return ltt_session::locked_ref(*new_session);
+ return ltt_session::make_locked_ref(*new_session);
}(),
descriptor);
if (ret_code != LTTNG_OK) {
auto session = [raw_session_ptr]() {
session_get(raw_session_ptr);
raw_session_ptr->lock();
- return ltt_session::locked_ref(*raw_session_ptr);
+ return ltt_session::make_locked_ref(*raw_session_ptr);
}();
/*
const auto session = [raw_session_ptr]() {
session_get(raw_session_ptr);
raw_session_ptr->lock();
- return ltt_session::locked_ref(*raw_session_ptr);
+ return ltt_session::make_locked_ref(*raw_session_ptr);
}();
if (session->destroyed) {
/* 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::make_locked_ref(*job->session);
if (run_job(*job, session, _notification_thread_handle)) {
return;
auto session = [raw_session_ptr]() {
session_get(raw_session_ptr);
raw_session_ptr->lock();
- return ltt_session::locked_ref(*raw_session_ptr);
+ return ltt_session::make_locked_ref(*raw_session_ptr);
}();
const auto save_ret = save_session(session, attr, creds);
*/
#define _LGPL_SOURCE
+#include "buffer-registry.hpp"
#include "cmd.hpp"
#include "kernel.hpp"
#include "lttng-sessiond.hpp"
#include "session.hpp"
#include "timer.hpp"
#include "trace-ust.hpp"
+#include "ust-app.hpp"
#include "utils.hpp"
#include <common/common.hpp>
+#include <common/ctl/format.hpp>
#include <common/sessiond-comm/sessiond-comm.hpp>
#include <common/trace-chunk.hpp>
#include <common/urcu.hpp>
/*
* Acquire session lock
*/
-void session_lock(struct ltt_session *session)
+void session_lock(const ltt_session *session)
{
LTTNG_ASSERT(session);
session->lock();
/*
* Release session lock
*/
-void session_unlock(struct ltt_session *session)
+void session_unlock(const ltt_session *session)
{
LTTNG_ASSERT(session);
session->unlock();
session_notify_destruction([session]() {
session_lock(session);
session_get(session);
- return ltt_session::locked_ref(*session);
+ return ltt_session::make_locked_ref(*session);
}());
pthread_mutex_destroy(&session->_lock);
* session.
*/
session_lock(session);
- return ltt_session::locked_ref(*session);
+ return ltt_session::make_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::make_locked_ref(*session);
}
ltt_session::const_locked_ref ltt_session::find_locked_const_session(ltt_session::id_t id)
{
lttng::urcu::read_lock_guard rcu_lock;
- auto session = session_find_by_id(id);
+ const auto *session = session_find_by_id(id);
if (!session) {
LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id);
}
session_lock(session);
- return ltt_session::const_locked_ref(*session);
+ return ltt_session::make_locked_ref(*session);
}
ltt_session::const_locked_ref ltt_session::find_locked_const_session(lttng::c_string_view name)
{
lttng::urcu::read_lock_guard rcu_lock;
- auto session = session_find_by_name(name.data());
+ const auto *session = session_find_by_name(name.data());
if (!session) {
LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name.data());
}
session_lock(session);
- return ltt_session::const_locked_ref(*session);
+ return ltt_session::make_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::make_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::make_ref(*session);
}
ltt_session::const_ref ltt_session::find_const_session(ltt_session::id_t id)
{
lttng::urcu::read_lock_guard rcu_lock;
- auto session = session_find_by_id(id);
+ const auto *session = session_find_by_id(id);
if (!session) {
LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id);
}
- return ltt_session::const_ref(*session);
+ return ltt_session::make_ref(*session);
}
ltt_session::const_ref ltt_session::find_const_session(lttng::c_string_view name)
{
lttng::urcu::read_lock_guard rcu_lock;
- auto session = session_find_by_name(name.data());
+ const auto *session = session_find_by_name(name.data());
if (!session) {
LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name.data());
}
- return ltt_session::const_ref(*session);
+ return ltt_session::make_ref(*session);
}
void ltt_session::_const_session_put(const ltt_session *session)
{
return std::unique_lock<std::mutex>(the_session_list.lock);
}
+
+lttng::sessiond::user_space_consumer_channel_keys
+ltt_session::user_space_consumer_channel_keys() const
+{
+ switch (ust_session->buffer_type) {
+ case LTTNG_BUFFER_PER_PID:
+ return lttng::sessiond::user_space_consumer_channel_keys(*ust_session,
+ *ust_app_get_all());
+ case LTTNG_BUFFER_PER_UID:
+ return lttng::sessiond::user_space_consumer_channel_keys(
+ *ust_session, ust_session->buffer_reg_uid_list);
+ default:
+ abort();
+ }
+}
+
+ls::user_space_consumer_channel_keys::iterator
+ls::user_space_consumer_channel_keys::begin() const noexcept
+{
+ return ls::user_space_consumer_channel_keys::iterator(_creation_context);
+}
+
+ls::user_space_consumer_channel_keys::iterator
+ls::user_space_consumer_channel_keys::end() const noexcept
+{
+ return ls::user_space_consumer_channel_keys::iterator(_creation_context, true);
+}
+
+ls::user_space_consumer_channel_keys::iterator&
+ls::user_space_consumer_channel_keys::iterator::operator++()
+{
+ if (_is_end) {
+ LTTNG_THROW_OUT_OF_RANGE(fmt::format(
+ "Attempted to advance channel key iterator past the end of channel keys: iteration_mode={}",
+ _creation_context._session.buffer_type));
+ }
+
+ switch (_creation_context._session.buffer_type) {
+ case LTTNG_BUFFER_PER_PID:
+ _advance_one_per_pid();
+ break;
+ case LTTNG_BUFFER_PER_UID:
+ _advance_one_per_uid();
+ break;
+ default:
+ abort();
+ }
+
+ return *this;
+}
+
+namespace {
+bool is_list_empty(const cds_list_head *head)
+{
+ return head == head->next;
+}
+
+bool is_last_element_of_list(const cds_list_head *head)
+{
+ return head->next == head->prev;
+}
+} /* namespace */
+
+ls::user_space_consumer_channel_keys::iterator::iterator(
+ const _iterator_creation_context& creation_context, bool is_end) :
+ _creation_context(creation_context), _is_end(is_end)
+{
+ if (_is_end) {
+ return;
+ }
+
+ switch (_creation_context._mode) {
+ case _iteration_mode::PER_PID:
+ _init_per_pid();
+ break;
+ case _iteration_mode::PER_UID:
+ _init_per_uid();
+ break;
+ }
+}
+
+void ls::user_space_consumer_channel_keys::iterator::_skip_to_next_app_per_pid(
+ bool try_current) noexcept
+{
+ auto& position = _position._per_pid;
+
+ while (true) {
+ if (!try_current) {
+ lttng_ht_get_next(_creation_context._container.apps,
+ &position.app_iterator);
+ } else {
+ try_current = false;
+ }
+
+ const auto app_node =
+ lttng_ht_iter_get_node<lttng_ht_node_ulong>(&position.app_iterator);
+ if (!app_node) {
+ _is_end = true;
+ return;
+ }
+
+ const auto& app = *lttng::utils::container_of(app_node, &ust_app::pid_n);
+ auto app_session = ust_app_lookup_app_session(&_creation_context._session, &app);
+
+ if (!app_session) {
+ /* This app is not traced by the target session. */
+ continue;
+ }
+
+ position.current_app_session = app_session->lock();
+
+ auto *registry = ust_app_get_session_registry(
+ (*_position._per_pid.current_app_session)->get_identifier());
+ if (!registry) {
+ DBG_FMT("Application session is being torn down: skipping application: app={}",
+ app);
+ continue;
+ }
+
+ position.current_registry_session = registry;
+ lttng_ht_get_first((*position.current_app_session)->channels,
+ &_position.channel_iterator);
+ break;
+ }
+}
+
+void ls::user_space_consumer_channel_keys::iterator::_init_per_pid() noexcept
+{
+ auto& position = _position._per_pid;
+
+ lttng_ht_get_first(_creation_context._container.apps, &position.app_iterator);
+ _skip_to_next_app_per_pid(true);
+}
+
+void ls::user_space_consumer_channel_keys::iterator::_init_per_uid() noexcept
+{
+ auto& position = _position._per_uid;
+
+ /* Start the iteration: get the first registry and point to its first channel. */
+ if (is_list_empty(&_creation_context._session.buffer_reg_uid_list)) {
+ _is_end = true;
+ return;
+ }
+
+ position.current_registry = lttng::utils::container_of(
+ _creation_context._session.buffer_reg_uid_list.next, &buffer_reg_uid::lnode);
+ lttng_ht_get_first(position.current_registry->registry->channels,
+ &_position.channel_iterator);
+}
+
+void ls::user_space_consumer_channel_keys::iterator::_advance_one_per_pid()
+{
+ auto& position = _position._per_pid;
+
+ if (!cds_lfht_iter_get_node(&_position.channel_iterator.iter)) {
+ /* Reached the last channel. Move on to the next app. */
+ _skip_to_next_app_per_pid(false);
+ return;
+ }
+
+ const auto current_app_node =
+ lttng_ht_iter_get_node<lttng_ht_node_ulong>(&position.app_iterator);
+ LTTNG_ASSERT(current_app_node);
+
+ lttng_ht_get_next((*position.current_app_session)->channels, &_position.channel_iterator);
+}
+
+void ls::user_space_consumer_channel_keys::iterator::_advance_one_per_uid()
+{
+ auto& position = _position._per_uid;
+
+ if (!cds_lfht_iter_get_node(&_position.channel_iterator.iter)) {
+ /* Reached the last channel of the registry. Move on to the next registry. */
+ if (is_last_element_of_list(&position.current_registry->lnode)) {
+ _is_end = true;
+ return;
+ }
+
+ position.current_registry = lttng::utils::container_of(
+ position.current_registry->lnode.next, &buffer_reg_uid::lnode);
+ cds_lfht_first(position.current_registry->registry->channels->ht,
+ &_position.channel_iterator.iter);
+
+ /* Assumes a registry can't be empty. */
+ LTTNG_ASSERT(cds_lfht_iter_get_node(&_position.channel_iterator.iter));
+ }
+
+ cds_lfht_next(position.current_registry->registry->channels->ht,
+ &_position.channel_iterator.iter);
+}
+
+bool ls::user_space_consumer_channel_keys::iterator::operator==(const iterator& other) const noexcept
+{
+ if (_is_end && other._is_end) {
+ return true;
+ }
+
+ /* Channel keys are unique; use them to compare the iterators. */
+ return !_is_end && !other._is_end && **this == *other;
+}
+
+bool ls::user_space_consumer_channel_keys::iterator::operator!=(const iterator& other) const noexcept
+{
+ return !(*this == other);
+}
+
+ls::user_space_consumer_channel_keys::iterator::key
+ls::user_space_consumer_channel_keys::iterator::_get_current_value_per_pid() const noexcept
+{
+ auto& position = _position._per_pid;
+
+ const auto *channel_node =
+ lttng_ht_iter_get_node<lttng_ht_node_str>(&_position.channel_iterator);
+ const auto current_app_node =
+ lttng_ht_iter_get_node<lttng_ht_node_ulong>(&position.app_iterator);
+ LTTNG_ASSERT(current_app_node);
+
+ const auto& app = *lttng::utils::container_of(current_app_node, &ust_app::pid_n);
+
+ if (channel_node) {
+ const auto& channel =
+ *lttng::utils::container_of(channel_node, &ust_app_channel::node);
+
+ return { static_cast<consumer_bitness>(app.abi.bits_per_long),
+ channel.key,
+ ls::user_space_consumer_channel_keys::channel_type::DATA };
+ } else {
+ LTTNG_ASSERT(position.current_registry_session);
+
+ /*
+ * Once the last data channel is delivered (iter points to the 'end' of the ht),
+ * deliver the metadata channel's key.
+ */
+ return { static_cast<consumer_bitness>(app.abi.bits_per_long),
+ position.current_registry_session->_metadata_key,
+ ls::user_space_consumer_channel_keys::channel_type::METADATA };
+ }
+}
+
+ls::user_space_consumer_channel_keys::iterator::key
+ls::user_space_consumer_channel_keys::iterator::_get_current_value_per_uid() const noexcept
+{
+ const auto *channel_node =
+ lttng_ht_iter_get_node<lttng_ht_node_u64>(&_position.channel_iterator);
+
+ if (channel_node) {
+ const auto& channel =
+ *lttng::utils::container_of(channel_node, &buffer_reg_channel::node);
+
+ return { static_cast<consumer_bitness>(
+ _position._per_uid.current_registry->bits_per_long),
+ channel.consumer_key,
+ ls::user_space_consumer_channel_keys::channel_type::DATA };
+ } else {
+ /*
+ * Once the last data channel is delivered (iter points to the 'end' of the ht),
+ * deliver the metadata channel's key.
+ */
+ return { static_cast<consumer_bitness>(
+ _position._per_uid.current_registry->bits_per_long),
+ _position._per_uid.current_registry->registry->reg.ust->_metadata_key,
+ ls::user_space_consumer_channel_keys::channel_type::METADATA };
+ }
+}
+
+ls::user_space_consumer_channel_keys::iterator::key
+ls::user_space_consumer_channel_keys::iterator::operator*() const
+{
+ if (_is_end) {
+ LTTNG_THROW_OUT_OF_RANGE(
+ "Attempt to use operator* on user_space_consumer_channel_keys iterator at the end position");
+ }
+
+ switch (_creation_context._mode) {
+ case _iteration_mode::PER_PID:
+ return _get_current_value_per_pid();
+ case _iteration_mode::PER_UID:
+ return _get_current_value_per_uid();
+ }
+
+ std::abort();
+}
+
+ls::ust::registry_session *ls::user_space_consumer_channel_keys::iterator::get_registry_session()
+{
+ if (_is_end) {
+ LTTNG_THROW_OUT_OF_RANGE(
+ "Attempt to get registry session on user_space_consumer_channel_keys iterator at the end position");
+ }
+
+ switch (_creation_context._mode) {
+ case _iteration_mode::PER_PID:
+ return _get_registry_session_per_pid();
+ case _iteration_mode::PER_UID:
+ return _get_registry_session_per_uid();
+ }
+
+ std::abort();
+}
+
+ls::ust::registry_session *
+ls::user_space_consumer_channel_keys::iterator::_get_registry_session_per_pid()
+{
+ return _position._per_pid.current_registry_session;
+}
+
+ls::ust::registry_session *
+ls::user_space_consumer_channel_keys::iterator::_get_registry_session_per_uid()
+{
+ return _position._per_uid.current_registry->registry->reg.ust;
+}
\ No newline at end of file
#include "consumer.hpp"
#include "snapshot.hpp"
#include "trace-kernel.hpp"
+#include "trace-ust.hpp"
+#include "ust-app.hpp"
#include <common/dynamic-array.hpp>
#include <common/exception.hpp>
#include <common/make-unique-wrapper.hpp>
#include <common/pthread-lock.hpp>
#include <common/reference.hpp>
+#include <common/urcu.hpp>
#include <lttng/location.h>
#include <lttng/lttng-error.h>
struct ltt_session;
struct ltt_session_list;
+struct buffer_reg_uid;
enum lttng_error_code
session_create(const char *name, uid_t uid, gid_t gid, struct ltt_session **out_session);
-void session_lock(struct ltt_session *session);
-void session_unlock(struct ltt_session *session);
+void session_lock(const ltt_session *session);
+void session_unlock(const ltt_session *session);
bool session_get(struct ltt_session *session);
void session_put(struct ltt_session *session);
struct cds_list_head head = CDS_LIST_HEAD_INIT(head);
};
+namespace lttng {
+namespace sessiond {
+class user_space_consumer_channel_keys {
+ friend ltt_session;
+
+public:
+ class iterator;
+
+ enum class consumer_bitness : std::uint8_t {
+ ABI_32 = 32,
+ ABI_64 = 64,
+ };
+
+ enum class channel_type : std::uint8_t {
+ METADATA,
+ DATA,
+ };
+
+ iterator begin() const noexcept;
+ iterator end() const noexcept;
+
+private:
+ enum class _iteration_mode : std::uint8_t {
+ PER_PID,
+ PER_UID,
+
+ };
+
+ struct _iterator_creation_context {
+ const _iteration_mode _mode;
+ const ltt_ust_session& _session;
+ union {
+ lttng_ht *apps;
+ const cds_list_head *buffer_registry;
+ } _container;
+ };
+
+public:
+ class iterator : public std::iterator<std::input_iterator_tag, std::uint64_t> {
+ friend user_space_consumer_channel_keys;
+
+ public:
+ struct key {
+ /* Bitness is needed to query the appropriate consumer daemon. */
+ consumer_bitness bitness;
+ std::uint64_t key_value;
+ channel_type type;
+
+ bool operator==(const key& other)
+ {
+ return bitness == other.bitness && key_value == other.key_value &&
+ type == other.type;
+ }
+ };
+
+ /*
+ * Copy constructor disabled since it would require handling the copy of locked
+ * references.
+ */
+ iterator(const iterator& other) = delete;
+ iterator(iterator&& other) = default;
+ ~iterator() = default;
+
+ iterator& operator++();
+ bool operator==(const iterator& other) const noexcept;
+ bool operator!=(const iterator& other) const noexcept;
+ key operator*() const;
+
+ /*
+ * Get the session registry of the channel currently
+ * pointed by the iterator. Never returns nullptr.
+ */
+ lttng::sessiond::ust::registry_session *get_registry_session();
+
+ private:
+ struct _iterator_position {
+ struct {
+ lttng_ht_iter app_iterator = {};
+ nonstd::optional<ust_app_session::locked_weak_ref>
+ current_app_session;
+ lttng::sessiond::ust::registry_session *current_registry_session =
+ nullptr;
+ } _per_pid;
+ struct {
+ buffer_reg_uid *current_registry = nullptr;
+ } _per_uid;
+
+ lttng_ht_iter channel_iterator = {};
+ };
+
+ explicit iterator(const _iterator_creation_context& creation_context,
+ bool is_end = false);
+
+ void _init_per_pid() noexcept;
+ void _skip_to_next_app_per_pid(bool try_current) noexcept;
+ void _advance_one_per_pid();
+ key _get_current_value_per_pid() const noexcept;
+ lttng::sessiond::ust::registry_session *_get_registry_session_per_pid();
+
+ void _init_per_uid() noexcept;
+ void _advance_one_per_uid();
+ key _get_current_value_per_uid() const noexcept;
+ lttng::sessiond::ust::registry_session *_get_registry_session_per_uid();
+
+ const _iterator_creation_context& _creation_context;
+ _iterator_position _position;
+ bool _is_end;
+ };
+
+private:
+ user_space_consumer_channel_keys(const ltt_ust_session& ust_session, lttng_ht& apps) :
+ _creation_context{ _iteration_mode::PER_PID, ust_session, { .apps = &apps } }
+ {
+ }
+
+ user_space_consumer_channel_keys(const ltt_ust_session& ust_session,
+ const cds_list_head& buffer_registry) :
+ _creation_context{ _iteration_mode::PER_UID,
+ ust_session,
+ { .buffer_registry = &buffer_registry } }
+ {
+ }
+
+ class _scoped_rcu_read_lock {
+ public:
+ _scoped_rcu_read_lock()
+ {
+ rcu_read_lock();
+ }
+
+ ~_scoped_rcu_read_lock()
+ {
+ if (_armed) {
+ rcu_read_unlock();
+ }
+ }
+
+ _scoped_rcu_read_lock(_scoped_rcu_read_lock&& other)
+ {
+ other._armed = false;
+ }
+
+ private:
+ bool _armed = true;
+ };
+
+ _scoped_rcu_read_lock _read_lock;
+ _iterator_creation_context _creation_context;
+};
+} /* namespace sessiond */
+} /* namespace lttng */
+
/*
* This data structure contains information needed to identify a tracing
* session for both LTTng and UST.
*/
struct ltt_session {
using id_t = uint64_t;
+ friend lttng::sessiond::user_space_consumer_channel_keys::iterator;
private:
static void _locked_session_release(ltt_session *session);
lttng::memory::create_deleter_class<const ltt_session,
ltt_session::_const_session_put>::deleter>;
+ static locked_ref make_locked_ref(ltt_session& session)
+ {
+ return lttng::make_non_copyable_reference<locked_ref::referenced_type,
+ locked_ref::deleter>(session);
+ }
+
+ static const_locked_ref make_locked_ref(const ltt_session& session)
+ {
+ return lttng::make_non_copyable_reference<const_locked_ref::referenced_type,
+ const_locked_ref::deleter>(session);
+ }
+
+ static ref make_ref(ltt_session& session)
+ {
+ return lttng::make_non_copyable_reference<ref::referenced_type, ref::deleter>(
+ session);
+ }
+
+ static const_ref make_ref(const ltt_session& session)
+ {
+ return lttng::make_non_copyable_reference<const_ref::referenced_type,
+ const_ref::deleter>(session);
+ }
+
void lock() const noexcept;
void unlock() const noexcept;
+ lttng::sessiond::user_space_consumer_channel_keys user_space_consumer_channel_keys() const;
+
/*
* Session list lock must be acquired by the caller.
*
*/
bool sample_session_id_by_name(const char *name, uint64_t *id);
+const char *session_get_base_path(const ltt_session::locked_ref& session);
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& 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);
+
+#else /* HAVE_LIBLTTNG_UST_CTL */
+
+static inline enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& session
+ __attribute__((unused)))
+{
+ return LTTNG_ERR_UNK;
+}
+
+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(const ltt_session::locked_ref& session
+ __attribute__((unused)))
+{
+ return LTTNG_ERR_UNK;
+}
+
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
#endif /* _LTT_SESSION_H */
#include "session.hpp"
#include "ust-app.hpp"
#include "ust-consumer.hpp"
-#include "ust-field-convert.hpp"
+#include "ust-field-quirks.hpp"
#include "utils.hpp"
#include <common/bytecode/bytecode.hpp>
static uint64_t _next_session_id;
static pthread_mutex_t next_session_id_lock = PTHREAD_MUTEX_INITIALIZER;
-namespace {
-
/*
* Return the session registry according to the buffer type of the given
* session.
* A registry per UID object MUST exists before calling this function or else
* it LTTNG_ASSERT() if not found. RCU read side lock must be acquired.
*/
-lsu::registry_session *get_session_registry(const struct ust_app_session *ua_sess)
+lsu::registry_session *ust_app_get_session_registry(const ust_app_session::identifier& ua_sess_id)
{
lsu::registry_session *registry = nullptr;
- LTTNG_ASSERT(ua_sess);
-
- switch (ua_sess->buffer_type) {
- case LTTNG_BUFFER_PER_PID:
+ switch (ua_sess_id.allocation_policy) {
+ case ust_app_session::identifier::buffer_allocation_policy::PER_PID:
{
- struct buffer_reg_pid *reg_pid = buffer_reg_pid_find(ua_sess->id);
+ struct buffer_reg_pid *reg_pid = buffer_reg_pid_find(ua_sess_id.id);
if (!reg_pid) {
goto error;
}
registry = reg_pid->registry->reg.ust;
break;
}
- case LTTNG_BUFFER_PER_UID:
+ case ust_app_session::identifier::buffer_allocation_policy::PER_UID:
{
- struct buffer_reg_uid *reg_uid =
- buffer_reg_uid_find(ua_sess->tracing_id,
- ua_sess->bits_per_long,
- lttng_credentials_get_uid(&ua_sess->real_credentials));
+ struct buffer_reg_uid *reg_uid = buffer_reg_uid_find(
+ ua_sess_id.session_id,
+ ua_sess_id.abi == ust_app_session::identifier::application_abi::ABI_32 ?
+ 32 :
+ 64,
+ lttng_credentials_get_uid(&ua_sess_id.app_credentials));
if (!reg_uid) {
goto error;
}
return registry;
}
-lsu::registry_session::locked_ref get_locked_session_registry(const struct ust_app_session *ua_sess)
+namespace {
+lsu::registry_session::locked_ref
+get_locked_session_registry(const ust_app_session::identifier& identifier)
{
- auto session = get_session_registry(ua_sess);
+ auto session = ust_app_get_session_registry(identifier);
if (session) {
pthread_mutex_lock(&session->_lock);
}
LTTNG_ASSERT(!ua_sess->deleted);
ua_sess->deleted = true;
- auto locked_registry = get_locked_session_registry(ua_sess);
+ auto locked_registry = get_locked_session_registry(locked_ua_sess->get_identifier());
/* Registry can be null on error path during initialization. */
if (locked_registry) {
/* Push metadata for application before freeing the application. */
/*
* Alloc new UST app channel.
*/
-static struct ust_app_channel *alloc_ust_app_channel(const char *name,
- struct ust_app_session *ua_sess,
- struct lttng_ust_abi_channel_attr *attr)
+static struct ust_app_channel *
+alloc_ust_app_channel(const char *name,
+ const ust_app_session::locked_weak_ref& ua_sess,
+ struct lttng_ust_abi_channel_attr *attr)
{
struct ust_app_channel *ua_chan;
ua_chan->enabled = true;
ua_chan->handle = -1;
- ua_chan->session = ua_sess;
+ ua_chan->session = &ua_sess.get();
ua_chan->key = get_next_channel_key();
ua_chan->ctx = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
ua_chan->events = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
* Disable the specified channel on to UST tracer for the UST session.
*/
static int disable_ust_channel(struct ust_app *app,
- struct ust_app_session *ua_sess,
+ const ust_app_session::locked_weak_ref& ua_sess,
struct ust_app_channel *ua_chan)
{
int ret;
* Enable the specified channel on to UST tracer for the UST session.
*/
static int enable_ust_channel(struct ust_app *app,
- struct ust_app_session *ua_sess,
+ const ust_app_session::locked_weak_ref& ua_sess,
struct ust_app_channel *ua_chan)
{
int ret;
/*
* Lookup sesison wrapper.
*/
-static void __lookup_session_by_app(const struct ltt_ust_session *usess,
- struct ust_app *app,
- struct lttng_ht_iter *iter)
+static void
+__lookup_session_by_app(const ltt_ust_session *usess, const ust_app *app, lttng_ht_iter *iter)
{
/* Get right UST app session from app */
lttng_ht_lookup(app->sessions, &usess->id, iter);
* Return ust app session from the app session hashtable using the UST session
* id.
*/
-static struct ust_app_session *lookup_session_by_app(const struct ltt_ust_session *usess,
- struct ust_app *app)
+ust_app_session *ust_app_lookup_app_session(const struct ltt_ust_session *usess,
+ const struct ust_app *app)
{
struct lttng_ht_iter iter;
struct lttng_ht_node_u64 *node;
health_code_update();
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
DBG2("UST app pid: %d session id %" PRIu64 " not found, creating it",
app->pid,
/*
* Lookup ust app channel for session and disable it on the tracer side.
*/
-static int disable_ust_app_channel(struct ust_app_session *ua_sess,
+static int disable_ust_app_channel(const ust_app_session::locked_weak_ref& ua_sess,
struct ust_app_channel *ua_chan,
struct ust_app *app)
{
* Lookup ust app channel for session and enable it on the tracer side. This
* MUST be called with a RCU read side lock acquired.
*/
-static int enable_ust_app_channel(struct ust_app_session *ua_sess,
+static int enable_ust_app_channel(const ust_app_session::locked_weak_ref& ua_sess,
struct ltt_ust_channel *uchan,
struct ust_app *app)
{
*/
static int create_channel_per_pid(struct ust_app *app,
struct ltt_ust_session *usess,
- struct ust_app_session *ua_sess,
+ const ust_app_session::locked_weak_ref& ua_sess,
struct ust_app_channel *ua_chan)
{
int ret;
LTTNG_ASSERT(app);
LTTNG_ASSERT(usess);
- LTTNG_ASSERT(ua_sess);
LTTNG_ASSERT(ua_chan);
DBG("UST app creating channel %s with per PID buffers", ua_chan->name);
lttng::urcu::read_lock_guard read_lock;
- registry = get_session_registry(ua_sess);
+ registry = ust_app_get_session_registry(ua_sess->get_identifier());
/* The UST app session lock is held, registry shall not be null. */
LTTNG_ASSERT(registry);
}
/* Create and get channel on the consumer side. */
- ret = do_consumer_create_channel(usess, ua_sess, ua_chan, app->abi.bits_per_long, registry);
+ ret = do_consumer_create_channel(
+ usess, &ua_sess.get(), ua_chan, app->abi.bits_per_long, registry);
if (ret < 0) {
ERR("Error creating UST channel \"%s\" on the consumer daemon", ua_chan->name);
goto error_remove_from_registry;
}
- ret = send_channel_pid_to_ust(app, ua_sess, ua_chan);
+ ret = send_channel_pid_to_ust(app, &ua_sess.get(), ua_chan);
if (ret < 0) {
if (ret != -ENOTCONN) {
ERR("Error sending channel to application");
*/
static int ust_app_channel_send(struct ust_app *app,
struct ltt_ust_session *usess,
- struct ust_app_session *ua_sess,
+ const ust_app_session::locked_weak_ref& ua_sess,
struct ust_app_channel *ua_chan)
{
int ret;
LTTNG_ASSERT(app);
LTTNG_ASSERT(usess);
LTTNG_ASSERT(usess->active);
- LTTNG_ASSERT(ua_sess);
LTTNG_ASSERT(ua_chan);
ASSERT_RCU_READ_LOCKED();
switch (usess->buffer_type) {
case LTTNG_BUFFER_PER_UID:
{
- ret = create_channel_per_uid(app, usess, ua_sess, ua_chan);
+ ret = create_channel_per_uid(app, usess, &ua_sess.get(), ua_chan);
if (ret < 0) {
goto error;
}
*
* Return 0 on success or else a negative value.
*/
-static int ust_app_channel_allocate(struct ust_app_session *ua_sess,
+static int ust_app_channel_allocate(const ust_app_session::locked_weak_ref& ua_sess,
struct ltt_ust_channel *uchan,
enum lttng_ust_abi_chan_type type,
struct ltt_ust_session *usess __attribute__((unused)),
*
* Called with UST app session lock held and RCU read side lock.
*/
-static int create_ust_app_metadata(struct ust_app_session *ua_sess,
+static int create_ust_app_metadata(const ust_app_session::locked_weak_ref& ua_sess,
struct ust_app *app,
struct consumer_output *consumer)
{
struct ust_app_channel *metadata;
struct consumer_socket *socket;
- LTTNG_ASSERT(ua_sess);
LTTNG_ASSERT(app);
LTTNG_ASSERT(consumer);
ASSERT_RCU_READ_LOCKED();
- auto locked_registry = get_locked_session_registry(ua_sess);
+ auto locked_registry = get_locked_session_registry(ua_sess->get_identifier());
/* The UST app session is held registry shall not be null. */
LTTNG_ASSERT(locked_registry);
* never added or monitored until we do a first push metadata to the
* consumer.
*/
- ret = ust_consumer_ask_channel(ua_sess,
+ ret = ust_consumer_ask_channel(&ua_sess.get(),
metadata,
consumer,
socket,
* The close metadata below nullifies the metadata pointer in the
* session so the delete session will NOT push/close a second time.
*/
- auto locked_registry = get_locked_session_registry(ua_sess);
+ auto locked_registry =
+ get_locked_session_registry(locked_ua_sess->get_identifier());
if (locked_registry) {
/* Push metadata for application before freeing the application. */
(void) push_metadata(locked_registry, ua_sess->consumer);
*/
continue;
}
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
continue;
}
LTTNG_ASSERT(ua_chan->enabled);
/* Disable channel onto application */
- ret = disable_ust_app_channel(ua_sess, ua_chan, app);
+ ret = disable_ust_app_channel(ua_sess->lock(), ua_chan, app);
if (ret < 0) {
/* XXX: We might want to report this error at some point... */
continue;
*/
continue;
}
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
continue;
}
/* Enable channel onto application */
- ret = enable_ust_app_channel(ua_sess, uchan, app);
+ ret = enable_ust_app_channel(ua_sess->lock(), uchan, app);
if (ret < 0) {
/* XXX: We might want to report this error at some point... */
continue;
*/
continue;
}
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
/* Next app */
continue;
/* The ua_sess lock must be held by the caller. */
static int ust_app_channel_create(struct ltt_ust_session *usess,
- struct ust_app_session *ua_sess,
+ const ust_app_session::locked_weak_ref& ua_sess,
struct ltt_ust_channel *uchan,
struct ust_app *app,
struct ust_app_channel **_ua_chan)
int ret = 0;
struct ust_app_channel *ua_chan = nullptr;
- LTTNG_ASSERT(ua_sess);
-
if (!strncmp(uchan->name, DEFAULT_METADATA_NAME, sizeof(uchan->name))) {
copy_channel_attr_to_ustctl(&ua_sess->metadata_attr, &uchan->attr);
ret = 0;
*/
continue;
}
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (!ua_sess) {
/* The application has problem or is probably dead. */
continue;
continue;
}
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (!ua_sess) {
/* The application has problem or is probably dead. */
continue;
return 0;
}
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
/* The session is in teardown process. Ignore and continue. */
return 0;
return 0;
}
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
return 0;
}
health_code_update();
{
- auto locked_registry = get_locked_session_registry(ua_sess);
+ auto locked_registry =
+ get_locked_session_registry(locked_ua_sess->get_identifier());
/* The UST app session is held registry shall not be null. */
LTTNG_ASSERT(locked_registry);
lttng::urcu::read_lock_guard read_lock;
cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
continue;
}
lttng::urcu::read_lock_guard read_lock;
cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
continue;
}
/* The ua_sess lock must be held by the caller. */
static int find_or_create_ust_app_channel(struct ltt_ust_session *usess,
- struct ust_app_session *ua_sess,
+ const ust_app_session::locked_weak_ref& ua_sess,
struct ust_app *app,
struct ltt_ust_channel *uchan,
struct ust_app_channel **ua_chan)
* RCU read lock must be held by the caller.
*/
static void ust_app_synchronize_all_channels(struct ltt_ust_session *usess,
- struct ust_app_session *ua_sess,
+ const ust_app_session::locked_weak_ref& ua_sess,
struct ust_app *app)
{
int ret = 0;
struct ltt_ust_channel *uchan;
LTTNG_ASSERT(usess);
- LTTNG_ASSERT(ua_sess);
LTTNG_ASSERT(app);
ASSERT_RCU_READ_LOCKED();
{
lttng::urcu::read_lock_guard read_lock;
- ust_app_synchronize_all_channels(usess, ua_sess, app);
+ ust_app_synchronize_all_channels(usess, locked_ua_sess, app);
/*
* Create the metadata for the application. This returns gracefully if a
* daemon, the consumer will use this assumption to send the
* "STREAMS_SENT" message to the relay daemon.
*/
- ret = create_ust_app_metadata(ua_sess, app, usess->consumer);
+ ret = create_ust_app_metadata(locked_ua_sess, app, usess->consumer);
if (ret < 0) {
ERR("Metadata creation failed for app sock %d for session id %" PRIu64,
app->sock,
{
struct ust_app_session *ua_sess;
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
return;
}
*/
continue;
}
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
continue;
}
ua_sess = ua_chan->session;
/* Get right session registry depending on the session buffer type. */
- auto locked_registry_session = get_locked_session_registry(ua_sess);
+
+ /*
+ * HACK: ua_sess is already locked by the client thread. This is called
+ * in the context of the handling of a notification from the application.
+ */
+ auto locked_ua_sess = ust_app_session::make_locked_weak_ref(*ua_sess);
+ auto locked_registry_session =
+ get_locked_session_registry(locked_ua_sess->get_identifier());
+ locked_ua_sess.release();
if (!locked_registry_session) {
DBG("Application session is being torn down. Abort event notify");
return 0;
}
{
- auto locked_registry = get_locked_session_registry(ua_sess);
+ auto locked_registry = get_locked_session_registry(ua_sess->get_identifier());
if (locked_registry) {
/*
* From this point on, this call acquires the ownership of the signature,
return 0;
}
- auto locked_registry = get_locked_session_registry(ua_sess);
+ auto locked_registry = get_locked_session_registry(ua_sess->get_identifier());
if (!locked_registry) {
DBG("Application session is being torn down (registry not found). Aborting enum registration.");
return 0;
char pathname[PATH_MAX];
size_t consumer_path_offset = 0;
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (!ua_sess) {
/* Session not associated with this app. */
continue;
}
}
- registry = get_session_registry(ua_sess);
+ registry = ust_app_get_session_registry(ua_sess->get_identifier());
if (!registry) {
DBG("Application session is being torn down. Skip application.");
continue;
struct ust_app_session *ua_sess;
struct lttng_ht_iter chan_iter;
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (!ua_sess) {
/* Session not associated with this app. */
continue;
cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
struct lttng_ht_iter uiter;
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
continue;
}
const auto update_health_code_on_exit =
lttng::make_scope_exit([]() noexcept { health_code_update(); });
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (ua_sess == nullptr) {
/* The session is in teardown process. Ignore and continue. */
return 0;
ust_app_reference app(raw_app);
raw_app = nullptr;
- ua_sess = lookup_session_by_app(usess, app.get());
+ ua_sess = ust_app_lookup_app_session(usess, app.get());
if (!ua_sess) {
/* Session not associated with this app. */
continue;
goto error;
}
- registry = get_session_registry(ua_sess);
+ registry = ust_app_get_session_registry(ua_sess->get_identifier());
LTTNG_ASSERT(registry);
/* Rotate the data channels. */
struct ust_app_session *ua_sess;
lsu::registry_session *registry;
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (!ua_sess) {
/* Session not associated with this app. */
continue;
}
- registry = get_session_registry(ua_sess);
+ registry = ust_app_get_session_registry(ua_sess->get_identifier());
if (!registry) {
DBG("Application session is being torn down. Skip application.");
continue;
struct ust_app_session *ua_sess;
lsu::registry_session *registry;
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (!ua_sess) {
/* Session not associated with this app. */
continue;
goto error_socket;
}
- registry = get_session_registry(ua_sess);
+ registry = ust_app_get_session_registry(ua_sess->get_identifier());
if (!registry) {
DBG("Application session is being torn down. Skip application.");
continue;
struct ust_app_session *ua_sess;
lsu::registry_session *registry;
- ua_sess = lookup_session_by_app(usess, app);
+ ua_sess = ust_app_lookup_app_session(usess, app);
if (!ua_sess) {
/* Session not associated with this app. */
continue;
goto error;
}
- registry = get_session_registry(ua_sess);
+ registry = ust_app_get_session_registry(ua_sess->get_identifier());
if (!registry) {
DBG("Application session is being torn down. Skip application.");
continue;
urcu_ref_put(&app->ref, ust_app_release);
}
-ust_app_session::const_locked_weak_ref ust_app_session::lock() const noexcept
-{
- pthread_mutex_lock(&_lock);
- return ust_app_session::const_locked_weak_ref(*this);
-}
-
-ust_app_session::locked_weak_ref ust_app_session::lock() noexcept
-{
- pthread_mutex_lock(&_lock);
- return ust_app_session::locked_weak_ref(*this);
-}
-
-void ust_app_session::_const_session_unlock(const ust_app_session *session)
+lttng_ht *ust_app_get_all()
{
- pthread_mutex_unlock(&session->_lock);
-}
-
-void ust_app_session::_session_unlock(ust_app_session *session)
-{
- pthread_mutex_unlock(&session->_lock);
-}
+ return ust_app_ht;
+}
\ No newline at end of file
#ifndef _LTT_UST_APP_H
#define _LTT_UST_APP_H
-#include "session.hpp"
+#include "trace-class.hpp"
#include "trace-ust.hpp"
-#include "ust-field-convert.hpp"
-#include "ust-registry-session.hpp"
-#include "ust-registry.hpp"
+#include "ust-field-quirks.hpp"
#include <common/format.hpp>
#include <common/index-allocator.hpp>
+#include <common/reference.hpp>
#include <common/scope-exit.hpp>
#include <common/uuid.hpp>
struct lttng_bytecode;
struct lttng_ust_filter_bytecode;
+namespace lttng {
+namespace sessiond {
+namespace ust {
+class registry_session;
+} /* namespace ust */
+} /* namespace sessiond */
+} /* namespace lttng */
+
extern int the_ust_consumerd64_fd, the_ust_consumerd32_fd;
/*
struct ust_app_session {
private:
- static void _session_unlock(ust_app_session *session);
- static void _const_session_unlock(const ust_app_session *session);
+ static void _session_unlock(ust_app_session *session)
+ {
+ _const_session_unlock(session);
+ }
+
+ static void _const_session_unlock(const ust_app_session *session)
+ {
+ pthread_mutex_unlock(&session->_lock);
+ }
public:
using locked_weak_ref = lttng::non_copyable_reference<
lttng::memory::create_deleter_class<const ust_app_session,
ust_app_session::_const_session_unlock>::deleter>;
- ust_app_session::const_locked_weak_ref lock() const noexcept;
- ust_app_session::locked_weak_ref lock() noexcept;
+ static locked_weak_ref make_locked_weak_ref(ust_app_session& ua_session)
+ {
+ return lttng::make_non_copyable_reference<locked_weak_ref::referenced_type,
+ locked_weak_ref::deleter>(ua_session);
+ }
+
+ static const_locked_weak_ref make_locked_weak_ref(const ust_app_session& ua_session)
+ {
+ return lttng::make_non_copyable_reference<const_locked_weak_ref::referenced_type,
+ const_locked_weak_ref::deleter>(
+ ua_session);
+ }
+
+ ust_app_session::const_locked_weak_ref lock() const noexcept
+ {
+ pthread_mutex_lock(&_lock);
+ return ust_app_session::make_locked_weak_ref(*this);
+ }
+
+ ust_app_session::locked_weak_ref lock() noexcept
+ {
+ pthread_mutex_lock(&_lock);
+ return ust_app_session::make_locked_weak_ref(*this);
+ }
+
+ struct identifier {
+ enum class application_abi : std::uint8_t { ABI_32 = 32, ABI_64 = 64 };
+ enum class buffer_allocation_policy : std::uint8_t { PER_PID, PER_UID };
+
+ /* Unique identifier of the ust_app_session. */
+ std::uint64_t id;
+ /* Unique identifier of the ltt_session. */
+ std::uint64_t session_id;
+ /* Credentials of the application which owns the ust_app_session. */
+ lttng_credentials app_credentials;
+ application_abi abi;
+ buffer_allocation_policy allocation_policy;
+ };
+
+ identifier get_identifier() const noexcept
+ {
+ /*
+ * To work around synchro design issues, this method allows the sampling
+ * of a ust_app_session's identifying properties without taking its lock.
+ *
+ * Since those properties are immutable, it is safe to sample them without
+ * holding the lock (as long as the existence of the instance is somehow
+ * guaranteed).
+ *
+ * The locking issue that motivates this method is that the application
+ * notitication handling thread needs to access the registry_session in response to
+ * a message from the application. The ust_app_session's ID is needed to look-up the
+ * registry session.
+ *
+ * The application's message can be emited in response to a command from the
+ * session daemon that is emited by the client thread.
+ *
+ * During that command, the client thread holds the ust_app_session lock until
+ * the application replies to the command. This causes the notification thread
+ * to block when it attempts to sample the ust_app_session's ID properties.
+ */
+ LTTNG_ASSERT(bits_per_long == 32 || bits_per_long == 64);
+ LTTNG_ASSERT(buffer_type == LTTNG_BUFFER_PER_PID ||
+ buffer_type == LTTNG_BUFFER_PER_UID);
+
+ return { .id = id,
+ .session_id = tracing_id,
+ .app_credentials = real_credentials,
+ .abi = bits_per_long == 32 ? identifier::application_abi::ABI_32 :
+ identifier::application_abi::ABI_64,
+ .allocation_policy = buffer_type == LTTNG_BUFFER_PER_PID ?
+ identifier::buffer_allocation_policy::PER_PID :
+ identifier::buffer_allocation_policy::PER_UID };
+ }
bool enabled = false;
/* started: has the session been in started state at any time ? */
void ust_app_add(struct ust_app *app);
struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock);
void ust_app_notify_sock_unregister(int sock);
-ssize_t ust_app_push_metadata(const lttng::sessiond::ust::registry_session::locked_ref& registry,
- struct consumer_socket *socket,
- int send_zero_data);
+
enum lttng_error_code ust_app_snapshot_record(const struct ltt_ust_session *usess,
const struct consumer_output *output,
uint64_t nb_packets_per_stream);
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(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(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 1;
}
+ust_app_session *ust_app_lookup_app_session(const struct ltt_ust_session *usess,
+ const struct ust_app *app);
+lttng::sessiond::ust::registry_session *
+ust_app_get_session_registry(const ust_app_session::identifier& identifier);
+
+lttng_ht *ust_app_get_all();
+
bool ust_app_supports_notifiers(const struct ust_app *app);
bool ust_app_supports_counters(const struct ust_app *app);
{
}
-static inline ssize_t ust_app_push_metadata(lttng::sessiond::ust::registry_session *registry
- __attribute__((unused)),
- struct consumer_socket *socket __attribute__((unused)),
- int send_zero_data __attribute__((unused)))
-{
- return 0;
-}
-
static inline enum lttng_error_code
ust_app_snapshot_record(struct ltt_ust_session *usess __attribute__((unused)),
const struct consumer_output *output __attribute__((unused)),
return 0;
}
-static inline enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& session
- __attribute__((unused)))
+static inline enum lttng_error_code
+ust_app_create_channel_subdirectories(const struct ltt_ust_session *session __attribute__((unused)))
{
return LTTNG_ERR_UNK;
}
-static inline enum lttng_error_code
-ust_app_create_channel_subdirectories(const struct ltt_ust_session *session __attribute__((unused)))
+static inline ust_app_session *ust_app_lookup_app_session(const ltt_ust_session *, const ust_app *)
{
- return LTTNG_ERR_UNK;
+ return nullptr;
}
-static inline int ust_app_release_object(struct ust_app *app __attribute__((unused)),
- struct lttng_ust_abi_object_data *data
- __attribute__((unused)))
+static inline lttng::sessiond::ust::registry_session *
+ust_app_get_session_registry(const ust_app_session::identifier&)
{
- return 0;
+ return nullptr;
}
-static inline enum lttng_error_code ust_app_clear_session(const ltt_session::locked_ref& session
- __attribute__((unused)))
+static inline lttng_ht *ust_app_get_all()
{
- return LTTNG_ERR_UNK;
+ return nullptr;
}
-static inline enum lttng_error_code ust_app_open_packets(const ltt_session::locked_ref& session
- __attribute__((unused)))
+static inline int ust_app_release_object(struct ust_app *app __attribute__((unused)),
+ struct lttng_ust_abi_object_data *data
+ __attribute__((unused)))
{
- return LTTNG_ERR_UNK;
+ return 0;
}
static inline void ust_app_get(ust_app& app __attribute__((unused)))
#include <stdint.h>
+namespace lttng {
+namespace sessiond {
+namespace ust {
+class registry_session;
+} /* namespace ust */
+} /* namespace sessiond */
+} /* namespace lttng */
+
int ust_consumer_ask_channel(struct ust_app_session *ua_sess,
struct ust_app_channel *ua_chan,
struct consumer_output *consumer,
*
*/
-#include "ust-field-convert.hpp"
+#include "field.hpp"
+#include "ust-app.hpp"
+#include "ust-field-quirks.hpp"
+#include "ust-registry-session.hpp"
+#include "ust-registry.hpp"
#include <common/exception.hpp>
#include <common/make-unique.hpp>
+++ /dev/null
-/*
- * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_UST_FIELD_CONVERT_H
-#define LTTNG_UST_FIELD_CONVERT_H
-
-#include "field.hpp"
-#include "ust-registry-session.hpp"
-#include "ust-registry.hpp"
-
-#include <cstddef>
-#include <type_traits>
-#include <vector>
-
-namespace lttng {
-namespace sessiond {
-namespace ust {
-
-enum class ctl_field_quirks : unsigned int {
- NONE = 0,
- /*
- * LTTng-UST with ABI major version <= 9 express variants with a tag
- * enumeration that doesn't match the fields of the variant. The
- * tag's mapping names are systematically prefixed with an underscore.
- */
- UNDERSCORE_PREFIXED_VARIANT_TAG_MAPPINGS = 1 << 0,
-};
-
-inline ctl_field_quirks operator&(ctl_field_quirks lhs, ctl_field_quirks rhs)
-{
- using enum_type = std::underlying_type<ctl_field_quirks>::type;
- return ctl_field_quirks(static_cast<enum_type>(lhs) & static_cast<enum_type>(rhs));
-}
-
-inline ctl_field_quirks operator|(ctl_field_quirks lhs, ctl_field_quirks rhs)
-{
- using enum_type = std::underlying_type<ctl_field_quirks>::type;
- return ctl_field_quirks(static_cast<enum_type>(lhs) | static_cast<enum_type>(rhs));
-}
-
-std::vector<trace::field::cuptr>
-create_trace_fields_from_ust_ctl_fields(const lttng::sessiond::ust::registry_session& session,
- const lttng_ust_ctl_field *fields,
- std::size_t field_count,
- trace::field_location::root lookup_root,
- ctl_field_quirks quirks = ctl_field_quirks::NONE);
-
-} /* namespace ust */
-} /* namespace sessiond */
-} /* namespace lttng */
-
-#endif /* LTTNG_UST_FIELD_CONVERT_H */
--- /dev/null
+/*
+ * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_UST_FIELD_CONVERT_H
+#define LTTNG_UST_FIELD_CONVERT_H
+
+#include <cstddef>
+#include <type_traits>
+#include <vector>
+
+namespace lttng {
+namespace sessiond {
+namespace ust {
+
+enum class ctl_field_quirks : unsigned int {
+ NONE = 0,
+ /*
+ * LTTng-UST with ABI major version <= 9 express variants with a tag
+ * enumeration that doesn't match the fields of the variant. The
+ * tag's mapping names are systematically prefixed with an underscore.
+ */
+ UNDERSCORE_PREFIXED_VARIANT_TAG_MAPPINGS = 1 << 0,
+};
+
+inline ctl_field_quirks operator&(ctl_field_quirks lhs, ctl_field_quirks rhs)
+{
+ using enum_type = std::underlying_type<ctl_field_quirks>::type;
+ return ctl_field_quirks(static_cast<enum_type>(lhs) & static_cast<enum_type>(rhs));
+}
+
+inline ctl_field_quirks operator|(ctl_field_quirks lhs, ctl_field_quirks rhs)
+{
+ using enum_type = std::underlying_type<ctl_field_quirks>::type;
+ return ctl_field_quirks(static_cast<enum_type>(lhs) | static_cast<enum_type>(rhs));
+}
+
+} /* namespace ust */
+} /* namespace sessiond */
+} /* namespace lttng */
+
+#endif /* LTTNG_UST_FIELD_CONVERT_H */
#include "trace-class.hpp"
#include "tsdl-trace-class-visitor.hpp"
#include "ust-app.hpp"
-#include "ust-field-convert.hpp"
+#include "ust-field-quirks.hpp"
+#include "ust-registry-session.hpp"
#include "ust-registry.hpp"
#include <common/compat/directory-handle.hpp>
} /* namespace sessiond */
} /* namespace lttng */
+#ifdef HAVE_LIBLTTNG_UST_CTL
+ssize_t ust_app_push_metadata(const lttng::sessiond::ust::registry_session::locked_ref& registry,
+ struct consumer_socket *socket,
+ int send_zero_data);
+#else /* HAVE_LIBLTTNG_UST_CTL */
+static inline ssize_t ust_app_push_metadata(lttng::sessiond::ust::registry_session *registry
+ __attribute__((unused)),
+ struct consumer_socket *socket __attribute__((unused)),
+ int send_zero_data __attribute__((unused)))
+{
+ return 0;
+}
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
#endif /* LTTNG_UST_REGISTRY_SESSION_H */
#include "event-class.hpp"
#include "field.hpp"
#include "lttng-ust-ctl.hpp"
-#include "session.hpp"
#include "stream-class.hpp"
#include "trace-class.hpp"
#include "ust-clock-class.hpp"
+#include "ust-field-quirks.hpp"
#include "ust-registry-channel.hpp"
#include "ust-registry-event.hpp"
#endif /* HAVE_LIBLTTNG_UST_CTL */
+namespace lttng {
+namespace sessiond {
+namespace ust {
+std::vector<trace::field::cuptr>
+create_trace_fields_from_ust_ctl_fields(const lttng::sessiond::ust::registry_session& session,
+ const lttng_ust_ctl_field *fields,
+ std::size_t field_count,
+ trace::field_location::root lookup_root,
+ ctl_field_quirks quirks = ctl_field_quirks::NONE);
+} // namespace ust
+} /* namespace sessiond */
+} /* namespace lttng */
+
#endif /* LTTNG_UST_REGISTRY_H */
#ifndef _LTT_UTILS_H
#define _LTT_UTILS_H
-#include "session.hpp"
-
struct lttng_ht;
struct consumer_output;
int b_loglevel_type,
int b_loglevel_value,
int loglevel_all_type);
-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 */
actions/rate-policy.cpp \
buffer-view.hpp buffer-view.cpp \
channel.cpp \
+ ctl/format.hpp \
compiler.hpp \
conditions/buffer-usage.cpp \
conditions/condition.cpp \
--- /dev/null
+/*
+ * Copyright (C) 2024 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_COMMON_CTL_FORMAT_H
+#define LTTNG_COMMON_CTL_FORMAT_H
+
+#include <common/format.hpp>
+
+#include <lttng/lttng.h>
+
+/*
+ * Due to a bug in g++ < 7.1, this specialization must be enclosed in the fmt namespace,
+ * see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480.
+ */
+namespace fmt {
+template <>
+struct formatter<lttng_buffer_type> : formatter<std::string> {
+ template <typename FormatContextType>
+ typename FormatContextType::iterator format(lttng_buffer_type buffer_type,
+ FormatContextType& ctx)
+ {
+ auto name = "unknown";
+
+ switch (buffer_type) {
+ case LTTNG_BUFFER_PER_PID:
+ name = "per-pid";
+ break;
+ case LTTNG_BUFFER_PER_UID:
+ name = "per-uid";
+ break;
+ case LTTNG_BUFFER_GLOBAL:
+ name = "global";
+ break;
+ }
+
+ return format_to(ctx.out(), name);
+ }
+};
+} /* namespace fmt */
+
+#endif /* LTTNG_COMMON_CTL_FORMAT_H */
\ No newline at end of file
{
}
+lttng::out_of_range::out_of_range(const std::string& msg, const lttng::source_location& location) :
+ lttng::runtime_error(msg, location)
+{
+}
+
lttng::unsupported_error::unsupported_error(const std::string& msg,
const lttng::source_location& location) :
lttng::runtime_error(msg, location)
throw lttng::ctl::error(msg, error_code, LTTNG_SOURCE_LOCATION())
#define LTTNG_THROW_POSIX(msg, errno_code) \
throw lttng::posix_error(msg, errno_code, LTTNG_SOURCE_LOCATION())
-#define LTTNG_THROW_ERROR(msg) throw lttng::runtime_error(msg, LTTNG_SOURCE_LOCATION())
+#define LTTNG_THROW_ERROR(msg) throw lttng::runtime_error(msg, LTTNG_SOURCE_LOCATION())
+#define LTTNG_THROW_OUT_OF_RANGE(msg) throw lttng::out_of_range(msg, LTTNG_SOURCE_LOCATION())
#define LTTNG_THROW_ALLOCATION_FAILURE_ERROR(msg, allocation_size) \
throw lttng::allocation_failure(msg, allocation_size, LTTNG_SOURCE_LOCATION())
#define LTTNG_THROW_UNSUPPORTED_ERROR(msg) \
std::size_t allocation_size;
};
+/**
+ * @class out_of_range
+ * @brief Represents an out of range access error.
+ *
+ * Thrown when attempting to access a container out of its valid range (e.g., advancing an iterator
+ * past end()).
+ */
+class out_of_range : public lttng::runtime_error {
+public:
+ explicit out_of_range(const std::string& msg,
+ const lttng::source_location& source_location);
+};
+
/**
* @class unsupported_error
* @brief Represents an error for unsupported features.
template <typename ReferencedType, typename CustomDeleter>
class non_copyable_reference {
public:
- explicit non_copyable_reference(ReferencedType& instance) noexcept : _value(&instance)
- {
- }
+ using referenced_type = ReferencedType;
+ using deleter = CustomDeleter;
non_copyable_reference(non_copyable_reference&& other) noexcept : _value(other._value)
{
- other._value = nullptr;
+ _value = other._value;
+ other.release();
}
non_copyable_reference() = delete;
non_copyable_reference(const non_copyable_reference&) = delete;
- non_copyable_reference& operator=(non_copyable_reference&&) = delete;
+ non_copyable_reference& operator=(non_copyable_reference&& other) noexcept
+ {
+ if (this != &other) {
+ _clean_up();
+ _value = other._value;
+ other.release();
+ }
+
+ return *this;
+ }
+
non_copyable_reference& operator=(const non_copyable_reference&) = delete;
ReferencedType& get() const noexcept
return *_value;
}
+ void release() noexcept
+ {
+ _value = nullptr;
+ }
+
~non_copyable_reference()
+ {
+ _clean_up();
+ }
+
+private:
+ explicit non_copyable_reference(ReferencedType& instance) noexcept : _value(&instance)
+ {
+ }
+
+ void _clean_up()
{
if (!_value) {
return;
typename CustomDeleter::deleter del;
del(_value);
+ release();
}
-private:
+ template <typename FactoryReferencedType, typename FactoryCustomDeleter>
+ friend non_copyable_reference<FactoryReferencedType, FactoryCustomDeleter>
+ make_non_copyable_reference(FactoryReferencedType&);
+
ReferencedType *_value = nullptr;
};
+template <typename ReferencedType, typename CustomDeleter>
+non_copyable_reference<ReferencedType, CustomDeleter>
+make_non_copyable_reference(ReferencedType& instance)
+{
+ return non_copyable_reference<ReferencedType, CustomDeleter>(instance);
+}
+
} /* namespace lttng */
#endif /* LTTNG_REFERENCE_H */
cds_list_for_each_entry_safe (iter, tmp, &session_list->head, list) {
ret = destroy_one_session([iter]() {
session_get(iter);
- return ltt_session::ref(*iter);
+ return ltt_session::make_ref(*iter);
}());
if (ret < 0) {