Mercurial > dovecot > original-hg > dovecot-1.2
changeset 1679:c47ff2e6e946 HEAD
Support for upgrading from old index file with smaller header.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 11 Aug 2003 05:40:40 +0300 |
parents | 417558e2103e |
children | 6a5e548b47d8 |
files | src/lib-index/Makefile.am src/lib-index/mail-index-compress.c src/lib-index/mail-index-file.c src/lib-index/mail-index-open.c src/lib-index/mail-index.c |
diffstat | 5 files changed, 95 insertions(+), 190 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/Makefile.am Mon Aug 11 04:56:37 2003 +0300 +++ b/src/lib-index/Makefile.am Mon Aug 11 05:40:40 2003 +0300 @@ -11,7 +11,6 @@ mail-cache.c \ mail-custom-flags.c \ mail-index.c \ - mail-index-compress.c \ mail-index-file.c \ mail-index-fsck.c \ mail-index-open.c \
--- a/src/lib-index/mail-index-compress.c Mon Aug 11 04:56:37 2003 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -/* Copyright (C) 2002 Timo Sirainen */ - -#include "lib.h" -#include "write-full.h" -#include "mail-index.h" -#include "mail-index-util.h" -#include "mail-cache.h" - -#include <stdio.h> -#include <unistd.h> - -int mail_index_truncate(struct mail_index *index) -{ - uoff_t empty_space, truncate_threshold; - - i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE); - - if (index->mmap_full_length <= INDEX_FILE_MIN_SIZE(index) || - index->anon_mmap) - return TRUE; - - /* really truncate the file only when it's almost empty */ - empty_space = index->mmap_full_length - index->mmap_used_length; - truncate_threshold = - index->mmap_full_length / 100 * INDEX_TRUNCATE_PERCENTAGE; - - if (empty_space > truncate_threshold) { - index->mmap_full_length = index->mmap_used_length + - (empty_space * INDEX_TRUNCATE_KEEP_PERCENTAGE / 100); - - /* keep the size record-aligned */ - index->mmap_full_length -= (index->mmap_full_length - - index->header_size) % - sizeof(struct mail_index_record); - - if (index->mmap_full_length < INDEX_FILE_MIN_SIZE(index)) - index->mmap_full_length = INDEX_FILE_MIN_SIZE(index); - - if (ftruncate(index->fd, (off_t)index->mmap_full_length) < 0) - return index_set_syscall_error(index, "ftruncate()"); - - index->header->sync_id++; - } - - return TRUE; -} - -#if 0 -static int mail_index_copy_data(struct mail_index *index, - int fd, const char *path) -{ - struct mail_index_data_header data_hdr; - struct mail_index_data_record_header *rec_hdr; - struct mail_index_record *rec; - unsigned char *mmap_data; - size_t mmap_data_size; - uoff_t offset; - - mmap_data = mail_index_data_get_mmaped(index->data, &mmap_data_size); - if (mmap_data == NULL) - return FALSE; - - /* write data header */ - memset(&data_hdr, 0, sizeof(data_hdr)); - data_hdr.indexid = index->indexid; - if (write_full(fd, &data_hdr, sizeof(data_hdr)) < 0) { - index_file_set_syscall_error(index, path, "write_full()"); - return FALSE; - } - - /* now we'll begin the actual moving. keep rebuild-flag on - while doing it. */ - index->header->flags |= MAIL_INDEX_FLAG_REBUILD; - if (!mail_index_fmdatasync(index, index->header_size)) - return FALSE; - - offset = sizeof(data_hdr); - rec = index->lookup(index, 1); - while (rec != NULL) { - if (rec->data_position + sizeof(*rec_hdr) > mmap_data_size) { - index_set_corrupted(index, - "data_position points outside file"); - return FALSE; - } - - rec_hdr = (struct mail_index_data_record_header *) - (mmap_data + rec->data_position); - if (rec->data_position + rec_hdr->data_size > mmap_data_size) { - index_set_corrupted(index, - "data_size points outside file"); - return FALSE; - } - - if (write_full(fd, mmap_data + rec->data_position, - rec_hdr->data_size) < 0) { - index_file_set_syscall_error(index, path, - "write_full()"); - return FALSE; - } - - rec->data_position = offset; - offset += rec_hdr->data_size; - - rec = index->next(index, rec); - } - - /* update header */ - data_hdr.used_file_size = offset; - - if (lseek(fd, 0, SEEK_SET) < 0) - return index_file_set_syscall_error(index, path, "lseek()"); - - if (write_full(fd, &data_hdr, sizeof(data_hdr)) < 0) { - index_file_set_syscall_error(index, path, "write_full()"); - return FALSE; - } - - return TRUE; -} - -int mail_index_compress_data(struct mail_index *index) -{ - const char *temppath, *datapath; - int fd, failed; - - if (index->anon_mmap) - return TRUE; - - /* write the data into temporary file updating the offsets in index - while doing it. if we fail (especially if out of disk space/quota) - we'll simply fail and index is rebuilt later */ - if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE)) - return FALSE; - - fd = mail_index_create_temp_file(index, &temppath); - if (fd == -1) - return FALSE; - - failed = !mail_index_copy_data(index, fd, temppath); - - if (fdatasync(fd) < 0) { - index_file_set_syscall_error(index, temppath, "fdatasync()"); - failed = TRUE; - } - - if (close(fd) < 0) { - index_file_set_syscall_error(index, temppath, "close()"); - failed = TRUE; - } - - if (!failed) { - /* now, rename the temp file to new data file. but before that - reset indexid to make sure that other processes know the - data file is closed. */ - (void)mail_index_data_mark_file_deleted(index->data); - - mail_index_data_free(index->data); - - datapath = t_strconcat(index->filepath, DATA_FILE_PREFIX, NULL); - if (rename(temppath, datapath) < 0) { - if (ENOSPACE(errno)) - index->nodiskspace = TRUE; - - index_set_error(index, "rename(%s, %s) failed: %m", - temppath, datapath); - failed = TRUE; - } - } - - if (failed) { - if (unlink(temppath) < 0) { - index_file_set_syscall_error(index, temppath, - "unlink()"); - } - return FALSE; - } - - /* make sure the whole file is synced before removing rebuild-flag */ - if (!mail_index_fmdatasync(index, index->mmap_used_length)) - return FALSE; - - index->header->flags &= ~(MAIL_INDEX_FLAG_COMPRESS_DATA | - MAIL_INDEX_FLAG_REBUILD); - - return mail_index_data_open(index); -} -#endif
--- a/src/lib-index/mail-index-file.c Mon Aug 11 04:56:37 2003 +0300 +++ b/src/lib-index/mail-index-file.c Mon Aug 11 05:40:40 2003 +0300 @@ -1,9 +1,12 @@ /* Copyright (C) 2003 Timo Sirainen */ #include "lib.h" +#include "file-set-size.h" #include "mail-index.h" #include "mail-index-util.h" +#include <unistd.h> + struct mail_index_record *mail_index_next(struct mail_index *index, struct mail_index_record *rec) { @@ -110,7 +113,91 @@ return rec_p + idx; } -int mail_index_compress(struct mail_index *index __attr_unused__) +int mail_index_compress(struct mail_index *index) { + size_t diff; + off_t new_file_size; + + if (index->header_size >= sizeof(struct mail_index_header)) + return TRUE; + + if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE)) + return FALSE; + + /* make sure the file is large enough */ + diff = sizeof(struct mail_index_header) - index->header_size; + if (index->mmap_used_length + diff > index->mmap_full_length) { + /* mmap_update ftruncates the file to multiples of + mail_index_record, make sure we grow it enough here. */ + new_file_size = index->mmap_used_length + diff + + (sizeof(struct mail_index_record) - + (diff % sizeof(struct mail_index_record))); + if (file_set_size(index->fd, new_file_size) < 0) { + index_set_syscall_error(index, "file_set_size()"); + return FALSE; + } + + index->header->sync_id++; + if (!mail_index_mmap_update(index)) + return FALSE; + } + + /* if we break, we'll have to rebuild it completely */ + index->header->flags |= MAIL_INDEX_HDR_FLAG_REBUILD; + if (!mail_index_fmdatasync(index, index->header_size)) + return FALSE; + + memmove((char *) index->mmap_base + sizeof(struct mail_index_header), + (char *) index->mmap_base + index->header_size, + index->mmap_used_length - index->header_size); + memset((char *) index->mmap_base + index->header_size, 0, diff); + + index->mmap_used_length += diff; + index->header_size = sizeof(struct mail_index_header); + + index->header->header_size = sizeof(struct mail_index_header); + index->header->used_file_size += diff; + index->header->sync_id++; + + if (!mail_index_fmdatasync(index, index->mmap_used_length)) + return FALSE; + + index->header->flags &= ~MAIL_INDEX_HDR_FLAG_REBUILD; + return mail_index_mmap_update(index); +} + +int mail_index_truncate(struct mail_index *index) +{ + uoff_t empty_space, truncate_threshold; + + i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE); + + if (index->mmap_full_length <= INDEX_FILE_MIN_SIZE(index) || + index->anon_mmap) + return TRUE; + + /* really truncate the file only when it's almost empty */ + empty_space = index->mmap_full_length - index->mmap_used_length; + truncate_threshold = + index->mmap_full_length / 100 * INDEX_TRUNCATE_PERCENTAGE; + + if (empty_space > truncate_threshold) { + index->mmap_full_length = index->mmap_used_length + + (empty_space * INDEX_TRUNCATE_KEEP_PERCENTAGE / 100); + + /* keep the size record-aligned */ + index->mmap_full_length -= (index->mmap_full_length - + index->header_size) % + sizeof(struct mail_index_record); + + if (index->mmap_full_length < INDEX_FILE_MIN_SIZE(index)) + index->mmap_full_length = INDEX_FILE_MIN_SIZE(index); + + if (ftruncate(index->fd, (off_t)index->mmap_full_length) < 0) + return index_set_syscall_error(index, "ftruncate()"); + + index->header->sync_id++; + } + return TRUE; }
--- a/src/lib-index/mail-index-open.c Mon Aug 11 04:56:37 2003 +0300 +++ b/src/lib-index/mail-index-open.c Mon Aug 11 05:40:40 2003 +0300 @@ -71,6 +71,12 @@ { int rebuilt; + if (index->header_size < sizeof(struct mail_index_header)) { + /* upgrading from older index file. */ + if (!mail_index_compress(index)) + return FALSE; + } + if (!mail_cache_open_or_create(index)) return FALSE;
--- a/src/lib-index/mail-index.c Mon Aug 11 04:56:37 2003 +0300 +++ b/src/lib-index/mail-index.c Mon Aug 11 05:40:40 2003 +0300 @@ -323,7 +323,7 @@ /* locking index when cache is locked can deadlock */ i_assert(try_lock || index->lock_type == MAIL_LOCK_EXCLUSIVE || - !mail_cache_is_locked(index->cache)); + index->cache == NULL || !mail_cache_is_locked(index->cache)); if (index->inconsistent) { /* index is in inconsistent state and nothing else than