Save/load: support session trace format
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Tue, 26 Apr 2022 20:49:38 +0000 (16:49 -0400)
committerJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Fri, 19 Aug 2022 16:08:08 +0000 (12:08 -0400)
Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Change-Id: I45d4e617a73f5b3c6d9cd56c03bdcc5cef05f36c

14 files changed:
include/lttng/trace-format-descriptor.h
src/bin/lttng-sessiond/client.cpp
src/bin/lttng-sessiond/cmd.cpp
src/bin/lttng-sessiond/cmd.hpp
src/bin/lttng-sessiond/save.cpp
src/bin/lttng/commands/create.cpp
src/bin/lttng/utils.cpp
src/common/config/session-config.cpp
src/common/relayd/relayd.cpp
src/common/session.xsd
src/common/sessiond-comm/relayd.hpp
src/common/sessiond-comm/sessiond-comm.hpp
src/lib/lttng-ctl/liblttng-ctl.sym
src/lib/lttng-ctl/lttng-ctl.cpp

index ade822582e3cb83dacaa34dffd720ef519aeb160..99cc94b04ba28cf0ad6c111cab96bd5ecad74bd2 100644 (file)
@@ -9,6 +9,8 @@
 #define LTTNG_TRACE_FORMAT_DESCRIPTOR_H
 
 #include <inttypes.h>
+#include <lttng/domain.h>
+#include <lttng/lttng-error.h>
 #include <lttng/lttng-export.h>
 
 #ifdef __cplusplus
@@ -16,6 +18,7 @@ extern "C" {
 #endif
 
 struct lttng_trace_format_descriptor;
+enum lttng_domain_type;
 
 enum lttng_trace_format_descriptor_status {
        LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID = -1,
@@ -49,6 +52,30 @@ LTTNG_EXPORT extern enum lttng_trace_format_descriptor_status lttng_trace_format
 
 LTTNG_EXPORT void lttng_trace_format_descriptor_destroy(
                struct lttng_trace_format_descriptor *descriptor);
+/*
+ * Check if the passed trace format is supported for the passed domain.
+ */
+LTTNG_EXPORT extern enum lttng_error_code lttng_domain_supports_trace_format(
+               const struct lttng_endpoint *session_daemon_endpoint,
+               enum lttng_domain_type domain_type,
+               const struct lttng_trace_format_descriptor *trace_format_descriptor);
+
+/*
+ * For network destinations targeting a relay daemon, the session daemon will
+ * establish a connection to check for the capability at the time of the call.
+ * Note that the relay daemon at the destination address may be replaced by
+ * the time tracing starts.
+ *
+ * When destination url is a network destination (relayd), the following
+ * URL format is expected:
+ *  NETPROTO://(HOST | IPADDR)[:CTRLPORT[:DATAPORT]][/TRACEPATH]
+ *
+ * Always returns LTTNG_OK for local destinations.
+ */
+LTTNG_EXPORT extern enum lttng_error_code lttng_destination_supports_trace_format(
+               const struct lttng_endpoint *session_daemon_endpoint,
+               const char *destination_url,
+               const struct lttng_trace_format_descriptor *trace_format_descriptor);
 
 #ifdef __cplusplus
 }
index 3c4ea1b772110c931b38459f15023c2dbb62f7c0..0aaf2c9745667c5a6c1e7224f8a63822ff31d772 100644 (file)
@@ -1009,6 +1009,9 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock,
        case LTTNG_EXECUTE_ERROR_QUERY:
                need_domain = false;
                break;
+       case LTTNG_EXECUTE_TRACE_FORMAT_SUPPORT_QUERY:
+               need_domain = cmd_ctx->lsm.u.trace_format_support_query.query_type == 0;
+               break;
        default:
                need_domain = true;
        }
@@ -1018,6 +1021,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock,
        case LTTNG_REGISTER_TRIGGER:
        case LTTNG_UNREGISTER_TRIGGER:
        case LTTNG_EXECUTE_ERROR_QUERY:
+       case LTTNG_EXECUTE_TRACE_FORMAT_SUPPORT_QUERY:
                need_consumerd = false;
                break;
        default:
@@ -1090,6 +1094,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock,
        case LTTNG_UNREGISTER_TRIGGER:
        case LTTNG_LIST_TRIGGERS:
        case LTTNG_EXECUTE_ERROR_QUERY:
+       case LTTNG_EXECUTE_TRACE_FORMAT_SUPPORT_QUERY:
                need_tracing_session = false;
                break;
        default:
