dovecot-1.1: maildir: Fixes to handling over 26 keywords.
dovecot at dovecot.org
dovecot at dovecot.org
Wed Jan 14 18:48:27 EET 2009
details: http://hg.dovecot.org/dovecot-1.1/rev/6f6b0299b559
changeset: 8095:6f6b0299b559
user: Timo Sirainen <tss at iki.fi>
date: Wed Jan 14 11:48:20 2009 -0500
description:
maildir: Fixes to handling over 26 keywords.
diffstat:
1 file changed, 96 insertions(+), 14 deletions(-)
src/lib-storage/index/maildir/maildir-sync-index.c | 110 +++++++++++++++++---
diffs (155 lines):
diff -r 48c279fcb9e3 -r 6f6b0299b559 src/lib-storage/index/maildir/maildir-sync-index.c
--- a/src/lib-storage/index/maildir/maildir-sync-index.c Wed Jan 14 11:12:03 2009 -0500
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c Wed Jan 14 11:48:20 2009 -0500
@@ -11,6 +11,7 @@
#include "maildir-sync.h"
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
struct maildir_index_sync_context {
@@ -25,7 +26,7 @@ struct maildir_index_sync_context {
struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
struct index_sync_changes_context *sync_changes;
enum mail_flags flags;
- ARRAY_TYPE(keyword_indexes) keywords;
+ ARRAY_TYPE(keyword_indexes) keywords, idx_keywords;
uint32_t seq, uid;
@@ -274,6 +275,98 @@ int maildir_sync_index_finish(struct mai
return ret;
}
+static int uint_cmp(const void *p1, const void *p2)
+{
+ const unsigned int *i1 = p1, *i2 = p2;
+
+ if (*i1 < *i2)
+ return -1;
+ else if (*i1 > *i2)
+ return -1;
+ else
+ return 0;
+}
+
+static void
+maildir_sync_mail_keywords(struct maildir_index_sync_context *ctx, uint32_t seq)
+{
+ struct maildir_mailbox *mbox = ctx->mbox;
+ struct mail_keywords *kw;
+ unsigned int i, j, old_count, new_count, *old_indexes, *new_indexes;
+ bool have_indexonly_keywords;
+ int diff;
+
+ mail_index_lookup_keywords(ctx->view, seq, &ctx->idx_keywords);
+ if (index_keyword_array_cmp(&ctx->keywords, &ctx->idx_keywords)) {
+ /* no changes - we should get here usually */
+ return;
+ }
+
+ /* sort the keywords */
+ old_indexes = array_get_modifiable(&ctx->idx_keywords, &old_count);
+ qsort(old_indexes, old_count, sizeof(*old_indexes), uint_cmp);
+ new_indexes = array_get_modifiable(&ctx->keywords, &new_count);
+ qsort(new_indexes, new_count, sizeof(*new_indexes), uint_cmp);
+
+ /* drop keywords that are in index-only. we don't want to touch them. */
+ have_indexonly_keywords = FALSE;
+ for (i = old_count; i > 0; i--) {
+ if (old_indexes[i-1] < MAILDIR_MAX_KEYWORDS)
+ break;
+ have_indexonly_keywords = TRUE;
+ array_delete(&ctx->idx_keywords, i-1, 1);
+ }
+
+ if (!have_indexonly_keywords) {
+ /* no index-only keywords found, so something changed.
+ just replace them all. */
+ kw = mail_index_keywords_create_from_indexes(mbox->ibox.index,
+ &ctx->keywords);
+ mail_index_update_keywords(ctx->trans, seq, MODIFY_REPLACE, kw);
+ mail_index_keywords_free(&kw);
+ return;
+ }
+
+ /* check again if non-index-only keywords changed */
+ if (index_keyword_array_cmp(&ctx->keywords, &ctx->idx_keywords))
+ return;
+
+ /* we can't reset all the keywords or we'd drop indexonly keywords too.
+ so first remove the unwanted keywords and then add back the wanted
+ ones. we can get these lists easily by removing common elements
+ from old and new keywords. */
+ new_indexes = array_get_modifiable(&ctx->keywords, &new_count);
+ for (i = 0; i < old_count && j < new_count; ) {
+ diff = (int)old_indexes[i] - (int)new_indexes[j];
+ if (diff == 0) {
+ array_delete(&ctx->keywords, j, 1);
+ array_delete(&ctx->idx_keywords, i, 1);
+ old_indexes = array_get_modifiable(&ctx->idx_keywords,
+ &old_count);
+ new_indexes = array_get_modifiable(&ctx->keywords,
+ &new_count);
+ } else if (diff < 0) {
+ i++;
+ } else {
+ j++;
+ }
+ }
+
+ if (array_count(&ctx->idx_keywords) > 0) {
+ kw = mail_index_keywords_create_from_indexes(mbox->ibox.index,
+ &ctx->idx_keywords);
+ mail_index_update_keywords(ctx->trans, seq, MODIFY_REMOVE, kw);
+ mail_index_keywords_free(&kw);
+ }
+
+ if (array_count(&ctx->keywords) > 0) {
+ kw = mail_index_keywords_create_from_indexes(mbox->ibox.index,
+ &ctx->keywords);
+ mail_index_update_keywords(ctx->trans, seq, MODIFY_ADD, kw);
+ mail_index_keywords_free(&kw);
+ }
+}
+
int maildir_sync_index(struct maildir_index_sync_context *ctx,
bool partial)
{
@@ -288,7 +381,6 @@ int maildir_sync_index(struct maildir_in
uint32_t seq, seq2, uid, prev_uid;
enum maildir_uidlist_rec_flag uflags;
const char *filename;
- ARRAY_TYPE(keyword_indexes) idx_keywords;
uint32_t uid_validity, next_uid, hdr_next_uid, first_recent_uid;
uint32_t first_uid;
unsigned int changes = 0;
@@ -322,7 +414,7 @@ int maildir_sync_index(struct maildir_in
mbox->syncing_commit = TRUE;
seq = prev_uid = 0; first_recent_uid = I_MAX(hdr->first_recent_uid, 1);
t_array_init(&ctx->keywords, MAILDIR_MAX_KEYWORDS);
- t_array_init(&idx_keywords, MAILDIR_MAX_KEYWORDS);
+ t_array_init(&ctx->idx_keywords, MAILDIR_MAX_KEYWORDS);
iter = maildir_uidlist_iter_init(mbox->uidlist);
while (maildir_uidlist_iter_next(iter, &uid, &uflags, &filename)) {
maildir_filename_get_flags(ctx->keywords_sync_ctx, filename,
@@ -432,17 +524,7 @@ int maildir_sync_index(struct maildir_in
ctx->flags);
}
- /* update keywords if they have changed */
- mail_index_lookup_keywords(view, seq, &idx_keywords);
- if (!index_keyword_array_cmp(&ctx->keywords, &idx_keywords)) {
- struct mail_keywords *kw;
-
- kw = mail_index_keywords_create_from_indexes(
- mbox->ibox.index, &ctx->keywords);
- mail_index_update_keywords(trans, seq,
- MODIFY_REPLACE, kw);
- mail_index_keywords_free(&kw);
- }
+ maildir_sync_mail_keywords(ctx, seq);
}
maildir_uidlist_iter_deinit(&iter);
mbox->syncing_commit = FALSE;
More information about the dovecot-cvs
mailing list