mdbox-map.c revision 59a82d4b3adeef388aa66435e3fe9d9a37290c1b
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2016 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#define DBOX_FORCE_PURGE_MIN_BYTES (1024*1024*10)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#define MAP_STORAGE(map) (&(map)->storage->storage.storage)
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainenstatic int mdbox_map_generate_uid_validity(struct mdbox_map *map);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid mdbox_map_set_corrupted(struct mdbox_map *map, const char *format, ...)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "mdbox map %s corrupted: %s",
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainenmdbox_map_init(struct mdbox_storage *storage, struct mailbox_list *root_list)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen root = mailbox_list_get_root_forced(root_list, MAILBOX_LIST_PATH_TYPE_DIR);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_root = mailbox_list_get_root_forced(root_list, MAILBOX_LIST_PATH_TYPE_INDEX);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen map->path = i_strconcat(root, "/"MDBOX_GLOBAL_DIR_NAME, NULL);
767ff4367960efd5fa868f3b56f850fd4c205c8bTimo Sirainen i_strconcat(index_root, "/"MDBOX_GLOBAL_DIR_NAME, NULL);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen map->index = mail_index_alloc(map->index_path,
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen mail_storage_get_lock_timeout(MAP_STORAGE(map), UINT_MAX));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen map->map_ext_id = mail_index_ext_register(map->index, "map",
b67974c4b89ab6950c2694cce8dfb1b6561cc084Josef 'Jeff' Sipek map->ref_ext_id = mail_index_ext_register(map->index, "ref", 0,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int mdbox_map_mkdir_storage(struct mdbox_map *map)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mailbox_list_mkdir_root(map->root_list, map->path,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_storage_copy_list_error(MAP_STORAGE(map), map->root_list);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (strcmp(map->path, map->index_path) != 0 &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_list_mkdir_root(map->root_list, map->index_path,
7204b8112e005ff81dcf628f7880ef1feed1effeTimo Sirainen mail_storage_copy_list_error(MAP_STORAGE(map), map->root_list);
767ff4367960efd5fa868f3b56f850fd4c205c8bTimo Sirainenstatic void mdbox_map_cleanup(struct mdbox_map *map)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int interval =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen MAP_STORAGE(map)->set->mail_temp_scan_interval;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* check once in a while if there are temp files to clean up */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* disabled */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else if (st.st_atime > st.st_ctime + DBOX_TMP_DELETE_SECS) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* there haven't been any changes to this directory since we
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen last checked it. */
4ca83616715c3bd417e34ced2c1d61852513e427Timo Sirainen } else if (st.st_atime < ioloop_time - (time_t)interval) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* time to scan */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (void)unlink_old_files(map->path, DBOX_TEMP_FILE_PREFIX,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int mdbox_map_open_internal(struct mdbox_map *map, bool create_missing)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* already opened */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_list_get_root_permissions(map->root_list, &perm);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_set_permissions(map->index, perm.file_create_mode,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen open_flags = MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY |
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_storage_settings_to_index_flags(MAP_STORAGE(map)->set);
767ff4367960efd5fa868f3b56f850fd4c205c8bTimo Sirainen /* storage/ directory already existed.
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen the index should exist also. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ret = mail_index_open(map->index, open_flags);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* storage/ already existed, but indexes didn't. we'll need to
5096d157aa1acd28a93f45b058ca5bf26a4fddbeTimo Sirainen take extra steps to make sure we won't overwrite any m.*
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen files that may already exist. */
03de962febfc2ac572f9e4029463c16d29c1ed55Timo Sirainen ret = mail_index_open(map->index, open_flags);
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek mail_storage_set_internal_error(MAP_STORAGE(map));
03de962febfc2ac572f9e4029463c16d29c1ed55Timo Sirainen /* index not found - for now just return failure */
03de962febfc2ac572f9e4029463c16d29c1ed55Timo Sirainen if (mail_index_get_header(map->view)->uid_validity == 0) {
03de962febfc2ac572f9e4029463c16d29c1ed55Timo Sirainen if (mdbox_map_generate_uid_validity(map) < 0 ||
03de962febfc2ac572f9e4029463c16d29c1ed55Timo Sirainen mail_storage_set_internal_error(MAP_STORAGE(map));
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainenint mdbox_map_open_or_create(struct mdbox_map *map)
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen return mdbox_map_open_internal(map, TRUE) <= 0 ? -1 : 0;
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen /* some open files may have read partially written mails. now that
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen map syncing makes the new mails visible, we need to make sure the
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen partial data is flushed out of memory */
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (mail_index_refresh(map->view->index) < 0) {
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen mail_storage_set_internal_error(MAP_STORAGE(map));
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (mail_index_view_get_transaction_count(map->view) > 0) {
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen /* can't sync when there are transactions */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen fscked = mail_index_reset_fscked(map->view->index);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (mail_index_view_sync_commit(&ctx, &delayed_expunges) < 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mail_storage_set_internal_error(MAP_STORAGE(map));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmdbox_map_get_ext_hdr(struct mdbox_map *map, struct mail_index_view *view,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_get_header_ext(view, map->map_ext_id, &data, &data_size);
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen memcpy(hdr_r, data, I_MIN(data_size, sizeof(*hdr_r)));
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainenuint32_t mdbox_map_get_rebuild_count(struct mdbox_map *map)
const void *data;
int ret;
return ret;
int ret;
return ret;
const void *data;
return uid;
const void *data;
const void *data;
bool expunged;
int ret;
return ret;
if (*ref16_p != 0)
return atomic;
const char *reason)
int ret;
if (ret <= 0) {
int ret = 0;
return ret;
struct mdbox_map_transaction_context *
bool external)
bool success;
if (external)
if (success) {
flags);
return ctx;
const char *reason)
const void *data;
if (diff > 0) {
map_uid);
unsigned int i, count;
for (i = 0; i < count; i++) {
const void *data;
int ret = 0;
if (ret == 0)
return ret;
struct mdbox_map_append_context *
return ctx;
if (interval == 0)
bool notfound;
if (want_altpath) {
return FALSE;
return FALSE;
if (notfound)
return FALSE;
return FALSE;
return FALSE;
return TRUE;
bool last;
int ret;
return FALSE;
return FALSE;
return TRUE;
bool want_altpath,
int ret;
return TRUE;
return TRUE;
return !file_too_old;
unsigned int i, count;
for (i = 0; i < count; i++) {
return TRUE;
return FALSE;
static struct dbox_file_append_context *
unsigned int i, count;
return append;
return NULL;
struct dirent *d;
int ret = 0;
&file_id) < 0)
if (errno != 0) {
return ret;
unsigned int backwards_lookup_count;
bool retry_later;
if (want_altpath) {
seq++;
int ret;
if (ret > 0)
else if (ret < 0)
if (ret <= 0) {
if (!existing) {
unsigned int count;
unsigned int count;
struct dirent *d;
unsigned int i, count;
for (i = 0; i < count; i++) {
file_id--;
unsigned int i, count;
int ret = 0;
*first_map_uid_r = 0;
*last_map_uid_r = 0;
for (i = 0; i < count; i++) {
return ret;
for (i = j = 0; i < map_uids_count; i++) {
i_unreached();
unsigned int i, count;
for (i = 0; i < count; i++) {
unsigned int i, count;
for (i = 0; i < count; i++) {
unsigned int i, count;
for (i = 0; i < count; i++) {
for (i = 0; i < count; i++) {
int ret;
if (ret <= 0) {
if (uid_validity == 0)
return uid_validity;