char session_name[LTTNG_NAME_MAX];
/* > 0 if a timer is set. */
uint64_t timer_us;
+ /* > 0 if the session should rotate when it has written that many bytes. */
+ uint64_t size;
} LTTNG_PACKED;
/*
extern enum lttng_rotation_status lttng_rotation_schedule_attr_set_timer_period(
struct lttng_rotation_schedule_attr *attr, uint64_t timer);
+/*
+ * Set the size to rotate the session (bytes, -1ULL to disable).
+ */
+void lttng_rotation_schedule_attr_set_size(
+ struct lttng_rotation_schedule_attr *attr, uint64_t size);
+
/*
* lttng rotate session handle functions.
*/
*
* Called with session lock held.
*/
-int cmd_destroy_session(struct ltt_session *session, int wpipe)
+int cmd_destroy_session(struct ltt_session *session, int wpipe,
+ struct notification_thread_handle *notification_thread_handle)
{
int ret;
struct ltt_ust_session *usess;
sessiond_rotate_timer_stop(session);
}
+ if (session->rotate_size) {
+ unsubscribe_session_consumed_size_rotation(session, notification_thread_handle);
+ session->rotate_size = 0;
+ }
+
/*
* The rename of the current chunk is performed at stop, but if we rotated
* the session after the previous stop command, we need to rename the
* Return 0 on success or else an LTTNG_ERR code.
*/
int cmd_rotation_set_schedule(struct ltt_session *session,
- uint64_t timer_us, uint64_t size)
+ uint64_t timer_us, uint64_t size,
+ struct notification_thread_handle *notification_thread_handle)
{
int ret;
goto end;
}
+ if (size && size != -1ULL && session->rotate_size) {
+ ret = LTTNG_ERR_ROTATION_SIZE_SET;
+ goto end;
+ } else if (size == -1ULL && !session->rotate_size) {
+ ret = LTTNG_ERR_ROTATION_NO_SIZE_SET;
+ goto end;
+ }
+
if (timer_us && !session->rotate_timer_period) {
if (timer_us > UINT_MAX) {
ret = LTTNG_ERR_INVALID;
session->rotate_timer_period = 0;
}
+ if (size > 0) {
+ if (size == -1ULL) {
+ ret = unsubscribe_session_consumed_size_rotation(session,
+ notification_thread_handle);
+ if (ret) {
+ ret = LTTNG_ERR_UNK;
+ goto end;
+ }
+ session->rotate_size = 0;
+ } else {
+ ret = subscribe_session_consumed_size_rotation(session,
+ size, notification_thread_handle);
+ if (ret) {
+ PERROR("Subscribe to session usage");
+ ret = LTTNG_ERR_UNK;
+ goto end;
+ }
+ session->rotate_size = size;
+ }
+ }
+
ret = LTTNG_OK;
goto end;
size_t nb_uri, lttng_sock_cred *creds, unsigned int live_timer);
int cmd_create_session_snapshot(char *name, struct lttng_uri *uris,
size_t nb_uri, lttng_sock_cred *creds);
-int cmd_destroy_session(struct ltt_session *session, int wpipe);
+int cmd_destroy_session(struct ltt_session *session, int wpipe,
+ struct notification_thread_handle *notification_thread_handle);
/* Channel commands */
int cmd_disable_channel(struct ltt_session *session,
int cmd_session_get_current_output(struct ltt_session *session,
struct lttng_session_get_current_output_return *output_return);
int cmd_rotation_set_schedule(struct ltt_session *session, uint64_t timer_us,
- uint64_t size);
+ uint64_t size,
+ struct notification_thread_handle *notification_thread_handle);
#endif /* CMD_H */
/* Cleanup ALL session */
cds_list_for_each_entry_safe(sess, stmp,
&session_list_ptr->head, list) {
- cmd_destroy_session(sess, kernel_poll_pipe[1]);
+ cmd_destroy_session(sess, kernel_poll_pipe[1],
+ notification_thread_handle);
}
}
}
case LTTNG_DESTROY_SESSION:
{
- ret = cmd_destroy_session(cmd_ctx->session, kernel_poll_pipe[1]);
+ ret = cmd_destroy_session(cmd_ctx->session, kernel_poll_pipe[1],
+ notification_thread_handle);
/* Set session to NULL so we do not unlock it after free. */
cmd_ctx->session = NULL;
ret = cmd_rotation_set_schedule(cmd_ctx->session,
cmd_ctx->lsm->u.rotate_setup.timer_us,
- cmd_ctx->lsm->u.rotate_setup.size);
+ cmd_ctx->lsm->u.rotate_setup.size,
+ notification_thread_handle);
if (ret < 0) {
ret = -ret;
goto error;
struct timer_thread_parameters timer_thread_ctx;
/* Queue of rotation jobs populated by the sessiond-timer. */
struct rotation_thread_timer_queue *rotation_timer_queue = NULL;
+ sem_t notification_thread_ready;
init_kernel_workarounds();
goto exit_health;
}
+ /*
+ * The rotation thread needs the notification thread to be ready before
+ * creating the rotate_notification_channel, so we use this semaphore as
+ * a rendez-vous point.
+ */
+ sem_init(¬ification_thread_ready, 0, 0);
+
/* notification_thread_data acquires the pipes' read side. */
notification_thread_handle = notification_thread_handle_create(
ust32_channel_monitor_pipe,
ust64_channel_monitor_pipe,
- kernel_channel_monitor_pipe);
+ kernel_channel_monitor_pipe,
+ ¬ification_thread_ready);
if (!notification_thread_handle) {
retval = -1;
ERR("Failed to create notification thread shared data");
ust64_channel_rotate_pipe,
kernel_channel_rotate_pipe,
thread_quit_pipe[0],
- rotation_timer_queue);
+ rotation_timer_queue,
+ notification_thread_handle,
+ ¬ification_thread_ready);
if (!rotation_thread_handle) {
retval = -1;
ERR("Failed to create rotation thread shared data");
exit_client:
exit_rotation:
exit_notification:
+ sem_destroy(¬ification_thread_ready);
ret = pthread_join(health_thread, &status);
if (ret) {
errno = ret;
struct notification_thread_handle *notification_thread_handle_create(
struct lttng_pipe *ust32_channel_monitor_pipe,
struct lttng_pipe *ust64_channel_monitor_pipe,
- struct lttng_pipe *kernel_channel_monitor_pipe)
+ struct lttng_pipe *kernel_channel_monitor_pipe,
+ sem_t *notification_thread_ready)
{
int ret;
struct notification_thread_handle *handle;
} else {
handle->channel_monitoring_pipes.kernel_consumer = -1;
}
+ handle->notification_thread_ready = notification_thread_ready;
end:
return handle;
error:
if (!state->triggers_ht) {
goto error;
}
+ sem_post(handle->notification_thread_ready);
end:
return 0;
error:
#include <common/compat/poll.h>
#include <common/hashtable/hashtable.h>
#include <pthread.h>
+#include <semaphore.h>
struct notification_thread_handle {
/*
int ust64_consumer;
int kernel_consumer;
} channel_monitoring_pipes;
+ /*
+ * To inform the rotation thread we are ready.
+ */
+ sem_t *notification_thread_ready;
};
/**
struct notification_thread_handle *notification_thread_handle_create(
struct lttng_pipe *ust32_channel_monitor_pipe,
struct lttng_pipe *ust64_channel_monitor_pipe,
- struct lttng_pipe *kernel_channel_monitor_pipe);
+ struct lttng_pipe *kernel_channel_monitor_pipe,
+ sem_t *notification_thread_ready);
void notification_thread_handle_destroy(
struct notification_thread_handle *handle);
#include <signal.h>
#include <inttypes.h>
+#include <lttng/notification/channel-internal.h>
#include <lttng/rotate-internal.h>
#include "session.h"
#include "health-sessiond.h"
#include "cmd.h"
#include "utils.h"
+#include "notification-thread-commands.h"
#include <urcu.h>
#include <urcu/list.h>
end:
return ret;
}
+
+int subscribe_session_consumed_size_rotation(struct ltt_session *session, uint64_t size,
+ struct notification_thread_handle *notification_thread_handle)
+{
+ int ret;
+ enum lttng_condition_status condition_status;
+ enum lttng_notification_channel_status nc_status;
+ struct lttng_action *action;
+
+ session->rotate_condition = lttng_condition_session_consumed_size_create();
+ if (!session->rotate_condition) {
+ ERR("Failed to create session consumed size condition object");
+ ret = -1;
+ goto end;
+ }
+
+ condition_status = lttng_condition_session_consumed_size_set_threshold(
+ session->rotate_condition, size);
+ if (condition_status != LTTNG_CONDITION_STATUS_OK) {
+ ERR("Could not set session consumed size condition threshold (size = %" PRIu64 ")",
+ size);
+ ret = -1;
+ goto end;
+ }
+
+ condition_status =
+ lttng_condition_session_consumed_size_set_session_name(
+ session->rotate_condition, session->name);
+ if (condition_status != LTTNG_CONDITION_STATUS_OK) {
+ ERR("Could not set session consumed size condition session name (name = %s)",
+ session->name);
+ ret = -1;
+ goto end;
+ }
+
+ action = lttng_action_notify_create();
+ if (!action) {
+ ERR("Could not create notify action");
+ ret = -1;
+ goto end;
+ }
+
+ session->rotate_trigger = lttng_trigger_create(session->rotate_condition,
+ action);
+ if (!session->rotate_trigger) {
+ ERR("Could not create size-based rotation trigger");
+ ret = -1;
+ goto end;
+ }
+
+ nc_status = lttng_notification_channel_subscribe(
+ rotate_notification_channel, session->rotate_condition);
+ if (nc_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
+ ERR("Could not subscribe to session consumed size notification");
+ ret = -1;
+ goto end;
+ }
+
+ ret = notification_thread_command_register_trigger(
+ notification_thread_handle, session->rotate_trigger);
+ if (ret < 0 && ret != -LTTNG_ERR_TRIGGER_EXISTS) {
+ ERR("Register trigger, %s", lttng_strerror(ret));
+ ret = -1;
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+ return ret;
+}
+
+int unsubscribe_session_consumed_size_rotation(struct ltt_session *session,
+ struct notification_thread_handle *notification_thread_handle)
+{
+ int ret = 0;
+ enum lttng_notification_channel_status status;
+
+ status = lttng_notification_channel_unsubscribe(
+ rotate_notification_channel,
+ session->rotate_condition);
+ if (status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
+ ERR("Session unsubscribe error: %d", (int) status);
+ ret = -1;
+ goto end;
+ }
+
+ ret = notification_thread_command_unregister_trigger(
+ notification_thread_handle, session->rotate_trigger);
+ if (ret != LTTNG_OK) {
+ ERR("Session unregister trigger error: %d", ret);
+ goto end;
+ }
+
+ ret = 0;
+end:
+ return ret;
+}
#ifndef ROTATE_H
#define ROTATE_H
+#include <lttng/notification/channel-internal.h>
#include "rotation-thread.h"
/*
struct cds_lfht_node rotate_channels_ht_node;
};
+
extern struct cds_lfht *channel_pending_rotate_ht;
+extern struct lttng_notification_channel *rotate_notification_channel;
unsigned long hash_channel_key(struct rotation_channel_key *key);
int rotate_add_channel_pending(uint64_t key, enum lttng_domain_type domain,
struct ltt_session *session);
+/*
+ * Subscribe/unsubscribe the notification_channel from the rotation_thread to
+ * session usage notifications to perform size-based rotations.
+ */
+int subscribe_session_consumed_size_rotation(struct ltt_session *session,
+ uint64_t size,
+ struct notification_thread_handle *notification_thread_handle);
+int unsubscribe_session_consumed_size_rotation(struct ltt_session *session,
+ struct notification_thread_handle *notification_thread_handle);
+
#endif /* ROTATE_H */
*/
struct cds_lfht *channel_pending_rotate_ht;
+struct lttng_notification_channel *rotate_notification_channel = NULL;
+
struct rotation_thread_state {
struct lttng_poll_event events;
};
struct lttng_pipe *ust64_channel_rotate_pipe,
struct lttng_pipe *kernel_channel_rotate_pipe,
int thread_quit_pipe,
- struct rotation_thread_timer_queue *rotation_timer_queue)
+ struct rotation_thread_timer_queue *rotation_timer_queue,
+ struct notification_thread_handle *notification_thread_handle,
+ sem_t *notification_thread_ready)
{
struct rotation_thread_handle *handle;
}
handle->thread_quit_pipe = thread_quit_pipe;
handle->rotation_timer_queue = rotation_timer_queue;
+ handle->notification_thread_handle = notification_thread_handle;
+ handle->notification_thread_ready = notification_thread_ready;
end:
return handle;
{
lttng_poll_clean(&state->events);
cds_lfht_destroy(channel_pending_rotate_ht, NULL);
+ if (rotate_notification_channel) {
+ lttng_notification_channel_destroy(rotate_notification_channel);
+ }
}
static
goto end;
}
+ /*
+ * We wait until the notification thread is ready to create the
+ * notification channel and add it to the poll_set.
+ */
+ sem_wait(handle->notification_thread_ready);
+ rotate_notification_channel = lttng_notification_channel_create(
+ lttng_session_daemon_notification_endpoint);
+ if (!rotate_notification_channel) {
+ ERR("[rotation-thread] Could not create notification channel");
+ ret = -1;
+ goto end;
+ }
+ ret = lttng_poll_add(&state->events, rotate_notification_channel->socket,
+ LPOLLIN | LPOLLERR);
+ if (ret < 0) {
+ ERR("[rotation-thread] Failed to add notification fd to pollset");
+ goto end;
+ }
+
end:
return ret;
}
}
DBG("[rotation-thread] Received notification for chan %" PRIu64
- ", domain %d\n", key, domain);
+ ", domain %d", key, domain);
channel_info = lookup_channel_pending(key, domain);
if (!channel_info) {
return ret;
}
+int handle_condition(
+ const struct lttng_condition *condition,
+ const struct lttng_evaluation *evaluation,
+ struct notification_thread_handle *notification_thread_handle)
+{
+ int ret = 0;
+ const char *condition_session_name = NULL;
+ enum lttng_condition_type condition_type;
+ enum lttng_condition_status condition_status;
+ enum lttng_evaluation_status evaluation_status;
+ uint64_t consumed;
+ struct ltt_session *session;
+
+ condition_type = lttng_condition_get_type(condition);
+
+ if (condition_type != LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE) {
+ ret = -1;
+ ERR("[rotation-thread] Condition type and session usage type are not the same");
+ goto end;
+ }
+
+ /* Fetch info to test */
+ condition_status = lttng_condition_session_consumed_size_get_session_name(
+ condition, &condition_session_name);
+ if (condition_status != LTTNG_CONDITION_STATUS_OK) {
+ ERR("[rotation-thread] Session name could not be fetched");
+ ret = -1;
+ goto end;
+ }
+ evaluation_status = lttng_evaluation_session_consumed_size_get_consumed_size(evaluation,
+ &consumed);
+ if (evaluation_status != LTTNG_EVALUATION_STATUS_OK) {
+ ERR("[rotation-thread] Failed to get evaluation");
+ ret = -1;
+ goto end;
+ }
+
+ session_lock_list();
+ session = session_find_by_name(condition_session_name);
+ if (!session) {
+ ret = -1;
+ session_unlock_list();
+ ERR("[rotation-thread] Session \"%s\" not found",
+ condition_session_name);
+ goto end;
+ }
+ session_lock(session);
+ session_unlock_list();
+
+ ret = unsubscribe_session_consumed_size_rotation(session,
+ notification_thread_handle);
+ if (ret) {
+ goto end;
+ }
+
+ ret = cmd_rotate_session(session, NULL);
+ if (ret == -LTTNG_ERR_ROTATION_PENDING) {
+ DBG("Rotate already pending, subscribe to the next threshold value");
+ ret = 0;
+ } else if (ret != LTTNG_OK) {
+ ERR("[rotation-thread] Failed to rotate on size notification with error: %s",
+ lttng_strerror(ret));
+ ret = -1;
+ goto end_unlock;
+ }
+ ret = subscribe_session_consumed_size_rotation(session,
+ consumed + session->rotate_size,
+ notification_thread_handle);
+ if (ret) {
+ ERR("[rotation-thread] Failed to subscribe to session consumed size condition");
+ goto end_unlock;
+ }
+ ret = 0;
+
+end_unlock:
+ session_unlock(session);
+end:
+ return ret;
+}
+
+static
+int handle_notification_channel(int fd, uint32_t revents,
+ struct rotation_thread_handle *handle,
+ struct rotation_thread_state *state)
+{
+ int ret;
+ struct lttng_notification *notification;
+ enum lttng_notification_channel_status status;
+ const struct lttng_evaluation *notification_evaluation;
+ const struct lttng_condition *notification_condition;
+
+ /* Receive the next notification. */
+ status = lttng_notification_channel_get_next_notification(
+ rotate_notification_channel,
+ ¬ification);
+
+ switch (status) {
+ case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
+ break;
+ case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
+ /* Not an error, we will wait for the next one */
+ ret = 0;
+ goto end;;
+ case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
+ ERR("Notification channel was closed");
+ ret = -1;
+ goto end;
+ default:
+ /* Unhandled conditions / errors. */
+ ERR("Unknown notification channel status");
+ ret = -1;
+ goto end;
+ }
+
+ notification_condition = lttng_notification_get_condition(notification);
+ notification_evaluation = lttng_notification_get_evaluation(notification);
+
+ ret = handle_condition(notification_condition, notification_evaluation,
+ handle->notification_thread_handle);
+
+end:
+ lttng_notification_destroy(notification);
+ if (ret != 0) {
+ goto end;
+ }
+
+
+ return ret;
+}
+
void *thread_rotation(void *data)
{
int ret;
ERR("[rotation-thread] Handle channel rotation pipe");
goto error;
}
+ } else if (fd == rotate_notification_channel->socket) {
+ ret = handle_notification_channel(fd, revents,
+ handle, &state);
+ if (ret) {
+ ERR("[rotation-thread] Error occured while handling activity on notification channel socket");
+ goto error;
+ }
}
}
}
#include <common/compat/poll.h>
#include <common/hashtable/hashtable.h>
#include <pthread.h>
+#include <semaphore.h>
#include "session.h"
/*
int kernel_consumer;
/* quit pipe */
int thread_quit_pipe;
+
struct rotation_thread_timer_queue *rotation_timer_queue;
+
+ /* Access to the notification thread cmd_queue */
+ struct notification_thread_handle *notification_thread_handle;
+
+ sem_t *notification_thread_ready;
};
struct rotation_thread_handle *rotation_thread_handle_create(
struct lttng_pipe *ust64_channel_rotate_pipe,
struct lttng_pipe *kernel_channel_rotate_pipe,
int thread_quit_pipe,
- struct rotation_thread_timer_queue *rotation_timer_queue);
+ struct rotation_thread_timer_queue *rotation_timer_queue,
+ struct notification_thread_handle *notification_thread_handle,
+ sem_t *notification_thread_ready);
void rotation_thread_handle_destroy(
struct rotation_thread_handle *handle);
* chunk.
*/
bool rotated_after_last_stop;
+ /*
+ * Condition and trigger for size-based rotations.
+ */
+ struct lttng_condition *rotate_condition;
+ struct lttng_trigger *rotate_trigger;
};
/* Prototypes */
OPT_HELP = 1,
OPT_LIST_OPTIONS,
OPT_TIMER,
+ OPT_SIZE,
};
static struct poptOption long_options[] = {
{"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
{"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
{"timer", 0, POPT_ARG_NONE, 0, OPT_TIMER, 0, 0},
+ {"size", 0, POPT_ARG_NONE, 0, OPT_SIZE, 0, 0},
{0, 0, 0, 0, 0, 0, 0}
};
-static int setup_rotate(char *session_name, uint64_t timer)
+static int setup_rotate(char *session_name, uint64_t timer, uint64_t size)
{
int ret = 0;
struct lttng_rotation_schedule_attr *attr = NULL;
lttng_rotation_schedule_attr_set_timer_period(attr, timer);
MSG("Disabling rotation timer on session %s", session_name);
}
+ if (size == -1ULL) {
+ lttng_rotation_schedule_attr_set_size(attr, size);
+ MSG("Disabling rotation based on size on session %s", session_name);
+ }
ret = lttng_rotation_set_schedule(attr);
if (ret) {
static poptContext pc;
char *session_name = NULL;
bool free_session_name = false;
- uint64_t timer = 0;
+ uint64_t timer = 0, size = 0;
pc = poptGetContext(NULL, argc, argv, long_options, 0);
popt_ret = poptReadDefaultConfig(pc, 0);
case OPT_TIMER:
timer = -1ULL;
break;
+ case OPT_SIZE:
+ size = -1ULL;
+ break;
default:
ret = CMD_UNDEFINED;
goto end;
}
/* No config options, just rotate the session now */
- if (timer == 0) {
- ERR("No timer given");
+ if (timer == 0 && size == 0) {
+ ERR("Missing timer period (--timer) or size limit (--size) option");
success = 0;
command_ret = -1;
} else {
- command_ret = setup_rotate(session_name, timer);
+ command_ret = setup_rotate(session_name, timer, size);
}
if (command_ret) {
OPT_HELP = 1,
OPT_LIST_OPTIONS,
OPT_TIMER,
+ OPT_SIZE,
};
static struct poptOption long_options[] = {
{"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
{"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}
};
-static int setup_rotate(char *session_name, uint64_t timer)
+static int setup_rotate(char *session_name, uint64_t timer, uint64_t size)
{
int ret = 0;
struct lttng_rotation_schedule_attr *attr = NULL;
}
}
}
+ if (size) {
+ lttng_rotation_schedule_attr_set_size(attr, size);
+ MSG("Configuring session %s to rotate every %" PRIu64 " bytes written",
+ session_name, size);
+ if (lttng_opt_mi) {
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_rotation_size, size);
+ if (ret) {
+ goto end;
+ }
+ }
+ }
ret = lttng_rotation_set_schedule(attr);
if (ret) {
static poptContext pc;
char *session_name = NULL;
char *opt_arg = NULL;
- uint64_t timer = 0;
bool free_session_name = false;
+ uint64_t timer = 0, size = 0;
pc = poptGetContext(NULL, argc, argv, long_options, 0);
popt_ret = poptReadDefaultConfig(pc, 0);
}
DBG("Rotation timer set to %" PRIu64, timer);
break;
+ case OPT_SIZE:
+ errno = 0;
+ opt_arg = poptGetOptArg(pc);
+ if (utils_parse_size_suffix(opt_arg, &size) < 0 || !size) {
+ ERR("Wrong value for --size option: %s", opt_arg);
+ ret = CMD_ERROR;
+ goto end;
+ }
+ DBG("Rotation size set to %" PRIu64, size);
+ break;
default:
ret = CMD_UNDEFINED;
goto end;
}
/* No config options, just rotate the session now */
- if (timer == 0) {
- ERR("No timer given");
+ if (timer == 0 && size == 0) {
+ ERR("No timer or size given");
success = 0;
command_ret = -1;
} else {
- command_ret = setup_rotate(session_name, timer);
+ command_ret = setup_rotate(session_name, timer, size);
}
if (command_ret) {
{
int ret, started = -1, snapshot_mode = -1;
uint64_t live_timer_interval = UINT64_MAX,
- rotation_timer_interval = 0;
+ rotation_timer_interval = 0,
+ rotation_size = 0;
xmlChar *name = NULL;
xmlChar *shm_path = NULL;
xmlNodePtr domains_node = NULL;
xmlNodePtr output_node = NULL;
xmlNodePtr node;
+ xmlNodePtr attributes_child;
struct lttng_domain *kernel_domain = NULL;
struct lttng_domain *ust_domain = NULL;
struct lttng_domain *jul_domain = NULL;
} else {
/*
* attributes, snapshot_mode, live_timer_interval, rotation_size,
- * rotation_timer_interval. */
- xmlNodePtr attributes_child =
- xmlFirstElementChild(node);
-
- if (!strcmp((const char *) attributes_child->name,
- config_element_snapshot_mode)) {
- /* snapshot_mode */
- xmlChar *snapshot_mode_content =
- xmlNodeGetContent(attributes_child);
- if (!snapshot_mode_content) {
- ret = -LTTNG_ERR_NOMEM;
- goto error;
- }
+ * rotation_timer_interval.
+ */
+ for (attributes_child = xmlFirstElementChild(node); attributes_child;
+ attributes_child = xmlNextElementSibling(attributes_child)) {
+ if (!strcmp((const char *) attributes_child->name,
+ config_element_snapshot_mode)) {
+ /* snapshot_mode */
+ xmlChar *snapshot_mode_content =
+ xmlNodeGetContent(attributes_child);
+ if (!snapshot_mode_content) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto error;
+ }
- ret = parse_bool(snapshot_mode_content, &snapshot_mode);
- free(snapshot_mode_content);
- if (ret) {
- ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
- goto error;
- }
- } else if (!strcmp((const char *) attributes_child->name,
- config_element_live_timer_interval)) {
- /* live_timer_interval */
- xmlChar *timer_interval_content =
- xmlNodeGetContent(attributes_child);
- if (!timer_interval_content) {
- ret = -LTTNG_ERR_NOMEM;
- goto error;
- }
+ ret = parse_bool(snapshot_mode_content, &snapshot_mode);
+ free(snapshot_mode_content);
+ if (ret) {
+ ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
+ goto error;
+ }
+ } else if (!strcmp((const char *) attributes_child->name,
+ config_element_live_timer_interval)) {
+ /* live_timer_interval */
+ xmlChar *timer_interval_content =
+ xmlNodeGetContent(attributes_child);
+ if (!timer_interval_content) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto error;
+ }
- ret = parse_uint(timer_interval_content, &live_timer_interval);
- free(timer_interval_content);
- if (ret) {
- ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
- goto error;
+ ret = parse_uint(timer_interval_content, &live_timer_interval);
+ free(timer_interval_content);
+ if (ret) {
+ ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
+ goto error;
+ }
}
- }
- if (!strcmp((const char *) attributes_child->name,
- config_element_rotation_timer_interval)) {
- /* rotation_timer_interval */
- xmlChar *timer_interval_content =
- xmlNodeGetContent(attributes_child);
- if (!timer_interval_content) {
- ret = -LTTNG_ERR_NOMEM;
- goto error;
+ if (!strcmp((const char *) attributes_child->name,
+ config_element_rotation_timer_interval)) {
+ /* rotation_timer_interval */
+ xmlChar *timer_interval_content =
+ xmlNodeGetContent(attributes_child);
+ if (!timer_interval_content) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ ret = parse_uint(timer_interval_content, &rotation_timer_interval);
+ free(timer_interval_content);
+ if (ret) {
+ ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
+ goto error;
+ }
}
+ if (!strcmp((const char *) attributes_child->name,
+ config_element_rotation_size)) {
+ /* rotation_size */
+ xmlChar *rotation_size_content =
+ xmlNodeGetContent(attributes_child);
+ if (!rotation_size_content) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto error;
+ }
- ret = parse_uint(timer_interval_content, &rotation_timer_interval);
- free(timer_interval_content);
- if (ret) {
- ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
- goto error;
+ ret = parse_uint(rotation_size_content, &rotation_size);
+ free(rotation_size_content);
+ if (ret) {
+ ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
+ goto error;
+ }
}
}
}
}
}
- if (rotation_timer_interval) {
+ if (rotation_timer_interval || rotation_size) {
struct lttng_rotation_schedule_attr *rotation_attr = lttng_rotation_schedule_attr_create();
if (!rotation_attr) {
}
lttng_rotation_schedule_attr_set_timer_period(rotation_attr,
rotation_timer_interval);
+ lttng_rotation_schedule_attr_set_size(rotation_attr, rotation_size);
ret = lttng_rotation_set_schedule(rotation_attr);
lttng_rotation_schedule_attr_destroy(rotation_attr);
if (ret) {
return status;
}
+void lttng_rotation_schedule_attr_set_size(
+ struct lttng_rotation_schedule_attr *attr, uint64_t size)
+{
+ attr->size = size;
+}
+
enum lttng_rotation_status lttng_rotation_handle_get_state(
struct lttng_rotation_handle *rotation_handle,
enum lttng_rotation_state *state)
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);
}
*rotate_timer = get_timer->rotate_timer;
-
ret = 0;
-
end:
free(get_timer);
return ret;