]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Broke mailbox_sync() into iterator.
authorTimo Sirainen <tss@iki.fi>
Mon, 12 Jul 2004 11:35:50 +0000 (14:35 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 12 Jul 2004 11:35:50 +0000 (14:35 +0300)
--HG--
branch : HEAD

29 files changed:
src/imap/Makefile.am
src/imap/client.h
src/imap/cmd-idle.c
src/imap/cmd-select.c
src/imap/cmd-status.c
src/imap/cmd-store.c
src/imap/commands-util.c
src/imap/imap-fetch.c
src/imap/imap-sync.c [new file with mode: 0644]
src/imap/imap-sync.h [new file with mode: 0644]
src/imap/mail-storage-callbacks.c
src/lib-imap/imap-util.c
src/lib-imap/imap-util.h
src/lib-storage/index/index-mailbox-check.c
src/lib-storage/index/index-status.c
src/lib-storage/index/index-storage.h
src/lib-storage/index/index-sync.c
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/maildir/maildir-storage.h
src/lib-storage/index/maildir/maildir-sync.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/index/mbox/mbox-storage.h
src/lib-storage/index/mbox/mbox-sync.c
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h
src/lib-storage/proxy-mailbox.c
src/pop3/client.c
src/pop3/mail-storage-callbacks.c

index 783138df5920863faec2c99d7b2064e303859e19..1775bd1b099a08b02d51ba247cee5710bfca0712 100644 (file)
@@ -68,6 +68,7 @@ imap_SOURCES = \
        imap-messageset.c \
        imap-search.c \
        imap-sort.c \
+       imap-sync.c \
        imap-thread.c \
        mail-storage-callbacks.c \
        main.c \
@@ -84,5 +85,6 @@ noinst_HEADERS = \
        imap-messageset.h \
        imap-search.h \
        imap-sort.h \
+       imap-sync.h \
        imap-thread.h \
        namespace.h
index 7ae049b5d64cc0c47e38ce698fa5ee6103a14577..3712c0b925e5b0ee6ebc0c5f22dfb49194bc114c 100644 (file)
@@ -25,6 +25,7 @@ struct client {
        struct mailbox *mailbox;
         struct mailbox_keywords keywords;
        unsigned int select_counter; /* increased when mailbox is changed */
+       uint32_t messages_count, recent_count;
 
        time_t last_input;
        unsigned int bad_counter;
index e43a4a29f9e761b02159c48e4e45de75bb785543..f3a7b8e58fa899d927a5cfc9f1113548b47141ee 100644 (file)
@@ -5,6 +5,7 @@
 #include "istream.h"
 #include "ostream.h"
 #include "commands.h"
+#include "imap-sync.h"
 
 #include <stdlib.h>
 
@@ -19,7 +20,7 @@ static void idle_finish(struct client *client, int done_ok)
 
        o_stream_cork(client->output);
 
-       if (client->idle_expunge) {
+       if (client->idle_expunge != 0) {
                client_send_line(client,
                        t_strdup_printf("* %u EXPUNGE", client->idle_expunge));
        }
@@ -28,12 +29,8 @@ static void idle_finish(struct client *client, int done_ok)
        client->io = io_add(i_stream_get_fd(client->input),
                            IO_READ, _client_input, client);
 
-       if (client->mailbox != NULL) {
-               mailbox_auto_sync(client->mailbox, mailbox_check_interval != 0 ?
-                                 MAILBOX_SYNC_FLAG_NO_EXPUNGES :
-                                 MAILBOX_SYNC_AUTO_STOP,
-                                 mailbox_check_interval);
-       }
+       if (client->mailbox != NULL)
+               mailbox_notify_changes(client->mailbox, 0, NULL, NULL);
 
        client_sync_full(client);
        if (done_ok)
@@ -78,21 +75,28 @@ static void idle_client_input(void *context)
 static void idle_timeout(void *context)
 {
        struct client *client = context;
-       struct mailbox_status status;
+
+       /* outlook workaround - it hasn't sent anything for a long time and
+          we're about to disconnect unless it does something. send a fake
+          EXISTS to see if it responds. it's expunged later. */
 
        timeout_remove(client->idle_to);
        client->idle_to = NULL;
 
-       if (mailbox_get_status(client->mailbox, STATUS_MESSAGES, &status) < 0) {
+       client->idle_expunge = client->messages_count+1;
+       client_send_line(client,
+                        t_strdup_printf("* %u EXISTS", client->idle_expunge));
+       mailbox_notify_changes(client->mailbox, 0, NULL, NULL);
+}
+
+static void idle_callback(struct mailbox *box, void *context)
+{
+       struct client *client = context;
+
+       if (imap_sync(client, box, 0) < 0) {
                client_send_untagged_storage_error(client,
                        mailbox_get_storage(client->mailbox));
-               idle_finish(client, TRUE);
-       } else {
-                client->idle_expunge = status.messages+1;
-               client_send_line(client,
-                       t_strdup_printf("* %u EXISTS", client->idle_expunge));
-
-               mailbox_auto_sync(client->mailbox, MAILBOX_SYNC_AUTO_STOP, 0);
+               mailbox_notify_changes(client->mailbox, 0, NULL, NULL);
        }
 }
 
@@ -113,9 +117,10 @@ int cmd_idle(struct client *client)
        if (interval == 0)
                interval = DEFAULT_IDLE_CHECK_INTERVAL;
 
-       if (client->mailbox != NULL)
-               mailbox_auto_sync(client->mailbox, 0, interval);
-
+       if (client->mailbox != NULL) {
+               mailbox_notify_changes(client->mailbox, interval,
+                                      idle_callback, client);
+       }
        client_send_line(client, "+ idling");
 
        io_remove(client->io);
index 080133e62ea5140620cad3f82945e4b59ea1ed26..f9fc81e464c26686c78f068b28681a71a2d27d90 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "common.h"
 #include "commands.h"
+#include "imap-sync.h"
 
 int _cmd_select_full(struct client *client, int readonly)
 {
@@ -34,6 +35,12 @@ int _cmd_select_full(struct client *client, int readonly)
                return TRUE;
        }
 
+       if (imap_sync(client, box, 0) < 0) {
+               client_send_storage_error(client, storage);
+               mailbox_close(box);
+               return TRUE;
+       }
+
        if (mailbox_get_status(box, STATUS_MESSAGES | STATUS_RECENT |
                               STATUS_FIRST_UNSEEN_SEQ | STATUS_UIDVALIDITY |
                               STATUS_UIDNEXT | STATUS_KEYWORDS,
@@ -45,6 +52,8 @@ int _cmd_select_full(struct client *client, int readonly)
 
        client_save_keywords(&client->keywords,
                             status.keywords, status.keywords_count);
+       client->messages_count = status.messages;
+       client->recent_count = status.recent;
 
        /* set client's mailbox only after getting status to make sure
           we're not sending any expunge/exists replies too early to client */
@@ -81,12 +90,6 @@ int _cmd_select_full(struct client *client, int readonly)
        client_send_tagline(client, mailbox_is_readonly(box) ?
                            "OK [READ-ONLY] Select completed." :
                            "OK [READ-WRITE] Select completed.");
-
-       if (mailbox_check_interval != 0) {
-               mailbox_auto_sync(box, MAILBOX_SYNC_FLAG_NO_EXPUNGES,
-                                 mailbox_check_interval);
-       }
-
        return TRUE;
 }
 
index 61fd3ea8cf403faf7bd3cf2598ffaeebfa173aa7..2f90cf35b68ad26433de4911edb16938da4cee73 100644 (file)
@@ -4,6 +4,7 @@
 #include "str.h"
 #include "imap-quote.h"
 #include "commands.h"
+#include "imap-sync.h"
 
 /* Returns status items, or -1 if error */
 static enum mailbox_status_items
@@ -64,7 +65,10 @@ static int get_mailbox_status(struct client *client,
                        return FALSE;
        }
 
-       failed = mailbox_get_status(box, items, status) < 0;
+       if (imap_sync(client, box, 0) < 0)
+               failed = TRUE;
+       else
+               failed = mailbox_get_status(box, items, status) < 0;
 
        if (box != client->mailbox)
                mailbox_close(box);
index 779b6d743c1ea044880b27b271e49526411aa497..9d3deb99436a33d1c79ff35641ff27dd298ab17b 100644 (file)
@@ -1,6 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "common.h"
+#include "str.h"
 #include "commands.h"
 #include "imap-search.h"
 #include "imap-util.h"
@@ -37,19 +38,21 @@ static int get_modify_type(struct client *client, const char *item,
 static int mail_send_flags(struct client *client, struct mail *mail)
 {
        const struct mail_full_flags *flags;
-       const char *str;
+       string_t *str;
 
        flags = mail->get_flags(mail);
        if (flags == NULL)
                return FALSE;
 
        t_push();
-       str = imap_write_flags(flags);
-       str = t_strdup_printf(client->cmd_uid ?
-                             "* %u FETCH (FLAGS (%s) UID %u)" :
-                             "* %u FETCH (FLAGS (%s))",
-                             mail->seq, str, mail->uid);
-       client_send_line(client, str);
+       str = t_str_new(128);
+       str_printfa(str, "* %u FETCH (FLAGS (", mail->seq);
+       imap_write_flags(str, flags);
+       if (client->cmd_uid)
+               str_printfa(str, ") UID %u)", mail->uid);
+       else
+               str_append(str, "))");
+       client_send_line(client, str_c(str));
        t_pop();
 
        return TRUE;
index 93ee9b5add2ffa5d1e0b6ce87bc336314b59bc34..9ecfce8da0d2f4f54ad6da27b4b876afa5834eb1 100644 (file)
@@ -7,6 +7,7 @@
 #include "imap-util.h"
 #include "mail-storage.h"
 #include "imap-parser.h"
+#include "imap-sync.h"
 #include "namespace.h"
 
 /* Maximum length for mailbox name, including it's path. This isn't fully
@@ -116,7 +117,7 @@ void client_sync_full(struct client *client)
        if (client->mailbox == NULL)
                return;
 
-       if (mailbox_sync(client->mailbox, 0) < 0) {
+       if (imap_sync(client, client->mailbox, 0) < 0) {
                client_send_untagged_storage_error(client,
                        mailbox_get_storage(client->mailbox));
        }
@@ -127,7 +128,7 @@ void client_sync_full_fast(struct client *client)
        if (client->mailbox == NULL)
                return;
 
-       if (mailbox_sync(client->mailbox, MAILBOX_SYNC_FLAG_FAST) < 0) {
+       if (imap_sync(client, client->mailbox, MAILBOX_SYNC_FLAG_FAST) < 0) {
                client_send_untagged_storage_error(client,
                        mailbox_get_storage(client->mailbox));
        }
@@ -138,8 +139,8 @@ void client_sync_without_expunges(struct client *client)
        if (client->mailbox == NULL)
                return;
 
-       if (mailbox_sync(client->mailbox, MAILBOX_SYNC_FLAG_FAST |
-                        MAILBOX_SYNC_FLAG_NO_EXPUNGES) < 0) {
+       if (imap_sync(client, client->mailbox, MAILBOX_SYNC_FLAG_FAST |
+                     MAILBOX_SYNC_FLAG_NO_EXPUNGES) < 0) {
                client_send_untagged_storage_error(client,
                        mailbox_get_storage(client->mailbox));
        }
index 4da3f6d3bf14daaeae0081dc4a33894a2b9d04a0..dc5fbc9e239bbbe96d03fc0625ca9be2b670995c 100644 (file)
@@ -58,7 +58,9 @@ static int fetch_flags(struct imap_fetch_context *ctx, struct mail *mail,
                flags = &full_flags;
        }
 
-       str_printfa(ctx->str, "FLAGS (%s) ", imap_write_flags(flags));
+       str_append(ctx->str, "FLAGS (");
+       imap_write_flags(ctx->str, flags);
+       str_append(ctx->str, ") ");
        return TRUE;
 }
 
diff --git a/src/imap/imap-sync.c b/src/imap/imap-sync.c
new file mode 100644 (file)
index 0000000..7c285ae
--- /dev/null
@@ -0,0 +1,88 @@
+/* Copyright (C) 2002 Timo Sirainen */
+
+#include "common.h"
+#include "str.h"
+#include "imap-util.h"
+#include "mail-storage.h"
+#include "imap-sync.h"
+
+int imap_sync(struct client *client, struct mailbox *box,
+             enum mailbox_sync_flags flags)
+{
+        struct mailbox_transaction_context *t;
+       struct mailbox_sync_context *ctx;
+        struct mailbox_sync_rec sync_rec;
+       struct mailbox_status status;
+       struct mail *mail;
+        const struct mail_full_flags *mail_flags;
+       string_t *str;
+       uint32_t seq;
+
+       if (client->mailbox != box) {
+               /* mailbox isn't selected - we only wish to sync the mailbox
+                  without sending anything to client */
+               ctx = mailbox_sync_init(box, flags);
+               while (mailbox_sync_next(ctx, &sync_rec) > 0)
+                       ;
+               return mailbox_sync_deinit(ctx, &status);
+       }
+
+       t_push();
+       str = t_str_new(256);
+
+       t = mailbox_transaction_begin(box, FALSE);
+       ctx = mailbox_sync_init(box, flags);
+       while (mailbox_sync_next(ctx, &sync_rec) > 0) {
+               switch (sync_rec.type) {
+               case MAILBOX_SYNC_TYPE_FLAGS:
+                       for (seq = sync_rec.seq1; seq <= sync_rec.seq2; seq++) {
+                               mail = mailbox_fetch(t, seq, MAIL_FETCH_FLAGS);
+
+                               mail_flags = mail->get_flags(mail);
+                               if (mail_flags == NULL)
+                                       continue;
+
+                               str_truncate(str, 0);
+                               str_printfa(str, "* %u FETCH (FLAGS (", seq);
+                               imap_write_flags(str, mail_flags);
+                               str_append(str, "))");
+                               client_send_line(client, str_c(str));
+                       }
+                       break;
+               case MAILBOX_SYNC_TYPE_EXPUNGE:
+                       for (seq = sync_rec.seq2; seq >= sync_rec.seq1; seq--) {
+                               str_truncate(str, 0);
+                               str_printfa(str, "* %u EXPUNGE", seq);
+                               client_send_line(client, str_c(str));
+                       }
+                       break;
+               }
+       }
+
+       if (mailbox_sync_deinit(ctx, &status) < 0) {
+               mailbox_transaction_rollback(t);
+               t_pop();
+               return -1;
+       }
+
+       mailbox_transaction_commit(t);
+
+       if (status.messages != client->messages_count) {
+                client->messages_count = status.messages;
+               str_truncate(str, 0);
+               str_printfa(str, "* %u EXISTS", status.messages);
+               client_send_line(client, str_c(str));
+       }
+       if (status.recent != client->recent_count) {
+                client->recent_count = status.recent;
+               str_truncate(str, 0);
+               str_printfa(str, "* %u RECENT", status.recent);
+               client_send_line(client, str_c(str));
+       }
+
+       /*FIXME:client_save_keywords(&client->keywords, keywords, keywords_count);
+       client_send_mailbox_flags(client, mailbox, keywords, keywords_count);*/
+
+       t_pop();
+       return 0;
+}
diff --git a/src/imap/imap-sync.h b/src/imap/imap-sync.h
new file mode 100644 (file)
index 0000000..2ec36e7
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __IMAP_SYNC_H
+#define __IMAP_SYNC_H
+
+int imap_sync(struct client *client, struct mailbox *box,
+             enum mailbox_sync_flags flags);
+
+#endif
index ddb68289dfb0adda7e997c8d075ff26ca8ecb497..ed06254832ab481a67bc804b4cfa5acb066e865d 100644 (file)
@@ -33,79 +33,8 @@ static void notify_no(struct mailbox *mailbox __attr_unused__,
        o_stream_flush(client->output);
 }
 
-static void expunge(struct mailbox *mailbox, unsigned int seq, void *context)
-{
-       struct client *client = context;
-       char str[MAX_INT_STRLEN+20];
-
-       if (client->mailbox != mailbox)
-               return;
-
-       i_snprintf(str, sizeof(str), "* %u EXPUNGE", seq);
-       client_send_line(client, str);
-}
-
-static void update_flags(struct mailbox *mailbox, unsigned int seq,
-                        const struct mail_full_flags *flags, void *context)
-{
-       struct client *client = context;
-       const char *str;
-
-       if (client->mailbox != mailbox)
-               return;
-
-       t_push();
-       str = imap_write_flags(flags);
-       str = t_strdup_printf("* %u FETCH (FLAGS (%s))", seq, str);
-       client_send_line(client, str);
-       t_pop();
-}
-
-static void message_count_changed(struct mailbox *mailbox, unsigned int count,
-                                 void *context)
-{
-       struct client *client = context;
-       char str[MAX_INT_STRLEN+20];
-
-       if (client->mailbox != mailbox)
-               return;
-
-       i_snprintf(str, sizeof(str), "* %u EXISTS", count);
-       client_send_line(client, str);
-}
-
-static void recent_count_changed(struct mailbox *mailbox, unsigned int count,
-                                void *context)
-{
-       struct client *client = context;
-       char str[MAX_INT_STRLEN+20];
-
-       if (client->mailbox != mailbox)
-               return;
-
-       i_snprintf(str, sizeof(str), "* %u RECENT", count);
-       client_send_line(client, str);
-}
-
-static void new_keywords(struct mailbox *mailbox, const char *keywords[],
-                        unsigned int keywords_count, void *context)
-{
-       struct client *client = context;
-
-       if (client->mailbox != mailbox)
-               return;
-
-       client_save_keywords(&client->keywords, keywords, keywords_count);
-       client_send_mailbox_flags(client, mailbox, keywords, keywords_count);
-}
-
 struct mail_storage_callbacks mail_storage_callbacks = {
        alert_no_diskspace,
        notify_ok,
-       notify_no,
-       expunge,
-       update_flags,
-       message_count_changed,
-       recent_count_changed,
-       new_keywords
+       notify_no
 };
index d8bb0b1e7eb63009b21f6fbec2bf474804d3b443..d3715fcf6ebf126d61350063107fb2fc262bbbbf 100644 (file)
@@ -5,38 +5,33 @@
 #include "mail-types.h"
 #include "imap-util.h"
 
-const char *imap_write_flags(const struct mail_full_flags *flags)
+void imap_write_flags(string_t *dest, const struct mail_full_flags *flags)
 {
-       string_t *str;
-       const char *sysflags;
        unsigned int i;
-
-       if (flags == 0)
-               return "";
-
-       sysflags = t_strconcat(
-               (flags->flags & MAIL_ANSWERED) ? " \\Answered" : "",
-               (flags->flags & MAIL_FLAGGED) ? " \\Flagged" : "",
-               (flags->flags & MAIL_DELETED) ? " \\Deleted" : "",
-               (flags->flags & MAIL_SEEN) ? " \\Seen" : "",
-               (flags->flags & MAIL_DRAFT) ? " \\Draft" : "",
-               (flags->flags & MAIL_RECENT)  ? " \\Recent" : "",
-               NULL);
-
-       if (*sysflags != '\0')
-               sysflags++;
-
-       if (flags->keywords_count == 0)
-               return sysflags;
-
-       /* we have keywords too */
-       str = t_str_new(256);
-       str_append(str, sysflags);
-
-       for (i = 0; i < flags->keywords_count; i++) {
-               if (str_len(str) > 0)
-                       str_append_c(str, ' ');
-               str_append(str, flags->keywords[i]);
+       size_t size;
+
+       size = str_len(dest);
+       if ((flags->flags & MAIL_ANSWERED) != 0)
+               str_append(dest, "\\Answered ");
+       if ((flags->flags & MAIL_FLAGGED) != 0)
+               str_append(dest, "\\Flagged ");
+       if ((flags->flags & MAIL_DELETED) != 0)
+               str_append(dest, "\\Deleted ");
+       if ((flags->flags & MAIL_SEEN) != 0)
+               str_append(dest, "\\Seen ");
+       if ((flags->flags & MAIL_DRAFT) != 0)
+               str_append(dest, "\\Draft ");
+       if ((flags->flags & MAIL_RECENT) != 0)
+               str_append(dest, "\\Recent ");
+
+       if (flags->keywords_count > 0) {
+               /* we have keywords too */
+               for (i = 0; i < flags->keywords_count; i++) {
+                       str_append(dest, flags->keywords[i]);
+                       str_append_c(dest, ' ');
+               }
        }
-       return str_c(str);
+
+       if (str_len(dest) != size)
+               str_truncate(dest, str_len(dest)-1);
 }
index 5e2ec036e844d3ac3fe3d1be966eea25318de848..6ab9f410f9f67210a6fba6e45fb9d209f848baec 100644 (file)
@@ -4,6 +4,6 @@
 struct mail_full_flags;
 
 /* Return flags as a space separated string. */
-const char *imap_write_flags(const struct mail_full_flags *flags);
+void imap_write_flags(string_t *dest, const struct mail_full_flags *flags);
 
 #endif
index 3f78054558870a96bade748490ffb883a9a44cbf..a38591e143040315643e37cc28bc1c15940a7e54 100644 (file)
@@ -9,31 +9,46 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 
+struct index_notify_file {
+       struct index_notify_file *next;
+
+       char *path;
+       time_t last_stamp;
+};
+
+struct index_notify_io {
+       struct index_notify_io *next;
+       struct io *io;
+       int fd;
+};
+
 static void check_timeout(void *context)
 {
        struct index_mailbox *ibox = context;
-       struct index_autosync_file *file;
+       struct index_notify_file *file;
        struct stat st;
-       int sync;
+       time_t last_check;
+       int notify;
 
        /* check changes only when we can also notify of new mail */
-       if ((unsigned int) (ioloop_time - ibox->sync_last_check) <
-           ibox->min_newmail_notify_interval)
+       last_check = I_MAX(ibox->sync_last_check, ibox->notify_last_check);
+       if ((unsigned int)(ioloop_time - last_check) <
+           ibox->min_notify_interval)
                return;
 
-       ibox->sync_last_check = ioloop_time;
+       ibox->notify_last_check = ioloop_time;
 
-       sync = ibox->autosync_pending;
-       for (file = ibox->autosync_files; file != NULL; file = file->next) {
+       notify = ibox->notify_pending;
+       for (file = ibox->notify_files; file != NULL; file = file->next) {
                if (stat(file->path, &st) == 0 &&
                    file->last_stamp != st.st_mtime)
                        file->last_stamp = st.st_mtime;
        }
 
-       if (sync) {
-               ibox->box.sync(&ibox->box, ibox->autosync_flags);
-               ibox->sync_last_notify = ioloop_time;
-               ibox->autosync_pending = FALSE;
+       if (notify) {
+               ibox->notify_last_sent = ioloop_time;
+               ibox->notify_pending = FALSE;
+               ibox->notify_callback(&ibox->box, ibox->notify_context);
        }
 }
 
@@ -41,24 +56,24 @@ static void notify_callback(void *context)
 {
        struct index_mailbox *ibox = context;
 
-       ibox->sync_last_check = ioloop_time;
-       if ((unsigned int) (ioloop_time - ibox->sync_last_notify) >=
-           ibox->min_newmail_notify_interval) {
-               ibox->box.sync(&ibox->box, ibox->autosync_flags);
-               ibox->sync_last_notify = ioloop_time;
-                ibox->autosync_pending = FALSE;
+       ibox->notify_last_check = ioloop_time;
+       if ((unsigned int)(ioloop_time - ibox->notify_last_sent) >=
+           ibox->min_notify_interval) {
+               ibox->notify_last_sent = ioloop_time;
+                ibox->notify_pending = FALSE;
+               ibox->notify_callback(&ibox->box, ibox->notify_context);
        } else {
-               ibox->autosync_pending = TRUE;
+               ibox->notify_pending = TRUE;
        }
 }
 
 void index_mailbox_check_add(struct index_mailbox *ibox,
                             const char *path, int dir)
 {
-       struct index_autosync_file *file;
+       struct index_notify_file *file;
        struct stat st;
        struct io *io;
-       struct index_autosync_io *aio;
+       struct index_notify_io *aio;
        int fd;
 
        fd = open(path, O_RDONLY);
@@ -66,56 +81,56 @@ void index_mailbox_check_add(struct index_mailbox *ibox,
                io = io_add(fd, dir ? IO_DIR_NOTIFY : IO_FILE_NOTIFY,
                            notify_callback, ibox);
                if (io != NULL) {
-                       aio = i_new(struct index_autosync_io, 1);
+                       aio = i_new(struct index_notify_io, 1);
                        aio->io = io;
                        aio->fd = fd;
-                       aio->next = ibox->autosync_ios;
-                       ibox->autosync_ios = aio;
+                       aio->next = ibox->notify_ios;
+                       ibox->notify_ios = aio;
                }
        }
 
-       file = i_new(struct index_autosync_file, 1);
+       file = i_new(struct index_notify_file, 1);
        file->path = i_strdup(path);
        if (fd < 0)
                file->last_stamp = stat(path, &st) < 0 ? 0 : st.st_mtime;
        else
                file->last_stamp = fstat(fd, &st) < 0 ? 0 : st.st_mtime;
 
-       file->next = ibox->autosync_files;
-        ibox->autosync_files = file;
+       file->next = ibox->notify_files;
+        ibox->notify_files = file;
 
-       if (ibox->autosync_to == NULL)
-               ibox->autosync_to = timeout_add(1000, check_timeout, ibox);
+       if (ibox->notify_to == NULL)
+               ibox->notify_to = timeout_add(1000, check_timeout, ibox);
 }
 
 void index_mailbox_check_remove_all(struct index_mailbox *ibox)
 {
-       struct index_autosync_file *file;
-       struct index_autosync_io *aio;
+       struct index_notify_file *file;
+       struct index_notify_io *aio;
 
        /* reset notify stamp */
-       ibox->sync_last_notify = 0;
+       ibox->notify_last_sent = 0;
 
-       while (ibox->autosync_files != NULL) {
-               file = ibox->autosync_files;
-               ibox->autosync_files = file->next;
+       while (ibox->notify_files != NULL) {
+               file = ibox->notify_files;
+               ibox->notify_files = file->next;
 
                 i_free(file->path);
                i_free(file);
        }
 
-       while (ibox->autosync_ios != NULL) {
-               aio = ibox->autosync_ios;
-               ibox->autosync_ios = aio->next;
+       while (ibox->notify_ios != NULL) {
+               aio = ibox->notify_ios;
+               ibox->notify_ios = aio->next;
 
                io_remove(aio->io);
                if (close(aio->fd) < 0)
-                       i_error("close(autosync_io) failed: %m");
+                       i_error("close(notify_io) failed: %m");
                i_free(aio);
        }
 
-       if (ibox->autosync_to != NULL) {
-               timeout_remove(ibox->autosync_to);
-               ibox->autosync_to = NULL;
+       if (ibox->notify_to != NULL) {
+               timeout_remove(ibox->notify_to);
+               ibox->notify_to = NULL;
        }
 }
index e9d7f8632b9c038fdc07b1460fb9c00d34dcc79f..63e70efbe06c6d76397f0a6ae801dec57ecec8c2 100644 (file)
@@ -3,10 +3,6 @@
 #include "lib.h"
 #include "index-storage.h"
 
-#define STATUS_MESSAGE_COUNTS \
-       (STATUS_MESSAGES | STATUS_RECENT | STATUS_UIDNEXT | \
-        STATUS_UIDVALIDITY | STATUS_UNSEEN | STATUS_FIRST_UNSEEN_SEQ)
-
 /*static void
 get_keywords(struct mail_keywords *mcf, struct mailbox_status *status)
 {
@@ -21,44 +17,47 @@ get_keywords(struct mail_keywords *mcf, struct mailbox_status *status)
                status->keywords[i] = t_strdup(flags[i]);
 }*/
 
-int index_storage_get_status(struct mailbox *box,
-                            enum mailbox_status_items items,
-                            struct mailbox_status *status)
+int index_storage_get_status_locked(struct index_mailbox *ibox,
+                                   enum mailbox_status_items items,
+                                   struct mailbox_status *status_r)
 {
-       struct index_mailbox *ibox = (struct index_mailbox *) box;
        const struct mail_index_header *hdr;
 
-       memset(status, 0, sizeof(struct mailbox_status));
-
-       if ((items & STATUS_MESSAGE_COUNTS) != 0) {
-               /* sync mailbox to update message counts */
-               if (mailbox_sync(box, 0) < 0)
-                       return -1;
-       }
+       memset(status_r, 0, sizeof(struct mailbox_status));
 
        /* we can get most of the status items without any trouble */
        if (mail_index_get_header(ibox->view, &hdr) < 0)
                return -1;
-       if ((items & STATUS_MESSAGE_COUNTS) != 0) {
-               status->messages = hdr->messages_count;
-               status->recent = ibox->synced_recent_count;
-               status->unseen = hdr->messages_count - hdr->seen_messages_count;
-               status->uidvalidity = hdr->uid_validity;
-               status->uidnext = hdr->next_uid;
-       }
-       //FIXME:status->diskspace_full = ibox->nodiskspace;
+
+       status_r->messages = hdr->messages_count;
+       status_r->recent = ibox->synced_recent_count;
+       status_r->unseen =
+               hdr->messages_count - hdr->seen_messages_count;
+       status_r->uidvalidity = hdr->uid_validity;
+       status_r->uidnext = hdr->next_uid;
+       //FIXME:status_r->diskspace_full = ibox->nodiskspace;
 
        if (items & STATUS_FIRST_UNSEEN_SEQ) {
                if (mail_index_lookup_first(ibox->view, 0, MAIL_SEEN,
-                                           &status->first_unseen_seq) < 0) {
+                                           &status_r->first_unseen_seq) < 0) {
                        mail_storage_set_index_error(ibox);
                        return -1;
                }
        }
 
        /*FIXME:if (items & STATUS_KEYWORDS)
-               get_keywords(ibox, status);*/
+               get_keywords(ibox, status_r);*/
+       return 0;
+}
+
+int index_storage_get_status(struct mailbox *box,
+                            enum mailbox_status_items items,
+                            struct mailbox_status *status)
+{
+       struct index_mailbox *ibox = (struct index_mailbox *)box;
+       int ret;
 
+       ret = index_storage_get_status_locked(ibox, items, status);
        mail_index_view_unlock(ibox->view);
-       return 0;
+       return ret;
 }
index 3e4602384d1fe7916defe043bcb0cd103c9e931e..caa16952b245cfd14d266d0ccf29288f8d45db3a 100644 (file)
@@ -22,19 +22,6 @@ enum mailbox_lock_notify_type {
        MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE
 };
 
-struct index_autosync_file {
-       struct index_autosync_file *next;
-
-       char *path;
-       time_t last_stamp;
-};
-
-struct index_autosync_io {
-       struct index_autosync_io *next;
-       struct io *io;
-       int fd;
-};
-
 struct index_storage {
        struct mail_storage storage;
 
@@ -63,12 +50,13 @@ struct index_mailbox {
        void (*mail_deinit)(struct index_mail *mail);
        int (*is_recent)(struct index_mailbox *ibox, uint32_t uid);
 
-       struct timeout *autosync_to;
-       struct index_autosync_file *autosync_files;
-        struct index_autosync_io *autosync_ios;
-       enum mailbox_sync_flags autosync_flags;
-       time_t sync_last_check, sync_last_notify;
-       unsigned int min_newmail_notify_interval;
+       struct timeout *notify_to;
+       struct index_notify_file *notify_files;
+        struct index_notify_io *notify_ios;
+       time_t notify_last_check, notify_last_sent;
+       unsigned int min_notify_interval;
+       mailbox_notify_callback_t *notify_callback;
+       void *notify_context;
 
        time_t next_lock_notify; /* temporary */
        enum mailbox_lock_notify_type last_notify_type;
@@ -78,7 +66,8 @@ struct index_mailbox {
 
        buffer_t *recent_flags;
        uint32_t recent_flags_start_seq, recent_flags_count;
-       unsigned int synced_recent_count;
+       uint32_t synced_recent_count;
+       time_t sync_last_check;
 
        /* mbox: */
        int mbox_fd;
@@ -106,7 +95,7 @@ struct index_mailbox {
        unsigned int recent_flags_synced:1;
        unsigned int sent_diskspace_warning:1;
        unsigned int sent_readonly_flags_warning:1;
-       unsigned int autosync_pending:1;
+       unsigned int notify_pending:1;
        unsigned int mail_read_mmaped:1;
        unsigned int syncing_commit:1;
 };
@@ -164,6 +153,14 @@ void index_mailbox_check_add(struct index_mailbox *ibox,
                             const char *path, int dir);
 void index_mailbox_check_remove_all(struct index_mailbox *ibox);
 
+struct mailbox_sync_context *
+index_mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags,
+                       int failed);
+int index_mailbox_sync_next(struct mailbox_sync_context *ctx,
+                           struct mailbox_sync_rec *sync_rec_r);
+int index_mailbox_sync_deinit(struct mailbox_sync_context *ctx,
+                             struct mailbox_status *status_r);
+
 int index_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags);
 
 void index_storage_set_callbacks(struct mail_storage *storage,
@@ -174,6 +171,9 @@ const char *index_storage_get_last_error(struct mail_storage *storage,
 int index_storage_get_status(struct mailbox *box,
                             enum mailbox_status_items items,
                             struct mailbox_status *status);
+int index_storage_get_status_locked(struct index_mailbox *ibox,
+                                   enum mailbox_status_items items,
+                                   struct mailbox_status *status_r);
 
 struct mail *
 index_storage_fetch(struct mailbox_transaction_context *t, uint32_t seq,
index fdb9efa228709e0309f59e8983cfc5e623bcad6f..abf627e64658669430d623c342dc50538814e387 100644 (file)
@@ -4,6 +4,17 @@
 #include "buffer.h"
 #include "index-storage.h"
 
+struct index_mailbox_sync_context {
+       struct mailbox_sync_context ctx;
+       struct index_mailbox *ibox;
+       struct mail_index_view_sync_ctx *sync_ctx;
+       uint32_t messages_count;
+
+       const uint32_t *expunges;
+       size_t expunges_count;
+       int failed;
+};
+
 void index_mailbox_set_recent(struct index_mailbox *ibox, uint32_t seq)
 {
        unsigned char *p;
@@ -97,124 +108,142 @@ static int index_mailbox_update_recent(struct index_mailbox *ibox,
        return 0;
 }
 
-int index_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
+struct mailbox_sync_context *
+index_mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags,
+                       int failed)
 {
        struct index_mailbox *ibox = (struct index_mailbox *)box;
-       struct mail_index_view_sync_ctx *ctx;
-        struct mail_full_flags full_flags;
-       const struct mail_index_record *rec;
-       struct mail_index_sync_rec sync;
-       struct mail_storage_callbacks *sc;
-       const uint32_t *expunges;
-       size_t i, expunges_count;
-       void *sc_context;
+        struct index_mailbox_sync_context *ctx;
        enum mail_index_sync_type sync_mask;
-       uint32_t seq, seq1, seq2;
-       uint32_t messages_count, last_messages_count;
-       int ret;
+
+       ctx = i_new(struct index_mailbox_sync_context, 1);
+       ctx->ctx.box = box;
+       ctx->ibox = ibox;
+
+       if (failed) {
+               ctx->failed = TRUE;
+               return &ctx->ctx;
+       }
+
+       ctx->messages_count = mail_index_view_get_message_count(ibox->view);
 
        sync_mask = MAIL_INDEX_SYNC_MASK_ALL;
        if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) != 0)
                sync_mask &= ~MAIL_INDEX_SYNC_TYPE_EXPUNGE;
 
-       if (mail_index_view_sync_begin(ibox->view, sync_mask, &ctx) < 0) {
-                mail_storage_set_index_error(ibox);
-               return -1;
+       if (mail_index_view_sync_begin(ibox->view, sync_mask,
+                                      &ctx->sync_ctx) < 0) {
+               mail_storage_set_index_error(ibox);
+               ctx->failed = TRUE;
+               return &ctx->ctx;
        }
 
-       last_messages_count = mail_index_view_get_message_count(ibox->view);
-
        if (!ibox->recent_flags_synced) {
                ibox->recent_flags_synced = TRUE;
-                index_mailbox_update_recent(ibox, 1, last_messages_count);
+                index_mailbox_update_recent(ibox, 1, ctx->messages_count);
        }
 
-       if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) != 0) {
-               expunges_count = 0;
-               expunges = NULL;
-       } else {
-               expunges =
-                       mail_index_view_sync_get_expunges(ctx, &expunges_count);
+       if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) == 0) {
+               ctx->expunges =
+                       mail_index_view_sync_get_expunges(ctx->sync_ctx,
+                                                         &ctx->expunges_count);
        }
+       return &ctx->ctx;
+}
 
-       sc = ibox->storage->callbacks;
-       sc_context = ibox->storage->callback_context;
+int index_mailbox_sync_next(struct mailbox_sync_context *_ctx,
+                           struct mailbox_sync_rec *sync_rec_r)
+{
+       struct index_mailbox_sync_context *ctx =
+               (struct index_mailbox_sync_context *)_ctx;
+       struct mail_index_sync_rec sync;
+       int ret;
 
-       memset(&full_flags, 0, sizeof(full_flags));
-       while ((ret = mail_index_view_sync_next(ctx, &sync)) > 0) {
+       if (ctx->failed)
+               return -1;
+
+       while ((ret = mail_index_view_sync_next(ctx->sync_ctx, &sync)) > 0) {
                switch (sync.type) {
                case MAIL_INDEX_SYNC_TYPE_APPEND:
+                       /* not interested */
                        break;
                case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
                        /* later */
                        break;
                case MAIL_INDEX_SYNC_TYPE_FLAGS:
-                       if (sc->update_flags == NULL)
-                               break;
-
                        /* FIXME: hide the flag updates for expunged messages */
-
-                       if (mail_index_lookup_uid_range(ibox->view,
-                                                       sync.uid1, sync.uid2,
-                                                       &seq1, &seq2) < 0) {
-                               ret = -1;
-                               break;
+                       if (mail_index_lookup_uid_range(ctx->ibox->view,
+                                               sync.uid1, sync.uid2,
+                                               &sync_rec_r->seq1,
+                                               &sync_rec_r->seq2) < 0) {
+                               ctx->failed = TRUE;
+                               return -1;
                        }
 
-                       if (seq1 == 0)
+                       if (sync_rec_r->seq1 == 0)
                                break;
 
-                       for (seq = seq1; seq <= seq2; seq++) {
-                               if (mail_index_lookup(ibox->view,
-                                                     seq, &rec) < 0) {
-                                       ret = -1;
-                                       break;
-                               }
-                               full_flags.flags = rec->flags; // FIXME
-                               if (index_mailbox_is_recent(ibox, seq))
-                                       full_flags.flags |= MAIL_RECENT;
-                               sc->update_flags(&ibox->box, seq,
-                                                &full_flags, sc_context);
-                       }
-                       break;
+                       sync_rec_r->type = MAILBOX_SYNC_TYPE_FLAGS;
+                       return 1;
                }
        }
 
-       if (ret < 0)
-               mail_storage_set_index_error(ibox);
-
-       if (sc->expunge != NULL) {
+       if (ret == 0 && ctx->expunges_count > 0) {
                /* expunges[] is a sorted array of sequences. it's easiest for
                   us to print them from end to beginning. */
-               messages_count = mail_index_view_get_message_count(ibox->view);
-               for (i = expunges_count*2; i > 0; i -= 2) {
-                       seq = expunges[i-1];
-                       index_mailbox_expunge_recent(ibox, expunges[i-2], seq);
-                       if (seq > messages_count)
-                               seq = messages_count;
-                       for (; seq >= expunges[i-2]; seq--) {
-                               sc->expunge(&ibox->box, seq, sc_context);
-                               last_messages_count--;
-                       }
-               }
-       }
+               sync_rec_r->seq1 = ctx->expunges[ctx->expunges_count*2-2];
+               sync_rec_r->seq2 = ctx->expunges[ctx->expunges_count*2-1];
+               index_mailbox_expunge_recent(ctx->ibox, sync_rec_r->seq1,
+                                            sync_rec_r->seq2);
+
+               if (sync_rec_r->seq2 > ctx->messages_count)
+                       sync_rec_r->seq2 = ctx->messages_count;
 
-       mail_index_view_sync_end(ctx);
+               ctx->messages_count -= sync_rec_r->seq2 - sync_rec_r->seq1 + 1;
+               ctx->expunges_count--;
 
-       messages_count = mail_index_view_get_message_count(ibox->view);
-       if (messages_count != last_messages_count) {
-               index_mailbox_update_recent(ibox, last_messages_count+1,
-                                           messages_count);
-               sc->message_count_changed(&ibox->box, messages_count,
-                                         sc_context);
+               sync_rec_r->type = MAILBOX_SYNC_TYPE_EXPUNGE;
+               return 1;
        }
 
-       if (ibox->recent_flags_count != ibox->synced_recent_count) {
-                ibox->synced_recent_count = ibox->recent_flags_count;
-               sc->recent_count_changed(&ibox->box, ibox->synced_recent_count,
-                                        sc_context);
+       if (ret < 0)
+               mail_storage_set_index_error(ctx->ibox);
+       return ret;
+}
+
+#define SYNC_STATUS_FLAGS \
+       (STATUS_MESSAGES | STATUS_RECENT | STATUS_UIDNEXT | \
+        STATUS_UIDVALIDITY | STATUS_UNSEEN | STATUS_KEYWORDS)
+
+int index_mailbox_sync_deinit(struct mailbox_sync_context *_ctx,
+                             struct mailbox_status *status_r)
+{
+       struct index_mailbox_sync_context *ctx =
+               (struct index_mailbox_sync_context *)_ctx;
+       struct index_mailbox *ibox = ctx->ibox;
+       uint32_t messages_count;
+       int ret = ctx->failed ? -1 : 0;
+
+       if (ctx->sync_ctx != NULL)
+               mail_index_view_sync_end(ctx->sync_ctx);
+
+       if (ret == 0) {
+               messages_count = mail_index_view_get_message_count(ibox->view);
+               if (messages_count != ctx->messages_count) {
+                       index_mailbox_update_recent(ibox,
+                                                   ctx->messages_count+1,
+                                                   messages_count);
+               }
+
+               if (ibox->recent_flags_count != ibox->synced_recent_count)
+                       ibox->synced_recent_count = ibox->recent_flags_count;
+
+               ret = index_storage_get_status_locked(ctx->ibox,
+                                                     SYNC_STATUS_FLAGS,
+                                                     status_r);
        }
 
-       mail_index_view_unlock(ibox->view);
+       mail_index_view_unlock(ctx->ibox->view);
+       i_free(ctx);
        return ret;
 }
index 4cb1c0e921fa3a42c8cb5fd481909aafcfb3e484..667158d2f583a6b6bf6e63585d1896521d609dc3 100644 (file)
@@ -798,22 +798,17 @@ static int maildir_storage_close(struct mailbox *box)
        return ret;
 }
 
-static void maildir_storage_auto_sync(struct mailbox *box,
-                                     enum mailbox_sync_flags flags,
-                                     unsigned int min_newmail_notify_interval)
+static void
+maildir_notify_changes(struct mailbox *box, unsigned int min_interval,
+                      mailbox_notify_callback_t *callback, void *context)
 {
        struct index_mailbox *ibox = (struct index_mailbox *)box;
 
-       ibox->min_newmail_notify_interval = min_newmail_notify_interval;
+       ibox->min_notify_interval = min_interval;
+       ibox->notify_callback = callback;
+       ibox->notify_context = context;
 
-       if ((ibox->autosync_flags == 0 && flags == 0) ||
-           (ibox->autosync_flags != 0 && flags != 0)) {
-               /* flags or interval just changed. or nothing. */
-               ibox->autosync_flags = flags;
-       }
-       ibox->autosync_flags = flags;
-
-       if (flags == 0) {
+       if (callback == NULL) {
                index_mailbox_check_remove_all(ibox);
                return;
        }
@@ -857,8 +852,10 @@ struct mailbox maildir_mailbox = {
         index_storage_allow_new_keywords,
        maildir_storage_close,
        index_storage_get_status,
-       maildir_storage_sync,
-       maildir_storage_auto_sync,
+       maildir_storage_sync_init,
+       index_mailbox_sync_next,
+       index_mailbox_sync_deinit,
+       maildir_notify_changes,
        maildir_transaction_begin,
        maildir_transaction_commit,
        maildir_transaction_rollback,
index 53f53b7c32ba1aee52efc6947f6c9d8bbe5147e2..d756e79b4431f4c5df159fbaf39902332948997b 100644 (file)
@@ -38,7 +38,8 @@ int maildir_mailbox_list_deinit(struct mailbox_list_context *ctx);
 struct mailbox_list *
 maildir_mailbox_list_next(struct mailbox_list_context *ctx);
 
-int maildir_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags);
+struct mailbox_sync_context *
+maildir_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags);
 int maildir_storage_sync_force(struct index_mailbox *ibox);
 
 struct mailbox_transaction_context *
index 33bb7589a2f5df5d59f972c369a7d6d73a11402d..845776bc01fdc45834771c4ba0f5a44081b373c2 100644 (file)
@@ -913,11 +913,12 @@ int maildir_storage_sync_force(struct index_mailbox *ibox)
        return ret;
 }
 
-int maildir_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
+struct mailbox_sync_context *
+maildir_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
 {
        struct index_mailbox *ibox = (struct index_mailbox *)box;
        struct maildir_sync_context *ctx;
-       int ret;
+       int ret = 0;
 
        if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 ||
            ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) {
@@ -926,10 +927,7 @@ int maildir_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
                ctx = maildir_sync_context_new(ibox);
                ret = maildir_sync_context(ctx, FALSE);
                maildir_sync_deinit(ctx);
-
-               if (ret < 0)
-                       return -1;
        }
 
-       return index_storage_sync(box, flags);
+       return index_mailbox_sync_init(box, flags, ret < 0);
 }
index c8a1adacddae13861b47c6e33d840b8432a4c570..0cc1cb31a912af79f350cf108fea1c3afa3143cf 100644 (file)
@@ -831,22 +831,17 @@ static int mbox_storage_close(struct mailbox *box)
        return 0;
 }
 
-static void mbox_storage_auto_sync(struct mailbox *box,
-                                  enum mailbox_sync_flags flags,
-                                  unsigned int min_newmail_notify_interval)
+static void
+mbox_notify_changes(struct mailbox *box, unsigned int min_interval,
+                   mailbox_notify_callback_t *callback, void *context)
 {
        struct index_mailbox *ibox = (struct index_mailbox *)box;
 
-       ibox->min_newmail_notify_interval = min_newmail_notify_interval;
+       ibox->min_notify_interval = min_interval;
+       ibox->notify_callback = callback;
+       ibox->notify_context = context;
 
-       if ((ibox->autosync_flags == 0 && flags == 0) ||
-           (ibox->autosync_flags != 0 && flags != 0)) {
-               /* flags or interval just changed. or nothing. */
-               ibox->autosync_flags = flags;
-       }
-       ibox->autosync_flags = flags;
-
-       if (flags == 0)
+       if (callback == NULL)
                index_mailbox_check_remove_all(ibox);
        else
                index_mailbox_check_add(ibox, ibox->path, FALSE);
@@ -885,8 +880,10 @@ struct mailbox mbox_mailbox = {
         index_storage_allow_new_keywords,
        mbox_storage_close,
        index_storage_get_status,
-       mbox_storage_sync,
-       mbox_storage_auto_sync,
+       mbox_storage_sync_init,
+       index_mailbox_sync_next,
+       index_mailbox_sync_deinit,
+       mbox_notify_changes,
        mbox_transaction_begin,
        mbox_transaction_commit,
        mbox_transaction_rollback,
index 7741ca35fc26166235b67bf2de33b325a1546014..c8ac722a252a497bf5f787ca30c0c6b429469184 100644 (file)
@@ -34,7 +34,8 @@ mbox_transaction_begin(struct mailbox *box, int hide);
 int mbox_transaction_commit(struct mailbox_transaction_context *t);
 void mbox_transaction_rollback(struct mailbox_transaction_context *t);
 
-int mbox_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags);
+struct mailbox_sync_context *
+mbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags);
 
 int mbox_save(struct mailbox_transaction_context *t,
              const struct mail_full_flags *flags,
index 25859551f829088ddf08eda888d3ff9bf43237ff..cd76b677dcd5c9b6b514704a2445ae70a3430841 100644 (file)
@@ -1320,17 +1320,18 @@ int mbox_sync(struct index_mailbox *ibox, int last_commit,
        return ret;
 }
 
-int mbox_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
+struct mailbox_sync_context *
+mbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
 {
        struct index_mailbox *ibox = (struct index_mailbox *)box;
+       int ret = 0;
 
        if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 ||
            ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) {
                ibox->sync_last_check = ioloop_time;
 
-               if (mbox_sync(ibox, FALSE, FALSE, FALSE) < 0)
-                       return -1;
+               ret = mbox_sync(ibox, FALSE, FALSE, FALSE);
        }
 
-       return index_storage_sync(box, flags);
+       return index_mailbox_sync_init(box, flags, ret < 0);
 }
index da1a5ccaafb82838f4ab72de5381f9a8eb1079d4..d34be8ff47197e5354e0c6f7ad9c2a18fc594ab4 100644 (file)
@@ -66,9 +66,17 @@ struct mailbox {
        int (*get_status)(struct mailbox *box, enum mailbox_status_items items,
                          struct mailbox_status *status);
 
-       int (*sync)(struct mailbox *box, enum mailbox_sync_flags flags);
-       void (*auto_sync)(struct mailbox *box, enum mailbox_sync_flags flags,
-                         unsigned int min_newmail_notify_interval);
+       struct mailbox_sync_context *
+               (*sync_init)(struct mailbox *box,
+                            enum mailbox_sync_flags flags);
+       int (*sync_next)(struct mailbox_sync_context *ctx,
+                        struct mailbox_sync_rec *sync_rec_r);
+       int (*sync_deinit)(struct mailbox_sync_context *ctx,
+                          struct mailbox_status *status_r);
+
+       void (*notify_changes)(struct mailbox *box, unsigned int min_interval,
+                              mailbox_notify_callback_t *callback,
+                              void *context);
 
        struct mailbox_transaction_context *
                (*transaction_begin)(struct mailbox *box, int hide);
@@ -116,6 +124,10 @@ struct mail_search_context {
        struct mailbox *box;
 };
 
+struct mailbox_sync_context {
+       struct mailbox *box;
+};
+
 /* Set error message in storage. Critical errors are logged with i_error(),
    but user sees only "internal error" message. */
 void mail_storage_clear_error(struct mail_storage *storage);
index 11b168ba2308b1f05c4f0f4f6e1fe37eef71cd3c..45fbbf899a2019db07e60b2cb69aaabcf06f94d0 100644 (file)
@@ -334,15 +334,28 @@ int mailbox_get_status(struct mailbox *box,
        return box->get_status(box, items, status);
 }
 
-int mailbox_sync(struct mailbox *box, enum mailbox_sync_flags flags)
+struct mailbox_sync_context *
+mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
 {
-       return box->sync(box, flags);
+       return box->sync_init(box, flags);
 }
 
-void mailbox_auto_sync(struct mailbox *box, enum mailbox_sync_flags flags,
-                      unsigned int min_newmail_notify_interval)
+int mailbox_sync_next(struct mailbox_sync_context *ctx,
+                     struct mailbox_sync_rec *sync_rec_r)
 {
-       box->auto_sync(box, flags, min_newmail_notify_interval);
+       return ctx->box->sync_next(ctx, sync_rec_r);
+}
+
+int mailbox_sync_deinit(struct mailbox_sync_context *ctx,
+                       struct mailbox_status *status_r)
+{
+       return ctx->box->sync_deinit(ctx, status_r);
+}
+
+void mailbox_notify_changes(struct mailbox *box, unsigned int min_interval,
+                           mailbox_notify_callback_t *callback, void *context)
+{
+       box->notify_changes(box, min_interval, callback, context);
 }
 
 struct mail *mailbox_fetch(struct mailbox_transaction_context *t, uint32_t seq,
index 1186e308ea64a897aff13056d77d611833869856..84ea4d3b1e978950f0eed268f7eb06fee4a0fe5c 100644 (file)
@@ -89,6 +89,11 @@ enum mailbox_sync_flags {
        MAILBOX_SYNC_AUTO_STOP          = 0x04
 };
 
+enum mailbox_sync_type {
+       MAILBOX_SYNC_TYPE_EXPUNGE       = 0x01,
+       MAILBOX_SYNC_TYPE_FLAGS         = 0x02
+};
+
 struct mail_storage;
 struct mail_storage_callbacks;
 struct mailbox_list;
@@ -123,6 +128,11 @@ struct mailbox_status {
        const char **keywords;
 };
 
+struct mailbox_sync_rec {
+       uint32_t seq1, seq2;
+       enum mailbox_sync_type type;
+};
+
 struct mail_storage_callbacks {
        /* Alert: Not enough disk space */
        void (*alert_no_diskspace)(struct mailbox *mailbox, void *context);
@@ -133,27 +143,10 @@ struct mail_storage_callbacks {
        void (*notify_no)(struct mailbox *mailbox, const char *text,
                          void *context);
 
-       /* EXPUNGE */
-       void (*expunge)(struct mailbox *mailbox, unsigned int seq,
-                       void *context);
-       /* FETCH FLAGS */
-       void (*update_flags)(struct mailbox *mailbox, unsigned int seq,
-                            const struct mail_full_flags *flags,
-                            void *context);
-
-       /* EXISTS */
-       void (*message_count_changed)(struct mailbox *mailbox,
-                                     unsigned int count, void *context);
-       /* RECENT */
-       void (*recent_count_changed)(struct mailbox *mailbox,
-                                    unsigned int count, void *context);
-       /* FLAGS, PERMANENTFLAGS */
-       void (*new_keywords)(struct mailbox *mailbox,
-                            const char *keywords[],
-                            unsigned int keywords_count, void *context);
-
 };
 
+typedef void mailbox_notify_callback_t(struct mailbox *box, void *context);
+
 extern int full_filesystem_access;
 
 void mail_storage_init(void);
@@ -271,12 +264,17 @@ int mailbox_get_status(struct mailbox *box,
                       struct mailbox_status *status);
 
 /* Synchronize the mailbox. */
-int mailbox_sync(struct mailbox *box, enum mailbox_sync_flags flags);
-
-/* Synchronize mailbox in background. It's done until this function is
-   called with flags = MAILBOX_SYNC_AUTO_STOP. */
-void mailbox_auto_sync(struct mailbox *box, enum mailbox_sync_flags flags,
-                      unsigned int min_newmail_notify_interval);
+struct mailbox_sync_context *
+mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags);
+int mailbox_sync_next(struct mailbox_sync_context *ctx,
+                     struct mailbox_sync_rec *sync_rec_r);
+int mailbox_sync_deinit(struct mailbox_sync_context *ctx,
+                       struct mailbox_status *status_r);
+
+/* Call given callback function when something changes in the mailbox.
+   It's done until this function is called with callback = NULL. */
+void mailbox_notify_changes(struct mailbox *box, unsigned int min_interval,
+                           mailbox_notify_callback_t *callback, void *context);
 
 struct mailbox_transaction_context *
 mailbox_transaction_begin(struct mailbox *box, int hide);
index d38e04bd94490db346208f976d0faf697908ba11..962fb1f954f6fd8e9d75186dfdf3200d89a25e6c 100644 (file)
@@ -32,19 +32,20 @@ static int _get_status(struct mailbox *box, enum mailbox_status_items items,
        return p->box->get_status(p->box, items, status);
 }
 
-static int _sync(struct mailbox *box, enum mailbox_sync_flags flags)
+static struct mailbox_sync_context *
+_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
 {
        struct proxy_mailbox *p = (struct proxy_mailbox *) box;
 
-       return p->box->sync(p->box, flags);
+       return p->box->sync_init(p->box, flags);
 }
 
-static void _auto_sync(struct mailbox *box, enum mailbox_sync_flags flags,
-                      unsigned int min_newmail_notify_interval)
+static void _notify_changes(struct mailbox *box, unsigned int min_interval,
+                           mailbox_notify_callback_t *callback, void *context)
 {
        struct proxy_mailbox *p = (struct proxy_mailbox *) box;
 
-       p->box->auto_sync(p->box, flags, min_newmail_notify_interval);
+       return p->box->notify_changes(box, min_interval, callback, context);
 }
 
 static struct mail *_fetch(struct mailbox_transaction_context *t, uint32_t seq,
@@ -150,8 +151,10 @@ void proxy_mailbox_init(struct proxy_mailbox *proxy, struct mailbox *box)
        pb->allow_new_keywords = _allow_new_keywords;
        pb->close = _close;
        pb->get_status = _get_status;
-       pb->sync = _sync;
-       pb->auto_sync = _auto_sync;
+       pb->sync_init = _sync_init;
+       pb->sync_next = box->sync_next;
+       pb->sync_deinit = box->sync_deinit;
+       pb->notify_changes = _notify_changes;
        pb->fetch = _fetch;
        pb->get_uids = _get_uids;
 
index 4f05a1ce1a34408f61c745a550d4d437f5034f0e..b28c8d2694182223e02981c77e47a797bdff4db0 100644 (file)
@@ -38,6 +38,18 @@ static void client_output_timeout(void *context)
        o_stream_close(client->output);
 }
 
+static int sync_mailbox(struct mailbox *box)
+{
+       struct mailbox_sync_context *ctx;
+        struct mailbox_sync_rec sync_rec;
+       struct mailbox_status status;
+
+       ctx = mailbox_sync_init(box, 0);
+       while (mailbox_sync_next(ctx, &sync_rec) > 0)
+               ;
+       return mailbox_sync_deinit(ctx, &status);
+}
+
 static int init_mailbox(struct client *client)
 {
        struct mail_search_arg search_arg;
@@ -51,6 +63,10 @@ static int init_mailbox(struct client *client)
        search_arg.type = SEARCH_ALL;
 
        for (i = 0; i < 2; i++) {
+               if (sync_mailbox(client->mailbox) < 0) {
+                       client_send_storage_error(client);
+                       return FALSE;
+               }
                if (mailbox_get_status(client->mailbox, STATUS_MESSAGES,
                                       &status) < 0) {
                        client_send_storage_error(client);
@@ -104,10 +120,6 @@ static int init_mailbox(struct client *client)
 
                /* well, sync and try again */
                mailbox_transaction_rollback(t);
-               if (mailbox_sync(client->mailbox, 0) < 0) {
-                       client_send_storage_error(client);
-                       return FALSE;
-               }
        }
 
        client_send_line(client, "-ERR [IN-USE] Couldn't sync mailbox.");
index 1b054843a2bdc7763cc672508ce1b5fc8e091dc0..21997604bb750a9888d26660ca6da57c5761a36b 100644 (file)
@@ -21,71 +21,8 @@ static void notify_no(struct mailbox *mailbox __attr_unused__,
 {
 }
 
-static void expunge(struct mailbox *mailbox __attr_unused__,
-                   unsigned int seq, void *context)
-{
-       struct client *client = context;
-       unsigned char *mask = client->deleted_bitmask;
-       unsigned int max, i, j;
-
-       /* external deletes - we have to fix our internal deleted array.
-          this should happen only when we're doing the expunging at quit. */
-       seq--;
-       client->messages_count--;
-
-       if (!client->deleted)
-               return;
-
-       max = client->messages_count / CHAR_BIT;
-       i = seq / CHAR_BIT; j = seq % CHAR_BIT;
-       mask[i] = (mask[i] & ((1 << j) - 1)) |
-               ((mask[i] >> (j+1)) << j) |
-               (i == max ? 0 : ((mask[i+1] & 1) << (CHAR_BIT-1)));
-
-       if (i != max) {
-               for (i++; i < max-1; i++) {
-                       mask[i] = (mask[i] >> 1) |
-                               ((mask[i+1] & 1) << (CHAR_BIT-1));
-               }
-
-               mask[i] >>= 1;
-       }
-}
-
-static void update_flags(struct mailbox *mailbox __attr_unused__,
-                        unsigned int seq __attr_unused__,
-                        const struct mail_full_flags *flags __attr_unused__,
-                        void *context __attr_unused__)
-{
-}
-
-static void message_count_changed(struct mailbox *mailbox __attr_unused__,
-                                 unsigned int count __attr_unused__,
-                                 void *context __attr_unused__)
-{
-}
-
-static void recent_count_changed(struct mailbox *mailbox __attr_unused__,
-                                unsigned int count __attr_unused__,
-                                void *context __attr_unused__)
-{
-}
-
-
-static void new_keywords(struct mailbox *mailbox __attr_unused__,
-                        const char *keywords[] __attr_unused__,
-                        unsigned int keywords_count __attr_unused__,
-                        void *context __attr_unused__)
-{
-}
-
 struct mail_storage_callbacks mail_storage_callbacks = {
        alert_no_diskspace,
        notify_ok,
-       notify_no,
-       expunge,
-       update_flags,
-       message_count_changed,
-       recent_count_changed,
-       new_keywords
+       notify_no
 };