]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master: Avoid sending status updates to master too often.
authorTimo Sirainen <tss@iki.fi>
Thu, 4 Mar 2010 18:00:01 +0000 (20:00 +0200)
committerTimo Sirainen <tss@iki.fi>
Thu, 4 Mar 2010 18:00:01 +0000 (20:00 +0200)
--HG--
branch : HEAD

src/lib-master/master-service-private.h
src/lib-master/master-service.c

index b8be76799fb7656d3655b0d737f88b7043fc3313..3435960367f17dc7da2de6b9de0ccc3b1664b2e8 100644 (file)
@@ -33,7 +33,11 @@ struct master_service {
        struct io *io_status_write, *io_status_error;
        unsigned int service_count_left;
        unsigned int total_available_count;
+
        struct master_status master_status;
+       unsigned int last_sent_status_avail_count;
+       time_t last_sent_status_time;
+       struct timeout *to_status;
 
        void (*die_callback)(void);
        struct timeout *to_die;
index a87f1ba195f5a6d6da961755225a2411e700d53c..6277cd863c63b5e361d087164681a61f119983d1 100644 (file)
@@ -634,6 +634,8 @@ void master_service_deinit(struct master_service **_service)
                timeout_remove(&service->to_die);
        if (service->to_overflow_state != NULL)
                timeout_remove(&service->to_overflow_state);
+       if (service->to_status != NULL)
+               timeout_remove(&service->to_status);
        if (service->io_status_error != NULL)
                io_remove(&service->io_status_error);
        if (service->io_status_write != NULL)
@@ -802,9 +804,32 @@ static bool master_status_update_is_important(struct master_service *service)
 void master_status_update(struct master_service *service)
 {
        ssize_t ret;
+       bool important_update;
 
-       if (service->master_status.pid == 0 || service->delay_status_updates)
-               return; /* closed */
+       important_update = master_status_update_is_important(service);
+       if (service->master_status.pid == 0 || service->delay_status_updates ||
+           service->master_status.available_count ==
+           service->last_sent_status_avail_count) {
+               /* a) closed, b) updating to same state */
+               if (service->to_status != NULL)
+                       timeout_remove(&service->to_status);
+               return;
+       }
+       if (ioloop_time == service->last_sent_status_time &&
+           !important_update) {
+               /* don't spam master */
+               if (service->to_status != NULL)
+                       timeout_reset(service->to_status);
+               else {
+                       service->to_status =
+                               timeout_add(1000, master_status_update,
+                                           service);
+               }
+               return;
+       }
+
+       if (service->to_status != NULL)
+               timeout_remove(&service->to_status);
 
        ret = write(MASTER_STATUS_FD, &service->master_status,
                    sizeof(service->master_status));
@@ -814,6 +839,9 @@ void master_status_update(struct master_service *service)
                        /* delayed important update sent successfully */
                        io_remove(&service->io_status_write);
                }
+               service->last_sent_status_time = ioloop_time;
+               service->last_sent_status_avail_count =
+                       service->master_status.available_count;
                service->initial_status_sent = TRUE;
        } else if (ret == 0) {
                /* shouldn't happen? */
@@ -824,7 +852,7 @@ void master_status_update(struct master_service *service)
                if (errno != EPIPE)
                        i_error("write(master_status_fd) failed: %m");
                service->master_status.pid = 0;
-       } else if (master_status_update_is_important(service)) {
+       } else if (important_update) {
                /* reader is busy, but it's important to get this notification
                   through. send it when possible. */
                if (service->io_status_write == NULL) {