clang-tidy: apply suggested fixes
[lttng-tools.git] / src / bin / lttng-sessiond / session.cpp
CommitLineData
5b74c7b1 1/*
21cf9b6b 2 * Copyright (C) 2011 EfficiOS Inc.
5b74c7b1 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
91d76f53 5 *
5b74c7b1
DG
6 */
7
6c1c0768 8#define _LGPL_SOURCE
16d64977 9#include "buffer-registry.hpp"
28ab034a
JG
10#include "cmd.hpp"
11#include "kernel.hpp"
12#include "lttng-sessiond.hpp"
13#include "session.hpp"
14#include "timer.hpp"
15#include "trace-ust.hpp"
16d64977 16#include "ust-app.hpp"
28ab034a
JG
17#include "utils.hpp"
18
19#include <common/common.hpp>
16d64977 20#include <common/ctl/format.hpp>
28ab034a
JG
21#include <common/sessiond-comm/sessiond-comm.hpp>
22#include <common/trace-chunk.hpp>
23#include <common/urcu.hpp>
24#include <common/utils.hpp>
25
26#include <lttng/location-internal.hpp>
27
e99e3664 28#include <dirent.h>
d022620a 29#include <inttypes.h>
e99e3664
JG
30#include <limits.h>
31#include <pthread.h>
5b74c7b1
DG
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
a304c14c 35#include <sys/stat.h>
3d071855 36#include <sys/types.h>
e99e3664 37#include <urcu.h>
5b74c7b1 38
f1494934 39namespace {
3e3665b8
JG
40struct ltt_session_destroy_notifier_element {
41 ltt_session_destroy_notifier notifier;
42 void *user_data;
43};
44
ccbdaca4
MD
45struct ltt_session_clear_notifier_element {
46 ltt_session_clear_notifier notifier;
47 void *user_data;
48};
49
e99e3664
JG
50namespace ls = lttng::sessiond;
51
8c0faa1d 52/*
b5541356 53 * NOTES:
8c0faa1d 54 *
b5541356 55 * No ltt_session.lock is taken here because those data structure are widely
e1bbf989 56 * spread across the lttng-tools code base so before calling functions below
b5541356 57 * that can read/write a session, the caller MUST acquire the session lock
54d01ffb 58 * using session_lock() and session_unlock().
8c0faa1d 59 */
8c0faa1d 60
f1494934
JG
61/* These characters are forbidden in a session name. Used by validate_name. */
62const char *forbidden_name_chars = "/";
63
64/* Global hash table to keep the sessions, indexed by id. */
cd9adb8b 65struct lttng_ht *ltt_sessions_ht_by_id = nullptr;
f1494934 66/* Global hash table to keep the sessions, indexed by name. */
cd9adb8b 67struct lttng_ht *ltt_sessions_ht_by_name = nullptr;
f1494934 68
5b74c7b1 69/*
b5541356 70 * Init tracing session list.
5b74c7b1 71 *
b5541356 72 * Please see session.h for more explanation and correct usage of the list.
5b74c7b1 73 */
1a496780 74struct ltt_session_list the_session_list;
d9a970b7
JG
75
76/*
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.
81 */
82struct ltt_session *session_find_by_name(const char *name)
83{
84 struct ltt_session *iter;
85
86 LTTNG_ASSERT(name);
87 ASSERT_SESSION_LIST_LOCKED();
88
89 DBG2("Trying to find session by name %s", name);
90
91 cds_list_for_each_entry (iter, &the_session_list.head, list) {
92 if (!strncmp(iter->name, name, NAME_MAX) && !iter->destroyed) {
93 goto found;
94 }
95 }
96
97 return nullptr;
98found:
99 return session_get(iter) ? iter : nullptr;
100}
101
102/*
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).
106 */
107struct ltt_session *session_find_by_id(uint64_t id)
108{
109 struct lttng_ht_node_u64 *node;
110 struct lttng_ht_iter iter;
111 struct ltt_session *ls;
112
113 ASSERT_RCU_READ_LOCKED();
114 ASSERT_SESSION_LIST_LOCKED();
115
116 if (!ltt_sessions_ht_by_id) {
117 goto end;
118 }
119
120 lttng_ht_lookup(ltt_sessions_ht_by_id, &id, &iter);
00d7d903 121 node = lttng_ht_iter_get_node<lttng_ht_node_u64>(&iter);
d9a970b7
JG
122 if (node == nullptr) {
123 goto end;
124 }
125 ls = lttng::utils::container_of(node, &ltt_session::node);
126
127 DBG3("Session %" PRIu64 " found by id.", id);
128 return session_get(ls) ? ls : nullptr;
129
130end:
131 DBG3("Session %" PRIu64 " NOT found by id", id);
132 return nullptr;
133}
f1494934 134} /* namespace */
23324029 135
1c1c3634
DG
136/*
137 * Validate the session name for forbidden characters.
138 *
139 * Return 0 on success else -1 meaning a forbidden char. has been found.
140 */
141static int validate_name(const char *name)
142{
143 int ret;
144 char *tok, *tmp_name;
145
a0377dfe 146 LTTNG_ASSERT(name);
1c1c3634
DG
147
148 tmp_name = strdup(name);
149 if (!tmp_name) {
150 /* ENOMEM here. */
151 ret = -1;
152 goto error;
153 }
154
155 tok = strpbrk(tmp_name, forbidden_name_chars);
156 if (tok) {
157 DBG("Session name %s contains a forbidden character", name);
158 /* Forbidden character has been found. */
159 ret = -1;
160 goto error;
161 }
162 ret = 0;
163
164error:
165 free(tmp_name);
166 return ret;
167}
168
5b74c7b1 169/*
050349bb 170 * Add a ltt_session structure to the global list.
5b74c7b1 171 *
050349bb 172 * The caller MUST acquire the session list lock before.
44e96653 173 * Returns the unique identifier for the session.
5b74c7b1 174 */
d022620a 175static uint64_t add_session_list(struct ltt_session *ls)
5b74c7b1 176{
a0377dfe 177 LTTNG_ASSERT(ls);
0525e9ae 178
f1494934
JG
179 cds_list_add(&ls->list, &the_session_list.head);
180 return the_session_list.next_uuid++;
5b74c7b1
DG
181}
182
183/*
050349bb 184 * Delete a ltt_session structure to the global list.
b5541356 185 *
050349bb 186 * The caller MUST acquire the session list lock before.
5b74c7b1
DG
187 */
188static void del_session_list(struct ltt_session *ls)
189{
a0377dfe 190 LTTNG_ASSERT(ls);
0525e9ae 191
5b74c7b1 192 cds_list_del(&ls->list);
5b74c7b1
DG
193}
194
b5541356 195/*
050349bb 196 * Return a pointer to the session list.
b5541356 197 */
cd9adb8b 198struct ltt_session_list *session_get_list()
b5541356 199{
f1494934 200 return &the_session_list;
b5541356
DG
201}
202
99d688f2
JG
203/*
204 * Returns once the session list is empty.
205 */
d9a970b7 206void session_list_wait_empty(std::unique_lock<std::mutex> list_lock)
99d688f2 207{
1a496780
JG
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); });
99d688f2
JG
211}
212
71e0a100
JG
213/*
214 * Try to acquire session list lock
215 */
0038180d 216int session_trylock_list() noexcept
71e0a100 217{
1a496780
JG
218 /* Return 0 if successfully acquired. */
219 return the_session_list.lock.try_lock() ? 0 : 1;
71e0a100
JG
220}
221
dd73d57b
JG
222/*
223 * Get the session's consumer destination type.
dd73d57b 224 */
a0a4f314 225enum consumer_dst_type session_get_consumer_destination_type(const ltt_session::locked_ref& session)
dd73d57b
JG
226{
227 /*
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.
231 */
28ab034a
JG
232 return session->kernel_session ? session->kernel_session->consumer->type :
233 session->ust_session->consumer->type;
dd73d57b
JG
234}
235
236/*
237 * Get the session's consumer network hostname.
238 * The caller must ensure that the destination is of type "net".
dd73d57b 239 */
a0a4f314 240const char *session_get_net_consumer_hostname(const ltt_session::locked_ref& session)
dd73d57b 241{
cd9adb8b 242 const char *hostname = nullptr;
dd73d57b
JG
243 const struct consumer_output *output;
244
28ab034a
JG
245 output = session->kernel_session ? session->kernel_session->consumer :
246 session->ust_session->consumer;
dd73d57b
JG
247
248 /*
249 * hostname is assumed to be the same for both control and data
250 * connections.
251 */
252 switch (output->dst.net.control.dtype) {
253 case LTTNG_DST_IPV4:
254 hostname = output->dst.net.control.dst.ipv4;
255 break;
256 case LTTNG_DST_IPV6:
257 hostname = output->dst.net.control.dst.ipv6;
258 break;
259 default:
260 abort();
261 }
262 return hostname;
263}
264
265/*
266 * Get the session's consumer network control and data ports.
267 * The caller must ensure that the destination is of type "net".
dd73d57b 268 */
a0a4f314 269void session_get_net_consumer_ports(const ltt_session::locked_ref& session,
28ab034a
JG
270 uint16_t *control_port,
271 uint16_t *data_port)
dd73d57b
JG
272{
273 const struct consumer_output *output;
274
28ab034a
JG
275 output = session->kernel_session ? session->kernel_session->consumer :
276 session->ust_session->consumer;
dd73d57b
JG
277 *control_port = output->dst.net.control.port;
278 *data_port = output->dst.net.data.port;
279}
280
5d65beab
JG
281/*
282 * Get the location of the latest trace archive produced by a rotation.
5d65beab 283 */
28ab034a 284struct lttng_trace_archive_location *
a0a4f314 285session_get_trace_archive_location(const ltt_session::locked_ref& session)
5d65beab 286{
d2956687 287 int ret;
cd9adb8b
JG
288 struct lttng_trace_archive_location *location = nullptr;
289 char *chunk_path = nullptr;
d2956687
JG
290
291 if (session->rotation_state != LTTNG_ROTATION_STATE_COMPLETED ||
28ab034a 292 !session->last_archived_chunk_name) {
d2956687
JG
293 goto end;
294 }
5d65beab 295
5d65beab
JG
296 switch (session_get_consumer_destination_type(session)) {
297 case CONSUMER_DST_LOCAL:
ecd1a12f 298 ret = asprintf(&chunk_path,
28ab034a
JG
299 "%s/" DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY "/%s",
300 session_get_base_path(session),
301 session->last_archived_chunk_name);
ecd1a12f
MD
302 if (ret == -1) {
303 goto end;
304 }
28ab034a 305 location = lttng_trace_archive_location_local_create(chunk_path);
5d65beab
JG
306 break;
307 case CONSUMER_DST_NET:
308 {
309 const char *hostname;
310 uint16_t control_port, data_port;
311
312 hostname = session_get_net_consumer_hostname(session);
28ab034a 313 session_get_net_consumer_ports(session, &control_port, &data_port);
5d65beab 314 location = lttng_trace_archive_location_relay_create(
28ab034a
JG
315 hostname,
316 LTTNG_TRACE_ARCHIVE_LOCATION_RELAY_PROTOCOL_TYPE_TCP,
317 control_port,
318 data_port,
319 session->last_chunk_path);
5d65beab
JG
320 break;
321 }
322 default:
323 abort();
324 }
325end:
d2956687 326 free(chunk_path);
5d65beab
JG
327 return location;
328}
329
23324029 330/*
e1bbf989 331 * Allocate the ltt_sessions_ht_by_id and ltt_sessions_ht_by_name HT.
9c6518bc
JG
332 *
333 * The session list lock must be held.
23324029 334 */
cd9adb8b 335static int ltt_sessions_ht_alloc()
23324029
JD
336{
337 int ret = 0;
338
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) {
342 ret = -1;
343 ERR("Failed to allocate ltt_sessions_ht_by_id");
344 goto end;
345 }
e1bbf989
JR
346
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) {
350 ret = -1;
351 ERR("Failed to allocate ltt_sessions_ht_by_name");
352 goto end;
353 }
354
23324029
JD
355end:
356 return ret;
357}
358
359/*
360 * Destroy the ltt_sessions_ht_by_id HT.
9c6518bc
JG
361 *
362 * The session list lock must be held.
23324029 363 */
cd9adb8b 364static void ltt_sessions_ht_destroy()
23324029 365{
e1bbf989 366 if (ltt_sessions_ht_by_id) {
3c339053 367 lttng_ht_destroy(ltt_sessions_ht_by_id);
cd9adb8b 368 ltt_sessions_ht_by_id = nullptr;
e1bbf989
JR
369 }
370
371 if (ltt_sessions_ht_by_name) {
3c339053 372 lttng_ht_destroy(ltt_sessions_ht_by_name);
cd9adb8b 373 ltt_sessions_ht_by_name = nullptr;
23324029 374 }
e1bbf989
JR
375
376 return;
23324029
JD
377}
378
379/*
e1bbf989
JR
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.
23324029
JD
383 */
384static void add_session_ht(struct ltt_session *ls)
385{
386 int ret;
387
a0377dfe 388 LTTNG_ASSERT(ls);
23324029
JD
389
390 if (!ltt_sessions_ht_by_id) {
391 ret = ltt_sessions_ht_alloc();
392 if (ret) {
393 ERR("Error allocating the sessions HT");
394 goto end;
395 }
396 }
e1bbf989
JR
397
398 /* Should always be present with ltt_sessions_ht_by_id. */
a0377dfe 399 LTTNG_ASSERT(ltt_sessions_ht_by_name);
e1bbf989 400
23324029
JD
401 lttng_ht_node_init_u64(&ls->node, ls->id);
402 lttng_ht_add_unique_u64(ltt_sessions_ht_by_id, &ls->node);
403
e1bbf989
JR
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);
406
23324029
JD
407end:
408 return;
409}
410
411/*
e1bbf989 412 * Test if ltt_sessions_ht_by_id/name are empty.
2a6ebf6b 413 * Return `false` if hash table objects are null.
23324029
JD
414 * The session list lock must be held.
415 */
cd9adb8b 416static bool ltt_sessions_ht_empty()
23324029 417{
2a6ebf6b 418 bool empty = false;
23324029
JD
419
420 if (!ltt_sessions_ht_by_id) {
2a6ebf6b 421 /* The hash tables do not exist yet. */
23324029
JD
422 goto end;
423 }
424
a0377dfe 425 LTTNG_ASSERT(ltt_sessions_ht_by_name);
e1bbf989 426
6f729565 427 if (lttng_ht_get_count(ltt_sessions_ht_by_id) != 0) {
2a6ebf6b
JR
428 /* Not empty.*/
429 goto end;
430 }
431
432 /*
433 * At this point it is expected that the `ltt_sessions_ht_by_name` ht is
434 * empty.
435 *
436 * The removal from both hash tables is done in two different
437 * places:
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.
442 *
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
446 * check.
447 */
448 LTTNG_ASSERT(lttng_ht_get_count(ltt_sessions_ht_by_name) == 0);
449 empty = true;
23324029 450end:
2a6ebf6b 451 return empty;
23324029
JD
452}
453
454/*
ed41e570 455 * Remove a ltt_session from the ltt_sessions_ht_by_id.
e1bbf989 456 * If empty, the ltt_sessions_ht_by_id/name HTs are freed.
23324029
JD
457 * The session list lock must be held.
458 */
459static void del_session_ht(struct ltt_session *ls)
460{
461 struct lttng_ht_iter iter;
462 int ret;
463
a0377dfe
FD
464 LTTNG_ASSERT(ls);
465 LTTNG_ASSERT(ltt_sessions_ht_by_id);
466 LTTNG_ASSERT(ltt_sessions_ht_by_name);
23324029
JD
467
468 iter.iter.node = &ls->node.node;
469 ret = lttng_ht_del(ltt_sessions_ht_by_id, &iter);
a0377dfe 470 LTTNG_ASSERT(!ret);
23324029
JD
471
472 if (ltt_sessions_ht_empty()) {
e1bbf989 473 DBG("Empty ltt_sessions_ht_by_id/name, destroying hast tables");
23324029
JD
474 ltt_sessions_ht_destroy();
475 }
476}
477
b5541356 478/*
6c9cc2ab 479 * Acquire session lock
b5541356 480 */
16d64977 481void session_lock(const ltt_session *session)
b5541356 482{
a0377dfe 483 LTTNG_ASSERT(session);
d9a970b7
JG
484 session->lock();
485}
0525e9ae 486
d9a970b7
JG
487void ltt_session::lock() const noexcept
488{
489 pthread_mutex_lock(&_lock);
490}
491
492void ltt_session::unlock() const noexcept
493{
494 ltt_session::_const_session_unlock(*this);
6c9cc2ab 495}
b5541356 496
6c9cc2ab
DG
497/*
498 * Release session lock
499 */
16d64977 500void session_unlock(const ltt_session *session)
6c9cc2ab 501{
a0377dfe 502 LTTNG_ASSERT(session);
d9a970b7
JG
503 session->unlock();
504}
0525e9ae 505
a0a4f314 506void ltt_session::_const_session_unlock(const ltt_session& session)
d9a970b7
JG
507{
508 pthread_mutex_unlock(&session._lock);
b5541356
DG
509}
510
a0a4f314 511static int _session_set_trace_chunk_no_lock_check(const ltt_session::locked_ref& session,
28ab034a
JG
512 struct lttng_trace_chunk *new_trace_chunk,
513 struct lttng_trace_chunk **_current_trace_chunk)
82b69413 514{
78fc586b 515 int ret = 0;
82b69413 516 unsigned int i, refs_to_acquire = 0, refs_acquired = 0, refs_to_release = 0;
82b69413
JG
517 struct cds_lfht_iter iter;
518 struct consumer_socket *socket;
d2956687
JG
519 struct lttng_trace_chunk *current_trace_chunk;
520 uint64_t chunk_id;
521 enum lttng_trace_chunk_status chunk_status;
82b69413 522
07c4863f 523 const lttng::urcu::read_lock_guard read_lock;
82b69413 524 /*
d2956687
JG
525 * Ownership of current trace chunk is transferred to
526 * `current_trace_chunk`.
82b69413 527 */
d2956687 528 current_trace_chunk = session->current_trace_chunk;
cd9adb8b 529 session->current_trace_chunk = nullptr;
82b69413 530 if (session->ust_session) {
28ab034a 531 lttng_trace_chunk_put(session->ust_session->current_trace_chunk);
cd9adb8b 532 session->ust_session->current_trace_chunk = nullptr;
82b69413
JG
533 }
534 if (session->kernel_session) {
28ab034a 535 lttng_trace_chunk_put(session->kernel_session->current_trace_chunk);
cd9adb8b 536 session->kernel_session->current_trace_chunk = nullptr;
82b69413 537 }
d2956687
JG
538 if (!new_trace_chunk) {
539 ret = 0;
540 goto end;
82b69413 541 }
d2956687 542 chunk_status = lttng_trace_chunk_get_id(new_trace_chunk, &chunk_id);
a0377dfe 543 LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK);
82b69413 544
d2956687
JG
545 refs_to_acquire = 1;
546 refs_to_acquire += !!session->ust_session;
547 refs_to_acquire += !!session->kernel_session;
548
28ab034a 549 for (refs_acquired = 0; refs_acquired < refs_to_acquire; refs_acquired++) {
d2956687
JG
550 if (!lttng_trace_chunk_get(new_trace_chunk)) {
551 ERR("Failed to acquire reference to new trace chunk of session \"%s\"",
28ab034a 552 session->name);
d2956687 553 goto error;
82b69413
JG
554 }
555 }
556
d2956687 557 if (session->ust_session) {
28ab034a
JG
558 const uint64_t relayd_id = session->ust_session->consumer->net_seq_index;
559 const bool is_local_trace = session->ust_session->consumer->type ==
560 CONSUMER_DST_LOCAL;
e5add6d0 561
d2956687 562 session->ust_session->current_trace_chunk = new_trace_chunk;
f8a37411 563 if (is_local_trace) {
d2956687 564 enum lttng_error_code ret_error_code;
82b69413 565
28ab034a
JG
566 ret_error_code =
567 ust_app_create_channel_subdirectories(session->ust_session);
d2956687 568 if (ret_error_code != LTTNG_OK) {
82b69413
JG
569 goto error;
570 }
f8a37411 571 }
28ab034a
JG
572 cds_lfht_for_each_entry (
573 session->ust_session->consumer->socks->ht, &iter, socket, node.node) {
d2956687
JG
574 pthread_mutex_lock(socket->lock);
575 ret = consumer_create_trace_chunk(socket,
28ab034a
JG
576 relayd_id,
577 session->id,
578 new_trace_chunk,
579 DEFAULT_UST_TRACE_DIR);
d2956687 580 pthread_mutex_unlock(socket->lock);
f8a37411 581 if (ret) {
d2956687 582 goto error;
f8a37411
JG
583 }
584 }
585 }
82b69413 586 if (session->kernel_session) {
28ab034a
JG
587 const uint64_t relayd_id = session->kernel_session->consumer->net_seq_index;
588 const bool is_local_trace = session->kernel_session->consumer->type ==
589 CONSUMER_DST_LOCAL;
e5add6d0 590
d2956687
JG
591 session->kernel_session->current_trace_chunk = new_trace_chunk;
592 if (is_local_trace) {
593 enum lttng_error_code ret_error_code;
594
28ab034a
JG
595 ret_error_code =
596 kernel_create_channel_subdirectories(session->kernel_session);
d2956687 597 if (ret_error_code != LTTNG_OK) {
d2956687
JG
598 goto error;
599 }
f8a37411 600 }
28ab034a
JG
601 cds_lfht_for_each_entry (
602 session->kernel_session->consumer->socks->ht, &iter, socket, node.node) {
d2956687
JG
603 pthread_mutex_lock(socket->lock);
604 ret = consumer_create_trace_chunk(socket,
28ab034a
JG
605 relayd_id,
606 session->id,
607 new_trace_chunk,
608 DEFAULT_KERNEL_TRACE_DIR);
d2956687 609 pthread_mutex_unlock(socket->lock);
f8a37411 610 if (ret) {
d2956687 611 goto error;
f8a37411
JG
612 }
613 }
614 }
82b69413
JG
615
616 /*
617 * Update local current trace chunk state last, only if all remote
d2956687 618 * creations succeeded.
82b69413
JG
619 */
620 session->current_trace_chunk = new_trace_chunk;
d2956687
JG
621 LTTNG_OPTIONAL_SET(&session->most_recent_chunk_id, chunk_id);
622end:
623 if (_current_trace_chunk) {
624 *_current_trace_chunk = current_trace_chunk;
cd9adb8b 625 current_trace_chunk = nullptr;
d2956687
JG
626 }
627end_no_move:
d2956687
JG
628 lttng_trace_chunk_put(current_trace_chunk);
629 return ret;
630error:
82b69413 631 if (session->ust_session) {
cd9adb8b 632 session->ust_session->current_trace_chunk = nullptr;
82b69413
JG
633 }
634 if (session->kernel_session) {
cd9adb8b 635 session->kernel_session->current_trace_chunk = nullptr;
82b69413 636 }
f8a37411 637 /*
82b69413
JG
638 * Release references taken in the case where all references could not
639 * be acquired.
640 */
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);
644 }
d2956687
JG
645 ret = -1;
646 goto end_no_move;
82b69413
JG
647}
648
28ab034a 649struct lttng_trace_chunk *
a0a4f314 650session_create_new_trace_chunk(const ltt_session::locked_ref& session,
28ab034a
JG
651 const struct consumer_output *consumer_output_override,
652 const char *session_base_path_override,
653 const char *chunk_name_override)
82b69413
JG
654{
655 int ret;
cd9adb8b 656 struct lttng_trace_chunk *trace_chunk = nullptr;
82b69413 657 enum lttng_trace_chunk_status chunk_status;
cd9adb8b 658 const time_t chunk_creation_ts = time(nullptr);
348a81dc
JG
659 bool is_local_trace;
660 const char *base_path;
cd9adb8b 661 struct lttng_directory_handle *session_output_directory = nullptr;
82b69413 662 const struct lttng_credentials session_credentials = {
ff588497
JR
663 .uid = LTTNG_OPTIONAL_INIT_VALUE(session->uid),
664 .gid = LTTNG_OPTIONAL_INIT_VALUE(session->gid),
82b69413
JG
665 };
666 uint64_t next_chunk_id;
348a81dc 667 const struct consumer_output *output;
a7ceb342 668 const char *new_path;
348a81dc
JG
669
670 if (consumer_output_override) {
671 output = consumer_output_override;
672 } else {
a0377dfe 673 LTTNG_ASSERT(session->ust_session || session->kernel_session);
28ab034a
JG
674 output = session->ust_session ? session->ust_session->consumer :
675 session->kernel_session->consumer;
348a81dc
JG
676 }
677
678 is_local_trace = output->type == CONSUMER_DST_LOCAL;
28ab034a 679 base_path = session_base_path_override ?: consumer_output_get_base_path(output);
82b69413 680
d2956687
JG
681 if (chunk_creation_ts == (time_t) -1) {
682 PERROR("Failed to sample time while creation session \"%s\" trace chunk",
28ab034a 683 session->name);
82b69413
JG
684 goto error;
685 }
82b69413 686
28ab034a
JG
687 next_chunk_id =
688 session->most_recent_chunk_id.is_set ? session->most_recent_chunk_id.value + 1 : 0;
82b69413 689
a7ceb342 690 if (session->current_trace_chunk &&
28ab034a 691 !lttng_trace_chunk_get_name_overridden(session->current_trace_chunk)) {
a7ceb342 692 chunk_status = lttng_trace_chunk_rename_path(session->current_trace_chunk,
28ab034a 693 DEFAULT_CHUNK_TMP_OLD_DIRECTORY);
a7ceb342
MD
694 if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
695 goto error;
696 }
697 }
698 if (!session->current_trace_chunk) {
699 if (!session->rotated) {
700 new_path = "";
701 } else {
cd9adb8b 702 new_path = nullptr;
a7ceb342
MD
703 }
704 } else {
705 new_path = DEFAULT_CHUNK_TMP_NEW_DIRECTORY;
706 }
707
28ab034a 708 trace_chunk = lttng_trace_chunk_create(next_chunk_id, chunk_creation_ts, new_path);
82b69413 709 if (!trace_chunk) {
82b69413
JG
710 goto error;
711 }
712
713 if (chunk_name_override) {
28ab034a 714 chunk_status = lttng_trace_chunk_override_name(trace_chunk, chunk_name_override);
d2956687 715 if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
82b69413
JG
716 goto error;
717 }
718 }
719
720 if (!is_local_trace) {
721 /*
722 * No need to set crendentials and output directory
723 * for remote trace chunks.
724 */
d2956687 725 goto end;
82b69413
JG
726 }
727
28ab034a 728 chunk_status = lttng_trace_chunk_set_credentials(trace_chunk, &session_credentials);
82b69413 729 if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
82b69413
JG
730 goto error;
731 }
732
28ab034a
JG
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);
82b69413 735 if (ret) {
82b69413
JG
736 goto error;
737 }
cbf53d23
JG
738 session_output_directory = lttng_directory_handle_create(base_path);
739 if (!session_output_directory) {
82b69413
JG
740 goto error;
741 }
28ab034a 742 chunk_status = lttng_trace_chunk_set_as_owner(trace_chunk, session_output_directory);
cbf53d23 743 lttng_directory_handle_put(session_output_directory);
cd9adb8b 744 session_output_directory = nullptr;
82b69413 745 if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
82b69413
JG
746 goto error;
747 }
d2956687
JG
748end:
749 return trace_chunk;
82b69413 750error:
cbf53d23 751 lttng_directory_handle_put(session_output_directory);
82b69413 752 lttng_trace_chunk_put(trace_chunk);
cd9adb8b 753 trace_chunk = nullptr;
d2956687
JG
754 goto end;
755}
756
a0a4f314 757int session_close_trace_chunk(const ltt_session::locked_ref& session,
28ab034a
JG
758 struct lttng_trace_chunk *trace_chunk,
759 enum lttng_trace_chunk_command_type close_command,
760 char *closed_trace_chunk_path)
d2956687
JG
761{
762 int ret = 0;
763 bool error_occurred = false;
764 struct cds_lfht_iter iter;
765 struct consumer_socket *socket;
766 enum lttng_trace_chunk_status chunk_status;
cd9adb8b 767 const time_t chunk_close_timestamp = time(nullptr);
a7ceb342 768 const char *new_path;
d2956687 769
28ab034a 770 chunk_status = lttng_trace_chunk_set_close_command(trace_chunk, close_command);
343defc2
MD
771 if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
772 ret = -1;
773 goto end;
bbc4768c
JG
774 }
775
d2956687
JG
776 if (chunk_close_timestamp == (time_t) -1) {
777 ERR("Failed to sample the close timestamp of the current trace chunk of session \"%s\"",
28ab034a 778 session->name);
d2956687
JG
779 ret = -1;
780 goto end;
781 }
a7ceb342
MD
782
783 if (close_command == LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE && !session->rotated) {
784 /* New chunk stays in session output directory. */
785 new_path = "";
786 } else {
787 /* Use chunk name for new chunk. */
cd9adb8b 788 new_path = nullptr;
a7ceb342
MD
789 }
790 if (session->current_trace_chunk &&
28ab034a 791 !lttng_trace_chunk_get_name_overridden(session->current_trace_chunk)) {
a7ceb342 792 /* Rename new chunk path. */
28ab034a
JG
793 chunk_status =
794 lttng_trace_chunk_rename_path(session->current_trace_chunk, new_path);
a7ceb342
MD
795 if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
796 ret = -1;
797 goto end;
798 }
799 }
800 if (!lttng_trace_chunk_get_name_overridden(trace_chunk) &&
28ab034a 801 close_command == LTTNG_TRACE_CHUNK_COMMAND_TYPE_NO_OPERATION) {
a7ceb342
MD
802 const char *old_path;
803
804 if (!session->rotated) {
805 old_path = "";
806 } else {
cd9adb8b 807 old_path = nullptr;
a7ceb342
MD
808 }
809 /* We need to move back the .tmp_old_chunk to its rightful place. */
28ab034a 810 chunk_status = lttng_trace_chunk_rename_path(trace_chunk, old_path);
a7ceb342
MD
811 if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
812 ret = -1;
813 goto end;
814 }
815 }
816 if (close_command == LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED) {
817 session->rotated = true;
818 }
28ab034a 819 chunk_status = lttng_trace_chunk_set_close_timestamp(trace_chunk, chunk_close_timestamp);
d2956687
JG
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\"",
28ab034a 822 session->name);
d2956687
JG
823 ret = -1;
824 goto end;
825 }
826
827 if (session->ust_session) {
28ab034a 828 const uint64_t relayd_id = session->ust_session->consumer->net_seq_index;
0a184d4e 829
28ab034a
JG
830 cds_lfht_for_each_entry (
831 session->ust_session->consumer->socks->ht, &iter, socket, node.node) {
d2956687
JG
832 pthread_mutex_lock(socket->lock);
833 ret = consumer_close_trace_chunk(socket,
28ab034a
JG
834 relayd_id,
835 session->id,
836 trace_chunk,
837 closed_trace_chunk_path);
d2956687
JG
838 pthread_mutex_unlock(socket->lock);
839 if (ret) {
840 ERR("Failed to close trace chunk on user space consumer");
841 error_occurred = true;
842 }
843 }
844 }
845 if (session->kernel_session) {
28ab034a 846 const uint64_t relayd_id = session->kernel_session->consumer->net_seq_index;
0a184d4e 847
28ab034a
JG
848 cds_lfht_for_each_entry (
849 session->kernel_session->consumer->socks->ht, &iter, socket, node.node) {
d2956687
JG
850 pthread_mutex_lock(socket->lock);
851 ret = consumer_close_trace_chunk(socket,
28ab034a
JG
852 relayd_id,
853 session->id,
854 trace_chunk,
855 closed_trace_chunk_path);
d2956687
JG
856 pthread_mutex_unlock(socket->lock);
857 if (ret) {
858 ERR("Failed to close trace chunk on kernel consumer");
859 error_occurred = true;
860 }
861 }
862 }
863 ret = error_occurred ? -1 : 0;
82b69413 864end:
d2956687 865 return ret;
82b69413
JG
866}
867
04ed9e10
JG
868/*
869 * This function skips the metadata channel as the begin/end timestamps of a
870 * metadata packet are useless.
871 *
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.
876 *
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.
883 */
a0a4f314 884static enum lttng_error_code session_kernel_open_packets(const ltt_session::locked_ref& session)
04ed9e10
JG
885{
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;
891
07c4863f 892 const lttng::urcu::read_lock_guard read_lock;
04ed9e10
JG
893
894 cds_lfht_first(session->kernel_session->consumer->socks->ht, &iter.iter);
895 node = cds_lfht_iter_get_node(&iter.iter);
0114db0e 896 socket = caa_container_of(node, typeof(*socket), node.node);
04ed9e10 897
28ab034a 898 cds_list_for_each_entry (chan, &session->kernel_session->channel_list.head, list) {
04ed9e10
JG
899 int open_ret;
900
901 DBG("Open packet of kernel channel: channel key = %" PRIu64
28ab034a
JG
902 ", session name = %s, session_id = %" PRIu64,
903 chan->key,
904 session->name,
905 session->id);
04ed9e10
JG
906
907 open_ret = consumer_open_channel_packets(socket, chan->key);
908 if (open_ret < 0) {
909 /* General error (no known error expected). */
910 ret = LTTNG_ERR_UNK;
911 goto end;
912 }
913 }
914
915end:
04ed9e10
JG
916 return ret;
917}
918
a0a4f314 919enum lttng_error_code session_open_packets(const ltt_session::locked_ref& session)
04ed9e10
JG
920{
921 enum lttng_error_code ret = LTTNG_OK;
922
923 DBG("Opening packets of session channels: session name = %s, session id = %" PRIu64,
28ab034a
JG
924 session->name,
925 session->id);
04ed9e10
JG
926
927 if (session->ust_session) {
928 ret = ust_app_open_packets(session);
929 if (ret != LTTNG_OK) {
930 goto end;
931 }
932 }
933
934 if (session->kernel_session) {
935 ret = session_kernel_open_packets(session);
936 if (ret != LTTNG_OK) {
937 goto end;
938 }
939 }
940
941end:
942 return ret;
943}
944
82b69413
JG
945/*
946 * Set a session's current trace chunk.
947 *
948 * Must be called with the session lock held.
949 */
a0a4f314 950int session_set_trace_chunk(const ltt_session::locked_ref& session,
28ab034a
JG
951 struct lttng_trace_chunk *new_trace_chunk,
952 struct lttng_trace_chunk **current_trace_chunk)
82b69413 953{
d9a970b7 954 ASSERT_LOCKED(session->_lock);
28ab034a
JG
955 return _session_set_trace_chunk_no_lock_check(
956 session, new_trace_chunk, current_trace_chunk);
82b69413
JG
957}
958
a0a4f314 959static void session_notify_destruction(const ltt_session::locked_ref& session)
3e3665b8
JG
960{
961 size_t i;
a0a4f314 962 const auto count = lttng_dynamic_array_get_count(&session->destroy_notifiers);
3e3665b8
JG
963
964 for (i = 0; i < count; i++) {
965 const struct ltt_session_destroy_notifier_element *element =
7966af57 966 (ltt_session_destroy_notifier_element *) lttng_dynamic_array_get_element(
28ab034a 967 &session->destroy_notifiers, i);
3e3665b8
JG
968
969 element->notifier(session, element->user_data);
970 }
971}
972
ccbdaca4
MD
973/*
974 * Fire each clear notifier once, and remove them from the array.
975 */
a0a4f314 976void session_notify_clear(const ltt_session::locked_ref& session)
ccbdaca4
MD
977{
978 size_t i;
a0a4f314 979 const auto count = lttng_dynamic_array_get_count(&session->clear_notifiers);
ccbdaca4
MD
980
981 for (i = 0; i < count; i++) {
982 const struct ltt_session_clear_notifier_element *element =
7966af57 983 (ltt_session_clear_notifier_element *) lttng_dynamic_array_get_element(
a0a4f314 984 &session->clear_notifiers, i);
ccbdaca4 985
a0a4f314 986 element->notifier(session, element->user_data);
ccbdaca4 987 }
a0a4f314 988 lttng_dynamic_array_clear(&session->clear_notifiers);
ccbdaca4
MD
989}
990
28ab034a 991static void session_release(struct urcu_ref *ref)
e32d7f27
JG
992{
993 int ret;
994 struct ltt_ust_session *usess;
995 struct ltt_kernel_session *ksess;
d9a970b7 996 struct ltt_session *session = lttng::utils::container_of(ref, &ltt_session::ref_count);
7fdbed1c 997 const bool session_published = session->published;
e32d7f27 998
a0377dfe 999 LTTNG_ASSERT(!session->chunk_being_archived);
d2956687 1000
e32d7f27
JG
1001 usess = session->ust_session;
1002 ksess = session->kernel_session;
3e3665b8 1003
f8a37411 1004 /* Clean kernel session teardown, keeping data for destroy notifier. */
e32d7f27
JG
1005 kernel_destroy_session(ksess);
1006
d070c424 1007 /* UST session teardown, keeping data for destroy notifier. */
e32d7f27
JG
1008 if (usess) {
1009 /* Close any relayd session */
1010 consumer_output_send_destroy_relayd(usess->consumer);
1011
1012 /* Destroy every UST application related to this session. */
1013 ret = ust_app_destroy_trace_all(usess);
1014 if (ret) {
1015 ERR("Error in ust_app_destroy_trace_all");
1016 }
1017
d070c424 1018 /* Clean up the rest, keeping destroy notifier data. */
e32d7f27
JG
1019 trace_ust_destroy_session(usess);
1020 }
1021
1022 /*
1023 * Must notify the kernel thread here to update it's poll set in order to
1024 * remove the channel(s)' fd just destroyed.
1025 */
412d7227 1026 ret = notify_thread_pipe(the_kernel_poll_pipe[1]);
e32d7f27
JG
1027 if (ret < 0) {
1028 PERROR("write kernel poll pipe");
1029 }
1030
1031 DBG("Destroying session %s (id %" PRIu64 ")", session->name, session->id);
e32d7f27 1032
e32d7f27 1033 snapshot_destroy(&session->snapshot);
99d688f2 1034
7fdbed1c 1035 if (session_published) {
1a496780 1036 ASSERT_SESSION_LIST_LOCKED();
f4cc5e83
JG
1037 del_session_list(session);
1038 del_session_ht(session);
f4cc5e83 1039 }
a0a4f314
JG
1040
1041 /*
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.
1046 */
1047 session->ref_count.refcount = 0xDEAD5E55;
1048 session_notify_destruction([session]() {
1049 session_lock(session);
1050 session_get(session);
16d64977 1051 return ltt_session::make_locked_ref(*session);
a0a4f314
JG
1052 }());
1053
1054 pthread_mutex_destroy(&session->_lock);
d070c424 1055
1ac9cb73 1056 consumer_output_put(session->consumer);
d070c424 1057 kernel_free_session(ksess);
cd9adb8b 1058 session->kernel_session = nullptr;
d070c424
MD
1059 if (usess) {
1060 trace_ust_free_session(usess);
cd9adb8b 1061 session->ust_session = nullptr;
d070c424 1062 }
7fdbed1c 1063 lttng_dynamic_array_reset(&session->destroy_notifiers);
ccbdaca4 1064 lttng_dynamic_array_reset(&session->clear_notifiers);
d2956687 1065 free(session->last_archived_chunk_name);
6fa5fe7c 1066 free(session->base_path);
c08136a3 1067 lttng_trigger_put(session->rotate_trigger);
e32d7f27 1068 free(session);
7fdbed1c
JG
1069 if (session_published) {
1070 /*
1a496780
JG
1071 * Notify after free-ing to ensure the memory is
1072 * reclaimed before the main thread exits (and prevent memory leak
1073 * reports).
7fdbed1c 1074 */
1a496780
JG
1075 ASSERT_SESSION_LIST_LOCKED();
1076 the_session_list.removal_cond.notify_all();
7fdbed1c 1077 }
e32d7f27
JG
1078}
1079
1080/*
1081 * Acquire a reference to a session.
1082 * This function may fail (return false); its return value must be checked.
1083 */
1084bool session_get(struct ltt_session *session)
1085{
d9a970b7 1086 return urcu_ref_get_unless_zero(&session->ref_count);
e32d7f27
JG
1087}
1088
1089/*
1090 * Release a reference to a session.
1091 */
1092void session_put(struct ltt_session *session)
1093{
b178f53e
JG
1094 if (!session) {
1095 return;
1096 }
e32d7f27
JG
1097 /*
1098 * The session list lock must be held as any session_put()
1099 * may cause the removal of the session from the session_list.
1100 */
1a496780 1101 ASSERT_SESSION_LIST_LOCKED();
d9a970b7
JG
1102 LTTNG_ASSERT(session->ref_count.refcount);
1103 urcu_ref_put(&session->ref_count, session_release);
e32d7f27
JG
1104}
1105
1106/*
1107 * Destroy a session.
1108 *
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.
1112 *
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.
1116 */
1117void session_destroy(struct ltt_session *session)
1118{
ed41e570
JR
1119 int ret;
1120 struct lttng_ht_iter iter;
1121
a0377dfe 1122 LTTNG_ASSERT(!session->destroyed);
e32d7f27 1123 session->destroyed = true;
ed41e570
JR
1124
1125 /*
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.
1128 *
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.
1131 */
1132 iter.iter.node = &session->node_by_name.node;
1133 ret = lttng_ht_del(ltt_sessions_ht_by_name, &iter);
1134 LTTNG_ASSERT(!ret);
1135
e32d7f27
JG
1136 session_put(session);
1137}
1138
a0a4f314 1139int session_add_destroy_notifier(const ltt_session::locked_ref& session,
28ab034a
JG
1140 ltt_session_destroy_notifier notifier,
1141 void *user_data)
3e3665b8 1142{
28ab034a
JG
1143 const struct ltt_session_destroy_notifier_element element = { .notifier = notifier,
1144 .user_data = user_data };
3e3665b8 1145
28ab034a 1146 return lttng_dynamic_array_add_element(&session->destroy_notifiers, &element);
3e3665b8
JG
1147}
1148
a0a4f314 1149int session_add_clear_notifier(const ltt_session::locked_ref& session,
28ab034a
JG
1150 ltt_session_clear_notifier notifier,
1151 void *user_data)
ccbdaca4 1152{
28ab034a
JG
1153 const struct ltt_session_clear_notifier_element element = { .notifier = notifier,
1154 .user_data = user_data };
ccbdaca4 1155
28ab034a 1156 return lttng_dynamic_array_add_element(&session->clear_notifiers, &element);
ccbdaca4
MD
1157}
1158
5b74c7b1 1159/*
b178f53e
JG
1160 * Create a new session and add it to the session list.
1161 * Session list lock must be held by the caller.
5b74c7b1 1162 */
28ab034a
JG
1163enum lttng_error_code
1164session_create(const char *name, uid_t uid, gid_t gid, struct ltt_session **out_session)
5b74c7b1 1165{
f3ed775e 1166 int ret;
b178f53e 1167 enum lttng_error_code ret_code;
cd9adb8b 1168 struct ltt_session *new_session = nullptr;
e07ae692 1169
1a496780 1170 ASSERT_SESSION_LIST_LOCKED();
b178f53e
JG
1171 if (name) {
1172 struct ltt_session *clashing_session;
1173
1174 clashing_session = session_find_by_name(name);
1175 if (clashing_session) {
1176 session_put(clashing_session);
1177 ret_code = LTTNG_ERR_EXIST_SESS;
1178 goto error;
1179 }
1180 }
64803277 1181 new_session = zmalloc<ltt_session>();
b178f53e
JG
1182 if (!new_session) {
1183 PERROR("Failed to allocate an ltt_session structure");
1184 ret_code = LTTNG_ERR_NOMEM;
1185 goto error;
5b74c7b1
DG
1186 }
1187
3e3665b8 1188 lttng_dynamic_array_init(&new_session->destroy_notifiers,
28ab034a 1189 sizeof(struct ltt_session_destroy_notifier_element),
cd9adb8b 1190 nullptr);
ccbdaca4 1191 lttng_dynamic_array_init(&new_session->clear_notifiers,
28ab034a 1192 sizeof(struct ltt_session_clear_notifier_element),
cd9adb8b 1193 nullptr);
d9a970b7
JG
1194 urcu_ref_init(&new_session->ref_count);
1195 pthread_mutex_init(&new_session->_lock, nullptr);
e32d7f27 1196
cd9adb8b 1197 new_session->creation_time = time(nullptr);
b178f53e
JG
1198 if (new_session->creation_time == (time_t) -1) {
1199 PERROR("Failed to sample session creation time");
1200 ret_code = LTTNG_ERR_SESSION_FAIL;
f3ed775e
DG
1201 goto error;
1202 }
1203
b178f53e
JG
1204 /* Create default consumer output. */
1205 new_session->consumer = consumer_create_output(CONSUMER_DST_LOCAL);
cd9adb8b 1206 if (new_session->consumer == nullptr) {
b178f53e 1207 ret_code = LTTNG_ERR_NOMEM;
1c1c3634
DG
1208 goto error;
1209 }
1210
b178f53e
JG
1211 if (name) {
1212 ret = lttng_strncpy(new_session->name, name, sizeof(new_session->name));
1213 if (ret) {
1214 ret_code = LTTNG_ERR_SESSION_INVALID_CHAR;
1215 goto error;
1216 }
1217 ret = validate_name(name);
1218 if (ret < 0) {
1219 ret_code = LTTNG_ERR_SESSION_INVALID_CHAR;
1220 goto error;
1221 }
1222 } else {
1223 int i = 0;
1224 bool found_name = false;
1225 char datetime[16];
1226 struct tm *timeinfo;
1227
1228 timeinfo = localtime(&new_session->creation_time);
1229 if (!timeinfo) {
1230 ret_code = LTTNG_ERR_SESSION_FAIL;
1231 goto error;
1232 }
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;
1236
1237 if (i == 0) {
1238 ret = snprintf(new_session->name,
28ab034a
JG
1239 sizeof(new_session->name),
1240 "%s-%s",
1241 DEFAULT_SESSION_NAME,
1242 datetime);
b178f53e
JG
1243 } else {
1244 ret = snprintf(new_session->name,
28ab034a
JG
1245 sizeof(new_session->name),
1246 "%s%d-%s",
1247 DEFAULT_SESSION_NAME,
1248 i,
1249 datetime);
b178f53e 1250 }
46ef2188 1251 new_session->name_contains_creation_time = true;
b178f53e
JG
1252 if (ret == -1 || ret >= sizeof(new_session->name)) {
1253 /*
1254 * Null-terminate in case the name is used
1255 * in logging statements.
1256 */
1257 new_session->name[sizeof(new_session->name) - 1] = '\0';
1258 ret_code = LTTNG_ERR_SESSION_FAIL;
1259 goto error;
1260 }
1261
28ab034a 1262 clashing_session = session_find_by_name(new_session->name);
b178f53e
JG
1263 session_put(clashing_session);
1264 if (!clashing_session) {
1265 found_name = true;
1266 break;
1267 }
1268 }
1269 if (found_name) {
1270 DBG("Generated session name \"%s\"", new_session->name);
1271 new_session->has_auto_generated_name = true;
1272 } else {
1273 ERR("Failed to auto-generate a session name");
1274 ret_code = LTTNG_ERR_SESSION_FAIL;
1275 goto error;
1276 }
1277 }
1278
d3e2ba59 1279 ret = gethostname(new_session->hostname, sizeof(new_session->hostname));
73184835
DG
1280 if (ret < 0) {
1281 if (errno == ENAMETOOLONG) {
1282 new_session->hostname[sizeof(new_session->hostname) - 1] = '\0';
b178f53e 1283 ERR("Hostname exceeds the maximal permitted length and has been truncated to %s",
28ab034a 1284 new_session->hostname);
73184835 1285 } else {
b178f53e 1286 ret_code = LTTNG_ERR_SESSION_FAIL;
73184835
DG
1287 goto error;
1288 }
d3e2ba59
JD
1289 }
1290
6df2e2c9
MD
1291 new_session->uid = uid;
1292 new_session->gid = gid;
1293
6dc3064a
DG
1294 ret = snapshot_init(&new_session->snapshot);
1295 if (ret < 0) {
b178f53e 1296 ret_code = LTTNG_ERR_NOMEM;
6dc3064a
DG
1297 goto error;
1298 }
1299
4f23c583 1300 new_session->rotation_state = LTTNG_ROTATION_STATE_NO_ROTATION;
92816cc3 1301
b178f53e 1302 /* Add new session to the session list. */
a991f516 1303 new_session->id = add_session_list(new_session);
b178f53e 1304
23324029
JD
1305 /*
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
1309 * by session id.
1310 */
1311 add_session_ht(new_session);
f4cc5e83 1312 new_session->published = true;
b5541356 1313
a4b92340 1314 /*
b178f53e
JG
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.
a4b92340 1317 */
b178f53e 1318 DBG("Tracing session %s created with ID %" PRIu64 " by uid = %d, gid = %d",
28ab034a
JG
1319 new_session->name,
1320 new_session->id,
1321 new_session->uid,
1322 new_session->gid);
b178f53e
JG
1323 ret_code = LTTNG_OK;
1324end:
1325 if (new_session) {
1326 (void) session_get(new_session);
1327 *out_session = new_session;
1328 }
1329 return ret_code;
5b74c7b1 1330error:
f4cc5e83 1331 session_put(new_session);
cd9adb8b 1332 new_session = nullptr;
b178f53e 1333 goto end;
5b74c7b1 1334}
2f77fc4b
DG
1335
1336/*
d7b377ed 1337 * Check if the UID matches the session. Root user has access to all
2f77fc4b
DG
1338 * sessions.
1339 */
a0a4f314 1340bool session_access_ok(const ltt_session::locked_ref& session, uid_t uid)
2f77fc4b 1341{
d7b377ed 1342 return (uid == session->uid) || uid == 0;
2f77fc4b 1343}
2961f09e
JG
1344
1345/*
1346 * Set a session's rotation state and reset all associated state.
1347 *
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.
1351 *
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
83ed9e90 1354 * state to be set to "NO_ROTATION". If an error occurred while the
2961f09e
JG
1355 * rotation was "ONGOING", result should be set to "ERROR", which will
1356 * allow a client to report it.
1357 *
1358 * Must be called with the session and session_list locks held.
1359 */
a0a4f314
JG
1360int session_reset_rotation_state(const ltt_session::locked_ref& session,
1361 enum lttng_rotation_state result)
2961f09e
JG
1362{
1363 int ret = 0;
1364
1a496780 1365 ASSERT_SESSION_LIST_LOCKED();
2961f09e 1366
a0a4f314
JG
1367 session->rotation_state = result;
1368 if (session->rotation_pending_check_timer_enabled) {
2961f09e
JG
1369 ret = timer_session_rotation_pending_check_stop(session);
1370 }
a0a4f314 1371 if (session->chunk_being_archived) {
d2956687
JG
1372 uint64_t chunk_id;
1373 enum lttng_trace_chunk_status chunk_status;
1374
a0a4f314 1375 chunk_status = lttng_trace_chunk_get_id(session->chunk_being_archived, &chunk_id);
a0377dfe 1376 LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK);
a0a4f314
JG
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;
ccbdaca4
MD
1380 /*
1381 * Fire the clear reply notifiers if we are completing a clear
1382 * rotation.
1383 */
1384 session_notify_clear(session);
d2956687 1385 }
2961f09e
JG
1386 return ret;
1387}
e1bbf989
JR
1388
1389/*
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.
1394 *
1395 * Return 0 when the session is not found,
1396 * Return 1 when the session is found and set `id`.
1397 */
1398bool sample_session_id_by_name(const char *name, uint64_t *id)
1399{
1400 bool found = false;
1401 struct lttng_ht_node_str *node;
1402 struct lttng_ht_iter iter;
1403 struct ltt_session *ls;
1404
07c4863f 1405 const lttng::urcu::read_lock_guard read_lock;
e1bbf989
JR
1406
1407 if (!ltt_sessions_ht_by_name) {
1408 found = false;
1409 goto end;
1410 }
1411
1412 lttng_ht_lookup(ltt_sessions_ht_by_name, name, &iter);
00d7d903 1413 node = lttng_ht_iter_get_node<lttng_ht_node_str>(&iter);
cd9adb8b 1414 if (node == nullptr) {
e1bbf989
JR
1415 found = false;
1416 goto end;
1417 }
1418
0114db0e 1419 ls = lttng::utils::container_of(node, &ltt_session::node_by_name);
e1bbf989
JR
1420 *id = ls->id;
1421 found = true;
1422
1423 DBG3("Session id `%" PRIu64 "` sampled for session `%s", *id, name);
1424end:
e1bbf989
JR
1425 return found;
1426}
e99e3664 1427
d9a970b7 1428void ltt_session::_locked_session_release(ltt_session *session)
e99e3664 1429{
0038180d
JG
1430 if (!session) {
1431 return;
1432 }
1433
e99e3664
JG
1434 session_unlock(session);
1435 session_put(session);
1436}
1437
d9a970b7
JG
1438void ltt_session::_locked_const_session_release(const ltt_session *session)
1439{
1440 if (!session) {
1441 return;
1442 }
1443
1444 ltt_session::_const_session_unlock(*session);
1445 ltt_session::_const_session_put(session);
1446}
1447
1448ltt_session::locked_ref ltt_session::find_locked_session(ltt_session::id_t id)
e99e3664 1449{
07c4863f 1450 const lttng::urcu::read_lock_guard rcu_lock;
e99e3664
JG
1451 auto session = session_find_by_id(id);
1452
1453 if (!session) {
d9a970b7 1454 LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id);
e99e3664
JG
1455 }
1456
1457 /*
1458 * The pointer falling out of scope will unlock and release the reference to the
1459 * session.
1460 */
1461 session_lock(session);
16d64977 1462 return ltt_session::make_locked_ref(*session);
e99e3664
JG
1463}
1464
d9a970b7
JG
1465ltt_session::locked_ref ltt_session::find_locked_session(lttng::c_string_view name)
1466{
07c4863f 1467 const lttng::urcu::read_lock_guard rcu_lock;
d9a970b7
JG
1468 auto session = session_find_by_name(name.data());
1469
1470 if (!session) {
1471 LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name.data());
1472 }
1473
1474 session_lock(session);
16d64977 1475 return ltt_session::make_locked_ref(*session);
d9a970b7
JG
1476}
1477
1478ltt_session::const_locked_ref ltt_session::find_locked_const_session(ltt_session::id_t id)
1479{
07c4863f 1480 const lttng::urcu::read_lock_guard rcu_lock;
16d64977 1481 const auto *session = session_find_by_id(id);
d9a970b7
JG
1482
1483 if (!session) {
1484 LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id);
1485 }
1486
1487 session_lock(session);
16d64977 1488 return ltt_session::make_locked_ref(*session);
d9a970b7
JG
1489}
1490
1491ltt_session::const_locked_ref ltt_session::find_locked_const_session(lttng::c_string_view name)
1492{
07c4863f 1493 const lttng::urcu::read_lock_guard rcu_lock;
16d64977 1494 const auto *session = session_find_by_name(name.data());
d9a970b7
JG
1495
1496 if (!session) {
1497 LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name.data());
1498 }
1499
1500 session_lock(session);
16d64977 1501 return ltt_session::make_locked_ref(*session);
d9a970b7
JG
1502}
1503
1504ltt_session::ref ltt_session::find_session(ltt_session::id_t id)
1505{
07c4863f 1506 const lttng::urcu::read_lock_guard rcu_lock;
d9a970b7
JG
1507 auto session = session_find_by_id(id);
1508
1509 if (!session) {
1510 LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id);
1511 }
1512
16d64977 1513 return ltt_session::make_ref(*session);
d9a970b7
JG
1514}
1515
1516ltt_session::ref ltt_session::find_session(lttng::c_string_view name)
1517{
07c4863f 1518 const lttng::urcu::read_lock_guard rcu_lock;
d9a970b7
JG
1519 auto session = session_find_by_name(name.data());
1520
1521 if (!session) {
1522 LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name.data());
1523 }
1524
16d64977 1525 return ltt_session::make_ref(*session);
d9a970b7
JG
1526}
1527
1528ltt_session::const_ref ltt_session::find_const_session(ltt_session::id_t id)
e99e3664 1529{
07c4863f 1530 const lttng::urcu::read_lock_guard rcu_lock;
16d64977 1531 const auto *session = session_find_by_id(id);
e99e3664
JG
1532
1533 if (!session) {
d9a970b7
JG
1534 LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id);
1535 }
1536
16d64977 1537 return ltt_session::make_ref(*session);
d9a970b7
JG
1538}
1539
1540ltt_session::const_ref ltt_session::find_const_session(lttng::c_string_view name)
1541{
07c4863f 1542 const lttng::urcu::read_lock_guard rcu_lock;
16d64977 1543 const auto *session = session_find_by_name(name.data());
d9a970b7
JG
1544
1545 if (!session) {
1546 LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name.data());
e99e3664
JG
1547 }
1548
16d64977 1549 return ltt_session::make_ref(*session);
d9a970b7
JG
1550}
1551
1552void ltt_session::_const_session_put(const ltt_session *session)
1553{
1554 /*
1555 * The session list lock must be held as any session_put()
1556 * may cause the removal of the session from the session_list.
1557 */
1558 ASSERT_SESSION_LIST_LOCKED();
1559 LTTNG_ASSERT(session->ref_count.refcount);
1560 urcu_ref_put(&session->ref_count, session_release);
1561}
1562
1563std::unique_lock<std::mutex> ls::lock_session_list()
1564{
1565 return std::unique_lock<std::mutex>(the_session_list.lock);
e99e3664 1566}
16d64977
JG
1567
1568lttng::sessiond::user_space_consumer_channel_keys
1569ltt_session::user_space_consumer_channel_keys() const
1570{
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);
1578 default:
1579 abort();
1580 }
1581}
1582
1583ls::user_space_consumer_channel_keys::iterator
1584ls::user_space_consumer_channel_keys::begin() const noexcept
1585{
1586 return ls::user_space_consumer_channel_keys::iterator(_creation_context);
1587}
1588
1589ls::user_space_consumer_channel_keys::iterator
1590ls::user_space_consumer_channel_keys::end() const noexcept
1591{
1592 return ls::user_space_consumer_channel_keys::iterator(_creation_context, true);
1593}
1594
1595ls::user_space_consumer_channel_keys::iterator&
1596ls::user_space_consumer_channel_keys::iterator::operator++()
1597{
1598 if (_is_end) {
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));
1602 }
1603
1604 switch (_creation_context._session.buffer_type) {
1605 case LTTNG_BUFFER_PER_PID:
1606 _advance_one_per_pid();
1607 break;
1608 case LTTNG_BUFFER_PER_UID:
1609 _advance_one_per_uid();
1610 break;
1611 default:
1612 abort();
1613 }
1614
1615 return *this;
1616}
1617
1618namespace {
1619bool is_list_empty(const cds_list_head *head)
1620{
1621 return head == head->next;
1622}
1623
1624bool is_last_element_of_list(const cds_list_head *head)
1625{
1626 return head->next == head->prev;
1627}
1628} /* namespace */
1629
1630ls::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)
1633{
1634 if (_is_end) {
1635 return;
1636 }
1637
1638 switch (_creation_context._mode) {
1639 case _iteration_mode::PER_PID:
1640 _init_per_pid();
1641 break;
1642 case _iteration_mode::PER_UID:
1643 _init_per_uid();
1644 break;
1645 }
1646}
1647
1648void ls::user_space_consumer_channel_keys::iterator::_skip_to_next_app_per_pid(
1649 bool try_current) noexcept
1650{
1651 auto& position = _position._per_pid;
1652
1653 while (true) {
1654 if (!try_current) {
1655 lttng_ht_get_next(_creation_context._container.apps,
1656 &position.app_iterator);
1657 } else {
1658 try_current = false;
1659 }
1660
1661 const auto app_node =
1662 lttng_ht_iter_get_node<lttng_ht_node_ulong>(&position.app_iterator);
1663 if (!app_node) {
1664 _is_end = true;
1665 return;
1666 }
1667
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);
1670
1671 if (!app_session) {
1672 /* This app is not traced by the target session. */
1673 continue;
1674 }
1675
1676 position.current_app_session = app_session->lock();
1677
1678 auto *registry = ust_app_get_session_registry(
1679 (*_position._per_pid.current_app_session)->get_identifier());
1680 if (!registry) {
1681 DBG_FMT("Application session is being torn down: skipping application: app={}",
1682 app);
1683 continue;
1684 }
1685
1686 position.current_registry_session = registry;
1687 lttng_ht_get_first((*position.current_app_session)->channels,
1688 &_position.channel_iterator);
1689 break;
1690 }
1691}
1692
1693void ls::user_space_consumer_channel_keys::iterator::_init_per_pid() noexcept
1694{
1695 auto& position = _position._per_pid;
1696
1697 lttng_ht_get_first(_creation_context._container.apps, &position.app_iterator);
1698 _skip_to_next_app_per_pid(true);
1699}
1700
1701void ls::user_space_consumer_channel_keys::iterator::_init_per_uid() noexcept
1702{
1703 auto& position = _position._per_uid;
1704
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)) {
1707 _is_end = true;
1708 return;
1709 }
1710
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);
1715}
1716
1717void ls::user_space_consumer_channel_keys::iterator::_advance_one_per_pid()
1718{
1719 auto& position = _position._per_pid;
1720
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);
1724 return;
1725 }
1726
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);
1730
1731 lttng_ht_get_next((*position.current_app_session)->channels, &_position.channel_iterator);
1732}
1733
1734void ls::user_space_consumer_channel_keys::iterator::_advance_one_per_uid()
1735{
1736 auto& position = _position._per_uid;
1737
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)) {
1741 _is_end = true;
1742 return;
1743 }
1744
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);
1749
1750 /* Assumes a registry can't be empty. */
1751 LTTNG_ASSERT(cds_lfht_iter_get_node(&_position.channel_iterator.iter));
1752 }
1753
1754 cds_lfht_next(position.current_registry->registry->channels->ht,
1755 &_position.channel_iterator.iter);
1756}
1757
1758bool ls::user_space_consumer_channel_keys::iterator::operator==(const iterator& other) const noexcept
1759{
1760 if (_is_end && other._is_end) {
1761 return true;
1762 }
1763
1764 /* Channel keys are unique; use them to compare the iterators. */
1765 return !_is_end && !other._is_end && **this == *other;
1766}
1767
1768bool ls::user_space_consumer_channel_keys::iterator::operator!=(const iterator& other) const noexcept
1769{
1770 return !(*this == other);
1771}
1772
1773ls::user_space_consumer_channel_keys::iterator::key
1774ls::user_space_consumer_channel_keys::iterator::_get_current_value_per_pid() const noexcept
1775{
1776 auto& position = _position._per_pid;
1777
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);
1783
1784 const auto& app = *lttng::utils::container_of(current_app_node, &ust_app::pid_n);
1785
1786 if (channel_node) {
1787 const auto& channel =
1788 *lttng::utils::container_of(channel_node, &ust_app_channel::node);
1789
1790 return { static_cast<consumer_bitness>(app.abi.bits_per_long),
1791 channel.key,
1792 ls::user_space_consumer_channel_keys::channel_type::DATA };
1793 } else {
1794 LTTNG_ASSERT(position.current_registry_session);
1795
1796 /*
1797 * Once the last data channel is delivered (iter points to the 'end' of the ht),
1798 * deliver the metadata channel's key.
1799 */
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 };
1803 }
1804}
1805
1806ls::user_space_consumer_channel_keys::iterator::key
1807ls::user_space_consumer_channel_keys::iterator::_get_current_value_per_uid() const noexcept
1808{
1809 const auto *channel_node =
1810 lttng_ht_iter_get_node<lttng_ht_node_u64>(&_position.channel_iterator);
1811
1812 if (channel_node) {
1813 const auto& channel =
1814 *lttng::utils::container_of(channel_node, &buffer_reg_channel::node);
1815
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 };
1820 } else {
1821 /*
1822 * Once the last data channel is delivered (iter points to the 'end' of the ht),
1823 * deliver the metadata channel's key.
1824 */
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 };
1829 }
1830}
1831
1832ls::user_space_consumer_channel_keys::iterator::key
1833ls::user_space_consumer_channel_keys::iterator::operator*() const
1834{
1835 if (_is_end) {
1836 LTTNG_THROW_OUT_OF_RANGE(
1837 "Attempt to use operator* on user_space_consumer_channel_keys iterator at the end position");
1838 }
1839
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();
1845 }
1846
1847 std::abort();
1848}
1849
1850ls::ust::registry_session *ls::user_space_consumer_channel_keys::iterator::get_registry_session()
1851{
1852 if (_is_end) {
1853 LTTNG_THROW_OUT_OF_RANGE(
1854 "Attempt to get registry session on user_space_consumer_channel_keys iterator at the end position");
1855 }
1856
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();
1862 }
1863
1864 std::abort();
1865}
1866
1867ls::ust::registry_session *
1868ls::user_space_consumer_channel_keys::iterator::_get_registry_session_per_pid()
1869{
1870 return _position._per_pid.current_registry_session;
1871}
1872
1873ls::ust::registry_session *
1874ls::user_space_consumer_channel_keys::iterator::_get_registry_session_per_uid()
1875{
1876 return _position._per_uid.current_registry->registry->reg.ust;
1877}
This page took 0.203992 seconds and 4 git commands to generate.