Fix: grab more than one packet for snapshots
[lttng-tools.git] / src / bin / lttng-sessiond / snapshot.c
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 #define _LGPL_SOURCE
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"
28 #include "utils.h"
29
30 /*
31 * Return the atomically incremented value of next_output_id.
32 */
33 static inline unsigned long get_next_output_id(struct snapshot *snapshot)
34 {
35 return uatomic_add_return(&snapshot->next_output_id, 1);
36 }
37
38 /*
39 * Initialized snapshot output with the given values.
40 *
41 * Return 0 on success or else a negative value.
42 */
43 static int output_init(uint64_t max_size, const char *name,
44 struct lttng_uri *uris, size_t nb_uri,
45 struct consumer_output *consumer, struct snapshot_output *output,
46 struct snapshot *snapshot)
47 {
48 int ret = 0, i;
49
50 memset(output, 0, sizeof(struct snapshot_output));
51
52 /*
53 * max_size of -1ULL means unset. Set to default (unlimited).
54 */
55 if (max_size == (uint64_t) -1ULL) {
56 max_size = 0;
57 }
58 output->max_size = max_size;
59
60 if (snapshot) {
61 output->id = get_next_output_id(snapshot);
62 }
63 lttng_ht_node_init_ulong(&output->node, (unsigned long) output->id);
64
65 if (name && name[0] != '\0') {
66 strncpy(output->name, name, sizeof(output->name));
67 } else {
68 /* Set default name. */
69 ret = snprintf(output->name, sizeof(output->name), "%s-%" PRIu32,
70 DEFAULT_SNAPSHOT_NAME, output->id);
71 if (ret < 0) {
72 ret = -ENOMEM;
73 goto error;
74 }
75 }
76
77 if (!consumer) {
78 goto end;
79 }
80
81 output->consumer = consumer_copy_output(consumer);
82 if (!output->consumer) {
83 ret = -ENOMEM;
84 goto error;
85 }
86 output->consumer->snapshot = 1;
87
88 /* No URL given. */
89 if (nb_uri == 0) {
90 ret = 0;
91 goto end;
92 }
93
94 if (uris[0].dtype == LTTNG_DST_PATH) {
95 memset(output->consumer->dst.trace_path, 0,
96 sizeof(output->consumer->dst.trace_path));
97 strncpy(output->consumer->dst.trace_path, uris[0].dst.path,
98 sizeof(output->consumer->dst.trace_path));
99 output->consumer->type = CONSUMER_DST_LOCAL;
100 ret = 0;
101 goto end;
102 }
103
104 if (nb_uri != 2) {
105 /* Absolutely needs two URIs for network. */
106 ret = -LTTNG_ERR_INVALID;
107 goto error;
108 }
109
110 for (i = 0; i < nb_uri; i ++) {
111 /* Network URIs */
112 ret = consumer_set_network_uri(output->consumer, &uris[i]);
113 if (ret < 0) {
114 goto error;
115 }
116 }
117
118 error:
119 end:
120 return ret;
121 }
122
123 /*
124 * Initialize a snapshot output object using the given parameters and URI(s).
125 * The name value and uris can be NULL.
126 *
127 * Return 0 on success or else a negative value.
128 */
129 int snapshot_output_init_with_uri(uint64_t max_size, const char *name,
130 struct lttng_uri *uris, size_t nb_uri,
131 struct consumer_output *consumer, struct snapshot_output *output,
132 struct snapshot *snapshot)
133 {
134 return output_init(max_size, name, uris, nb_uri, consumer, output,
135 snapshot);
136 }
137
138 /*
139 * Initialize a snapshot output object using the given parameters. The name
140 * value and url can be NULL.
141 *
142 * Return 0 on success or else a negative value.
143 */
144 int snapshot_output_init(uint64_t max_size, const char *name,
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
159 ret = output_init(max_size, name, uris, nb_uri, consumer, output,
160 snapshot);
161
162 error:
163 free(uris);
164 return ret;
165 }
166
167 struct 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 */
175 void 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 */
200 void 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 */
220 void snapshot_output_destroy(struct snapshot_output *obj)
221 {
222 assert(obj);
223
224 if (obj->consumer) {
225 consumer_output_send_destroy_relayd(obj->consumer);
226 consumer_destroy_output(obj->consumer);
227 }
228 free(obj);
229 }
230
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 */
237 struct 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
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 */
263 struct 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
280 error:
281 return output;
282 }
283
284 /*
285 * Initialized a snapshot object that was already allocated.
286 *
287 * Return 0 on success or else a negative errno value.
288 */
289 int 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
305 error:
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 */
313 void snapshot_destroy(struct snapshot *obj)
314 {
315 struct lttng_ht_iter iter;
316 struct snapshot_output *output;
317
318 assert(obj);
319
320 rcu_read_lock();
321 cds_lfht_for_each_entry(obj->output_ht->ht, &iter.iter, output,
322 node.node) {
323 snapshot_delete_output(obj, output);
324 snapshot_output_destroy(output);
325 }
326 rcu_read_unlock();
327 ht_cleanup_push(obj->output_ht);
328 }
This page took 0.037643 seconds and 6 git commands to generate.