@@ -2331,6 +2336,11 @@ skip_domain:
 
                break;
        }
+       case LTTNG_EXECUTE_TRACE_FORMAT_SUPPORT_QUERY:
+       {
+               ret = cmd_execute_trace_format_support_query(*cmd_ctx, *sock, *sock_error);
+               break;
+       }
        default:
                ret = LTTNG_ERR_UND;
                break;
index 214085c55a29bd11c4f548db101eb64e6c488989..94edb6368637eb625497819ac27eff4e5d246221 100644 (file)
@@ -951,7 +951,9 @@ static lttng_error_code send_consumer_relayd_sockets(const ltt_session& session,
                consumer->relay_major_version = control_sock->major;
                consumer->relay_minor_version = control_sock->minor;
 
-               ret = relayd_get_configuration(control_sock, 0, result_flags, nullptr);
+               ret = relayd_get_configuration(control_sock,
+                               LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT,
+                               result_flags, &supported_trace_format);
                if (ret < 0) {
                        ERR("Unable to get relayd configuration");
                        status = LTTNG_ERR_RELAYD_CONNECT_FAIL;
@@ -6063,6 +6065,132 @@ end:
        return ret;
 }
 
+enum lttng_error_code cmd_execute_trace_format_support_query(
+               struct command_ctx& cmd_ctx, int sock, int& sock_error)
+{
+       int ret;
+       enum lttng_error_code ret_code;
+       struct lttng_payload query_payload;
+       size_t payload_len, offset = 0;
+       ssize_t sock_recv_len, consumed;
+
+       lttng::trace_format_descriptor::uptr trace_format;
+
+       lttng_payload_init(&query_payload);
+
+       /* Receive the payload */
+       payload_len = (size_t) cmd_ctx.lsm.u.trace_format_support_query.trace_format_length +
+                       cmd_ctx.lsm.u.trace_format_support_query.type_payload_length;
+       ret = lttng_dynamic_buffer_set_size(&query_payload.buffer, payload_len);
+       if (ret) {
+               ret_code = LTTNG_ERR_NOMEM;
+       }
+
+       sock_recv_len = lttcomm_recv_unix_sock(sock, query_payload.buffer.data, payload_len);
+       if (sock_recv_len < 0 || sock_recv_len != payload_len) {
+               ERR("Failed to receive error query in command payload");
+               sock_error = 1;
+               ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+               goto end;
+       }
+
+       /* Receive fds, if any. */
+       if (cmd_ctx.lsm.fd_count > 0) {
+               sock_recv_len = lttcomm_recv_payload_fds_unix_sock(
+                               sock, cmd_ctx.lsm.fd_count, &query_payload);
+               if (sock_recv_len > 0 && sock_recv_len != cmd_ctx.lsm.fd_count * sizeof(int)) {
+                       ERR("Failed to receive all file descriptors for error query in command payload: expected fd count = %u, ret = %d",
+                                       cmd_ctx.lsm.fd_count, (int) ret);
+                       ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+                       sock_error = 1;
+                       goto end;
+               } else if (sock_recv_len <= 0) {
+                       ERR("Failed to receive file descriptors for error query in command payload: expected fd count = %u, ret = %d",
+                                       cmd_ctx.lsm.fd_count, (int) ret);
+                       ret_code = LTTNG_ERR_FATAL;
+                       sock_error = 1;
+                       goto end;
+               }
+       }
+
+       /* Deserialize trace_format_descriptor. */
+       {
+               struct lttng_payload_view view =
+                               lttng_payload_view_from_payload(&query_payload, offset, -1);
+               if (!lttng_payload_view_is_valid(&view)) {
+                       ret = LTTNG_ERR_INVALID_PROTOCOL;
+                       goto end;
+               }
+
+               consumed = lttng::trace_format_descriptor::create_from_payload(&view, trace_format);
+
+               if (consumed != cmd_ctx.lsm.u.trace_format_support_query.trace_format_length) {
+                       ERR("Invalid trace format descriptor received as part of command payload");
+                       ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+                       goto end;
+               }
+               offset += consumed;
+       }
+
+       switch (cmd_ctx.lsm.u.trace_format_support_query.query_type) {
+       case 0:
+       {
+               if (cmd_ctx.lsm.domain.type != LTTNG_DOMAIN_KERNEL) {
+                       /* UST supports all trace format*/
+                       ret_code = LTTNG_OK;
+                       goto end;
+               }
+               ret_code = kernel_domain_check_trace_format_requirements(*trace_format);
+               break;
+       }
+       case 1:
+       {
+               struct lttcomm_relayd_sock *relay_sock = nullptr;
+               struct lttng_uri uri;
+               uint64_t result_flags = 0;
+               uint64_t supported_trace_format = 0;
+               struct lttng_payload_view view = lttng_payload_view_from_payload(&query_payload,
+                               offset,
+                               cmd_ctx.lsm.u.trace_format_support_query.type_payload_length);
+               if (!lttng_payload_view_is_valid(&view)) {
+                       ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+                       goto end;
+               }
+
+               memcpy(&uri, view.buffer.data, sizeof(uri));
+               ret_code = create_connect_relayd(&uri, &relay_sock);
+               if (ret_code != LTTNG_OK) {
+                       goto end;
+               }
+               LTTNG_ASSERT(sock);
+
+               ret_code = relayd_get_configuration(relay_sock,
+                               LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT,
+                               result_flags, &supported_trace_format);
+               if (ret_code != LTTNG_OK) {
+                       goto end;
+               }
+
+               if (!(supported_trace_format & trace_format->relayd_type())) {
+                       ERR("Relayd does not support the requested trace format");
+                       ret_code = LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_RELAY_DAEMON;
+                       goto end;
+               }
+
+               ret_code = LTTNG_OK;
+               break;
+       }
+       default:
+       {
+               ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+               break;
+       }
+       }
+end:
+       lttng_payload_reset(&query_payload);
+       return ret_code;
+}
+
 /* Wait for a given path to be removed before continuing. */
 static enum lttng_error_code wait_on_path(void *path_data)
 {
index 4dd877be7a3d3cc1a958c75eb1110d86073bb506..78d4f9cdeea4fc35fc92f700029e48476063c075 100644 (file)
@@ -161,6 +161,9 @@ enum lttng_error_code cmd_execute_error_query(const struct lttng_credentials *cm
                struct lttng_error_query_results **_results,
                struct notification_thread_handle *notification_thread);
 
+enum lttng_error_code cmd_execute_trace_format_support_query(
+               struct command_ctx& cmd_ctx, int sock, int& sock_error);
+
 int cmd_rotate_session(struct ltt_session *session,
                struct lttng_rotate_session_return *rotate_return,
                bool quiet_rotation,
index 5db70faef47e98f0c865e65e69916365beab3a89..825ad54136eee4c3384b3e3552e9a9a1f4a795d5 100644 (file)
@@ -2752,6 +2752,11 @@ int save_session(struct ltt_session *session,
                }
        }
 
+       ret = (int) session->trace_format->config_serialize(writer);
+       if (ret != LTTNG_OK) {
+               goto end;
+       }
+
        ret = save_domains(writer, session);
        if (ret != LTTNG_OK) {
                goto end;
index 68a1020a892ef53cdb8379fc5266fcccc8b60b2a..5841013d646814bc57c77bcafca579e74cae494f 100644 (file)
@@ -307,6 +307,7 @@ struct lttng_session_descriptor *create_session_descriptor(void)
                        goto error;
                }
        }
+
 end:
        free(uris);
        return descriptor;
@@ -316,6 +317,77 @@ error:
        goto end;
 }
 
