relayd: Implement get_configuration relayd protocol command
[lttng-tools.git] / src / common / relayd / relayd.c
index 8e6b71173052436103275898c4fe5ec02e02c2f5..54fe6734516589bd6c3fe432ae8aaba4eea7846b 100644 (file)
@@ -45,6 +45,17 @@ bool relayd_supports_chunks(const struct lttcomm_relayd_sock *sock)
        return false;
 }
 
+static
+bool relayd_supports_get_configuration(const struct lttcomm_relayd_sock *sock)
+{
+       if (sock->major > 2) {
+               return true;
+       } else if (sock->major == 2 && sock->minor >= 12) {
+               return true;
+       }
+       return false;
+}
+
 /*
  * Send command. Fill up the header and append the data.
  */
@@ -143,7 +154,9 @@ static int relayd_create_session_2_11(struct lttcomm_relayd_sock *rsock,
                const char *base_path, int session_live_timer,
                unsigned int snapshot, uint64_t sessiond_session_id,
                const lttng_uuid sessiond_uuid, const uint64_t *current_chunk_id,
-               time_t creation_time, bool session_name_contains_creation_time)
+               time_t creation_time, bool session_name_contains_creation_time,
+               struct lttcomm_relayd_create_session_reply_2_11 *reply,
+               char *output_path)
 {
        int ret;
        struct lttcomm_relayd_create_session_2_11 *msg = NULL;
@@ -159,7 +172,7 @@ static int relayd_create_session_2_11(struct lttcomm_relayd_sock *rsock,
        /* The three names are sent with a '\0' delimiter between them. */
        session_name_len = strlen(session_name) + 1;
        hostname_len = strlen(hostname) + 1;
-       base_path_len = base_path ? strlen(base_path) + 1 : 0;
+       base_path_len = strlen(base_path) + 1;
 
        msg_length = sizeof(*msg) + session_name_len + hostname_len + base_path_len;
        msg = zmalloc(msg_length);
@@ -189,7 +202,7 @@ static int relayd_create_session_2_11(struct lttcomm_relayd_sock *rsock,
                goto error;
        }
        dst += hostname_len;
-       if (base_path && lttng_strncpy(dst, base_path, base_path_len)) {
+       if (lttng_strncpy(dst, base_path, base_path_len)) {
                ret = -1;
                goto error;
        }
@@ -212,6 +225,24 @@ static int relayd_create_session_2_11(struct lttcomm_relayd_sock *rsock,
        if (ret < 0) {
                goto error;
        }
+       /* Receive response */
+       ret = recv_reply(rsock, reply, sizeof(*reply));
+       if (ret < 0) {
+               goto error;
+       }
+       reply->generic.session_id = be64toh(reply->generic.session_id);
+       reply->generic.ret_code = be32toh(reply->generic.ret_code);
+       reply->output_path_length = be32toh(reply->output_path_length);
+       if (reply->output_path_length >= LTTNG_PATH_MAX) {
+               ERR("Invalid session output path length in reply (%" PRIu32 " bytes) exceeds maximal allowed length (%d bytes)",
+                               reply->output_path_length, LTTNG_PATH_MAX);
+               ret = -1;
+               goto error;
+       }
+       ret = recv_reply(rsock, output_path, reply->output_path_length);
+       if (ret < 0) {
+               goto error;
+       }
 error:
        free(msg);
        return ret;
@@ -222,7 +253,8 @@ error:
  */
 static int relayd_create_session_2_4(struct lttcomm_relayd_sock *rsock,
                const char *session_name, const char *hostname,
-               int session_live_timer, unsigned int snapshot)
+               int session_live_timer, unsigned int snapshot,
+               struct lttcomm_relayd_status_session *reply)
 {
        int ret;
        struct lttcomm_relayd_create_session_2_4 msg;
@@ -245,6 +277,13 @@ static int relayd_create_session_2_4(struct lttcomm_relayd_sock *rsock,
                goto error;
        }
 
+       /* Receive response */
+       ret = recv_reply(rsock, reply, sizeof(*reply));
+       if (ret < 0) {
+               goto error;
+       }
+       reply->session_id = be64toh(reply->session_id);
+       reply->ret_code = be32toh(reply->ret_code);
 error:
        return ret;
 }
@@ -252,7 +291,8 @@ error:
 /*
  * RELAYD_CREATE_SESSION from 2.1 to 2.3.
  */
-static int relayd_create_session_2_1(struct lttcomm_relayd_sock *rsock)
+static int relayd_create_session_2_1(struct lttcomm_relayd_sock *rsock,
+               struct lttcomm_relayd_status_session *reply)
 {
        int ret;
 
@@ -262,6 +302,13 @@ static int relayd_create_session_2_1(struct lttcomm_relayd_sock *rsock)
                goto error;
        }
 
+       /* Receive response */
+       ret = recv_reply(rsock, reply, sizeof(*reply));
+       if (ret < 0) {
+               goto error;
+       }
+       reply->session_id = be64toh(reply->session_id);
+       reply->ret_code = be32toh(reply->ret_code);
 error:
        return ret;
 }
@@ -280,10 +327,11 @@ int relayd_create_session(struct lttcomm_relayd_sock *rsock,
                unsigned int snapshot, uint64_t sessiond_session_id,
                const lttng_uuid sessiond_uuid,
                const uint64_t *current_chunk_id,
-               time_t creation_time, bool session_name_contains_creation_time)
+               time_t creation_time, bool session_name_contains_creation_time,
+               char *output_path)
 {
        int ret;
-       struct lttcomm_relayd_status_session reply;
+       struct lttcomm_relayd_create_session_reply_2_11 reply = {};
 
        assert(rsock);
        assert(relayd_session_id);
@@ -292,44 +340,38 @@ int relayd_create_session(struct lttcomm_relayd_sock *rsock,
 
        if (rsock->minor < 4) {
                /* From 2.1 to 2.3 */
-               ret = relayd_create_session_2_1(rsock);
+               ret = relayd_create_session_2_1(rsock, &reply.generic);
        } else if (rsock->minor >= 4 && rsock->minor < 11) {
                /* From 2.4 to 2.10 */
                ret = relayd_create_session_2_4(rsock, session_name,
-                               hostname, session_live_timer, snapshot);
+                               hostname, session_live_timer, snapshot,
+                               &reply.generic);
        } else {
                /* From 2.11 to ... */
                ret = relayd_create_session_2_11(rsock, session_name,
                                hostname, base_path, session_live_timer, snapshot,
                                sessiond_session_id, sessiond_uuid,
                                current_chunk_id, creation_time,
-                               session_name_contains_creation_time);
-       }
-
-       if (ret < 0) {
-               goto error;
+                               session_name_contains_creation_time,
+                               &reply, output_path);
        }
 
-       /* Receive response */
-       ret = recv_reply(rsock, (void *) &reply, sizeof(reply));
        if (ret < 0) {
                goto error;
        }
 
-       reply.session_id = be64toh(reply.session_id);
-       reply.ret_code = be32toh(reply.ret_code);
-
        /* Return session id or negative ret code. */
-       if (reply.ret_code != LTTNG_OK) {
+       if (reply.generic.ret_code != LTTNG_OK) {
                ret = -1;
-               ERR("Relayd create session replied error %d", reply.ret_code);
+               ERR("Relayd create session replied error %d",
+                       reply.generic.ret_code);
                goto error;
        } else {
                ret = 0;
-               *relayd_session_id = reply.session_id;
+               *relayd_session_id = reply.generic.session_id;
        }
 
-       DBG("Relayd session created with id %" PRIu64, reply.session_id);
+       DBG("Relayd session created with id %" PRIu64, reply.generic.session_id);
 
 error:
        return ret;
@@ -460,21 +502,37 @@ error:
  * On success return 0 else return ret_code negative value.
  */
 int relayd_add_stream(struct lttcomm_relayd_sock *rsock, const char *channel_name,
-               const char *pathname, uint64_t *stream_id,
+               const char *domain_name, const char *_pathname, uint64_t *stream_id,
                uint64_t tracefile_size, uint64_t tracefile_count,
                struct lttng_trace_chunk *trace_chunk)
 {
        int ret;
        struct lttcomm_relayd_status_stream reply;
+       char pathname[RELAYD_COMM_LTTNG_PATH_MAX];
+       char *separator;
 
        /* Code flow error. Safety net. */
        assert(rsock);
        assert(channel_name);
-       assert(pathname);
+       assert(domain_name);
+       assert(_pathname);
        assert(trace_chunk);
 
        DBG("Relayd adding stream for channel name %s", channel_name);
 
+       if (_pathname[0] == '\0') {
+               separator = "";
+       } else {
+               separator = "/";
+       }
+       ret = snprintf(pathname, RELAYD_COMM_LTTNG_PATH_MAX, "%s%s%s",
+                       domain_name, separator, _pathname);
+       if (ret <= 0 || ret >= RELAYD_COMM_LTTNG_PATH_MAX) {
+               ERR("stream path too long.");
+               ret = -1;
+               goto error;
+       }
+
        /* Compat with relayd 2.1 */
        if (rsock->minor == 1) {
                /* For 2.1 */
@@ -1342,12 +1400,13 @@ end:
 }
 
 int relayd_close_trace_chunk(struct lttcomm_relayd_sock *sock,
-               struct lttng_trace_chunk *chunk)
+               struct lttng_trace_chunk *chunk,
+               char *path)
 {
        int ret = 0;
        enum lttng_trace_chunk_status status;
        struct lttcomm_relayd_close_trace_chunk msg = {};
-       struct lttcomm_relayd_generic_reply reply = {};
+       struct lttcomm_relayd_close_trace_chunk_reply reply = {};
        uint64_t chunk_id;
        time_t close_timestamp;
        LTTNG_OPTIONAL(enum lttng_trace_chunk_command_type) close_command = {};
@@ -1407,11 +1466,29 @@ int relayd_close_trace_chunk(struct lttcomm_relayd_sock *sock,
                goto end;
        }
 
-       reply.ret_code = be32toh(reply.ret_code);
-       if (reply.ret_code != LTTNG_OK) {
+       reply.path_length = be32toh(reply.path_length);
+       if (reply.path_length >= LTTNG_PATH_MAX) {
+               ERR("Chunk path too long");
+               ret = -1;
+               goto end;
+       }
+
+       ret = recv_reply(sock, path, reply.path_length);
+       if (ret < 0) {
+               ERR("Failed to receive relay daemon trace chunk close command reply");
+               goto end;
+       }
+       if (path[reply.path_length - 1] != '\0') {
+               ERR("Invalid trace chunk path returned by relay daemon (not null-terminated)");
+               ret = -1;
+               goto end;
+       }
+
+       reply.generic.ret_code = be32toh(reply.generic.ret_code);
+       if (reply.generic.ret_code != LTTNG_OK) {
                ret = -1;
                ERR("Relayd trace chunk close replied error %d",
-                               reply.ret_code);
+                               reply.generic.ret_code);
        } else {
                ret = 0;
                DBG("Relayd successfully closed trace chunk: chunk_id = %" PRIu64,
@@ -1430,6 +1507,8 @@ int relayd_trace_chunk_exists(struct lttcomm_relayd_sock *sock,
 
        if (!relayd_supports_chunks(sock)) {
                DBG("Refusing to check for trace chunk existence: relayd does not support chunks");
+               /* The chunk will never exist */
+               *chunk_exists = false;
                goto end;
        }
 
@@ -1465,3 +1544,54 @@ int relayd_trace_chunk_exists(struct lttcomm_relayd_sock *sock,
 end:
        return ret;
 }
+
+int relayd_get_configuration(struct lttcomm_relayd_sock *sock,
+               uint64_t query_flags,
+               uint64_t *result_flags)
+{
+       int ret = 0;
+       struct lttcomm_relayd_get_configuration msg = (typeof(msg)) {
+               .query_flags = htobe64(query_flags),
+       };
+       struct lttcomm_relayd_get_configuration_reply reply = {};
+
+       if (!relayd_supports_get_configuration(sock)) {
+               DBG("Refusing to get relayd configuration (unsupported by relayd)");
+               if (query_flags) {
+                       ret = -1;
+                       goto end;
+               }
+               *result_flags = 0;
+               goto end;
+       }
+
+       ret = send_command(sock, RELAYD_GET_CONFIGURATION, &msg, sizeof(msg),
+                       0);
+       if (ret < 0) {
+               ERR("Failed to send get configuration command to relay daemon");
+               goto end;
+       }
+
+       ret = recv_reply(sock, &reply, sizeof(reply));
+       if (ret < 0) {
+               ERR("Failed to receive relay daemon get configuration command reply");
+               goto end;
+       }
+
+       reply.generic.ret_code = be32toh(reply.generic.ret_code);
+       if (reply.generic.ret_code != LTTNG_OK) {
+               ret = -1;
+               ERR("Relayd get configuration replied error %d",
+                               reply.generic.ret_code);
+       } else {
+               reply.relayd_configuration_flags =
+                       be64toh(reply.relayd_configuration_flags);
+               ret = 0;
+               DBG("Relayd successfully got configuration: query_flags = %" PRIu64
+                               ", results_flags = %" PRIu64, query_flags,
+                               reply.relayd_configuration_flags);
+               *result_flags = reply.relayd_configuration_flags;
+       }
+end:
+       return ret;
+}
This page took 0.029341 seconds and 5 git commands to generate.