Implement the relayd live features
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index 55bd767b57875fd7d6aedc1c803cf060fb4aff57..85f396f1c0e2329938e50690d919309f239bef6c 100644 (file)
@@ -462,9 +462,6 @@ static int init_kernel_tracing(struct ltt_kernel_session *session)
        if (session->consumer_fds_sent == 0 && session->consumer != NULL) {
                cds_lfht_for_each_entry(session->consumer->socks->ht, &iter.iter,
                                socket, node.node) {
-                       /* Code flow error */
-                       assert(socket->fd >= 0);
-
                        pthread_mutex_lock(socket->lock);
                        ret = kernel_consumer_send_session(socket, session);
                        pthread_mutex_unlock(socket->lock);
@@ -550,7 +547,8 @@ error:
  */
 static int send_consumer_relayd_socket(int domain, unsigned int session_id,
                struct lttng_uri *relayd_uri, struct consumer_output *consumer,
-               struct consumer_socket *consumer_sock)
+               struct consumer_socket *consumer_sock,
+               char *session_name, char *hostname, int session_live_timer)
 {
        int ret;
        struct lttcomm_relayd_sock *rsock = NULL;
@@ -576,7 +574,8 @@ static int send_consumer_relayd_socket(int domain, unsigned int session_id,
 
        /* Send relayd socket to consumer. */
        ret = consumer_send_relayd_socket(consumer_sock, rsock, consumer,
-                       relayd_uri->stype, session_id);
+                       relayd_uri->stype, session_id,
+                       session_name, hostname, session_live_timer);
        if (ret < 0) {
                ret = LTTNG_ERR_ENABLE_CONSUMER_FAIL;
                goto close_sock;
@@ -618,7 +617,8 @@ error:
  * session.
  */
 static int send_consumer_relayd_sockets(int domain, unsigned int session_id,
-               struct consumer_output *consumer, struct consumer_socket *sock)
+               struct consumer_output *consumer, struct consumer_socket *sock,
+               char *session_name, char *hostname, int session_live_timer)
 {
        int ret = LTTNG_OK;
 
@@ -628,7 +628,8 @@ static int send_consumer_relayd_sockets(int domain, unsigned int session_id,
        /* Sending control relayd socket. */
        if (!sock->control_sock_sent) {
                ret = send_consumer_relayd_socket(domain, session_id,
-                               &consumer->dst.net.control, consumer, sock);
+                               &consumer->dst.net.control, consumer, sock,
+                               session_name, hostname, session_live_timer);
                if (ret != LTTNG_OK) {
                        goto error;
                }
@@ -637,7 +638,8 @@ static int send_consumer_relayd_sockets(int domain, unsigned int session_id,
        /* Sending data relayd socket. */
        if (!sock->data_sock_sent) {
                ret = send_consumer_relayd_socket(domain, session_id,
-                               &consumer->dst.net.data, consumer, sock);
+                               &consumer->dst.net.data, consumer, sock,
+                               session_name, hostname, session_live_timer);
                if (ret != LTTNG_OK) {
                        goto error;
                }
@@ -674,12 +676,11 @@ int cmd_setup_relayd(struct ltt_session *session)
                /* For each consumer socket, send relayd sockets */
                cds_lfht_for_each_entry(usess->consumer->socks->ht, &iter.iter,
                                socket, node.node) {
-                       /* Code flow error */
-                       assert(socket->fd >= 0);
-
                        pthread_mutex_lock(socket->lock);
                        ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_UST, session->id,
-                                       usess->consumer, socket);
+                                       usess->consumer, socket,
+                                       session->name, session->hostname,
+                                       session->live_timer);
                        pthread_mutex_unlock(socket->lock);
                        if (ret != LTTNG_OK) {
                                goto error;
@@ -693,12 +694,11 @@ int cmd_setup_relayd(struct ltt_session *session)
                        && ksess->consumer->enabled) {
                cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter,
                                socket, node.node) {
-                       /* Code flow error */
-                       assert(socket->fd >= 0);
-
                        pthread_mutex_lock(socket->lock);
                        ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_KERNEL, session->id,
-                                       ksess->consumer, socket);
+                                       ksess->consumer, socket,
+                                       session->name, session->hostname,
+                                       session->live_timer);
                        pthread_mutex_unlock(socket->lock);
                        if (ret != LTTNG_OK) {
                                goto error;
@@ -868,6 +868,16 @@ int cmd_enable_channel(struct ltt_session *session,
                goto error;
        }
 
+       /*
+        * If the session is a live session, remove the switch timer, the
+        * live timer does the same thing but sends also synchronisation
+        * beacons for inactive streams.
+        */
+       if (session->live_timer > 0) {
+               attr->attr.live_timer_interval = session->live_timer;
+               attr->attr.switch_timer_interval = 0;
+       }
+
        switch (domain->type) {
        case LTTNG_DOMAIN_KERNEL:
        {
@@ -876,7 +886,19 @@ int cmd_enable_channel(struct ltt_session *session,
                kchan = trace_kernel_get_channel_by_name(attr->name,
                                session->kernel_session);
                if (kchan == NULL) {
+                       /*
+                        * Don't try to create a channel if the session
+                        * has been started at some point in time
+                        * before. The tracer does not allow it.
+                        */
+                       if (session->started) {
+                               ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
+                               goto error;
+                       }
                        ret = channel_kernel_create(session->kernel_session, attr, wpipe);
+                       if (attr->name[0] != '\0') {
+                               session->kernel_session->has_non_default_channel = 1;
+                       }
                } else {
                        ret = channel_kernel_enable(session->kernel_session, kchan);
                }
@@ -896,7 +918,19 @@ int cmd_enable_channel(struct ltt_session *session,
 
                uchan = trace_ust_find_channel_by_name(chan_ht, attr->name);
                if (uchan == NULL) {
+                       /*
+                        * Don't try to create a channel if the session
+                        * has been started at some point in time
+                        * before. The tracer does not allow it.
+                        */
+                       if (session->started) {
+                               ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
+                               goto error;
+                       }
                        ret = channel_ust_create(usess, attr, domain->buf_type);
+                       if (attr->name[0] != '\0') {
+                               usess->has_non_default_channel = 1;
+                       }
                } else {
                        ret = channel_ust_enable(usess, uchan);
                }
@@ -931,6 +965,16 @@ int cmd_disable_event(struct ltt_session *session, int domain,
 
                ksess = session->kernel_session;
 
+               /*
+                * If a non-default channel has been created in the
+                * session, explicitely require that -c chan_name needs
+                * to be provided.
+                */
+               if (ksess->has_non_default_channel && channel_name[0] == '\0') {
+                       ret = LTTNG_ERR_NEED_CHANNEL_NAME;
+                       goto error;
+               }
+
                kchan = trace_kernel_get_channel_by_name(channel_name, ksess);
                if (kchan == NULL) {
                        ret = LTTNG_ERR_KERN_CHAN_NOT_FOUND;
@@ -952,6 +996,16 @@ int cmd_disable_event(struct ltt_session *session, int domain,
 
                usess = session->ust_session;
 
+               /*
+                * If a non-default channel has been created in the
+                * session, explicitely require that -c chan_name needs
+                * to be provided.
+                */
+               if (usess->has_non_default_channel && channel_name[0] == '\0') {
+                       ret = LTTNG_ERR_NEED_CHANNEL_NAME;
+                       goto error;
+               }
+
                uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
                                channel_name);
                if (uchan == NULL) {
@@ -1003,6 +1057,16 @@ int cmd_disable_event_all(struct ltt_session *session, int domain,
 
                ksess = session->kernel_session;
 
+               /*
+                * If a non-default channel has been created in the
+                * session, explicitely require that -c chan_name needs
+                * to be provided.
+                */
+               if (ksess->has_non_default_channel && channel_name[0] == '\0') {
+                       ret = LTTNG_ERR_NEED_CHANNEL_NAME;
+                       goto error;
+               }
+
                kchan = trace_kernel_get_channel_by_name(channel_name, ksess);
                if (kchan == NULL) {
                        ret = LTTNG_ERR_KERN_CHAN_NOT_FOUND;
@@ -1024,6 +1088,16 @@ int cmd_disable_event_all(struct ltt_session *session, int domain,
 
                usess = session->ust_session;
 
+               /*
+                * If a non-default channel has been created in the
+                * session, explicitely require that -c chan_name needs
+                * to be provided.
+                */
+               if (usess->has_non_default_channel && channel_name[0] == '\0') {
+                       ret = LTTNG_ERR_NEED_CHANNEL_NAME;
+                       goto error;
+               }
+
                uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
                                channel_name);
                if (uchan == NULL) {
@@ -1077,7 +1151,6 @@ int cmd_add_context(struct ltt_session *session, int domain,
                        }
                        chan_kern_created = 1;
                }
-
                /* Add kernel context to kernel tracer */
                ret = context_kernel_add(session->kernel_session, ctx, channel_name);
                if (ret != LTTNG_OK) {
@@ -1087,10 +1160,11 @@ int cmd_add_context(struct ltt_session *session, int domain,
        case LTTNG_DOMAIN_UST:
        {
                struct ltt_ust_session *usess = session->ust_session;
+               unsigned int chan_count;
+
                assert(usess);
 
-               unsigned int chan_count =
-                       lttng_ht_get_count(usess->domain_global.channels);
+               chan_count = lttng_ht_get_count(usess->domain_global.channels);
                if (chan_count == 0) {
                        struct lttng_channel *attr;
                        /* Create default channel */
@@ -1173,6 +1247,17 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain,
        {
                struct ltt_kernel_channel *kchan;
 
+               /*
+                * If a non-default channel has been created in the
+                * session, explicitely require that -c chan_name needs
+                * to be provided.
+                */
+               if (session->kernel_session->has_non_default_channel
+                               && channel_name[0] == '\0') {
+                       ret = LTTNG_ERR_NEED_CHANNEL_NAME;
+                       goto error;
+               }
+
                kchan = trace_kernel_get_channel_by_name(channel_name,
                                session->kernel_session);
                if (kchan == NULL) {
@@ -1222,6 +1307,16 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain,
 
                assert(usess);
 
+               /*
+                * If a non-default channel has been created in the
+                * session, explicitely require that -c chan_name needs
+                * to be provided.
+                */
+               if (usess->has_non_default_channel && channel_name[0] == '\0') {
+                       ret = LTTNG_ERR_NEED_CHANNEL_NAME;
+                       goto error;
+               }
+
                /* Get channel from global UST domain */
                uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
                                channel_name);
@@ -1294,6 +1389,17 @@ int cmd_enable_event_all(struct ltt_session *session,
 
                assert(session->kernel_session);
 
+               /*
+                * If a non-default channel has been created in the
+                * session, explicitely require that -c chan_name needs
+                * to be provided.
+                */
+               if (session->kernel_session->has_non_default_channel
+                               && channel_name[0] == '\0') {
+                       ret = LTTNG_ERR_NEED_CHANNEL_NAME;
+                       goto error;
+               }
+
                kchan = trace_kernel_get_channel_by_name(channel_name,
                                session->kernel_session);
                if (kchan == NULL) {
@@ -1358,6 +1464,16 @@ int cmd_enable_event_all(struct ltt_session *session,
 
                assert(usess);
 
+               /*
+                * If a non-default channel has been created in the
+                * session, explicitely require that -c chan_name needs
+                * to be provided.
+                */
+               if (usess->has_non_default_channel && channel_name[0] == '\0') {
+                       ret = LTTNG_ERR_NEED_CHANNEL_NAME;
+                       goto error;
+               }
+
                /* Get channel from global UST domain */
                uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
                                channel_name);
@@ -1676,7 +1792,7 @@ error:
  * Command LTTNG_CREATE_SESSION processed by the client thread.
  */
 int cmd_create_session_uri(char *name, struct lttng_uri *uris,
-               size_t nb_uri, lttng_sock_cred *creds)
+               size_t nb_uri, lttng_sock_cred *creds, unsigned int live_timer)
 {
        int ret;
        struct ltt_session *session;
@@ -1714,6 +1830,7 @@ int cmd_create_session_uri(char *name, struct lttng_uri *uris,
        session = session_find_by_name(name);
        assert(session);
 
+       session->live_timer = live_timer;
        /* Create default consumer output for the session not yet created. */
        session->consumer = consumer_create_output(CONSUMER_DST_LOCAL);
        if (session->consumer == NULL) {
@@ -1760,7 +1877,7 @@ int cmd_create_session_snapshot(char *name, struct lttng_uri *uris,
         * Create session in no output mode with URIs set to NULL. The uris we've
         * received are for a default snapshot output if one.
         */
-       ret = cmd_create_session_uri(name, NULL, 0, creds);
+       ret = cmd_create_session_uri(name, NULL, 0, creds, -1);
        if (ret != LTTNG_OK) {
                goto error;
        }
@@ -1930,13 +2047,15 @@ int cmd_register_consumer(struct ltt_session *session, int domain,
                        ret = LTTNG_ERR_CONNECT_FAIL;
                        goto error;
                }
+               cdata->cmd_sock = sock;
 
-               socket = consumer_allocate_socket(sock);
+               socket = consumer_allocate_socket(&cdata->cmd_sock);
                if (socket == NULL) {
                        ret = close(sock);
                        if (ret < 0) {
                                PERROR("close register consumer");
                        }
+                       cdata->cmd_sock = -1;
                        ret = LTTNG_ERR_FATAL;
                        goto error;
                }
@@ -2167,7 +2286,7 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, uid_t uid,
 
 /*
  * Command LTTNG_DATA_PENDING returning 0 if the data is NOT pending meaning
- * ready for trace analysis (or anykind of reader) or else 1 for pending data.
+ * ready for trace analysis (or any kind of reader) or else 1 for pending data.
  */
 int cmd_data_pending(struct ltt_session *session)
 {
@@ -2223,8 +2342,8 @@ int cmd_snapshot_add_output(struct ltt_session *session,
        DBG("Cmd snapshot add output for session %s", session->name);
 
        /*
-        * Persmission denied to create an output if the session is not set in no
-        * output mode.
+        * Permission denied to create an output if the session is not
+        * set in no output mode.
         */
        if (session->output_traces) {
                ret = LTTNG_ERR_EPERM;
@@ -2287,8 +2406,8 @@ int cmd_snapshot_del_output(struct ltt_session *session,
        rcu_read_lock();
 
        /*
-        * Persmission denied to create an output if the session is not set in no
-        * output mode.
+        * Permission denied to create an output if the session is not
+        * set in no output mode.
         */
        if (session->output_traces) {
                ret = LTTNG_ERR_EPERM;
@@ -2339,8 +2458,8 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session,
        DBG("Cmd snapshot list outputs for session %s", session->name);
 
        /*
-        * Persmission denied to create an output if the session is not set in no
-        * output mode.
+        * Permission denied to create an output if the session is not
+        * set in no output mode.
         */
        if (session->output_traces) {
                ret = LTTNG_ERR_EPERM;
@@ -2429,7 +2548,9 @@ static int set_relayd_for_snapshot(struct consumer_output *consumer,
        cds_lfht_for_each_entry(snap_output->consumer->socks->ht, &iter.iter,
                        socket, node.node) {
                ret = send_consumer_relayd_sockets(0, session->id,
-                               snap_output->consumer, socket);
+                               snap_output->consumer, socket,
+                               session->name, session->hostname,
+                               session->live_timer);
                if (ret != LTTNG_OK) {
                        rcu_read_unlock();
                        goto error;
@@ -2480,11 +2601,7 @@ static int record_kernel_snapshot(struct ltt_kernel_session *ksess,
        }
 
        ret = kernel_snapshot_record(ksess, output, wait, nb_streams);
-       if (ret < 0) {
-               ret = LTTNG_ERR_SNAPSHOT_FAIL;
-               if (ret == -EINVAL) {
-                       ret = LTTNG_ERR_INVALID;
-               }
+       if (ret != LTTNG_OK) {
                goto error_snapshot;
        }
 
@@ -2521,7 +2638,7 @@ static int record_ust_snapshot(struct ltt_ust_session *usess,
        }
 
        /*
-        * Copy kernel session sockets so we can communicate with the right
+        * Copy UST session sockets so we can communicate with the right
         * consumer for the snapshot record command.
         */
        ret = consumer_copy_sockets(output->consumer, usess->consumer);
@@ -2537,10 +2654,12 @@ static int record_ust_snapshot(struct ltt_ust_session *usess,
 
        ret = ust_app_snapshot_record(usess, output, wait, nb_streams);
        if (ret < 0) {
-               ret = LTTNG_ERR_SNAPSHOT_FAIL;
                if (ret == -EINVAL) {
                        ret = LTTNG_ERR_INVALID;
+                       goto error_snapshot;
                }
+
+               ret = LTTNG_ERR_SNAPSHOT_FAIL;
                goto error_snapshot;
        }
 
@@ -2597,8 +2716,8 @@ int cmd_snapshot_record(struct ltt_session *session,
        DBG("Cmd snapshot record for session %s", session->name);
 
        /*
-        * Persmission denied to create an output if the session is not set in no
-        * output mode.
+        * Permission denied to create an output if the session is not
+        * set in no output mode.
         */
        if (session->output_traces) {
                ret = LTTNG_ERR_EPERM;
@@ -2735,6 +2854,8 @@ int cmd_snapshot_record(struct ltt_session *session,
 
        if (snapshot_success) {
                session->snapshot.nb_snapshot++;
+       } else {
+               ret = LTTNG_ERR_SNAPSHOT_FAIL;
        }
 
 error:
This page took 0.041153 seconds and 5 git commands to generate.