assert(session);
- *rotate_return = zmalloc(sizeof(struct lttng_rotate_session_return));
- if (!*rotate_return) {
- ret = -ENOMEM;
- goto end;
+ if (rotate_return) {
+ *rotate_return = zmalloc(sizeof(struct lttng_rotate_session_return));
+ if (!*rotate_return) {
+ ret = -ENOMEM;
+ goto end;
+ }
}
if (session->live_timer || session->snapshot_mode ||
}
}
- (*rotate_return)->rotate_id = session->rotate_count;
- (*rotate_return)->status = LTTNG_ROTATE_STARTED;
+ if (rotate_return) {
+ (*rotate_return)->rotate_id = session->rotate_count;
+ (*rotate_return)->status = LTTNG_ROTATE_STARTED;
+ }
DBG("Cmd rotate session %s, rotate_id %" PRIu64, session->name,
session->rotate_count);
goto end;
error:
- (*rotate_return)->status = LTTNG_ROTATE_ERROR;
+ if (rotate_return) {
+ (*rotate_return)->status = LTTNG_ROTATE_ERROR;
+ }
end:
return ret;
}
int apps_cmd_notify_pipe[2] = { -1, -1 };
/*
- * Pipe to wakeup the rotation thread when the
- * LTTNG_SESSIOND_SIG_ROTATE_PENDING signal is caught.
+ * Pipe to wakeup the rotation thread when a timer related to the session
+ * rotation feature fires.
*/
static int rotate_timer_pipe[2] = { -1, -1 };
/*
* Create the rotate_timer_pipe as non blocking because we have to
- * write in it from the sighandler.
+ * write in it from the sighandler of the timer thread.
*/
ret = utils_create_pipe_cloexec_nonblock(rotate_timer_pipe);
if (ret < 0) {
return ret;
}
+static
+int rotate_pending_relay_timer(struct ltt_session *session)
+{
+ int ret;
+
+ DBG("[rotation-thread] Check rotate pending on session %" PRIu64,
+ session->id);
+ ret = relay_rotate_pending(session, session->rotate_count - 1);
+ if (ret < 0) {
+ ERR("[rotation-thread] Check relay rotate pending");
+ goto end;
+ }
+ if (ret == 0) {
+ DBG("[rotation-thread] Rotation completed on the relay for "
+ "session %" PRIu64, session->id);
+ /*
+ * Stop the timer and clear the queue, the timers are currently
+ * ignored because of the rotate_pending_relay_check_in_progress
+ * flag.
+ */
+ sessiond_timer_rotate_pending_stop(session);
+ /*
+ * Now we can clear the pending flag in the session. New
+ * rotations can start now.
+ */
+ session->rotate_pending_relay = false;
+ } else if (ret == 1) {
+ DBG("[rotation-thread] Rotation still pending on the relay for "
+ "session %" PRIu64, session->id);
+ }
+ /*
+ * Allow the timer thread to send other notifications when needed.
+ */
+ session->rotate_pending_relay_check_in_progress = false;
+ fprintf(stderr, "RET PENDING: %d\n", ret);
+
+ ret = 0;
+
+end:
+ return ret;
+}
+
+static
+int rotate_timer(struct ltt_session *session)
+{
+ int ret;
+
+ DBG("[rotation-thread] Rotate timer on session %" PRIu64, session->id);
+ ret = cmd_rotate_session(session, NULL);
+ fprintf(stderr, "RET ROTATE TIMER: %d\n", ret);
+
+ return ret;
+}
+
static
int handle_rotate_timer_pipe(int fd, uint32_t revents,
struct rotation_thread_handle *handle,
struct rotation_thread_state *state)
{
int ret = 0;
- uint64_t session_id;
struct ltt_session *session;
+ struct sessiond_rotation_timer timer_data;
if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
ret = lttng_poll_del(&state->events, fd);
goto end;
}
+ memset(&timer_data, 0, sizeof(struct sessiond_rotation_timer));
+
do {
- ret = read(fd, &session_id, sizeof(session_id));
+ ret = read(fd, &timer_data, sizeof(timer_data));
} while (ret == -1 && errno == EINTR);
- if (ret != sizeof(session_id)) {
+ if (ret != sizeof(timer_data)) {
ERR("[rotation-thread] Failed to read from pipe (fd = %i)",
fd);
ret = -1;
goto end;
}
- session = session_find_by_id(session_id);
+ session = session_find_by_id(timer_data.session_id);
if (!session) {
ERR("[rotation-thread] Session %" PRIu64 " not found",
- session_id);
+ timer_data.session_id);
ret = -1;
goto end;
}
- DBG("[rotation-thread] Check rotate pending on session %" PRIu64,
- session_id);
- ret = relay_rotate_pending(session, session->rotate_count - 1);
- if (ret < 0) {
- ERR("[rotation-thread] Check relay rotate pending");
- goto end;
- }
- if (ret == 0) {
- DBG("[rotation-thread] Rotation completed on the relay for "
- "session %" PRIu64, session_id);
- session->rotate_pending_relay = false;
- sessiond_timer_rotate_pending_stop(session);
- } else if (ret == 1) {
- DBG("[rotation-thread] Rotation still pending on the relay for "
- "session %" PRIu64, session_id);
+ if (timer_data.signal == LTTNG_SESSIOND_SIG_ROTATE_PENDING) {
+ ret = rotate_pending_relay_timer(session);
+ } else if (timer_data.signal == LTTNG_SESSIOND_SIG_ROTATE_TIMER) {
+ ret = rotate_timer(session);
+ } else {
+ ERR("Unknown signal in rotate timer");
+ ret = -1;
}
- /*
- * Allow the timer thread to send other notifications if needed.
- */
- session->rotate_pending_relay_check_in_progress = false;
- fprintf(stderr, "RET PENDING: %d\n", ret);
-
- ret = 0;
end:
return ret;
ret = handle_rotate_timer_pipe(fd, revents,
handle, &state);
if (ret) {
- ERR("[rotation-thread] Rotate pending");
+ ERR("[rotation-thread] Rotate timer");
goto error;
}
} else if (fd == handle->ust32_consumer ||
new_session->rotate_pending = false;
new_session->rotate_pending_relay = false;
+ new_session->rotate_relay_pending_timer_enabled = false;
+ new_session->rotate_timer = false;
/* Add new session to the session list */
session_lock_list();
* Timer to check periodically if a relay has completed the last
* rotation.
*/
- int rotate_relay_pending_timer_enabled;
+ bool rotate_relay_pending_timer_enabled;
timer_t rotate_relay_pending_timer;
+ /* Timer to periodically rotate a session. */
+ bool rotate_timer_enabled;
+ timer_t rotate_timer;
};
/* Prototypes */
#include "sessiond-timer.h"
#include "health-sessiond.h"
-#if 0
-#include <bin/lttng-sessiond/ust-ctl.h>
-#include <bin/lttng-consumerd/health-consumerd.h>
-#include <common/common.h>
-#include <common/compat/endian.h>
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <common/kernel-consumer/kernel-consumer.h>
-#include <common/consumer/consumer-stream.h>
-#include <common/consumer/consumer-timer.h>
-#include <common/consumer/consumer-testpoint.h>
-#include <common/ust-consumer/ust-consumer.h>
-#endif
-
static struct timer_signal_data timer_signal = {
.tid = 0,
.setup_done = 0,
if (ret) {
PERROR("sigaddset switch");
}
+ ret = sigaddset(mask, LTTNG_SESSIOND_SIG_ROTATE_TIMER);
+ if (ret) {
+ PERROR("sigaddset switch");
+ }
}
static
return ret;
}
-int sessiond_timer_rotate_pending_start(struct ltt_session *session, unsigned int
- interval_us)
+int sessiond_timer_rotate_pending_start(struct ltt_session *session,
+ unsigned int interval_us)
{
int ret;
ret = session_timer_start(&session->rotate_relay_pending_timer,
session, interval_us,
LTTNG_SESSIOND_SIG_ROTATE_PENDING);
- session->rotate_relay_pending_timer_enabled = !!(ret == 0);
+ if (ret == 0) {
+ session->rotate_relay_pending_timer_enabled = true;
+ }
return ret;
}
ERR("Failed to stop live timer");
}
- session->rotate_relay_pending_timer_enabled = 0;
+ session->rotate_relay_pending_timer_enabled = false;
+}
+
+int sessiond_rotate_timer_start(struct ltt_session *session,
+ unsigned int interval_us)
+{
+ int ret;
+
+ ret = session_timer_start(&session->rotate_timer, session, interval_us,
+ LTTNG_SESSIOND_SIG_ROTATE_TIMER);
+ if (ret == 0) {
+ session->rotate_timer_enabled = true;
+ }
+
+ return ret;
+}
+
+/*
+ * Stop and delete the channel's live timer.
+ */
+void sessiond_rotate_timer_stop(struct ltt_session *session)
+{
+ int ret;
+
+ assert(session);
+
+ ret = session_timer_stop(&session->rotate_timer,
+ LTTNG_SESSIOND_SIG_ROTATE_TIMER);
+ if (ret == -1) {
+ ERR("Failed to stop live timer");
+ }
+
+ session->rotate_timer_enabled = false;
}
/*
{
int ret;
struct ltt_session *session = si->si_value.sival_ptr;
+ struct sessiond_rotation_timer timer_data;
assert(session);
/*
}
session->rotate_pending_relay_check_in_progress = true;
- ret = lttng_write(ctx->rotate_timer_pipe, &session->id,
- sizeof(session->id));
+ memset(&timer_data, 0, sizeof(struct sessiond_rotation_timer));
+ timer_data.session_id = session->id;
+ timer_data.signal = LTTNG_SESSIOND_SIG_ROTATE_PENDING;
+ ret = lttng_write(ctx->rotate_timer_pipe, &timer_data,
+ sizeof(timer_data));
if (ret < sizeof(session->id)) {
PERROR("wakeup rotate pipe");
}
return;
}
+static
+void rotate_timer(struct timer_thread_parameters *ctx, int sig, siginfo_t *si)
+{
+ int ret;
+ struct ltt_session *session = si->si_value.sival_ptr;
+ struct sessiond_rotation_timer timer_data;
+ assert(session);
+
+ /*
+ * No rate limiting here, so if the timer fires too quickly, there will
+ * be a backlog of timers queued up and we will try to catch up.
+ */
+ memset(&timer_data, 0, sizeof(struct sessiond_rotation_timer));
+ timer_data.session_id = session->id;
+ timer_data.signal = LTTNG_SESSIOND_SIG_ROTATE_TIMER;
+ ret = lttng_write(ctx->rotate_timer_pipe, &timer_data,
+ sizeof(timer_data));
+ if (ret < sizeof(session->id)) {
+ PERROR("wakeup rotate pipe");
+ }
+
+ return;
+}
+
/*
* This thread is the sighandler for the timer signals.
*/
} else if (signr == LTTNG_SESSIOND_SIG_ROTATE_PENDING) {
fprintf(stderr, "PENDING TIMER\n");
relay_rotation_pending_timer(ctx, info.si_signo, &info);
+ } else if (signr == LTTNG_SESSIOND_SIG_ROTATE_TIMER) {
+ fprintf(stderr, "ROTATE TIMER\n");
+ rotate_timer(ctx, info.si_signo, &info);
} else {
ERR("Unexpected signal %d\n", info.si_signo);
}
#define LTTNG_SESSIOND_SIG_TEARDOWN SIGRTMIN + 10
#define LTTNG_SESSIOND_SIG_EXIT SIGRTMIN + 11
#define LTTNG_SESSIOND_SIG_ROTATE_PENDING SIGRTMIN + 12
+#define LTTNG_SESSIOND_SIG_ROTATE_TIMER SIGRTMIN + 13
#define CLOCKID CLOCK_MONOTONIC
int rotate_timer_pipe;
};
+struct sessiond_rotation_timer {
+ uint64_t session_id;
+ unsigned int signal;
+} LTTNG_PACKED;
+
void *sessiond_timer_thread(void *data);
int sessiond_timer_signal_init(void);
interval_us);
void sessiond_timer_rotate_pending_stop(struct ltt_session *session);
+int sessiond_rotate_timer_start(struct ltt_session *session,
+ unsigned int interval_us);
+
+void sessiond_rotate_timer_stop(struct ltt_session *session);
+
#endif /* SESSIOND_TIMER_H */