Fix: Close socket handle on error
[lttng-tools.git] / src / bin / lttng-sessiond / snapshot.c
CommitLineData
6dc3064a
DG
1/*
2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
6c1c0768 18#define _LGPL_SOURCE
6dc3064a
DG
19#include <assert.h>
20#include <inttypes.h>
21#include <string.h>
22#include <urcu/uatomic.h>
23
24#include <common/defaults.h>
25
26#include "snapshot.h"
53efb85a 27#include "utils.h"
6dc3064a
DG
28
29/*
30 * Return the atomically incremented value of next_output_id.
31 */
32static inline unsigned long get_next_output_id(struct snapshot *snapshot)
33{
34 return uatomic_add_return(&snapshot->next_output_id, 1);
35}
36
37/*
5288612f 38 * Initialized snapshot output with the given values.
6dc3064a
DG
39 *
40 * Return 0 on success or else a negative value.
41 */
5feee503
JG
42static int output_init(const struct ltt_session *session,
43 uint64_t max_size, const char *name,
5288612f 44 struct lttng_uri *uris, size_t nb_uri,
6dc3064a
DG
45 struct consumer_output *consumer, struct snapshot_output *output,
46 struct snapshot *snapshot)
47{
5288612f 48 int ret = 0, i;
6dc3064a 49
d4b5a90c
DG
50 memset(output, 0, sizeof(struct snapshot_output));
51
d07ceecd
MD
52 /*
53 * max_size of -1ULL means unset. Set to default (unlimited).
54 */
e1986656
DG
55 if (max_size == (uint64_t) -1ULL) {
56 max_size = 0;
57 }
6dc3064a 58 output->max_size = max_size;
e1986656 59
6dc3064a
DG
60 if (snapshot) {
61 output->id = get_next_output_id(snapshot);
62 }
63 lttng_ht_node_init_ulong(&output->node, (unsigned long) output->id);
64
ee91bab2 65 if (name && name[0] != '\0') {
35f3ec96
MD
66 if (lttng_strncpy(output->name, name, sizeof(output->name))) {
67 ret = -LTTNG_ERR_INVALID;
68 goto error;
69 }
6dc3064a
DG
70 } else {
71 /* Set default name. */
72 ret = snprintf(output->name, sizeof(output->name), "%s-%" PRIu32,
73 DEFAULT_SNAPSHOT_NAME, output->id);
74 if (ret < 0) {
75 ret = -ENOMEM;
76 goto error;
77 }
78 }
79
80 if (!consumer) {
81 goto end;
82 }
83
6dc3064a
DG
84 output->consumer = consumer_copy_output(consumer);
85 if (!output->consumer) {
86 ret = -ENOMEM;
87 goto error;
88 }
7d2f7452 89 output->consumer->snapshot = 1;
6dc3064a
DG
90
91 /* No URL given. */
92 if (nb_uri == 0) {
93 ret = 0;
94 goto end;
95 }
96
97 if (uris[0].dtype == LTTNG_DST_PATH) {
366a9222
JD
98 memset(output->consumer->dst.session_root_path, 0,
99 sizeof(output->consumer->dst.session_root_path));
100 if (lttng_strncpy(output->consumer->dst.session_root_path,
35f3ec96 101 uris[0].dst.path,
366a9222 102 sizeof(output->consumer->dst.session_root_path))) {
35f3ec96
MD
103 ret = -LTTNG_ERR_INVALID;
104 goto error;
105 }
6dc3064a
DG
106 output->consumer->type = CONSUMER_DST_LOCAL;
107 ret = 0;
108 goto end;
109 }
110
111 if (nb_uri != 2) {
112 /* Absolutely needs two URIs for network. */
113 ret = -LTTNG_ERR_INVALID;
114 goto error;
115 }
116
117 for (i = 0; i < nb_uri; i ++) {
118 /* Network URIs */
5feee503
JG
119 ret = consumer_set_network_uri(session, output->consumer,
120 &uris[i]);
6dc3064a
DG
121 if (ret < 0) {
122 goto error;
123 }
124 }
125
126error:
127end:
5288612f
DG
128 return ret;
129}
130
131/*
132 * Initialize a snapshot output object using the given parameters and URI(s).
133 * The name value and uris can be NULL.
134 *
135 * Return 0 on success or else a negative value.
136 */
5feee503
JG
137int snapshot_output_init_with_uri(const struct ltt_session *session,
138 uint64_t max_size, const char *name,
5288612f
DG
139 struct lttng_uri *uris, size_t nb_uri,
140 struct consumer_output *consumer, struct snapshot_output *output,
141 struct snapshot *snapshot)
142{
5feee503
JG
143 return output_init(session, max_size, name, uris, nb_uri, consumer,
144 output, snapshot);
5288612f
DG
145}
146
147/*
148 * Initialize a snapshot output object using the given parameters. The name
149 * value and url can be NULL.
150 *
151 * Return 0 on success or else a negative value.
152 */
5feee503
JG
153int snapshot_output_init(const struct ltt_session *session,
154 uint64_t max_size, const char *name,
5288612f
DG
155 const char *ctrl_url, const char *data_url,
156 struct consumer_output *consumer, struct snapshot_output *output,
157 struct snapshot *snapshot)
158{
159 int ret = 0, nb_uri;
160 struct lttng_uri *uris = NULL;
161
162 /* Create an array of URIs from URLs. */
163 nb_uri = uri_parse_str_urls(ctrl_url, data_url, &uris);
164 if (nb_uri < 0) {
165 ret = nb_uri;
166 goto error;
167 }
168
5feee503
JG
169 ret = output_init(session, max_size, name, uris, nb_uri, consumer,
170 output, snapshot);
5288612f
DG
171
172error:
6dc3064a
DG
173 free(uris);
174 return ret;
175}
176
177struct snapshot_output *snapshot_output_alloc(void)
178{
179 return zmalloc(sizeof(struct snapshot_output));
180}
181
182/*
183 * Delete output from the snapshot object.
184 */
185void snapshot_delete_output(struct snapshot *snapshot,
186 struct snapshot_output *output)
187{
188 int ret;
189 struct lttng_ht_iter iter;
190
191 assert(snapshot);
192 assert(snapshot->output_ht);
193 assert(output);
194
195 iter.iter.node = &output->node.node;
196 rcu_read_lock();
197 ret = lttng_ht_del(snapshot->output_ht, &iter);
198 rcu_read_unlock();
199 assert(!ret);
200 /*
201 * This is safe because the ownership of a snapshot object is in a session
202 * for which the session lock need to be acquired to read and modify it.
203 */
204 snapshot->nb_output--;
205}
206
207/*
208 * Add output object to the snapshot.
209 */
210void snapshot_add_output(struct snapshot *snapshot,
211 struct snapshot_output *output)
212{
213 assert(snapshot);
214 assert(snapshot->output_ht);
215 assert(output);
216
217 rcu_read_lock();
218 lttng_ht_add_unique_ulong(snapshot->output_ht, &output->node);
219 rcu_read_unlock();
220 /*
221 * This is safe because the ownership of a snapshot object is in a session
222 * for which the session lock need to be acquired to read and modify it.
223 */
224 snapshot->nb_output++;
225}
226
227/*
228 * Destroy and free a snapshot output object.
229 */
230void snapshot_output_destroy(struct snapshot_output *obj)
231{
232 assert(obj);
233
234 if (obj->consumer) {
235 consumer_output_send_destroy_relayd(obj->consumer);
6addfa37 236 consumer_output_put(obj->consumer);
6dc3064a
DG
237 }
238 free(obj);
239}
240
eb240553
DG
241/*
242 * RCU read side lock MUST be acquired before calling this since the returned
243 * pointer is in a RCU hash table.
244 *
245 * Return the reference on success or else NULL.
246 */
247struct snapshot_output *snapshot_find_output_by_name(const char *name,
248 struct snapshot *snapshot)
249{
250 struct lttng_ht_iter iter;
251 struct snapshot_output *output = NULL;
252
253 assert(snapshot);
254 assert(name);
255
256 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
257 node.node) {
258 if (!strncmp(output->name, name, strlen(name))) {
259 return output;
260 }
261 }
262
263 /* Not found */
264 return NULL;
265}
266
6dc3064a
DG
267/*
268 * RCU read side lock MUST be acquired before calling this since the returned
269 * pointer is in a RCU hash table.
270 *
271 * Return the reference on success or else NULL.
272 */
273struct snapshot_output *snapshot_find_output_by_id(uint32_t id,
274 struct snapshot *snapshot)
275{
276 struct lttng_ht_node_ulong *node;
277 struct lttng_ht_iter iter;
278 struct snapshot_output *output = NULL;
279
280 assert(snapshot);
281
282 lttng_ht_lookup(snapshot->output_ht, (void *)((unsigned long) id), &iter);
283 node = lttng_ht_iter_get_node_ulong(&iter);
284 if (!node) {
285 DBG3("Snapshot output not found with id %" PRId32, id);
286 goto error;
287 }
288 output = caa_container_of(node, struct snapshot_output, node);
289
290error:
291 return output;
292}
293
6dc3064a
DG
294/*
295 * Initialized a snapshot object that was already allocated.
296 *
297 * Return 0 on success or else a negative errno value.
298 */
299int snapshot_init(struct snapshot *obj)
300{
301 int ret;
302
303 assert(obj);
304
305 memset(obj, 0, sizeof(struct snapshot));
306
307 obj->output_ht = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
308 if (!obj->output_ht) {
309 ret = -ENOMEM;
310 goto error;
311 }
312
313 ret = 0;
314
315error:
316 return ret;
317}
318
319/*
320 * Destroy snapshot object but the pointer is not freed so it's safe to pass a
321 * static reference.
322 */
323void snapshot_destroy(struct snapshot *obj)
324{
325 struct lttng_ht_iter iter;
326 struct snapshot_output *output;
327
56ca63c0
JG
328 if (!obj->output_ht) {
329 return;
330 }
6dc3064a
DG
331
332 rcu_read_lock();
333 cds_lfht_for_each_entry(obj->output_ht->ht, &iter.iter, output,
334 node.node) {
335 snapshot_delete_output(obj, output);
336 snapshot_output_destroy(output);
337 }
338 rcu_read_unlock();
53efb85a 339 ht_cleanup_push(obj->output_ht);
6dc3064a 340}
This page took 0.057301 seconds and 4 git commands to generate.