Mercurial > dovecot > core-2.2
view src/lib-storage/index/dbox-single/sdbox-storage.c @ 13287:957060ca5b69
Moved GUID code to liblib. Use guid_128_t type consistently everywhere.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 25 Aug 2011 01:16:11 +0300 |
parents | 189c9baf840a |
children | bba92468b051 |
line wrap: on
line source
/* Copyright (c) 2007-2011 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "master-service.h" #include "mail-index-modseq.h" #include "mail-search-build.h" #include "mailbox-list-private.h" #include "dbox-mail.h" #include "dbox-save.h" #include "sdbox-file.h" #include "sdbox-sync.h" #include "sdbox-storage.h" extern struct mail_storage dbox_storage, sdbox_storage; extern struct mailbox sdbox_mailbox; extern struct dbox_storage_vfuncs sdbox_dbox_storage_vfuncs; static struct mail_storage *sdbox_storage_alloc(void) { struct sdbox_storage *storage; pool_t pool; pool = pool_alloconly_create("sdbox storage", 512+256); storage = p_new(pool, struct sdbox_storage, 1); storage->storage.v = sdbox_dbox_storage_vfuncs; storage->storage.storage = sdbox_storage; storage->storage.storage.pool = pool; return &storage->storage.storage; } static struct mailbox * sdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list, const char *vname, enum mailbox_flags flags) { struct sdbox_mailbox *mbox; struct index_mailbox_context *ibox; pool_t pool; /* dbox can't work without index files */ flags &= ~MAILBOX_FLAG_NO_INDEX_FILES; pool = pool_alloconly_create("sdbox mailbox", 1024*3); mbox = p_new(pool, struct sdbox_mailbox, 1); mbox->box = sdbox_mailbox; mbox->box.pool = pool; mbox->box.storage = storage; mbox->box.list = list; mbox->box.mail_vfuncs = &sdbox_mail_vfuncs; index_storage_mailbox_alloc(&mbox->box, vname, flags, DBOX_INDEX_PREFIX); ibox = INDEX_STORAGE_CONTEXT(&mbox->box); ibox->index_flags |= MAIL_INDEX_OPEN_FLAG_KEEP_BACKUPS | MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY; mbox->storage = (struct sdbox_storage *)storage; return &mbox->box; } int sdbox_read_header(struct sdbox_mailbox *mbox, struct sdbox_index_header *hdr, bool log_error) { struct mail_index_view *view; const void *data; size_t data_size; int ret; view = mail_index_view_open(mbox->box.index); mail_index_get_header_ext(view, mbox->hdr_ext_id, &data, &data_size); if (data_size < SDBOX_INDEX_HEADER_MIN_SIZE && (!mbox->box.creating || data_size != 0)) { if (log_error) { mail_storage_set_critical( &mbox->storage->storage.storage, "sdbox %s: Invalid dbox header size", mailbox_get_path(&mbox->box)); } ret = -1; } else { memset(hdr, 0, sizeof(*hdr)); memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr))); ret = 0; } mail_index_view_close(&view); return ret; } void sdbox_update_header(struct sdbox_mailbox *mbox, struct mail_index_transaction *trans, const struct mailbox_update *update) { struct sdbox_index_header hdr, new_hdr; if (sdbox_read_header(mbox, &hdr, TRUE) < 0) memset(&hdr, 0, sizeof(hdr)); new_hdr = hdr; if (update != NULL && !guid_128_is_empty(update->mailbox_guid)) { memcpy(new_hdr.mailbox_guid, update->mailbox_guid, sizeof(new_hdr.mailbox_guid)); } else if (guid_128_is_empty(new_hdr.mailbox_guid)) { guid_128_generate(new_hdr.mailbox_guid); } if (memcmp(&hdr, &new_hdr, sizeof(hdr)) != 0) { mail_index_update_header_ext(trans, mbox->hdr_ext_id, 0, &new_hdr, sizeof(new_hdr)); } memcpy(mbox->mailbox_guid, new_hdr.mailbox_guid, sizeof(mbox->mailbox_guid)); } static int sdbox_mailbox_create_indexes(struct mailbox *box, const struct mailbox_update *update, struct mail_index_transaction *trans) { struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box; struct mail_index_transaction *new_trans = NULL; const struct mail_index_header *hdr; uint32_t uid_validity, uid_next; if (trans == NULL) { new_trans = mail_index_transaction_begin(box->view, 0); trans = new_trans; } hdr = mail_index_get_header(box->view); if (update != NULL && update->uid_validity != 0) uid_validity = update->uid_validity; else if (hdr->uid_validity != 0) uid_validity = hdr->uid_validity; else { /* set uidvalidity */ uid_validity = dbox_get_uidvalidity_next(box->list); } if (hdr->uid_validity != uid_validity) { if (hdr->uid_validity != 0) { /* UIDVALIDITY change requires index to be reset */ mail_index_reset(trans); } mail_index_update_header(trans, offsetof(struct mail_index_header, uid_validity), &uid_validity, sizeof(uid_validity), TRUE); } if (update != NULL && hdr->next_uid < update->min_next_uid) { uid_next = update->min_next_uid; mail_index_update_header(trans, offsetof(struct mail_index_header, next_uid), &uid_next, sizeof(uid_next), TRUE); } if (update != NULL && update->min_first_recent_uid != 0 && hdr->first_recent_uid < update->min_first_recent_uid) { uint32_t first_recent_uid = update->min_first_recent_uid; mail_index_update_header(trans, offsetof(struct mail_index_header, first_recent_uid), &first_recent_uid, sizeof(first_recent_uid), FALSE); } if (update != NULL && update->min_highest_modseq != 0 && mail_index_modseq_get_highest(box->view) < update->min_highest_modseq) { mail_index_modseq_enable(box->index); mail_index_update_highest_modseq(trans, update->min_highest_modseq); } sdbox_update_header(mbox, trans, update); if (new_trans != NULL) { if (mail_index_transaction_commit(&new_trans) < 0) { mail_storage_set_internal_error(box->storage); mail_index_reset_error(box->index); return -1; } } return 0; } static const char * sdbox_get_attachment_path_suffix(struct dbox_file *_file) { struct sdbox_file *file = (struct sdbox_file *)_file; return t_strdup_printf("-%s-%u", guid_128_to_string(file->mbox->mailbox_guid), file->uid); } void sdbox_set_mailbox_corrupted(struct mailbox *box) { struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box; struct sdbox_index_header hdr; if (sdbox_read_header(mbox, &hdr, TRUE) < 0 || hdr.rebuild_count == 0) mbox->corrupted_rebuild_count = 1; else mbox->corrupted_rebuild_count = hdr.rebuild_count; } static void sdbox_set_file_corrupted(struct dbox_file *_file) { struct sdbox_file *file = (struct sdbox_file *)_file; sdbox_set_mailbox_corrupted(&file->mbox->box); } static int sdbox_mailbox_open(struct mailbox *box) { struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box; struct sdbox_index_header hdr; if (dbox_mailbox_open(box) < 0) return -1; mbox->hdr_ext_id = mail_index_ext_register(box->index, "dbox-hdr", sizeof(struct sdbox_index_header), 0, 0); if (box->creating) { /* wait for mailbox creation to initialize the index */ return 0; } if (box->creating) { /* wait for mailbox creation to initialize the index */ return 0; } /* get/generate mailbox guid */ if (sdbox_read_header(mbox, &hdr, FALSE) < 0) { /* it's possible that this mailbox is just now being created by another process. lock it first and see if the header is available then. */ struct mail_index_sync_ctx *sync_ctx; struct mail_index_view *view; struct mail_index_transaction *trans; if (mail_index_sync_begin(box->index, &sync_ctx, &view, &trans, 0) > 0) (void)mail_index_sync_commit(&sync_ctx); if (sdbox_read_header(mbox, &hdr, TRUE) < 0) memset(&hdr, 0, sizeof(hdr)); } if (guid_128_is_empty(hdr.mailbox_guid)) { /* regenerate it */ if (sdbox_mailbox_create_indexes(box, NULL, NULL) < 0 || sdbox_read_header(mbox, &hdr, TRUE) < 0) return -1; } memcpy(mbox->mailbox_guid, hdr.mailbox_guid, sizeof(mbox->mailbox_guid)); return 0; } static void sdbox_mailbox_close(struct mailbox *box) { struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box; if (mbox->corrupted_rebuild_count != 0) (void)sdbox_sync(mbox, 0); index_storage_mailbox_close(box); } static int sdbox_mailbox_get_metadata(struct mailbox *box, enum mailbox_metadata_items items, struct mailbox_metadata *metadata_r) { struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box; if ((items & MAILBOX_METADATA_GUID) != 0) { memcpy(metadata_r->guid, mbox->mailbox_guid, sizeof(metadata_r->guid)); } return index_mailbox_get_metadata(box, items, metadata_r); } static int dbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update) { if (!box->opened) { if (mailbox_open(box) < 0) return -1; } if (update->cache_fields != NULL) index_storage_mailbox_update_cache_fields(box, update); return sdbox_mailbox_create_indexes(box, update, NULL); } struct mail_storage sdbox_storage = { .name = SDBOX_STORAGE_NAME, .class_flags = 0, .v = { NULL, sdbox_storage_alloc, dbox_storage_create, dbox_storage_destroy, NULL, dbox_storage_get_list_settings, NULL, sdbox_mailbox_alloc, NULL } }; struct mail_storage dbox_storage = { .name = "dbox", /* alias */ .class_flags = MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG, .v = { NULL, sdbox_storage_alloc, dbox_storage_create, dbox_storage_destroy, NULL, dbox_storage_get_list_settings, NULL, sdbox_mailbox_alloc, NULL } }; struct mailbox sdbox_mailbox = { .v = { index_storage_is_readonly, index_storage_mailbox_enable, index_storage_mailbox_exists, sdbox_mailbox_open, sdbox_mailbox_close, index_storage_mailbox_free, dbox_mailbox_create, dbox_mailbox_update, index_storage_mailbox_delete, index_storage_mailbox_rename, index_storage_get_status, sdbox_mailbox_get_metadata, index_storage_list_index_has_changed, index_storage_list_index_update_sync, sdbox_storage_sync_init, index_mailbox_sync_next, index_mailbox_sync_deinit, NULL, dbox_notify_changes, index_transaction_begin, index_transaction_commit, index_transaction_rollback, NULL, dbox_mail_alloc, index_storage_search_init, index_storage_search_deinit, index_storage_search_next_nonblock, index_storage_search_next_update_seq, sdbox_save_alloc, sdbox_save_begin, dbox_save_continue, sdbox_save_finish, sdbox_save_cancel, sdbox_copy, sdbox_transaction_save_commit_pre, sdbox_transaction_save_commit_post, sdbox_transaction_save_rollback, index_storage_is_inconsistent } }; struct dbox_storage_vfuncs sdbox_dbox_storage_vfuncs = { sdbox_file_free, sdbox_file_create_fd, sdbox_mail_open, sdbox_mailbox_create_indexes, sdbox_get_attachment_path_suffix, sdbox_set_mailbox_corrupted, sdbox_set_file_corrupted };