start to handle async rotation on the relay + basics for remote rotate_pending
[deliverable/lttng-tools.git] / src / bin / lttng-sessiond / ust-app.c
index a9dff558cbb22940bd6bc75c2041c3e6952c858a..2283f980ae079c53c483f5c9f11e58aa4600b099 100644 (file)
@@ -43,6 +43,7 @@
 #include "session.h"
 #include "lttng-sessiond.h"
 #include "notification-thread-commands.h"
+#include "rotation-thread.h"
 
 static
 int ust_app_flush_app_session(struct ust_app *app, struct ust_app_session *ua_sess);
@@ -92,6 +93,7 @@ static void copy_channel_attr_to_ustctl(
        attr->switch_timer_interval = uattr->switch_timer_interval;
        attr->read_timer_interval = uattr->read_timer_interval;
        attr->output = uattr->output;
+       attr->blocking_timeout = uattr->u.s.blocking_timeout;
 }
 
 /*
@@ -1040,6 +1042,7 @@ struct ust_app_channel *alloc_ust_app_channel(char *name,
                ua_chan->attr.switch_timer_interval = attr->switch_timer_interval;
                ua_chan->attr.read_timer_interval = attr->read_timer_interval;
                ua_chan->attr.output = attr->output;
+               ua_chan->attr.blocking_timeout = attr->u.s.blocking_timeout;
        }
        /* By default, the channel is a per cpu channel. */
        ua_chan->attr.type = LTTNG_UST_CHAN_PER_CPU;
@@ -1803,6 +1806,8 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan,
        ua_chan->attr.read_timer_interval = uchan->attr.read_timer_interval;
        ua_chan->monitor_timer_interval = uchan->monitor_timer_interval;
        ua_chan->attr.output = uchan->attr.output;
+       ua_chan->attr.blocking_timeout = uchan->attr.u.s.blocking_timeout;
+
        /*
         * Note that the attribute channel type is not set since the channel on the
         * tracing registry side does not have this information.
@@ -2361,7 +2366,7 @@ int create_ust_app_channel_context(struct ust_app_session *ua_sess,
        ua_ctx = alloc_ust_app_ctx(uctx);
        if (ua_ctx == NULL) {
                /* malloc failed */
-               ret = -1;
+               ret = -ENOMEM;
                goto error;
        }
 
@@ -4413,9 +4418,21 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
 
        /* Create directories if consumer is LOCAL and has a path defined. */
        if (usess->consumer->type == CONSUMER_DST_LOCAL &&
-                       strlen(usess->consumer->dst.trace_path) > 0) {
-               ret = run_as_mkdir_recursive(usess->consumer->dst.trace_path,
-                               S_IRWXU | S_IRWXG, ua_sess->euid, ua_sess->egid);
+                       strlen(usess->consumer->dst.session_root_path) > 0) {
+               char *tmp_path;
+
+               tmp_path = zmalloc(PATH_MAX * sizeof(char));
+               if (!tmp_path) {
+                       ERR("Alloc tmp_path");
+                       goto error_unlock;
+               }
+               snprintf(tmp_path, PATH_MAX, "%s%s%s",
+                               usess->consumer->dst.session_root_path,
+                               usess->consumer->chunk_path,
+                               usess->consumer->subdir);
+               ret = run_as_mkdir_recursive(tmp_path, S_IRWXU | S_IRWXG,
+                               ua_sess->euid, ua_sess->egid);
+               free(tmp_path);
                if (ret < 0) {
                        if (errno != EEXIST) {
                                ERR("Trace directory creation error");
@@ -6111,21 +6128,24 @@ int ust_app_uid_get_channel_runtime_stats(uint64_t ust_session_id,
        int ret;
        uint64_t consumer_chan_key;
 
+       *discarded = 0;
+       *lost = 0;
+
        ret = buffer_reg_uid_consumer_channel_key(
                        buffer_reg_uid_list, ust_session_id,
                        uchan_id, &consumer_chan_key);
        if (ret < 0) {
+               /* Not found */
+               ret = 0;
                goto end;
        }
 
        if (overwrite) {
                ret = consumer_get_lost_packets(ust_session_id,
                                consumer_chan_key, consumer, lost);
-               *discarded = 0;
        } else {
                ret = consumer_get_discarded_events(ust_session_id,
                                consumer_chan_key, consumer, discarded);
-               *lost = 0;
        }
 
 end:
@@ -6144,10 +6164,13 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
        struct ust_app_session *ua_sess;
        struct ust_app_channel *ua_chan;
 
+       *discarded = 0;
+       *lost = 0;
+
        rcu_read_lock();
        /*
-        * Iterate over every registered applications, return when we
-        * found one in the right session and channel.
+        * Iterate over every registered applications. Sum counters for
+        * all applications containing requested session and channel.
         */
        cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                struct lttng_ht_iter uiter;
@@ -6166,19 +6189,26 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
                ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
 
                if (overwrite) {
+                       uint64_t _lost;
+
                        ret = consumer_get_lost_packets(usess->id, ua_chan->key,
-                                       consumer, lost);
-                       *discarded = 0;
-                       goto end;
+                                       consumer, &_lost);
+                       if (ret < 0) {
+                               break;
+                       }
+                       (*lost) += _lost;
                } else {
+                       uint64_t _discarded;
+
                        ret = consumer_get_discarded_events(usess->id,
-                                       ua_chan->key, consumer, discarded);
-                       *lost = 0;
-                       goto end;
+                                       ua_chan->key, consumer, &_discarded);
+                       if (ret < 0) {
+                               break;
+                       }
+                       (*discarded) += _discarded;
                }
        }
 
-end:
        rcu_read_unlock();
        return ret;
 }
