]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
replicator: Added doveadm socket for communicating with "doveadm replicator".
authorTimo Sirainen <tss@iki.fi>
Sun, 24 Mar 2013 14:48:29 +0000 (16:48 +0200)
committerTimo Sirainen <tss@iki.fi>
Sun, 24 Mar 2013 14:48:29 +0000 (16:48 +0200)
src/replication/replication-common.h
src/replication/replicator/Makefile.am
src/replication/replicator/doveadm-connection.c [new file with mode: 0644]
src/replication/replicator/doveadm-connection.h [new file with mode: 0644]
src/replication/replicator/replicator-queue.c
src/replication/replicator/replicator-queue.h
src/replication/replicator/replicator-settings.c
src/replication/replicator/replicator.c

index 89832ffdabdae3c0832e1a62a3aafa71c45eb831..999734032c6aa5a3f74e8932e5a889f8c0bbf33b 100644 (file)
@@ -12,11 +12,28 @@ enum replication_priority {
        REPLICATION_PRIORITY_SYNC
 };
 
+static inline const char *
+replicator_priority_to_str(enum replication_priority priority)
+{
+       switch (priority) {
+       case REPLICATION_PRIORITY_NONE:
+               return "none";
+       case REPLICATION_PRIORITY_LOW:
+               return "low";
+       case REPLICATION_PRIORITY_HIGH:
+               return "high";
+       case REPLICATION_PRIORITY_SYNC:
+               return "sync";
+       }
+}
+
 static inline int
 replication_priority_parse(const char *str,
                           enum replication_priority *priority_r)
 {
-       if (strcmp(str, "low") == 0)
+       if (strcmp(str, "none") == 0)
+               *priority_r = REPLICATION_PRIORITY_NONE;
+       else if (strcmp(str, "low") == 0)
                *priority_r = REPLICATION_PRIORITY_LOW;
        else if (strcmp(str, "high") == 0)
                *priority_r = REPLICATION_PRIORITY_HIGH;
index adf21ca74f73a930cbdb99464ec6e7f5d2a4798c..b3510f808528796456dcc8b7b3c35b5f943b68c5 100644 (file)
@@ -15,6 +15,7 @@ replicator_LDADD = $(LIBDOVECOT)
 replicator_DEPENDENCIES = $(LIBDOVECOT_DEPS)
 
 replicator_SOURCES = \
+       doveadm-connection.c \
        dsync-client.c \
        replicator.c \
        replicator-brain.c \
@@ -23,6 +24,7 @@ replicator_SOURCES = \
        notify-connection.c
 
 noinst_HEADERS = \
+       doveadm-connection.h \
        dsync-client.h \
        replicator-brain.h \
        replicator-queue.h \
diff --git a/src/replication/replicator/doveadm-connection.c b/src/replication/replicator/doveadm-connection.c
new file mode 100644 (file)
index 0000000..8f8d87d
--- /dev/null
@@ -0,0 +1,114 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "connection.h"
+#include "ostream.h"
+#include "str.h"
+#include "strescape.h"
+#include "wildcard-match.h"
+#include "master-service.h"
+#include "replicator-queue.h"
+#include "doveadm-connection.h"
+
+#include <unistd.h>
+
+#define REPLICATOR_DOVEADM_MAJOR_VERSION 1
+#define REPLICATOR_DOVEADM_MINOR_VERSION 0
+
+struct doveadm_connection {
+       struct connection conn;
+       struct replicator_queue *queue;
+};
+static struct connection_list *doveadm_connections;
+
+static int
+client_input_status(struct doveadm_connection *client, const char *const *args)
+{
+       struct replicator_user *const *users, *user;
+       unsigned int i, count;
+       const char *mask = args[0];
+       string_t *str = t_str_new(128);
+
+       users = replicator_queue_get_users(client->queue, &count);
+       for (i = 0; i < count; i++) {
+               user = users[i];
+               if (mask != NULL && wildcard_match(user->username, mask))
+                       continue;
+
+               str_truncate(str, 0);
+               str_append_tabescaped(str, user->username);
+               str_append_c(str, '\t');
+               str_append(str, replicator_priority_to_str(user->priority));
+               str_printfa(str, "\t%lld\t%lld\t%d\n",
+                           (long long)user->last_fast_sync,
+                           (long long)user->last_full_sync,
+                           user->last_sync_failed);
+               o_stream_send(client->conn.output, str_data(str), str_len(str));
+       }
+       o_stream_send(client->conn.output, "\n", 1);
+       return 0;
+}
+
+static int client_input_args(struct connection *conn, const char *const *args)
+{
+       struct doveadm_connection *client = (struct doveadm_connection *)conn;
+       const char *cmd = args[0];
+
+       if (cmd == NULL) {
+               i_error("%s: Empty command", conn->name);
+               return 0;
+       }
+       args++;
+
+       if (strcmp(cmd, "STATUS") == 0)
+               return client_input_status(client, args);
+       i_error("%s: Unknown command: %s", conn->name, cmd);
+       return -1;
+}
+
+static void client_destroy(struct connection *conn)
+{
+       struct doveadm_connection *client = (struct doveadm_connection *)conn;
+
+       connection_deinit(&client->conn);
+       i_free(client);
+
+       master_service_client_connection_destroyed(master_service);
+}
+
+void doveadm_connection_create(struct replicator_queue *queue, int fd)
+{
+       struct doveadm_connection *client;
+
+       client = i_new(struct doveadm_connection, 1);
+       client->queue = queue;
+       connection_init_server(doveadm_connections, &client->conn,
+                              "(doveadm client)", fd, fd);
+}
+
+static struct connection_settings doveadm_conn_set = {
+       .service_name_in = "replicator-doveadm-client",
+       .service_name_out = "replicator-doveadm-server",
+       .major_version = REPLICATOR_DOVEADM_MAJOR_VERSION,
+       .minor_version = REPLICATOR_DOVEADM_MINOR_VERSION,
+
+       .input_max_size = (size_t)-1,
+       .output_max_size = (size_t)-1,
+       .client = FALSE
+};
+
+static const struct connection_vfuncs doveadm_conn_vfuncs = {
+       .destroy = client_destroy,
+       .input_args = client_input_args
+};
+
+void doveadm_connections_init(void)
+{
+       doveadm_connections = connection_list_init(&doveadm_conn_set,
+                                                  &doveadm_conn_vfuncs);
+}
+
+void doveadm_connections_deinit(void)
+{
+       connection_list_deinit(&doveadm_connections);
+}
diff --git a/src/replication/replicator/doveadm-connection.h b/src/replication/replicator/doveadm-connection.h
new file mode 100644 (file)
index 0000000..27081c3
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef DOVEADM_CONNECTION_H
+#define DOVEADM_CONNECTION_H
+
+void doveadm_connection_create(struct replicator_queue *queue, int fd);
+
+void doveadm_connections_init(void);
+void doveadm_connections_deinit(void);
+
+#endif
index 64d9334fe6843050d71f8483cb0a1e857008e572..5736f07fb2e63dd7b6009bef7b39ab92f3f8d327 100644 (file)
@@ -371,3 +371,14 @@ int replicator_queue_export(struct replicator_queue *queue, const char *path)
        o_stream_destroy(&output);
        return ret;
 }
