]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Add indexer add/remove/list commands
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 25 Jan 2022 17:45:32 +0000 (18:45 +0100)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Sun, 13 Feb 2022 10:23:26 +0000 (10:23 +0000)
src/doveadm/Makefile.am
src/doveadm/doveadm-cmd.c
src/doveadm/doveadm-cmd.h
src/doveadm/doveadm-indexer.c [new file with mode: 0644]

index 464835c37ef276ff93db1e80b64a8cb060cefd61..ff463419665754e8c03936583a1d90abe06d788a 100644 (file)
@@ -77,6 +77,7 @@ doveadm_common_cmds = \
        doveadm-dict.c \
        doveadm-director.c \
        doveadm-fs.c \
+       doveadm-indexer.c \
        doveadm-instance.c \
        doveadm-kick.c \
        doveadm-log.c \
index 3fd9bc83b97adac5c4508cd2ba8fa4a392c47105..496827c011e1c724a822a7eb7a90c6c5de196dd8 100644 (file)
@@ -31,6 +31,9 @@ static struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = {
        &doveadm_cmd_proxy_kick_ver2,
        &doveadm_cmd_who_ver2,
        &doveadm_cmd_proxy_list_ver2,
+       &doveadm_cmd_indexer_add,
+       &doveadm_cmd_indexer_remove,
+       &doveadm_cmd_indexer_list,
 };
 
 ARRAY_TYPE(doveadm_cmd_ver2) doveadm_cmds_ver2;
index cbb1e50b824a5adaa6e6a9e11b09ef5ba7448182..d29ebd9c92e9af6d10ad2d434f5be4f42e342393 100644 (file)
@@ -159,5 +159,8 @@ extern struct doveadm_cmd_ver2 doveadm_cmd_proxy_list_ver2;
 extern struct doveadm_cmd_ver2 doveadm_cmd_sis_deduplicate;
 extern struct doveadm_cmd_ver2 doveadm_cmd_sis_find;
 extern struct doveadm_cmd_ver2 doveadm_cmd_zlibconnect;
+extern struct doveadm_cmd_ver2 doveadm_cmd_indexer_add;
+extern struct doveadm_cmd_ver2 doveadm_cmd_indexer_remove;
+extern struct doveadm_cmd_ver2 doveadm_cmd_indexer_list;
 
 #endif
