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