2 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
9 #include "consumer-output.hpp"
10 #include "snapshot-output.hpp"
11 #include "snapshot.hpp"
14 #include <common/defaults.hpp>
15 #include <common/urcu.hpp>
19 #include <urcu/uatomic.h>
22 * Return the atomically incremented value of next_output_id.
24 static inline unsigned long get_next_output_id(struct snapshot
*snapshot
)
26 return uatomic_add_return(&snapshot
->next_output_id
, 1);
30 * Initialized snapshot output with the given values.
32 * Return 0 on success or else a negative value.
34 static int output_init(const ltt_session::locked_ref
& session
,
37 struct lttng_uri
*uris
,
39 struct consumer_output
*consumer
,
40 struct snapshot_output
*output
,
41 struct snapshot
*snapshot
)
45 memset(output
, 0, sizeof(struct snapshot_output
));
48 * max_size of -1ULL means unset. Set to default (unlimited).
50 if (max_size
== (uint64_t) -1ULL) {
53 output
->max_size
= max_size
;
56 output
->id
= get_next_output_id(snapshot
);
58 lttng_ht_node_init_ulong(&output
->node
, (unsigned long) output
->id
);
60 if (name
&& name
[0] != '\0') {
61 if (lttng_strncpy(output
->name
, name
, sizeof(output
->name
))) {
62 ret
= -LTTNG_ERR_INVALID
;
66 /* Set default name. */
67 ret
= snprintf(output
->name
,
70 DEFAULT_SNAPSHOT_NAME
,
82 output
->consumer
= consumer_copy_output(consumer
);
83 if (!output
->consumer
) {
87 output
->consumer
->snapshot
= 1;
95 if (uris
[0].dtype
== LTTNG_DST_PATH
) {
96 memset(output
->consumer
->dst
.session_root_path
,
98 sizeof(output
->consumer
->dst
.session_root_path
));
99 if (lttng_strncpy(output
->consumer
->dst
.session_root_path
,
101 sizeof(output
->consumer
->dst
.session_root_path
))) {
102 ret
= -LTTNG_ERR_INVALID
;
105 output
->consumer
->type
= CONSUMER_DST_LOCAL
;
111 /* Absolutely needs two URIs for network. */
112 ret
= -LTTNG_ERR_INVALID
;
116 for (i
= 0; i
< nb_uri
; i
++) {
118 ret
= consumer_set_network_uri(session
, output
->consumer
, &uris
[i
]);
130 * Initialize a snapshot output object using the given parameters and URI(s).
131 * The name value and uris can be NULL.
133 * Return 0 on success or else a negative value.
135 int snapshot_output_init_with_uri(const ltt_session::locked_ref
& session
,
138 struct lttng_uri
*uris
,
140 struct consumer_output
*consumer
,
141 struct snapshot_output
*output
,
142 struct snapshot
*snapshot
)
144 return output_init(session
, max_size
, name
, uris
, nb_uri
, consumer
, output
, snapshot
);
148 * Initialize a snapshot output object using the given parameters. The name
149 * value and url can be NULL.
151 * Return 0 on success or else a negative value.
153 int snapshot_output_init(const ltt_session::locked_ref
& session
,
156 const char *ctrl_url
,
157 const char *data_url
,
158 struct consumer_output
*consumer
,
159 struct snapshot_output
*output
,
160 struct snapshot
*snapshot
)
163 struct lttng_uri
*uris
= nullptr;
165 /* Create an array of URIs from URLs. */
166 nb_uri
= uri_parse_str_urls(ctrl_url
, data_url
, &uris
);
172 ret
= output_init(session
, max_size
, name
, uris
, nb_uri
, consumer
, output
, snapshot
);
179 struct snapshot_output
*snapshot_output_alloc()
181 return zmalloc
<snapshot_output
>();
185 * Delete output from the snapshot object.
187 void snapshot_delete_output(struct snapshot
*snapshot
, struct snapshot_output
*output
)
190 struct lttng_ht_iter iter
;
192 LTTNG_ASSERT(snapshot
);
193 LTTNG_ASSERT(snapshot
->output_ht
);
194 LTTNG_ASSERT(output
);
196 iter
.iter
.node
= &output
->node
.node
;
197 const lttng::urcu::read_lock_guard read_lock
;
198 ret
= lttng_ht_del(snapshot
->output_ht
, &iter
);
201 * This is safe because the ownership of a snapshot object is in a session
202 * for which the session lock need to be acquired to read and modify it.
204 snapshot
->nb_output
--;
208 * Add output object to the snapshot.
210 void snapshot_add_output(struct snapshot
*snapshot
, struct snapshot_output
*output
)
212 LTTNG_ASSERT(snapshot
);
213 LTTNG_ASSERT(snapshot
->output_ht
);
214 LTTNG_ASSERT(output
);
216 const lttng::urcu::read_lock_guard read_lock
;
217 lttng_ht_add_unique_ulong(snapshot
->output_ht
, &output
->node
);
219 * This is safe because the ownership of a snapshot object is in a session
220 * for which the session lock need to be acquired to read and modify it.
222 snapshot
->nb_output
++;
226 * Destroy and free a snapshot output object.
228 void snapshot_output_destroy(struct snapshot_output
*obj
)
233 consumer_output_send_destroy_relayd(obj
->consumer
);
234 consumer_output_put(obj
->consumer
);
240 * RCU read side lock MUST be acquired before calling this since the returned
241 * pointer is in a RCU hash table.
243 * Return the reference on success or else NULL.
245 struct snapshot_output
*snapshot_find_output_by_name(const char *name
, struct snapshot
*snapshot
)
247 struct lttng_ht_iter iter
;
248 struct snapshot_output
*output
= nullptr;
250 LTTNG_ASSERT(snapshot
);
252 ASSERT_RCU_READ_LOCKED();
254 cds_lfht_for_each_entry (snapshot
->output_ht
->ht
, &iter
.iter
, output
, node
.node
) {
255 if (!strncmp(output
->name
, name
, strlen(name
))) {
265 * RCU read side lock MUST be acquired before calling this since the returned
266 * pointer is in a RCU hash table.
268 * Return the reference on success or else NULL.
270 struct snapshot_output
*snapshot_find_output_by_id(uint32_t id
, struct snapshot
*snapshot
)
272 struct lttng_ht_node_ulong
*node
;
273 struct lttng_ht_iter iter
;
274 struct snapshot_output
*output
= nullptr;
276 LTTNG_ASSERT(snapshot
);
277 ASSERT_RCU_READ_LOCKED();
279 lttng_ht_lookup(snapshot
->output_ht
, (void *) ((unsigned long) id
), &iter
);
280 node
= lttng_ht_iter_get_node
<lttng_ht_node_ulong
>(&iter
);
282 DBG3("Snapshot output not found with id %" PRId32
, id
);
285 output
= lttng::utils::container_of(node
, &snapshot_output::node
);
292 * Initialized a snapshot object that was already allocated.
294 * Return 0 on success or else a negative errno value.
296 int snapshot_init(struct snapshot
*obj
)
302 memset(obj
, 0, sizeof(struct snapshot
));
304 obj
->output_ht
= lttng_ht_new(0, LTTNG_HT_TYPE_ULONG
);
305 if (!obj
->output_ht
) {
317 * Destroy snapshot object but the pointer is not freed so it's safe to pass a
320 void snapshot_destroy(struct snapshot
*obj
)
322 struct lttng_ht_iter iter
;
323 struct snapshot_output
*output
;
325 if (!obj
->output_ht
) {
330 const lttng::urcu::read_lock_guard read_lock
;
332 cds_lfht_for_each_entry (obj
->output_ht
->ht
, &iter
.iter
, output
, node
.node
) {
333 snapshot_delete_output(obj
, output
);
334 snapshot_output_destroy(output
);
338 lttng_ht_destroy(obj
->output_ht
);