dovecot-2.0: master: Added process_min_avail setting for services.

dovecot at dovecot.org dovecot at dovecot.org
Fri Sep 4 22:44:42 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/af7f0be02d3b
changeset: 9872:af7f0be02d3b
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Sep 04 15:44:36 2009 -0400
description:
master: Added process_min_avail setting for services.

diffstat:

4 files changed, 75 insertions(+), 32 deletions(-)
src/master/master-settings.c |   59 ++++++++++++++++++++++++------------------
src/master/master-settings.h |    1 
src/master/service-monitor.c |   43 ++++++++++++++++++++++++++----
src/master/service-process.c |    4 +-

diffs (216 lines):

diff -r 8a38b5b82a1d -r af7f0be02d3b src/master/master-settings.c
--- a/src/master/master-settings.c	Fri Sep 04 15:00:37 2009 -0400
+++ b/src/master/master-settings.c	Fri Sep 04 15:44:36 2009 -0400
@@ -100,6 +100,7 @@ static struct setting_define service_set
 
 	DEF(SET_BOOL, drop_priv_before_exec),
 
+	DEF(SET_UINT, process_min_avail),
 	DEF(SET_UINT, process_limit),
 	DEF(SET_UINT, client_limit),
 	DEF(SET_UINT, service_count),
@@ -131,6 +132,7 @@ static struct service_settings service_d
 
 	MEMBER(drop_priv_before_exec) FALSE,
 
+	MEMBER(process_min_avail) 0,
 	MEMBER(process_limit) (unsigned int)-1,
 	MEMBER(client_limit) 0,
 	MEMBER(service_count) 0,
@@ -285,52 +287,61 @@ master_settings_verify(void *_set, pool_
 	}
 	services = array_get(&set->services, &count);
 	for (i = 0; i < count; i++) {
-		if (*services[i]->name == '\0') {
+		struct service_settings *service = services[i];
+
+		if (*service->name == '\0') {
 			*error_r = t_strdup_printf(
 				"Service #%d is missing name", i);
 			return FALSE;
 		}
-		if (*services[i]->type != '\0' &&
-		    strcmp(services[i]->type, "log") != 0 &&
-		    strcmp(services[i]->type, "config") != 0 &&
-		    strcmp(services[i]->type, "anvil") != 0 &&
-		    strcmp(services[i]->type, "auth") != 0 &&
-		    strcmp(services[i]->type, "auth-source") != 0) {
+		if (*service->type != '\0' &&
+		    strcmp(service->type, "log") != 0 &&
+		    strcmp(service->type, "config") != 0 &&
+		    strcmp(service->type, "anvil") != 0 &&
+		    strcmp(service->type, "auth") != 0 &&
+		    strcmp(service->type, "auth-source") != 0) {
 			*error_r = t_strconcat("Unknown service type: ",
-					       services[i]->type, NULL);
+					       service->type, NULL);
 			return FALSE;
 		}
 		for (j = 0; j < i; j++) {
-			if (strcmp(services[i]->name, services[j]->name) == 0) {
+			if (strcmp(service->name, services[j]->name) == 0) {
 				*error_r = t_strdup_printf(
 					"Duplicate service name: %s",
-					services[i]->name);
+					service->name);
 				return FALSE;
 			}
 		}
 	}
 	for (i = 0; i < count; i++) {
-		if (*services[i]->executable != '/') {
-			services[i]->executable =
+		struct service_settings *service = services[i];
+
+		if (*service->executable != '/') {
+			service->executable =
 				p_strconcat(pool, set->libexec_dir, "/",
-					    services[i]->executable, NULL);
-		}
-		if (*services[i]->chroot != '/' &&
-		    *services[i]->chroot != '\0') {
-			services[i]->chroot =
+					    service->executable, NULL);
+		}
+		if (*service->chroot != '/' && *service->chroot != '\0') {
+			service->chroot =
 				p_strconcat(pool, set->base_dir, "/",
-					    services[i]->chroot, NULL);
-		}
-		if (services[i]->drop_priv_before_exec &&
-		    *services[i]->chroot != '\0') {
+					    service->chroot, NULL);
+		}
+		if (service->drop_priv_before_exec &&
+		    *service->chroot != '\0') {
 			*error_r = t_strdup_printf("service(%s): "
 				"drop_priv_before_exec=yes can't be "
-				"used with chroot", services[i]->name);
+				"used with chroot", service->name);
 			return FALSE;
 		}
