From: Timo Sirainen Date: Sun, 15 Jun 2003 02:20:52 +0000 (+0300) Subject: Dirty maildir flags support works now. X-Git-Tag: 1.1.alpha1~4556 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=406a92a344f789e6ec763104b03de3f0b8fcfdb7;p=thirdparty%2Fdovecot%2Fcore.git Dirty maildir flags support works now. --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-index-open.c b/src/lib-index/mail-index-open.c index 690e8e51e8..c6b5ec33e1 100644 --- a/src/lib-index/mail-index-open.c +++ b/src/lib-index/mail-index-open.c @@ -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) { diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h index 36b5abf40e..33ab950db6 100644 --- a/src/lib-index/mail-index.h +++ b/src/lib-index/mail-index.h @@ -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_. */ diff --git a/src/lib-index/maildir/maildir-expunge.c b/src/lib-index/maildir/maildir-expunge.c index 6cdb37115b..08aa50853c 100644 --- a/src/lib-index/maildir/maildir-expunge.c +++ b/src/lib-index/maildir/maildir-expunge.c @@ -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); diff --git a/src/lib-index/maildir/maildir-index.h b/src/lib-index/maildir/maildir-index.h index d21c4e44f2..c58b7a55ba 100644 --- a/src/lib-index/maildir/maildir-index.h +++ b/src/lib-index/maildir/maildir-index.h @@ -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, diff --git a/src/lib-index/maildir/maildir-sync.c b/src/lib-index/maildir/maildir-sync.c index 96e9380463..c393e986c0 100644 --- a/src/lib-index/maildir/maildir-sync.c +++ b/src/lib-index/maildir/maildir-sync.c @@ -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. */ diff --git a/src/lib-index/maildir/maildir-update-flags.c b/src/lib-index/maildir/maildir-update-flags.c index 847e2b2b2f..adffe48971 100644 --- a/src/lib-index/maildir/maildir-update-flags.c +++ b/src/lib-index/maildir/maildir-update-flags.c @@ -7,6 +7,66 @@ #include +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; } diff --git a/src/lib-storage/index/maildir/maildir-storage.c b/src/lib-storage/index/maildir/maildir-storage.c index f935d24c36..2d22ef2eb3 100644 --- a/src/lib-storage/index/maildir/maildir-storage.c +++ b/src/lib-storage/index/maildir/maildir-storage.c @@ -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,