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