dovecot-1.2: Added dict_process_count setting for creating multi...

dovecot at dovecot.org dovecot at dovecot.org
Sat Jan 17 20:56:34 EET 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/67c08c386702
changeset: 8649:67c08c386702
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Jan 17 13:56:24 2009 -0500
description:
Added dict_process_count setting for creating multiple dict processes.

diffstat:

6 files changed, 137 insertions(+), 94 deletions(-)
src/master/dict-process.c         |  216 +++++++++++++++++++++----------------
src/master/dict-process.h         |    6 -
src/master/main.c                 |    6 -
src/master/master-settings-defs.c |    1 
src/master/master-settings.c      |    1 
src/master/master-settings.h      |    1 

diffs (truncated from 364 to 300 lines):

diff -r 5bd547dbb8fc -r 67c08c386702 src/master/dict-process.c
--- a/src/master/dict-process.c	Sat Jan 17 13:41:44 2009 -0500
+++ b/src/master/dict-process.c	Sat Jan 17 13:56:24 2009 -0500
@@ -16,26 +16,36 @@
 
 #define DICT_SERVER_SOCKET_NAME "dict-server"
 
+struct dict_listener {
+	char *path;
+	int fd;
+	struct io *io;
+
+	struct dict_process *processes;
+};
+
 struct dict_process {
 	struct child_process process;
-	char *path;
-	int fd;
-
+	struct dict_process *next;
+
+	struct dict_listener *listener;
 	struct log_io *log;
-	struct io *io;
 };
 
