struct relay_connection {
struct lttcomm_sock *sock;
struct relay_session *session;
+ struct relay_viewer_session *viewer_session;
struct cds_wfq_node qnode;
struct lttng_ht_node_ulong sock_n;
struct rcu_head rcu_node;
health_code_update();
+ if (!conn->viewer_session) {
+ DBG("Client trying to attach before creating a live viewer session");
+ response.status = htobe32(LTTNG_VIEWER_ATTACH_NO_SESSION);
+ goto send_reply;
+ }
+
rcu_read_lock();
session = session_find_by_id(conn->sessions_ht,
be64toh(request.session_id));
return ret;
}
+/*
+ * Create a viewer session.
+ *
+ * Return 0 on success or else a negative value.
+ */
+static
+int viewer_create_session(struct relay_connection *conn)
+{
+ int ret;
+ struct lttng_viewer_create_session_response resp;
+
+ DBG("Viewer create session received");
+
+ resp.status = htobe32(LTTNG_VIEWER_CREATE_SESSION_OK);
+ conn->viewer_session = zmalloc(sizeof(conn->viewer_session));
+ if (!conn->viewer_session) {
+ ERR("Allocation viewer session");
+ resp.status = htobe32(LTTNG_VIEWER_CREATE_SESSION_ERR);
+ goto send_reply;
+ }
+ CDS_INIT_LIST_HEAD(&conn->viewer_session->sessions_head);
+
+send_reply:
+ health_code_update();
+ ret = send_response(conn->sock, &resp, sizeof(resp));
+ 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_GET_NEW_STREAMS:
ret = viewer_get_new_streams(conn);
break;
+ case LTTNG_VIEWER_CREATE_SESSION:
+ ret = viewer_create_session(conn);
+ break;
default:
ERR("Received unknown viewer command (%u)", be32toh(recv_hdr->cmd));
live_relay_unknown_command(conn);
LTTNG_VIEWER_GET_PACKET = 5,
LTTNG_VIEWER_GET_METADATA = 6,
LTTNG_VIEWER_GET_NEW_STREAMS = 7,
+ LTTNG_VIEWER_CREATE_SESSION = 8,
};
enum lttng_viewer_attach_return_code {
LTTNG_VIEWER_ATTACH_UNK = 3, /* The session ID is unknown. */
LTTNG_VIEWER_ATTACH_NOT_LIVE = 4, /* The session is not live. */
LTTNG_VIEWER_ATTACH_SEEK_ERR = 5, /* Seek error. */
+ LTTNG_VIEWER_ATTACH_NO_SESSION = 6, /* No viewer session created. */
};
enum lttng_viewer_next_index_return_code {
LTTNG_VIEWER_NEW_STREAMS_ERR = 3, /* Error. */
};
+enum lttng_viewer_create_session_return_code {
+ LTTNG_VIEWER_CREATE_SESSION_OK = 1,
+ LTTNG_VIEWER_CREATE_SESSION_ERR = 2,
+};
+
struct lttng_viewer_session {
uint64_t id;
uint32_t live_timer;
char stream_list[];
} __attribute__((__packed__));
+struct lttng_viewer_create_session_response {
+ /* enum lttng_viewer_create_session_return_code */
+ uint32_t status;
+} __attribute__((__packed__));
+
#endif /* LTTNG_VIEWER_H */
#include <limits.h>
#include <inttypes.h>
#include <pthread.h>
+#include <urcu/list.h>
#include <common/hashtable/hashtable.h>
* process of sending those streams.
*/
pthread_mutex_t viewer_ready_lock;
+
+ /*
+ * Member of the session list in struct relay_viewer_session.
+ */
+ struct cds_list_head viewer_session_list;
+};
+
+struct relay_viewer_session {
+ struct cds_list_head sessions_head;
};
static inline void session_viewer_attach(struct relay_session *session)