Mercurial > dovecot > core-2.2
changeset 13587:cd7b56e965d2
mailbox list indexes: Moved iteration code to separate file.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 02 Oct 2011 17:18:31 +0300 |
parents | 8800d0429b7c |
children | 940ddec22822 |
files | src/lib-storage/list/Makefile.am src/lib-storage/list/mailbox-list-index-iter.c src/lib-storage/list/mailbox-list-index.c src/lib-storage/list/mailbox-list-index.h |
diffstat | 4 files changed, 181 insertions(+), 169 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/list/Makefile.am Sun Oct 02 17:12:58 2011 +0300 +++ b/src/lib-storage/list/Makefile.am Sun Oct 02 17:18:31 2011 +0300 @@ -14,6 +14,7 @@ mailbox-list-fs-flags.c \ mailbox-list-fs-iter.c \ mailbox-list-index.c \ + mailbox-list-index-iter.c \ mailbox-list-index-status.c \ mailbox-list-maildir.c \ mailbox-list-maildir-iter.c \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-storage/list/mailbox-list-index-iter.c Sun Oct 02 17:18:31 2011 +0300 @@ -0,0 +1,172 @@ +/* Copyright (c) 2006-2011 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "str.h" +#include "imap-match.h" +#include "mail-storage.h" +#include "mailbox-list-subscriptions.h" +#include "mailbox-list-index.h" + +struct mailbox_list_iterate_context * +mailbox_list_index_iter_init(struct mailbox_list *list, + const char *const *patterns, + enum mailbox_list_iter_flags flags) +{ + struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list); + struct mailbox_list_index_iterate_context *ctx; + char ns_sep = mail_namespace_get_sep(list->ns); + + ctx = i_new(struct mailbox_list_index_iterate_context, 1); + ctx->ctx.list = list; + ctx->ctx.flags = flags; + ctx->ctx.glob = imap_match_init_multiple(default_pool, patterns, + TRUE, ns_sep); + array_create(&ctx->ctx.module_contexts, default_pool, sizeof(void *), 5); + ctx->sep = ns_sep; + + if (mailbox_list_index_refresh(ctx->ctx.list) < 0) { + /* no indexing */ + ctx->backend_ctx = ilist->module_ctx.super. + iter_init(list, patterns, flags); + } else { + /* listing mailboxes from index */ + ctx->info.ns = list->ns; + ctx->path = str_new(default_pool, 128); + ctx->next_node = ilist->mailbox_tree; + ilist->iter_refcount++; + } + return &ctx->ctx; +} + +static void +mailbox_list_index_update_info(struct mailbox_list_index_iterate_context *ctx) +{ + struct mailbox_list_index_node *node = ctx->next_node; + struct mailbox *box; + + str_truncate(ctx->path, ctx->parent_len); + if (str_len(ctx->path) > 0) + str_append_c(ctx->path, ctx->sep); + str_append(ctx->path, node->name); + + ctx->info.name = str_c(ctx->path); + ctx->info.flags = 0; + if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NONEXISTENT) != 0) + ctx->info.flags |= MAILBOX_NONEXISTENT; + else if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NOSELECT) != 0) + ctx->info.flags |= MAILBOX_NOSELECT; + if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NOINFERIORS) != 0) + ctx->info.flags |= MAILBOX_NOINFERIORS; + ctx->info.flags |= node->children != NULL ? + MAILBOX_CHILDREN : MAILBOX_NOCHILDREN; + + if ((ctx->ctx.flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED | + MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0) { + mailbox_list_set_subscription_flags(ctx->ctx.list, + ctx->info.name, + &ctx->info.flags); + } + + box = mailbox_alloc(ctx->ctx.list, ctx->info.name, 0); + mailbox_list_index_status_set_info_flags(box, node->uid, + &ctx->info.flags); + mailbox_free(&box); +} + +static void +mailbox_list_index_update_next(struct mailbox_list_index_iterate_context *ctx, + bool follow_children) +{ + struct mailbox_list_index_node *node = ctx->next_node; + + if (node->children != NULL && follow_children) { + ctx->parent_len = str_len(ctx->path); + ctx->next_node = node->children; + } else { + while (node->next == NULL) { + node = node->parent; + if (node != NULL) { + ctx->parent_len -= strlen(node->name); + if (node->parent != NULL) + ctx->parent_len--; + } + if (node == NULL) { + /* last one */ + ctx->next_node = NULL; + return; + } + } + ctx->next_node = node->next; + } +} + +static bool +iter_subscriptions_ok(struct mailbox_list_index_iterate_context *ctx) +{ + if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0) + return TRUE; + + if ((ctx->info.flags & MAILBOX_SUBSCRIBED) != 0) + return TRUE; + + if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) != 0 && + (ctx->info.flags & MAILBOX_CHILD_SUBSCRIBED) != 0) + return TRUE; + return FALSE; +} + +const struct mailbox_info * +mailbox_list_index_iter_next(struct mailbox_list_iterate_context *_ctx) +{ + struct mailbox_list_index_iterate_context *ctx = + (struct mailbox_list_index_iterate_context *)_ctx; + struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(_ctx->list); + bool follow_children; + enum imap_match_result match; + + if (ctx->backend_ctx != NULL) { + /* index isn't being used */ + return ilist->module_ctx.super.iter_next(ctx->backend_ctx); + } + + /* listing mailboxes from index */ + while (ctx->next_node != NULL) { + mailbox_list_index_update_info(ctx); + match = imap_match(_ctx->glob, ctx->info.name); + + follow_children = (match & (IMAP_MATCH_YES | + IMAP_MATCH_CHILDREN)) != 0; + if (match == IMAP_MATCH_YES && iter_subscriptions_ok(ctx)) { + mailbox_list_index_update_next(ctx, TRUE); + return &ctx->info; + } else if ((_ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0 && + (ctx->info.flags & MAILBOX_CHILD_SUBSCRIBED) == 0) { + /* listing only subscriptions, but there are no + subscribed children. */ + follow_children = FALSE; + } + mailbox_list_index_update_next(ctx, follow_children); + } + return NULL; +} + +int mailbox_list_index_iter_deinit(struct mailbox_list_iterate_context *_ctx) +{ + struct mailbox_list_index_iterate_context *ctx = + (struct mailbox_list_index_iterate_context *)_ctx; + struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(_ctx->list); + int ret = ctx->failed ? -1 : 0; + + if (ctx->backend_ctx != NULL) + ret = ilist->module_ctx.super.iter_deinit(ctx->backend_ctx); + else { + i_assert(ilist->iter_refcount > 0); + ilist->iter_refcount--; + str_free(&ctx->path); + } + + imap_match_deinit(&ctx->ctx.glob); + array_free(&ctx->ctx.module_contexts); + i_free(ctx); + return ret; +}
--- a/src/lib-storage/list/mailbox-list-index.c Sun Oct 02 17:12:58 2011 +0300 +++ b/src/lib-storage/list/mailbox-list-index.c Sun Oct 02 17:18:31 2011 +0300 @@ -2,13 +2,10 @@ #include "lib.h" #include "ioloop.h" -#include "str.h" #include "hash.h" -#include "imap-match.h" #include "mail-index.h" #include "mail-storage.h" #include "mail-storage-hooks.h" -#include "mailbox-list-subscriptions.h" #include "mailbox-list-index.h" struct mailbox_list_index_sync_context { @@ -551,172 +548,6 @@ mail_index_view_close(&view); } -static struct mailbox_list_iterate_context * -mailbox_list_index_iter_init(struct mailbox_list *list, - const char *const *patterns, - enum mailbox_list_iter_flags flags) -{ - struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list); - struct mailbox_list_index_iterate_context *ctx; - char ns_sep = mail_namespace_get_sep(list->ns); - - ctx = i_new(struct mailbox_list_index_iterate_context, 1); - ctx->ctx.list = list; - ctx->ctx.flags = flags; - ctx->ctx.glob = imap_match_init_multiple(default_pool, patterns, - TRUE, ns_sep); - array_create(&ctx->ctx.module_contexts, default_pool, sizeof(void *), 5); - ctx->sep = ns_sep; - - if (mailbox_list_index_refresh(ctx->ctx.list) < 0) { - /* no indexing */ - mail_index_mark_corrupted(ilist->index); - ctx->backend_ctx = ilist->module_ctx.super. - iter_init(list, patterns, flags); - } else { - /* listing mailboxes from index */ - ctx->info.ns = list->ns; - ctx->path = str_new(default_pool, 128); - ctx->next_node = ilist->mailbox_tree; - ilist->iter_refcount++; - } - return &ctx->ctx; -} - -static void -mailbox_list_index_update_info(struct mailbox_list_index_iterate_context *ctx) -{ - struct mailbox_list_index_node *node = ctx->next_node; - struct mailbox *box; - - str_truncate(ctx->path, ctx->parent_len); - if (str_len(ctx->path) > 0) - str_append_c(ctx->path, ctx->sep); - str_append(ctx->path, node->name); - - ctx->info.name = str_c(ctx->path); - ctx->info.flags = 0; - if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NONEXISTENT) != 0) - ctx->info.flags |= MAILBOX_NONEXISTENT; - else if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NOSELECT) != 0) - ctx->info.flags |= MAILBOX_NOSELECT; - if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NOINFERIORS) != 0) - ctx->info.flags |= MAILBOX_NOINFERIORS; - ctx->info.flags |= node->children != NULL ? - MAILBOX_CHILDREN : MAILBOX_NOCHILDREN; - - if ((ctx->ctx.flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED | - MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0) { - mailbox_list_set_subscription_flags(ctx->ctx.list, - ctx->info.name, - &ctx->info.flags); - } - - box = mailbox_alloc(ctx->ctx.list, ctx->info.name, 0); - mailbox_list_index_status_set_info_flags(box, node->uid, - &ctx->info.flags); - mailbox_free(&box); -} - -static void -mailbox_list_index_update_next(struct mailbox_list_index_iterate_context *ctx, - bool follow_children) -{ - struct mailbox_list_index_node *node = ctx->next_node; - - if (node->children != NULL && follow_children) { - ctx->parent_len = str_len(ctx->path); - ctx->next_node = node->children; - } else { - while (node->next == NULL) { - node = node->parent; - if (node != NULL) { - ctx->parent_len -= strlen(node->name); - if (node->parent != NULL) - ctx->parent_len--; - } - if (node == NULL) { - /* last one */ - ctx->next_node = NULL; - return; - } - } - ctx->next_node = node->next; - } -} - -static bool -iter_subscriptions_ok(struct mailbox_list_index_iterate_context *ctx) -{ - if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0) - return TRUE; - - if ((ctx->info.flags & MAILBOX_SUBSCRIBED) != 0) - return TRUE; - - if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) != 0 && - (ctx->info.flags & MAILBOX_CHILD_SUBSCRIBED) != 0) - return TRUE; - return FALSE; -} - -static const struct mailbox_info * -mailbox_list_index_iter_next(struct mailbox_list_iterate_context *_ctx) -{ - struct mailbox_list_index_iterate_context *ctx = - (struct mailbox_list_index_iterate_context *)_ctx; - struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(_ctx->list); - bool follow_children; - enum imap_match_result match; - - if (ctx->backend_ctx != NULL) { - /* index isn't being used */ - return ilist->module_ctx.super.iter_next(ctx->backend_ctx); - } - - /* listing mailboxes from index */ - while (ctx->next_node != NULL) { - mailbox_list_index_update_info(ctx); - match = imap_match(_ctx->glob, ctx->info.name); - - follow_children = (match & (IMAP_MATCH_YES | - IMAP_MATCH_CHILDREN)) != 0; - if (match == IMAP_MATCH_YES && iter_subscriptions_ok(ctx)) { - mailbox_list_index_update_next(ctx, TRUE); - return &ctx->info; - } else if ((_ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0 && - (ctx->info.flags & MAILBOX_CHILD_SUBSCRIBED) == 0) { - /* listing only subscriptions, but there are no - subscribed children. */ - follow_children = FALSE; - } - mailbox_list_index_update_next(ctx, follow_children); - } - return NULL; -} - -static int -mailbox_list_index_iter_deinit(struct mailbox_list_iterate_context *_ctx) -{ - struct mailbox_list_index_iterate_context *ctx = - (struct mailbox_list_index_iterate_context *)_ctx; - struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(_ctx->list); - int ret = ctx->failed ? -1 : 0; - - if (ctx->backend_ctx != NULL) - ret = ilist->module_ctx.super.iter_deinit(ctx->backend_ctx); - else { - i_assert(ilist->iter_refcount > 0); - ilist->iter_refcount--; - str_free(&ctx->path); - } - - imap_match_deinit(&ctx->ctx.glob); - array_free(&ctx->ctx.module_contexts); - i_free(ctx); - return ret; -} - static void mailbox_list_index_deinit(struct mailbox_list *list) { struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
--- a/src/lib-storage/list/mailbox-list-index.h Sun Oct 02 17:12:58 2011 +0300 +++ b/src/lib-storage/list/mailbox-list-index.h Sun Oct 02 17:18:31 2011 +0300 @@ -102,6 +102,14 @@ int mailbox_list_index_refresh(struct mailbox_list *list); void mailbox_list_index_refresh_later(struct mailbox_list *list); +struct mailbox_list_iterate_context * +mailbox_list_index_iter_init(struct mailbox_list *list, + const char *const *patterns, + enum mailbox_list_iter_flags flags); +const struct mailbox_info * +mailbox_list_index_iter_next(struct mailbox_list_iterate_context *ctx); +int mailbox_list_index_iter_deinit(struct mailbox_list_iterate_context *ctx); + void mailbox_list_index_status_set_info_flags(struct mailbox *box, uint32_t uid, enum mailbox_info_flags *flags);