-static struct dict_process *dict_process;
-
-static void dict_process_unlisten(struct dict_process *process);
-
-static int dict_process_start(struct dict_process *process)
-{
+static struct dict_listener *dict_listener;
+
+static int dict_process_create(struct dict_listener *listener)
+{
+	struct dict_process *process;
 	struct log_io *log;
 	const char *executable, *const *dicts;
 	unsigned int i, count;
 	int log_fd;
 	pid_t pid;
+
+	process = i_new(struct dict_process, 1);
+	process->process.type = PROCESS_TYPE_DICT;
+	process->listener = listener;
 
 	log_fd = log_create_pipe(&log, 0);
 	if (log_fd < 0)
@@ -48,11 +58,15 @@ static int dict_process_start(struct dic
 
 	if (pid < 0) {
 		(void)close(log_fd);
+		i_free(process);
 		return -1;
 	}
 
 	if (pid != 0) {
 		/* master */
+		process->next = process->listener->processes;
+		process->listener->processes = process;
+
 		child_process_add(pid, &process->process);
 		log_set_prefix(log, "dict: ");
 		log_set_pid(log, pid);
@@ -60,7 +74,6 @@ static int dict_process_start(struct dic
 
 		process->log = log;
 		log_ref(process->log);
-                dict_process_unlisten(process);
 		return 0;
 	}
 	log_set_prefix(log, "master-dict: ");
@@ -75,14 +88,15 @@ static int dict_process_start(struct dic
 	/* stderr = log, 3 = listener */
 	if (dup2(log_fd, 2) < 0)
 		i_fatal("dup2(stderr) failed: %m");
-	if (dup2(process->fd, 3) < 0)
+	if (dup2(process->listener->fd, 3) < 0)
 		i_fatal("dup2(3) failed: %m");
 
 	for (i = 0; i <= 3; i++)
 		fd_close_on_exec(i, FALSE);
 
 	child_process_init_env();
-	env_put(t_strconcat("DICT_LISTEN_FROM_FD=", process->path, NULL));
+	env_put(t_strconcat("DICT_LISTEN_FROM_FD=",
+			    process->listener->path, NULL));
 
 	if (settings_root->defaults->dict_db_config != NULL) {
 		env_put(t_strconcat("DB_CONFIG=",
@@ -105,92 +119,118 @@ static int dict_process_start(struct dic
 	return -1;
 }
 
-static void dict_process_listen_input(struct dict_process *process)
-{
-	i_assert(process->log == NULL);
-	dict_process_start(process);
-}
-
-static int dict_process_listen(struct dict_process *process)
-{
+static void dict_process_deinit(struct dict_process *process)
+{
+	struct dict_process **p;
+
+	for (p = &process->listener->processes; *p != NULL; p++) {
+		if (*p == process) {
+			*p = process->next;
+			break;
+		}
+	}
+
+	if (process->log != NULL)
+		log_unref(process->log);
+	i_free(process);
+}
+
+static void dict_listener_input(struct dict_listener *listener)
+{
+	unsigned int i;
+	int fd;
+
+	i_assert(listener->processes == NULL);
+
+	for (i = 0; i < settings_root->defaults->dict_process_count; i++) {
+		if (dict_process_create(listener) < 0)
+			break;
+	}
+	if (i > 0)
+		io_remove(&listener->io);
+	else {
+		/* failed to create dict process, so just reject this
+		   connection and try again later */
+		fd = net_accept(listener->fd, NULL, NULL);
+		if (fd >= 0)
+			(void)close(fd);
+	}
+}
+
+static struct dict_listener *dict_listener_init(const char *path)
+{
+	struct dict_listener *listener;
 	mode_t old_umask;
 
+	listener = i_new(struct dict_listener, 1);
+	listener->path = i_strdup(path);
 	old_umask = umask(0);
-	process->fd = net_listen_unix_unlink_stale(process->path, 128);
+	listener->fd = net_listen_unix_unlink_stale(path, 128);
 	umask(old_umask);
-	if (process->fd == -1) {
+	if (listener->fd == -1) {
 		if (errno == EADDRINUSE)
-			i_error("Socket already exists: %s", process->path);
+			i_fatal("Socket already exists: %s", path);
 		else
-			i_error("net_listen_unix(%s) failed: %m", process->path);
-		return -1;
-	}
-	fd_close_on_exec(process->fd, TRUE);
-	process->io = io_add(process->fd, IO_READ,
-			     dict_process_listen_input, process);
-
-	return process->fd != -1 ? 0 : -1;
-}
-
-static void dict_process_unlisten(struct dict_process *process)
-{
-	if (process->fd == -1)
-		return;
-
-	io_remove(&process->io);
-
-	if (close(process->fd) < 0)
-		i_error("close(dict) failed: %m");
-	process->fd = -1;
+			i_fatal("net_listen_unix(%s) failed: %m", path);
+	}
+	fd_close_on_exec(listener->fd, TRUE);
+	listener->io = io_add(listener->fd, IO_READ,
+			      dict_listener_input, listener);
+	return listener;
+}
+
+static void dict_listener_deinit(struct dict_listener *listener)
+{
+	if (listener->io != NULL)
+		io_remove(&listener->io);
+	if (close(listener->fd) < 0)
+		i_error("close(dict listener) failed: %m");
+
+	while (listener->processes != NULL)
+		dict_process_deinit(listener->processes);
 }
 
 static void
-dict_process_destroyed(struct child_process *process,
-		       pid_t pid ATTR_UNUSED,
-		       bool abnormal_exit ATTR_UNUSED)
-{
-	struct dict_process *p = (struct dict_process *)process;
-
-	if (p->log != NULL) {
-		/* not killed by ourself */
-		log_unref(p->log);
-		p->log = NULL;
-	}
-	(void)dict_process_listen(p);
-}
-
-void dict_process_init(void)
-{
-	struct dict_process *process;
-
-	process = dict_process = i_new(struct dict_process, 1);
-	process->process.type = PROCESS_TYPE_DICT;
-	process->fd = -1;
-	process->path = i_strconcat(settings_root->defaults->base_dir,
-				    "/"DICT_SERVER_SOCKET_NAME, NULL);
-	(void)dict_process_listen(process);
+dict_process_destroyed(struct child_process *_process,
+		       pid_t pid ATTR_UNUSED, bool abnormal_exit ATTR_UNUSED)
+{
+	struct dict_process *process = (struct dict_process *)_process;
+	struct dict_listener *listener = process->listener;
+
+	dict_process_deinit(process);
+	if (listener->processes == NULL) {
+		/* last listener died, create new ones */
+		listener->io = io_add(listener->fd, IO_READ,
+				      dict_listener_input, listener);
+	}
+}
+
+void dict_processes_init(void)
+{
+	const char *path;
+
+	path = t_strconcat(settings_root->defaults->base_dir,
+			   "/"DICT_SERVER_SOCKET_NAME, NULL);
+	dict_listener = dict_listener_init(path);
 
 	child_process_set_destroy_callback(PROCESS_TYPE_DICT,
 					   dict_process_destroyed);
 }
 
-void dict_process_deinit(void)
-{
-	struct dict_process *process = dict_process;
-
-	dict_process_unlisten(process);
-	if (process->log != NULL)
-		log_unref(process->log);
-	i_free(process->path);
-	i_free(process);
-}
-
-void dict_process_kill(void)
-{
-	struct dict_process *process = dict_process;
-
-	if (process->log != NULL) {
-		log_unref(process->log);
-		process->log = NULL;
-	}
-}
+void dict_processes_deinit(void)
+{
+	dict_listener_deinit(dict_listener);
+}
+
+void dict_processes_kill(void)
+{
+	struct dict_process *process;
+
+	process = dict_listener->processes;
+	for (; process != NULL; process = process->next) {
+		if (process->log != NULL) {
+			log_unref(process->log);
+			process->log = NULL;
+		}
+	}
+}
diff -r 5bd547dbb8fc -r 67c08c386702 src/master/dict-process.h
--- a/src/master/dict-process.h	Sat Jan 17 13:41:44 2009 -0500
+++ b/src/master/dict-process.h	Sat Jan 17 13:56:24 2009 -0500
@@ -1,8 +1,8 @@
 #ifndef DICT_PROCESS_H
 #define DICT_PROCESS_H
 
-void dict_process_init(void);
-void dict_process_deinit(void);
-void dict_process_kill(void);
+void dict_processes_init(void);
+void dict_processes_deinit(void);
+void dict_processes_kill(void);
 


More information about the dovecot-cvs mailing list