Support snapshot max-size limitation
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index 6f7c71d0549474746ef78243f3204cd9ba014ab2..c522d51c2dc27e46efa08ccb7f85085e16e4e4d3 100644 (file)
@@ -25,6 +25,7 @@
 #include <common/common.h>
 #include <common/sessiond-comm/sessiond-comm.h>
 #include <common/relayd/relayd.h>
+#include <common/utils.h>
 
 #include "channel.h"
 #include "consumer.h"
@@ -721,7 +722,7 @@ static int start_kernel_session(struct ltt_kernel_session *ksess, int wpipe)
        struct ltt_kernel_channel *kchan;
 
        /* Open kernel metadata */
-       if (ksess->metadata == NULL) {
+       if (ksess->metadata == NULL && ksess->output_traces) {
                ret = kernel_open_metadata(ksess);
                if (ret < 0) {
                        ret = LTTNG_ERR_KERN_META_FAIL;
@@ -730,7 +731,7 @@ static int start_kernel_session(struct ltt_kernel_session *ksess, int wpipe)
        }
 
        /* Open kernel metadata stream */
-       if (ksess->metadata_stream_fd < 0) {
+       if (ksess->metadata && ksess->metadata_stream_fd < 0) {
                ret = kernel_open_metadata_stream(ksess);
                if (ret < 0) {
                        ERR("Kernel create metadata stream failed");
@@ -1681,12 +1682,7 @@ int cmd_create_session_uri(char *name, struct lttng_uri *uris,
        struct ltt_session *session;
 
        assert(name);
-
-       /* No URIs is not possible. */
-       if (uris == NULL) {
-               ret = LTTNG_ERR_SESSION_FAIL;
-               goto session_error;
-       }
+       assert(creds);
 
        /*
         * Verify if the session already exist
@@ -1725,9 +1721,15 @@ int cmd_create_session_uri(char *name, struct lttng_uri *uris,
                goto consumer_error;
        }
 
-       ret = cmd_set_consumer_uri(0, session, nb_uri, uris);
-       if (ret != LTTNG_OK) {
-               goto consumer_error;
+       if (uris) {
+               ret = cmd_set_consumer_uri(0, session, nb_uri, uris);
+               if (ret != LTTNG_OK) {
+                       goto consumer_error;
+               }
+               session->output_traces = 1;
+       } else {
+               session->output_traces = 0;
+               DBG2("Session %s created with no output", session->name);
        }
 
        session->consumer->enabled = 1;
@@ -1741,6 +1743,72 @@ find_error:
        return ret;
 }
 
+/*
+ * Command LTTNG_CREATE_SESSION_SNAPSHOT processed by the client thread.
+ */
+int cmd_create_session_snapshot(char *name, struct lttng_uri *uris,
+               size_t nb_uri, lttng_sock_cred *creds)
+{
+       int ret;
+       struct ltt_session *session;
+       struct snapshot_output *new_output = NULL;
+
+       assert(name);
+       assert(creds);
+
+       /*
+        * 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);
+       if (ret != LTTNG_OK) {
+               goto error;
+       }
+
+       /* Get the newly created session pointer back. This should NEVER fail. */
+       session = session_find_by_name(name);
+       assert(session);
+
+       /* Flag session for snapshot mode. */
+       session->snapshot_mode = 1;
+
+       /* Skip snapshot output creation if no URI is given. */
+       if (nb_uri == 0) {
+               goto end;
+       }
+
+       new_output = snapshot_output_alloc();
+       if (!new_output) {
+               ret = LTTNG_ERR_NOMEM;
+               goto error_snapshot_alloc;
+       }
+
+       ret = snapshot_output_init_with_uri(DEFAULT_SNAPSHOT_MAX_SIZE, NULL,
+                       uris, nb_uri, session->consumer, new_output, &session->snapshot);
+       if (ret < 0) {
+               if (ret == -ENOMEM) {
+                       ret = LTTNG_ERR_NOMEM;
+               } else {
+                       ret = LTTNG_ERR_INVALID;
+               }
+               goto error_snapshot;
+       }
+
+       rcu_read_lock();
+       snapshot_add_output(&session->snapshot, new_output);
+       rcu_read_unlock();
+
+end:
+       return LTTNG_OK;
+
+error_snapshot:
+       snapshot_output_destroy(new_output);
+error_snapshot_alloc:
+       session_destroy(session);
+error:
+       return ret;
+}
+
 /*
  * Command LTTNG_DESTROY_SESSION processed by the client thread.
  */
@@ -2186,27 +2254,6 @@ int cmd_snapshot_add_output(struct ltt_session *session,
                goto free_error;
        }
 
-       /*
-        * Copy sockets so the snapshot output can use them on destroy.
-        */
-
-       if (session->ust_session) {
-               ret = consumer_copy_sockets(new_output->consumer,
-                               session->ust_session->consumer);
-               if (ret < 0) {
-                       goto free_error;
-               }
-               new_output->ust_sockets_copied = 1;
-       }
-       if (session->kernel_session) {
-               ret = consumer_copy_sockets(new_output->consumer,
-                               session->kernel_session->consumer);
-               if (ret < 0) {
-                       goto free_error;
-               }
-               new_output->kernel_sockets_copied = 1;
-       }
-
        rcu_read_lock();
        snapshot_add_output(&session->snapshot, new_output);
        if (id) {
@@ -2373,8 +2420,8 @@ static int set_relayd_for_snapshot(struct consumer_output *consumer,
         * snapshot output.
         */
        rcu_read_lock();
-       cds_lfht_for_each_entry(consumer->socks->ht, &iter.iter, socket,
-                       node.node) {
+       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);
                if (ret < 0) {
@@ -2394,7 +2441,8 @@ error:
  * Return 0 on success or else a negative value.
  */
 static int record_kernel_snapshot(struct ltt_kernel_session *ksess,
-               struct snapshot_output *output, struct ltt_session *session, int wait)
+               struct snapshot_output *output, struct ltt_session *session,
+               int wait, int nb_streams)
 {
        int ret;
 
@@ -2402,24 +2450,40 @@ static int record_kernel_snapshot(struct ltt_kernel_session *ksess,
        assert(output);
        assert(session);
 
-       if (!output->kernel_sockets_copied) {
-               ret = consumer_copy_sockets(output->consumer, ksess->consumer);
-               if (ret < 0) {
-                       goto error;
-               }
-               output->kernel_sockets_copied = 1;
+       /* Get the datetime for the snapshot output directory. */
+       ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime,
+                       sizeof(output->datetime));
+       if (!ret) {
+               ret = -EINVAL;
+               goto error;
        }
 
-       ret = set_relayd_for_snapshot(ksess->consumer, output, session);
+       /*
+        * Copy kernel session sockets so we can communicate with the right
+        * consumer for the snapshot record command.
+        */
+       ret = consumer_copy_sockets(output->consumer, ksess->consumer);
        if (ret < 0) {
                goto error;
        }
 
-       ret = kernel_snapshot_record(ksess, output, wait);
+       ret = set_relayd_for_snapshot(ksess->consumer, output, session);
        if (ret < 0) {
-               goto error;
+               goto error_snapshot;
+       }
+
+       ret = kernel_snapshot_record(ksess, output, wait, nb_streams);
+       if (ret < 0) {
+               ret = -LTTNG_ERR_SNAPSHOT_FAIL;
+               if (ret == -EINVAL) {
+                       ret = -LTTNG_ERR_INVALID;
+               }
+               goto error_snapshot;
        }
 
+error_snapshot:
+       /* Clean up copied sockets so this output can use some other later on. */
+       consumer_destroy_output_sockets(output->consumer);
 error:
        return ret;
 }
@@ -2430,7 +2494,8 @@ error:
  * Return 0 on success or else a negative value.
  */
 static int record_ust_snapshot(struct ltt_ust_session *usess,
-               struct snapshot_output *output, struct ltt_session *session, int wait)
+               struct snapshot_output *output, struct ltt_session *session,
+               int wait, int nb_streams)
 {
        int ret;
 
@@ -2438,28 +2503,67 @@ static int record_ust_snapshot(struct ltt_ust_session *usess,
        assert(output);
        assert(session);
 
-       if (!output->ust_sockets_copied) {
-               ret = consumer_copy_sockets(output->consumer, usess->consumer);
-               if (ret < 0) {
-                       goto error;
-               }
-               output->ust_sockets_copied = 1;
+       /* Get the datetime for the snapshot output directory. */
+       ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime,
+                       sizeof(output->datetime));
+       if (!ret) {
+               ret = -EINVAL;
+               goto error;
        }
 
-       ret = set_relayd_for_snapshot(usess->consumer, output, session);
+       /*
+        * Copy kernel session sockets so we can communicate with the right
+        * consumer for the snapshot record command.
+        */
+       ret = consumer_copy_sockets(output->consumer, usess->consumer);
        if (ret < 0) {
                goto error;
        }
 
-       ret = ust_app_snapshot_record(usess, output, wait);
+       ret = set_relayd_for_snapshot(usess->consumer, output, session);
        if (ret < 0) {
-               goto error;
+               goto error_snapshot;
+       }
+
+       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;
        }
 
+error_snapshot:
+       /* Clean up copied sockets so this output can use some other later on. */
+       consumer_destroy_output_sockets(output->consumer);
 error:
        return ret;
 }
 
+/*
+ * Returns the total number of streams for a session or a negative value
+ * on error.
+ */
+static unsigned int get_total_nb_stream(struct ltt_session *session)
+{
+       unsigned int total_streams = 0;
+
+       if (session->kernel_session) {
+               struct ltt_kernel_session *ksess = session->kernel_session;
+
+               total_streams += ksess->stream_count_global;
+       }
+
+       if (session->ust_session) {
+               struct ltt_ust_session *usess = session->ust_session;
+
+               total_streams += ust_app_get_nb_stream(usess);
+       }
+
+       return total_streams;
+}
+
 /*
  * Command LTTNG_SNAPSHOT_RECORD from lib lttng ctl.
  *
@@ -2473,6 +2577,7 @@ int cmd_snapshot_record(struct ltt_session *session,
 {
        int ret = LTTNG_OK;
        struct snapshot_output *tmp_sout = NULL;
+       unsigned int nb_streams;
 
        assert(session);
 
@@ -2514,11 +2619,18 @@ int cmd_snapshot_record(struct ltt_session *session,
                }
        }
 
+       /*
+        * Get the total number of stream of that session which is used by the
+        * maximum size of the snapshot feature.
+        */
+       nb_streams = get_total_nb_stream(session);
+
        if (session->kernel_session) {
                struct ltt_kernel_session *ksess = session->kernel_session;
 
                if (tmp_sout) {
-                       ret = record_kernel_snapshot(ksess, tmp_sout, session, wait);
+                       ret = record_kernel_snapshot(ksess, tmp_sout, session,
+                                       wait, nb_streams);
                        if (ret < 0) {
                                goto error;
                        }
@@ -2529,7 +2641,8 @@ int cmd_snapshot_record(struct ltt_session *session,
                        rcu_read_lock();
                        cds_lfht_for_each_entry(session->snapshot.output_ht->ht,
                                        &iter.iter, sout, node.node) {
-                               ret = record_kernel_snapshot(ksess, sout, session, wait);
+                               ret = record_kernel_snapshot(ksess, sout,
+                                               session, wait, nb_streams);
                                if (ret < 0) {
                                        rcu_read_unlock();
                                        goto error;
@@ -2543,7 +2656,8 @@ int cmd_snapshot_record(struct ltt_session *session,
                struct ltt_ust_session *usess = session->ust_session;
 
                if (tmp_sout) {
-                       ret = record_ust_snapshot(usess, tmp_sout, session, wait);
+                       ret = record_ust_snapshot(usess, tmp_sout, session,
+                                       wait, nb_streams);
                        if (ret < 0) {
                                goto error;
                        }
@@ -2554,7 +2668,8 @@ int cmd_snapshot_record(struct ltt_session *session,
                        rcu_read_lock();
                        cds_lfht_for_each_entry(session->snapshot.output_ht->ht,
                                        &iter.iter, sout, node.node) {
-                               ret = record_ust_snapshot(usess, tmp_sout, session, wait);
+                               ret = record_ust_snapshot(usess, sout, session,
+                                               wait, nb_streams);
                                if (ret < 0) {
                                        rcu_read_unlock();
                                        goto error;
This page took 0.030254 seconds and 4 git commands to generate.