docs: Add supported versions and fix-backport policy
[lttng-tools.git] / src / bin / lttng-sessiond / snapshot.cpp
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
28ab034a
JG
9#include "snapshot.hpp"
10#include "utils.hpp"
6dc3064a 11
c9e313bc 12#include <common/defaults.hpp>
56047f5a 13#include <common/urcu.hpp>
6dc3064a 14
28ab034a
JG
15#include <inttypes.h>
16#include <string.h>
17#include <urcu/uatomic.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 32static int output_init(const struct ltt_session *session,
28ab034a
JG
33 uint64_t max_size,
34 const char *name,
35 struct lttng_uri *uris,
36 size_t nb_uri,
37 struct consumer_output *consumer,
38 struct snapshot_output *output,
39 struct snapshot *snapshot)
6dc3064a 40{
5288612f 41 int ret = 0, i;
6dc3064a 42
d4b5a90c
DG
43 memset(output, 0, sizeof(struct snapshot_output));
44
d07ceecd
MD
45 /*
46 * max_size of -1ULL means unset. Set to default (unlimited).
47 */
e1986656
DG
48 if (max_size == (uint64_t) -1ULL) {
49 max_size = 0;
50 }
6dc3064a 51 output->max_size = max_size;
e1986656 52
6dc3064a
DG
53 if (snapshot) {
54 output->id = get_next_output_id(snapshot);
55 }
56 lttng_ht_node_init_ulong(&output->node, (unsigned long) output->id);
57
ee91bab2 58 if (name && name[0] != '\0') {
35f3ec96
MD
59 if (lttng_strncpy(output->name, name, sizeof(output->name))) {
60 ret = -LTTNG_ERR_INVALID;
61 goto error;
62 }
6dc3064a
DG
63 } else {
64 /* Set default name. */
28ab034a
JG
65 ret = snprintf(output->name,
66 sizeof(output->name),
67 "%s-%" PRIu32,
68 DEFAULT_SNAPSHOT_NAME,
69 output->id);
6dc3064a
DG
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) {
28ab034a
JG
94 memset(output->consumer->dst.session_root_path,
95 0,
96 sizeof(output->consumer->dst.session_root_path));
366a9222 97 if (lttng_strncpy(output->consumer->dst.session_root_path,
28ab034a
JG
98 uris[0].dst.path,
99 sizeof(output->consumer->dst.session_root_path))) {
35f3ec96
MD
100 ret = -LTTNG_ERR_INVALID;
101 goto error;
102 }
6dc3064a
DG
103 output->consumer->type = CONSUMER_DST_LOCAL;
104 ret = 0;
105 goto end;
106 }
107
108 if (nb_uri != 2) {
109 /* Absolutely needs two URIs for network. */
110 ret = -LTTNG_ERR_INVALID;
111 goto error;
112 }
113
28ab034a 114 for (i = 0; i < nb_uri; i++) {
6dc3064a 115 /* Network URIs */
28ab034a 116 ret = consumer_set_network_uri(session, output->consumer, &uris[i]);
6dc3064a
DG
117 if (ret < 0) {
118 goto error;
119 }
120 }
121
122error:
123end:
5288612f
DG
124 return ret;
125}
126
127/*
128 * Initialize a snapshot output object using the given parameters and URI(s).
129 * The name value and uris can be NULL.
130 *
131 * Return 0 on success or else a negative value.
132 */
b178f53e 133int snapshot_output_init_with_uri(const struct ltt_session *session,
28ab034a
JG
134 uint64_t max_size,
135 const char *name,
136 struct lttng_uri *uris,
137 size_t nb_uri,
138 struct consumer_output *consumer,
139 struct snapshot_output *output,
140 struct snapshot *snapshot)
5288612f 141{
28ab034a 142 return output_init(session, max_size, name, uris, nb_uri, consumer, output, snapshot);
5288612f
DG
143}
144
145/*
146 * Initialize a snapshot output object using the given parameters. The name
147 * value and url can be NULL.
148 *
149 * Return 0 on success or else a negative value.
150 */
b178f53e 151int snapshot_output_init(const struct ltt_session *session,
28ab034a
JG
152 uint64_t max_size,
153 const char *name,
154 const char *ctrl_url,
155 const char *data_url,
156 struct consumer_output *consumer,
157 struct snapshot_output *output,
158 struct snapshot *snapshot)
5288612f
DG
159{
160 int ret = 0, nb_uri;
cd9adb8b 161 struct lttng_uri *uris = nullptr;
5288612f
DG
162
163 /* Create an array of URIs from URLs. */
164 nb_uri = uri_parse_str_urls(ctrl_url, data_url, &uris);
165 if (nb_uri < 0) {
166 ret = nb_uri;
167 goto error;
168 }
169
28ab034a 170 ret = output_init(session, max_size, name, uris, nb_uri, consumer, output, snapshot);
5288612f
DG
171
172error:
6dc3064a
DG
173 free(uris);
174 return ret;
175}
176
cd9adb8b 177struct snapshot_output *snapshot_output_alloc()
6dc3064a 178{
64803277 179 return zmalloc<snapshot_output>();
6dc3064a
DG
180}
181
182/*
183 * Delete output from the snapshot object.
184 */
28ab034a 185void snapshot_delete_output(struct snapshot *snapshot, struct snapshot_output *output)
6dc3064a
DG
186{
187 int ret;
188 struct lttng_ht_iter iter;
189
a0377dfe
FD
190 LTTNG_ASSERT(snapshot);
191 LTTNG_ASSERT(snapshot->output_ht);
192 LTTNG_ASSERT(output);
6dc3064a
DG
193
194 iter.iter.node = &output->node.node;
56047f5a 195 lttng::urcu::read_lock_guard read_lock;
6dc3064a 196 ret = lttng_ht_del(snapshot->output_ht, &iter);
a0377dfe 197 LTTNG_ASSERT(!ret);
6dc3064a
DG
198 /*
199 * This is safe because the ownership of a snapshot object is in a session
200 * for which the session lock need to be acquired to read and modify it.
201 */
202 snapshot->nb_output--;
203}
204
205/*
206 * Add output object to the snapshot.
207 */
28ab034a 208void snapshot_add_output(struct snapshot *snapshot, struct snapshot_output *output)
6dc3064a 209{
a0377dfe
FD
210 LTTNG_ASSERT(snapshot);
211 LTTNG_ASSERT(snapshot->output_ht);
212 LTTNG_ASSERT(output);
6dc3064a 213
56047f5a 214 lttng::urcu::read_lock_guard read_lock;
6dc3064a 215 lttng_ht_add_unique_ulong(snapshot->output_ht, &output->node);
6dc3064a
DG
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{
a0377dfe 228 LTTNG_ASSERT(obj);
6dc3064a
DG
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 */
28ab034a 243struct snapshot_output *snapshot_find_output_by_name(const char *name, struct snapshot *snapshot)
eb240553
DG
244{
245 struct lttng_ht_iter iter;
cd9adb8b 246 struct snapshot_output *output = nullptr;
eb240553 247
a0377dfe
FD
248 LTTNG_ASSERT(snapshot);
249 LTTNG_ASSERT(name);
48b7cdc2 250 ASSERT_RCU_READ_LOCKED();
eb240553 251
28ab034a 252 cds_lfht_for_each_entry (snapshot->output_ht->ht, &iter.iter, output, node.node) {
eb240553
DG
253 if (!strncmp(output->name, name, strlen(name))) {
254 return output;
255 }
256 }
257
258 /* Not found */
cd9adb8b 259 return nullptr;
eb240553
DG
260}
261
6dc3064a
DG
262/*
263 * RCU read side lock MUST be acquired before calling this since the returned
264 * pointer is in a RCU hash table.
265 *
266 * Return the reference on success or else NULL.
267 */
28ab034a 268struct snapshot_output *snapshot_find_output_by_id(uint32_t id, struct snapshot *snapshot)
6dc3064a
DG
269{
270 struct lttng_ht_node_ulong *node;
271 struct lttng_ht_iter iter;
cd9adb8b 272 struct snapshot_output *output = nullptr;
6dc3064a 273
a0377dfe 274 LTTNG_ASSERT(snapshot);
48b7cdc2 275 ASSERT_RCU_READ_LOCKED();
6dc3064a 276
28ab034a 277 lttng_ht_lookup(snapshot->output_ht, (void *) ((unsigned long) id), &iter);
6dc3064a
DG
278 node = lttng_ht_iter_get_node_ulong(&iter);
279 if (!node) {
280 DBG3("Snapshot output not found with id %" PRId32, id);
281 goto error;
282 }
0114db0e 283 output = lttng::utils::container_of(node, &snapshot_output::node);
6dc3064a
DG
284
285error:
286 return output;
287}
288
6dc3064a
DG
289/*
290 * Initialized a snapshot object that was already allocated.
291 *
292 * Return 0 on success or else a negative errno value.
293 */
294int snapshot_init(struct snapshot *obj)
295{
296 int ret;
297
a0377dfe 298 LTTNG_ASSERT(obj);
6dc3064a
DG
299
300 memset(obj, 0, sizeof(struct snapshot));
301
302 obj->output_ht = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
303 if (!obj->output_ht) {
304 ret = -ENOMEM;
305 goto error;
306 }
307
308 ret = 0;
309
310error:
311 return ret;
312}
313
314/*
315 * Destroy snapshot object but the pointer is not freed so it's safe to pass a
316 * static reference.
317 */
318void snapshot_destroy(struct snapshot *obj)
319{
320 struct lttng_ht_iter iter;
321 struct snapshot_output *output;
322
f4cc5e83
JG
323 if (!obj->output_ht) {
324 return;
325 }
6dc3064a 326
56047f5a
JG
327 {
328 lttng::urcu::read_lock_guard read_lock;
329
330 cds_lfht_for_each_entry (obj->output_ht->ht, &iter.iter, output, node.node) {
331 snapshot_delete_output(obj, output);
332 snapshot_output_destroy(output);
333 }
6dc3064a 334 }
56047f5a 335
3c339053 336 lttng_ht_destroy(obj->output_ht);
6dc3064a 337}
This page took 0.097857 seconds and 4 git commands to generate.