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