Live: command to detach a viewer session
authorJulien Desfossez <jdesfossez@efficios.com>
Mon, 7 Mar 2016 17:46:50 +0000 (12:46 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 16 Mar 2016 18:18:08 +0000 (14:18 -0400)
The LTTNG_VIEWER_DETACH_SESSION command allows the viewer to detach from
a session it is currently attached to without requiring it to close
the network connection.

Fixes: #853

Signed-off-by: Julien Desfossez <jdesfossez@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-relayd/live.c
src/bin/lttng-relayd/lttng-viewer-abi.h
src/bin/lttng-relayd/viewer-session.c
src/bin/lttng-relayd/viewer-session.h

index 0cf2665161251a71ce1351e76c5f997598c5251d..a9f4f648b0bafff2e2bf4cfb0af258f8ce3135bf 100644 (file)
@@ -1734,6 +1734,78 @@ end:
        return ret;
 }
 
+/*
+ * Detach a viewer session.
+ *
+ * Return 0 on success or else a negative value.
+ */
+static
+int viewer_detach_session(struct relay_connection *conn)
+{
+       int ret;
+       struct lttng_viewer_detach_session_response response;
+       struct lttng_viewer_detach_session_request request;
+       struct relay_session *session = NULL;
+       uint64_t viewer_session_to_close;
+
+       DBG("Viewer detach session received");
+
+       assert(conn);
+
+       health_code_update();
+
+       /* Receive the request from the connected client. */
+       ret = recv_request(conn->sock, &request, sizeof(request));
+       if (ret < 0) {
+               goto end;
+       }
+       viewer_session_to_close = be64toh(request.session_id);
+
+       if (!conn->viewer_session) {
+               DBG("Client trying to detach before creating a live viewer session");
+               response.status = htobe32(LTTNG_VIEWER_DETACH_SESSION_ERR);
+               goto send_reply;
+       }
+
+       health_code_update();
+
+       memset(&response, 0, sizeof(response));
+       DBG("Detaching from session ID %" PRIu64, viewer_session_to_close);
+
+       session = session_get_by_id(be64toh(request.session_id));
+       if (!session) {
+               DBG("Relay session %" PRIu64 " not found",
+                               be64toh(request.session_id));
+               response.status = htobe32(LTTNG_VIEWER_DETACH_SESSION_UNK);
+               goto send_reply;
+       }
+
+       ret = viewer_session_is_attached(conn->viewer_session, session);
+       if (ret != 1) {
+               DBG("Not attached to this session");
+               response.status = htobe32(LTTNG_VIEWER_DETACH_SESSION_ERR);
+               goto send_reply_put;
+       }
+
+       viewer_session_close_one_session(conn->viewer_session, session);
+       response.status = htobe32(LTTNG_VIEWER_DETACH_SESSION_OK);
+       DBG("Session %" PRIu64 " detached.", viewer_session_to_close);
+
+send_reply_put:
+       session_put(session);
+
+send_reply:
+       health_code_update();
+       ret = send_response(conn->sock, &response, sizeof(response));
+       if (ret < 0) {
+               goto end;
+       }
+       health_code_update();
+       ret = 0;
+
+end:
+       return ret;
+}
 
 /*
  * live_relay_unknown_command: send -1 if received unknown command
@@ -1795,6 +1867,9 @@ int process_control(struct lttng_viewer_cmd *recv_hdr,
        case LTTNG_VIEWER_CREATE_SESSION:
                ret = viewer_create_session(conn);
                break;
+       case LTTNG_VIEWER_DETACH_SESSION:
+               ret = viewer_detach_session(conn);
+               break;
        default:
                ERR("Received unknown viewer command (%u)",
                                be32toh(recv_hdr->cmd));
index f9bce98d0b8dd8b8d5d6e480c993020502bf5d28..35267ca3fc38fab0d26bdc8486834ba746a0d0fe 100644 (file)
@@ -48,6 +48,7 @@ enum lttng_viewer_command {
        LTTNG_VIEWER_GET_METADATA       = 6,
        LTTNG_VIEWER_GET_NEW_STREAMS    = 7,
        LTTNG_VIEWER_CREATE_SESSION     = 8,
+       LTTNG_VIEWER_DETACH_SESSION     = 9,
 };
 
 enum lttng_viewer_attach_return_code {
@@ -105,6 +106,12 @@ enum lttng_viewer_create_session_return_code {
        LTTNG_VIEWER_CREATE_SESSION_ERR         = 2,
 };
 
+enum lttng_viewer_detach_session_return_code {
+       LTTNG_VIEWER_DETACH_SESSION_OK          = 1,
+       LTTNG_VIEWER_DETACH_SESSION_UNK         = 2,
+       LTTNG_VIEWER_DETACH_SESSION_ERR         = 3,
+};
+
 struct lttng_viewer_session {
        uint64_t id;
        uint32_t live_timer;
@@ -232,4 +239,16 @@ struct lttng_viewer_create_session_response {
        uint32_t status;
 } __attribute__((__packed__));
 
+/*
+ * LTTNG_VIEWER_DETACH_SESSION payload.
+ */
+struct lttng_viewer_detach_session_request {
+       uint64_t session_id;
+} __attribute__((__packed__));
+
+struct lttng_viewer_detach_session_response {
+       /* enum lttng_viewer_detach_session_return_code */
+       uint32_t status;
+} __attribute__((__packed__));
+
 #endif /* LTTNG_VIEWER_ABI_H */
