dovecot-2.1: Keep track of what Dovecot instances have been exec...

dovecot at dovecot.org dovecot at dovecot.org
Mon Feb 6 21:27:08 EET 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/5f60958926e1
changeset: 14068:5f60958926e1
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Feb 06 21:26:55 2012 +0200
description:
Keep track of what Dovecot instances have been executed and their instance_name.
doveadm instance command can be used to list/remove them.

diffstat:

 src/doveadm/Makefile.am          |    1 +
 src/doveadm/doveadm-instance.c   |  110 ++++++++++++
 src/doveadm/doveadm.c            |    1 +
 src/doveadm/doveadm.h            |    1 +
 src/lib-master/Makefile.am       |    2 +
 src/lib-master/master-instance.c |  331 +++++++++++++++++++++++++++++++++++++++
 src/lib-master/master-instance.h |   43 +++++
 src/master/main.c                |   31 +++
 8 files changed, 520 insertions(+), 0 deletions(-)

diffs (truncated from 617 to 300 lines):

diff -r 6cd1b564fcc2 -r 5f60958926e1 src/doveadm/Makefile.am
--- a/src/doveadm/Makefile.am	Mon Feb 06 21:25:37 2012 +0200
+++ b/src/doveadm/Makefile.am	Mon Feb 06 21:26:55 2012 +0200
@@ -91,6 +91,7 @@
 	doveadm-dump-log.c \
 	doveadm-dump-mailboxlog.c \
 	doveadm-dump-thread.c \
+	doveadm-instance.c \
 	doveadm-kick.c \
 	doveadm-log.c \
 	doveadm-master.c \
