refactor: session: provide an iterator over consumer data channel keys
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 13 Jun 2024 21:50:04 +0000 (21:50 +0000)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 5 Jul 2024 16:49:14 +0000 (12:49 -0400)
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>
25 files changed:
src/bin/lttng-sessiond/Makefile.am
src/bin/lttng-sessiond/buffer-registry.hpp
src/bin/lttng-sessiond/client.cpp
src/bin/lttng-sessiond/cmd.cpp
src/bin/lttng-sessiond/main.cpp
src/bin/lttng-sessiond/rotation-thread.cpp
src/bin/lttng-sessiond/save.cpp
src/bin/lttng-sessiond/session.cpp
src/bin/lttng-sessiond/session.hpp
src/bin/lttng-sessiond/ust-app.cpp
src/bin/lttng-sessiond/ust-app.hpp
src/bin/lttng-sessiond/ust-consumer.hpp
src/bin/lttng-sessiond/ust-field-convert.cpp
src/bin/lttng-sessiond/ust-field-convert.hpp [deleted file]
src/bin/lttng-sessiond/ust-field-quirks.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/ust-registry-session.cpp
src/bin/lttng-sessiond/ust-registry-session.hpp
src/bin/lttng-sessiond/ust-registry.hpp
src/bin/lttng-sessiond/utils.hpp
src/common/Makefile.am
src/common/ctl/format.hpp [new file with mode: 0644]
src/common/exception.cpp
src/common/exception.hpp
src/common/reference.hpp
tests/unit/test_session.cpp

index 7dc4bbe4e65b148ad89e08e6951cd2e655639872..05a7a11ce8aafc2df7ff7ca27c41e81346b6efd6 100644 (file)
@@ -72,7 +72,7 @@ liblttng_sessiond_common_la_SOURCES += trace-ust.cpp ust-registry.cpp ust-app.cp
                        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 \
index 2bdc58367b0705cce6aa72bd66d31285c4872283..f266fbce2a8d381103a5caa971175ae58a2b47c5 100644 (file)
@@ -78,7 +78,7 @@ struct buffer_reg_uid {
 
        /* 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];
index b4958e3743037393c19717f5609397e7a18486f5..89989f377a5d8c2dcc30ca377b2dcdebf38969b7 100644 (file)
@@ -589,7 +589,7 @@ static unsigned int lttng_sessions_count(uid_t uid, gid_t gid __attribute__((unu
                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. */
index 8817b45684528a0d9405209d3209d838a1e1cd6c..6aa9c9402f29c5384f5b24ea23502be5aad4e550 100644 (file)
@@ -3159,7 +3159,7 @@ cmd_create_session_from_descriptor(struct lttng_session_descriptor *descriptor,
                [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))) {
@@ -3216,7 +3216,7 @@ cmd_create_session_from_descriptor(struct lttng_session_descriptor *descriptor,
                [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) {
@@ -3980,7 +3980,7 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions,
                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);
                }();
 
                /*
index ee4e4690b09f2a3f0a868442caf8a67490e11a1c..b5a42b5dcfdd9b1674bb1a1a2b375d7815065d91 100644 (file)
@@ -1296,7 +1296,7 @@ static void destroy_all_sessions_and_wait()
                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) {
index 71f9bbcb5c10d4cba3998dfb5eecd55ec50b9c39..10e0656724a8f26cdd5591ab3f94d7ae89a4c1a4 100644 (file)
@@ -548,7 +548,7 @@ void ls::rotation_thread::_handle_job_queue()
 
                /* 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;
index b65bcf9f28a06d7fde45437e8206dd2dad420a6e..7e3c49290a193b0e627a54d55d8cca49e9252a4a 100644 (file)
@@ -2762,7 +2762,7 @@ int cmd_save_sessions(struct lttng_save_session_attr *attr, lttng_sock_cred *cre
                        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);
 
index cfa8c8b0384b134db1183282dab8111fe55234e4..ea92db57f9e0a24f796c7e3f8f93eff3ba5bd6f8 100644 (file)
@@ -6,15 +6,18 @@
  */
 
 #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>
@@ -475,7 +478,7 @@ static void del_session_ht(struct ltt_session *ls)
 /*
  * Acquire session lock
  */
-void session_lock(struct ltt_session *session)
+void session_lock(const ltt_session *session)
 {
        LTTNG_ASSERT(session);
        session->lock();
@@ -494,7 +497,7 @@ void ltt_session::unlock() const noexcept
 /*
  * Release session lock
  */
-void session_unlock(struct ltt_session *session)
+void session_unlock(const ltt_session *session)
 {
        LTTNG_ASSERT(session);
        session->unlock();
@@ -1045,7 +1048,7 @@ static void session_release(struct urcu_ref *ref)
        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);
@@ -1456,7 +1459,7 @@ ltt_session::locked_ref ltt_session::find_locked_session(ltt_session::id_t id)
         * 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)
@@ -1469,33 +1472,33 @@ ltt_session::locked_ref ltt_session::find_locked_session(lttng::c_string_view na
        }
 
        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)
