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