-		fix_file_listener_paths(&services[i]->unix_listeners,
+		if (service->process_min_avail > service->process_limit) {
+			*error_r = t_strdup_printf("service(%s): "
+				"process_min_avail is higher than process_limit",
+				service->name);
+			return FALSE;
+		}
+		fix_file_listener_paths(&service->unix_listeners,
 					pool, set->base_dir);
-		fix_file_listener_paths(&services[i]->fifo_listeners,
+		fix_file_listener_paths(&service->fifo_listeners,
 					pool, set->base_dir);
 	}
 	set->protocols_split = p_strsplit(pool, set->protocols, " ");
diff -r 8a38b5b82a1d -r af7f0be02d3b src/master/master-settings.h
--- a/src/master/master-settings.h	Fri Sep 04 15:00:37 2009 -0400
+++ b/src/master/master-settings.h	Fri Sep 04 15:44:36 2009 -0400
@@ -31,6 +31,7 @@ struct service_settings {
 
 	bool drop_priv_before_exec;
 
+	unsigned int process_min_avail;
 	unsigned int process_limit;
 	unsigned int client_limit;
 	unsigned int service_count;
diff -r 8a38b5b82a1d -r af7f0be02d3b src/master/service-monitor.c
--- a/src/master/service-monitor.c	Fri Sep 04 15:00:37 2009 -0400
+++ b/src/master/service-monitor.c	Fri Sep 04 15:44:36 2009 -0400
@@ -17,7 +17,7 @@
 
 #define SERVICE_STARTUP_FAILURE_THROTTLE_SECS 60
 
-void service_monitor_stop(struct service *service);
+static void service_monitor_start_extra_avail(struct service *service);
 
 static void service_status_input(struct service *service)
 {
@@ -79,8 +79,10 @@ static void service_status_input(struct 
 			process->available_count - status.available_count;
 		if (status.available_count == 0) {
 			i_assert(service->process_avail > 0);
-			if (--service->process_avail == 0)
-                                service_monitor_listen_start(service);
+			service->process_avail--;
+
+			service_monitor_start_extra_avail(service);
+			service_monitor_listen_start(service);
 		}
 		process->idle_start = 0;
 	} else {
@@ -127,10 +129,36 @@ static void service_accept(struct servic
 		service_monitor_listen_stop(service);
 }
 
+static void service_monitor_start_extra_avail(struct service *service)
+{
+	unsigned int i, count;
+
+	if (service->process_avail >= service->set->process_min_avail)
+		return;
+
+	count = service->set->process_min_avail - service->process_avail;
+	if (service->process_count + count > service->process_limit)
+		count = service->process_limit - service->process_count;
+
+	for (i = 0; i < count; i++) {
+		if (service_process_create(service, NULL, NULL) == NULL) {
+			service_monitor_throttle(service);
+			break;
+		}
+	}
+	if (i > 0 && service->listening) {
+		/* we created some processes, they'll do the listening now */
+		service_monitor_listen_stop(service);
+	}
+}
+
 void service_monitor_listen_start(struct service *service)
 {
 	struct service_listener *const *listeners;
 	unsigned int i, count;
+
+	if (service->process_avail > 0)
+		return;
 
 	service->listening = TRUE;
 	service->listen_pending = FALSE;
@@ -185,8 +213,10 @@ void services_monitor_start(struct servi
 				       service_status_input, services[i]);
 		}
 
-		if (services[i]->status_fd[0] != -1)
+		if (services[i]->status_fd[0] != -1) {
+			service_monitor_start_extra_avail(services[i]);
 			service_monitor_listen_start(services[i]);
+		}
 	}
 
 	if (service_process_create(service_list->log, NULL, NULL) != NULL)
@@ -265,8 +295,9 @@ void services_monitor_reap_children(void
 			service_process_failure(process, status);
 		}
 		service_process_destroy(process);
-
-                if (service->process_avail == 0 && service->to_throttle == NULL)
+		service_monitor_start_extra_avail(service);
+
+                if (service->to_throttle == NULL)
 			service_monitor_listen_start(service);
 	}
 }
diff -r 8a38b5b82a1d -r af7f0be02d3b src/master/service-process.c
--- a/src/master/service-process.c	Fri Sep 04 15:00:37 2009 -0400
+++ b/src/master/service-process.c	Fri Sep 04 15:44:36 2009 -0400
@@ -451,8 +451,8 @@ service_process_create(struct service *s
 	int fd[2];
 	pid_t pid;
 
-	if (!service->listening) {
-		/* probably throttling service, don't create new processes */
+	if (service->to_throttle != NULL) {
+		/* throttling service, don't create new processes */
 		return NULL;
 	}
 	if (service->process_count >= service->process_limit) {


More information about the dovecot-cvs mailing list