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