45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen#include "lib.h"
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen#include "ioloop.h"
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen#include "hash.h"
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen#include "mail-storage.h"
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen#include "mailbox-list-private.h"
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen#include "mailbox-guid-cache.h"
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainenstruct mailbox_guid_cache_rec {
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen guid_128_t guid;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen const char *vname;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen};
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainenint mailbox_guid_cache_find(struct mailbox_list *list,
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen const guid_128_t guid, const char **vname_r)
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen{
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen const struct mailbox_guid_cache_rec *rec;
4ded3d18fa391ae5908f9834f1390cf55e8c99d5Timo Sirainen const uint8_t *guid_p = guid;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen if (!hash_table_is_created(list->guid_cache) ||
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen list->guid_cache_invalidated) {
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen mailbox_guid_cache_refresh(list);
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen rec = hash_table_lookup(list->guid_cache, guid_p);
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen } else {
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen rec = hash_table_lookup(list->guid_cache, guid_p);
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen if (rec == NULL && list->guid_cache_updated) {
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen mailbox_guid_cache_refresh(list);
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen rec = hash_table_lookup(list->guid_cache, guid_p);
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen }
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen }
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen if (rec == NULL) {
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen *vname_r = NULL;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen return list->guid_cache_errors ? -1 : 0;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen }
4ded3d18fa391ae5908f9834f1390cf55e8c99d5Timo Sirainen *vname_r = rec->vname;
4ded3d18fa391ae5908f9834f1390cf55e8c99d5Timo Sirainen return 0;
4ded3d18fa391ae5908f9834f1390cf55e8c99d5Timo Sirainen}
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainenvoid mailbox_guid_cache_refresh(struct mailbox_list *list)
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen{
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen struct mailbox_list_iterate_context *ctx;
ba153863e55d75a7c2f28c9c010a905b8887b62bTimo Sirainen const struct mailbox_info *info;
b3a069922c8150a1cb14ec7683444f60dee98b55Timo Sirainen struct mailbox *box;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen struct mailbox_metadata metadata;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen struct mailbox_guid_cache_rec *rec;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen uint8_t *guid_p;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen if (!hash_table_is_created(list->guid_cache)) {
7b9f0c6aba07358e5520dc60c058126a4cae4056Timo Sirainen list->guid_cache_pool =
7b9f0c6aba07358e5520dc60c058126a4cae4056Timo Sirainen pool_alloconly_create("guid cache", 1024*16);
7b9f0c6aba07358e5520dc60c058126a4cae4056Timo Sirainen hash_table_create(&list->guid_cache, list->guid_cache_pool, 0,
7b9f0c6aba07358e5520dc60c058126a4cae4056Timo Sirainen guid_128_hash, guid_128_cmp);
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen } else {
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen hash_table_clear(list->guid_cache, TRUE);
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen p_clear(list->guid_cache_pool);
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen }
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen list->guid_cache_invalidated = FALSE;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen list->guid_cache_updated = FALSE;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen list->guid_cache_errors = FALSE;
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen ctx = mailbox_list_iter_init(list, "*",
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen MAILBOX_LIST_ITER_SKIP_ALIASES |
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen MAILBOX_LIST_ITER_NO_AUTO_BOXES);
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen while ((info = mailbox_list_iter_next(ctx)) != NULL) {
128ab2c52a29068be87e12ab5aebbb8fdc933adfTimo Sirainen if ((info->flags &
(MAILBOX_NOSELECT | MAILBOX_NONEXISTENT)) != 0)
continue;
box = mailbox_alloc(list, info->vname, 0);
if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID,
&metadata) < 0) {
i_error("Couldn't get mailbox %s GUID: %s",
info->vname, mailbox_get_last_internal_error(box, NULL));
list->guid_cache_errors = TRUE;
} else if ((rec = hash_table_lookup(list->guid_cache,
(const uint8_t *)metadata.guid)) != NULL) {
i_warning("Mailbox %s has duplicate GUID with %s: %s",
info->vname, rec->vname,
guid_128_to_string(metadata.guid));
} else {
rec = p_new(list->guid_cache_pool,
struct mailbox_guid_cache_rec, 1);
memcpy(rec->guid, metadata.guid, sizeof(rec->guid));
rec->vname = p_strdup(list->guid_cache_pool, info->vname);
guid_p = rec->guid;
hash_table_insert(list->guid_cache, guid_p, rec);
}
mailbox_free(&box);
}
if (mailbox_list_iter_deinit(&ctx) < 0)
list->guid_cache_errors = TRUE;
}