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
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));
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 {
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;
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 */
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;
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();
}
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 */