@@ -6248,3 +6278,204 @@ int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess)
 
        return 0;
 }
+
+/*
+ * Rotate all the channels of a session.
+ *
+ * Return 0 on success or else a negative value.
+ */
+int ust_app_rotate_session(struct ltt_session *session)
+{
+       int ret = 0, nr_channels = 0, nr_app = 0;
+       struct lttng_ht_iter iter;
+       struct ust_app *app;
+       struct ltt_ust_session *usess = session->ust_session;
+       char *pathname;
+
+       assert(usess);
+
+       rcu_read_lock();
+
+       pathname = zmalloc(PATH_MAX * sizeof(char));
+       if (!pathname) {
+               ERR("Failed to alloc pathname");
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       switch (usess->buffer_type) {
+       case LTTNG_BUFFER_PER_UID:
+       {
+               struct buffer_reg_uid *reg;
+
+               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+                       struct buffer_reg_channel *reg_chan;
+                       struct consumer_socket *socket;
+
+                       nr_channels++;
+                       /* Get consumer socket to use to push the metadata.*/
+                       socket = consumer_find_socket_by_bitness(reg->bits_per_long,
+                                       usess->consumer);
+                       if (!socket) {
+                               ret = -EINVAL;
+                               goto error;
+                       }
+
+                       /*
+                        * Account the metadata channel first to make sure the
+                        * number of channels waiting for a rotation cannot
+                        * reach 0 before we complete the iteration over all
+                        * the channels.
+                        */
+                       ret = rotate_add_channel_pending(
+                                       reg->registry->reg.ust->metadata_key,
+                                       LTTNG_DOMAIN_UST, session);
+                       if (ret < 0) {
+                               ret = LTTNG_ERR_KERN_CONSUMER_FAIL;
+                               pthread_mutex_unlock(socket->lock);
+                               goto error;
+                       }
+
+                       ret = snprintf(pathname, PATH_MAX,
+                                       DEFAULT_UST_TRACE_DIR "/" DEFAULT_UST_TRACE_UID_PATH,
+                                       reg->uid, reg->bits_per_long);
+                       if (ret < 0) {
+                               PERROR("snprintf rotate path");
+                               pthread_mutex_unlock(socket->lock);
+                               goto error;
+                       }
+
+                       /* Rotate the data channels. */
+                       cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
+                                       reg_chan, node.node) {
+                               ret = rotate_add_channel_pending(
+                                               reg_chan->consumer_key,
+                                               LTTNG_DOMAIN_UST, session);
+                               if (ret < 0) {
+                                       ret = LTTNG_ERR_KERN_CONSUMER_FAIL;
+                                       pthread_mutex_unlock(socket->lock);
+                                       goto error;
+                               }
+                               ret = consumer_rotate_channel(socket,
+                                               reg_chan->consumer_key,
+                                               usess->uid, usess->gid,
+                                               usess->consumer, pathname, 0,
+                                               session->rotate_count);
+                               if (ret < 0) {
+                                       goto error;
+                               }
+                       }
+
+                       (void) push_metadata(reg->registry->reg.ust, usess->consumer);
+
+                       ret = consumer_rotate_channel(socket,
+                                       reg->registry->reg.ust->metadata_key,
+                                       usess->uid, usess->gid,
+                                       usess->consumer, pathname, 1,
+                                       session->rotate_count);
+                       if (ret < 0) {
+                               goto error;
+                       }
+               }
+               break;
+       }
+       case LTTNG_BUFFER_PER_PID:
+       {
+               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       struct consumer_socket *socket;
+                       struct lttng_ht_iter chan_iter;
+                       struct ust_app_channel *ua_chan;
+                       struct ust_app_session *ua_sess;
+                       struct ust_registry_session *registry;
+
+                       ua_sess = lookup_session_by_app(usess, app);
+                       if (!ua_sess) {
+                               /* Session not associated with this app. */
+                               continue;
+                       }
+                       nr_app++;
+                       ret = snprintf(pathname, PATH_MAX, DEFAULT_UST_TRACE_DIR "/%s",
+                                       ua_sess->path);
+                       if (ret < 0) {
+                               PERROR("snprintf snapshot path");
+                               goto error;
+                       }
+
+                       /* Get the right consumer socket for the application. */
+                       socket = consumer_find_socket_by_bitness(app->bits_per_long,
+                                       usess->consumer);
+                       if (!socket) {
+                               ret = -EINVAL;
+                               goto error;
+                       }
+
+                       registry = get_session_registry(ua_sess);
+                       if (!registry) {
+                               DBG("Application session is being torn down. Abort snapshot record.");
+                               ret = -1;
+                               goto error;
+                       }
+
+                       /*
+                        * Account the metadata channel first to make sure the
+                        * number of channels waiting for a rotation cannot
+                        * reach 0 before we complete the iteration over all
+                        * the channels.
+                        */
+                       ret = rotate_add_channel_pending(registry->metadata_key,
+                                       LTTNG_DOMAIN_UST, session);
+                       if (ret < 0) {
+                               ret = LTTNG_ERR_KERN_CONSUMER_FAIL;
+                               pthread_mutex_unlock(socket->lock);
+                               goto error;
+                       }
+
+                       /* Rotate the data channels. */
+                       cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
+                                       ua_chan, node.node) {
+                               ret = rotate_add_channel_pending(
+                                               ua_chan->key, LTTNG_DOMAIN_UST,
+                                               session);
+                               if (ret < 0) {
+                                       ret = LTTNG_ERR_KERN_CONSUMER_FAIL;
+                                       pthread_mutex_unlock(socket->lock);
+                                       goto error;
+                               }
+                               ret = consumer_rotate_channel(socket, ua_chan->key,
+                                               ua_sess->euid, ua_sess->egid,
+                                               ua_sess->consumer, pathname, 0,
+                                               session->rotate_count);
+                               if (ret < 0) {
+                                       goto error;
+                               }
+                       }
+
+                       /* Rotate the metadata channel. */
+                       (void) push_metadata(registry, usess->consumer);
+                       ret = consumer_rotate_channel(socket, registry->metadata_key,
+                                       ua_sess->euid, ua_sess->egid,
+                                       ua_sess->consumer, pathname, 1,
+                                       session->rotate_count);
+                       if (ret < 0) {
+                               goto error;
+                       }
+               }
+               break;
+       }
+       default:
+               assert(0);
+               break;
+       }
+
+       if (nr_app == 0 && nr_channels == 0) {
+               session->rotate_pending = 0;
+               session->rotate_status = LTTNG_ROTATE_EMPTY;
+       }
+
+       ret = LTTNG_OK;
+
+error:
+       rcu_read_unlock();
+       free(pathname);
+       return ret;
+}
This page took 0.029902 seconds and 5 git commands to generate.