-/*
- * Called with the rotation_timer_queue lock held.
- * Return true if the same timer job already exists in the queue, false if not.
- */
-static
-bool check_duplicate_timer_job(struct timer_thread_parameters *ctx,
- struct ltt_session *session, unsigned int signal)
-{
- bool ret = false;
- struct sessiond_rotation_timer *node;
-
- rcu_read_lock();
- cds_list_for_each_entry(node, &ctx->rotation_timer_queue->list, head) {
- if (node->session_id == session->id && node->signal == signal) {
- ret = true;
- goto end;
- }
- }
-
-end:
- rcu_read_unlock();
- return ret;
-}
-
-/*
- * Add the session ID and signal value to the rotation_timer_queue if it is
- * not already there and wakeup the rotation thread. The rotation thread
- * empties the whole queue everytime it is woken up. The event_pipe is
- * non-blocking, if it would block, we just return because we know the
- * rotation thread will be awaken anyway.
- */
-static
-int enqueue_timer_rotate_job(struct timer_thread_parameters *ctx,
- struct ltt_session *session, unsigned int signal)
-{
- int ret;
- char *c = "!";
- struct sessiond_rotation_timer *timer_data = NULL;
-
- pthread_mutex_lock(&ctx->rotation_timer_queue->lock);
- if (check_duplicate_timer_job(ctx, session, signal)) {
- /*
- * This timer job is already pending, we don't need to add
- * it.
- */
- ret = 0;
- goto end;
- }
-
- timer_data = zmalloc(sizeof(struct sessiond_rotation_timer));
- if (!timer_data) {
- PERROR("Allocation of timer data");
- ret = -1;
- goto end;
- }
- timer_data->session_id = session->id;
- timer_data->signal = signal;
- cds_list_add_tail(&timer_data->head,
- &ctx->rotation_timer_queue->list);
-
- ret = lttng_write(
- lttng_pipe_get_writefd(ctx->rotation_timer_queue->event_pipe),
- c, 1);
- if (ret < 0) {
- /*
- * We do not want to block in the timer handler, the job has been
- * enqueued in the list, the wakeup pipe is probably full, the job
- * will be processed when the rotation_thread catches up.
- */
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- ret = 0;
- goto end;
- }
- PERROR("Timer wakeup rotation thread");
- goto end;
- }
-
- ret = 0;
-
-end:
- pthread_mutex_unlock(&ctx->rotation_timer_queue->lock);
- return ret;
-}
-
-/*
- * Ask the rotation thread to check if the last rotation started in this
- * session is still pending on the relay.
- */
-static
-void relay_rotation_pending_timer(struct timer_thread_parameters *ctx,
- int sig, siginfo_t *si)
-{
- struct ltt_session *session = si->si_value.sival_ptr;
-
- assert(session);
-
- (void) enqueue_timer_rotate_job(ctx, session,
- LTTNG_SESSIOND_SIG_ROTATE_PENDING);
-}
-
-/*
- * Handle the LTTNG_SESSIOND_SIG_ROTATE_TIMER timer. Add the session ID to
- * the rotation_timer_queue so the rotation thread can trigger a new rotation
- * on that session.
- */
-static
-void rotate_timer(struct timer_thread_parameters *ctx, int sig, siginfo_t *si)
-{
- int ret;
- /*
- * The session cannot be freed/destroyed while we are running this
- * signal handler.
- */
- struct ltt_session *session = si->si_value.sival_ptr;
- assert(session);
-
- ret = enqueue_timer_rotate_job(ctx, session, LTTNG_SESSIOND_SIG_ROTATE_TIMER);
- if (ret) {
- PERROR("wakeup rotate pipe");
- }
-}
-