diff --git a/src/doveadm/doveadm-indexer.c b/src/doveadm/doveadm-indexer.c
new file mode 100644 (file)
index 0000000..69437cd
--- /dev/null
@@ -0,0 +1,200 @@
+/* Copyright (c) 2022 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "strescape.h"
+#include "connection.h"
+#include "istream.h"
+#include "ostream.h"
+#include "doveadm.h"
+#include "doveadm-print.h"
+
+#include <unistd.h>
+
+#define INDEXER_SOCKET_NAME "indexer"
+
+static struct istream *indexer_send_cmd(const char *cmd)
+{
+       const char *path = t_strconcat(doveadm_settings->base_dir,
+                                      "/"INDEXER_SOCKET_NAME, NULL);
+       const struct connection_settings set = {
+               .service_name_out = "indexer-client",
+               .service_name_in = "indexer-server",
+               .major_version = 1,
+               .minor_version = 0,
+       };
+       const char *error;
+       struct istream *input;
+       struct ostream *output;
+       if (doveadm_blocking_connect(path, &set, &input, &output, &error) < 0)
+               i_fatal("%s", error);
+       o_stream_nsend_str(output, t_strconcat(cmd, "\r\n", NULL));
+       if (o_stream_flush(output) < 0)
+               i_fatal("write(indexer) failed: %s", o_stream_get_error(output));
+       o_stream_unref(&output);
+       return input;
+}
+
+static struct istream *
+indexer_send_cmd_with_args(const char *cmd, const char *const *args)
+{
+       string_t *str = t_str_new(128);
+
+       str_append(str, cmd);
+       if (args != NULL) {
+               for (unsigned int i = 0; args[i] != NULL; i++) {
+                       str_append_c(str, '\t');
+                       str_append_tabescaped(str, args[i]);
+               }
+       }
+       return indexer_send_cmd(str_c(str));
+}
+
+static void cmd_indexer_add(struct doveadm_cmd_context *cctx)
+{
+       const char *user, *mailbox, *line;
+       int64_t max_recent;
+       bool head;
+
+       if (!doveadm_cmd_param_bool(cctx, "head", &head))
+               head = FALSE;
+       if (!doveadm_cmd_param_int64(cctx, "max-recent", &max_recent))
+               max_recent = 0;
+       if (!doveadm_cmd_param_str(cctx, "user", &user) ||
+           !doveadm_cmd_param_str(cctx, "mailbox", &mailbox))
+               help_ver2(&doveadm_cmd_indexer_add);
+
+       const char *cmd = head ? "PREPEND" : "APPEND";
+       const char *const args[] = {
+               "0", user, mailbox, dec2str(max_recent),
+               NULL
+       };
+       struct istream *input = indexer_send_cmd_with_args(cmd, args);
+
+       alarm(5);
+       if ((line = i_stream_read_next_line(input)) == NULL)
+               i_fatal("read(indexer) failed: %s", i_stream_get_error(input));
+       if (strcmp(line, "0\tOK") != 0)
+               i_fatal("indexer: %s returned unexpected reply: %s", cmd, line);
+       alarm(0);
+       i_stream_destroy(&input);
+}
+
+static void cmd_indexer_remove(struct doveadm_cmd_context *cctx)
+{
+       const char *line, *user_mask, *mailbox_mask;
+
+       if (!doveadm_cmd_param_str(cctx, "user-mask", &user_mask))
+               help_ver2(&doveadm_cmd_indexer_remove);
+       if (!doveadm_cmd_param_str(cctx, "mailbox-mask", &mailbox_mask))
+               mailbox_mask = NULL;
+
+       const char *const args[] = { "0", user_mask, mailbox_mask, NULL };
+       struct istream *input = indexer_send_cmd_with_args("REMOVE", args);
+
+       alarm(5);
+       if ((line = i_stream_read_next_line(input)) == NULL)
+               i_fatal("read(indexer) failed: %s", i_stream_get_error(input));
+       if (strcmp(line, "0\tOK") != 0)
+               i_fatal("indexer: REMOVE returned unexpected reply: %s", line);
+       alarm(0);
+       i_stream_destroy(&input);
+}
+
+static int cmd_indexer_list_print(const char *const *args)
+{
+       if (str_array_length(args) < 7)
+               return -1;
+
+       /* <tag> <username> <mailbox> <session-id> <max-recent-msgs> <type>
+          <flags> */
+       doveadm_print(args[1]);
+       doveadm_print(args[2]);
+       doveadm_print(args[3]);
+       doveadm_print(args[4]);
+       switch (args[5][0]) {
+       case 'i':
+               doveadm_print("index");
+               break;
+       case 'o':
+               doveadm_print("optimize");
+               break;
+       default:
+               doveadm_print(args[5]);
+               break;
+       }
+       if (args[6][0] != 'w')
+               doveadm_print("queued");
+       else if (args[6][1] == 'h')
+               doveadm_print("working/head-queued");
+       else if (args[6][1] == 't')
+               doveadm_print("working/tail-queued");
+       else
+               doveadm_print("working");
+       return 0;
+}
+
+static void cmd_indexer_list(struct doveadm_cmd_context *cctx)
+{
+       const char *line, *user_mask;
+
+       if (!doveadm_cmd_param_str(cctx, "user-mask", &user_mask))
+               user_mask = NULL;
+
+       const char *const args[] = { "0", "all", user_mask, NULL };
+       struct istream *input = indexer_send_cmd_with_args("LIST", args);
+
+       doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
+       doveadm_print_header_simple("username");
+       doveadm_print_header_simple("mailbox");
+       doveadm_print_header_simple("session_id");
+       doveadm_print_header_simple("max_recent");
+       doveadm_print_header_simple("type");
+       doveadm_print_header_simple("status");
+
+       alarm(30);
+       while ((line = i_stream_read_next_line(input)) != NULL) {
+               if (strcmp(line, "0") == 0)
+                       break;
+               T_BEGIN {
+                       const char *const *args = t_strsplit_tabescaped(line);
+                       if (cmd_indexer_list_print(args) < 0)
+                               i_fatal("Unexpected input: %s", line);
+               } T_END;
+       }
+       if (line == NULL)
+               i_fatal("read(indexer) failed: %s", i_stream_get_error(input));
+       alarm(0);
+       i_stream_destroy(&input);
+}
+
+struct doveadm_cmd_ver2 doveadm_cmd_indexer_add = {
+       .cmd = cmd_indexer_add,
+       .name = "indexer add",
+       .usage = "[-h] [-n <max recent>] <user> <mailbox>",
+DOVEADM_CMD_PARAMS_START
+DOVEADM_CMD_PARAM('h', "head", CMD_PARAM_BOOL, 0)
+DOVEADM_CMD_PARAM('n', "max-recent", CMD_PARAM_STR, 0)
+DOVEADM_CMD_PARAM('\0', "user", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAM('\0', "mailbox", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAMS_END
+};
+
+struct doveadm_cmd_ver2 doveadm_cmd_indexer_remove = {
+       .cmd = cmd_indexer_remove,
+       .name = "indexer remove",
+       .usage = "<user mask> [<mailbox mask>]",
+DOVEADM_CMD_PARAMS_START
+DOVEADM_CMD_PARAM('\0', "user-mask", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAM('\0', "mailbox-mask", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAMS_END
+};
+
+struct doveadm_cmd_ver2 doveadm_cmd_indexer_list = {
+       .cmd = cmd_indexer_list,
+       .name = "indexer list",
+       .usage = "[<user mask>]",
+DOVEADM_CMD_PARAMS_START
+DOVEADM_CMD_PARAM('\0', "user-mask", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAMS_END
+};