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