X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-relayd%2Fsession.c;h=02cc748e75f6fd8f25f3cf5e47623d7523c1affb;hp=07f1d9f03522d22553d11350444acc9754bb3a8f;hb=2a174661a1e0ab551b41ff1cae7191688525fc1f;hpb=2f8f53af90479595d530f8f02e71dd0b9fb810ee diff --git a/src/bin/lttng-relayd/session.c b/src/bin/lttng-relayd/session.c index 07f1d9f03..02cc748e7 100644 --- a/src/bin/lttng-relayd/session.c +++ b/src/bin/lttng-relayd/session.c @@ -16,7 +16,52 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#define _GNU_SOURCE +#include + +#include "ctf-trace.h" #include "session.h" +#include "stream.h" + +/* Global session id used in the session creation. */ +static uint64_t last_relay_session_id; + +static void rcu_destroy_session(struct rcu_head *head) +{ + struct relay_session *session = + caa_container_of(head, struct relay_session, rcu_node); + + free(session); +} + +/* + * Create a new session by assigning a new session ID. + * + * Return allocated session or else NULL. + */ +struct relay_session *session_create(void) +{ + struct relay_session *session; + + session = zmalloc(sizeof(*session)); + if (!session) { + PERROR("relay session zmalloc"); + goto error; + } + + session->ctf_traces_ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); + if (!session->ctf_traces_ht) { + free(session); + goto error; + } + + pthread_mutex_init(&session->viewer_ready_lock, NULL); + session->id = ++last_relay_session_id; + lttng_ht_node_init_u64(&session->session_n, session->id); + +error: + return session; +} /* * Lookup a session within the given hash table and session id. RCU read side @@ -28,18 +73,107 @@ struct relay_session *session_find_by_id(struct lttng_ht *ht, uint64_t id) { struct relay_session *session = NULL; - struct lttng_ht_node_ulong *node; + struct lttng_ht_node_u64 *node; struct lttng_ht_iter iter; assert(ht); - lttng_ht_lookup(ht, (void *)((unsigned long) id), &iter); - node = lttng_ht_iter_get_node_ulong(&iter); + lttng_ht_lookup(ht, &id, &iter); + node = lttng_ht_iter_get_node_u64(&iter); if (!node) { + DBG("Session find by ID %" PRIu64 " id NOT found", id); goto end; } session = caa_container_of(node, struct relay_session, session_n); + DBG("Session find by ID %" PRIu64 " id found", id); end: return session; } + +/* + * Delete session from the given hash table. + * + * Return lttng ht del error code being 0 on success and 1 on failure. + */ +int session_delete(struct lttng_ht *ht, struct relay_session *session) +{ + struct lttng_ht_iter iter; + + assert(ht); + assert(session); + + iter.iter.node = &session->session_n.node; + return lttng_ht_del(ht, &iter); +} + +/* + * The caller MUST be from the viewer thread since the viewer refcount is + * decremented. With this calue down to 0, it will try to destroy the session. + */ +void session_viewer_try_destroy(struct lttng_ht *ht, + struct relay_session *session) +{ + unsigned long ret_ref; + + assert(session); + + ret_ref = uatomic_add_return(&session->viewer_refcount, -1); + if (ret_ref == 0) { + session_try_destroy(ht, session); + } +} + +/* + * Should only be called from the main streaming thread since it does not touch + * the viewer refcount. If this refcount is down to 0, destroy the session only + * and only if the session deletion succeeds. This is done because the viewer + * *and* the streaming thread can both concurently try to destroy the session + * thus the first come first serve. + */ +void session_try_destroy(struct lttng_ht *ht, struct relay_session *session) +{ + int ret = 0; + unsigned long ret_ref; + + assert(session); + + ret_ref = uatomic_read(&session->viewer_refcount); + if (ret_ref == 0 && session->close_flag) { + if (ht) { + ret = session_delete(ht, session); + } + if (!ret) { + /* Only destroy the session if the deletion was successful. */ + session_destroy(session); + } + } +} + +/* + * Destroy a session object. + */ +void session_destroy(struct relay_session *session) +{ + struct ctf_trace *ctf_trace; + struct lttng_ht_iter iter; + + assert(session); + + DBG("Relay destroying session %" PRIu64, session->id); + + /* + * Empty the ctf trace hash table which will destroy the stream contained + * in that table. + */ + rcu_read_lock(); + cds_lfht_for_each_entry(session->ctf_traces_ht->ht, &iter.iter, ctf_trace, + node.node) { + ctf_trace_delete(session->ctf_traces_ht, ctf_trace); + ctf_trace_destroy(ctf_trace); + } + lttng_ht_destroy(session->ctf_traces_ht); + rcu_read_unlock(); + + call_rcu(&session->rcu_node, rcu_destroy_session); +}