diff -r 6cd1b564fcc2 -r 5f60958926e1 src/doveadm/doveadm-instance.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/doveadm-instance.c	Mon Feb 06 21:26:55 2012 +0200
@@ -0,0 +1,110 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "master-instance.h"
+#include "doveadm.h"
+#include "doveadm-print.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+
+extern struct doveadm_cmd doveadm_cmd_instance[];
+
+static void instance_cmd_help(doveadm_command_t *cmd) ATTR_NORETURN;
+
+static bool pid_file_read(const char *path)
+{
+	char buf[32];
+	int fd;
+	ssize_t ret;
+	pid_t pid;
+	bool found = FALSE;
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1) {
+		if (errno != ENOENT)
+			i_error("open(%s) failed: %m", path);
+		return FALSE;
+	}
+
+	ret = read(fd, buf, sizeof(buf));
+	if (ret < 0)
+		i_error("read(%s) failed: %m", path);
+	else if (ret > 0 && buf[ret-1] == '\n') {
+		buf[ret-1] = '\0';
+		if (str_to_pid(buf, &pid) == 0) {
+			found = !(pid == getpid() ||
+				  (kill(pid, 0) < 0 && errno == ESRCH));
+		}
+	}
+	(void)close(fd);
+	return found;
+}
+
+static void cmd_instance_list(int argc ATTR_UNUSED, char *argv[] ATTR_UNUSED)
+{
+	struct master_instance_list *list;
+	struct master_instance_list_iter *iter;
+	const struct master_instance *inst;
+	const char *pidfile_path;
+
+	doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
+	doveadm_print_header("path", "path", DOVEADM_PRINT_HEADER_FLAG_EXPAND);
+	doveadm_print_header_simple("name");
+	doveadm_print_header_simple("running");
+
+	list = master_instance_list_init(MASTER_INSTANCE_PATH);
+	iter = master_instance_list_iterate_init(list);
+	while ((inst = master_instance_iterate_list_next(iter)) != NULL) {
+		doveadm_print(inst->base_dir);
+		doveadm_print(inst->name);
+		pidfile_path = t_strconcat(inst->base_dir, "/master.pid", NULL);
+		if (pid_file_read(pidfile_path))
+			doveadm_print("yes");
+		else
+			doveadm_print("no");
+	}
+	master_instance_iterate_list_deinit(&iter);
+	master_instance_list_deinit(&list);
+}
+
+static void cmd_instance_remove(int argc, char *argv[])
+{
+	struct master_instance_list *list;
+	int ret;
+
+	if (argc != 2)
+		instance_cmd_help(cmd_instance_remove);
+
+	list = master_instance_list_init(MASTER_INSTANCE_PATH);
+	if ((ret = master_instance_list_remove(list, argv[1])) < 0)
+		i_error("Failed to remove instance");
+	else if (ret == 0)
+		i_error("Instance already didn't exist");
+	master_instance_list_deinit(&list);
+}
+
+struct doveadm_cmd doveadm_cmd_instance[] = {
+	{ cmd_instance_list, "instance list", "" },
+	{ cmd_instance_remove, "instance remove", "<base dir>" }
+};
+
+static void instance_cmd_help(doveadm_command_t *cmd)
+{
+	unsigned int i;
+
+	for (i = 0; i < N_ELEMENTS(doveadm_cmd_instance); i++) {
+		if (doveadm_cmd_instance[i].cmd == cmd)
+			help(&doveadm_cmd_instance[i]);
+	}
+	i_unreached();
+}
+
+void doveadm_register_instance_commands(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < N_ELEMENTS(doveadm_cmd_instance); i++)
+		doveadm_register_cmd(&doveadm_cmd_instance[i]);
+}
diff -r 6cd1b564fcc2 -r 5f60958926e1 src/doveadm/doveadm.c
--- a/src/doveadm/doveadm.c	Mon Feb 06 21:25:37 2012 +0200
+++ b/src/doveadm/doveadm.c	Mon Feb 06 21:26:55 2012 +0200
@@ -321,6 +321,7 @@
 	} else {
 		quick_init = FALSE;
 		doveadm_register_director_commands();
+		doveadm_register_instance_commands();
 		doveadm_register_mount_commands();
 		doveadm_register_proxy_commands();
 		doveadm_register_log_commands();
diff -r 6cd1b564fcc2 -r 5f60958926e1 src/doveadm/doveadm.h
--- a/src/doveadm/doveadm.h	Mon Feb 06 21:25:37 2012 +0200
+++ b/src/doveadm/doveadm.h	Mon Feb 06 21:26:55 2012 +0200
@@ -38,6 +38,7 @@
 void doveadm_register_director_commands(void);
 void doveadm_register_proxy_commands(void);
 void doveadm_register_log_commands(void);
+void doveadm_register_instance_commands(void);
 void doveadm_register_mount_commands(void);
 
 #endif
diff -r 6cd1b564fcc2 -r 5f60958926e1 src/lib-master/Makefile.am
--- a/src/lib-master/Makefile.am	Mon Feb 06 21:25:37 2012 +0200
+++ b/src/lib-master/Makefile.am	Mon Feb 06 21:26:55 2012 +0200
@@ -14,6 +14,7 @@
 	ipc-client.c \
 	ipc-server.c \
 	master-auth.c \
+	master-instance.c \
 	master-login.c \
 	master-login-auth.c \
 	master-service.c \
@@ -27,6 +28,7 @@
 	ipc-client.h \
 	ipc-server.h \
 	master-auth.h \
+	master-instance.h \
 	master-interface.h \
 	master-login.h \
 	master-login-auth.h \
diff -r 6cd1b564fcc2 -r 5f60958926e1 src/lib-master/master-instance.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-master/master-instance.c	Mon Feb 06 21:26:55 2012 +0200
@@ -0,0 +1,331 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "istream.h"
+#include "ostream.h"
+#include "file-dotlock.h"
+#include "str.h"
+#include "strescape.h"
+#include "master-instance.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+
+struct master_instance_list {
+	pool_t pool;
+	const char *path;
+
+	ARRAY_DEFINE(instances, struct master_instance);
+};
+
+struct master_instance_list_iter {
+	struct master_instance_list *list;
+	unsigned int idx;
+};
+
+static const struct dotlock_settings dotlock_set = {
+	.timeout = 1,
+	.stale_timeout = 60
+};
+
+struct master_instance_list *master_instance_list_init(const char *path)
+{
+	struct master_instance_list *list;
+	pool_t pool;
+
+	pool = pool_alloconly_create("master instances", 256);
+	list = p_new(pool, struct master_instance_list, 1);
+	list->pool = pool;
+	list->path = p_strdup(pool, path);
+	p_array_init(&list->instances, pool, 8);
+	return list;
+}
+
+void master_instance_list_deinit(struct master_instance_list **_list)
+{
+	struct master_instance_list *list = *_list;
+
+	*_list = NULL;
+	pool_unref(&list->pool);
+}
+
+static void master_instance_list_drop_stale(struct master_instance_list *list)
+{
+	const struct master_instance *instances;
+	unsigned int i, count;
+	time_t stale_timestamp = time(NULL) - MASTER_INSTANCE_AUTO_STALE_SECS;
+
+	instances = array_get(&list->instances, &count);
+	for (i = 0; i < count; ) {
+		if (instances[i].name[0] == '\0' &&
+		    instances[i].last_used < stale_timestamp) {
+			array_delete(&list->instances, i, 1);
+			instances = array_get(&list->instances, &count);
+		} else {
+			i++;
+		}
+	}
+}
+
+static int
+master_instance_list_add_line(struct master_instance_list *list,
+			      const char *line)
+{
+	struct master_instance *inst;
+	const char *const *args;
+	time_t last_used;
+
+	/* <last used> <name> <base dir> */
+	args = t_strsplit_tabescaped(line);
+	if (str_array_length(args) != 3)
+		return -1;
+	if (str_to_time(args[0], &last_used) < 0)
+		return -1;
+
+	inst = array_append_space(&list->instances);
+	inst->last_used = last_used;
+	inst->name = p_strdup(list->pool, args[1]);
+	inst->base_dir = p_strdup(list->pool, args[2]);
+	return 0;
+}
+
+static int master_instance_list_refresh(struct master_instance_list *list)
+{
+	struct istream *input;
+	const char *line;
+	int fd, ret = 0;
+
+	array_clear(&list->instances);
+
+	fd = open(list->path, O_RDONLY);
+	if (fd == -1) {
+		if (errno == ENOENT)
+			return 0;
+
+		i_error("open(%s) failed: %m", list->path);
+		return -1;
+	}
+	input = i_stream_create_fd(fd, PATH_MAX, TRUE);
+	while ((line = i_stream_read_next_line(input)) != NULL) T_BEGIN {
+		if (master_instance_list_add_line(list, line) < 0)
+			i_error("Invalid line in %s: %s", list->path, line);
+	} T_END;
+	if (input->stream_errno != 0) {
+		i_error("read(%s) failed: %m", line);
+		ret = -1;
+	}
+	i_stream_destroy(&input);
+	return ret;
+}
+
+static int
+master_instance_list_write(struct master_instance_list *list,
+			   int fd, const char *path)
+{
+	struct ostream *output;
+	const struct master_instance *inst;
+	string_t *str = t_str_new(128);
+
+	output = o_stream_create_fd(fd, 0, FALSE);


More information about the dovecot-cvs mailing list