]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Dirty maildir flags support works now.
authorTimo Sirainen <tss@iki.fi>
Sun, 15 Jun 2003 02:20:52 +0000 (05:20 +0300)
committerTimo Sirainen <tss@iki.fi>
Sun, 15 Jun 2003 02:20:52 +0000 (05:20 +0300)
--HG--
branch : HEAD

src/lib-index/mail-index-open.c
src/lib-index/mail-index.h
src/lib-index/maildir/maildir-expunge.c
src/lib-index/maildir/maildir-index.h
src/lib-index/maildir/maildir-sync.c
src/lib-index/maildir/maildir-update-flags.c
src/lib-storage/index/maildir/maildir-storage.c

index 690e8e51e868f6a47ef1b6a372c90e27ea147154..c6b5ec33e1d720303b14fd2ac54b85ad6e622344 100644 (file)
@@ -30,6 +30,9 @@ static int mail_index_open_init(struct mail_index *index,
        index->maildir_have_new =
                (hdr->flags & MAIL_INDEX_FLAG_MAILDIR_NEW) != 0;
 
+       if ((hdr->flags & MAIL_INDEX_FLAG_DIRTY_MESSAGES) != 0)
+               index->next_dirty_flush = ioloop_time;
+
        /* update \Recent message counters */
        if ((flags & MAIL_INDEX_OPEN_FLAG_UPDATE_RECENT) != 0 &&
            hdr->last_nonrecent_uid != hdr->next_uid-1) {
index 36b5abf40eb44931db419378751a4ea2e5b987ca..33ab950db6405f33366e5053e5fe3c808b5648ca 100644 (file)
@@ -404,7 +404,7 @@ struct mail_index {
 
        /* last maildir sync: */
        time_t last_new_mtime, last_uidlist_mtime;
-       time_t maildir_cur_dirty;
+       time_t maildir_cur_dirty, next_dirty_flush;
        int maildir_lock_fd;
        pool_t new_filename_pool;
        struct hash_table *new_filenames;
@@ -458,7 +458,7 @@ struct mail_index {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-       0, 0, 0, 0
+       0, 0, 0, 0, 0
 #endif
 
 /* defaults - same as above but prefixed with mail_index_. */
index 6cdb37115bdc5cfd92614acc321fe45fde07f68d..08aa50853c244b269bb4251191b33ed67163ce85 100644 (file)
@@ -17,6 +17,12 @@ static int maildir_expunge_mail_file(struct mail_index *index,
        if (*fname == NULL)
                return -1;
 
+       /* if we're in out-of-space condition, reset it since we'll probably
+          have enough space now. */
+       index->maildir_keep_new = FALSE;
+       if (index->next_dirty_flush != 0)
+               index->next_dirty_flush = ioloop_time;
+
        if ((rec->index_flags & INDEX_MAIL_FLAG_MAILDIR_NEW) != 0) {
                /* probably in new/ dir */
                path = t_strconcat(index->mailbox_path, "/new/", *fname, NULL);
index d21c4e44f20c7c1c24465a91ea32418f45797ca3..c58b7a55ba178910a26391a876821f45031c38d1 100644 (file)
@@ -8,6 +8,9 @@
 /* ":2,DFRST" - leave the 2 extra for other clients' additions */
 #define MAILDIR_LOCATION_EXTRA_SPACE 10
 
+/* How often to try to flush dirty flags. */
+#define MAILDIR_DIRTY_FLUSH_TIMEOUT (60*5)
+
 struct mail_index *
 maildir_index_alloc(const char *maildir, const char *index_dir,
                    const char *control_dir);
@@ -35,6 +38,7 @@ int maildir_index_append_file(struct mail_index *index, const char *dir,
 int maildir_index_update_flags(struct mail_index *index,
                               struct mail_index_record *rec, unsigned int seq,
                               enum mail_flags flags, int external_change);
+int maildir_try_flush_dirty_flags(struct mail_index *index, int force);
 
 struct istream *maildir_open_mail(struct mail_index *index,
                                  struct mail_index_record *rec,
index 96e938046337327861af8c105a8284b5a2db71b9..c393e986c0096fd39211541ed50ec5508f1d5160 100644 (file)
@@ -1098,6 +1098,9 @@ static int maildir_index_sync_context(struct maildir_sync_context *ctx,
        struct stat st;
        time_t new_mtime, cur_mtime;
 
+       if (!maildir_try_flush_dirty_flags(ctx->index, FALSE))
+               return FALSE;
+
        if (index->fd != -1) {
                /* FIXME: file_sync_stamp should be in index file's headers.
                   it should also contain maildir_cur_dirty. */
index 847e2b2b2f5809f1ad4829f7d5363e8fd38b25b4..adffe48971774d168b54683168cd79d254c04b10 100644 (file)
@@ -7,6 +7,66 @@
 
 #include <stdio.h>
 
+int maildir_try_flush_dirty_flags(struct mail_index *index, int force)
+{
+       struct mail_index_record *rec;
+       const char *old_fname, *old_path, *new_fname, *new_path;
+       int flag, dirty = FALSE;
+
+       if (index->next_dirty_flush == 0 ||
+           (ioloop_time < index->next_dirty_flush && !force))
+               return TRUE;
+
+       if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
+               return FALSE;
+
+       rec = index->lookup(index, 1);
+       while (rec != NULL) {
+               if ((rec->index_flags & INDEX_MAIL_FLAG_DIRTY) != 0) {
+                       old_fname = maildir_get_location(index, rec);
+                       if (old_fname == NULL)
+                               return FALSE;
+
+                       flag = (rec->index_flags &
+                               INDEX_MAIL_FLAG_MAILDIR_NEW) != 0;
+                       old_path = t_strconcat(index->mailbox_path,
+                                              flag ? "/new/" : "/cur/",
+                                              old_fname, NULL);
+
+                       new_fname = maildir_filename_set_flags(old_fname,
+                                                              rec->msg_flags);
+                       new_path = t_strconcat(index->mailbox_path,
+                                              "/cur/", new_fname, NULL);
+
+                       if (strcmp(old_path, new_path) == 0 ||
+                           rename(old_path, new_path) == 0)
+                                rec->index_flags &= ~INDEX_MAIL_FLAG_DIRTY;
+                       else {
+                               dirty = TRUE;
+                               if (errno != ENOENT && errno != EACCES &&
+                                   !ENOSPACE(errno)) {
+                                       index_set_error(index,
+                                               "rename(%s, %s) failed: %m",
+                                               old_path, new_path);
+                                       return FALSE;
+                               }
+                       }
+               }
+
+               rec = index->next(index, rec);
+       }
+
+       if (!dirty) {
+               index->header->flags &= ~MAIL_INDEX_FLAG_DIRTY_MESSAGES;
+               index->next_dirty_flush = 0;
+       } else {
+               index->next_dirty_flush =
+                       ioloop_time + MAILDIR_DIRTY_FLUSH_TIMEOUT;
+       }
+
+       return TRUE;
+}
+
 static int handle_error(struct mail_index *index,
                        const char *path, const char *new_path)
 {
@@ -76,6 +136,8 @@ static int maildir_rename_mail(struct mail_index *index,
                                               "/cur/", new_fname, NULL);
                }
 
+               ret = 0; break;
+
                if (strcmp(old_fname, new_fname) == 0)
                        ret = 1;
                else {
@@ -117,6 +179,10 @@ static int maildir_rename_mail(struct mail_index *index,
                /* we couldn't actually rename() the file now.
                   leave it's flags dirty so they get changed later. */
                rec->index_flags |= INDEX_MAIL_FLAG_DIRTY;
+               index->header->flags |= MAIL_INDEX_FLAG_DIRTY_MESSAGES;
+               index->next_dirty_flush =
+                       ioloop_time + MAILDIR_DIRTY_FLUSH_TIMEOUT;
+               *new_fname_r = NULL;
        }
        return TRUE;
 }
@@ -127,7 +193,7 @@ int maildir_index_update_flags(struct mail_index *index,
 {
        struct mail_index_update *update;
        const char *new_fname;
-       int ret;
+       int failed = FALSE;
 
        t_push();
        if (!maildir_rename_mail(index, rec, flags, &new_fname)) {
@@ -135,18 +201,18 @@ int maildir_index_update_flags(struct mail_index *index,
                return FALSE;
        }
 
-       /* update the filename in index */
-       update = index->update_begin(index, rec);
-       index->update_field(update, DATA_FIELD_LOCATION, new_fname, 0);
-
-       if (!index->update_end(update))
-               ret = FALSE;
-       else if (!mail_index_update_flags(index, rec, seq, flags,
-                                         external_change))
-               ret = FALSE;
-       else
-               ret = TRUE;
+       if (new_fname != NULL) {
+               /* update the filename in index */
+               update = index->update_begin(index, rec);
+               index->update_field(update, DATA_FIELD_LOCATION, new_fname, 0);
+               if (!index->update_end(update))
+                       failed = TRUE;
+       }
+
+       if (!failed && !mail_index_update_flags(index, rec, seq, flags,
+                                               external_change))
+               failed = TRUE;
        t_pop();
 
-       return ret;
+       return !failed;
 }
index f935d24c36df098232a89e1cf50eb08de25112d0..2d22ef2eb3aa0531fdf5ad7bc6881c138246c8fe 100644 (file)
@@ -635,6 +635,21 @@ static int maildir_get_mailbox_name_status(struct mail_storage *storage,
        }
 }
 
+static int maildir_storage_close(struct mailbox *box)
+{
+       struct index_mailbox *ibox = (struct index_mailbox *) box;
+       int failed = FALSE;
+
+        index_storage_init_lock_notify(ibox);
+       if (!maildir_try_flush_dirty_flags(ibox->index, TRUE)) {
+               mail_storage_set_index_error(ibox);
+               failed = TRUE;
+       }
+       ibox->index->set_lock_notify_callback(ibox->index, NULL, NULL);
+
+       return index_storage_close(box) && !failed;
+}
+
 static void maildir_storage_auto_sync(struct mailbox *box,
                                      enum mailbox_sync_type sync_type,
                                      unsigned int min_newmail_notify_interval)
@@ -688,7 +703,7 @@ struct mailbox maildir_mailbox = {
        NULL, /* name */
        NULL, /* storage */
 
-       index_storage_close,
+       maildir_storage_close,
        index_storage_get_status,
        index_storage_sync,
        maildir_storage_auto_sync,