@@ -1507,7 +1510,7 @@ 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)
@@ -1519,31 +1522,31 @@ 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)
@@ -1561,3 +1564,314 @@ std::unique_lock<std::mutex> ls::lock_session_list()
 {
        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
index d86147ac48d7da9a6e6236bf2195ef45146db232..3f1dda9909947e406d66b283b251025710fcb7b1 100644 (file)
@@ -11,6 +11,8 @@
 #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>
@@ -18,6 +20,7 @@
 #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>
@@ -35,11 +38,12 @@ struct ltt_ust_session;
 
 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);
@@ -92,12 +96,165 @@ struct ltt_session_list {
        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);
@@ -123,9 +280,35 @@ public:
                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.
         *
@@ -459,4 +642,34 @@ bool session_output_supports_trace_chunks(const struct ltt_session *session);
  */
 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 */
index 0e40506ffa0dba674141256b4b6af03e924e0754..cc23c75fa04c4cf4eb0d8c12e34ceee7754318e4 100644 (file)
@@ -22,7 +22,7 @@
 #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>
@@ -76,8 +76,6 @@ static pthread_mutex_t next_channel_key_lock = PTHREAD_MUTEX_INITIALIZER;
 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.
@@ -85,28 +83,28 @@ namespace {
  * 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;
                }
@@ -121,9 +119,11 @@ 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);
        }
@@ -931,7 +931,7 @@ static void delete_ust_app_session(int sock, struct ust_app_session *ua_sess, st
        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. */
@@ -1185,9 +1185,10 @@ error_free:
 /*
  * 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;
 
@@ -1204,7 +1205,7 @@ static struct ust_app_channel *alloc_ust_app_channel(const char *name,
 
        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);
@@ -1832,7 +1833,7 @@ error:
  * 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;
@@ -1875,7 +1876,7 @@ error:
  * 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;
@@ -2518,9 +2519,8 @@ error:
 /*
  * 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);
@@ -2530,8 +2530,8 @@ static void __lookup_session_by_app(const struct ltt_ust_session *usess,
  * 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;
@@ -2716,7 +2716,7 @@ static int find_or_create_ust_app_session(struct ltt_ust_session *usess,
 
        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,
@@ -2976,7 +2976,7 @@ error:
 /*
  * 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)
 {
@@ -2997,7 +2997,7 @@ error:
  * 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)
 {
@@ -3555,7 +3555,7 @@ error:
  */
 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;
@@ -3565,14 +3565,13 @@ static int create_channel_per_pid(struct ust_app *app,
 
        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);
 
@@ -3593,13 +3592,14 @@ static int create_channel_per_pid(struct ust_app *app,
        }
 
        /* 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");
@@ -3653,7 +3653,7 @@ error:
  */
 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;
@@ -3661,7 +3661,6 @@ static int ust_app_channel_send(struct ust_app *app,
        LTTNG_ASSERT(app);
        LTTNG_ASSERT(usess);
        LTTNG_ASSERT(usess->active);
-       LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(ua_chan);
        ASSERT_RCU_READ_LOCKED();
 
@@ -3669,7 +3668,7 @@ static int ust_app_channel_send(struct ust_app *app,
        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;
                }
@@ -3712,7 +3711,7 @@ 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)),
@@ -3877,7 +3876,7 @@ end:
  *
  * 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)
 {
@@ -3885,12 +3884,11 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
        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);
 
@@ -3943,7 +3941,7 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
         * 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,
@@ -4361,7 +4359,8 @@ static void ust_app_unregister(ust_app& app)
                 * 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);
@@ -4863,7 +4862,7 @@ int ust_app_disable_channel_glb(struct ltt_ust_session *usess, struct ltt_ust_ch
                                 */
                                continue;
                        }
-                       ua_sess = lookup_session_by_app(usess, app);
+                       ua_sess = ust_app_lookup_app_session(usess, app);
                        if (ua_sess == nullptr) {
                                continue;
                        }
