+ if (!session->active) {
+ /*
+ * A stop command was issued during the rotation, it is
+ * up to the rotation completion check to perform the
+ * renaming of the last chunk that was produced.
+ */
+ ret = notification_thread_command_session_rotation_ongoing(
+ notification_thread_handle,
+ session->name,
+ session->uid,
+ session->gid,
+ session->current_archive_id);
+ if (ret != LTTNG_OK) {
+ ERR("[rotation-thread] Failed to notify notification thread of completed rotation for session %s",
+ session->name);
+ }
+
+ ret = rename_active_chunk(session);
+ if (ret < 0) {
+ ERR("[rotation-thread] Failed to rename active rotation chunk");
+ goto end;
+ }
+
+ /* Ownership of location is transferred. */
+ location = session_get_trace_archive_location(session);
+ ret = notification_thread_command_session_rotation_completed(
+ notification_thread_handle,
+ session->name,
+ session->uid,
+ session->gid,
+ session->current_archive_id,
+ location);
+ if (ret != LTTNG_OK) {
+ ERR("[rotation-thread] Failed to notify notification thread of completed rotation for session %s",
+ session->name);
+ }
+ }
+
+ ret = 0;
+end:
+ if (session->rotation_state == LTTNG_ROTATION_STATE_ONGOING) {
+ DBG("[rotation-thread] Rotation of trace archive %" PRIu64 " is still pending for session %s",
+ session->current_archive_id - 1, session->name);
+ ret = timer_session_rotation_pending_check_start(session,
+ DEFAULT_ROTATE_PENDING_TIMER);
+ if (ret) {
+ ERR("Re-enabling rotate pending timer");
+ ret = -1;
+ goto end;
+ }
+ }
+
+ return ret;
+}
+
+/* Call with the session and session_list locks held. */
+static
+int launch_session_rotation(struct ltt_session *session)
+{
+ int ret;
+ struct lttng_rotate_session_return rotation_return;
+
+ DBG("[rotation-thread] Launching scheduled time-based rotation on session \"%s\"",
+ session->name);
+
+ ret = cmd_rotate_session(session, &rotation_return);
+ if (ret == LTTNG_OK) {
+ DBG("[rotation-thread] Scheduled time-based rotation successfully launched on session \"%s\"",
+ session->name);
+ } else {
+ /* Don't consider errors as fatal. */
+ DBG("[rotation-thread] Scheduled time-based rotation aborted for session %s: %s",
+ session->name, lttng_strerror(ret));
+ }
+ return 0;
+}
+
+static
+int run_job(struct rotation_thread_job *job, struct ltt_session *session,
+ struct notification_thread_handle *notification_thread_handle)
+{
+ int ret;
+
+ switch (job->type) {
+ case ROTATION_THREAD_JOB_TYPE_SCHEDULED_ROTATION:
+ ret = launch_session_rotation(session);
+ break;
+ case ROTATION_THREAD_JOB_TYPE_CHECK_PENDING_ROTATION:
+ ret = check_session_rotation_pending(session,
+ notification_thread_handle);
+ break;
+ default:
+ abort();
+ }
+ return ret;
+}
+
+static
+int handle_job_queue(struct rotation_thread_handle *handle,
+ struct rotation_thread *state,
+ struct rotation_thread_timer_queue *queue)
+{
+ int ret = 0;
+ int fd = lttng_pipe_get_readfd(queue->event_pipe);
+ struct ltt_session *session;
+ char buf;
+
+ ret = lttng_read(fd, &buf, 1);
+ if (ret != 1) {
+ ERR("[rotation-thread] Failed to read from wakeup pipe (fd = %i)", fd);