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);
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.
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;
+ }
}
}
}
}
- /* 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.
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;
}
return ret;
}
+/*
+ * Set the base_path of the session only if subdir of a control uris is set.
+ * Return LTTNG_OK on success, otherwise LTTNG_ERR_*.
+ */
+static int set_session_base_path_from_uris(struct ltt_session *session,
+ size_t nb_uri,
+ struct lttng_uri *uris)
+{
+ int ret;
+ size_t i;
+
+ for (i = 0; i < nb_uri; i++) {
+ if (uris[i].stype != LTTNG_STREAM_CONTROL ||
+ uris[i].subdir[0] == '\0') {
+ /* Not interested in these URIs */
+ continue;
+ }
+
+ if (session->base_path != NULL) {
+ free(session->base_path);
+ session->base_path = NULL;
+ }
+
+ /* Set session base_path */
+ session->base_path = strdup(uris[i].subdir);
+ if (!session->base_path) {
+ 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 \"%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.
*/
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 */
for (i = 0; i < nb_uri; i++) {
- ret = add_uri_to_consumer(session,
- session->consumer,
- &uris[i], LTTNG_DOMAIN_NONE);
+ ret = add_uri_to_consumer(session, session->consumer, &uris[i],
+ LTTNG_DOMAIN_NONE);
if (ret != LTTNG_OK) {
goto error;
}
const char *session_name;
struct ltt_session *new_session = NULL;
enum lttng_session_descriptor_status descriptor_status;
- const char *base_path;
session_lock_list();
if (home_path) {
ret_code = LTTNG_ERR_INVALID;
goto end;
}
- ret = lttng_session_descriptor_get_base_path(descriptor, &base_path);
- if (ret) {
- ret_code = LTTNG_ERR_INVALID;
- goto end;
- }
+
ret_code = session_create(session_name, creds->uid, creds->gid,
- base_path, &new_session);
+ &new_session);
if (ret_code != LTTNG_OK) {
goto end;
}
cmd_ret = LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP;
goto end;
}
-
- session->rotation_state = LTTNG_ROTATION_STATE_ONGOING;
-
if (session->active) {
new_trace_chunk = session_create_new_trace_chunk(session, NULL,
NULL, NULL);
goto error;
}
- assert(chunk_being_archived);
- chunk_status = lttng_trace_chunk_get_id(chunk_being_archived,
- &ongoing_rotation_chunk_id);
- assert(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK);
-
if (session->kernel_session) {
cmd_ret = kernel_rotate_session(session);
if (cmd_ret != LTTNG_OK) {
}
}
+ if (!session->active) {
+ session->rotated_after_last_stop = true;
+ }
+
+ if (!chunk_being_archived) {
+ DBG("Rotating session \"%s\" from a \"NULL\" trace chunk to a new trace chunk, skipping completion check",
+ session->name);
+ if (failed_to_rotate) {
+ cmd_ret = rotation_fail_code;
+ goto error;
+ }
+ cmd_ret = LTTNG_OK;
+ goto end;
+ }
+
+ session->rotation_state = LTTNG_ROTATION_STATE_ONGOING;
+ chunk_status = lttng_trace_chunk_get_id(chunk_being_archived,
+ &ongoing_rotation_chunk_id);
+ assert(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK);
+
ret = session_close_trace_chunk(session, chunk_being_archived,
quiet_rotation ?
NULL :
goto error;
}
- if (!session->active) {
- session->rotated_after_last_stop = true;
- }
-
if (rotate_return) {
rotate_return->rotation_id = ongoing_rotation_chunk_id;
}