]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imapc: Send UID FETCH commands with larger uidset parameter if possible.
authorTimo Sirainen <tss@iki.fi>
Sun, 30 Jan 2011 18:47:43 +0000 (20:47 +0200)
committerTimo Sirainen <tss@iki.fi>
Sun, 30 Jan 2011 18:47:43 +0000 (20:47 +0200)
This code assumes that server doesn't reorganize FETCH replies when it's
given an increasing UID range, which in theory IMAP server would be allowed
to do, but I doubt there are any.

14 files changed:
src/lib-storage/index/imapc/Makefile.am
src/lib-storage/index/imapc/imapc-client-private.h
src/lib-storage/index/imapc/imapc-client.c
src/lib-storage/index/imapc/imapc-client.h
src/lib-storage/index/imapc/imapc-connection.c
src/lib-storage/index/imapc/imapc-connection.h
src/lib-storage/index/imapc/imapc-mail.c
src/lib-storage/index/imapc/imapc-mail.h [new file with mode: 0644]
src/lib-storage/index/imapc/imapc-mailbox.c
src/lib-storage/index/imapc/imapc-search.c
src/lib-storage/index/imapc/imapc-storage.c
src/lib-storage/index/imapc/imapc-storage.h
src/lib-storage/index/index-mail.c
src/lib-storage/index/index-mail.h

index c4e23bb8b036380ba8cdef44674fa7dc40facb39..4f47d890d0afe9300e17dd7724c87d931492a7e0 100644 (file)
@@ -25,6 +25,7 @@ libstorage_imapc_la_SOURCES = \
 headers = \
        imapc-connection.h \
        imapc-list.h \
+       imapc-mail.h \
        imapc-seqmap.h \
        imapc-storage.h \
        imapc-sync.h
