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)
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;
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;
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.
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)
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;
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) */
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
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;
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)