dovecot-2.2: lib-storage: Fixes to handling private message flag...
dovecot at dovecot.org
dovecot at dovecot.org
Tue Jul 31 19:32:19 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/c3a781ef0aeb
changeset: 14738:c3a781ef0aeb
user: Timo Sirainen <tss at iki.fi>
date: Tue Jul 31 19:32:03 2012 +0300
description:
lib-storage: Fixes to handling private message flag indexes.
diffstat:
src/lib-storage/index/index-search.c | 56 ++++++++++------------
src/lib-storage/index/index-status.c | 81 ++++++++++++++++++++++++++++-----
src/lib-storage/index/index-sync-pvt.c | 9 +++
src/lib-storage/index/index-sync.c | 7 +-
4 files changed, 107 insertions(+), 46 deletions(-)
diffs (282 lines):
diff -r 1af9d08e67d7 -r c3a781ef0aeb src/lib-storage/index/index-search.c
--- a/src/lib-storage/index/index-search.c Tue Jul 31 02:46:21 2012 +0300
+++ b/src/lib-storage/index/index-search.c Tue Jul 31 19:32:03 2012 +0300
@@ -151,10 +151,7 @@
static bool
index_search_get_pvt(struct index_search_context *ctx, uint32_t uid)
{
- if (ctx->box->view_pvt == NULL) {
- /* no private view (set by view syncing) -> no private flags */
- return FALSE;
- }
+ index_transaction_init_pvt(ctx->mail_ctx.transaction);
if (ctx->pvt_uid == uid)
return ctx->pvt_seq != 0;
@@ -183,12 +180,17 @@
if ((arg->value.flags & MAIL_RECENT) != 0 &&
index_mailbox_is_recent(ctx->box, rec->uid))
flags |= MAIL_RECENT;
- if (index_search_get_pvt(ctx, rec->uid)) {
+ if (ctx->box->view_pvt == NULL) {
+ /* no private view (set by view syncing) ->
+ no private flags */
+ } else {
pvt_flags_mask = mailbox_get_private_flags_mask(ctx->box);
flags &= ~pvt_flags_mask;
- rec = mail_index_lookup(ctx->mail_ctx.transaction->view_pvt,
- ctx->pvt_seq);
- flags |= rec->flags & pvt_flags_mask;
+ if (index_search_get_pvt(ctx, rec->uid)) {
+ rec = mail_index_lookup(ctx->mail_ctx.transaction->view_pvt,
+ ctx->pvt_seq);
+ flags |= rec->flags & pvt_flags_mask;
+ }
}
return (flags & arg->value.flags) == arg->value.flags;
case SEARCH_KEYWORDS:
@@ -892,20 +894,14 @@
struct mail_search_arg *args,
uint32_t *seq1, uint32_t *seq2)
{
- const struct mail_index_header *hdr_seen, *hdr_del, *hdr_pvt;
+ const struct mail_index_header *hdr;
enum mail_flags pvt_flags_mask;
- hdr_seen = hdr_del = mail_index_get_header(ctx->view);
-
- if (ctx->box->view_pvt != NULL) {
- pvt_flags_mask = mailbox_get_private_flags_mask(ctx->box);
- index_transaction_init_pvt(ctx->mail_ctx.transaction);
- hdr_pvt = mail_index_get_header(ctx->mail_ctx.transaction->view_pvt);
- if ((pvt_flags_mask & MAIL_SEEN) != 0)
- hdr_seen = hdr_pvt;
- if ((pvt_flags_mask & MAIL_DELETED) != 0)
- hdr_del = hdr_pvt;
- }
+ hdr = mail_index_get_header(ctx->view);
+ /* we can't trust that private view's header is fully up to date,
+ so do this optimization only for non-private flags */
+ pvt_flags_mask = ctx->box->view_pvt == NULL ? 0 :
+ mailbox_get_private_flags_mask(ctx->box);
for (; args != NULL; args = args->next) {
if (args->type != SEARCH_FLAGS) {
@@ -915,13 +911,13 @@
}
continue;
}
- if ((args->value.flags & MAIL_SEEN) != 0) {
+ if ((args->value.flags & MAIL_SEEN) != 0 &&
+ (pvt_flags_mask & MAIL_SEEN) == 0) {
/* SEEN with 0 seen? */
- if (!args->match_not && hdr_seen->seen_messages_count == 0)
+ if (!args->match_not && hdr->seen_messages_count == 0)
return FALSE;
- if (hdr_seen->seen_messages_count ==
- hdr_seen->messages_count) {
+ if (hdr->seen_messages_count == hdr->messages_count) {
/* UNSEEN with all seen? */
if (args->match_not)
return FALSE;
@@ -931,17 +927,17 @@
} else if (args->match_not) {
/* UNSEEN with lowwater limiting */
search_limit_lowwater(ctx,
- hdr_seen->first_unseen_uid_lowwater, seq1);
+ hdr->first_unseen_uid_lowwater, seq1);
}
}
- if ((args->value.flags & MAIL_DELETED) != 0) {
+ if ((args->value.flags & MAIL_DELETED) != 0 &&
+ (pvt_flags_mask & MAIL_DELETED) == 0) {
/* DELETED with 0 deleted? */
if (!args->match_not &&
- hdr_del->deleted_messages_count == 0)
+ hdr->deleted_messages_count == 0)
return FALSE;
- if (hdr_del->deleted_messages_count ==
- hdr_del->messages_count) {
+ if (hdr->deleted_messages_count == hdr->messages_count) {
/* UNDELETED with all deleted? */
if (args->match_not)
return FALSE;
@@ -951,7 +947,7 @@
} else if (!args->match_not) {
/* DELETED with lowwater limiting */
search_limit_lowwater(ctx,
- hdr_del->first_deleted_uid_lowwater, seq1);
+ hdr->first_deleted_uid_lowwater, seq1);
}
}
}
diff -r 1af9d08e67d7 -r c3a781ef0aeb src/lib-storage/index/index-status.c
--- a/src/lib-storage/index/index-status.c Tue Jul 31 02:46:21 2012 +0300
+++ b/src/lib-storage/index/index-status.c Tue Jul 31 19:32:03 2012 +0300
@@ -43,18 +43,72 @@
return 0;
}
+static unsigned int index_storage_count_pvt_unseen(struct mailbox *box)
+{
+ const struct mail_index_record *pvt_rec;
+ uint32_t shared_seq, pvt_seq, shared_count, pvt_count;
+ uint32_t shared_uid;
+ unsigned int unseen_count = 0;
+
+ /* we can't trust private index to be up to date. we'll need to go
+ through the shared index and for each existing mail lookup its
+ private flags. if a mail doesn't exist in private index then its
+ flags are 0. */
+ shared_count = mail_index_view_get_messages_count(box->view);
+ pvt_count = mail_index_view_get_messages_count(box->view_pvt);
+ shared_seq = pvt_seq = 1;
+ while (shared_seq <= shared_count && pvt_seq <= pvt_count) {
+ mail_index_lookup_uid(box->view, shared_seq, &shared_uid);
+ pvt_rec = mail_index_lookup(box->view_pvt, pvt_seq);
+
+ if (shared_uid == pvt_rec->uid) {
+ if ((pvt_rec->flags & MAIL_SEEN) == 0)
+ unseen_count++;
+ shared_seq++; pvt_seq++;
+ } else if (shared_uid < pvt_rec->uid) {
+ shared_seq++;
+ } else {
+ pvt_seq++;
+ }
+ }
+ unseen_count += (shared_count+1) - shared_seq;
+ return unseen_count;
+}
+
+static uint32_t index_storage_find_first_pvt_unseen_seq(struct mailbox *box)
+{
+ const struct mail_index_header *pvt_hdr;
+ const struct mail_index_record *pvt_rec;
+ uint32_t pvt_seq, pvt_count, shared_seq, seq2;
+
+ pvt_count = mail_index_view_get_messages_count(box->view_pvt);
+ mail_index_lookup_first(box->view_pvt, 0, MAIL_SEEN, &pvt_seq);
+ for (; pvt_seq <= pvt_count; pvt_seq++) {
+ pvt_rec = mail_index_lookup(box->view_pvt, pvt_seq);
+ if ((pvt_rec->flags & MAIL_SEEN) == 0 &&
+ mail_index_lookup_seq(box->view, pvt_rec->uid, &shared_seq))
+ return shared_seq;
+ }
+ /* if shared index has any messages that don't exist in private index,
+ the first of them is the first unseen message */
+ pvt_hdr = mail_index_get_header(box->view_pvt);
+ if (mail_index_lookup_seq_range(box->view,
+ pvt_hdr->next_uid, (uint32_t)-1,
+ &shared_seq, &seq2))
+ return shared_seq;
+ return 0;
+}
+
void index_storage_get_open_status(struct mailbox *box,
enum mailbox_status_items items,
struct mailbox_status *status_r)
{
- const struct mail_index_header *hdr, *hdr_pvt;
+ const struct mail_index_header *hdr;
memset(status_r, 0, sizeof(struct mailbox_status));
/* we can get most of the status items without any trouble */
hdr = mail_index_get_header(box->view);
- hdr_pvt = box->view_pvt == NULL ? NULL :
- mail_index_get_header(box->view_pvt);
status_r->messages = hdr->messages_count;
if ((items & STATUS_RECENT) != 0) {
/* make sure recent count is set, in case syncing hasn't
@@ -63,13 +117,14 @@
status_r->recent = index_mailbox_get_recent_count(box);
i_assert(status_r->recent <= status_r->messages);
}
- if (hdr_pvt == NULL ||
- (mailbox_get_private_flags_mask(box) & MAIL_SEEN) == 0) {
- status_r->unseen = hdr->messages_count -
- hdr->seen_messages_count;
- } else {
- status_r->unseen = hdr_pvt->messages_count -
- hdr_pvt->seen_messages_count;
+ if ((items & STATUS_UNSEEN) != 0) {
+ if (box->view_pvt == NULL ||
+ (mailbox_get_private_flags_mask(box) & MAIL_SEEN) == 0) {
+ status_r->unseen = hdr->messages_count -
+ hdr->seen_messages_count;
+ } else {
+ status_r->unseen = index_storage_count_pvt_unseen(box);
+ }
}
status_r->uidvalidity = hdr->uid_validity;
status_r->uidnext = hdr->next_uid;
@@ -87,13 +142,13 @@
}
if ((items & STATUS_FIRST_UNSEEN_SEQ) != 0) {
- if (hdr_pvt == NULL ||
+ if (box->view_pvt == NULL ||
(mailbox_get_private_flags_mask(box) & MAIL_SEEN) == 0) {
mail_index_lookup_first(box->view, 0, MAIL_SEEN,
&status_r->first_unseen_seq);
} else {
- mail_index_lookup_first(box->view_pvt, 0, MAIL_SEEN,
- &status_r->first_unseen_seq);
+ status_r->first_unseen_seq =
+ index_storage_find_first_pvt_unseen_seq(box);
}
}
if ((items & STATUS_LAST_CACHED_SEQ) != 0)
diff -r 1af9d08e67d7 -r c3a781ef0aeb src/lib-storage/index/index-sync-pvt.c
--- a/src/lib-storage/index/index-sync-pvt.c Tue Jul 31 02:46:21 2012 +0300
+++ b/src/lib-storage/index/index-sync-pvt.c Tue Jul 31 19:32:03 2012 +0300
@@ -178,6 +178,7 @@
seq_shared = 1;
}
+ uid = 0;
for (; seq_shared <= count_shared; seq_shared++) {
mail_index_lookup_uid(view_shared, seq_shared, &uid);
mail_index_append(trans_pvt, uid, &seq_pvt);
@@ -189,6 +190,14 @@
seq_old_pvt, seq_pvt);
}
}
+
+ if (uid < hdr_shared->next_uid) {
+ mail_index_update_header(trans_pvt,
+ offsetof(struct mail_index_header, next_uid),
+ &hdr_shared->next_uid,
+ sizeof(hdr_shared->next_uid), FALSE);
+ }
+
if ((ret = mail_index_sync_commit(&sync_ctx)) < 0)
mail_storage_set_index_error(box);
mail_index_view_close(&view_shared);
diff -r 1af9d08e67d7 -r c3a781ef0aeb src/lib-storage/index/index-sync.c
--- a/src/lib-storage/index/index-sync.c Tue Jul 31 02:46:21 2012 +0300
+++ b/src/lib-storage/index/index-sync.c Tue Jul 31 19:32:03 2012 +0300
@@ -189,9 +189,6 @@
return &ctx->ctx;
}
- /* sync private index if needed */
- (void)index_storage_mailbox_sync_pvt(box);
-
if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) != 0)
sync_flags |= MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES;
@@ -394,6 +391,10 @@
if (array_is_created(&ctx->all_flag_update_uids))
array_free(&ctx->all_flag_update_uids);
+ /* sync private index if needed. do this last to make sure that all
+ the new messages are added to the private index, so their flags can
+ be updated. */
+ (void)index_storage_mailbox_sync_pvt(_ctx->box);
i_free(ctx);
return ret;
}
More information about the dovecot-cvs
mailing list