Size-based rotation
authorJulien Desfossez <jdesfossez@efficios.com>
Fri, 9 Feb 2018 19:53:32 +0000 (14:53 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 3 Apr 2018 16:12:29 +0000 (12:12 -0400)
The user can now configure the desired size of each chunk, every time a
chunk is bigger than the specified size, a rotation is automatically
started. The size of a chunk is measured by polling from the monitoring
thread, so the accuracy depends on the monitoring sampling rate.

Signed-off-by: Julien Desfossez <jdesfossez@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
16 files changed:
include/lttng/rotate-internal.h
include/lttng/rotation.h
src/bin/lttng-sessiond/cmd.c
src/bin/lttng-sessiond/cmd.h
src/bin/lttng-sessiond/main.c
src/bin/lttng-sessiond/notification-thread.c
src/bin/lttng-sessiond/notification-thread.h
src/bin/lttng-sessiond/rotate.c
src/bin/lttng-sessiond/rotate.h
src/bin/lttng-sessiond/rotation-thread.c
src/bin/lttng-sessiond/rotation-thread.h
src/bin/lttng-sessiond/session.h
src/bin/lttng/commands/disable_rotation.c
src/bin/lttng/commands/enable_rotation.c
src/common/config/session-config.c
src/lib/lttng-ctl/rotate.c

index 29ea8c8359f7e6513b81a7583927f001bcac8efa..f5e4dc950b4875ef5e239e2ec497042d34643c59 100644 (file)
@@ -48,6 +48,8 @@ struct lttng_rotation_schedule_attr {
        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;
 
 /*
index 186cbd6f6464f7bd761e8d593a2b390083f711db..00d68d7e5c5015a71982f1fe3d5690eca205f135 100644 (file)
@@ -134,6 +134,12 @@ extern enum lttng_rotation_status lttng_rotation_schedule_attr_set_session_name(
 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.
  */
index 375324aec870bea400ce620b95fe8603ed1357cd..e88d7a2f77eb41534062fbe01dbe990d11f65855 100644 (file)
@@ -2953,7 +2953,8 @@ error:
  *
  * 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;
@@ -2975,6 +2976,11 @@ int cmd_destroy_session(struct ltt_session *session, int wpipe)
                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
@@ -4659,7 +4665,8 @@ end:
  * 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;
 
@@ -4683,6 +4690,14 @@ int cmd_rotation_set_schedule(struct ltt_session *session,
                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;
@@ -4707,6 +4722,27 @@ int cmd_rotation_set_schedule(struct ltt_session *session,
                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;
index 25c4ad506bc9c45519483cc240e312f53e6a53b5..6a6c87eaa0b6ea303f11afb63e27c8243bc23857 100644 (file)
@@ -34,7 +34,8 @@ int cmd_create_session_uri(char *name, struct lttng_uri *uris,
                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,
@@ -126,6 +127,7 @@ int cmd_rotate_get_info(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 */
index cec3a504a01371aed72f81f419f43a66539ba162..4c885d7b74f63f2c51447932fe36afccabb81d8e 100644 (file)
@@ -595,7 +595,8 @@ static void sessiond_cleanup(void)
                /* 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);
                }
        }
 
@@ -3771,7 +3772,8 @@ error_add_context:
        }
        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;
@@ -4200,7 +4202,8 @@ error_add_context:
 
                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;
@@ -5709,6 +5712,7 @@ int main(int argc, char **argv)
        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();
 
@@ -6116,11 +6120,19 @@ int main(int argc, char **argv)
                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(&notification_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,
+                       &notification_thread_ready);
        if (!notification_thread_handle) {
                retval = -1;
                ERR("Failed to create notification thread shared data");
@@ -6158,7 +6170,9 @@ int main(int argc, char **argv)
                        ust64_channel_rotate_pipe,
                        kernel_channel_rotate_pipe,
                        thread_quit_pipe[0],
-                       rotation_timer_queue);
+                       rotation_timer_queue,
+                       notification_thread_handle,
+                       &notification_thread_ready);
        if (!rotation_thread_handle) {
                retval = -1;
                ERR("Failed to create rotation thread shared data");
@@ -6346,6 +6360,7 @@ exit_dispatch:
 exit_client:
 exit_rotation:
 exit_notification:
+       sem_destroy(&notification_thread_ready);
        ret = pthread_join(health_thread, &status);
        if (ret) {
                errno = ret;
index 62d47ee54182cfc3da2a27d3dbf4ba37638a67f4..a8acd6f2482d5646d32a9e05fdab2e2abbe6bf38 100644 (file)
@@ -85,7 +85,8 @@ end:
 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;
@@ -141,6 +142,7 @@ struct notification_thread_handle *notification_thread_handle_create(
        } else {
                handle->channel_monitoring_pipes.kernel_consumer = -1;
        }
+       handle->notification_thread_ready = notification_thread_ready;
 end:
        return handle;
 error:
@@ -432,6 +434,7 @@ int init_thread_state(struct notification_thread_handle *handle,
        if (!state->triggers_ht) {
                goto error;
        }
+       sem_post(handle->notification_thread_ready);
 end:
        return 0;
 error:
index 011ffbfaed7b71f5287e11787b4ab0014f108201..2169b2efb69968b2e82ff83434abf45ec904050b 100644 (file)
@@ -26,6 +26,7 @@
 #include <common/compat/poll.h>
 #include <common/hashtable/hashtable.h>
 #include <pthread.h>
+#include <semaphore.h>
 
 struct notification_thread_handle {
        /*
@@ -47,6 +48,10 @@ 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;
 };
 
 /**
@@ -185,7 +190,8 @@ struct notification_thread_state {
 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);
 
index 4264cd4bd91fadeca704f9895b4c0733610a1b9c..bd6dbddf95492492eb02a5dd87d138cfffe6c108 100644 (file)
@@ -32,6 +32,7 @@
 #include <signal.h>
 #include <inttypes.h>
 
+#include <lttng/notification/channel-internal.h>
 #include <lttng/rotate-internal.h>
 
 #include "session.h"
@@ -41,6 +42,7 @@
 #include "health-sessiond.h"
 #include "cmd.h"
 #include "utils.h"
+#include "notification-thread-commands.h"
 
 #include <urcu.h>
 #include <urcu/list.h>
@@ -401,3 +403,101 @@ int relay_rotate_pending(struct ltt_session *session, uint64_t chunk_id)
 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;
+}
index ea2383f2c9415cc14286587bc74804da5f8f1c89..6dc3b7aa189768f9c47787f12e03ae031d0585ee 100644 (file)
@@ -18,6 +18,7 @@
 #ifndef ROTATE_H
 #define ROTATE_H
 
+#include <lttng/notification/channel-internal.h>
 #include "rotation-thread.h"
 
 /*
@@ -41,7 +42,9 @@ struct rotation_channel_info {
        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);
 
@@ -60,4 +63,14 @@ int relay_rotate_pending(struct ltt_session *session, uint64_t chunk_id);
 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 */
index ecccc7bb01ab00bbbba7dd71675b88a7f4b08e3d..9f15ed06edacbae130cef7ac9e4c0c7793ecee87 100644 (file)
@@ -53,6 +53,8 @@
  */
 struct cds_lfht *channel_pending_rotate_ht;
 
+struct lttng_notification_channel *rotate_notification_channel = NULL;
+
 struct rotation_thread_state {
        struct lttng_poll_event events;
 };
@@ -143,7 +145,9 @@ 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)
 {
        struct rotation_thread_handle *handle;
 
@@ -184,6 +188,8 @@ struct rotation_thread_handle *rotation_thread_handle_create(
        }
        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;
@@ -257,6 +263,9 @@ void fini_thread_state(struct rotation_thread_state *state)
 {
        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
@@ -282,6 +291,25 @@ int init_thread_state(struct rotation_thread_handle *handle,
                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;
 }
@@ -328,7 +356,7 @@ int handle_channel_rotation_pipe(int fd, uint32_t revents,
        }
 
        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) {
@@ -566,6 +594,136 @@ end:
        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,
+                       &notification);
+
+       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;
@@ -639,6 +797,13 @@ void *thread_rotation(void *data)
                                        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;
+                               }
                        }
                }
        }
index c7bca0c4b7937fc6e2d4dc114255d32b3af4fc39..41da6e0444e209855fe14d7986834e9dd1979c99 100644 (file)
@@ -26,6 +26,7 @@
 #include <common/compat/poll.h>
 #include <common/hashtable/hashtable.h>
 #include <pthread.h>
+#include <semaphore.h>
 #include "session.h"
 
 /*
@@ -49,7 +50,13 @@ struct rotation_thread_handle {
        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(
@@ -57,7 +64,9 @@ 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);
index e00e51cc6dedab784759db6c764589236737667c..ab9b1a9a4355edf8aa98ecb29d7350802d96fb26 100644 (file)
@@ -186,6 +186,11 @@ struct ltt_session {
         * chunk.
         */
        bool rotated_after_last_stop;
+       /*
+        * Condition and trigger for size-based rotations.
+        */
+       struct lttng_condition *rotate_condition;
+       struct lttng_trigger *rotate_trigger;
 };
 
 /* Prototypes */
index b0de06d9f99ec5399da5498da34d9009c86fd9df..e917cbdc172beb785f172f9bcb0c09e7d4cdff8f 100644 (file)
@@ -39,6 +39,7 @@ enum {
        OPT_HELP = 1,
        OPT_LIST_OPTIONS,
        OPT_TIMER,
+       OPT_SIZE,
 };
 
 static struct poptOption long_options[] = {
@@ -47,10 +48,11 @@ 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;
@@ -86,6 +88,10 @@ static int setup_rotate(char *session_name, uint64_t timer)
                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) {
@@ -140,7 +146,7 @@ int cmd_disable_rotation(int argc, const char **argv)
        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);
@@ -161,6 +167,9 @@ int cmd_disable_rotation(int argc, const char **argv)
                case OPT_TIMER:
                        timer = -1ULL;
                        break;
+               case OPT_SIZE:
+                       size = -1ULL;
+                       break;
                default:
                        ret = CMD_UNDEFINED;
                        goto end;
@@ -203,12 +212,12 @@ int cmd_disable_rotation(int argc, const char **argv)
        }
 
        /* 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) {
index a746f016f4ceb189b9fff4243ab23cf0ef1cc874..80fc495ba8de8dcbf94a76bf98cc9c164e3f8ef3 100644 (file)
@@ -40,6 +40,7 @@ enum {
        OPT_HELP = 1,
        OPT_LIST_OPTIONS,
        OPT_TIMER,
+       OPT_SIZE,
 };
 
 static struct poptOption long_options[] = {
@@ -48,10 +49,11 @@ 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;
@@ -93,6 +95,18 @@ static int setup_rotate(char *session_name, uint64_t timer)
                        }
                }
        }
+       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) {
@@ -147,8 +161,8 @@ int cmd_enable_rotation(int argc, const char **argv)
        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);
@@ -181,6 +195,16 @@ int cmd_enable_rotation(int argc, const char **argv)
                        }
                        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;
@@ -223,12 +247,12 @@ int cmd_enable_rotation(int argc, const char **argv)
        }
 
        /* 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) {
index 49047b1d6acc9f573aa5fb537dd9a6826bae8ede..8b91f32d5aebf47f6a05af102bb3358c069155b7 100644 (file)
@@ -2519,12 +2519,14 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
 {
        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;
@@ -2579,58 +2581,76 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
                } 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;
+                                       }
                                }
                        }
                }
@@ -2770,7 +2790,7 @@ domain_init_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) {
@@ -2783,6 +2803,7 @@ domain_init_error:
                }
                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) {
index 9ad32f962c035a90429bef225edc75919aa73b41..d9907cc67e34b3c33304f989b69d920c81cb1c03 100644 (file)
@@ -149,6 +149,12 @@ end:
        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)
@@ -323,6 +329,7 @@ int lttng_rotation_set_schedule(
        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);
 
@@ -349,9 +356,7 @@ int lttng_rotation_schedule_get_timer_period(const char *session_name,
        }
 
        *rotate_timer = get_timer->rotate_timer;
-
        ret = 0;
-
 end:
        free(get_timer);
        return ret;
This page took 0.066171 seconds and 4 git commands to generate.