Mercurial > dovecot > original-hg > dovecot-1.2
changeset 2053:66f5d28f9b27 HEAD
race condition fixes
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 24 May 2004 05:47:23 +0300 |
parents | 9d1ce6135d4f |
children | 02e066d4df9a |
files | src/lib-storage/index/maildir/maildir-sync.c src/lib-storage/index/maildir/maildir-uidlist.c src/lib-storage/index/maildir/maildir-uidlist.h |
diffstat | 3 files changed, 53 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-sync.c Mon May 24 05:30:10 2004 +0300 +++ b/src/lib-storage/index/maildir/maildir-sync.c Mon May 24 05:47:23 2004 +0300 @@ -629,15 +629,33 @@ if (seq > hdr->messages_count) { if (uid < hdr->next_uid) { - /* message not in index, but next_uid header - is updated? shouldn't really happen.. */ - mail_storage_set_critical(ibox->box.storage, - "Maildir sync: UID < next_uid " - "(%u < %u, file = %s)", - uid, hdr->next_uid, filename); - mail_index_mark_corrupted(ibox->index); - ret = -1; - break; + /* most likely a race condition: we read the + maildir, then someone else expunged messages + and committed changes to index. so, this + message shouldn't actually exist. mark it + racy and check in next sync. + + the difference between this and the later + check is that this one happens when messages + are expunged from the end */ + if ((uflags & + MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) { + mail_storage_set_critical( + ibox->box.storage, + "Maildir sync: UID < next_uid " + "(%u < %u, file = %s)", + uid, hdr->next_uid, filename); + mail_index_mark_corrupted(ibox->index); + ret = -1; + break; + } + ibox->dirty_cur_time = ioloop_time; + maildir_uidlist_add_flags(ibox->uidlist, + filename, + MAILDIR_UIDLIST_REC_FLAG_RACING); + + seq--; + continue; } mail_index_append(trans, uid, &seq); @@ -661,20 +679,9 @@ /* most likely a race condition: we read the maildir, then someone else expunged messages and committed changes to index. so, this message - shouldn't actually exist. check to be sure. - - FIXME: we could avoid this stat() and just mark - this check in the uidlist and check it at next - sync.. */ - struct stat st; - const char *str; - - t_push(); - str = t_strdup_printf("%s/%s", - (uflags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) ? - ctx->new_dir : ctx->cur_dir, filename); - if (stat(str, &st) == 0) { - t_pop(); + shouldn't actually exist. mark it racy and check + in next sync. */ + if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) { mail_storage_set_critical(ibox->box.storage, "Maildir sync: UID inserted in the " "middle of mailbox " @@ -683,8 +690,11 @@ mail_index_mark_corrupted(ibox->index); ret = -1; break; - } - t_pop(); + } + + ibox->dirty_cur_time = ioloop_time; + maildir_uidlist_add_flags(ibox->uidlist, filename, + MAILDIR_UIDLIST_REC_FLAG_RACING); seq--; continue;
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Mon May 24 05:30:10 2004 +0300 +++ b/src/lib-storage/index/maildir/maildir-uidlist.c Mon May 24 05:47:23 2004 +0300 @@ -848,6 +848,18 @@ return ret; } +void maildir_uidlist_add_flags(struct maildir_uidlist *uidlist, + const char *filename, + enum maildir_uidlist_rec_flag flags) +{ + struct maildir_uidlist_rec *rec; + + rec = hash_lookup(uidlist->files, filename); + i_assert(rec != NULL); + + rec->flags |= flags; +} + struct maildir_uidlist_iter_ctx * maildir_uidlist_iter_init(struct maildir_uidlist *uidlist) {
--- a/src/lib-storage/index/maildir/maildir-uidlist.h Mon May 24 05:30:10 2004 +0300 +++ b/src/lib-storage/index/maildir/maildir-uidlist.h Mon May 24 05:47:23 2004 +0300 @@ -7,7 +7,8 @@ MAILDIR_UIDLIST_REC_FLAG_NEW_DIR = 0x01, MAILDIR_UIDLIST_REC_FLAG_MOVED = 0x02, MAILDIR_UIDLIST_REC_FLAG_RECENT = 0x04, - MAILDIR_UIDLIST_REC_FLAG_NONSYNCED = 0x08 + MAILDIR_UIDLIST_REC_FLAG_NONSYNCED = 0x08, + MAILDIR_UIDLIST_REC_FLAG_RACING = 0x10 }; int maildir_uidlist_try_lock(struct maildir_uidlist *uidlist); @@ -47,6 +48,10 @@ int maildir_uidlist_sync_finish(struct maildir_uidlist_sync_ctx *ctx); int maildir_uidlist_sync_deinit(struct maildir_uidlist_sync_ctx *ctx); +void maildir_uidlist_add_flags(struct maildir_uidlist *uidlist, + const char *filename, + enum maildir_uidlist_rec_flag flags); + /* List all maildir files. */ struct maildir_uidlist_iter_ctx * maildir_uidlist_iter_init(struct maildir_uidlist *uidlist);