2 * Copyright (C) 2011 EfficiOS Inc.
4 * SPDX-License-Identifier: GPL-2.0-only
9 #include "buffer-registry.hpp"
12 #include "lttng-sessiond.hpp"
13 #include "session.hpp"
15 #include "trace-ust.hpp"
16 #include "ust-app.hpp"
19 #include <common/common.hpp>
20 #include <common/ctl/format.hpp>
21 #include <common/sessiond-comm/sessiond-comm.hpp>
22 #include <common/trace-chunk.hpp>
23 #include <common/urcu.hpp>
24 #include <common/utils.hpp>
26 #include <lttng/location-internal.hpp>
36 #include <sys/types.h>
40 struct ltt_session_destroy_notifier_element
{
41 ltt_session_destroy_notifier notifier
;
45 struct ltt_session_clear_notifier_element
{
46 ltt_session_clear_notifier notifier
;
50 namespace ls
= lttng::sessiond
;
55 * No ltt_session.lock is taken here because those data structure are widely
56 * spread across the lttng-tools code base so before calling functions below
57 * that can read/write a session, the caller MUST acquire the session lock
58 * using session_lock() and session_unlock().
61 /* These characters are forbidden in a session name. Used by validate_name. */
62 const char *forbidden_name_chars
= "/";
64 /* Global hash table to keep the sessions, indexed by id. */
65 struct lttng_ht
*ltt_sessions_ht_by_id
= nullptr;
66 /* Global hash table to keep the sessions, indexed by name. */
67 struct lttng_ht
*ltt_sessions_ht_by_name
= nullptr;
70 * Init tracing session list.
72 * Please see session.h for more explanation and correct usage of the list.
74 struct ltt_session_list the_session_list
;
77 * Return a ltt_session structure ptr that matches name. If no session found,
78 * NULL is returned. This must be called with the session list lock held using
79 * session_lock_list and session_unlock_list.
80 * A reference to the session is implicitly acquired by this function.
82 struct ltt_session
*session_find_by_name(const char *name
)
84 struct ltt_session
*iter
;
87 ASSERT_SESSION_LIST_LOCKED();
89 DBG2("Trying to find session by name %s", name
);
91 cds_list_for_each_entry (iter
, &the_session_list
.head
, list
) {
92 if (!strncmp(iter
->name
, name
, NAME_MAX
) && !iter
->destroyed
) {
99 return session_get(iter
) ? iter
: nullptr;
103 * Return an ltt_session that matches the id. If no session is found,
104 * NULL is returned. This must be called with rcu_read_lock and
105 * session list lock held (to guarantee the lifetime of the session).
107 struct ltt_session
*session_find_by_id(uint64_t id
)
109 struct lttng_ht_node_u64
*node
;
110 struct lttng_ht_iter iter
;
111 struct ltt_session
*ls
;
113 ASSERT_RCU_READ_LOCKED();
114 ASSERT_SESSION_LIST_LOCKED();
116 if (!ltt_sessions_ht_by_id
) {
120 lttng_ht_lookup(ltt_sessions_ht_by_id
, &id
, &iter
);
121 node
= lttng_ht_iter_get_node
<lttng_ht_node_u64
>(&iter
);
122 if (node
== nullptr) {
125 ls
= lttng::utils::container_of(node
, <t_session::node
);
127 DBG3("Session %" PRIu64
" found by id.", id
);
128 return session_get(ls
) ? ls
: nullptr;
131 DBG3("Session %" PRIu64
" NOT found by id", id
);
137 * Validate the session name for forbidden characters.
139 * Return 0 on success else -1 meaning a forbidden char. has been found.
141 static int validate_name(const char *name
)
144 char *tok
, *tmp_name
;
148 tmp_name
= strdup(name
);
155 tok
= strpbrk(tmp_name
, forbidden_name_chars
);
157 DBG("Session name %s contains a forbidden character", name
);
158 /* Forbidden character has been found. */
170 * Add a ltt_session structure to the global list.
172 * The caller MUST acquire the session list lock before.
173 * Returns the unique identifier for the session.
175 static uint64_t add_session_list(struct ltt_session
*ls
)
179 cds_list_add(&ls
->list
, &the_session_list
.head
);
180 return the_session_list
.next_uuid
++;
184 * Delete a ltt_session structure to the global list.
186 * The caller MUST acquire the session list lock before.
188 static void del_session_list(struct ltt_session
*ls
)
192 cds_list_del(&ls
->list
);
196 * Return a pointer to the session list.
198 struct ltt_session_list
*session_get_list()
200 return &the_session_list
;
204 * Returns once the session list is empty.
206 void session_list_wait_empty(std::unique_lock
<std::mutex
> list_lock
)
208 /* Keep waiting until the session list is empty. */
209 the_session_list
.removal_cond
.wait(list_lock
,
210 [] { return cds_list_empty(&the_session_list
.head
); });
214 * Try to acquire session list lock
216 int session_trylock_list() noexcept
218 /* Return 0 if successfully acquired. */
219 return the_session_list
.lock
.try_lock() ? 0 : 1;
223 * Get the session's consumer destination type.
225 enum consumer_dst_type
session_get_consumer_destination_type(const ltt_session::locked_ref
& session
)
228 * The output information is duplicated in both of those session types.
229 * Hence, it doesn't matter from which it is retrieved. However, it is
230 * possible for only one of them to be set.
232 return session
->kernel_session
? session
->kernel_session
->consumer
->type
:
233 session
->ust_session
->consumer
->type
;
237 * Get the session's consumer network hostname.
238 * The caller must ensure that the destination is of type "net".
240 const char *session_get_net_consumer_hostname(const ltt_session::locked_ref
& session
)
242 const char *hostname
= nullptr;
243 const struct consumer_output
*output
;
245 output
= session
->kernel_session
? session
->kernel_session
->consumer
:
246 session
->ust_session
->consumer
;
249 * hostname is assumed to be the same for both control and data
252 switch (output
->dst
.net
.control
.dtype
) {
254 hostname
= output
->dst
.net
.control
.dst
.ipv4
;
257 hostname
= output
->dst
.net
.control
.dst
.ipv6
;
266 * Get the session's consumer network control and data ports.
267 * The caller must ensure that the destination is of type "net".
269 void session_get_net_consumer_ports(const ltt_session::locked_ref
& session
,
270 uint16_t *control_port
,
273 const struct consumer_output
*output
;
275 output
= session
->kernel_session
? session
->kernel_session
->consumer
:
276 session
->ust_session
->consumer
;
277 *control_port
= output
->dst
.net
.control
.port
;
278 *data_port
= output
->dst
.net
.data
.port
;
282 * Get the location of the latest trace archive produced by a rotation.
284 struct lttng_trace_archive_location
*
285 session_get_trace_archive_location(const ltt_session::locked_ref
& session
)
288 struct lttng_trace_archive_location
*location
= nullptr;
289 char *chunk_path
= nullptr;
291 if (session
->rotation_state
!= LTTNG_ROTATION_STATE_COMPLETED
||
292 !session
->last_archived_chunk_name
) {
296 switch (session_get_consumer_destination_type(session
)) {
297 case CONSUMER_DST_LOCAL
:
298 ret
= asprintf(&chunk_path
,
299 "%s/" DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY
"/%s",
300 session_get_base_path(session
),
301 session
->last_archived_chunk_name
);
305 location
= lttng_trace_archive_location_local_create(chunk_path
);
307 case CONSUMER_DST_NET
:
309 const char *hostname
;
310 uint16_t control_port
, data_port
;
312 hostname
= session_get_net_consumer_hostname(session
);
313 session_get_net_consumer_ports(session
, &control_port
, &data_port
);
314 location
= lttng_trace_archive_location_relay_create(
316 LTTNG_TRACE_ARCHIVE_LOCATION_RELAY_PROTOCOL_TYPE_TCP
,
319 session
->last_chunk_path
);
331 * Allocate the ltt_sessions_ht_by_id and ltt_sessions_ht_by_name HT.
333 * The session list lock must be held.
335 static int ltt_sessions_ht_alloc()
339 DBG("Allocating ltt_sessions_ht_by_id");
340 ltt_sessions_ht_by_id
= lttng_ht_new(0, LTTNG_HT_TYPE_U64
);
341 if (!ltt_sessions_ht_by_id
) {
343 ERR("Failed to allocate ltt_sessions_ht_by_id");
347 DBG("Allocating ltt_sessions_ht_by_name");
348 ltt_sessions_ht_by_name
= lttng_ht_new(0, LTTNG_HT_TYPE_STRING
);
349 if (!ltt_sessions_ht_by_name
) {
351 ERR("Failed to allocate ltt_sessions_ht_by_name");
360 * Destroy the ltt_sessions_ht_by_id HT.
362 * The session list lock must be held.
364 static void ltt_sessions_ht_destroy()
366 if (ltt_sessions_ht_by_id
) {
367 lttng_ht_destroy(ltt_sessions_ht_by_id
);
368 ltt_sessions_ht_by_id
= nullptr;
371 if (ltt_sessions_ht_by_name
) {
372 lttng_ht_destroy(ltt_sessions_ht_by_name
);
373 ltt_sessions_ht_by_name
= nullptr;
380 * Add a ltt_session to the ltt_sessions_ht_by_id and ltt_sessions_ht_by_name.
381 * If unallocated, the ltt_sessions_ht_by_id and ltt_sessions_ht_by_name. HTs
382 * are allocated. The session list lock must be held.
384 static void add_session_ht(struct ltt_session
*ls
)
390 if (!ltt_sessions_ht_by_id
) {
391 ret
= ltt_sessions_ht_alloc();
393 ERR("Error allocating the sessions HT");
398 /* Should always be present with ltt_sessions_ht_by_id. */
399 LTTNG_ASSERT(ltt_sessions_ht_by_name
);
401 lttng_ht_node_init_u64(&ls
->node
, ls
->id
);
402 lttng_ht_add_unique_u64(ltt_sessions_ht_by_id
, &ls
->node
);
404 lttng_ht_node_init_str(&ls
->node_by_name
, ls
->name
);
405 lttng_ht_add_unique_str(ltt_sessions_ht_by_name
, &ls
->node_by_name
);
412 * Test if ltt_sessions_ht_by_id/name are empty.
413 * Return `false` if hash table objects are null.
414 * The session list lock must be held.
416 static bool ltt_sessions_ht_empty()
420 if (!ltt_sessions_ht_by_id
) {
421 /* The hash tables do not exist yet. */
425 LTTNG_ASSERT(ltt_sessions_ht_by_name
);
427 if (lttng_ht_get_count(ltt_sessions_ht_by_id
) != 0) {
433 * At this point it is expected that the `ltt_sessions_ht_by_name` ht is
436 * The removal from both hash tables is done in two different
438 * - removal from `ltt_sessions_ht_by_name` is done during
439 * `session_destroy()`
440 * - removal from `ltt_sessions_ht_by_id` is done later
441 * in `session_release()` on the last reference put.
443 * This means that it is possible for `ltt_sessions_ht_by_name` to be
444 * empty but for `ltt_sessions_ht_by_id` to still contain objects when
445 * multiple sessions exists. The reverse is false, hence this sanity
448 LTTNG_ASSERT(lttng_ht_get_count(ltt_sessions_ht_by_name
) == 0);
455 * Remove a ltt_session from the ltt_sessions_ht_by_id.
456 * If empty, the ltt_sessions_ht_by_id/name HTs are freed.
457 * The session list lock must be held.
459 static void del_session_ht(struct ltt_session
*ls
)
461 struct lttng_ht_iter iter
;
465 LTTNG_ASSERT(ltt_sessions_ht_by_id
);
466 LTTNG_ASSERT(ltt_sessions_ht_by_name
);
468 iter
.iter
.node
= &ls
->node
.node
;
469 ret
= lttng_ht_del(ltt_sessions_ht_by_id
, &iter
);
472 if (ltt_sessions_ht_empty()) {
473 DBG("Empty ltt_sessions_ht_by_id/name, destroying hast tables");
474 ltt_sessions_ht_destroy();
479 * Acquire session lock
481 void session_lock(const ltt_session
*session
)
483 LTTNG_ASSERT(session
);
487 void ltt_session::lock() const noexcept
489 pthread_mutex_lock(&_lock
);
492 void ltt_session::unlock() const noexcept
494 ltt_session::_const_session_unlock(*this);
498 * Release session lock
500 void session_unlock(const ltt_session
*session
)
502 LTTNG_ASSERT(session
);
506 void ltt_session::_const_session_unlock(const ltt_session
& session
)
508 pthread_mutex_unlock(&session
._lock
);
511 static int _session_set_trace_chunk_no_lock_check(const ltt_session::locked_ref
& session
,
512 struct lttng_trace_chunk
*new_trace_chunk
,
513 struct lttng_trace_chunk
**_current_trace_chunk
)
516 unsigned int i
, refs_to_acquire
= 0, refs_acquired
= 0, refs_to_release
= 0;
517 struct cds_lfht_iter iter
;
518 struct consumer_socket
*socket
;
519 struct lttng_trace_chunk
*current_trace_chunk
;
521 enum lttng_trace_chunk_status chunk_status
;
523 lttng::urcu::read_lock_guard read_lock
;
525 * Ownership of current trace chunk is transferred to
526 * `current_trace_chunk`.
528 current_trace_chunk
= session
->current_trace_chunk
;
529 session
->current_trace_chunk
= nullptr;
530 if (session
->ust_session
) {
531 lttng_trace_chunk_put(session
->ust_session
->current_trace_chunk
);
532 session
->ust_session
->current_trace_chunk
= nullptr;
534 if (session
->kernel_session
) {
535 lttng_trace_chunk_put(session
->kernel_session
->current_trace_chunk
);
536 session
->kernel_session
->current_trace_chunk
= nullptr;
538 if (!new_trace_chunk
) {
542 chunk_status
= lttng_trace_chunk_get_id(new_trace_chunk
, &chunk_id
);
543 LTTNG_ASSERT(chunk_status
== LTTNG_TRACE_CHUNK_STATUS_OK
);
546 refs_to_acquire
+= !!session
->ust_session
;
547 refs_to_acquire
+= !!session
->kernel_session
;
549 for (refs_acquired
= 0; refs_acquired
< refs_to_acquire
; refs_acquired
++) {
550 if (!lttng_trace_chunk_get(new_trace_chunk
)) {
551 ERR("Failed to acquire reference to new trace chunk of session \"%s\"",
557 if (session
->ust_session
) {
558 const uint64_t relayd_id
= session
->ust_session
->consumer
->net_seq_index
;
559 const bool is_local_trace
= session
->ust_session
->consumer
->type
==
562 session
->ust_session
->current_trace_chunk
= new_trace_chunk
;
563 if (is_local_trace
) {
564 enum lttng_error_code ret_error_code
;
567 ust_app_create_channel_subdirectories(session
->ust_session
);
568 if (ret_error_code
!= LTTNG_OK
) {
572 cds_lfht_for_each_entry (
573 session
->ust_session
->consumer
->socks
->ht
, &iter
, socket
, node
.node
) {
574 pthread_mutex_lock(socket
->lock
);
575 ret
= consumer_create_trace_chunk(socket
,
579 DEFAULT_UST_TRACE_DIR
);
580 pthread_mutex_unlock(socket
->lock
);
586 if (session
->kernel_session
) {
587 const uint64_t relayd_id
= session
->kernel_session
->consumer
->net_seq_index
;
588 const bool is_local_trace
= session
->kernel_session
->consumer
->type
==
591 session
->kernel_session
->current_trace_chunk
= new_trace_chunk
;
592 if (is_local_trace
) {
593 enum lttng_error_code ret_error_code
;
596 kernel_create_channel_subdirectories(session
->kernel_session
);
597 if (ret_error_code
!= LTTNG_OK
) {
601 cds_lfht_for_each_entry (
602 session
->kernel_session
->consumer
->socks
->ht
, &iter
, socket
, node
.node
) {
603 pthread_mutex_lock(socket
->lock
);
604 ret
= consumer_create_trace_chunk(socket
,
608 DEFAULT_KERNEL_TRACE_DIR
);
609 pthread_mutex_unlock(socket
->lock
);
617 * Update local current trace chunk state last, only if all remote
618 * creations succeeded.
620 session
->current_trace_chunk
= new_trace_chunk
;
621 LTTNG_OPTIONAL_SET(&session
->most_recent_chunk_id
, chunk_id
);
623 if (_current_trace_chunk
) {
624 *_current_trace_chunk
= current_trace_chunk
;
625 current_trace_chunk
= nullptr;
628 lttng_trace_chunk_put(current_trace_chunk
);
631 if (session
->ust_session
) {
632 session
->ust_session
->current_trace_chunk
= nullptr;
634 if (session
->kernel_session
) {
635 session
->kernel_session
->current_trace_chunk
= nullptr;
638 * Release references taken in the case where all references could not
641 refs_to_release
= refs_to_acquire
- refs_acquired
;
642 for (i
= 0; i
< refs_to_release
; i
++) {
643 lttng_trace_chunk_put(new_trace_chunk
);
649 struct lttng_trace_chunk
*
650 session_create_new_trace_chunk(const ltt_session::locked_ref
& session
,
651 const struct consumer_output
*consumer_output_override
,
652 const char *session_base_path_override
,
653 const char *chunk_name_override
)
656 struct lttng_trace_chunk
*trace_chunk
= nullptr;
657 enum lttng_trace_chunk_status chunk_status
;
658 const time_t chunk_creation_ts
= time(nullptr);
660 const char *base_path
;
661 struct lttng_directory_handle
*session_output_directory
= nullptr;
662 const struct lttng_credentials session_credentials
= {
663 .uid
= LTTNG_OPTIONAL_INIT_VALUE(session
->uid
),
664 .gid
= LTTNG_OPTIONAL_INIT_VALUE(session
->gid
),
666 uint64_t next_chunk_id
;
667 const struct consumer_output
*output
;
668 const char *new_path
;
670 if (consumer_output_override
) {
671 output
= consumer_output_override
;
673 LTTNG_ASSERT(session
->ust_session
|| session
->kernel_session
);
674 output
= session
->ust_session
? session
->ust_session
->consumer
:
675 session
->kernel_session
->consumer
;
678 is_local_trace
= output
->type
== CONSUMER_DST_LOCAL
;
679 base_path
= session_base_path_override
?: consumer_output_get_base_path(output
);
681 if (chunk_creation_ts
== (time_t) -1) {
682 PERROR("Failed to sample time while creation session \"%s\" trace chunk",
688 session
->most_recent_chunk_id
.is_set
? session
->most_recent_chunk_id
.value
+ 1 : 0;
690 if (session
->current_trace_chunk
&&
691 !lttng_trace_chunk_get_name_overridden(session
->current_trace_chunk
)) {
692 chunk_status
= lttng_trace_chunk_rename_path(session
->current_trace_chunk
,
693 DEFAULT_CHUNK_TMP_OLD_DIRECTORY
);
694 if (chunk_status
!= LTTNG_TRACE_CHUNK_STATUS_OK
) {
698 if (!session
->current_trace_chunk
) {
699 if (!session
->rotated
) {
705 new_path
= DEFAULT_CHUNK_TMP_NEW_DIRECTORY
;
708 trace_chunk
= lttng_trace_chunk_create(next_chunk_id
, chunk_creation_ts
, new_path
);
713 if (chunk_name_override
) {
714 chunk_status
= lttng_trace_chunk_override_name(trace_chunk
, chunk_name_override
);
715 if (chunk_status
!= LTTNG_TRACE_CHUNK_STATUS_OK
) {
720 if (!is_local_trace
) {
722 * No need to set crendentials and output directory
723 * for remote trace chunks.
728 chunk_status
= lttng_trace_chunk_set_credentials(trace_chunk
, &session_credentials
);
729 if (chunk_status
!= LTTNG_TRACE_CHUNK_STATUS_OK
) {
733 DBG("Creating base output directory of session \"%s\" at %s", session
->name
, base_path
);
734 ret
= utils_mkdir_recursive(base_path
, S_IRWXU
| S_IRWXG
, session
->uid
, session
->gid
);
738 session_output_directory
= lttng_directory_handle_create(base_path
);
739 if (!session_output_directory
) {
742 chunk_status
= lttng_trace_chunk_set_as_owner(trace_chunk
, session_output_directory
);
743 lttng_directory_handle_put(session_output_directory
);
744 session_output_directory
= nullptr;
745 if (chunk_status
!= LTTNG_TRACE_CHUNK_STATUS_OK
) {
751 lttng_directory_handle_put(session_output_directory
);
752 lttng_trace_chunk_put(trace_chunk
);
753 trace_chunk
= nullptr;
757 int session_close_trace_chunk(const ltt_session::locked_ref
& session
,
758 struct lttng_trace_chunk
*trace_chunk
,
759 enum lttng_trace_chunk_command_type close_command
,
760 char *closed_trace_chunk_path
)
763 bool error_occurred
= false;
764 struct cds_lfht_iter iter
;
765 struct consumer_socket
*socket
;
766 enum lttng_trace_chunk_status chunk_status
;
767 const time_t chunk_close_timestamp
= time(nullptr);
768 const char *new_path
;
770 chunk_status
= lttng_trace_chunk_set_close_command(trace_chunk
, close_command
);
771 if (chunk_status
!= LTTNG_TRACE_CHUNK_STATUS_OK
) {
776 if (chunk_close_timestamp
== (time_t) -1) {
777 ERR("Failed to sample the close timestamp of the current trace chunk of session \"%s\"",
783 if (close_command
== LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE
&& !session
->rotated
) {
784 /* New chunk stays in session output directory. */
787 /* Use chunk name for new chunk. */
790 if (session
->current_trace_chunk
&&
791 !lttng_trace_chunk_get_name_overridden(session
->current_trace_chunk
)) {
792 /* Rename new chunk path. */
794 lttng_trace_chunk_rename_path(session
->current_trace_chunk
, new_path
);
795 if (chunk_status
!= LTTNG_TRACE_CHUNK_STATUS_OK
) {
800 if (!lttng_trace_chunk_get_name_overridden(trace_chunk
) &&
801 close_command
== LTTNG_TRACE_CHUNK_COMMAND_TYPE_NO_OPERATION
) {
802 const char *old_path
;
804 if (!session
->rotated
) {
809 /* We need to move back the .tmp_old_chunk to its rightful place. */
810 chunk_status
= lttng_trace_chunk_rename_path(trace_chunk
, old_path
);
811 if (chunk_status
!= LTTNG_TRACE_CHUNK_STATUS_OK
) {
816 if (close_command
== LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED
) {
817 session
->rotated
= true;
819 chunk_status
= lttng_trace_chunk_set_close_timestamp(trace_chunk
, chunk_close_timestamp
);
820 if (chunk_status
!= LTTNG_TRACE_CHUNK_STATUS_OK
) {
821 ERR("Failed to set the close timestamp of the current trace chunk of session \"%s\"",
827 if (session
->ust_session
) {
828 const uint64_t relayd_id
= session
->ust_session
->consumer
->net_seq_index
;
830 cds_lfht_for_each_entry (
831 session
->ust_session
->consumer
->socks
->ht
, &iter
, socket
, node
.node
) {
832 pthread_mutex_lock(socket
->lock
);
833 ret
= consumer_close_trace_chunk(socket
,
837 closed_trace_chunk_path
);
838 pthread_mutex_unlock(socket
->lock
);
840 ERR("Failed to close trace chunk on user space consumer");
841 error_occurred
= true;
845 if (session
->kernel_session
) {
846 const uint64_t relayd_id
= session
->kernel_session
->consumer
->net_seq_index
;
848 cds_lfht_for_each_entry (
849 session
->kernel_session
->consumer
->socks
->ht
, &iter
, socket
, node
.node
) {
850 pthread_mutex_lock(socket
->lock
);
851 ret
= consumer_close_trace_chunk(socket
,
855 closed_trace_chunk_path
);
856 pthread_mutex_unlock(socket
->lock
);
858 ERR("Failed to close trace chunk on kernel consumer");
859 error_occurred
= true;
863 ret
= error_occurred
? -1 : 0;
869 * This function skips the metadata channel as the begin/end timestamps of a
870 * metadata packet are useless.
872 * Moreover, opening a packet after a "clear" will cause problems for live
873 * sessions as it will introduce padding that was not part of the first trace
874 * chunk. The relay daemon expects the content of the metadata stream of
875 * successive metadata trace chunks to be strict supersets of one another.
877 * For example, flushing a packet at the beginning of the metadata stream of
878 * a trace chunk resulting from a "clear" session command will cause the
879 * size of the metadata stream of the new trace chunk to not match the size of
880 * the metadata stream of the original chunk. This will confuse the relay
881 * daemon as the same "offset" in a metadata stream will no longer point
882 * to the same content.
884 static enum lttng_error_code
session_kernel_open_packets(const ltt_session::locked_ref
& session
)
886 enum lttng_error_code ret
= LTTNG_OK
;
887 struct consumer_socket
*socket
;
888 struct lttng_ht_iter iter
;
889 struct cds_lfht_node
*node
;
890 struct ltt_kernel_channel
*chan
;
892 lttng::urcu::read_lock_guard read_lock
;
894 cds_lfht_first(session
->kernel_session
->consumer
->socks
->ht
, &iter
.iter
);
895 node
= cds_lfht_iter_get_node(&iter
.iter
);
896 socket
= caa_container_of(node
, typeof(*socket
), node
.node
);
898 cds_list_for_each_entry (chan
, &session
->kernel_session
->channel_list
.head
, list
) {
901 DBG("Open packet of kernel channel: channel key = %" PRIu64
902 ", session name = %s, session_id = %" PRIu64
,
907 open_ret
= consumer_open_channel_packets(socket
, chan
->key
);
909 /* General error (no known error expected). */
919 enum lttng_error_code
session_open_packets(const ltt_session::locked_ref
& session
)
921 enum lttng_error_code ret
= LTTNG_OK
;
923 DBG("Opening packets of session channels: session name = %s, session id = %" PRIu64
,
927 if (session
->ust_session
) {
928 ret
= ust_app_open_packets(session
);
929 if (ret
!= LTTNG_OK
) {
934 if (session
->kernel_session
) {
935 ret
= session_kernel_open_packets(session
);
936 if (ret
!= LTTNG_OK
) {
946 * Set a session's current trace chunk.
948 * Must be called with the session lock held.
950 int session_set_trace_chunk(const ltt_session::locked_ref
& session
,
951 struct lttng_trace_chunk
*new_trace_chunk
,
952 struct lttng_trace_chunk
**current_trace_chunk
)
954 ASSERT_LOCKED(session
->_lock
);
955 return _session_set_trace_chunk_no_lock_check(
956 session
, new_trace_chunk
, current_trace_chunk
);
959 static void session_notify_destruction(const ltt_session::locked_ref
& session
)
962 const auto count
= lttng_dynamic_array_get_count(&session
->destroy_notifiers
);
964 for (i
= 0; i
< count
; i
++) {
965 const struct ltt_session_destroy_notifier_element
*element
=
966 (ltt_session_destroy_notifier_element
*) lttng_dynamic_array_get_element(
967 &session
->destroy_notifiers
, i
);
969 element
->notifier(session
, element
->user_data
);
974 * Fire each clear notifier once, and remove them from the array.
976 void session_notify_clear(const ltt_session::locked_ref
& session
)
979 const auto count
= lttng_dynamic_array_get_count(&session
->clear_notifiers
);
981 for (i
= 0; i
< count
; i
++) {
982 const struct ltt_session_clear_notifier_element
*element
=
983 (ltt_session_clear_notifier_element
*) lttng_dynamic_array_get_element(
984 &session
->clear_notifiers
, i
);
986 element
->notifier(session
, element
->user_data
);
988 lttng_dynamic_array_clear(&session
->clear_notifiers
);
991 static void session_release(struct urcu_ref
*ref
)
994 struct ltt_ust_session
*usess
;
995 struct ltt_kernel_session
*ksess
;
996 struct ltt_session
*session
= lttng::utils::container_of(ref
, <t_session::ref_count
);
997 const bool session_published
= session
->published
;
999 LTTNG_ASSERT(!session
->chunk_being_archived
);
1001 usess
= session
->ust_session
;
1002 ksess
= session
->kernel_session
;
1004 /* Clean kernel session teardown, keeping data for destroy notifier. */
1005 kernel_destroy_session(ksess
);
1007 /* UST session teardown, keeping data for destroy notifier. */
1009 /* Close any relayd session */
1010 consumer_output_send_destroy_relayd(usess
->consumer
);
1012 /* Destroy every UST application related to this session. */
1013 ret
= ust_app_destroy_trace_all(usess
);
1015 ERR("Error in ust_app_destroy_trace_all");
1018 /* Clean up the rest, keeping destroy notifier data. */
1019 trace_ust_destroy_session(usess
);
1023 * Must notify the kernel thread here to update it's poll set in order to
1024 * remove the channel(s)' fd just destroyed.
1026 ret
= notify_thread_pipe(the_kernel_poll_pipe
[1]);
1028 PERROR("write kernel poll pipe");
1031 DBG("Destroying session %s (id %" PRIu64
")", session
->name
, session
->id
);
1033 snapshot_destroy(&session
->snapshot
);
1035 if (session_published
) {
1036 ASSERT_SESSION_LIST_LOCKED();
1037 del_session_list(session
);
1038 del_session_ht(session
);
1042 * The notifiers make use of free-functions that expect a locked reference to a session.
1043 * To create such a reference, we need to acquire the lock and acquire a reference (increase
1044 * the ref-count). To ensure the release of the reference does not re-cross the zero value,
1045 * set the refcount to a tombstone value.
1047 session
->ref_count
.refcount
= 0xDEAD5E55;
1048 session_notify_destruction([session
]() {
1049 session_lock(session
);
1050 session_get(session
);
1051 return ltt_session::make_locked_ref(*session
);
1054 pthread_mutex_destroy(&session
->_lock
);
1056 consumer_output_put(session
->consumer
);
1057 kernel_free_session(ksess
);
1058 session
->kernel_session
= nullptr;
1060 trace_ust_free_session(usess
);
1061 session
->ust_session
= nullptr;
1063 lttng_dynamic_array_reset(&session
->destroy_notifiers
);
1064 lttng_dynamic_array_reset(&session
->clear_notifiers
);
1065 free(session
->last_archived_chunk_name
);
1066 free(session
->base_path
);
1067 lttng_trigger_put(session
->rotate_trigger
);
1069 if (session_published
) {
1071 * Notify after free-ing to ensure the memory is
1072 * reclaimed before the main thread exits (and prevent memory leak
1075 ASSERT_SESSION_LIST_LOCKED();
1076 the_session_list
.removal_cond
.notify_all();
1081 * Acquire a reference to a session.
1082 * This function may fail (return false); its return value must be checked.
1084 bool session_get(struct ltt_session
*session
)
1086 return urcu_ref_get_unless_zero(&session
->ref_count
);
1090 * Release a reference to a session.
1092 void session_put(struct ltt_session
*session
)
1098 * The session list lock must be held as any session_put()
1099 * may cause the removal of the session from the session_list.
1101 ASSERT_SESSION_LIST_LOCKED();
1102 LTTNG_ASSERT(session
->ref_count
.refcount
);
1103 urcu_ref_put(&session
->ref_count
, session_release
);
1107 * Destroy a session.
1109 * This method does not immediately release/free the session as other
1110 * components may still hold a reference to the session. However,
1111 * the session should no longer be presented to the user.
1113 * Releases the session list's reference to the session
1114 * and marks it as destroyed. Iterations on the session list should be
1115 * mindful of the "destroyed" flag.
1117 void session_destroy(struct ltt_session
*session
)
1120 struct lttng_ht_iter iter
;
1122 LTTNG_ASSERT(!session
->destroyed
);
1123 session
->destroyed
= true;
1126 * Remove immediately from the "session by name" hash table. Only one
1127 * session is expected to exist with a given name for at any given time.
1129 * Even if a session still technically exists for a little while longer,
1130 * there is no point in performing action on a "destroyed" session.
1132 iter
.iter
.node
= &session
->node_by_name
.node
;
1133 ret
= lttng_ht_del(ltt_sessions_ht_by_name
, &iter
);
1136 session_put(session
);
1139 int session_add_destroy_notifier(const ltt_session::locked_ref
& session
,
1140 ltt_session_destroy_notifier notifier
,
1143 const struct ltt_session_destroy_notifier_element element
= { .notifier
= notifier
,
1144 .user_data
= user_data
};
1146 return lttng_dynamic_array_add_element(&session
->destroy_notifiers
, &element
);
1149 int session_add_clear_notifier(const ltt_session::locked_ref
& session
,
1150 ltt_session_clear_notifier notifier
,
1153 const struct ltt_session_clear_notifier_element element
= { .notifier
= notifier
,
1154 .user_data
= user_data
};
1156 return lttng_dynamic_array_add_element(&session
->clear_notifiers
, &element
);
1160 * Create a new session and add it to the session list.
1161 * Session list lock must be held by the caller.
1163 enum lttng_error_code
1164 session_create(const char *name
, uid_t uid
, gid_t gid
, struct ltt_session
**out_session
)
1167 enum lttng_error_code ret_code
;
1168 struct ltt_session
*new_session
= nullptr;
1170 ASSERT_SESSION_LIST_LOCKED();
1172 struct ltt_session
*clashing_session
;
1174 clashing_session
= session_find_by_name(name
);
1175 if (clashing_session
) {
1176 session_put(clashing_session
);
1177 ret_code
= LTTNG_ERR_EXIST_SESS
;
1181 new_session
= zmalloc
<ltt_session
>();
1183 PERROR("Failed to allocate an ltt_session structure");
1184 ret_code
= LTTNG_ERR_NOMEM
;
1188 lttng_dynamic_array_init(&new_session
->destroy_notifiers
,
1189 sizeof(struct ltt_session_destroy_notifier_element
),
1191 lttng_dynamic_array_init(&new_session
->clear_notifiers
,
1192 sizeof(struct ltt_session_clear_notifier_element
),
1194 urcu_ref_init(&new_session
->ref_count
);
1195 pthread_mutex_init(&new_session
->_lock
, nullptr);
1197 new_session
->creation_time
= time(nullptr);
1198 if (new_session
->creation_time
== (time_t) -1) {
1199 PERROR("Failed to sample session creation time");
1200 ret_code
= LTTNG_ERR_SESSION_FAIL
;
1204 /* Create default consumer output. */
1205 new_session
->consumer
= consumer_create_output(CONSUMER_DST_LOCAL
);
1206 if (new_session
->consumer
== nullptr) {
1207 ret_code
= LTTNG_ERR_NOMEM
;
1212 ret
= lttng_strncpy(new_session
->name
, name
, sizeof(new_session
->name
));
1214 ret_code
= LTTNG_ERR_SESSION_INVALID_CHAR
;
1217 ret
= validate_name(name
);
1219 ret_code
= LTTNG_ERR_SESSION_INVALID_CHAR
;
1224 bool found_name
= false;
1226 struct tm
*timeinfo
;
1228 timeinfo
= localtime(&new_session
->creation_time
);
1230 ret_code
= LTTNG_ERR_SESSION_FAIL
;
1233 strftime(datetime
, sizeof(datetime
), "%Y%m%d-%H%M%S", timeinfo
);
1234 for (i
= 0; i
< INT_MAX
; i
++) {
1235 struct ltt_session
*clashing_session
;
1238 ret
= snprintf(new_session
->name
,
1239 sizeof(new_session
->name
),
1241 DEFAULT_SESSION_NAME
,
1244 ret
= snprintf(new_session
->name
,
1245 sizeof(new_session
->name
),
1247 DEFAULT_SESSION_NAME
,
1251 new_session
->name_contains_creation_time
= true;
1252 if (ret
== -1 || ret
>= sizeof(new_session
->name
)) {
1254 * Null-terminate in case the name is used
1255 * in logging statements.
1257 new_session
->name
[sizeof(new_session
->name
) - 1] = '\0';
1258 ret_code
= LTTNG_ERR_SESSION_FAIL
;
1262 clashing_session
= session_find_by_name(new_session
->name
);
1263 session_put(clashing_session
);
1264 if (!clashing_session
) {
1270 DBG("Generated session name \"%s\"", new_session
->name
);
1271 new_session
->has_auto_generated_name
= true;
1273 ERR("Failed to auto-generate a session name");
1274 ret_code
= LTTNG_ERR_SESSION_FAIL
;
1279 ret
= gethostname(new_session
->hostname
, sizeof(new_session
->hostname
));
1281 if (errno
== ENAMETOOLONG
) {
1282 new_session
->hostname
[sizeof(new_session
->hostname
) - 1] = '\0';
1283 ERR("Hostname exceeds the maximal permitted length and has been truncated to %s",
1284 new_session
->hostname
);
1286 ret_code
= LTTNG_ERR_SESSION_FAIL
;
1291 new_session
->uid
= uid
;
1292 new_session
->gid
= gid
;
1294 ret
= snapshot_init(&new_session
->snapshot
);
1296 ret_code
= LTTNG_ERR_NOMEM
;
1300 new_session
->rotation_state
= LTTNG_ROTATION_STATE_NO_ROTATION
;
1302 /* Add new session to the session list. */
1303 new_session
->id
= add_session_list(new_session
);
1306 * Add the new session to the ltt_sessions_ht_by_id.
1307 * No ownership is taken by the hash table; it is merely
1308 * a wrapper around the session list used for faster access
1311 add_session_ht(new_session
);
1312 new_session
->published
= true;
1315 * Consumer is left to NULL since the create_session_uri command will
1316 * set it up and, if valid, assign it to the session.
1318 DBG("Tracing session %s created with ID %" PRIu64
" by uid = %d, gid = %d",
1323 ret_code
= LTTNG_OK
;
1326 (void) session_get(new_session
);
1327 *out_session
= new_session
;
1331 session_put(new_session
);
1332 new_session
= nullptr;
1337 * Check if the UID matches the session. Root user has access to all
1340 bool session_access_ok(const ltt_session::locked_ref
& session
, uid_t uid
)
1342 return (uid
== session
->uid
) || uid
== 0;
1346 * Set a session's rotation state and reset all associated state.
1348 * This function resets the rotation state (check timers, pending
1349 * flags, etc.) and sets the result of the last rotation. The result
1350 * can be queries by a liblttng-ctl client.
1352 * Be careful of the result passed to this function. For instance,
1353 * on failure to launch a rotation, a client will expect the rotation
1354 * state to be set to "NO_ROTATION". If an error occurred while the
1355 * rotation was "ONGOING", result should be set to "ERROR", which will
1356 * allow a client to report it.
1358 * Must be called with the session and session_list locks held.
1360 int session_reset_rotation_state(const ltt_session::locked_ref
& session
,
1361 enum lttng_rotation_state result
)
1365 ASSERT_SESSION_LIST_LOCKED();
1367 session
->rotation_state
= result
;
1368 if (session
->rotation_pending_check_timer_enabled
) {
1369 ret
= timer_session_rotation_pending_check_stop(session
);
1371 if (session
->chunk_being_archived
) {
1373 enum lttng_trace_chunk_status chunk_status
;
1375 chunk_status
= lttng_trace_chunk_get_id(session
->chunk_being_archived
, &chunk_id
);
1376 LTTNG_ASSERT(chunk_status
== LTTNG_TRACE_CHUNK_STATUS_OK
);
1377 LTTNG_OPTIONAL_SET(&session
->last_archived_chunk_id
, chunk_id
);
1378 lttng_trace_chunk_put(session
->chunk_being_archived
);
1379 session
->chunk_being_archived
= nullptr;
1381 * Fire the clear reply notifiers if we are completing a clear
1384 session_notify_clear(session
);
1390 * Sample the id of a session looked up via its name.
1391 * Here the term "sampling" hint the caller that this return the id at a given
1392 * point in time with no guarantee that the session for which the id was
1393 * sampled still exist at that point.
1395 * Return 0 when the session is not found,
1396 * Return 1 when the session is found and set `id`.
1398 bool sample_session_id_by_name(const char *name
, uint64_t *id
)
1401 struct lttng_ht_node_str
*node
;
1402 struct lttng_ht_iter iter
;
1403 struct ltt_session
*ls
;
1405 lttng::urcu::read_lock_guard read_lock
;
1407 if (!ltt_sessions_ht_by_name
) {
1412 lttng_ht_lookup(ltt_sessions_ht_by_name
, name
, &iter
);
1413 node
= lttng_ht_iter_get_node
<lttng_ht_node_str
>(&iter
);
1414 if (node
== nullptr) {
1419 ls
= lttng::utils::container_of(node
, <t_session::node_by_name
);
1423 DBG3("Session id `%" PRIu64
"` sampled for session `%s", *id
, name
);
1428 void ltt_session::_locked_session_release(ltt_session
*session
)
1434 session_unlock(session
);
1435 session_put(session
);
1438 void ltt_session::_locked_const_session_release(const ltt_session
*session
)
1444 ltt_session::_const_session_unlock(*session
);
1445 ltt_session::_const_session_put(session
);
1448 ltt_session::locked_ref
ltt_session::find_locked_session(ltt_session::id_t id
)
1450 lttng::urcu::read_lock_guard rcu_lock
;
1451 auto session
= session_find_by_id(id
);
1454 LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id
);
1458 * The pointer falling out of scope will unlock and release the reference to the
1461 session_lock(session
);
1462 return ltt_session::make_locked_ref(*session
);
1465 ltt_session::locked_ref
ltt_session::find_locked_session(lttng::c_string_view name
)
1467 lttng::urcu::read_lock_guard rcu_lock
;
1468 auto session
= session_find_by_name(name
.data());
1471 LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name
.data());
1474 session_lock(session
);
1475 return ltt_session::make_locked_ref(*session
);
1478 ltt_session::const_locked_ref
ltt_session::find_locked_const_session(ltt_session::id_t id
)
1480 lttng::urcu::read_lock_guard rcu_lock
;
1481 const auto *session
= session_find_by_id(id
);
1484 LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id
);
1487 session_lock(session
);
1488 return ltt_session::make_locked_ref(*session
);
1491 ltt_session::const_locked_ref
ltt_session::find_locked_const_session(lttng::c_string_view name
)
1493 lttng::urcu::read_lock_guard rcu_lock
;
1494 const auto *session
= session_find_by_name(name
.data());
1497 LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name
.data());
1500 session_lock(session
);
1501 return ltt_session::make_locked_ref(*session
);
1504 ltt_session::ref
ltt_session::find_session(ltt_session::id_t id
)
1506 lttng::urcu::read_lock_guard rcu_lock
;
1507 auto session
= session_find_by_id(id
);
1510 LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id
);
1513 return ltt_session::make_ref(*session
);
1516 ltt_session::ref
ltt_session::find_session(lttng::c_string_view name
)
1518 lttng::urcu::read_lock_guard rcu_lock
;
1519 auto session
= session_find_by_name(name
.data());
1522 LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name
.data());
1525 return ltt_session::make_ref(*session
);
1528 ltt_session::const_ref
ltt_session::find_const_session(ltt_session::id_t id
)
1530 lttng::urcu::read_lock_guard rcu_lock
;
1531 const auto *session
= session_find_by_id(id
);
1534 LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id
);
1537 return ltt_session::make_ref(*session
);
1540 ltt_session::const_ref
ltt_session::find_const_session(lttng::c_string_view name
)
1542 lttng::urcu::read_lock_guard rcu_lock
;
1543 const auto *session
= session_find_by_name(name
.data());
1546 LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name
.data());
1549 return ltt_session::make_ref(*session
);
1552 void ltt_session::_const_session_put(const ltt_session
*session
)
1555 * The session list lock must be held as any session_put()
1556 * may cause the removal of the session from the session_list.
1558 ASSERT_SESSION_LIST_LOCKED();
1559 LTTNG_ASSERT(session
->ref_count
.refcount
);
1560 urcu_ref_put(&session
->ref_count
, session_release
);
1563 std::unique_lock
<std::mutex
> ls::lock_session_list()
1565 return std::unique_lock
<std::mutex
>(the_session_list
.lock
);
1568 lttng::sessiond::user_space_consumer_channel_keys
1569 ltt_session::user_space_consumer_channel_keys() const
1571 switch (ust_session
->buffer_type
) {
1572 case LTTNG_BUFFER_PER_PID
:
1573 return lttng::sessiond::user_space_consumer_channel_keys(*ust_session
,
1574 *ust_app_get_all());
1575 case LTTNG_BUFFER_PER_UID
:
1576 return lttng::sessiond::user_space_consumer_channel_keys(
1577 *ust_session
, ust_session
->buffer_reg_uid_list
);
1583 ls::user_space_consumer_channel_keys::iterator
1584 ls::user_space_consumer_channel_keys::begin() const noexcept
1586 return ls::user_space_consumer_channel_keys::iterator(_creation_context
);
1589 ls::user_space_consumer_channel_keys::iterator
1590 ls::user_space_consumer_channel_keys::end() const noexcept
1592 return ls::user_space_consumer_channel_keys::iterator(_creation_context
, true);
1595 ls::user_space_consumer_channel_keys::iterator
&
1596 ls::user_space_consumer_channel_keys::iterator::operator++()
1599 LTTNG_THROW_OUT_OF_RANGE(fmt::format(
1600 "Attempted to advance channel key iterator past the end of channel keys: iteration_mode={}",
1601 _creation_context
._session
.buffer_type
));
1604 switch (_creation_context
._session
.buffer_type
) {
1605 case LTTNG_BUFFER_PER_PID
:
1606 _advance_one_per_pid();
1608 case LTTNG_BUFFER_PER_UID
:
1609 _advance_one_per_uid();
1619 bool is_list_empty(const cds_list_head
*head
)
1621 return head
== head
->next
;
1624 bool is_last_element_of_list(const cds_list_head
*head
)
1626 return head
->next
== head
->prev
;
1630 ls::user_space_consumer_channel_keys::iterator::iterator(
1631 const _iterator_creation_context
& creation_context
, bool is_end
) :
1632 _creation_context(creation_context
), _is_end(is_end
)
1638 switch (_creation_context
._mode
) {
1639 case _iteration_mode::PER_PID
:
1642 case _iteration_mode::PER_UID
:
1648 void ls::user_space_consumer_channel_keys::iterator::_skip_to_next_app_per_pid(
1649 bool try_current
) noexcept
1651 auto& position
= _position
._per_pid
;
1655 lttng_ht_get_next(_creation_context
._container
.apps
,
1656 &position
.app_iterator
);
1658 try_current
= false;
1661 const auto app_node
=
1662 lttng_ht_iter_get_node
<lttng_ht_node_ulong
>(&position
.app_iterator
);
1668 const auto& app
= *lttng::utils::container_of(app_node
, &ust_app::pid_n
);
1669 auto app_session
= ust_app_lookup_app_session(&_creation_context
._session
, &app
);
1672 /* This app is not traced by the target session. */
1676 position
.current_app_session
= app_session
->lock();
1678 auto *registry
= ust_app_get_session_registry(
1679 (*_position
._per_pid
.current_app_session
)->get_identifier());
1681 DBG_FMT("Application session is being torn down: skipping application: app={}",
1686 position
.current_registry_session
= registry
;
1687 lttng_ht_get_first((*position
.current_app_session
)->channels
,
1688 &_position
.channel_iterator
);
1693 void ls::user_space_consumer_channel_keys::iterator::_init_per_pid() noexcept
1695 auto& position
= _position
._per_pid
;
1697 lttng_ht_get_first(_creation_context
._container
.apps
, &position
.app_iterator
);
1698 _skip_to_next_app_per_pid(true);
1701 void ls::user_space_consumer_channel_keys::iterator::_init_per_uid() noexcept
1703 auto& position
= _position
._per_uid
;
1705 /* Start the iteration: get the first registry and point to its first channel. */
1706 if (is_list_empty(&_creation_context
._session
.buffer_reg_uid_list
)) {
1711 position
.current_registry
= lttng::utils::container_of(
1712 _creation_context
._session
.buffer_reg_uid_list
.next
, &buffer_reg_uid::lnode
);
1713 lttng_ht_get_first(position
.current_registry
->registry
->channels
,
1714 &_position
.channel_iterator
);
1717 void ls::user_space_consumer_channel_keys::iterator::_advance_one_per_pid()
1719 auto& position
= _position
._per_pid
;
1721 if (!cds_lfht_iter_get_node(&_position
.channel_iterator
.iter
)) {
1722 /* Reached the last channel. Move on to the next app. */
1723 _skip_to_next_app_per_pid(false);
1727 const auto current_app_node
=
1728 lttng_ht_iter_get_node
<lttng_ht_node_ulong
>(&position
.app_iterator
);
1729 LTTNG_ASSERT(current_app_node
);
1731 lttng_ht_get_next((*position
.current_app_session
)->channels
, &_position
.channel_iterator
);
1734 void ls::user_space_consumer_channel_keys::iterator::_advance_one_per_uid()
1736 auto& position
= _position
._per_uid
;
1738 if (!cds_lfht_iter_get_node(&_position
.channel_iterator
.iter
)) {
1739 /* Reached the last channel of the registry. Move on to the next registry. */
1740 if (is_last_element_of_list(&position
.current_registry
->lnode
)) {
1745 position
.current_registry
= lttng::utils::container_of(
1746 position
.current_registry
->lnode
.next
, &buffer_reg_uid::lnode
);
1747 cds_lfht_first(position
.current_registry
->registry
->channels
->ht
,
1748 &_position
.channel_iterator
.iter
);
1750 /* Assumes a registry can't be empty. */
1751 LTTNG_ASSERT(cds_lfht_iter_get_node(&_position
.channel_iterator
.iter
));
1754 cds_lfht_next(position
.current_registry
->registry
->channels
->ht
,
1755 &_position
.channel_iterator
.iter
);
1758 bool ls::user_space_consumer_channel_keys::iterator::operator==(const iterator
& other
) const noexcept
1760 if (_is_end
&& other
._is_end
) {
1764 /* Channel keys are unique; use them to compare the iterators. */
1765 return !_is_end
&& !other
._is_end
&& **this == *other
;
1768 bool ls::user_space_consumer_channel_keys::iterator::operator!=(const iterator
& other
) const noexcept
1770 return !(*this == other
);
1773 ls::user_space_consumer_channel_keys::iterator::key
1774 ls::user_space_consumer_channel_keys::iterator::_get_current_value_per_pid() const noexcept
1776 auto& position
= _position
._per_pid
;
1778 const auto *channel_node
=
1779 lttng_ht_iter_get_node
<lttng_ht_node_str
>(&_position
.channel_iterator
);
1780 const auto current_app_node
=
1781 lttng_ht_iter_get_node
<lttng_ht_node_ulong
>(&position
.app_iterator
);
1782 LTTNG_ASSERT(current_app_node
);
1784 const auto& app
= *lttng::utils::container_of(current_app_node
, &ust_app::pid_n
);
1787 const auto& channel
=
1788 *lttng::utils::container_of(channel_node
, &ust_app_channel::node
);
1790 return { static_cast<consumer_bitness
>(app
.abi
.bits_per_long
),
1792 ls::user_space_consumer_channel_keys::channel_type::DATA
};
1794 LTTNG_ASSERT(position
.current_registry_session
);
1797 * Once the last data channel is delivered (iter points to the 'end' of the ht),
1798 * deliver the metadata channel's key.
1800 return { static_cast<consumer_bitness
>(app
.abi
.bits_per_long
),
1801 position
.current_registry_session
->_metadata_key
,
1802 ls::user_space_consumer_channel_keys::channel_type::METADATA
};
1806 ls::user_space_consumer_channel_keys::iterator::key
1807 ls::user_space_consumer_channel_keys::iterator::_get_current_value_per_uid() const noexcept
1809 const auto *channel_node
=
1810 lttng_ht_iter_get_node
<lttng_ht_node_u64
>(&_position
.channel_iterator
);
1813 const auto& channel
=
1814 *lttng::utils::container_of(channel_node
, &buffer_reg_channel::node
);
1816 return { static_cast<consumer_bitness
>(
1817 _position
._per_uid
.current_registry
->bits_per_long
),
1818 channel
.consumer_key
,
1819 ls::user_space_consumer_channel_keys::channel_type::DATA
};
1822 * Once the last data channel is delivered (iter points to the 'end' of the ht),
1823 * deliver the metadata channel's key.
1825 return { static_cast<consumer_bitness
>(
1826 _position
._per_uid
.current_registry
->bits_per_long
),
1827 _position
._per_uid
.current_registry
->registry
->reg
.ust
->_metadata_key
,
1828 ls::user_space_consumer_channel_keys::channel_type::METADATA
};
1832 ls::user_space_consumer_channel_keys::iterator::key
1833 ls::user_space_consumer_channel_keys::iterator::operator*() const
1836 LTTNG_THROW_OUT_OF_RANGE(
1837 "Attempt to use operator* on user_space_consumer_channel_keys iterator at the end position");
1840 switch (_creation_context
._mode
) {
1841 case _iteration_mode::PER_PID
:
1842 return _get_current_value_per_pid();
1843 case _iteration_mode::PER_UID
:
1844 return _get_current_value_per_uid();
1850 ls::ust::registry_session
*ls::user_space_consumer_channel_keys::iterator::get_registry_session()
1853 LTTNG_THROW_OUT_OF_RANGE(
1854 "Attempt to get registry session on user_space_consumer_channel_keys iterator at the end position");
1857 switch (_creation_context
._mode
) {
1858 case _iteration_mode::PER_PID
:
1859 return _get_registry_session_per_pid();
1860 case _iteration_mode::PER_UID
:
1861 return _get_registry_session_per_uid();
1867 ls::ust::registry_session
*
1868 ls::user_space_consumer_channel_keys::iterator::_get_registry_session_per_pid()
1870 return _position
._per_pid
.current_registry_session
;
1873 ls::ust::registry_session
*
1874 ls::user_space_consumer_channel_keys::iterator::_get_registry_session_per_uid()
1876 return _position
._per_uid
.current_registry
->registry
->reg
.ust
;