2 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
9 #include "snapshot.hpp"
12 #include <common/defaults.hpp>
13 #include <common/urcu.hpp>
17 #include <urcu/uatomic.h>
20 * Return the atomically incremented value of next_output_id.
22 static inline unsigned long get_next_output_id(struct snapshot
*snapshot
)
24 return uatomic_add_return(&snapshot
->next_output_id
, 1);
28 * Initialized snapshot output with the given values.
30 * Return 0 on success or else a negative value.
32 static int output_init(const struct ltt_session
*session
,
35 struct lttng_uri
*uris
,
37 struct consumer_output
*consumer
,
38 struct snapshot_output
*output
,
39 struct snapshot
*snapshot
)
43 memset(output
, 0, sizeof(struct snapshot_output
));
46 * max_size of -1ULL means unset. Set to default (unlimited).
48 if (max_size
== (uint64_t) -1ULL) {
51 output
->max_size
= max_size
;
54 output
->id
= get_next_output_id(snapshot
);
56 lttng_ht_node_init_ulong(&output
->node
, (unsigned long) output
->id
);
58 if (name
&& name
[0] != '\0') {
59 if (lttng_strncpy(output
->name
, name
, sizeof(output
->name
))) {
60 ret
= -LTTNG_ERR_INVALID
;
64 /* Set default name. */
65 ret
= snprintf(output
->name
,
68 DEFAULT_SNAPSHOT_NAME
,
80 output
->consumer
= consumer_copy_output(consumer
);
81 if (!output
->consumer
) {
85 output
->consumer
->snapshot
= 1;
93 if (uris
[0].dtype
== LTTNG_DST_PATH
) {
94 memset(output
->consumer
->dst
.session_root_path
,
96 sizeof(output
->consumer
->dst
.session_root_path
));
97 if (lttng_strncpy(output
->consumer
->dst
.session_root_path
,
99 sizeof(output
->consumer
->dst
.session_root_path
))) {
100 ret
= -LTTNG_ERR_INVALID
;
103 output
->consumer
->type
= CONSUMER_DST_LOCAL
;
109 /* Absolutely needs two URIs for network. */
110 ret
= -LTTNG_ERR_INVALID
;
114 for (i
= 0; i
< nb_uri
; i
++) {
116 ret
= consumer_set_network_uri(session
, output
->consumer
, &uris
[i
]);
128 * Initialize a snapshot output object using the given parameters and URI(s).
129 * The name value and uris can be NULL.
131 * Return 0 on success or else a negative value.
133 int snapshot_output_init_with_uri(const struct ltt_session
*session
,
136 struct lttng_uri
*uris
,
138 struct consumer_output
*consumer
,
139 struct snapshot_output
*output
,
140 struct snapshot
*snapshot
)
142 return output_init(session
, max_size
, name
, uris
, nb_uri
, consumer
, output
, snapshot
);
146 * Initialize a snapshot output object using the given parameters. The name
147 * value and url can be NULL.
149 * Return 0 on success or else a negative value.
151 int snapshot_output_init(const struct ltt_session
*session
,
154 const char *ctrl_url
,
155 const char *data_url
,
156 struct consumer_output
*consumer
,
157 struct snapshot_output
*output
,
158 struct snapshot
*snapshot
)
161 struct lttng_uri
*uris
= nullptr;
163 /* Create an array of URIs from URLs. */
164 nb_uri
= uri_parse_str_urls(ctrl_url
, data_url
, &uris
);
170 ret
= output_init(session
, max_size
, name
, uris
, nb_uri
, consumer
, output
, snapshot
);
177 struct snapshot_output
*snapshot_output_alloc()
179 return zmalloc
<snapshot_output
>();
183 * Delete output from the snapshot object.
185 void snapshot_delete_output(struct snapshot
*snapshot
, struct snapshot_output
*output
)
188 struct lttng_ht_iter iter
;
190 LTTNG_ASSERT(snapshot
);
191 LTTNG_ASSERT(snapshot
->output_ht
);
192 LTTNG_ASSERT(output
);
194 iter
.iter
.node
= &output
->node
.node
;
195 lttng::urcu::read_lock_guard read_lock
;
196 ret
= lttng_ht_del(snapshot
->output_ht
, &iter
);
199 * This is safe because the ownership of a snapshot object is in a session
200 * for which the session lock need to be acquired to read and modify it.
202 snapshot
->nb_output
--;
206 * Add output object to the snapshot.
208 void snapshot_add_output(struct snapshot
*snapshot
, struct snapshot_output
*output
)
210 LTTNG_ASSERT(snapshot
);
211 LTTNG_ASSERT(snapshot
->output_ht
);
212 LTTNG_ASSERT(output
);
214 lttng::urcu::read_lock_guard read_lock
;
215 lttng_ht_add_unique_ulong(snapshot
->output_ht
, &output
->node
);
217 * This is safe because the ownership of a snapshot object is in a session
218 * for which the session lock need to be acquired to read and modify it.
220 snapshot
->nb_output
++;
224 * Destroy and free a snapshot output object.
226 void snapshot_output_destroy(struct snapshot_output
*obj
)
231 consumer_output_send_destroy_relayd(obj
->consumer
);
232 consumer_output_put(obj
->consumer
);
238 * RCU read side lock MUST be acquired before calling this since the returned
239 * pointer is in a RCU hash table.
241 * Return the reference on success or else NULL.
243 struct snapshot_output
*snapshot_find_output_by_name(const char *name
, struct snapshot
*snapshot
)
245 struct lttng_ht_iter iter
;
246 struct snapshot_output
*output
= nullptr;
248 LTTNG_ASSERT(snapshot
);
250 ASSERT_RCU_READ_LOCKED();
252 cds_lfht_for_each_entry (snapshot
->output_ht
->ht
, &iter
.iter
, output
, node
.node
) {
253 if (!strncmp(output
->name
, name
, strlen(name
))) {
263 * RCU read side lock MUST be acquired before calling this since the returned
264 * pointer is in a RCU hash table.
266 * Return the reference on success or else NULL.
268 struct snapshot_output
*snapshot_find_output_by_id(uint32_t id
, struct snapshot
*snapshot
)
270 struct lttng_ht_node_ulong
*node
;
271 struct lttng_ht_iter iter
;
272 struct snapshot_output
*output
= nullptr;
274 LTTNG_ASSERT(snapshot
);
275 ASSERT_RCU_READ_LOCKED();
277 lttng_ht_lookup(snapshot
->output_ht
, (void *) ((unsigned long) id
), &iter
);
278 node
= lttng_ht_iter_get_node_ulong(&iter
);
280 DBG3("Snapshot output not found with id %" PRId32
, id
);
283 output
= lttng::utils::container_of(node
, &snapshot_output::node
);
290 * Initialized a snapshot object that was already allocated.
292 * Return 0 on success or else a negative errno value.
294 int snapshot_init(struct snapshot
*obj
)
300 memset(obj
, 0, sizeof(struct snapshot
));
302 obj
->output_ht
= lttng_ht_new(0, LTTNG_HT_TYPE_ULONG
);
303 if (!obj
->output_ht
) {
315 * Destroy snapshot object but the pointer is not freed so it's safe to pass a
318 void snapshot_destroy(struct snapshot
*obj
)
320 struct lttng_ht_iter iter
;
321 struct snapshot_output
*output
;
323 if (!obj
->output_ht
) {
328 lttng::urcu::read_lock_guard read_lock
;
330 cds_lfht_for_each_entry (obj
->output_ht
->ht
, &iter
.iter
, output
, node
.node
) {
331 snapshot_delete_output(obj
, output
);
332 snapshot_output_destroy(output
);
336 lttng_ht_destroy(obj
->output_ht
);