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