From: Timo Sirainen Date: Thu, 4 Mar 2010 18:00:01 +0000 (+0200) Subject: lib-master: Avoid sending status updates to master too often. X-Git-Tag: 2.0.beta4~135 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2037c54ef0239bf7814badab08fc15f945f560fb;p=thirdparty%2Fdovecot%2Fcore.git lib-master: Avoid sending status updates to master too often. --HG-- branch : HEAD --- diff --git a/src/lib-master/master-service-private.h b/src/lib-master/master-service-private.h index b8be76799f..3435960367 100644 --- a/src/lib-master/master-service-private.h +++ b/src/lib-master/master-service-private.h @@ -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; diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c index a87f1ba195..6277cd863c 100644 --- a/src/lib-master/master-service.c +++ b/src/lib-master/master-service.c @@ -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) {