Fix: sessiond: no rotation performed from null chunk to new chunk
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index 1dec61ea17b6ba7f74e122e37a7df99afa2e07c6..5a122d8d3c8dcf7e7f361b34f69f46c4680c0d22 100644 (file)
@@ -2572,6 +2572,8 @@ int cmd_start_trace(struct ltt_session *session)
        unsigned long nb_chan = 0;
        struct ltt_kernel_session *ksession;
        struct ltt_ust_session *usess;
+       const bool session_rotated_after_last_stop =
+                       session->rotated_after_last_stop;
 
        assert(session);
 
@@ -2585,6 +2587,22 @@ int cmd_start_trace(struct ltt_session *session)
                goto error;
        }
 
+       if (session->rotation_state == LTTNG_ROTATION_STATE_ONGOING &&
+                       !session->current_trace_chunk) {
+               /*
+                * A rotation was launched while the session was stopped and
+                * it has not been completed yet. It is not possible to start
+                * the session since starting the session here would require a
+                * rotation from "NULL" to a new trace chunk. That rotation
+                * would overlap with the ongoing rotation, which is not
+                * supported.
+                */
+               WARN("Refusing to start session \"%s\" as a rotation launched after the last \"stop\" is still ongoing",
+                               session->name);
+               ret = LTTNG_ERR_ROTATION_PENDING;
+               goto error;
+       }
+
        /*
         * Starting a session without channel is useless since after that it's not
         * possible to enable channel thus inform the client.
@@ -2600,21 +2618,45 @@ int cmd_start_trace(struct ltt_session *session)
                goto error;
        }
 
+       session->active = 1;
+       session->rotated_after_last_stop = false;
        if (session->output_traces && !session->current_trace_chunk) {
-               struct lttng_trace_chunk *trace_chunk;
+               if (!session->has_been_started) {
+                       struct lttng_trace_chunk *trace_chunk;
 
-               trace_chunk = session_create_new_trace_chunk(
-                               session, NULL, NULL, NULL);
-               if (!trace_chunk) {
-                       ret = LTTNG_ERR_CREATE_DIR_FAIL;
-                       goto error;
-               }
-               assert(!session->current_trace_chunk);
-               ret = session_set_trace_chunk(session, trace_chunk, NULL);
-               lttng_trace_chunk_put(trace_chunk);
-               if (ret) {
-                       ret = LTTNG_ERR_CREATE_TRACE_CHUNK_FAIL_CONSUMER;
-                       goto error;
+                       DBG("Creating initial trace chunk of session \"%s\"",
+                                       session->name);
+                       trace_chunk = session_create_new_trace_chunk(
+                                       session, NULL, NULL, NULL);
+                       if (!trace_chunk) {
+                               ret = LTTNG_ERR_CREATE_DIR_FAIL;
+                               goto error;
+                       }
+                       assert(!session->current_trace_chunk);
+                       ret = session_set_trace_chunk(session, trace_chunk,
+                                       NULL);
+                       lttng_trace_chunk_put(trace_chunk);
+                       if (ret) {
+                               ret = LTTNG_ERR_CREATE_TRACE_CHUNK_FAIL_CONSUMER;
+                               goto error;
+                       }
+               } else {
+                       DBG("Rotating session \"%s\" from its current \"NULL\" trace chunk to a new chunk",
+                                       session->name);
+                       /*
+                        * Rotate existing streams into the new chunk.
+                        * This is a "quiet" rotation has no client has
+                        * explicitly requested this operation.
+                        *
+                        * There is also no need to wait for the rotation
+                        * to complete as it will happen immediately. No data
+                        * was produced as the session was stopped, so the
+                        * rotation should happen on reception of the command.
+                        */
+                       ret = cmd_rotate_session(session, NULL, true);
+                       if (ret != LTTNG_OK) {
+                               goto error;
+                       }
                }
        }
 
@@ -2637,10 +2679,6 @@ int cmd_start_trace(struct ltt_session *session)
                }
        }
 
-       /* Flag this after a successful start. */
-       session->has_been_started = 1;
-       session->active = 1;
-
        /*
         * Clear the flag that indicates that a rotation was done while the
         * session was stopped.
@@ -2661,6 +2699,15 @@ int cmd_start_trace(struct ltt_session *session)
        ret = LTTNG_OK;
 
 error:
+       if (ret == LTTNG_OK) {
+               /* Flag this after a successful start. */
+               session->has_been_started |= 1;
+       } else {
+               session->active = 0;
+               /* Restore initial state on error. */
+               session->rotated_after_last_stop =
+                               session_rotated_after_last_stop;
+       }
        return ret;
 }
 
@@ -2740,24 +2787,15 @@ error:
 }
 
 /*
- * Command LTTNG_SET_CONSUMER_URI processed by the client thread.
+ * Set the base_path of the session only if subdir of a control uris is set.
+ * Return LTTNG_OK on success, otherwise LTTNG_ERR_*.
  */
-int cmd_set_consumer_uri(struct ltt_session *session, size_t nb_uri,
+static int set_session_base_path_from_uris(struct ltt_session *session,
+               size_t nb_uri,
                struct lttng_uri *uris)
 {
-       int ret, i;
-       struct ltt_kernel_session *ksess = session->kernel_session;
-       struct ltt_ust_session *usess = session->ust_session;
-
-       assert(session);
-       assert(uris);
-       assert(nb_uri > 0);
-
-       /* Can't set consumer URI if the session is active. */
-       if (session->active) {
-               ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
-               goto error;
-       }
+       int ret;
+       size_t i;
 
        for (i = 0; i < nb_uri; i++) {
                if (uris[i].stype != LTTNG_STREAM_CONTROL ||
@@ -2774,11 +2812,47 @@ int cmd_set_consumer_uri(struct ltt_session *session, size_t nb_uri,
                /* Set session base_path */
                session->base_path = strdup(uris[i].subdir);
                if (!session->base_path) {
-                       PERROR("Copying base path: %s", uris[i].subdir);
+                       PERROR("Failed to copy base path \"%s\" to session \"%s\"",
+                                       uris[i].subdir, session->name);
+                       ret = LTTNG_ERR_NOMEM;
                        goto error;
                }
-               DBG2("Setting base path for session %" PRIu64 ": %s",
-                               session->id, session->base_path);
+               DBG2("Setting base path \"%s\" for session \"%s\"",
+                               session->base_path, session->name);
+       }
+       ret = LTTNG_OK;
+error:
+       return ret;
+}
+
+/*
+ * Command LTTNG_SET_CONSUMER_URI processed by the client thread.
+ */
+int cmd_set_consumer_uri(struct ltt_session *session, size_t nb_uri,
+               struct lttng_uri *uris)
+{
+       int ret, i;
+       struct ltt_kernel_session *ksess = session->kernel_session;
+       struct ltt_ust_session *usess = session->ust_session;
+
+       assert(session);
+       assert(uris);
+       assert(nb_uri > 0);
+
+       /* Can't set consumer URI if the session is active. */
+       if (session->active) {
+               ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
+               goto error;
+       }
+
+       /*
+        * Set the session base path if any. This is done inside
+        * cmd_set_consumer_uri to preserve backward compatibility of the
+        * previous session creation api vs the session descriptor api.
+        */
+       ret = set_session_base_path_from_uris(session, nb_uri, uris);
+       if (ret != LTTNG_OK) {
+               goto error;
        }
 
        /* Set the "global" consumer URIs */
This page took 0.025461 seconds and 4 git commands to generate.