@@ -4879,7 +4878,7 @@ int ust_app_disable_channel_glb(struct ltt_ust_session *usess, struct ltt_ust_ch
                        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;
@@ -4917,13 +4916,13 @@ int ust_app_enable_channel_glb(struct ltt_ust_session *usess, struct ltt_ust_cha
                                 */
                                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;
@@ -4968,7 +4967,7 @@ int ust_app_disable_event_glb(struct ltt_ust_session *usess,
                                 */
                                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;
@@ -5017,7 +5016,7 @@ int ust_app_disable_event_glb(struct ltt_ust_session *usess,
 
 /* 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)
@@ -5025,8 +5024,6 @@ static int ust_app_channel_create(struct ltt_ust_session *usess,
        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;
@@ -5123,7 +5120,7 @@ int ust_app_enable_event_glb(struct ltt_ust_session *usess,
                                 */
                                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;
@@ -5207,7 +5204,7 @@ int ust_app_create_event_glb(struct ltt_ust_session *usess,
                                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;
@@ -5266,7 +5263,7 @@ static int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *ap
                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;
@@ -5356,7 +5353,7 @@ static int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app
                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;
        }
@@ -5432,7 +5429,8 @@ static int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app
        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);
@@ -5556,7 +5554,7 @@ static int ust_app_flush_session(struct ltt_ust_session *usess)
                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;
                        }
@@ -5690,7 +5688,7 @@ static int ust_app_clear_quiescent_session(struct ltt_ust_session *usess)
                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;
                        }
@@ -5863,7 +5861,7 @@ int ust_app_destroy_trace_all(struct ltt_ust_session *usess)
 
 /* 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)
@@ -6066,7 +6064,7 @@ end:
  * 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;
@@ -6074,7 +6072,6 @@ static void ust_app_synchronize_all_channels(struct ltt_ust_session *usess,
        struct ltt_ust_channel *uchan;
 
        LTTNG_ASSERT(usess);
-       LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(app);
        ASSERT_RCU_READ_LOCKED();
 
@@ -6151,7 +6148,7 @@ static void ust_app_synchronize(struct ltt_ust_session *usess, struct ust_app *a
        {
                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
@@ -6162,7 +6159,7 @@ static void ust_app_synchronize(struct ltt_ust_session *usess, struct ust_app *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,
@@ -6175,7 +6172,7 @@ static void ust_app_global_destroy(struct ltt_ust_session *usess, struct ust_app
 {
        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;
        }
@@ -6295,7 +6292,7 @@ int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess,
                                 */
                                continue;
                        }
-                       ua_sess = lookup_session_by_app(usess, app);
+                       ua_sess = ust_app_lookup_app_session(usess, app);
                        if (ua_sess == nullptr) {
                                continue;
                        }
