]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap: expunge: Expunge \Deleted mails in batches of 1000
authorJosef 'Jeff' Sipek <jeff.sipek@open-xchange.com>
Tue, 4 Feb 2020 17:32:59 +0000 (12:32 -0500)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Thu, 6 Feb 2020 16:16:40 +0000 (16:16 +0000)
src/imap/imap-expunge.c

index 20b48b29c92a6c0090b0b75062ee63d80741212a..ff1a2134e857f8a91b9030ebb9b616916013e68f 100644 (file)
@@ -3,8 +3,11 @@
 #include "imap-common.h"
 #include "mail-storage.h"
 #include "mail-search-build.h"
+#include "imap-search-args.h"
 #include "imap-expunge.h"
 
+#define IMAP_EXPUNGE_BATCH_SIZE 1000
+
 /* get a seqset of all the mails with \Deleted */
 static int imap_expunge_get_seqset(struct mailbox *box,
                                   struct mail_search_arg *next_search_arg,
@@ -46,17 +49,19 @@ static int imap_expunge_get_seqset(struct mailbox *box,
 int imap_expunge(struct mailbox *box, struct mail_search_arg *next_search_arg,
                 unsigned int *expunged_count)
 {
-       struct mail_search_context *ctx;
-        struct mailbox_transaction_context *t;
-       struct mail *mail;
+       struct imap_search_seqset_iter *seqset_iter;
        struct mail_search_args *search_args;
+       struct mailbox_status status;
        bool expunges = FALSE;
+       int ret;
 
        if (mailbox_is_readonly(box)) {
                /* silently ignore */
                return 0;
        }
 
+       mailbox_get_open_status(box, STATUS_MESSAGES, &status);
+
        search_args = mail_search_build_init();
        search_args->args = p_new(search_args->pool, struct mail_search_arg, 1);
        search_args->args->type = SEARCH_SEQSET;
@@ -68,23 +73,39 @@ int imap_expunge(struct mailbox *box, struct mail_search_arg *next_search_arg,
                return -1;
        }
 
-       t = mailbox_transaction_begin(box, 0, "EXPUNGE");
-       ctx = mailbox_search_init(t, search_args, NULL, 0, NULL);
+       seqset_iter = imap_search_seqset_iter_init(search_args, status.messages,
+                                                  IMAP_EXPUNGE_BATCH_SIZE);
+
+       do {
+               struct mailbox_transaction_context *t;
+               struct mail_search_context *ctx;
+               struct mail *mail;
+
+               t = mailbox_transaction_begin(box, 0, "EXPUNGE");
+               ctx = mailbox_search_init(t, search_args, NULL, 0, NULL);
+
+               while (mailbox_search_next(ctx, &mail)) {
+                       *expunged_count += 1;
+                       mail_expunge(mail);
+                       expunges = TRUE;
+               }
+
+               ret = mailbox_search_deinit(&ctx);
+               if (ret < 0) {
+                       mailbox_transaction_rollback(&t);
+                       break;
+               } else {
+                       ret = mailbox_transaction_commit(&t);
+                       if (ret < 0)
+                               break;
+               }
+       } while (imap_search_seqset_iter_next(seqset_iter));
+
+       imap_search_seqset_iter_deinit(&seqset_iter);
        mail_search_args_unref(&search_args);
 
-       while (mailbox_search_next(ctx, &mail)) {
-               *expunged_count += 1;
-               mail_expunge(mail);
-               expunges = TRUE;
-       }
-
-       if (mailbox_search_deinit(&ctx) < 0) {
-               mailbox_transaction_rollback(&t);
-               return -1;
-       } else {
-               if (mailbox_transaction_commit(&t) < 0)
-                       return -1;
-       }
+       if (ret < 0)
+               return ret;
 
        return expunges ? 1 : 0;
 }