}
hdr.messages_count = 0;
+ hdr.recent_messages_count = 0;
hdr.seen_messages_count = 0;
hdr.deleted_messages_count = 0;
}
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)
hdr.first_deleted_uid_lowwater = hdr.next_uid;
CHECK(messages_count, !=);
+ CHECK(recent_messages_count, !=);
CHECK(seen_messages_count, !=);
CHECK(deleted_messages_count, !=);
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;
}
}
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 ||
#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)
uint32_t next_uid;
uint32_t messages_count;
+ uint32_t recent_messages_count;
uint32_t seen_messages_count;
uint32_t deleted_messages_count;
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;*/
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,
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
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) {
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);
uint32_t first_recent_uid;
unsigned int initial_read:1;
+ unsigned int initial_sync:1;
};
struct maildir_uidlist_sync_ctx {
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;
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);
}
}
ctx->finished = TRUE;
+ ctx->uidlist->initial_sync = TRUE;
return !ctx->locked;
}