Fix: sessiond: snapshot: handle consumer return codes
[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 */
5288612f
DG
42static int output_init(uint64_t max_size, const char *name,
43 struct lttng_uri *uris, size_t nb_uri,
6dc3064a
DG
44 struct consumer_output *consumer, struct snapshot_output *output,
45 struct snapshot *snapshot)
46{
5288612f 47 int ret = 0, i;
6dc3064a 48
d4b5a90c
DG
49 memset(output, 0, sizeof(struct snapshot_output));
50
d07ceecd
MD
51 /*
52 * max_size of -1ULL means unset. Set to default (unlimited).
53 */
e1986656
DG
54 if (max_size == (uint64_t) -1ULL) {
55 max_size = 0;
56 }
6dc3064a 57 output->max_size = max_size;
e1986656 58
6dc3064a
DG
59 if (snapshot) {
60 output->id = get_next_output_id(snapshot);
61 }
62 lttng_ht_node_init_ulong(&output->node, (unsigned long) output->id);
63
ee91bab2 64 if (name && name[0] != '\0') {
35f3ec96
MD
65 if (lttng_strncpy(output->name, name, sizeof(output->name))) {
66 ret = -LTTNG_ERR_INVALID;
67 goto error;
68 }
6dc3064a
DG
69 } else {
70 /* Set default name. */
71 ret = snprintf(output->name, sizeof(output->name), "%s-%" PRIu32,
72 DEFAULT_SNAPSHOT_NAME, output->id);
73 if (ret < 0) {
74 ret = -ENOMEM;
75 goto error;
76 }
77 }
78
79 if (!consumer) {
80 goto end;
81 }
82
6dc3064a
DG
83 output->consumer = consumer_copy_output(consumer);
84 if (!output->consumer) {
85 ret = -ENOMEM;
86 goto error;
87 }
7d2f7452 88 output->consumer->snapshot = 1;
6dc3064a
DG
89
90 /* No URL given. */
91 if (nb_uri == 0) {
92 ret = 0;
93 goto end;
94 }
95
96 if (uris[0].dtype == LTTNG_DST_PATH) {
366a9222
JD
97 memset(output->consumer->dst.session_root_path, 0,
98 sizeof(output->consumer->dst.session_root_path));
99 if (lttng_strncpy(output->consumer->dst.session_root_path,
35f3ec96 100 uris[0].dst.path,
366a9222 101 sizeof(output->consumer->dst.session_root_path))) {
35f3ec96
MD
102 ret = -LTTNG_ERR_INVALID;
103 goto error;
104 }
6dc3064a
DG
105 output->consumer->type = CONSUMER_DST_LOCAL;
106 ret = 0;
107 goto end;
108 }
109
110 if (nb_uri != 2) {
111 /* Absolutely needs two URIs for network. */
112 ret = -LTTNG_ERR_INVALID;
113 goto error;
114 }
115
116 for (i = 0; i < nb_uri; i ++) {
117 /* Network URIs */
118 ret = consumer_set_network_uri(output->consumer, &uris[i]);
119 if (ret < 0) {
120 goto error;
121 }
122 }
123
124error:
125end:
5288612f
DG
126 return ret;
127}
128
129/*
130 * Initialize a snapshot output object using the given parameters and URI(s).
131 * The name value and uris can be NULL.
132 *
133 * Return 0 on success or else a negative value.
134 */
135int snapshot_output_init_with_uri(uint64_t max_size, const char *name,
136 struct lttng_uri *uris, size_t nb_uri,
137 struct consumer_output *consumer, struct snapshot_output *output,
138 struct snapshot *snapshot)
139{
140 return output_init(max_size, name, uris, nb_uri, consumer, output,
141 snapshot);
142}
143
144/*
145 * Initialize a snapshot output object using the given parameters. The name
146 * value and url can be NULL.
147 *
148 * Return 0 on success or else a negative value.
149 */
150int snapshot_output_init(uint64_t max_size, const char *name,
151 const char *ctrl_url, const char *data_url,
152 struct consumer_output *consumer, struct snapshot_output *output,
153 struct snapshot *snapshot)
154{
155 int ret = 0, nb_uri;
156 struct lttng_uri *uris = NULL;
157
158 /* Create an array of URIs from URLs. */
159 nb_uri = uri_parse_str_urls(ctrl_url, data_url, &uris);
160 if (nb_uri < 0) {
161 ret = nb_uri;
162 goto error;
163 }
164
165 ret = output_init(max_size, name, uris, nb_uri, consumer, output,
166 snapshot);
167
168error:
6dc3064a
DG
169 free(uris);
170 return ret;
171}
172
173struct snapshot_output *snapshot_output_alloc(void)
174{
175 return zmalloc(sizeof(struct snapshot_output));
176}
177
178/*
179 * Delete output from the snapshot object.
180 */
181void snapshot_delete_output(struct snapshot *snapshot,
182 struct snapshot_output *output)
183{
184 int ret;
185 struct lttng_ht_iter iter;
186
187 assert(snapshot);
188 assert(snapshot->output_ht);
189 assert(output);
190
191 iter.iter.node = &output->node.node;
192 rcu_read_lock();
193 ret = lttng_ht_del(snapshot->output_ht, &iter);
194 rcu_read_unlock();
195 assert(!ret);
196 /*
197 * This is safe because the ownership of a snapshot object is in a session
198 * for which the session lock need to be acquired to read and modify it.
199 */
200 snapshot->nb_output--;
201}
202
203/*
204 * Add output object to the snapshot.
205 */
206void snapshot_add_output(struct snapshot *snapshot,
207 struct snapshot_output *output)
208{
209 assert(snapshot);
210 assert(snapshot->output_ht);
211 assert(output);
212
213 rcu_read_lock();
214 lttng_ht_add_unique_ulong(snapshot->output_ht, &output->node);
215 rcu_read_unlock();
216 /*
217 * This is safe because the ownership of a snapshot object is in a session
218 * for which the session lock need to be acquired to read and modify it.
219 */
220 snapshot->nb_output++;
221}
222
223/*
224 * Destroy and free a snapshot output object.
225 */
226void snapshot_output_destroy(struct snapshot_output *obj)
227{
228 assert(obj);
229
230 if (obj->consumer) {
231 consumer_output_send_destroy_relayd(obj->consumer);
6addfa37 232 consumer_output_put(obj->consumer);
6dc3064a
DG
233 }
234 free(obj);
235}
236
eb240553
DG
237/*
238 * RCU read side lock MUST be acquired before calling this since the returned
239 * pointer is in a RCU hash table.
240 *
241 * Return the reference on success or else NULL.
242 */
243struct snapshot_output *snapshot_find_output_by_name(const char *name,
244 struct snapshot *snapshot)
245{
246 struct lttng_ht_iter iter;
247 struct snapshot_output *output = NULL;
248
249 assert(snapshot);
250 assert(name);
251
252 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
253 node.node) {
254 if (!strncmp(output->name, name, strlen(name))) {
255 return output;
256 }
257 }
258
259 /* Not found */
260 return NULL;
261}
262
6dc3064a
DG
263/*
264 * RCU read side lock MUST be acquired before calling this since the returned
265 * pointer is in a RCU hash table.
266 *
267 * Return the reference on success or else NULL.
268 */
269struct snapshot_output *snapshot_find_output_by_id(uint32_t id,
270 struct snapshot *snapshot)
271{
272 struct lttng_ht_node_ulong *node;
273 struct lttng_ht_iter iter;
274 struct snapshot_output *output = NULL;
275
276 assert(snapshot);
277
278 lttng_ht_lookup(snapshot->output_ht, (void *)((unsigned long) id), &iter);
279 node = lttng_ht_iter_get_node_ulong(&iter);
280 if (!node) {
281 DBG3("Snapshot output not found with id %" PRId32, id);
282 goto error;
283 }
284 output = caa_container_of(node, struct snapshot_output, node);
285
286error:
287 return output;
288}
289
6dc3064a
DG
290/*
291 * Initialized a snapshot object that was already allocated.
292 *
293 * Return 0 on success or else a negative errno value.
294 */
295int snapshot_init(struct snapshot *obj)
296{
297 int ret;
298
299 assert(obj);
300
301 memset(obj, 0, sizeof(struct snapshot));
302
303 obj->output_ht = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
304 if (!obj->output_ht) {
305 ret = -ENOMEM;
306 goto error;
307 }
308
309 ret = 0;
310
311error:
312 return ret;
313}
314
315/*
316 * Destroy snapshot object but the pointer is not freed so it's safe to pass a
317 * static reference.
318 */
319void snapshot_destroy(struct snapshot *obj)
320{
321 struct lttng_ht_iter iter;
322 struct snapshot_output *output;
323
324 assert(obj);
325
326 rcu_read_lock();
327 cds_lfht_for_each_entry(obj->output_ht->ht, &iter.iter, output,
328 node.node) {
329 snapshot_delete_output(obj, output);
330 snapshot_output_destroy(output);
331 }
332 rcu_read_unlock();
53efb85a 333 ht_cleanup_push(obj->output_ht);
6dc3064a 334}
This page took 0.055906 seconds and 4 git commands to generate.