#include "lttng-ctl-helper.h"
-struct lttng_rotation_immediate_attr *lttng_rotation_immediate_attr_create(void)
-{
- return zmalloc(sizeof(struct lttng_rotation_immediate_attr));
-}
-
-struct lttng_rotation_schedule_attr *lttng_rotation_schedule_attr_create(void)
-{
- return zmalloc(sizeof(struct lttng_rotation_schedule_attr));
-}
-
-void lttng_rotation_immediate_attr_destroy(
- struct lttng_rotation_immediate_attr *attr)
-{
- free(attr);
-}
-
-void lttng_rotation_schedule_attr_destroy(struct lttng_rotation_schedule_attr *attr)
-{
- if (attr) {
- free(attr);
- attr = NULL;
- }
-}
-
-enum lttng_rotation_status lttng_rotation_immediate_attr_set_session_name(
- struct lttng_rotation_immediate_attr *attr,
- const char *session_name)
-{
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
- int ret;
-
- if (!attr || !session_name) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto error;
- }
-
- ret = lttng_strncpy(attr->session_name, session_name,
- sizeof(attr->session_name));
- if (ret) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto error;
- }
-
-error:
- return status;
-}
-
static
enum lttng_rotation_status ask_rotation_info(
struct lttng_rotation_handle *rotation_handle,
}
-enum lttng_rotation_status lttng_rotation_schedule_attr_set_session_name(
- struct lttng_rotation_schedule_attr *attr,
- const char *session_name)
-{
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
- int ret;
-
- if (!attr || !session_name) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto error;
- }
-
- ret = lttng_strncpy(attr->session_name, session_name,
- sizeof(attr->session_name));
- if (ret) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto error;
- }
-
-error:
- return status;
-}
-
-enum lttng_rotation_status lttng_rotation_schedule_attr_set_timer_period(
- struct lttng_rotation_schedule_attr *attr,
- uint64_t timer)
-{
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
-
- if (!attr) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- attr->timer_us = timer;
-end:
- return status;
-}
-
-void lttng_rotation_schedule_attr_set_size(
- struct lttng_rotation_schedule_attr *attr, uint64_t size)
-{
- attr->size = size;
-}
-
static
struct lttng_trace_archive_location *
create_trace_archive_location_from_get_info(
void lttng_rotation_handle_destroy(
struct lttng_rotation_handle *rotation_handle)
{
+ if (!rotation_handle) {
+ return;
+ }
lttng_trace_archive_location_destroy(rotation_handle->archive_location);
free(rotation_handle);
}
static
int init_rotation_handle(struct lttng_rotation_handle *rotation_handle,
- struct lttng_rotate_session_return *rotate_return,
- struct lttng_rotation_immediate_attr *attr)
+ const char *session_name,
+ struct lttng_rotate_session_return *rotate_return)
{
int ret;
- ret = lttng_strncpy(rotation_handle->session_name, attr->session_name,
+ ret = lttng_strncpy(rotation_handle->session_name, session_name,
sizeof(rotation_handle->session_name));
if (ret) {
goto end;
*
* Return 0 on success else a negative LTTng error code.
*/
-int lttng_rotate_session(struct lttng_rotation_immediate_attr *attr,
+int lttng_rotate_session(const char *session_name,
+ struct lttng_rotation_immediate_descriptor *descriptor,
struct lttng_rotation_handle **rotation_handle)
{
struct lttcomm_session_msg lsm;
struct lttng_rotate_session_return *rotate_return = NULL;
int ret;
+ size_t session_name_len;
- if (!attr) {
+ if (!session_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ session_name_len = strlen(session_name);
+ if (session_name_len >= sizeof(lsm.session.name) ||
+ session_name_len >= member_sizeof(struct lttng_rotation_handle, session_name)) {
ret = -LTTNG_ERR_INVALID;
goto end;
}
memset(&lsm, 0, sizeof(lsm));
lsm.cmd_type = LTTNG_ROTATE_SESSION;
- lttng_ctl_copy_string(lsm.session.name, attr->session_name,
+ lttng_ctl_copy_string(lsm.session.name, session_name,
sizeof(lsm.session.name));
ret = lttng_ctl_ask_sessiond(&lsm, (void **) &rotate_return);
goto end;
}
- init_rotation_handle(*rotation_handle, rotate_return, attr);
+ init_rotation_handle(*rotation_handle, session_name, rotate_return);
ret = 0;
}
/*
- * Configure the automatic rotate parameters.
+ * Update the automatic rotation parameters.
+ * 'add' as true enables the provided schedule, false removes the shedule.
+ *
+ * The external API makes it appear as though arbitrary schedules can
+ * be added or removed at will. However, the session daemon is
+ * currently limited to one schedule per type (per session).
+ *
+ * The additional flexibility of the public API is offered for future
+ * rotation schedules that could indicate more precise criteria than
+ * size and time (e.g. a domain) where it could make sense to add
+ * multiple schedules of a given type to a session.
+ *
+ * Hence, the exact schedule that the user wishes to remove (and not
+ * just its type) must be passed so that the session daemon can
+ * validate that is exists before clearing it.
*/
-int lttng_rotation_set_schedule(
- struct lttng_rotation_schedule_attr *attr)
+static
+enum lttng_rotation_status lttng_rotation_update_schedule(
+ const char *session_name,
+ const struct lttng_rotation_schedule *schedule,
+ bool add)
{
struct lttcomm_session_msg lsm;
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
int ret;
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
+ if (!session_name || !schedule) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ if (strlen(session_name) >= sizeof(lsm.session.name)) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
goto end;
}
memset(&lsm, 0, sizeof(lsm));
lsm.cmd_type = LTTNG_ROTATION_SET_SCHEDULE;
- lttng_ctl_copy_string(lsm.session.name, attr->session_name,
+ lttng_ctl_copy_string(lsm.session.name, session_name,
sizeof(lsm.session.name));
- lsm.u.rotate_setup.timer_us = attr->timer_us;
- lsm.u.rotate_setup.size = attr->size;
+
+ lsm.u.rotation_set_schedule.type = (uint32_t) schedule->type;
+ switch (schedule->type) {
+ case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
+ {
+ status = lttng_rotation_schedule_size_threshold_get_threshold(
+ schedule, &lsm.u.rotation_set_schedule.value);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ if (status == LTTNG_ROTATION_STATUS_UNAVAILABLE) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ }
+ goto end;
+ }
+
+ lsm.u.rotation_set_schedule.set = !!add;
+ break;
+ }
+ case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
+ {
+ status = lttng_rotation_schedule_periodic_get_period(
+ schedule, &lsm.u.rotation_set_schedule.value);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ if (status == LTTNG_ROTATION_STATUS_UNAVAILABLE) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ }
+ goto end;
+ }
+
+ lsm.u.rotation_set_schedule.set = !!add;
+ break;
+ }
+ default:
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ if (ret >= 0) {
+ goto end;
+ }
+
+ switch (-ret) {
+ case LTTNG_ERR_ROTATION_SCHEDULE_SET:
+ status = LTTNG_ROTATION_STATUS_SCHEDULE_ALREADY_SET;
+ break;
+ case LTTNG_ERR_ROTATION_SCHEDULE_NOT_SET:
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ break;
+ default:
+ status = LTTNG_ROTATION_STATUS_ERROR;
+ }
end:
- return ret;
+ return status;
}
-int lttng_rotation_schedule_get_timer_period(const char *session_name,
- uint64_t *rotate_timer)
+static
+struct lttng_rotation_schedules *lttng_rotation_schedules_create(void)
+{
+ return zmalloc(sizeof(struct lttng_rotation_schedules));
+}
+
+static
+void lttng_schedules_add(struct lttng_rotation_schedules *schedules,
+ struct lttng_rotation_schedule *schedule)
+{
+ schedules->schedules[schedules->count++] = schedule;
+}
+
+static
+int get_schedules(const char *session_name,
+ struct lttng_rotation_schedules **_schedules)
{
- struct lttcomm_session_msg lsm;
- struct lttng_rotation_schedule_get_timer_period *get_timer = NULL;
int ret;
+ struct lttcomm_session_msg lsm;
+ struct lttng_session_list_schedules_return *schedules_comm;
+ struct lttng_rotation_schedules *schedules = NULL;
+ struct lttng_rotation_schedule *periodic = NULL, *size = NULL;
memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_ROTATION_SCHEDULE_GET_TIMER_PERIOD;
+ lsm.cmd_type = LTTNG_SESSION_LIST_ROTATION_SCHEDULES;
lttng_ctl_copy_string(lsm.session.name, session_name,
sizeof(lsm.session.name));
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) &get_timer);
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) &schedules_comm);
if (ret < 0) {
- ret = -1;
goto end;
}
- *rotate_timer = get_timer->rotate_timer;
- ret = 0;
+ schedules = lttng_rotation_schedules_create();
+ if (!schedules) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ if (schedules_comm->periodic.set == 1) {
+ enum lttng_rotation_status status;
+
+ periodic = lttng_rotation_schedule_periodic_create();
+ if (!periodic) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ status = lttng_rotation_schedule_periodic_set_period(
+ periodic, schedules_comm->periodic.value);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ /*
+ * This would imply that the session daemon returned
+ * an invalid periodic rotation schedule value.
+ */
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ lttng_schedules_add(schedules, periodic);
+ periodic = NULL;
+ }
+
+ if (schedules_comm->size.set == 1) {
+ enum lttng_rotation_status status;
+
+ size = lttng_rotation_schedule_size_threshold_create();
+ if (!size) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ status = lttng_rotation_schedule_size_threshold_set_threshold(
+ size, schedules_comm->size.value);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ /*
+ * This would imply that the session daemon returned
+ * an invalid size threshold schedule value.
+ */
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ lttng_schedules_add(schedules, size);
+ size = NULL;
+ }
+
+ ret = LTTNG_OK;
end:
- free(get_timer);
+ free(schedules_comm);
+ free(periodic);
+ free(size);
+ *_schedules = schedules;
return ret;
}
-int lttng_rotation_schedule_get_size(const char *session_name,
- uint64_t *rotate_size)
+enum lttng_rotation_schedule_type lttng_rotation_schedule_get_type(
+ const struct lttng_rotation_schedule *schedule)
{
- struct lttcomm_session_msg lsm;
- struct lttng_rotation_schedule_get_size *get_size = NULL;
- int ret;
+ return schedule ? schedule->type : LTTNG_ROTATION_SCHEDULE_TYPE_UNKNOWN;
+}
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_ROTATION_SCHEDULE_GET_SIZE;
- lttng_ctl_copy_string(lsm.session.name, session_name,
- sizeof(lsm.session.name));
+struct lttng_rotation_schedule *
+lttng_rotation_schedule_size_threshold_create(void)
+{
+ struct lttng_rotation_schedule_size_threshold *schedule;
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) &get_size);
- if (ret < 0) {
- ret = -1;
+ schedule = zmalloc(sizeof(*schedule));
+ if (!schedule) {
goto end;
}
- *rotate_size = get_size->rotate_size;
+ schedule->parent.type = LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD;
+end:
+ return &schedule->parent;
+}
- ret = 0;
+enum lttng_rotation_status
+lttng_rotation_schedule_size_threshold_get_threshold(
+ const struct lttng_rotation_schedule *schedule,
+ uint64_t *size_threshold_bytes)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ struct lttng_rotation_schedule_size_threshold *size_schedule;
+ if (!schedule || !size_threshold_bytes ||
+ schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ size_schedule = container_of(schedule,
+ struct lttng_rotation_schedule_size_threshold,
+ parent);
+ if (size_schedule->size.set) {
+ *size_threshold_bytes = size_schedule->size.bytes;
+ } else {
+ status = LTTNG_ROTATION_STATUS_UNAVAILABLE;
+ goto end;
+ }
end:
- free(get_size);
- return ret;
+ return status;
+}
+
+enum lttng_rotation_status
+lttng_rotation_schedule_size_threshold_set_threshold(
+ struct lttng_rotation_schedule *schedule,
+ uint64_t size_threshold_bytes)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ struct lttng_rotation_schedule_size_threshold *size_schedule;
+
+ if (!schedule || size_threshold_bytes == 0 ||
+ size_threshold_bytes == -1ULL ||
+ schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ size_schedule = container_of(schedule,
+ struct lttng_rotation_schedule_size_threshold,
+ parent);
+ size_schedule->size.bytes = size_threshold_bytes;
+ size_schedule->size.set = true;
+end:
+ return status;
+}
+
+struct lttng_rotation_schedule *
+lttng_rotation_schedule_periodic_create(void)
+{
+ struct lttng_rotation_schedule_periodic *schedule;
+
+ schedule = zmalloc(sizeof(*schedule));
+ if (!schedule) {
+ goto end;
+ }
+
+ schedule->parent.type = LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC;
+end:
+ return &schedule->parent;
+}
+
+enum lttng_rotation_status
+lttng_rotation_schedule_periodic_get_period(
+ const struct lttng_rotation_schedule *schedule,
+ uint64_t *period_us)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ struct lttng_rotation_schedule_periodic *periodic_schedule;
+
+ if (!schedule || !period_us ||
+ schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ periodic_schedule = container_of(schedule,
+ struct lttng_rotation_schedule_periodic,
+ parent);
+ if (periodic_schedule->period.set) {
+ *period_us = periodic_schedule->period.us;
+ } else {
+ status = LTTNG_ROTATION_STATUS_UNAVAILABLE;
+ goto end;
+ }
+end:
+ return status;
+}
+
+enum lttng_rotation_status
+lttng_rotation_schedule_periodic_set_period(
+ struct lttng_rotation_schedule *schedule,
+ uint64_t period_us)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ struct lttng_rotation_schedule_periodic *periodic_schedule;
+
+ if (!schedule || period_us == 0 || period_us == -1ULL ||
+ schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ periodic_schedule = container_of(schedule,
+ struct lttng_rotation_schedule_periodic,
+ parent);
+ periodic_schedule->period.us = period_us;
+ periodic_schedule->period.set = true;
+end:
+ return status;
+}
+
+void lttng_rotation_schedule_destroy(struct lttng_rotation_schedule *schedule)
+{
+ if (!schedule) {
+ return;
+ }
+ free(schedule);
+}
+
+void lttng_rotation_schedules_destroy(
+ struct lttng_rotation_schedules *schedules)
+{
+ unsigned int i;
+
+ if (!schedules) {
+ return;
+ }
+
+ for (i = 0; i < schedules->count; i++) {
+ lttng_rotation_schedule_destroy(schedules->schedules[i]);
+ }
+ free(schedules);
+}
+
+
+enum lttng_rotation_status lttng_rotation_schedules_get_count(
+ const struct lttng_rotation_schedules *schedules,
+ unsigned int *count)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+
+ if (!schedules || !count) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ *count = schedules->count;
+end:
+ return status;
+}
+
+const struct lttng_rotation_schedule *lttng_rotation_schedules_get_at_index(
+ const struct lttng_rotation_schedules *schedules,
+ unsigned int index)
+{
+ const struct lttng_rotation_schedule *schedule = NULL;
+
+ if (!schedules || index >= schedules->count) {
+ goto end;
+ }
+
+ schedule = schedules->schedules[index];
+end:
+ return schedule;
+}
+
+enum lttng_rotation_status lttng_session_add_rotation_schedule(
+ const char *session_name,
+ const struct lttng_rotation_schedule *schedule)
+{
+ return lttng_rotation_update_schedule(session_name, schedule, true);
+}
+
+enum lttng_rotation_status lttng_session_remove_rotation_schedule(
+ const char *session_name,
+ const struct lttng_rotation_schedule *schedule)
+{
+ return lttng_rotation_update_schedule(session_name, schedule, false);
+}
+
+int lttng_session_list_rotation_schedules(
+ const char *session_name,
+ struct lttng_rotation_schedules **schedules)
+{
+ return get_schedules(session_name, schedules);
}