Add a basic .clang-tidy file and fix typedef warnings
[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>
6dc3064a 13
28ab034a
JG
14#include <inttypes.h>
15#include <string.h>
16#include <urcu/uatomic.h>
6dc3064a
DG
17
18/*
19 * Return the atomically incremented value of next_output_id.
20 */
21static inline unsigned long get_next_output_id(struct snapshot *snapshot)
22{
23 return uatomic_add_return(&snapshot->next_output_id, 1);
24}
25
26/*
5288612f 27 * Initialized snapshot output with the given values.
6dc3064a
DG
28 *
29 * Return 0 on success or else a negative value.
30 */
b178f53e 31static int output_init(const struct ltt_session *session,
28ab034a
JG
32 uint64_t max_size,
33 const char *name,
34 struct lttng_uri *uris,
35 size_t nb_uri,
36 struct consumer_output *consumer,
37 struct snapshot_output *output,
38 struct snapshot *snapshot)
6dc3064a 39{
5288612f 40 int ret = 0, i;
6dc3064a 41
d4b5a90c
DG
42 memset(output, 0, sizeof(struct snapshot_output));
43
d07ceecd
MD
44 /*
45 * max_size of -1ULL means unset. Set to default (unlimited).
46 */
e1986656
DG
47 if (max_size == (uint64_t) -1ULL) {
48 max_size = 0;
49 }
6dc3064a 50 output->max_size = max_size;
e1986656 51
6dc3064a
DG
52 if (snapshot) {
53 output->id = get_next_output_id(snapshot);
54 }
55 lttng_ht_node_init_ulong(&output->node, (unsigned long) output->id);
56
ee91bab2 57 if (name && name[0] != '\0') {
35f3ec96
MD
58 if (lttng_strncpy(output->name, name, sizeof(output->name))) {
59 ret = -LTTNG_ERR_INVALID;
60 goto error;
61 }
6dc3064a
DG
62 } else {
63 /* Set default name. */
28ab034a
JG
64 ret = snprintf(output->name,
65 sizeof(output->name),
66 "%s-%" PRIu32,
67 DEFAULT_SNAPSHOT_NAME,
68 output->id);
6dc3064a
DG
69 if (ret < 0) {
70 ret = -ENOMEM;
71 goto error;
72 }
73 }
74
75 if (!consumer) {
76 goto end;
77 }
78
6dc3064a
DG
79 output->consumer = consumer_copy_output(consumer);
80 if (!output->consumer) {
81 ret = -ENOMEM;
82 goto error;
83 }
7d2f7452 84 output->consumer->snapshot = 1;
6dc3064a
DG
85
86 /* No URL given. */
87 if (nb_uri == 0) {
88 ret = 0;
89 goto end;
90 }
91
92 if (uris[0].dtype == LTTNG_DST_PATH) {
28ab034a
JG
93 memset(output->consumer->dst.session_root_path,
94 0,
95 sizeof(output->consumer->dst.session_root_path));
366a9222 96 if (lttng_strncpy(output->consumer->dst.session_root_path,
28ab034a
JG
97 uris[0].dst.path,
98 sizeof(output->consumer->dst.session_root_path))) {
35f3ec96
MD
99 ret = -LTTNG_ERR_INVALID;
100 goto error;
101 }
6dc3064a
DG
102 output->consumer->type = CONSUMER_DST_LOCAL;
103 ret = 0;
104 goto end;
105 }
106
107 if (nb_uri != 2) {
108 /* Absolutely needs two URIs for network. */
109 ret = -LTTNG_ERR_INVALID;
110 goto error;
111 }
112
28ab034a 113 for (i = 0; i < nb_uri; i++) {
6dc3064a 114 /* Network URIs */
28ab034a 115 ret = consumer_set_network_uri(session, output->consumer, &uris[i]);
6dc3064a
DG
116 if (ret < 0) {
117 goto error;
118 }
119 }
120
121error:
122end:
5288612f
DG
123 return ret;
124}
125
126/*
127 * Initialize a snapshot output object using the given parameters and URI(s).
128 * The name value and uris can be NULL.
129 *
130 * Return 0 on success or else a negative value.
131 */
b178f53e 132int snapshot_output_init_with_uri(const struct ltt_session *session,
28ab034a
JG
133 uint64_t max_size,
134 const char *name,
135 struct lttng_uri *uris,
136 size_t nb_uri,
137 struct consumer_output *consumer,
138 struct snapshot_output *output,
139 struct snapshot *snapshot)
5288612f 140{
28ab034a 141 return output_init(session, max_size, name, uris, nb_uri, consumer, output, snapshot);
5288612f
DG
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 */
b178f53e 150int snapshot_output_init(const struct ltt_session *session,
28ab034a
JG
151 uint64_t max_size,
152 const char *name,
153 const char *ctrl_url,
154 const char *data_url,
155 struct consumer_output *consumer,
156 struct snapshot_output *output,
157 struct snapshot *snapshot)
5288612f
DG
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
28ab034a 169 ret = output_init(session, max_size, name, uris, nb_uri, consumer, output, snapshot);
5288612f
DG
170
171error:
6dc3064a
DG
172 free(uris);
173 return ret;
174}
175
176struct snapshot_output *snapshot_output_alloc(void)
177{
64803277 178 return zmalloc<snapshot_output>();
6dc3064a
DG
179}
180
181/*
182 * Delete output from the snapshot object.
183 */
28ab034a 184void snapshot_delete_output(struct snapshot *snapshot, struct snapshot_output *output)
6dc3064a
DG
185{
186 int ret;
187 struct lttng_ht_iter iter;
188
a0377dfe
FD
189 LTTNG_ASSERT(snapshot);
190 LTTNG_ASSERT(snapshot->output_ht);
191 LTTNG_ASSERT(output);
6dc3064a
DG
192
193 iter.iter.node = &output->node.node;
194 rcu_read_lock();
195 ret = lttng_ht_del(snapshot->output_ht, &iter);
196 rcu_read_unlock();
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
DG
213
214 rcu_read_lock();
215 lttng_ht_add_unique_ulong(snapshot->output_ht, &output->node);
216 rcu_read_unlock();
217 /*
218 * This is safe because the ownership of a snapshot object is in a session
219 * for which the session lock need to be acquired to read and modify it.
220 */
221 snapshot->nb_output++;
222}
223
224/*
225 * Destroy and free a snapshot output object.
226 */
227void snapshot_output_destroy(struct snapshot_output *obj)
228{
a0377dfe 229 LTTNG_ASSERT(obj);
6dc3064a
DG
230
231 if (obj->consumer) {
232 consumer_output_send_destroy_relayd(obj->consumer);
6addfa37 233 consumer_output_put(obj->consumer);
6dc3064a
DG
234 }
235 free(obj);
236}
237
eb240553
DG
238/*
239 * RCU read side lock MUST be acquired before calling this since the returned
240 * pointer is in a RCU hash table.
241 *
242 * Return the reference on success or else NULL.
243 */
28ab034a 244struct snapshot_output *snapshot_find_output_by_name(const char *name, struct snapshot *snapshot)
eb240553
DG
245{
246 struct lttng_ht_iter iter;
247 struct snapshot_output *output = NULL;
248
a0377dfe
FD
249 LTTNG_ASSERT(snapshot);
250 LTTNG_ASSERT(name);
48b7cdc2 251 ASSERT_RCU_READ_LOCKED();
eb240553 252
28ab034a 253 cds_lfht_for_each_entry (snapshot->output_ht->ht, &iter.iter, output, node.node) {
eb240553
DG
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 */
28ab034a 269struct snapshot_output *snapshot_find_output_by_id(uint32_t id, struct snapshot *snapshot)
6dc3064a
DG
270{
271 struct lttng_ht_node_ulong *node;
272 struct lttng_ht_iter iter;
273 struct snapshot_output *output = NULL;
274
a0377dfe 275 LTTNG_ASSERT(snapshot);
48b7cdc2 276 ASSERT_RCU_READ_LOCKED();
6dc3064a 277
28ab034a 278 lttng_ht_lookup(snapshot->output_ht, (void *) ((unsigned long) id), &iter);
6dc3064a
DG
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 }
0114db0e 284 output = lttng::utils::container_of(node, &snapshot_output::node);
6dc3064a
DG
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
a0377dfe 299 LTTNG_ASSERT(obj);
6dc3064a
DG
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
f4cc5e83
JG
324 if (!obj->output_ht) {
325 return;
326 }
6dc3064a
DG
327
328 rcu_read_lock();
28ab034a 329 cds_lfht_for_each_entry (obj->output_ht->ht, &iter.iter, output, node.node) {
6dc3064a
DG
330 snapshot_delete_output(obj, output);
331 snapshot_output_destroy(output);
332 }
333 rcu_read_unlock();
3c339053 334 lttng_ht_destroy(obj->output_ht);
6dc3064a 335}
This page took 0.086518 seconds and 4 git commands to generate.