]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imapc: Add imapc_sync_handle_untagged_fetches()
authorMarkus Valentin <markus.valentin@open-xchange.com>
Tue, 18 Jan 2022 08:22:24 +0000 (09:22 +0100)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Mon, 14 Mar 2022 11:38:19 +0000 (11:38 +0000)
src/lib-storage/index/imapc/imapc-mailbox.c
src/lib-storage/index/imapc/imapc-storage.c
src/lib-storage/index/imapc/imapc-storage.h
src/lib-storage/index/imapc/imapc-sync.c

index 61052922c9ded23657f64a2136ac628e797e2721..cb2dc9dc74cff5ce5a6c3d4b33ac9fdda22c1757 100644 (file)
@@ -40,7 +40,7 @@ void imapc_mailbox_set_corrupted(struct imapc_mailbox *mbox,
        imapc_client_mailbox_reconnect(mbox->client_box, errmsg);
 }
 
-static struct mail_index_view *
+struct mail_index_view *
 imapc_mailbox_get_sync_view(struct imapc_mailbox *mbox)
 {
        if (mbox->sync_view == NULL)
@@ -487,7 +487,7 @@ imapc_untagged_fetch_ctx_create(void)
        return ctx;
 }
 
-static void imapc_untagged_fetch_ctx_free(struct imapc_untagged_fetch_ctx **_ctx)
+void imapc_untagged_fetch_ctx_free(struct imapc_untagged_fetch_ctx **_ctx)
 {
        struct imapc_untagged_fetch_ctx *ctx = *_ctx;
 
@@ -497,10 +497,10 @@ static void imapc_untagged_fetch_ctx_free(struct imapc_untagged_fetch_ctx **_ctx
        pool_unref(&ctx->pool);
 }
 
-static void
-imapc_untagged_fetch_update_flags(struct imapc_mailbox *mbox,
-                                 struct imapc_untagged_fetch_ctx *ctx,
-                                 uint32_t lseq)
+void imapc_untagged_fetch_update_flags(struct imapc_mailbox *mbox,
+                                      struct imapc_untagged_fetch_ctx *ctx,
+                                      struct mail_index_view *view,
+                                      uint32_t lseq)
 {
        ARRAY_TYPE(keyword_indexes) old_kws;
        struct mail_keywords *kw;
@@ -510,14 +510,14 @@ imapc_untagged_fetch_update_flags(struct imapc_mailbox *mbox,
        if (!ctx->have_flags)
                return;
 
-       rec = mail_index_lookup(mbox->delayed_sync_view, lseq);
+       rec = mail_index_lookup(view, lseq);
        if (rec->flags != ctx->flags) {
                mail_index_update_flags(mbox->delayed_sync_trans, lseq,
                                        MODIFY_REPLACE, ctx->flags);
        }
 
        t_array_init(&old_kws, 8);
-       mail_index_lookup_keywords(mbox->delayed_sync_view, lseq, &old_kws);
+       mail_index_lookup_keywords(view, lseq, &old_kws);
 
        if (ctx->have_gmail_labels) {
                /* add keyword for mails that have GMail labels.
@@ -582,7 +582,11 @@ static bool imapc_untagged_fetch_handle(struct imapc_mailbox *mbox,
                mbox->sync_next_lseq++;
        }
 
-       imapc_untagged_fetch_update_flags(mbox, ctx, lseq);
+       if (!new_message) {
+               /* Only update flags immediately for existing messages */
+               imapc_untagged_fetch_update_flags(mbox, ctx,
+                                                 mbox->delayed_sync_view, lseq);
+       }
 
        if (ctx->modseq != 0) {
                if (mail_index_modseq_lookup(mbox->delayed_sync_view, lseq) < ctx->modseq)
index 49bf78f7e48d243d0965208800ef22fbcaa59d7e..0db89092f37fd63976e02447449e894562afdfb1 100644 (file)
@@ -538,6 +538,7 @@ imapc_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        p_array_init(&mbox->untagged_callbacks, pool, 16);
        p_array_init(&mbox->resp_text_callbacks, pool, 16);
        p_array_init(&mbox->fetch_requests, pool, 16);
+       p_array_init(&mbox->untagged_fetch_contexts, pool, 16);
        p_array_init(&mbox->delayed_expunged_uids, pool, 16);
        mbox->pending_fetch_cmd = str_new(pool, 128);
        mbox->prev_mail_cache.fd = -1;
index 6d2e3e871a66f10c6356f869310439c004f4ebf3..6040c3389a8d0ad936cee641dd9b54c311423c83 100644 (file)
@@ -126,6 +126,7 @@ struct imapc_mailbox {
        struct timeout *to_idle_check, *to_idle_delay;
 
        ARRAY(struct imapc_fetch_request *) fetch_requests;
+       ARRAY(struct imapc_untagged_fetch_ctx *) untagged_fetch_contexts;
        /* if non-empty, contains the latest FETCH command we're going to be
           sending soon (but still waiting to see if we can increase its
           UID range) */
@@ -240,4 +241,13 @@ void imapc_mailbox_register_resp_text(struct imapc_mailbox *mbox,
 
 void imapc_mailbox_register_callbacks(struct imapc_mailbox *mbox);
 
+struct mail_index_view *
+imapc_mailbox_get_sync_view(struct imapc_mailbox *mbox);
+
+void imapc_untagged_fetch_ctx_free(struct imapc_untagged_fetch_ctx **_ctx);
+void imapc_untagged_fetch_update_flags(struct imapc_mailbox *mbox,
+                                      struct imapc_untagged_fetch_ctx *ctx,
+                                      struct mail_index_view *view,
+                                      uint32_t lseq);
+
 #endif
index 68de93b8ca139e028da177a1c6a3b73636edd7a5..afd8c67497bc632200ffccb45335e230f8dbe566 100644 (file)
@@ -524,6 +524,68 @@ static int imapc_sync_finish(struct imapc_sync_context **_ctx)
        return ret;
 }
 
+static int imapc_untagged_fetch_uid_cmp(struct imapc_untagged_fetch_ctx *const *ctx1,
+                                       struct imapc_untagged_fetch_ctx *const *ctx2)
+{
+       return (*ctx1)->uid < (*ctx2)->uid ? -1 :
+               (*ctx1)->uid > (*ctx2)->uid ? 1 : 0;
+}
+
+static void imapc_sync_handle_untagged_fetches(struct imapc_mailbox *mbox)
+{
+       struct imapc_untagged_fetch_ctx *untagged_fetch_context;
+       struct mail_index_view *updated_view;
+       uint32_t lseq;
+
+       i_assert(array_count(&mbox->untagged_fetch_contexts) > 0);
+       i_assert(mbox->delayed_sync_trans == NULL);
+
+       array_sort(&mbox->untagged_fetch_contexts, imapc_untagged_fetch_uid_cmp);
+
+       mbox->delayed_sync_trans =
+               mail_index_transaction_begin(imapc_mailbox_get_sync_view(mbox),
+                                                    MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
+
+       array_foreach_elem(&mbox->untagged_fetch_contexts, untagged_fetch_context) {
+               if (untagged_fetch_context->uid < mbox->min_append_uid ||
+                   untagged_fetch_context->uid < mail_index_get_header(mbox->sync_view)->next_uid) {
+                       /* The message was already added */
+                       continue;
+               }
+
+               mail_index_append(mbox->delayed_sync_trans,
+                                 untagged_fetch_context->uid,
+                                 &lseq);
+               mbox->min_append_uid = untagged_fetch_context->uid + 1;
+       }
+
+       updated_view = mail_index_transaction_open_updated_view(mbox->delayed_sync_trans);
+
+       array_foreach_elem(&mbox->untagged_fetch_contexts, untagged_fetch_context) {
+               if (!untagged_fetch_context->have_flags) {
+                       imapc_untagged_fetch_ctx_free(&untagged_fetch_context);
+                       continue;
+               }
+
+               /* Lookup the mail belonging to this context using the
+                  context->uid */
+               if (!mail_index_lookup_seq(updated_view,
+                                          untagged_fetch_context->uid,
+                                          &lseq)) {
+                       /* mail is expunged already */
+                       imapc_untagged_fetch_ctx_free(&untagged_fetch_context);
+                       continue;
+               }
+
+               imapc_untagged_fetch_update_flags(mbox, untagged_fetch_context,
+                                                 updated_view, lseq);
+               imapc_untagged_fetch_ctx_free(&untagged_fetch_context);
+       }
+
+       mail_index_view_close(&updated_view);
+       array_clear(&mbox->untagged_fetch_contexts);
+}
+
 static int imapc_sync(struct imapc_mailbox *mbox)
 {
        struct imapc_sync_context *sync_ctx;
@@ -536,6 +598,10 @@ static int imapc_sync(struct imapc_mailbox *mbox)
 
        if (imapc_sync_begin(mbox, &sync_ctx, force) < 0)
                return -1;
+
+       if (!array_is_empty(&mbox->untagged_fetch_contexts))
+               imapc_sync_handle_untagged_fetches(mbox);
+
        if (sync_ctx == NULL)
                return 0;
        if (imapc_sync_finish(&sync_ctx) < 0)