+static int trace_format_check(struct lttng_session_descriptor& descriptor)
+{
+       int ret = 0;
+       enum lttng_error_code ret_code;
+       const lttng_trace_format_descriptor *trace_format_descriptor = nullptr;
+       enum lttng_session_descriptor_status status;
+       std::string destination;
+
+       status = lttng_session_descriptor_get_trace_format_descriptor(
+                       &descriptor, &trace_format_descriptor);
+       if (status != LTTNG_SESSION_DESCRIPTOR_STATUS_OK) {
+               ret_code = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       /*
+        * Only check kernel domain since only the kernel tracer can lag behind
+        * in term of feature.
+        */
+
+       ret_code = lttng_domain_supports_trace_format(lttng_session_daemon_command_endpoint,
+                       LTTNG_DOMAIN_KERNEL, trace_format_descriptor);
+       if (ret_code == LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_KERNEL_TRACER) {
+               WARN("%s", lttng_strerror(ret_code));
+       } else if (ret_code == LTTNG_ERR_KERN_NA || ret_code == LTTNG_ERR_NEED_ROOT_SESSIOND) {
+               /*
+                * Not an error, kernel tracers is simply not available at that
+                * time. Next operation will fail as necessary.
+                */
+               DBG("Kernel tracer not available for trace format support check");
+       } else if (ret_code != LTTNG_OK) {
+               ERR("Failed to validate trace format support: %s", lttng_strerror(ret_code));
+               ret = -1;
+               goto end;
+       }
+
+       if (opt_output_path) {
+               char *tmp = utils_expand_path(opt_output_path);
+               if (!tmp) {
+                       ret = -1;
+                       goto end;
+               }
+               destination = tmp;
+               free(tmp);
+       } else if (opt_url || opt_ctrl_url) {
+               destination = opt_ctrl_url ? opt_ctrl_url : opt_url;
+       } else if (opt_live_timer) {
+               destination = "tcp://127.0.0.1";
+       }
+
+       if (!destination.empty()) {
+               ret_code = lttng_destination_supports_trace_format(
+                               lttng_session_daemon_command_endpoint, destination.c_str(),
+                               trace_format_descriptor);
+               if (ret_code == LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_RELAY_DAEMON) {
+                       WARN("%s", lttng_strerror(ret_code));
+               } else if (ret_code == LTTNG_ERR_RELAYD_CONNECT_FAIL) {
+                       DBG("Could not validate trace format support: %s",
+                                       lttng_strerror(ret_code));
+               } else if (ret_code != LTTNG_OK) {
+                       ERR("Failed to validate trace format support: %s",
+                                       lttng_strerror(ret_code));
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
 /*
  *  Create a tracing session.
  *  If no name is specified, a default name is generated.
@@ -375,6 +447,7 @@ static int create_session(void)
                ret = CMD_ERROR;
                goto error;
        }
+
        ret_code = lttng_create_session_ext(session_descriptor);
        if (ret_code != LTTNG_OK) {
                ERR("%s", lttng_strerror(-ret_code));
@@ -382,8 +455,14 @@ static int create_session(void)
                goto error;
        }
 
+       ret = trace_format_check(*session_descriptor);
+       if (ret < 0) {
+               ret = CMD_ERROR;
+               goto error;
+       }
+
        descriptor_status = lttng_session_descriptor_get_session_name(
-               session_descriptor, &created_session_name);
+                       session_descriptor, &created_session_name);
        if (descriptor_status != LTTNG_SESSION_DESCRIPTOR_STATUS_OK) {
                ERR("Failed to obtain created session name");
                ret = CMD_ERROR;
index 9a9f39bf2529b1cd6328f5052b73672715d12663..fd839ecbfed9bf3756fbd74df34c25409bdb0e36 100644 (file)
@@ -6,15 +6,16 @@
  */
 
 #define _LGPL_SOURCE
-#include <stdlib.h>
+#include <arpa/inet.h>
 #include <ctype.h>
+#include <inttypes.h>
 #include <limits.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <signal.h>
 #include <netinet/in.h>
-#include <arpa/inet.h>
-#include <inttypes.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include <common/error.hpp>
@@ -348,16 +349,51 @@ int spawn_relayd(const char *pathname, int port)
                 * Spawn session daemon and tell
                 * it to signal us when ready.
                 */
-               execlp(pathname, "lttng-relayd", "-L", url, NULL);
+               execlp(pathname, "lttng-relayd", "-L", url, "--daemonize", NULL);
                /* execlp only returns if error happened */
                if (errno == ENOENT) {
                        ERR("No relayd found. Use --relayd-path.");
                } else {
                        PERROR("execlp");
                }
-               kill(getppid(), SIGTERM);       /* wake parent */
+               kill(getppid(), SIGTERM); /* wake parent */
                exit(EXIT_FAILURE);
        } else if (pid > 0) {
+               /*
+                * In daemon mode (--daemonize), lttng-relayd only exits when
+                * it's ready to accept commands.
+                */
+               for (;;) {
+                       int status;
+                       pid_t wait_pid_ret = waitpid(pid, &status, 0);
+
+                       if (wait_pid_ret < 0) {
+                               if (errno == EINTR) {
+                                       continue;
+                               }
+                               PERROR("waitpid");
+                               ret = -errno;
+                               goto end;
+                       }
+
+                       if (WIFSIGNALED(status)) {
+                               ERR("Relay daemon was killed by signal %d", WTERMSIG(status));
+                               ret = -1;
+                               goto end;
+                       } else if (WIFEXITED(status)) {
+                               DBG("Relay daemon terminated normally (exit status: %d)",
+                                               WEXITSTATUS(status));
+
+                               if (WEXITSTATUS(status) != 0) {
+                                       ERR("Relay daemon terminated with an error (exit status: %d)",
+                                                       WEXITSTATUS(status));
+                                       ret = -1;
+                                       goto end;
+                               }
+                               break;
+                       }
+               }
+
                goto end;
        } else {
                PERROR("fork");
index f9d9d0eca558973a1e649bd4281d2572f9795bd2..351c7f921db7fe2389fd00f685a095c49d6b9979 100644 (file)
@@ -1154,9 +1154,10 @@ end:
        return ret;
 }
 
-static
-int create_snapshot_session(const char *session_name, xmlNodePtr output_node,
-               const struct config_load_session_override_attr *overrides)
+static int create_snapshot_session(const char *session_name,
+               xmlNodePtr output_node,
+               const struct config_load_session_override_attr *overrides,
+               const struct lttng_trace_format_descriptor *trace_format_descriptor)
 {
        int ret;
        enum lttng_error_code ret_code;
@@ -1178,6 +1179,16 @@ int create_snapshot_session(const char *session_name, xmlNodePtr output_node,
                goto end;
        }
 
+       if (trace_format_descriptor != nullptr) {
+               enum lttng_session_descriptor_status s_status;
+               s_status = lttng_session_descriptor_set_trace_format_descriptor(
+                               session_descriptor, trace_format_descriptor);
+               if (s_status != LTTNG_SESSION_DESCRIPTOR_STATUS_OK) {
+                       ret = -LTTNG_ERR_FATAL;
+                       goto end;
+               }
+       }
+
        ret_code = lttng_create_session_ext(session_descriptor);
        if (ret_code != LTTNG_OK) {
                ret = -ret_code;
@@ -1313,11 +1324,11 @@ end:
        return ret;
 }
 
-static
-int create_session(const char *name,
-       xmlNodePtr output_node,
-       uint64_t live_timer_interval,
-       const struct config_load_session_override_attr *overrides)
+static int create_session(const char *name,
+               xmlNodePtr output_node,
+               uint64_t live_timer_interval,
+               const struct config_load_session_override_attr *overrides,
+               const struct lttng_trace_format_descriptor *trace_format_descriptor)
 {
        int ret = 0;
        enum lttng_error_code ret_code;
@@ -1408,6 +1419,16 @@ int create_session(const char *name,
                goto end;
        }
 
+       if (trace_format_descriptor != nullptr) {
+               enum lttng_session_descriptor_status s_status;
+               s_status = lttng_session_descriptor_set_trace_format_descriptor(
+                               session_descriptor, trace_format_descriptor);
+               if (s_status != LTTNG_SESSION_DESCRIPTOR_STATUS_OK) {
+                       ret = -LTTNG_ERR_FATAL;
+                       goto end;
+               }
+       }
+
        ret_code = lttng_create_session_ext(session_descriptor);
        if (ret_code != LTTNG_OK) {
                ret = -ret_code;
@@ -3261,6 +3282,49 @@ end:
        return ret;
 }
 
+/* TODO: this could most probably be moved to a similar scheme to create_from_buffer/payload for the
+ * lttng::trace_format_descriptor object */
+static int process_trace_format_descriptor_node(xmlNodePtr trace_format_descriptor_node,
+               struct lttng_trace_format_descriptor **descriptor)
+{
+       int ret;
+       xmlNodePtr node;
+       struct lttng_trace_format_descriptor *local_descriptor = nullptr;
+       struct lttng_trace_format_descriptor *(*constructor)(void) = nullptr;
+
+       for (node = xmlFirstElementChild(trace_format_descriptor_node); node;
+                       node = xmlNextElementSibling(node)) {
+               if (!strcmp((const char *) node->name, config_element_session_trace_format_ctf1)) {
+                       constructor = lttng_trace_format_ctf_1_descriptor_create;
+                       break;
+               } else if (!strcmp((const char *) node->name,
+                                          config_element_session_trace_format_ctf2)) {
+                       constructor = lttng_trace_format_ctf_2_descriptor_create;
+                       break;
+               }
+       }
+
+       if (constructor == nullptr) {
+               ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
+               goto end;
+       }
+
+       local_descriptor = constructor();
+
+       if (local_descriptor == nullptr) {
+               ret = -LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       *descriptor = local_descriptor;
+       local_descriptor = nullptr;
+       ret = 0;
+
+end:
+       lttng_trace_format_descriptor_destroy(local_descriptor);
+       return ret;
+}
+
 static
 int process_session_node(xmlNodePtr session_node, const char *session_name,
                int overwrite,
@@ -3281,6 +3345,7 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
        struct lttng_domain *jul_domain = NULL;
        struct lttng_domain *log4j_domain = NULL;
        struct lttng_domain *python_domain = NULL;
+       struct lttng_trace_format_descriptor *trace_format_descriptor = nullptr;
 
        for (node = xmlFirstElementChild(session_node); node;
                node = xmlNextElementSibling(node)) {
@@ -3327,6 +3392,13 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
                        }
 
                        shm_path = node_content;
+               } else if (!trace_format_descriptor &&
+                               !strcmp((const char *) node->name,
+                                               config_element_session_trace_format)) {
+                       ret = process_trace_format_descriptor_node(node, &trace_format_descriptor);
+                       if (ret) {
+                               goto error;
+                       }
                } else {
                        /*
                         * attributes, snapshot_mode, live_timer_interval, rotation_size,
@@ -3482,16 +3554,16 @@ domain_init_error:
 
        /* Create session type depending on output type */
        if (snapshot_mode && snapshot_mode != -1) {
-               ret = create_snapshot_session((const char *) name, output_node,
-                               overrides);
+               ret = create_snapshot_session((const char *) name, output_node, overrides,
+                               trace_format_descriptor);
        } else if (live_timer_interval &&
                live_timer_interval != UINT64_MAX) {
-               ret = create_session((const char *) name,
-                               output_node, live_timer_interval, overrides);
+               ret = create_session((const char *) name, output_node, live_timer_interval,
+                               overrides, trace_format_descriptor);
        } else {
                /* regular session */
-               ret = create_session((const char *) name,
-                               output_node, UINT64_MAX, overrides);
+               ret = create_session((const char *) name, output_node, UINT64_MAX, overrides,
+                               trace_format_descriptor);
        }
        if (ret) {
                goto error;
@@ -3543,6 +3615,7 @@ end:
        }
 
 error:
+       lttng_trace_format_descriptor_destroy(trace_format_descriptor);
        free(kernel_domain);
        free(ust_domain);
        free(jul_domain);
index 9f444d6e982cbfe0c95d3fd5274e7d276cb5e63c..20a8aecba51a5dd49df149bd0e47c740201ccef9 100644 (file)
@@ -103,7 +103,6 @@ static int send_command(struct lttcomm_relayd_sock *rsock,
        if (ret < 0) {
                PERROR("Failed to send command %s of size %" PRIu64,
                                lttcomm_relayd_command_str(cmd), buf_size);
-       ret = rsock->sock.ops->sendmsg(&rsock->sock, buf, buf_size, flags);
                ret = -errno;
                goto error;
        }
index 986fb2dda175a8df19f3cec1be20264ab92e4052..4248f8e6b384e2332ea046208e4a03d7ca8c4752 100644 (file)
@@ -512,6 +512,30 @@ by its signed 32-bit representation when converted to msec.
        </xs:choice>
 </xs:complexType>
 
+       <!-- Maps to a lttng_event_rule. -->
+       <xs:complexType name="trace_format_descriptor_type">
+               <xs:all>
+                       <xs:element ref="trace_format_descriptor_sub_type" minOccurs="1" />
+               </xs:all>
+       </xs:complexType>
+
+       <!-- Maps to a lttng_trace_format_descriptor subtypes -->
+       <xs:element name="trace_format_descriptor_sub_type" abstract="true"/>
+       <xs:element name="ctf1" type="trace_format_descriptor_ctf1_type" substitutionGroup="trace_format_descriptor_sub_type" />
+       <xs:element name="ctf2" type="trace_format_descriptor_ctf2_type" substitutionGroup="trace_format_descriptor_sub_type" />
+
+       <!-- Maps to a lttng_trace_format_ctf1_descriptor. -->
+       <xs:complexType name="trace_format_descriptor_ctf1_type">
+               <xs:all>
+               </xs:all>
+       </xs:complexType>
+
+       <!-- Maps to a lttng_trace_format_ctf2_descriptor. -->
+       <xs:complexType name="trace_format_descriptor_ctf2_type">
+               <xs:all>
+               </xs:all>
+       </xs:complexType>
+
 <xs:complexType name="session_type">
        <xs:all>
                <xs:element name="name" type="name_type"/>
@@ -520,6 +544,7 @@ by its signed 32-bit representation when converted to msec.
                <xs:element name="started" type="xs:boolean" default="0" minOccurs="0"/>
                <xs:element name="attributes" type="session_attributes_type" minOccurs="0"/>
                <xs:element name="output" type="session_output_type" minOccurs="0"/>
+               <xs:element name="trace_format" type="trace_format_descriptor_type" minOccurs="0" />
        </xs:all>
 </xs:complexType>
 
index 49d3ed1f7ea34f2fb62a9f555f346e54704c2876..d266284cb06fa3ab6b9340130b9eea1db5938714 100644 (file)
@@ -20,7 +20,9 @@
 #include <common/optional.hpp>
 
 #define RELAYD_VERSION_COMM_MAJOR             VERSION_MAJOR
-#define RELAYD_VERSION_COMM_MINOR             VERSION_MINOR
+/* FIXME: remove, SPOOFING VERSION as 2.15 */
+//#define RELAYD_VERSION_COMM_MINOR             VERSION_MINOR
+#define RELAYD_VERSION_COMM_MINOR             15
 
 #define RELAYD_COMM_LTTNG_HOST_NAME_MAX_2_4    64
 #define RELAYD_COMM_LTTNG_NAME_MAX_2_4 255
index f5e55ec34e1e7557fbaf1ded64981a9799c1a44d..2ef6544761fdd7b3595b2fe3984ba05cf9c48c25 100644 (file)
@@ -103,6 +103,7 @@ enum lttcomm_sessiond_command {
        LTTNG_CLEAR_SESSION                             = 50,
        LTTNG_LIST_TRIGGERS                             = 51,
        LTTNG_EXECUTE_ERROR_QUERY                       = 52,
+       LTTNG_EXECUTE_TRACE_FORMAT_SUPPORT_QUERY        = 53,
 };
 
 static inline
@@ -195,6 +196,8 @@ const char *lttcomm_sessiond_command_str(enum lttcomm_sessiond_command cmd)
                return "LTTNG_LIST_TRIGGERS";
        case LTTNG_EXECUTE_ERROR_QUERY:
                return "LTTNG_EXECUTE_ERROR_QUERY";
+       case LTTNG_EXECUTE_TRACE_FORMAT_SUPPORT_QUERY:
+               return "LTTNG_EXECUTE_TRACE_FORMAT_SUPPORT_QUERY";
        default:
                abort();
        }
@@ -535,6 +538,12 @@ struct lttcomm_session_msg {
                        uint64_t session_descriptor_size;
                        /* An lttng_session_descriptor follows. */
                } LTTNG_PACKED create_session;
+               struct {
+                       uint32_t query_type;
+                       uint32_t type_payload_length;
+                       uint32_t trace_format_length;
+               } LTTNG_PACKED trace_format_support_query;
+
        } u;
        /* Count of fds sent. */
        uint32_t fd_count;
index 1866c4801861fc919d23d5df18346e705da53ad5..5bd03fdcf0560a4007ca15dc085fcf2d4ac0effc 100644 (file)
@@ -192,6 +192,7 @@ lttng_create_session_ext
 lttng_create_session_live
 lttng_create_session_snapshot
 lttng_data_pending
+lttng_destination_supports_trace_format
 lttng_destroy_handle
 lttng_destroy_session
 lttng_destroy_session_ext
@@ -205,6 +206,7 @@ lttng_disable_channel
 lttng_disable_consumer
 lttng_disable_event
 lttng_disable_event_ext
+lttng_domain_supports_trace_format
 lttng_elf_get_sdt_probe_offsets
 lttng_elf_get_symbol_offset
 lttng_enable_channel
index c6b2e2f35a83a463f5db96968c88ed4da68b9154..5c7dc917bbaae2ba55e0cd2d252e7d000eeaaccb 100644 (file)
@@ -3441,3 +3441,182 @@ static void __attribute__((destructor)) lttng_ctl_exit(void)
 {
        free(tracing_group);
 }
+
+LTTNG_EXPORT enum lttng_error_code lttng_domain_supports_trace_format(
+               const struct lttng_endpoint *session_daemon_endpoint,
+               enum lttng_domain_type domain_type,
+               const struct lttng_trace_format_descriptor *trace_format_descriptor)
+{
+       int ret;
+       enum lttng_error_code ret_code;
+       struct lttcomm_session_msg lsm = {
+                       .cmd_type = LTTNG_EXECUTE_TRACE_FORMAT_SUPPORT_QUERY,
+                       .session = {},
+                       .domain = {},
+                       .u = {},
+                       .fd_count = 0,
+       };
+       struct lttng_payload message;
+       struct lttng_payload reply;
+       struct lttcomm_session_msg *message_lsm;
+
+       lttng_payload_init(&message);
+       lttng_payload_init(&reply);
+
+       if (!session_daemon_endpoint || !trace_format_descriptor) {
+               ret_code = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       lsm.domain.type = domain_type;
+       lsm.u.trace_format_support_query.query_type = 0;
+       lsm.u.trace_format_support_query.type_payload_length = 0;
+
+       if (session_daemon_endpoint != lttng_session_daemon_command_endpoint) {
+               ret_code = LTTNG_ERR_INVALID_ERROR_QUERY_TARGET;
+               goto end;
+       }
+
+       ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+       if (ret) {
+               ret_code = LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       ret = reinterpret_cast<const lttng::trace_format_descriptor *>(trace_format_descriptor)
+                             ->serialize(&message);
+       if (ret) {
+               ret_code = LTTNG_ERR_UNK;
+               goto end;
+       }
+
+       message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
+       message_lsm->u.trace_format_support_query.trace_format_length =
+                       (uint32_t) message.buffer.size - sizeof(lsm);
+
+       {
+               struct lttng_payload_view message_view =
+                               lttng_payload_view_from_payload(&message, 0, -1);
+
+               message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(&message_view);
+               ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
+               if (ret < 0) {
+                       ret_code = (lttng_error_code) -ret;
+                       goto end;
+               }
+               if (ret != 0) {
+                       /* No payload expected */
+                       ret = LTTNG_ERR_INVALID_PROTOCOL;
+               }
+       }
+
+       ret_code = LTTNG_OK;
+end:
+       lttng_payload_reset(&message);
+       lttng_payload_reset(&reply);
+       return ret_code;
+}
+
+LTTNG_EXPORT extern enum lttng_error_code lttng_destination_supports_trace_format(
+               const struct lttng_endpoint *session_daemon_endpoint,
+               const char *destination_url,
+               const struct lttng_trace_format_descriptor *trace_format_descriptor)
+{
+       int ret;
+       ssize_t size;
+       enum lttng_error_code ret_code;
+       struct lttcomm_session_msg lsm = {
+                       .cmd_type = LTTNG_EXECUTE_TRACE_FORMAT_SUPPORT_QUERY,
+                       .session = {},
+                       .domain = {},
+                       .u = {},
+                       .fd_count = 0,
+       };
+       struct lttng_payload message;
+       struct lttng_payload reply;
+       struct lttcomm_session_msg *message_lsm;
+       struct lttng_uri *uris = NULL;
+       size_t size_before_payload = 0;
+
+       lttng_payload_init(&message);
+       lttng_payload_init(&reply);
+
+       if (!session_daemon_endpoint || !trace_format_descriptor) {
+               ret_code = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       size = uri_parse_str_urls(destination_url, NULL, &uris);
+       if (size < 1) {
+               ret_code = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       if (uris[0].dtype == LTTNG_DST_PATH) {
+               /* Local output */
+               ret_code = LTTNG_OK;
+               goto end;
+       }
+
+       lsm.u.trace_format_support_query.query_type = 1;
+
+       if (session_daemon_endpoint != lttng_session_daemon_command_endpoint) {
+               ret_code = LTTNG_ERR_INVALID_ERROR_QUERY_TARGET;
+               goto end;
+       }
+
+       ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+       if (ret) {
+               ret_code = LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       size_before_payload = message.buffer.size;
+
+       ret = reinterpret_cast<const lttng::trace_format_descriptor *>(trace_format_descriptor)
+                             ->serialize(&message);
+       if (ret) {
+               ret_code = LTTNG_ERR_UNK;
+               goto end;
+       }
+
+       message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
+       message_lsm->u.trace_format_support_query.trace_format_length =
+                       (uint32_t) message.buffer.size - size_before_payload;
+
+       /* FIXME replace all this with good old serialization of sub query type
+        * object. (internal) */
+       size_before_payload = message.buffer.size;
+       ret = lttng_dynamic_buffer_append(&message.buffer, &uris[0], sizeof(*uris));
+       if (ret) {
+               ret_code = LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
+       message_lsm->u.trace_format_support_query.type_payload_length =
+                       (uint32_t) message.buffer.size - size_before_payload;
+
+       {
+               struct lttng_payload_view message_view =
+                               lttng_payload_view_from_payload(&message, 0, -1);
+
+               message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(&message_view);
+               ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
+               if (ret < 0) {
+                       ret_code = (lttng_error_code) -ret;
+                       goto end;
+               }
+               if (ret != 0) {
+                       /* No payload expected */
+                       ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+                       goto end;
+               }
+       }
+
+       ret_code = LTTNG_OK;
+end:
+       lttng_payload_reset(&message);
+       lttng_payload_reset(&reply);
+       return ret_code;
+}
This page took 0.052523 seconds and 5 git commands to generate.