LTTNG_ERR_COMMAND_CANCELLED = 128, /* Command cancelled. */
LTTNG_ERR_ROTATE_PENDING = 129, /* Rotate already pending for this session. */
LTTNG_ERR_ROTATE_NOT_AVAILABLE = 130, /* Rotate feature not available for this type of session (e.g: live) */
- LTTNG_ERR_ROTATE_NO_DATA = 131, /* No data to rotate. */
+ LTTNG_ERR_ROTATE_NO_DATA = 131, /* No data to rotate. */
+ LTTNG_ERR_ROTATE_TIMER_EXISTS = 132, /* Rotate timer already setup for this session. */
+ LTTNG_ERR_ROTATE_SIZE_EXISTS = 133, /* Rotate size already setup for this session. */
/* MUST be last element */
LTTNG_ERR_NR, /* Last element */
* This is opaque to the public library.
*/
struct lttng_rotate_session_attr {
- /*
- * Session name to rotate.
- */
+ /* Session name to rotate. */
char session_name[LTTNG_NAME_MAX];
+ /* For the rotate pending request. */
+ uint64_t rotate_id;
+ /* > 0 if a timer is set. */
+ uint64_t timer_us;
/*
- * For the rotate pending request.
+ * > 0 if the session should rotate when it has written that many
+ * bytes.
*/
- uint64_t rotate_id;
+ uint64_t size;
} LTTNG_PACKED;
/*
#ifndef LTTNG_ROTATE_H
#define LTTNG_ROTATE_H
+#include <stdint.h>
+
#ifdef __cplusplus
extern "C" {
#endif
int lttng_rotate_session_attr_set_session_name(
struct lttng_rotate_session_attr *attr, const char *session_name);
+/*
+ * Set the timer to periodically rotate the session.
+ */
+void lttng_rotate_session_attr_set_timer(
+ struct lttng_rotate_session_attr *attr, uint64_t timer);
+
+/*
+ * Set the size to rotate the session.
+ */
+void lttng_rotate_session_attr_set_size(
+ struct lttng_rotate_session_attr *attr, uint64_t size);
+
/*
* lttng rotate session handle functions.
*/
extern int lttng_rotate_session_pending(
struct lttng_rotate_session_handle *rotate_handle);
+/*
+ * Configure a session to rotate periodically or based on the size written.
+ */
+extern int lttng_rotate_setup(struct lttng_rotate_session_attr *attr);
+
#ifdef __cplusplus
}
#endif
PERROR("Rename completed rotation chunk");
goto end;
}
+ ret = 0;
end:
memset(&reply, 0, sizeof(reply));
}
}
+ if (session->rotate_timer_period) {
+ ret = sessiond_rotate_timer_start(session,
+ session->rotate_timer_period);
+ if (ret < 0) {
+ ERR("Failed to enable rotate timer");
+ ret = LTTNG_ERR_UNK;
+ goto error;
+ }
+ }
+
/* Flag this after a successful start. */
session->has_been_started = 1;
session->active = 1;
sessiond_timer_rotate_pending_stop(session);
}
+ if (session->rotate_timer_enabled) {
+ sessiond_rotate_timer_stop(session);
+ }
+
/* Clean kernel session teardown */
kernel_destroy_session(ksess);
return ret;
}
+/*
+ * Command LTTNG_ROTATE_SETUP from the lttng-ctl library.
+ *
+ * Configure the automatic rotation parameters.
+ *
+ * Return 0 on success or else a LTTNG_ERR code.
+ */
+int cmd_rotate_setup(struct ltt_session *session,
+ uint64_t timer_us, uint64_t size)
+{
+ int ret;
+
+ assert(session);
+
+ DBG("Cmd rotate setup session %s", session->name);
+
+ if (timer_us && session->rotate_timer_period) {
+ ret = LTTNG_ERR_ROTATE_TIMER_EXISTS;
+ goto end;
+ }
+
+ if (size && session->rotate_size) {
+ ret = LTTNG_ERR_ROTATE_SIZE_EXISTS;
+ goto end;
+ }
+
+ if (timer_us && !session->rotate_timer_period) {
+ session->rotate_timer_period = timer_us;
+ /*
+ * Only start the timer if the session is active, otherwise
+ * it will be started when the session starts.
+ */
+ if (session->active) {
+ ret = sessiond_rotate_timer_start(session, timer_us);
+ if (ret) {
+ ERR("Failed to enable rotate timer");
+ ret = LTTNG_ERR_UNK;
+ goto end;
+ }
+ }
+ } else if (timer_us == -1ULL && session->rotate_timer_period > 0) {
+ sessiond_rotate_timer_stop(session);
+ }
+ session->rotate_size = size;
+
+ ret = LTTNG_OK;
+
+ goto end;
+
+end:
+ return ret;
+}
+
/*
* Init command subsystem.
*/
int cmd_rotate_pending(struct ltt_session *session,
struct lttng_rotate_pending_return **pending_return,
uint64_t rotate_id);
+int cmd_rotate_setup(struct ltt_session *session, uint64_t timer_us,
+ uint64_t size);
#endif /* CMD_H */
case LTTNG_UNREGISTER_TRIGGER:
case LTTNG_ROTATE_SESSION:
case LTTNG_ROTATE_PENDING:
+ case LTTNG_ROTATE_SETUP:
need_domain = 0;
break;
default:
ret = LTTNG_OK;
break;
}
+ case LTTNG_ROTATE_SETUP:
+ {
+ ret = cmd_rotate_setup(cmd_ctx->session,
+ cmd_ctx->lsm->u.rotate_setup.timer_us,
+ cmd_ctx->lsm->u.rotate_setup.size);
+ break;
+ }
default:
ret = LTTNG_ERR_UND;
break;
int ret;
DBG("[rotation-thread] Rotate timer on session %" PRIu64, session->id);
+
+ /*
+ * If the session is stopped, we need to cancel this timer.
+ */
+ pthread_mutex_lock(&session->lock);
+ if (!session->active && session->rotate_timer_enabled) {
+ sessiond_rotate_timer_stop(session);
+ }
+ pthread_mutex_unlock(&session->lock);
+
ret = cmd_rotate_session(session, NULL);
fprintf(stderr, "RET ROTATE TIMER: %d\n", ret);
+ if (ret == -LTTNG_ERR_ROTATE_PENDING) {
+ ret = 0;
+ goto end;
+ } else if (ret != LTTNG_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = 0;
+
+end:
return ret;
}
/* Timer to periodically rotate a session. */
bool rotate_timer_enabled;
timer_t rotate_timer;
+ uint64_t rotate_timer_period;
+ uint64_t rotate_size;
};
/* Prototypes */
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <inttypes.h>
+#include <ctype.h>
#include <common/sessiond-comm/sessiond-comm.h>
#include <common/mi-lttng.h>
enum {
OPT_HELP = 1,
OPT_LIST_OPTIONS,
+ OPT_TIMER,
+ OPT_SIZE,
};
static struct poptOption long_options[] = {
{"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
{"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
{"no-wait", 'n', POPT_ARG_VAL, &opt_no_wait, 1, 0, 0},
+ {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
+ {"timer", 0, POPT_ARG_INT, 0, OPT_TIMER, 0, 0},
+ {"size", 0, POPT_ARG_INT, 0, OPT_SIZE, 0, 0},
{0, 0, 0, 0, 0, 0, 0}
};
return ret;
}
-static int rotate_tracing(void)
+static int setup_rotate(char *session_name, uint64_t timer, uint64_t size)
+{
+ int ret = 0;
+ struct lttng_rotate_session_attr *attr = NULL;
+
+ attr = lttng_rotate_session_attr_create();
+ if (!attr) {
+ goto error;
+ }
+
+ ret = lttng_rotate_session_attr_set_session_name(attr, session_name);
+ if (ret < 0) {
+ goto error;
+ }
+
+ lttng_rotate_session_attr_set_timer(attr, timer);
+ lttng_rotate_session_attr_set_size(attr, size);
+
+ if (timer) {
+ DBG("Configuring session %s to rotate every %" PRIu64 " us",
+ session_name, timer);
+ }
+ if (size) {
+ DBG("Configuring session %s to rotate every %" PRIu64 " bytes written",
+ session_name, size);
+ }
+
+ ret = lttng_rotate_setup(attr);
+
+ goto end;
+
+error:
+ ret = -1;
+end:
+ return ret;
+}
+
+static int rotate_tracing(char *session_name)
{
int ret;
- char *session_name = NULL, *path = NULL;
+ char *path = NULL;
struct lttng_rotate_session_attr *attr = NULL;
struct lttng_rotate_session_handle *handle = NULL;
enum lttng_rotate_status rotate_status;
goto error;
}
- if (opt_session_name == NULL) {
- session_name = get_session_name();
- if (session_name == NULL) {
- goto error;
- }
- } else {
- session_name = opt_session_name;
- }
-
ret = lttng_rotate_session_attr_set_session_name(attr, session_name);
if (ret < 0) {
goto error;
error:
ret = CMD_ERROR;
end:
- if (opt_session_name == NULL) {
- free(session_name);
- }
lttng_rotate_session_handle_destroy(handle);
lttng_rotate_session_attr_destroy(attr);
return ret;
{
int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
static poptContext pc;
+ char *session_name = NULL;
+ char *opt_arg = NULL;
+ uint64_t timer = 0, size = 0;
pc = poptGetContext(NULL, argc, argv, long_options, 0);
poptReadDefaultConfig(pc, 0);
case OPT_LIST_OPTIONS:
list_cmd_options(stdout, long_options);
goto end;
+ case OPT_TIMER:
+ {
+ errno = 0;
+ opt_arg = poptGetOptArg(pc);
+ timer = strtoull(opt_arg, NULL, 0);
+ if (errno != 0 || !isdigit(opt_arg[0])) {
+ ERR("Wrong value in --timer parameter: %s", opt_arg);
+ ret = CMD_ERROR;
+ goto end;
+ }
+ DBG("Rotation timer set to %" PRIu64, timer);
+ break;
+ }
+ case OPT_SIZE:
+ {
+ errno = 0;
+ opt_arg = poptGetOptArg(pc);
+ size = strtoull(opt_arg, NULL, 0);
+ if (errno != 0 || !isdigit(opt_arg[0])) {
+ ERR("Wrong value in --timer parameter: %s", opt_arg);
+ ret = CMD_ERROR;
+ goto end;
+ }
+ DBG("Rotation size set to %" PRIu64, size);
+ break;
+ }
default:
ret = CMD_UNDEFINED;
goto end;
}
}
- opt_session_name = (char*) poptGetArg(pc);
+ if (opt_session_name == NULL) {
+ session_name = get_session_name();
+ if (session_name == NULL) {
+ goto end;
+ }
+ } else {
+ session_name = opt_session_name;
+ }
/* Mi check */
if (lttng_opt_mi) {
}
}
- command_ret = rotate_tracing();
+ fprintf(stderr, "T: %lu, S: %lu\n", timer, size);
+ /* No config options, just rotate the session now */
+ if (timer == 0 && size == 0) {
+ command_ret = rotate_tracing(session_name);
+ } else {
+ command_ret = setup_rotate(session_name, timer, size);
+ }
if (command_ret) {
+ ERR("%s", lttng_strerror(command_ret));
success = 0;
}
/* Overwrite ret if an error occurred with start_tracing */
ret = command_ret ? command_ret : ret;
poptFreeContext(pc);
+ free(session_name);
return ret;
}
[ ERROR_INDEX(LTTNG_ERR_ROTATE_PENDING) ] = "Rotate already pending for this session.",
[ ERROR_INDEX(LTTNG_ERR_ROTATE_NOT_AVAILABLE) ] = "Rotate feature not available for this type of session",
[ ERROR_INDEX(LTTNG_ERR_ROTATE_NO_DATA) ] = "No trace data to rotate",
+ [ ERROR_INDEX(LTTNG_ERR_ROTATE_TIMER_EXISTS) ] = "Rotate timer already setup for this session",
+ [ ERROR_INDEX(LTTNG_ERR_ROTATE_SIZE_EXISTS) ] = "Rotate size already setup for this session",
/* Last element */
[ ERROR_INDEX(LTTNG_ERR_NR) ] = "Unknown error code"
LTTNG_UNREGISTER_TRIGGER = 44,
LTTNG_ROTATE_SESSION = 45,
LTTNG_ROTATE_PENDING = 46,
+ LTTNG_ROTATE_SETUP = 47,
};
enum lttcomm_relayd_command {
struct {
uint64_t rotate_id;
} LTTNG_PACKED rotate_pending;
+ struct {
+ uint64_t timer_us;
+ uint64_t size;
+ } LTTNG_PACKED rotate_setup;
} u;
} LTTNG_PACKED;
return ret;
}
+void lttng_rotate_session_attr_set_timer(
+ struct lttng_rotate_session_attr *attr,
+ uint64_t timer)
+{
+ attr->timer_us = timer;
+}
+
+void lttng_rotate_session_attr_set_size(
+ struct lttng_rotate_session_attr *attr,
+ uint64_t size)
+{
+ attr->size = size;
+}
+
enum lttng_rotate_status lttng_rotate_session_get_status(
struct lttng_rotate_session_handle *rotate_handle)
{
free(pending_return);
return ret;
}
+
+/*
+ * Configure the automatic rotate parameters.
+ *
+ * Return 0 on success else a negative LTTng error code.
+ */
+int lttng_rotate_setup(struct lttng_rotate_session_attr *attr)
+{
+ struct lttcomm_session_msg lsm;
+ int ret;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_ROTATE_SETUP;
+ lttng_ctl_copy_string(lsm.session.name, attr->session_name,
+ sizeof(lsm.session.name));
+ lsm.u.rotate_setup.timer_us = attr->timer_us;
+ lsm.u.rotate_setup.size = attr->size;
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ fprintf(stderr, "SETUP RET: %d\n", ret);
+
+end:
+ return ret;
+}
+