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