mdbox-storage.c revision a46d8b27aa617c79f51dd8dfb363f5b3518b63e4
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "lib.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "array.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "mkdir-parents.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "mail-index-modseq.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "mail-index-alloc-cache.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "mailbox-log.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "dbox-mail.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "dbox-save.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "mdbox-map.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "mdbox-file.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "mdbox-sync.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "mdbox-storage-rebuild.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "mdbox-storage.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenextern struct mail_storage mdbox_storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenextern struct mailbox mdbox_mailbox;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenextern struct dbox_storage_vfuncs mdbox_dbox_storage_vfuncs;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic struct mail_storage *mdbox_storage_alloc(void)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_storage *storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen pool_t pool;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
4c1deab456fe8877bf025d11843167ac1f36327aTimo Sirainen pool = pool_alloconly_create("mdbox storage", 2048);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage = p_new(pool, struct mdbox_storage, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->storage.v = mdbox_dbox_storage_vfuncs;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->storage.storage = mdbox_storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->storage.storage.pool = pool;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return &storage->storage.storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmdbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char **error_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_storage *storage = (struct mdbox_storage *)_storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *dir;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->set = mail_storage_get_driver_settings(_storage);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(storage->set->mdbox_max_open_files >= 2);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (*ns->list->set.mailbox_dir_name == '\0') {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *error_r = "dbox: MAILBOXDIR must not be empty";
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _storage->unique_root_dir =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen p_strdup(_storage->pool, ns->list->set.root_dir);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dir = mailbox_list_get_path(ns->list, NULL, MAILBOX_LIST_PATH_TYPE_DIR);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->storage_dir = p_strconcat(_storage->pool, dir,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "/"MDBOX_GLOBAL_DIR_NAME, NULL);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->alt_storage_dir = p_strconcat(_storage->pool,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ns->list->set.alt_dir,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "/"MDBOX_GLOBAL_DIR_NAME, NULL);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_array_init(&storage->open_files,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen I_MIN(storage->set->mdbox_max_open_files, 128));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->map = dbox_map_init(storage, ns->list, storage->storage_dir);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void mdbox_storage_destroy(struct mail_storage *_storage)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_storage *storage = (struct mdbox_storage *)_storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (storage->storage.files_corrupted) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mdbox_storage_rebuild(storage) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_files_free(storage);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_map_deinit(&storage->map);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen array_free(&storage->open_files);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct mailbox *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen const char *name, enum mailbox_flags flags)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_mailbox *mbox;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct index_mailbox_context *ibox;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen pool_t pool;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* dbox can't work without index files */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen flags &= ~MAILBOX_FLAG_NO_INDEX_FILES;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
3b32bc12710240f86465a00fbb2bd1ef030e6c40Timo Sirainen pool = pool_alloconly_create("mdbox mailbox", 1024*3);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mbox = p_new(pool, struct mdbox_mailbox, 1);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mbox->box = mdbox_mailbox;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mbox->box.pool = pool;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mbox->box.storage = storage;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mbox->box.list = list;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mbox->box.mail_vfuncs = &mdbox_mail_vfuncs;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen index_storage_mailbox_alloc(&mbox->box, name, flags, DBOX_INDEX_PREFIX);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_set_fsync_types(mbox->box.index,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen MAIL_INDEX_SYNC_TYPE_APPEND |
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen MAIL_INDEX_SYNC_TYPE_EXPUNGE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox->save_commit_pre = mdbox_transaction_save_commit_pre;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox->save_commit_post = mdbox_transaction_save_commit_post;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox->save_rollback = mdbox_transaction_save_rollback;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox->index_flags |= MAIL_INDEX_OPEN_FLAG_KEEP_BACKUPS |
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mbox->storage = (struct mdbox_storage *)storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mbox->ext_id =
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_ext_register(mbox->box.index, "mdbox", 0,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen sizeof(struct mdbox_mail_index_record),
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen sizeof(uint32_t));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mbox->hdr_ext_id =
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_ext_register(mbox->box.index, "mdbox-hdr",
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen sizeof(struct mdbox_index_header), 0, 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mbox->guid_ext_id =
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_ext_register(mbox->box.index, "guid",
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen 0, MAIL_GUID_128_SIZE, 1);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return &mbox->box;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint mdbox_read_header(struct mdbox_mailbox *mbox,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_index_header *hdr)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const void *data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size_t data_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_get_header_ext(mbox->box.view, mbox->hdr_ext_id,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen &data, &data_size);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (data_size < MDBOX_INDEX_HEADER_MIN_SIZE &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (!mbox->creating || data_size != 0)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_storage_set_critical(&mbox->storage->storage.storage,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "dbox %s: Invalid dbox header size",
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mbox->box.path);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memset(hdr, 0, sizeof(*hdr));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid mdbox_update_header(struct mdbox_mailbox *mbox,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_index_transaction *trans,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct mailbox_update *update)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_index_header hdr, new_hdr;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mdbox_read_header(mbox, &hdr) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memset(&hdr, 0, sizeof(hdr));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen new_hdr = hdr;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (update != NULL && !mail_guid_128_is_empty(update->mailbox_guid)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memcpy(new_hdr.mailbox_guid, update->mailbox_guid,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen sizeof(new_hdr.mailbox_guid));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else if (mail_guid_128_is_empty(new_hdr.mailbox_guid)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_generate_guid_128(new_hdr.mailbox_guid);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen new_hdr.map_uid_validity =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_map_get_uid_validity(mbox->storage->map);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (memcmp(&hdr, &new_hdr, sizeof(hdr)) != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_update_header_ext(trans, mbox->hdr_ext_id, 0,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen &new_hdr, sizeof(new_hdr));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int mdbox_write_index_header(struct mailbox *box,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct mailbox_update *update)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_index_transaction *trans;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct mail_index_header *hdr;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen uint32_t uid_validity, uid_next;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (dbox_map_open(mbox->storage->map, TRUE) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen hdr = mail_index_get_header(box->view);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen trans = mail_index_transaction_begin(box->view, 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
6d2c938f017a2fc55ae476f88839f03a3d3c5fbdTimo Sirainen uid_validity = hdr->uid_validity;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (update != NULL && update->uid_validity != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen uid_validity = update->uid_validity;
6d2c938f017a2fc55ae476f88839f03a3d3c5fbdTimo Sirainen else if (uid_validity == 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* set uidvalidity */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen uid_validity = dbox_get_uidvalidity_next(box->list);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (hdr->uid_validity != uid_validity) {
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen if (hdr->uid_validity != 0) {
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen /* UIDVALIDITY change requires index to be reset */
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen mail_index_reset(trans);
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_update_header(trans,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen offsetof(struct mail_index_header, uid_validity),
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen &uid_validity, sizeof(uid_validity), TRUE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (update != NULL && hdr->next_uid < update->min_next_uid) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen uid_next = update->min_next_uid;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_update_header(trans,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen offsetof(struct mail_index_header, next_uid),
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen &uid_next, sizeof(uid_next), TRUE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (update != NULL && update->min_highest_modseq != 0 &&
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen mail_index_modseq_get_highest(box->view) <
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen update->min_highest_modseq) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_update_highest_modseq(trans,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen update->min_highest_modseq);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen mdbox_update_header(mbox, trans, update);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mail_index_transaction_commit(&trans) < 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mail_storage_set_index_error(box);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int mdbox_mailbox_create_indexes(struct mailbox *box,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct mailbox_update *update)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen int ret;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen mbox->creating = TRUE;
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen ret = mdbox_write_index_header(box, update);
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen mbox->creating = FALSE;
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen return ret;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainenstatic int
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainenmdbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_index_header hdr;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mdbox_read_header(mbox, &hdr) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memset(&hdr, 0, sizeof(hdr));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mail_guid_128_is_empty(hdr.mailbox_guid)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* regenerate it */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mdbox_write_index_header(box, NULL) < 0 ||
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_read_header(mbox, &hdr) < 0)
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen memcpy(guid, hdr.mailbox_guid, MAIL_GUID_128_SIZE);
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmdbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!box->opened) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (index_storage_mailbox_open(box, FALSE) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
a46d8b27aa617c79f51dd8dfb363f5b3518b63e4Timo Sirainen if (update->cache_fields != NULL)
a46d8b27aa617c79f51dd8dfb363f5b3518b63e4Timo Sirainen index_storage_mailbox_update_cache_fields(box, update);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return mdbox_write_index_header(box, update);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenstatic int mdbox_mailbox_unref_mails(struct mdbox_mailbox *mbox)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen struct dbox_map_transaction_context *map_trans;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct mail_index_header *hdr;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct mdbox_mail_index_record *dbox_rec;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ARRAY_TYPE(uint32_t) map_uids;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const void *data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool expunged;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen uint32_t seq;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen int ret;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* get a list of all map_uids in this mailbox */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_array_init(&map_uids, 128);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen hdr = mail_index_get_header(mbox->box.view);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (seq = 1; seq <= hdr->messages_count; seq++) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mail_index_lookup_ext(mbox->box.view, seq, mbox->ext_id,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen &data, &expunged);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_rec = data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (dbox_rec == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* no multi-mails */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen break;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (dbox_rec->map_uid != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen array_append(&map_uids, &dbox_rec->map_uid, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* unreference the map_uids */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen map_trans = dbox_map_transaction_begin(mbox->storage->map, FALSE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ret = dbox_map_update_refcounts(map_trans, &map_uids, -1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ret == 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ret = dbox_map_transaction_commit(map_trans);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_map_transaction_free(&map_trans);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen array_free(&map_uids);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return ret;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenstatic int mdbox_mailbox_delete(struct mailbox *box)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (box->opened) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (mdbox_mailbox_unref_mails(mbox) < 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return index_storage_mailbox_delete(box);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct mail_storage mdbox_storage = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .name = MDBOX_STORAGE_NAME,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .class_flags = MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .v = {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_get_setting_parser_info,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_storage_alloc,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_storage_create,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_storage_destroy,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen NULL,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_storage_get_list_settings,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen NULL,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_mailbox_alloc,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_sync_purge
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct mailbox mdbox_mailbox = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .v = {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_is_readonly,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_allow_new_keywords,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_mailbox_enable,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_mailbox_open,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_mailbox_close,
438f12d7a776da695019114884b48188d94613efTimo Sirainen index_storage_mailbox_free,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_mailbox_create,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_mailbox_update,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mdbox_mailbox_delete,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen index_storage_mailbox_rename,
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen index_storage_get_status,
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen mdbox_mailbox_get_guid,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen NULL,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen NULL,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_storage_sync_init,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_mailbox_sync_next,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_mailbox_sync_deinit,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen NULL,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_notify_changes,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_transaction_begin,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_transaction_commit,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_transaction_rollback,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_transaction_set_max_modseq,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_keywords_create,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_keywords_create_from_indexes,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_keywords_ref,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_keywords_unref,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_keyword_is_valid,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_get_seq_range,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_get_uid_range,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_get_expunges,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen NULL,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen NULL,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen NULL,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_mail_alloc,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_header_lookup_init,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_header_lookup_deinit,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_search_init,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_search_deinit,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_search_next_nonblock,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_search_next_update_seq,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_save_alloc,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_save_begin,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_save_continue,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_save_finish,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_save_cancel,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_copy,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_storage_is_inconsistent
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct dbox_storage_vfuncs mdbox_dbox_storage_vfuncs = {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_file_unrefed,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_file_create_fd,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_mail_open,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdbox_mailbox_create_indexes
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};