dovecot: Fixed mailbox list indexes to work properly with subscr...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Jul 18 03:53:10 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/ca0770f7b1a8
changeset: 6059:ca0770f7b1a8
user: Timo Sirainen <tss at iki.fi>
date: Wed Jul 18 03:53:02 2007 +0300
description:
Fixed mailbox list indexes to work properly with subscriptions
diffstat:
2 files changed, 124 insertions(+), 60 deletions(-)
src/lib-storage/list/index-mailbox-list.c | 181 +++++++++++++++++++----------
src/lib-storage/list/index-mailbox-list.h | 3
diffs (275 lines):
diff -r 07d08be5bbb8 -r ca0770f7b1a8 src/lib-storage/list/index-mailbox-list.c
--- a/src/lib-storage/list/index-mailbox-list.c Wed Jul 18 03:15:53 2007 +0300
+++ b/src/lib-storage/list/index-mailbox-list.c Wed Jul 18 03:53:02 2007 +0300
@@ -8,6 +8,7 @@
#include "mail-index.h"
#include "mail-storage.h"
#include "mailbox-tree.h"
+#include "mailbox-list-subscriptions.h"
#include "mailbox-list-index.h"
#include "index-mailbox-list.h"
@@ -203,7 +204,7 @@ index_mailbox_list_iter_init(struct mail
struct index_mailbox_list_iterate_context *ctx;
const char *prefix, *cur_prefix, *const *tmp;
enum mailbox_list_iter_flags subs_flags;
- int cur_recurse_level;
+ int ret, cur_recurse_level;
ctx = i_new(struct index_mailbox_list_iterate_context, 1);
ctx->ctx.list = list;
@@ -222,6 +223,19 @@ index_mailbox_list_iter_init(struct mail
ctx->glob = imap_match_init_multiple(default_pool, patterns, TRUE,
list->hierarchy_sep);
+ if ((flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
+ MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0) {
+ /* we'll need to know the subscriptions */
+ ctx->subs_tree = mailbox_tree_init(list->hierarchy_sep);
+ if (mailbox_list_subscriptions_fill(&ctx->ctx, ctx->subs_tree,
+ ctx->glob, FALSE) < 0) {
+ /* let the backend handle this failure */
+ ctx->backend_ctx = ilist->module_ctx.super.
+ iter_init(list, patterns, flags);
+ return &ctx->ctx;
+ }
+ }
+
ctx->mail_view = mail_index_view_open(ilist->mail_index);
ctx->view = mailbox_list_index_view_init(ilist->list_index,
ctx->mail_view);
@@ -240,49 +254,77 @@ index_mailbox_list_iter_init(struct mail
prefix = "";
if (!index_mailbox_list_is_synced(ctx) > 0) {
- if (index_mailbox_list_sync(ctx) < 0) {
+ ret = index_mailbox_list_sync(ctx);
+
+ mail_index_view_close(&ctx->mail_view);
+ mailbox_list_index_view_deinit(&ctx->view);
+
+ if (ret < 0) {
ctx->backend_ctx = ilist->module_ctx.super.
iter_init(list, patterns, flags);
return &ctx->ctx;
}
+
/* updated, we'll have to reopen views */
- mail_index_view_close(&ctx->mail_view);
- mailbox_list_index_view_deinit(&ctx->view);
-
ctx->mail_view = mail_index_view_open(ilist->mail_index);
ctx->view = mailbox_list_index_view_init(ilist->list_index,
ctx->mail_view);
}
- /* list from index */
if (ctx->info_pool == NULL) {
ctx->info_pool =
pool_alloconly_create("mailbox name pool", 128);
}
- ctx->iter_ctx =
- mailbox_list_index_iterate_init(ctx->view, prefix,
- ctx->recurse_level);
- ctx->prefix = *prefix == '\0' ? i_strdup("") :
- i_strdup_printf("%s%c", prefix, list->hierarchy_sep);
+
+ if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
+ ctx->subs_iter =
+ mailbox_tree_iterate_init(ctx->subs_tree,
+ NULL, MAILBOX_MATCHED);
+ } else {
+ /* list from index */
+ ctx->iter_ctx =
+ mailbox_list_index_iterate_init(ctx->view, prefix,
+ ctx->recurse_level);
+ ctx->prefix = *prefix == '\0' ? i_strdup("") :
+ i_strdup_printf("%s%c", prefix, list->hierarchy_sep);
+ }
return &ctx->ctx;
}
-/* skip nonexistent mailboxes when finding with "*" */
-#define info_flags_match(ctx, info) \
- (((info)->flags & MAILBOX_NONEXISTENT) == 0 || \
- (ctx)->recurse_level >= 0)
-
-static int iter_next_nonsync(struct index_mailbox_list_iterate_context *ctx,
- const struct mailbox_info **info_r)
+static int
+list_index_get_info_flags(struct index_mailbox_list_iterate_context *ctx,
+ uint32_t uid, enum mailbox_info_flags *flags_r)
+{
+ struct index_mailbox_list *ilist = INDEX_LIST_CONTEXT(ctx->ctx.list);
+ const struct mail_index_record *rec;
+ uint32_t seq;
+
+ if (mail_index_lookup_uid_range(ctx->mail_view, uid, uid,
+ &seq, &seq) < 0)
+ return -1;
+ if (seq == 0) {
+ mailbox_list_index_set_corrupted(ilist->list_index,
+ "Desynced: Record expunged from mail index");
+ return -1;
+ }
+
+ if (mail_index_lookup(ctx->mail_view, seq, &rec) < 0)
+ return -1;
+
+ *flags_r = index_mailbox_list_index_flags_translate(rec->flags);
+ return 0;
+}
+
+static int list_index_iter_next(struct index_mailbox_list_iterate_context *ctx,
+ const struct mailbox_info **info_r)
{
struct index_mailbox_list *ilist = INDEX_LIST_CONTEXT(ctx->ctx.list);
struct mailbox_list_index_info iinfo;
- const struct mail_index_record *rec;
- uint32_t seq;
+ struct mailbox_node *subs_node;
int ret;
/* find the next matching mailbox */
- do {
+ for (;;) {
p_clear(ctx->info_pool);
ret = mailbox_list_index_iterate_next(ctx->iter_ctx, &iinfo);
if (ret <= 0) {
@@ -293,41 +335,39 @@ static int iter_next_nonsync(struct inde
ctx->info.name = *ctx->prefix == '\0' ? iinfo.name :
p_strconcat(ctx->info_pool, ctx->prefix,
iinfo.name, NULL);
- } while (imap_match(ctx->glob, ctx->info.name) != IMAP_MATCH_YES);
-
- /* get the mailbox's flags */
- if (mail_index_lookup_uid_range(ctx->mail_view, iinfo.uid, iinfo.uid,
- &seq, &seq) < 0)
- return -1;
- if (seq == 0) {
- mailbox_list_index_set_corrupted(ilist->list_index,
- "Desynced: Record expunged from mail index");
- return -1;
- }
-
- if (mail_index_lookup(ctx->mail_view, seq, &rec) < 0)
- return -1;
- ctx->info.flags = index_mailbox_list_index_flags_translate(rec->flags);
-
- /* do some sanity checks to the flags */
- if ((ctx->info.flags & MAILBOX_CHILDREN) != 0 &&
- (ctx->info.flags & MAILBOX_NOCHILDREN) != 0) {
- mailbox_list_index_set_corrupted(ilist->list_index,
- "Mail index has both children and nochildren flags");
- return -1;
- }
- if ((ctx->info.flags & MAILBOX_NOCHILDREN) != 0 &&
- iinfo.has_children) {
- mailbox_list_index_set_corrupted(ilist->list_index,
- "Desynced: Children flags wrong in mail index");
- return -1;
- }
-
- if (!info_flags_match(ctx, &ctx->info))
- return iter_next_nonsync(ctx, info_r);
-
- *info_r = &ctx->info;
- return 0;
+ if (imap_match(ctx->glob, ctx->info.name) != IMAP_MATCH_YES)
+ continue;
+
+ if (list_index_get_info_flags(ctx, iinfo.uid,
+ &ctx->info.flags) < 0)
+ return -1;
+
+ if ((ctx->info.flags & MAILBOX_NOCHILDREN) != 0 &&
+ iinfo.has_children) {
+ mailbox_list_index_set_corrupted(ilist->list_index,
+ "Desynced: Children flags wrong in mail index");
+ return -1;
+ }
+
+ /* skip nonexistent mailboxes when finding with "*" */
+ if ((ctx->info.flags & MAILBOX_NONEXISTENT) != 0 &&
+ ctx->recurse_level < 0)
+ continue;
+
+ if (ctx->subs_tree != NULL) {
+ /* get subscription states */
+ subs_node = mailbox_tree_lookup(ctx->subs_tree,
+ ctx->info.name);
+ if (subs_node != NULL) {
+ ctx->info.flags |= subs_node->flags &
+ (MAILBOX_SUBSCRIBED |
+ MAILBOX_CHILD_SUBSCRIBED);
+ }
+ }
+
+ *info_r = &ctx->info;
+ return 0;
+ }
}
static const struct mailbox_info *
@@ -337,16 +377,35 @@ index_mailbox_list_iter_next(struct mail
(struct index_mailbox_list_iterate_context *)_ctx;
struct index_mailbox_list *ilist = INDEX_LIST_CONTEXT(_ctx->list);
const struct mailbox_info *info;
+ struct mailbox_node *subs_node;
+ uint32_t uid;
if (ctx->iter_ctx != NULL) {
- if (iter_next_nonsync(ctx, &info) < 0) {
+ /* listing mailboxes from index */
+ if (list_index_iter_next(ctx, &info) < 0) {
ctx->failed = TRUE;
return NULL;
}
return info;
- }
-
- return ilist->module_ctx.super.iter_next(ctx->backend_ctx);
+ } else if (ctx->backend_ctx != NULL) {
+ /* index isn't being used */
+ return ilist->module_ctx.super.iter_next(ctx->backend_ctx);
+ }
+
+ /* listing subscriptions, but we also want flags */
+ subs_node = mailbox_tree_iterate_next(ctx->subs_iter, &ctx->info.name);
+ if (subs_node == NULL)
+ return NULL;
+
+ if (mailbox_list_index_lookup(ctx->view, ctx->info.name, &uid) < 0 ||
+ list_index_get_info_flags(ctx, uid, &ctx->info.flags) < 0) {
+ ctx->failed = TRUE;
+ return NULL;
+ }
+
+ ctx->info.flags |= subs_node->flags &
+ (MAILBOX_SUBSCRIBED | MAILBOX_CHILD_SUBSCRIBED);
+ return &ctx->info;
}
static int
@@ -357,6 +416,8 @@ index_mailbox_list_iter_deinit(struct ma
struct index_mailbox_list *ilist = INDEX_LIST_CONTEXT(_ctx->list);
int ret = ctx->failed ? -1 : 0;
+ if (ctx->subs_iter != NULL)
+ mailbox_tree_iterate_deinit(&ctx->subs_iter);
if (ctx->iter_ctx != NULL)
mailbox_list_index_iterate_deinit(&ctx->iter_ctx);
if (ctx->info_pool != NULL)
diff -r 07d08be5bbb8 -r ca0770f7b1a8 src/lib-storage/list/index-mailbox-list.h
--- a/src/lib-storage/list/index-mailbox-list.h Wed Jul 18 03:15:53 2007 +0300
+++ b/src/lib-storage/list/index-mailbox-list.h Wed Jul 18 03:53:02 2007 +0300
@@ -29,6 +29,9 @@ struct index_mailbox_list_iterate_contex
struct mailbox_list_iter_ctx *iter_ctx;
struct mailbox_list_iterate_context *backend_ctx;
+ struct mailbox_tree_context *subs_tree;
+ struct mailbox_tree_iterate_context *subs_iter;
+
struct mailbox_list_index_view *view;
struct mail_index_view *mail_view;
struct mail_index_transaction *trans;
More information about the dovecot-cvs
mailing list