From: Timo Sirainen Date: Sat, 22 May 2004 22:23:29 +0000 (+0300) Subject: Recent flag fixes. Should work perfectly now with maildir. X-Git-Tag: 1.1.alpha1~4068 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d482b35af87f5fd872bad007da0475813a401a49;p=thirdparty%2Fdovecot%2Fcore.git Recent flag fixes. Should work perfectly now with maildir. --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-index-fsck.c b/src/lib-index/mail-index-fsck.c index 04f6c3400f..ebcbda4496 100644 --- a/src/lib-index/mail-index-fsck.c +++ b/src/lib-index/mail-index-fsck.c @@ -41,6 +41,7 @@ static int mail_index_fsck_locked(struct mail_index *index, } hdr.messages_count = 0; + hdr.recent_messages_count = 0; hdr.seen_messages_count = 0; hdr.deleted_messages_count = 0; @@ -56,6 +57,8 @@ static int mail_index_fsck_locked(struct mail_index *index, } hdr.messages_count++; + if ((rec->flags & MAIL_RECENT) != 0) + hdr.recent_messages_count++; if ((rec->flags & MAIL_SEEN) != 0) hdr.seen_messages_count++; if ((rec->flags & MAIL_DELETED) != 0) @@ -88,6 +91,7 @@ static int mail_index_fsck_locked(struct mail_index *index, hdr.first_deleted_uid_lowwater = hdr.next_uid; CHECK(messages_count, !=); + CHECK(recent_messages_count, !=); CHECK(seen_messages_count, !=); CHECK(deleted_messages_count, !=); diff --git a/src/lib-index/mail-index-sync-update.c b/src/lib-index/mail-index-sync-update.c index c46f038e6b..706e33a75d 100644 --- a/src/lib-index/mail-index-sync-update.c +++ b/src/lib-index/mail-index-sync-update.c @@ -20,20 +20,28 @@ struct mail_index_update_ctx { void mail_index_header_update_counts(struct mail_index_header *hdr, uint8_t old_flags, uint8_t new_flags) { + if (((old_flags ^ new_flags) & MAIL_RECENT) != 0) { + /* different recent-flag */ + if ((old_flags & MAIL_RECENT) == 0) + hdr->recent_messages_count++; + else if (--hdr->recent_messages_count == 0) + hdr->first_recent_uid_lowwater = hdr->next_uid; + } + if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) { /* different seen-flag */ - if ((old_flags & MAIL_SEEN) == 0) - hdr->seen_messages_count++; - else + if ((old_flags & MAIL_SEEN) != 0) hdr->seen_messages_count--; + else if (++hdr->seen_messages_count == hdr->messages_count) + hdr->first_unseen_uid_lowwater = hdr->next_uid; } if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) { /* different deleted-flag */ if ((old_flags & MAIL_DELETED) == 0) hdr->deleted_messages_count++; - else - hdr->deleted_messages_count--; + else if (--hdr->deleted_messages_count == 0) + hdr->first_deleted_uid_lowwater = hdr->next_uid; } } diff --git a/src/lib-index/mail-index.c b/src/lib-index/mail-index.c index 0ae31dcfa6..f9b6fb504e 100644 --- a/src/lib-index/mail-index.c +++ b/src/lib-index/mail-index.c @@ -77,7 +77,8 @@ static int mail_index_check_header(struct mail_index *index, if (hdr->next_uid == 0) return 0; - if (hdr->seen_messages_count > hdr->messages_count || + if (hdr->recent_messages_count > hdr->messages_count || + hdr->seen_messages_count > hdr->messages_count || hdr->deleted_messages_count > hdr->messages_count) return 0; if (hdr->first_recent_uid_lowwater > hdr->next_uid || diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h index 5faf316f68..3f91bb052a 100644 --- a/src/lib-index/mail-index.h +++ b/src/lib-index/mail-index.h @@ -6,7 +6,7 @@ #define MAIL_INDEX_MAJOR_VERSION 4 #define MAIL_INDEX_MINOR_VERSION 0 -#define MAIL_INDEX_HEADER_MIN_SIZE 68 +#define MAIL_INDEX_HEADER_MIN_SIZE 72 /* Number of keywords in mail_index_record. */ #define INDEX_KEYWORDS_COUNT (3*8) @@ -77,6 +77,7 @@ struct mail_index_header { uint32_t next_uid; uint32_t messages_count; + uint32_t recent_messages_count; uint32_t seen_messages_count; uint32_t deleted_messages_count; diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c index 6708cb788b..101de3604e 100644 --- a/src/lib-storage/index/index-mail.c +++ b/src/lib-storage/index/index-mail.c @@ -169,7 +169,7 @@ const struct mail_full_flags *index_mail_get_flags(struct mail *_mail) struct index_mail *mail = (struct index_mail *) _mail; struct index_mail_data *data = &mail->data; - data->flags.flags = data->rec->flags; + data->flags.flags = data->rec->flags & MAIL_FLAGS_MASK; /*FIXME:data->flags.keywords = mail_keywords_list_get(mail->ibox->index->keywords); data->flags.keywords_count = MAIL_KEYWORDS_COUNT;*/ @@ -641,8 +641,7 @@ int index_mail_update_flags(struct mail *mail, enum mail_flags modify_flags; keywords_mask_t keywords; - /* \Recent can't be changed */ - modify_flags = flags->flags & ~MAIL_RECENT; + modify_flags = flags->flags & MAIL_FLAGS_MASK; /*if (!index_mailbox_fix_keywords(ibox, &modify_flags, flags->keywords, diff --git a/src/lib-storage/index/maildir/maildir-sync.c b/src/lib-storage/index/maildir/maildir-sync.c index e9e24c9564..54c53dba9a 100644 --- a/src/lib-storage/index/maildir/maildir-sync.c +++ b/src/lib-storage/index/maildir/maildir-sync.c @@ -442,6 +442,8 @@ static int maildir_scan_dir(struct maildir_sync_context *ctx, int new_dir) ret = maildir_uidlist_sync_next_pre(ctx->uidlist_sync_ctx, dp->d_name); if (ret == 0) { + /* new file and we couldn't lock uidlist, check this + later in next sync. */ if (new_dir) ctx->ibox->last_new_mtime = 0; else @@ -596,6 +598,13 @@ static int maildir_sync_index(struct maildir_sync_context *ctx) while (maildir_uidlist_iter_next(iter, &uid, &uflags, &filename)) { maildir_filename_get_flags(filename, &flags, keywords); + if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0 && + (uflags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0 && + (uflags & MAILDIR_UIDLIST_REC_FLAG_MOVED) == 0) { + /* mail is recent for next session as well */ + flags |= MAIL_RECENT; + } + __again: seq++; if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) { @@ -673,14 +682,21 @@ static int maildir_sync_index(struct maildir_sync_context *ctx) continue; } - maildir_filename_get_flags(filename, &flags, keywords); - if ((uint8_t)flags != (rec->flags & MAIL_FLAGS_MASK) || + if (((uint8_t)flags & ~MAIL_RECENT) != + (rec->flags & (MAIL_FLAGS_MASK^MAIL_RECENT)) || memcmp(keywords, rec->keywords, INDEX_KEYWORDS_BYTE_COUNT) != 0) { - /* FIXME: this is wrong if there's syncs later. - it gets fixed in next sync however.. */ + /* FIXME: this is wrong if there's pending changes in + transaction log already. it gets fixed in next sync + however.. */ mail_index_update_flags(trans, seq, MODIFY_REPLACE, flags, keywords); + } else if ((flags & MAIL_RECENT) == 0 && + (rec->flags & MAIL_RECENT) != 0) { + /* just remove recent flag */ + memset(keywords, 0, sizeof(keywords)); + mail_index_update_flags(trans, seq, MODIFY_REMOVE, + MAIL_RECENT, keywords); } } maildir_uidlist_iter_deinit(iter); diff --git a/src/lib-storage/index/maildir/maildir-uidlist.c b/src/lib-storage/index/maildir/maildir-uidlist.c index 0d57f05daa..bfd21e6892 100644 --- a/src/lib-storage/index/maildir/maildir-uidlist.c +++ b/src/lib-storage/index/maildir/maildir-uidlist.c @@ -44,6 +44,7 @@ struct maildir_uidlist { uint32_t first_recent_uid; unsigned int initial_read:1; + unsigned int initial_sync:1; }; struct maildir_uidlist_sync_ctx { @@ -389,6 +390,18 @@ uint32_t maildir_uidlist_get_recent_count(struct maildir_uidlist *uidlist) size_t size; uint32_t count; + if (!uidlist->initial_sync) { + /* we haven't synced yet, trust index */ + const struct mail_index_header *hdr; + + if (mail_index_get_header(uidlist->ibox->view, &hdr) < 0) + return 0; + return hdr->recent_messages_count; + } + + /* all recent messages were in new/ dir, so even if we did only + a partial sync we should know all the recent messages. */ + if (uidlist->first_recent_uid == 0) return 0; @@ -606,6 +619,10 @@ maildir_uidlist_sync_next_partial(struct maildir_uidlist_sync_ctx *ctx, buffer_append(uidlist->record_buf, &rec, sizeof(rec)); } + if ((flags & MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0 && + rec->uid != (uint32_t)-1) + maildir_uidlist_mark_recent(uidlist, rec->uid); + rec->flags = (rec->flags | flags) & ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED; rec->filename = p_strdup(uidlist->record_pool, filename); hash_insert(uidlist->files, rec->filename, rec); @@ -777,6 +794,7 @@ int maildir_uidlist_sync_finish(struct maildir_uidlist_sync_ctx *ctx) } } ctx->finished = TRUE; + ctx->uidlist->initial_sync = TRUE; return !ctx->locked; }