index 0862cf4ab250ee5d7b8d8bd0c11fe0236e680125..ff8e27ef85b376f476d04aadfb50d7ff39f2fe3f 100644 (file)
@@ -18,6 +18,8 @@ struct imapc_client {
        ARRAY_DEFINE(conns, struct imapc_client_connection *);
 
        struct ioloop *ioloop;
+
+       unsigned int stop_now:1;
 };
 
 struct imapc_client_mailbox {
index 23425e9e06a5706e1e13a065d4880ec0d4a4560f..4871686595acbc1673ca849ef386909abf4ea53c 100644 (file)
@@ -70,15 +70,24 @@ void imapc_client_run(struct imapc_client *client)
 {
        struct imapc_client_connection *const *connp;
        struct ioloop *prev_ioloop = current_ioloop;
+       bool handle_pending = client->stop_now;
 
        i_assert(client->ioloop == NULL);
 
+       client->stop_now = FALSE;
+
        client->ioloop = io_loop_create();
+       io_loop_set_running(client->ioloop);
+
        array_foreach(&client->conns, connp) {
                imapc_connection_ioloop_changed((*connp)->conn);
                imapc_connection_connect((*connp)->conn);
+               if (handle_pending)
+                       imapc_connection_input_pending((*connp)->conn);
        }
-       io_loop_run(client->ioloop);
+
+       if (io_loop_is_running(client->ioloop))
+               io_loop_run(client->ioloop);
 
        current_ioloop = prev_ioloop;
        array_foreach(&client->conns, connp)
@@ -94,6 +103,12 @@ void imapc_client_stop(struct imapc_client *client)
                io_loop_stop(client->ioloop);
 }
 
+void imapc_client_stop_now(struct imapc_client *client)
+{
+       client->stop_now = TRUE;
+       imapc_client_stop(client);
+}
+
 static struct imapc_client_connection *
 imapc_client_add_connection(struct imapc_client *client)
 {
index dd6ab9d99b5bffbab5a2301f9e7b8d3fecb21126..d9762a19e549c2d3322d2ff014b32da231f3d3ce 100644 (file)
@@ -86,6 +86,9 @@ void imapc_client_register_untagged(struct imapc_client *client,
 
 void imapc_client_run(struct imapc_client *client);
 void imapc_client_stop(struct imapc_client *client);
+/* Stop immediately, don't finish even any already read pending replies.
+   They'll be finished when imapc_client_run() is again called. */
+void imapc_client_stop_now(struct imapc_client *client);
 
 struct imapc_client_mailbox *
 imapc_client_mailbox_open(struct imapc_client *client, const char *name,
index 3e2451457e3f7bff682f87d0cad07fad723e7c8d..364566ec56fa59fe703449f23e36fa573be119c3 100644 (file)
@@ -677,8 +677,6 @@ static int imapc_connection_input_one(struct imapc_connection *conn)
 
 static void imapc_connection_input(struct imapc_connection *conn)
 {
-       int ret;
-
        if (i_stream_read(conn->input) == -1) {
                /* disconnected */
                i_error("imapc(%s): Server disconnected unexpectedly",
@@ -687,15 +685,7 @@ static void imapc_connection_input(struct imapc_connection *conn)
                return;
        }
 
-       o_stream_cork(conn->output);
-       do {
-               T_BEGIN {
-                       ret = imapc_connection_input_one(conn);
-               } T_END;
-       } while (ret > 0);
-
-       if (conn->output != NULL)
-               o_stream_uncork(conn->output);
+       imapc_connection_input_pending(conn);
 }
 
 static void imapc_connection_connected(struct imapc_connection *conn)
@@ -800,6 +790,24 @@ void imapc_connection_connect(struct imapc_connection *conn)
        }
 }
 
+void imapc_connection_input_pending(struct imapc_connection *conn)
+{
+       int ret = 1;
+
+       if (conn->input == NULL)
+               return;
+
+       o_stream_cork(conn->output);
+       while (ret > 0 && !conn->client->stop_now) {
+               T_BEGIN {
+                       ret = imapc_connection_input_one(conn);
+               } T_END;
+       }
+
+       if (conn->output != NULL)
+               o_stream_uncork(conn->output);
+}
+
 static struct imapc_command *
 imapc_command_begin(imapc_command_callback_t *callback, void *context)
 {
index 75c28a91a84df0ddf2ae3772fa56f215a87ecc37..842b014ed703ed674442db1d2c01fac6e35834fb 100644 (file)
@@ -23,6 +23,7 @@ void imapc_connection_deinit(struct imapc_connection **conn);
 
 void imapc_connection_connect(struct imapc_connection *conn);
 void imapc_connection_ioloop_changed(struct imapc_connection *conn);
+void imapc_connection_input_pending(struct imapc_connection *conn);
 
 void imapc_connection_cmd(struct imapc_connection *conn, const char *cmdline,
                          imapc_command_callback_t *callback, void *context);
index cb3e3deccdd3ff8a8b704644d830e1373d688d00..1df5168727397909909038b578d827e032ac40d3 100644 (file)
@@ -3,22 +3,24 @@
 #include "lib.h"
 #include "str.h"
 #include "istream.h"
-#include "index-mail.h"
+#include "imapc-mail.h"
 #include "imapc-client.h"
 #include "imapc-storage.h"
 
-static void imapc_mail_set_seq(struct mail *_mail, uint32_t seq)
+struct mail *
+imapc_mail_alloc(struct mailbox_transaction_context *t,
+                enum mail_fetch_field wanted_fields,
+                struct mailbox_header_lookup_ctx *wanted_headers)
 {
-       index_mail_set_seq(_mail, seq);
-       imapc_mail_fetch(_mail);
-}
+       struct imapc_mail *mail;
+       pool_t pool;
 
-static bool imapc_mail_set_uid(struct mail *_mail, uint32_t uid)
-{
-       if (!index_mail_set_uid(_mail, uid))
-               return FALSE;
-       imapc_mail_fetch(_mail);
-       return TRUE;
+       pool = pool_alloconly_create("mail", 2048);
+       mail = p_new(pool, struct imapc_mail, 1);
+       mail->imail.mail.pool = pool;
+
+       index_mail_init(&mail->imail, t, wanted_fields, wanted_headers);
+       return &mail->imail.mail.mail;
 }
 
 static int imapc_mail_get_received_date(struct mail *_mail, time_t *date_r)
@@ -26,8 +28,15 @@ static int imapc_mail_get_received_date(struct mail *_mail, time_t *date_r)
        struct index_mail *mail = (struct index_mail *)_mail;
        struct index_mail_data *data = &mail->data;
 
-       if (data->received_date == (time_t)-1)
-               return -1;
+       if (data->received_date == (time_t)-1) {
+               if (imapc_mail_fetch(_mail, MAIL_FETCH_RECEIVED_DATE) < 0)
+                       return -1;
+               if (data->received_date == (time_t)-1) {
+                       mail_storage_set_critical(_mail->box->storage,
+                               "imapc: Remote server didn't send INTERNALDATE");
+                       return -1;
+               }
+       }
        *date_r = data->received_date;
        return 0;
 }
@@ -37,8 +46,10 @@ static int imapc_mail_get_save_date(struct mail *_mail, time_t *date_r)
        struct index_mail *mail = (struct index_mail *)_mail;
        struct index_mail_data *data = &mail->data;
 
-       if (data->save_date == (time_t)-1)
+       if (data->save_date == (time_t)-1) {
+               /* FIXME */
                return -1;
+       }
        *date_r = data->save_date;
        return 0;
 }
@@ -90,9 +101,25 @@ imapc_mail_get_stream(struct mail *_mail, struct message_size *hdr_size,
 {
        struct index_mail *mail = (struct index_mail *)_mail;
        struct index_mail_data *data = &mail->data;
+       enum mail_fetch_field fetch_field;
 
-       if (data->stream == NULL)
-               return -1;
+       if (data->stream == NULL) {
+               if (!mail->data.initialized) {
+                       /* coming here from mail_set_seq() */
+                       return -1;
+               }
+               fetch_field = body_size != NULL ||
+                       (mail->wanted_fields & MAIL_FETCH_STREAM_BODY) != 0 ?
+                       MAIL_FETCH_STREAM_BODY : MAIL_FETCH_STREAM_HEADER;
+               if (imapc_mail_fetch(_mail, fetch_field) < 0)
+                       return -1;
+
+               if (data->stream == NULL) {
+                       mail_storage_set_critical(_mail->box->storage,
+                               "imapc: Remote server didn't send BODY[]");
+                       return -1;
+               }
+       }
 
        return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
 }
@@ -100,8 +127,8 @@ imapc_mail_get_stream(struct mail *_mail, struct message_size *hdr_size,
 struct mail_vfuncs imapc_mail_vfuncs = {
        index_mail_close,
        index_mail_free,
-       imapc_mail_set_seq,
-       imapc_mail_set_uid,
+       index_mail_set_seq,
+       index_mail_set_uid,
        index_mail_set_uid_cache_updates,
 
        index_mail_get_flags,
diff --git a/src/lib-storage/index/imapc/imapc-mail.h b/src/lib-storage/index/imapc/imapc-mail.h
new file mode 100644 (file)
index 0000000..28c8720
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef IMAPC_MAIL_H
+#define IMAPC_MAIL_H
+
+#include "index-mail.h"
+
+struct imapc_mail {
+       struct index_mail imail;
+       unsigned int searching:1;
+};
+
+extern struct mail_vfuncs imapc_mail_vfuncs;
+
+struct mail *
+imapc_mail_alloc(struct mailbox_transaction_context *t,
+                enum mail_fetch_field wanted_fields,
+                struct mailbox_header_lookup_ctx *wanted_headers);
+int imapc_mail_fetch(struct mail *mail, enum mail_fetch_field fields);
+
+#endif
index 609fd0fea425a06cba23aed9e1aadb4941999f16..28758b2a7c37a9e8fd15bf16d28576c5389611f4 100644 (file)
@@ -92,7 +92,7 @@ static void imapc_untagged_fetch(const struct imapc_untagged_reply *reply,
        enum mail_flags flags;
        uint32_t uid, old_count;
        unsigned int i, j;
-       ARRAY_TYPE(const_string) keywords;
+       ARRAY_TYPE(const_string) keywords = ARRAY_INIT;
        bool seen_flags = FALSE;
 
        if (mbox == NULL || seq == 0 || !imap_arg_get_list(reply->args, &list))
index 5553fec87502d3d0b005ce044ead1ec6f35ef51a..663dc6f08567d5926d3798fec71da1cab1a30dec 100644 (file)
@@ -6,41 +6,94 @@
 #include "str.h"
 #include "imap-arg.h"
 #include "imap-date.h"
+#include "imap-util.h"
 #include "mail-user.h"
-#include "index-mail.h"
+#include "mail-search.h"
+#include "index-search-private.h"
+#include "imapc-mail.h"
 #include "imapc-client.h"
 #include "imapc-storage.h"
 
-void imapc_mail_fetch(struct mail *mail)
+struct imapc_search_context {
+       struct index_search_context ictx;
+
+       /* non-NULL during _search_next_nonblock() */
+       struct mail *cur_mail;
+
+       /* sequences of messages we're next wanting to fetch. */
+       ARRAY_TYPE(seq_range) next_seqs;
+       uint32_t next_pending_seq, saved_seq;
+
+       unsigned int fetching:1;
+};
+
+static void imapc_search_fetch_callback(const struct imapc_command_reply *reply,
+                                       void *context)
 {
-       struct mail_private *pmail = (struct mail_private *)mail;
-       struct imapc_mailbox *mbox = (struct imapc_mailbox *)mail->box;
-       string_t *str;
-       unsigned int orig_len;
+       struct imapc_search_context *ctx = context;
+       struct imapc_mailbox *mbox =
+               (struct imapc_mailbox *)ctx->ictx.mail_ctx.transaction->box;
 
-       str = t_str_new(64);
-       str_printfa(str, "UID FETCH %u (", mail->uid);
-       orig_len = str_len(str);
-
-       if ((pmail->wanted_fields & (MAIL_FETCH_STREAM_HEADER |
-                                    MAIL_FETCH_STREAM_BODY |
-                                    MAIL_FETCH_MESSAGE_PARTS |
-                                    MAIL_FETCH_NUL_STATE |
-                                    MAIL_FETCH_IMAP_BODY |
-                                    MAIL_FETCH_IMAP_BODYSTRUCTURE |
-                                    MAIL_FETCH_PHYSICAL_SIZE |
-                                    MAIL_FETCH_VIRTUAL_SIZE)) != 0)
+       if (reply->state == IMAPC_COMMAND_STATE_OK)
+               ;
+       else if (reply->state == IMAPC_COMMAND_STATE_NO) {
+               imapc_copy_error_from_reply(mbox->storage, MAIL_ERROR_PARAMS,
+                                           reply);
+       } else {
+               mail_storage_set_critical(&mbox->storage->storage,
+                       "imapc: Command failed: %s", reply->text_full);
+       }
+       ctx->fetching = FALSE;
+       imapc_client_stop(mbox->storage->client);
+}
+
+static bool
+imapc_append_wanted_fields(string_t *str, enum mail_fetch_field fields,
+                          bool want_headers)
+{
+       bool ret = FALSE;
+
+       if ((fields & (MAIL_FETCH_STREAM_BODY |
+                      MAIL_FETCH_MESSAGE_PARTS |
+                      MAIL_FETCH_NUL_STATE |
+                      MAIL_FETCH_IMAP_BODY |
+                      MAIL_FETCH_IMAP_BODYSTRUCTURE |
+                      MAIL_FETCH_PHYSICAL_SIZE |
+                      MAIL_FETCH_VIRTUAL_SIZE)) != 0) {
                str_append(str, "BODY.PEEK[] ");
-       else if ((pmail->wanted_fields & (MAIL_FETCH_IMAP_ENVELOPE |
-                                         MAIL_FETCH_HEADER_MD5 |
-                                         MAIL_FETCH_DATE)) != 0 ||
-                pmail->wanted_headers != NULL)
+               ret = TRUE;
+       } else if (want_headers ||
+                  (fields & (MAIL_FETCH_STREAM_HEADER |
+                             MAIL_FETCH_IMAP_ENVELOPE |
+                             MAIL_FETCH_HEADER_MD5 |
+                             MAIL_FETCH_DATE)) != 0) {
                str_append(str, "BODY.PEEK[HEADER] ");
+               ret = TRUE;
+       }
 
-       if ((pmail->wanted_fields & MAIL_FETCH_RECEIVED_DATE) != 0)
+       if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0) {
                str_append(str, "INTERNALDATE ");
+               ret = TRUE;
+       }
+       return ret;
+}
+
+static void
+imapc_search_send_fetch(struct imapc_search_context *ctx,
+                       const ARRAY_TYPE(seq_range) *uids)
+{
+       struct mail *mail = ctx->cur_mail;
+       struct mail_private *pmail = (struct mail_private *)mail;
+       struct imapc_mailbox *mbox = (struct imapc_mailbox *)mail->box;
+       string_t *str;
+
+       str = t_str_new(64);
+       str_append(str, "UID FETCH ");
+       imap_write_seq_range(str, uids);
+       str_append(str, " (");
 
-       if (str_len(str) == orig_len) {
+       if (!imapc_append_wanted_fields(str, pmail->wanted_fields,
+                                       pmail->wanted_headers != NULL)) {
                /* we don't need to fetch anything */
                return;
        }
@@ -48,11 +101,9 @@ void imapc_mail_fetch(struct mail *mail)
        str_truncate(str, str_len(str) - 1);
        str_append_c(str, ')');
 
-       mbox->cur_fetch_mail = mail;
-       imapc_client_mailbox_cmdf(mbox->client_box, imapc_async_stop_callback,
-                                 mbox->storage, "%1s", str_c(str));
-       imapc_client_run(mbox->storage->client);
-       mbox->cur_fetch_mail = NULL;
+       ctx->fetching = TRUE;
+       imapc_client_mailbox_cmdf(mbox->client_box, imapc_search_fetch_callback,
+                                 ctx, "%1s", str_c(str));
 }
 
 struct mail_search_context *
@@ -60,16 +111,122 @@ imapc_search_init(struct mailbox_transaction_context *t,
                  struct mail_search_args *args,
                  const enum mail_sort_type *sort_program)
 {
-       return index_storage_search_init(t, args, sort_program);
+       struct imapc_search_context *ctx;
+
+       ctx = i_new(struct imapc_search_context, 1);
+       index_storage_search_init_context(&ctx->ictx, t, args, sort_program);
+       i_array_init(&ctx->next_seqs, 64);
+       ctx->ictx.recheck_index_args = TRUE;
+       return &ctx->ictx.mail_ctx;
+}
+
+int imapc_search_deinit(struct mail_search_context *_ctx)
+{
+       struct imapc_search_context *ctx = (struct imapc_search_context *)_ctx;
+       struct imapc_mailbox *mbox =
+               (struct imapc_mailbox *)_ctx->transaction->box;
+
+       while (ctx->fetching)
+               imapc_client_run(mbox->storage->client);
+
+       array_free(&ctx->next_seqs);
+       return index_storage_search_deinit(_ctx);
 }
 
 bool imapc_search_next_nonblock(struct mail_search_context *_ctx,
                                struct mail *mail, bool *tryagain_r)
 {
-       if (!index_storage_search_next_nonblock(_ctx, mail, tryagain_r))
+       struct imapc_search_context *ctx = (struct imapc_search_context *)_ctx;
+       struct imapc_mailbox *mbox =
+               (struct imapc_mailbox *)_ctx->transaction->box;
+       struct imapc_mail *imail = (struct imapc_mail *)mail;
+       bool ret;
+
+       imail->searching = TRUE;
+       ctx->cur_mail = mail;
+       ret = index_storage_search_next_nonblock(_ctx, mail, tryagain_r);
+       ctx->cur_mail = NULL;
+       imail->searching = FALSE;
+       if (!ret)
                return FALSE;
 
-       imapc_mail_fetch(mail);
+       if (ctx->fetching) {
+               mbox->cur_fetch_mail = mail;
+               imapc_client_run(mbox->storage->client);
+               mbox->cur_fetch_mail = NULL;
+       }
+       return TRUE;
+}
+
+static void imapc_get_short_uid_range(struct mailbox *box,
+                                     const ARRAY_TYPE(seq_range) *seqs,
+                                     ARRAY_TYPE(seq_range) *uids)
+{
+       const struct seq_range *range;
+       unsigned int i, count;
+       uint32_t uid1, uid2;
+
+       range = array_get(seqs, &count);
+       for (i = 0; i < count; i++) {
+               mail_index_lookup_uid(box->view, range[i].seq1, &uid1);
+               mail_index_lookup_uid(box->view, range[i].seq2, &uid2);
+               seq_range_array_add_range(uids, uid1, uid2);
+       }
+}
+
+static void imapc_search_update_next_seqs(struct imapc_search_context *ctx)
+{
+       struct mail_search_context *_ctx = &ctx->ictx.mail_ctx;
+       uint32_t prev_seq;
+
+       /* add messages to the next_seqs list as long as the sequences
+          are incrementing */
+       if (ctx->next_pending_seq == 0)
+               prev_seq = 0;
+       else {
+               prev_seq = ctx->next_pending_seq;
+               seq_range_array_add(&ctx->next_seqs, 0, prev_seq);
+       }
+       if (ctx->saved_seq != 0)
+               _ctx->seq = ctx->saved_seq;
+       while (index_storage_search_next_update_seq(_ctx)) {
+               mail_search_args_reset(_ctx->args->args, FALSE);
+               if (_ctx->seq < prev_seq) {
+                       ctx->next_pending_seq = _ctx->seq;
+                       break;
+               }
+               seq_range_array_add(&ctx->next_seqs, 0, _ctx->seq);
+       }
+       ctx->saved_seq = _ctx->seq;
+       if (array_count(&ctx->next_seqs) > 0) T_BEGIN {
+               ARRAY_TYPE(seq_range) uids;
+
+               t_array_init(&uids, array_count(&ctx->next_seqs)*2);
+               imapc_get_short_uid_range(_ctx->transaction->box,
+                                         &ctx->next_seqs, &uids);
+               imapc_search_send_fetch(ctx, &uids);
+       } T_END;
+}
+
+bool imapc_search_next_update_seq(struct mail_search_context *_ctx)
+{
+       struct imapc_search_context *ctx = (struct imapc_search_context *)_ctx;
+       struct seq_range *seqs;
+       unsigned int count;
+
+       seqs = array_get_modifiable(&ctx->next_seqs, &count);
+       if (count == 0) {
+               imapc_search_update_next_seqs(ctx);
+               seqs = array_get_modifiable(&ctx->next_seqs, &count);
+               if (count == 0)
+                       return FALSE;
+       }
+
+       _ctx->seq = seqs[0].seq1;
+       if (seqs[0].seq1 < seqs[0].seq2)
+               seqs[0].seq1++;
+       else
+               array_delete(&ctx->next_seqs, 0, 1);
        return TRUE;
 }
 
@@ -123,6 +280,8 @@ imapc_fetch_stream(struct index_mail *imail, const char *value, bool body)
 
 void imapc_fetch_mail_update(struct mail *mail, const struct imap_arg *args)
 {
+       struct imapc_mailbox *mbox =
+               (struct imapc_mailbox *)mail->transaction->box;
        struct index_mail *imail = (struct index_mail *)mail;
        const char *key, *value;
        unsigned int i;
@@ -151,4 +310,31 @@ void imapc_fetch_mail_update(struct mail *mail, const struct imap_arg *args)
                        imail->data.received_date = t;
                }
        }
+       imapc_client_stop_now(mbox->storage->client);
+}
+
+int imapc_mail_fetch(struct mail *mail, enum mail_fetch_field fields)
+{
+       struct imapc_mailbox *mbox =
+               (struct imapc_mailbox *)mail->transaction->box;
+       struct imapc_simple_context sctx;
+       string_t *str;
+
+       str = t_str_new(64);
+       str_printfa(str, "UID FETCH %u (", mail->uid);
+
+       if (!imapc_append_wanted_fields(str, fields, FALSE))
+               return 0;
+
+       str_truncate(str, str_len(str) - 1);
+       str_append_c(str, ')');
+
+       sctx.storage = mbox->storage;
+       imapc_client_mailbox_cmdf(mbox->client_box, imapc_async_stop_callback,
+                                 mbox->storage, "%1s", str_c(str));
+
+       mbox->cur_fetch_mail = mail;
+       imapc_client_run(mbox->storage->client);
+       mbox->cur_fetch_mail = NULL;
+       return sctx.ret;
 }
index 70845329efedad96b713cc38ad9cb5f094a2b4bc..96beba6ce925489c0915dfcb0171e30c07fed3df 100644 (file)
@@ -6,7 +6,7 @@
 #include "safe-mkstemp.h"
 #include "imap-arg.h"
 #include "imap-resp-code.h"
-#include "index-mail.h"
+#include "imapc-mail.h"
 #include "imapc-client.h"
 #include "imapc-list.h"
 #include "imapc-sync.h"
@@ -544,11 +544,11 @@ struct mailbox imapc_mailbox = {
                index_transaction_commit,
                index_transaction_rollback,
                NULL,
-               index_mail_alloc,
+               imapc_mail_alloc,
                imapc_search_init,
-               index_storage_search_deinit,
+               imapc_search_deinit,
                imapc_search_next_nonblock,
-               index_storage_search_next_update_seq,
+               imapc_search_next_update_seq,
                imapc_save_alloc,
                imapc_save_begin,
                imapc_save_continue,
index 77be532612e8118402dbaf28eeb020f86b23f669..a4b9f97864606c8cc6dc77b693d4739260e82146 100644 (file)
@@ -60,8 +60,6 @@ struct imapc_simple_context {
        int ret;
 };
 
-extern struct mail_vfuncs imapc_mail_vfuncs;
-
 struct mail_save_context *
 imapc_save_alloc(struct mailbox_transaction_context *_t);
 int imapc_save_begin(struct mail_save_context *ctx, struct istream *input);
@@ -75,13 +73,14 @@ void imapc_transaction_save_commit_post(struct mail_save_context *ctx,
                                        struct mail_index_transaction_commit_result *result);
 void imapc_transaction_save_rollback(struct mail_save_context *ctx);
 
-void imapc_mail_fetch(struct mail *mail);
 struct mail_search_context *
 imapc_search_init(struct mailbox_transaction_context *t,
                  struct mail_search_args *args,
                  const enum mail_sort_type *sort_program);
+int imapc_search_deinit(struct mail_search_context *_ctx);
 bool imapc_search_next_nonblock(struct mail_search_context *_ctx,
                                struct mail *mail, bool *tryagain_r);
+bool imapc_search_next_update_seq(struct mail_search_context *_ctx);
 void imapc_fetch_mail_update(struct mail *mail, const struct imap_arg *args);
 
 void imapc_copy_error_from_reply(struct imapc_storage *storage,
index 5a411e771fb92b708fe1164ab3edb0d78e2376bd..3e6ea1e1e723d15421b9a96f6df8cd86048de54b 100644 (file)
@@ -1340,6 +1340,7 @@ void index_mail_set_seq(struct mail *_mail, uint32_t seq)
                if (!_mail->saving && _mail->uid < hdr->next_uid)
                        (void)mail_get_stream(_mail, NULL, NULL, &input);
        }
+       mail->data.initialized = TRUE;
 }
 
 bool index_mail_set_uid(struct mail *_mail, uint32_t uid)
index 6c4f2bb0af528a1a955de3ebcb9562888567f2da..18eb89e13dae28a31573882f7940f3740aca9407 100644 (file)
@@ -96,6 +96,7 @@ struct index_mail_data {
        ARRAY_TYPE(keywords) keywords;
        ARRAY_TYPE(keyword_indexes) keyword_indexes;
 
+       unsigned int initialized:1;
        unsigned int save_sent_date:1;
        unsigned int sent_date_parsed:1;
        unsigned int save_envelope:1;