index 6d74b351717dc695103127b178c2074dd142a54b..a4b859726a6ea9b9bc7ef86ac5a019f43e29bdc2 100644 (file)
@@ -105,6 +105,41 @@ void viewer_session_destroy(struct relay_viewer_session *vsession)
        free(vsession);
 }
 
+/*
+ * Release ownership of all the streams of one session and detach the viewer.
+ */
+void viewer_session_close_one_session(struct relay_viewer_session *vsession,
+               struct relay_session *session)
+{
+       struct lttng_ht_iter iter;
+       struct relay_viewer_stream *vstream;
+
+       /*
+        * TODO: improvement: create more efficient list of
+        * vstream per session.
+        */
+       cds_lfht_for_each_entry(viewer_streams_ht->ht, &iter.iter,
+                       vstream, stream_n.node) {
+               if (!viewer_stream_get(vstream)) {
+                       continue;
+               }
+               if (vstream->stream->trace->session != session) {
+                       viewer_stream_put(vstream);
+                       continue;
+               }
+               /* Put local reference. */
+               viewer_stream_put(vstream);
+               /*
+                * We have reached one of the viewer stream's lifetime
+                * end condition. This "put" will cause the proper
+                * teardown of the viewer stream.
+                */
+               viewer_stream_put(vstream);
+       }
+
+       viewer_session_detach(vsession, session);
+}
+
 void viewer_session_close(struct relay_viewer_session *vsession)
 {
        struct relay_session *session;
@@ -112,32 +147,7 @@ void viewer_session_close(struct relay_viewer_session *vsession)
        rcu_read_lock();
        cds_list_for_each_entry_rcu(session,
                        &vsession->session_list, viewer_session_node) {
-               struct lttng_ht_iter iter;
-               struct relay_viewer_stream *vstream;
-
-               /*
-                * TODO: improvement: create more efficient list of
-                * vstream per session.
-                */
-               cds_lfht_for_each_entry(viewer_streams_ht->ht, &iter.iter,
-                               vstream, stream_n.node) {
-                       if (!viewer_stream_get(vstream)) {
-                               continue;
-                       }
-                       if (vstream->stream->trace->session != session) {
-                               viewer_stream_put(vstream);
-                               continue;
-                       }
-                       /* Put local reference. */
-                       viewer_stream_put(vstream);
-                       /*
-                        * We have reached one of the viewer stream's lifetime
-                        * end condition.
-                        */
-                       viewer_stream_put(vstream);
-               }
-
-               viewer_session_detach(vsession, session);
+               viewer_session_close_one_session(vsession, session);
        }
        rcu_read_unlock();
 }
index 4013b35874e76bca293e132ac0a7854d4da18818..249a483d5f16a05486f9a648f511971983c74729 100644 (file)
@@ -49,5 +49,7 @@ int viewer_session_attach(struct relay_viewer_session *vsession,
                struct relay_session *session);
 int viewer_session_is_attached(struct relay_viewer_session *vsession,
                struct relay_session *session);
+void viewer_session_close_one_session(struct relay_viewer_session *vsession,
+               struct relay_session *session);
 
 #endif /* _VIEWER_SESSION_H */
This page took 0.039776 seconds and 4 git commands to generate.