output->enabled = 1;
output->type = type;
output->net_seq_index = (uint64_t) -1ULL;
+ urcu_ref_init(&output->ref);
output->socks = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
*
* Should *NOT* be called with RCU read-side lock held.
*/
-void consumer_destroy_output(struct consumer_output *obj)
+static void consumer_release_output(struct urcu_ref *ref)
{
- if (obj == NULL) {
- return;
- }
+ struct consumer_output *obj =
+ caa_container_of(ref, struct consumer_output, ref);
consumer_destroy_output_sockets(obj);
free(obj);
}
+/*
+ * Get the consumer_output object.
+ */
+void consumer_output_get(struct consumer_output *obj)
+{
+ urcu_ref_get(&obj->ref);
+}
+
+/*
+ * Put the consumer_output object.
+ *
+ * Should *NOT* be called with RCU read-side lock held.
+ */
+void consumer_output_put(struct consumer_output *obj)
+{
+ if (!obj) {
+ return;
+ }
+ urcu_ref_put(&obj->ref, consumer_release_output);
+}
+
/*
* Copy consumer output and returned the newly allocated copy.
*
struct consumer_output *consumer_copy_output(struct consumer_output *obj)
{
int ret;
- struct lttng_ht *tmp_ht_ptr;
struct consumer_output *output;
assert(obj);
output = consumer_create_output(obj->type);
if (output == NULL) {
- goto error;
+ goto end;
}
- /* Avoid losing the HT reference after the memcpy() */
- tmp_ht_ptr = output->socks;
-
- memcpy(output, obj, sizeof(struct consumer_output));
-
- /* Putting back the HT pointer and start copying socket(s). */
- output->socks = tmp_ht_ptr;
-
+ output->enabled = obj->enabled;
+ output->net_seq_index = obj->net_seq_index;
+ memcpy(output->subdir, obj->subdir, PATH_MAX);
+ output->snapshot = obj->snapshot;
+ memcpy(&output->dst, &obj->dst, sizeof(output->dst));
ret = consumer_copy_sockets(output, obj);
if (ret < 0) {
- goto malloc_error;
+ goto error_put;
}
-
-error:
+end:
return output;
-malloc_error:
- consumer_destroy_output(output);
+error_put:
+ consumer_output_put(output);
return NULL;
}
#include <common/consumer.h>
#include <common/hashtable/hashtable.h>
#include <lttng/lttng.h>
+#include <urcu/ref.h>
#include "snapshot.h"
* Consumer output object describing where and how to send data.
*/
struct consumer_output {
+ struct urcu_ref ref; /* Refcount */
+
/* If the consumer is enabled meaning that should be used */
unsigned int enabled;
enum consumer_dst_type type;
struct consumer_output *consumer_create_output(enum consumer_dst_type type);
struct consumer_output *consumer_copy_output(struct consumer_output *obj);
-void consumer_destroy_output(struct consumer_output *obj);
+void consumer_output_get(struct consumer_output *obj);
+void consumer_output_put(struct consumer_output *obj);
int consumer_set_network_uri(struct consumer_output *obj,
struct lttng_uri *uri);
int consumer_send_fds(struct consumer_socket *sock, int *fds, size_t nb_fd);
* domain.
*/
if (session->kernel_session->consumer) {
- consumer_destroy_output(session->kernel_session->consumer);
+ consumer_output_put(session->kernel_session->consumer);
}
session->kernel_session->consumer =
consumer_copy_output(session->consumer);
case LTTNG_DOMAIN_UST:
DBG3("Copying tracing session consumer output in UST session");
if (session->ust_session->consumer) {
- consumer_destroy_output(session->ust_session->consumer);
+ consumer_output_put(session->ust_session->consumer);
}
session->ust_session->consumer =
consumer_copy_output(session->consumer);
del_session_list(session);
pthread_mutex_destroy(&session->lock);
- consumer_destroy_output(session->consumer);
+ consumer_output_put(session->consumer);
snapshot_destroy(&session->snapshot);
free(session);
if (obj->consumer) {
consumer_output_send_destroy_relayd(obj->consumer);
- consumer_destroy_output(obj->consumer);
+ consumer_output_put(obj->consumer);
}
free(obj);
}
goto error;
}
- /*
- * The tmp_consumer stays NULL until a set_consumer_uri command is
- * executed. At this point, the consumer should be nullify until an
- * enable_consumer command. This assignment is symbolic since we've zmalloc
- * the struct.
- */
- lks->tmp_consumer = NULL;
-
return lks;
error:
}
/* Wipe consumer output object */
- consumer_destroy_output(session->consumer);
- consumer_destroy_output(session->tmp_consumer);
+ consumer_output_put(session->consumer);
free(session);
}
/* UID/GID of the user owning the session */
uid_t uid;
gid_t gid;
- /*
- * Two consumer_output object are needed where one is needed for the
- * current output object and the second one is the temporary object used to
- * store URI being set by the lttng_set_consumer_uri call. Once
- * lttng_enable_consumer is called, the two pointers are swapped.
- */
struct consumer_output *consumer;
- struct consumer_output *tmp_consumer;
/* Tracing session id */
uint64_t id;
/* Session is active or not meaning it has been started or stopped. */
goto error_consumer;
}
- /*
- * The tmp_consumer stays NULL until a set_consumer_uri command is
- * executed. At this point, the consumer should be nullify until an
- * enable_consumer command. This assignment is symbolic since we've zmalloc
- * the struct.
- */
- lus->tmp_consumer = NULL;
-
DBG2("UST trace session create successful");
return lus;
buffer_reg_uid_destroy(reg, session->consumer);
}
- consumer_destroy_output(session->consumer);
- consumer_destroy_output(session->tmp_consumer);
+ consumer_output_put(session->consumer);
fini_pid_tracker(&session->pid_tracker);
gid_t gid;
/* Is the session active meaning has is been started or stopped. */
unsigned int active:1;
- /*
- * Two consumer_output object are needed where one is for the current
- * output object and the second one is the temporary object used to store
- * URI being set by the lttng_set_consumer_uri call. Once
- * lttng_enable_consumer is called, the two pointers are swapped.
- */
struct consumer_output *consumer;
- struct consumer_output *tmp_consumer;
/* Sequence number for filters so the tracer knows the ordering. */
uint64_t filter_seq_num;
/* This indicates which type of buffer this session is set for. */
}
pthread_mutex_unlock(&ua_sess->lock);
+ consumer_output_put(ua_sess->consumer);
+
call_rcu(&ua_sess->rcu_head, delete_ust_app_session_rcu);
}
ua_sess->egid = usess->gid;
ua_sess->buffer_type = usess->buffer_type;
ua_sess->bits_per_long = app->bits_per_long;
+
/* There is only one consumer object per session possible. */
+ consumer_output_get(usess->consumer);
ua_sess->consumer = usess->consumer;
+
ua_sess->output_traces = usess->output_traces;
ua_sess->live_timer_interval = usess->live_timer_interval;
copy_channel_attr_to_ustctl(&ua_sess->metadata_attr,
lttng_ht_add_unique_str(ua_sess->channels, &ua_chan->node);
}
+ return;
error:
- return;
+ consumer_output_put(ua_sess->consumer);
}
/*