return 0;
}
-static int mail_index_sync_read_and_sort(struct mail_index_sync_ctx *ctx)
+static int mail_index_sync_add_recent_updates(struct mail_index_sync_ctx *ctx)
+{
+ struct mail_transaction_flag_update update;
+ const struct mail_index_record *rec;
+ uint32_t seq, messages_count;
+
+ memset(&update, 0, sizeof(update));
+
+ messages_count = mail_index_view_get_message_count(ctx->view);
+ for (seq = 1; seq <= messages_count; seq++) {
+ if (mail_index_lookup(ctx->view, seq, &rec) < 0)
+ return -1;
+
+ if ((rec->flags & MAIL_RECENT) == 0)
+ continue;
+
+ update.uid1 = update.uid2 = rec->uid;
+ mail_index_sync_sort_flags(ctx->updates_buf,
+ &update, sizeof(update));
+ }
+ return 0;
+}
+
+static int
+mail_index_sync_read_and_sort(struct mail_index_sync_ctx *ctx, int sync_recent)
{
size_t size;
int ret;
return -1;
}
+ if (sync_recent) {
+ if (mail_index_sync_add_recent_updates(ctx) < 0)
+ return -1;
+ }
+
while ((ret = mail_transaction_log_view_next(ctx->view->log_view,
&ctx->hdr,
&ctx->data, NULL)) > 0) {
return ret;
}
-static int mail_index_need_lock(struct mail_index *index,
+static int mail_index_need_lock(struct mail_index *index, int sync_recent,
uint32_t log_file_seq, uoff_t log_file_offset)
{
+ if (sync_recent && index->hdr->recent_messages_count > 0)
+ return 1;
+
if (index->hdr->log_file_seq > log_file_seq ||
(index->hdr->log_file_seq == log_file_seq &&
index->hdr->log_file_offset >= log_file_offset)) {
int mail_index_sync_begin(struct mail_index *index,
struct mail_index_sync_ctx **ctx_r,
struct mail_index_view **view_r,
- uint32_t log_file_seq, uoff_t log_file_offset)
+ uint32_t log_file_seq, uoff_t log_file_offset,
+ int sync_recent)
{
struct mail_index_sync_ctx *ctx;
uint32_t seq;
return -1;
}
- if (!mail_index_need_lock(index, log_file_seq, log_file_offset)) {
+ if (!mail_index_need_lock(index, sync_recent,
+ log_file_seq, log_file_offset)) {
mail_index_unlock(index, lock_id);
mail_transaction_log_sync_unlock(index->log);
return 0;
1024, (size_t)-1);
ctx->updates_buf = buffer_create_dynamic(default_pool,
1024, (size_t)-1);
- if (mail_index_sync_read_and_sort(ctx) < 0) {
+ if (mail_index_sync_read_and_sort(ctx, sync_recent) < 0) {
mail_index_sync_end(ctx);
return -1;
}
}
#define FLAG_UPDATE_IS_INTERNAL(u, empty) \
- (((u)->add_flags | (u)->remove_flags) == MAIL_INDEX_MAIL_FLAG_DIRTY && \
+ ((((u)->add_flags | (u)->remove_flags) & \
+ ~(MAIL_INDEX_MAIL_FLAG_DIRTY | MAIL_RECENT)) == 0 && \
memcmp((u)->add_keywords, empty, INDEX_KEYWORDS_BYTE_COUNT) == 0 && \
memcmp((u)->add_keywords, empty, INDEX_KEYWORDS_BYTE_COUNT) == 0)
int mail_index_sync_begin(struct mail_index *index,
struct mail_index_sync_ctx **ctx_r,
struct mail_index_view **view_r,
- uint32_t log_file_seq, uoff_t log_file_offset);
+ uint32_t log_file_seq, uoff_t log_file_offset,
+ int sync_recent);
/* Returns -1 if error, 0 if sync is finished, 1 if record was filled. */
int mail_index_sync_next(struct mail_index_sync_ctx *ctx,
struct mail_index_sync_rec *sync_rec);
ibox->syncing_commit = TRUE;
ret = mail_index_sync_begin(ibox->index, &ctx.sync_ctx, &ctx.view,
ibox->commit_log_file_seq,
- ibox->commit_log_file_offset);
+ ibox->commit_log_file_offset, FALSE);
if (ret > 0) {
ctx.trans = mail_index_transaction_begin(ctx.view, FALSE);
sync_ctx.ibox = ibox;
if (mail_index_sync_begin(ibox->index, &sync_ctx.sync_ctx, &view,
- (uint32_t)-1, (uoff_t)-1) <= 0) {
+ (uint32_t)-1, (uoff_t)-1, FALSE) <= 0) {
mail_storage_set_index_error(ibox);
return -1;
}
if (ctx->hdr_pos[MBOX_HDR_STATUS] == (size_t)-1 &&
(ctx->mail.flags & STATUS_FLAGS_MASK) != 0) {
- if (!ctx->sync_ctx->ibox->keep_recent)
- ctx->mail.flags |= MBOX_NONRECENT;
str_append(ctx->header, "Status: ");
ctx->hdr_pos[MBOX_HDR_STATUS] = str_len(ctx->header);
status_flags_append(ctx, mbox_status_flags);
ctx->mail.keywords);
}
+ /* keep our old recent flag. especially because we use it
+ negatively as non-recent */
+ ctx->mail.flags = (ctx->mail.flags & ~MAIL_RECENT) |
+ (old_flags & MAIL_RECENT);
+
if ((old_flags & STATUS_FLAGS_MASK) !=
(ctx->mail.flags & STATUS_FLAGS_MASK))
mbox_sync_update_status(ctx);
if (!sync_ctx->ibox->keep_recent) {
/* need to add 'O' flag to Status-header */
mail_ctx->need_rewrite = TRUE;
+ mail_ctx->mail.flags |= MBOX_NONRECENT;
}
index_mailbox_set_recent(sync_ctx->ibox,
mail_ctx->seq - mail_ctx->pseudo);
&idx_flags, idx_keywords);
mbox_flags = (rec->flags & ~MAIL_FLAGS_MASK) |
- (mail->flags & (MAIL_FLAGS_MASK^MAIL_RECENT));
+ (mail->flags & MAIL_FLAGS_MASK);
+ mbox_flags ^= MAIL_RECENT;
- if (!sync_ctx->ibox->keep_recent)
- mbox_flags &= ~MAIL_RECENT;
-
- if (idx_flags != mbox_flags ||
+ if ((idx_flags & ~MAIL_RECENT) != (mbox_flags & ~MAIL_RECENT) ||
memcmp(idx_keywords, mail->keywords,
INDEX_KEYWORDS_BYTE_COUNT) != 0) {
mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
MODIFY_REPLACE, mbox_flags,
mail->keywords);
+ } else if (((idx_flags ^ mbox_flags) & MAIL_RECENT) != 0) {
+ /* drop recent flag */
+ memset(idx_keywords, 0, INDEX_KEYWORDS_BYTE_COUNT);
+ mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
+ MODIFY_REMOVE, MAIL_RECENT,
+ idx_keywords);
}
}
uint32_t seq;
uoff_t offset;
unsigned int lock_id = 0;
- int ret, lock_type;
+ int ret, changed, lock_type;
if (lock) {
if (mbox_lock(ibox, F_RDLCK, &lock_id) <= 0)
}
if (sync_header)
- ret = 0;
+ changed = 0;
else {
- if ((ret = mbox_sync_has_changed(ibox)) < 0) {
+ if ((changed = mbox_sync_has_changed(ibox)) < 0) {
if (lock)
(void)mbox_unlock(ibox, lock_id);
return -1;
}
}
- if (ret == 0 && !last_commit)
- return 0;
-
if (last_commit) {
seq = ibox->commit_log_file_seq;
offset = ibox->commit_log_file_offset;
}
ret = mail_index_sync_begin(ibox->index, &index_sync_ctx, &sync_view,
- seq, offset);
+ seq, offset, !ibox->keep_recent);
if (ret <= 0) {
if (ret < 0)
mail_storage_set_index_error(ibox);
return ret;
}
+ if (!changed && !mail_index_sync_have_more(index_sync_ctx)) {
+ if (mail_index_sync_end(index_sync_ctx) < 0) {
+ mail_storage_set_index_error(ibox);
+ return -1;
+ }
+ return 0;
+ }
+
memset(&sync_ctx, 0, sizeof(sync_ctx));
sync_ctx.ibox = ibox;
sync_ctx.from_line = str_new(default_pool, 256);
ret = mail_index_sync_begin(ibox->index,
&sync_ctx.index_sync_ctx,
&sync_ctx.sync_view,
- (uint32_t)-1, (uoff_t)-1);
+ (uint32_t)-1, (uoff_t)-1, FALSE);
if (ret < 0)
mail_storage_set_index_error(ibox);
else {