Accept uid and gid parameters in utils_mkdir()/utils_mkdir_recursive()
[lttng-tools.git] / src / bin / lttng-relayd / session.c
CommitLineData
2f8f53af
DG
1/*
2 * Copyright (C) 2013 - Julien Desfossez <jdesfossez@efficios.com>
3 * David Goulet <dgoulet@efficios.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License, version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 51
16 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
2a174661 19#define _GNU_SOURCE
6c1c0768 20#define _LGPL_SOURCE
2a174661
DG
21#include <common/common.h>
22
23#include "ctf-trace.h"
2f8f53af 24#include "session.h"
2a174661
DG
25#include "stream.h"
26
27/* Global session id used in the session creation. */
28static uint64_t last_relay_session_id;
29
30static void rcu_destroy_session(struct rcu_head *head)
31{
32 struct relay_session *session =
33 caa_container_of(head, struct relay_session, rcu_node);
34
35 free(session);
36}
37
38/*
39 * Create a new session by assigning a new session ID.
40 *
41 * Return allocated session or else NULL.
42 */
43struct relay_session *session_create(void)
44{
45 struct relay_session *session;
46
47 session = zmalloc(sizeof(*session));
48 if (!session) {
49 PERROR("relay session zmalloc");
50 goto error;
51 }
52
53 session->ctf_traces_ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
54 if (!session->ctf_traces_ht) {
55 free(session);
78394403 56 session = NULL;
2a174661
DG
57 goto error;
58 }
59
60 pthread_mutex_init(&session->viewer_ready_lock, NULL);
61 session->id = ++last_relay_session_id;
62 lttng_ht_node_init_u64(&session->session_n, session->id);
63
64error:
65 return session;
66}
2f8f53af
DG
67
68/*
69 * Lookup a session within the given hash table and session id. RCU read side
70 * lock MUST be acquired before calling this and as long as the caller has a
71 * reference to the object.
72 *
73 * Return session or NULL if not found.
74 */
75struct relay_session *session_find_by_id(struct lttng_ht *ht, uint64_t id)
76{
77 struct relay_session *session = NULL;
2a174661 78 struct lttng_ht_node_u64 *node;
2f8f53af
DG
79 struct lttng_ht_iter iter;
80
81 assert(ht);
82
2a174661
DG
83 lttng_ht_lookup(ht, &id, &iter);
84 node = lttng_ht_iter_get_node_u64(&iter);
2f8f53af 85 if (!node) {
2a174661 86 DBG("Session find by ID %" PRIu64 " id NOT found", id);
2f8f53af
DG
87 goto end;
88 }
89 session = caa_container_of(node, struct relay_session, session_n);
2a174661 90 DBG("Session find by ID %" PRIu64 " id found", id);
2f8f53af
DG
91
92end:
93 return session;
94}
2a174661
DG
95
96/*
97 * Delete session from the given hash table.
98 *
99 * Return lttng ht del error code being 0 on success and 1 on failure.
100 */
101int session_delete(struct lttng_ht *ht, struct relay_session *session)
102{
103 struct lttng_ht_iter iter;
104
105 assert(ht);
106 assert(session);
107
108 iter.iter.node = &session->session_n.node;
109 return lttng_ht_del(ht, &iter);
110}
111
112/*
113 * The caller MUST be from the viewer thread since the viewer refcount is
114 * decremented. With this calue down to 0, it will try to destroy the session.
115 */
116void session_viewer_try_destroy(struct lttng_ht *ht,
117 struct relay_session *session)
118{
119 unsigned long ret_ref;
120
121 assert(session);
122
123 ret_ref = uatomic_add_return(&session->viewer_refcount, -1);
124 if (ret_ref == 0) {
125 session_try_destroy(ht, session);
126 }
127}
128
129/*
130 * Should only be called from the main streaming thread since it does not touch
131 * the viewer refcount. If this refcount is down to 0, destroy the session only
132 * and only if the session deletion succeeds. This is done because the viewer
133 * *and* the streaming thread can both concurently try to destroy the session
134 * thus the first come first serve.
135 */
136void session_try_destroy(struct lttng_ht *ht, struct relay_session *session)
137{
138 int ret = 0;
139 unsigned long ret_ref;
140
141 assert(session);
142
143 ret_ref = uatomic_read(&session->viewer_refcount);
144 if (ret_ref == 0 && session->close_flag) {
145 if (ht) {
146 ret = session_delete(ht, session);
147 }
148 if (!ret) {
149 /* Only destroy the session if the deletion was successful. */
150 session_destroy(session);
151 }
152 }
153}
154
155/*
156 * Destroy a session object.
f10db9cc
JG
157 *
158 * This function must *NOT* be called with an RCU read lock held since
159 * the session's ctf_traces_ht is destroyed.
2a174661
DG
160 */
161void session_destroy(struct relay_session *session)
162{
163 struct ctf_trace *ctf_trace;
164 struct lttng_ht_iter iter;
165
166 assert(session);
167
168 DBG("Relay destroying session %" PRIu64, session->id);
169
170 /*
171 * Empty the ctf trace hash table which will destroy the stream contained
172 * in that table.
173 */
174 rcu_read_lock();
175 cds_lfht_for_each_entry(session->ctf_traces_ht->ht, &iter.iter, ctf_trace,
176 node.node) {
177 ctf_trace_delete(session->ctf_traces_ht, ctf_trace);
178 ctf_trace_destroy(ctf_trace);
179 }
2a174661 180 rcu_read_unlock();
f10db9cc 181 lttng_ht_destroy(session->ctf_traces_ht);
2a174661
DG
182
183 call_rcu(&session->rcu_node, rcu_destroy_session);
184}
This page took 0.049507 seconds and 4 git commands to generate.