@@ -6476,7 +6473,15 @@ static int handle_app_register_channel_notification(int sock,
        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;
@@ -6648,7 +6653,7 @@ static int add_event_ust_registry(int sock,
        }
 
        {
-               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,
@@ -6763,7 +6768,7 @@ static int add_enum_ust_registry(int sock,
                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;
@@ -7184,7 +7189,7 @@ enum lttng_error_code ust_app_snapshot_record(const struct ltt_ust_session *uses
                        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;
@@ -7232,7 +7237,7 @@ enum lttng_error_code ust_app_snapshot_record(const struct ltt_ust_session *uses
                                }
                        }
 
-                       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;
@@ -7309,7 +7314,7 @@ uint64_t ust_app_get_size_one_more_packet_per_stream(const struct ltt_ust_sessio
                        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;
@@ -7396,7 +7401,7 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
        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;
                }
@@ -7443,7 +7448,7 @@ static int ust_app_regenerate_statedump(struct ltt_ust_session *usess, struct us
        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;
@@ -7585,7 +7590,7 @@ enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& sess
                        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;
@@ -7599,7 +7604,7 @@ enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& sess
                                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. */
@@ -7706,13 +7711,13 @@ enum lttng_error_code ust_app_create_channel_subdirectories(const struct ltt_ust
                        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;
@@ -7825,7 +7830,7 @@ enum lttng_error_code ust_app_clear_session(const ltt_session::locked_ref& sessi
                        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;
@@ -7839,7 +7844,7 @@ enum lttng_error_code ust_app_clear_session(const ltt_session::locked_ref& sessi
                                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;
@@ -7967,7 +7972,7 @@ enum lttng_error_code ust_app_open_packets(const ltt_session::locked_ref& sessio
                        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;
@@ -7981,7 +7986,7 @@ enum lttng_error_code ust_app_open_packets(const ltt_session::locked_ref& sessio
                                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;
@@ -8066,24 +8071,7 @@ void ust_app_put(struct ust_app *app)
        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
index e38ee830b5383cae48b856a15ea6f03538c9e219..02c4d7d0ec2378d33bd66ff097ab982e2abf3a42 100644 (file)
@@ -9,14 +9,13 @@
 #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;
 
 /*
@@ -192,8 +199,15 @@ struct ust_app_channel {
 
 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<
@@ -205,8 +219,80 @@ public:
                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 ? */
@@ -421,9 +507,7 @@ int ust_app_recv_notify(int sock);
 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);
@@ -444,11 +528,8 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
                                          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);
 
@@ -457,6 +538,13 @@ static inline int ust_app_supported()
        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);
 
@@ -631,14 +719,6 @@ static inline void ust_app_notify_sock_unregister(int sock __attribute__((unused
 {
 }
 
-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)),
@@ -723,35 +803,33 @@ static inline int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess
        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)))
index 9fc83e6abf790458f3f989e351dcd7924de8de41..212dd82483965ca636b7fcba57786c4be061a95d 100644 (file)
 
 #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,
index b51ba7bfc2c7e55ea4749b0e2d41807a7a33deed..888fe058cd6918a28ffc9eaca21e25e6afb8ca6b 100644 (file)
@@ -5,7 +5,11 @@
  *
  */
 
-#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>
diff --git a/src/bin/lttng-sessiond/ust-field-convert.hpp b/src/bin/lttng-sessiond/ust-field-convert.hpp
deleted file mode 100644 (file)
index 063abcd..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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 */
diff --git a/src/bin/lttng-sessiond/ust-field-quirks.hpp b/src/bin/lttng-sessiond/ust-field-quirks.hpp
new file mode 100644 (file)
index 0000000..82ce0fc
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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 */
index 8441b4e2c9a4a25e03f4284160bc8056ae6c80f9..860e623cd2ce5efd22aa0e219f6244053fa50157 100644 (file)
@@ -13,7 +13,8 @@
 #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>
index 404eabbe08ee777a26fbd8e6a4425a296bfa0921..48efd8848c69b0d102b5bd2db7d008c8de68d693 100644 (file)
@@ -206,4 +206,18 @@ private:
 } /* 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 */
index 4bb14be6fcc7d3a1f6c76ffa674bc847927c3650..c0a8ce374eb6eac4902eba11800c4c93dbfdbab7 100644 (file)
 #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"
 
@@ -263,4 +263,17 @@ static inline int ust_metadata_event_statedump(lttng::sessiond::ust::registry_se
 
 #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 */
index 2f9bf8e62d302fca85ab449d0c56e3872482de95..d2c621a70d3b5bc8d2e0a949f25966eaf6ce03c1 100644 (file)
@@ -8,8 +8,6 @@
 #ifndef _LTT_UTILS_H
 #define _LTT_UTILS_H
 
-#include "session.hpp"
-
 struct lttng_ht;
 struct consumer_output;
 
@@ -20,7 +18,6 @@ int loglevels_match(int a_loglevel_type,
                    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 */
index 257347ce2ff2dc278329038164b0821891b6adcb..68ab02f048f2c9fd7d8b33893f5391938ced36e5 100644 (file)
@@ -57,6 +57,7 @@ libcommon_lgpl_la_SOURCES = \
        actions/rate-policy.cpp \
        buffer-view.hpp buffer-view.cpp \
        channel.cpp \
+       ctl/format.hpp \
        compiler.hpp \
        conditions/buffer-usage.cpp \
        conditions/condition.cpp \
diff --git a/src/common/ctl/format.hpp b/src/common/ctl/format.hpp
new file mode 100644 (file)
index 0000000..ce957b0
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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
index 4375f815931910f4a5bc9a919db8e89875c30c27..9288aaa07924ab0e645f58efdb37ed59024b6d28 100644 (file)
@@ -38,6 +38,11 @@ lttng::allocation_failure::allocation_failure(const std::string& msg,
 {
 }
 
+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)
index 340231734d3620b113f622ab7879c7b1bac5bae2..6c926b62f0796c70fecff55ca70d5d4891a2b749 100644 (file)
@@ -22,7 +22,8 @@
        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) \
@@ -110,6 +111,19 @@ public:
        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.
index ccf5f4e86f3bcc709b6894a64eda1d3339fabac9..d98b2181d374a5bfccf0766ff7ca566c1f5d97e2 100644 (file)
@@ -16,18 +16,28 @@ namespace lttng {
 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
@@ -45,7 +55,22 @@ public:
                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;
@@ -53,12 +78,23 @@ public:
 
                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 */
index f972c44bbb18e723667c2bb493d697f8b6e3b3e6..37de10d3bb097df97227aaaf4649063381d03cd5 100644 (file)
@@ -308,7 +308,7 @@ static void test_large_session_number()
                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) {
This page took 0.060071 seconds and 4 git commands to generate.