+
+struct replicator_user *const *
+replicator_queue_get_users(struct replicator_queue *queue,
+                          unsigned int *count_r)
+{
+       struct priorityq_item *const *items =
+               priorityq_items(queue->user_queue);
+
+       *count_r = priorityq_count(queue->user_queue);
+       return (void *)items;
+}
index 5e9e9e35e4c6cf711caae7d205c2d77b84a8c42c..20f9d1b9ed8c98a84a3108dd21041cf5a72d7517 100644 (file)
@@ -8,6 +8,7 @@ struct replicator_user {
        struct priorityq_item item;
 
        char *username;
+       /* dsync state for incremental syncing */
        char *state;
        /* last time this user's state was updated */
        time_t last_update;
@@ -58,4 +59,9 @@ void replicator_queue_push(struct replicator_queue *queue,
 int replicator_queue_import(struct replicator_queue *queue, const char *path);
 int replicator_queue_export(struct replicator_queue *queue, const char *path);
 
+/* Returns an (unsorted) array of all users in the queue. */
+struct replicator_user *const *
+replicator_queue_get_users(struct replicator_queue *queue,
+                          unsigned int *count_r);
+
 #endif
index c06f25875fe50b4465f6bb6e4353ebc7fff4d5a5..f5f3bdcb3903867918d7a754af6b0853bb915790 100644 (file)
@@ -8,10 +8,12 @@
 
 /* <settings checks> */
 static struct file_listener_settings replicator_unix_listeners_array[] = {
-       { "replicator", 0600, "$default_internal_user", "" }
+       { "replicator", 0600, "$default_internal_user", "" },
+       { "replicator-doveadm", 0600, "$default_internal_user", "" }
 };
 static struct file_listener_settings *replicator_unix_listeners[] = {
-       &replicator_unix_listeners_array[0]
+       &replicator_unix_listeners_array[0],
+       &replicator_unix_listeners_array[1]
 };
 static buffer_t replicator_unix_listeners_buf = {
        replicator_unix_listeners, sizeof(replicator_unix_listeners), { 0, }
index 92964d69a92bc6a1a0b07e33b269bd0801cf1f07..4b53c70d2d0014fb250e20f0c269c7550f972d88 100644 (file)
@@ -7,6 +7,7 @@
 #include "master-service.h"
 #include "master-service-settings.h"
 #include "notify-connection.h"
+#include "doveadm-connection.h"
 #include "replicator-brain.h"
 #include "replicator-queue.h"
 #include "replicator-settings.h"
@@ -24,7 +25,10 @@ static struct timeout *to_dump;
 static void client_connected(struct master_service_connection *conn)
 {
        master_service_client_connection_accept(conn);
-       (void)notify_connection_create(conn->fd, queue);
+       if (strcmp(conn->name, "replicator-doveadm") == 0)
+               doveadm_connection_create(queue, conn->fd);
+       else
+               (void)notify_connection_create(conn->fd, queue);
 }
 
 static void replication_add_users(struct replicator_queue *queue)
@@ -80,12 +84,14 @@ static void main_init(void)
        to_dump = timeout_add(REPLICATOR_DB_DUMP_INTERVAL_MSECS,
                              replicator_dump_timeout, (void *)NULL);
        brain = replicator_brain_init(queue, set);
+       doveadm_connections_init();
 }
 
 static void main_deinit(void)
 {
        const char *path;
 
+       doveadm_connections_deinit();
        notify_connections_destroy_all();
        replicator_brain_deinit(&brain);
        timeout_remove(&to_dump);