Mercurial > dovecot > original-hg > dovecot-1.2
changeset 4247:9c3f19110538 HEAD
Don't compress cache file if it was just compressed by another process.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 03 May 2006 23:07:13 +0300 |
parents | 524a584f2302 |
children | f17622d1d927 |
files | src/lib-index/mail-cache-compress.c src/lib-index/mail-cache-private.h src/lib-index/mail-cache.c |
diffstat | 3 files changed, 78 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-cache-compress.c Wed May 03 22:43:25 2006 +0300 +++ b/src/lib-index/mail-cache-compress.c Wed May 03 23:07:13 2006 +0300 @@ -3,6 +3,9 @@ #include "lib.h" #include "buffer.h" #include "ostream.h" +#include "nfs-workarounds.h" +#include "read-full.h" +#include "close-keep-errno.h" #include "file-dotlock.h" #include "file-cache.h" #include "file-set-size.h" @@ -236,21 +239,52 @@ return mail_index_transaction_commit(&t, &seq, &offset); } +static int mail_cache_compress_has_file_changed(struct mail_cache *cache) +{ + struct mail_cache_header hdr; + unsigned int i; + int fd, ret; + + for (i = 0;; i++) { + fd = nfs_safe_open(cache->filepath, O_RDONLY); + if (fd == -1) { + if (errno == ENOENT) + return 0; + + mail_cache_set_syscall_error(cache, "open()"); + return -1; + } + + ret = read_full(fd, &hdr, sizeof(hdr)); + close_keep_errno(fd); + + if (ret >= 0) { + if (ret == 0) + return 0; + if (cache->need_compress_file_seq == (uint32_t)-1) { + /* previously it didn't exist */ + return 1; + } + return hdr.file_seq != cache->need_compress_file_seq; + } else if (errno != ESTALE || i >= NFS_ESTALE_RETRY_COUNT) { + mail_cache_set_syscall_error(cache, "read()"); + return -1; + } + } + return -1; +} + static int mail_cache_compress_locked(struct mail_cache *cache, struct mail_index_view *view) { struct dotlock *dotlock; mode_t old_mask; - int fd; + int fd, ret; /* get the latest info on fields */ if (mail_cache_header_fields_read(cache) < 0) return -1; -#ifdef DEBUG - i_warning("Compressing cache file %s", cache->filepath); -#endif - old_mask = umask(cache->index->mode ^ 0666); fd = file_dotlock_open(&cache->dotlock_settings, cache->filepath, 0, &dotlock); @@ -261,6 +295,21 @@ return -1; } + if ((ret = mail_cache_compress_has_file_changed(cache)) != 0) { + if (ret < 0) + return -1; + + /* was just compressed, forget this */ + cache->need_compress_file_seq = 0; + file_dotlock_delete(&dotlock); + return mail_cache_reopen(cache); + } + +#ifdef DEBUG + i_warning("Compressing cache file %s (%u)", + cache->filepath, cache->need_compress_file_seq); +#endif + if (cache->index->gid != (gid_t)-1 && fchown(fd, (uid_t)-1, cache->index->gid) < 0) { mail_cache_set_syscall_error(cache, "fchown()"); @@ -268,8 +317,6 @@ return -1; } - // FIXME: check that cache file wasn't just recreated - if (mail_cache_copy(cache, view, fd) < 0) { (void)file_dotlock_delete(&dotlock); return -1; @@ -294,7 +341,7 @@ if (mail_cache_header_fields_read(cache) < 0) return -1; - cache->need_compress = FALSE; + cache->need_compress_file_seq = 0; return 0; } @@ -329,5 +376,5 @@ bool mail_cache_need_compress(struct mail_cache *cache) { - return cache->need_compress; + return cache->need_compress_file_seq != 0; }
--- a/src/lib-index/mail-cache-private.h Wed May 03 22:43:25 2006 +0300 +++ b/src/lib-index/mail-cache-private.h Wed May 03 23:07:13 2006 +0300 @@ -140,11 +140,14 @@ unsigned int fields_count; struct hash_table *field_name_hash; /* name -> idx */ + /* 0 is no need for compression, otherwise the file sequence number + which we want compressed. */ + uint32_t need_compress_file_seq; + unsigned int *file_field_map; unsigned int file_fields_count; unsigned int locked:1; - unsigned int need_compress:1; unsigned int hdr_modified:1; unsigned int field_header_write_pending:1; };
--- a/src/lib-index/mail-cache.c Wed May 03 22:43:25 2006 +0300 +++ b/src/lib-index/mail-cache.c Wed May 03 23:07:13 2006 +0300 @@ -4,6 +4,7 @@ #include "array.h" #include "buffer.h" #include "hash.h" +#include "nfs-workarounds.h" #include "file-cache.h" #include "mmap-util.h" #include "write-full.h" @@ -71,17 +72,18 @@ const struct mail_index_ext *ext; if (MAIL_CACHE_IS_UNUSABLE(cache) && - (cache->need_compress || MAIL_INDEX_IS_IN_MEMORY(cache->index))) { + (cache->need_compress_file_seq != 0 || + MAIL_INDEX_IS_IN_MEMORY(cache->index))) { /* reopening does no good */ return 0; } mail_cache_file_close(cache); - cache->fd = open(cache->filepath, O_RDWR); + cache->fd = nfs_safe_open(cache->filepath, O_RDWR); if (cache->fd == -1) { if (errno == ENOENT) - cache->need_compress = TRUE; + cache->need_compress_file_seq = (uint32_t)-1; else mail_cache_set_syscall_error(cache, "open()"); return -1; @@ -103,7 +105,7 @@ file_seq really is corrupted. either way, this shouldn't happen often so we'll just mark cache to be compressed later which fixes this. */ - cache->need_compress = TRUE; + cache->need_compress_file_seq = cache->hdr->file_seq; mail_index_view_close(&view); return 0; } @@ -197,7 +199,9 @@ cache->hdr = cache->data; if (offset == 0 && !mail_cache_verify_header(cache)) { - cache->need_compress = TRUE; + cache->need_compress_file_seq = + cache->hdr->file_seq != 0 ? + cache->hdr->file_seq : (uint32_t)-1; return -1; } return 0; @@ -216,7 +220,7 @@ if (cache->fd == -1) { /* unusable, waiting for compression or index is in memory */ - i_assert(cache->need_compress || + i_assert(cache->need_compress_file_seq != 0 || MAIL_INDEX_IS_IN_MEMORY(cache->index)); return -1; } @@ -237,7 +241,9 @@ cache->hdr = cache->mmap_base; if (!mail_cache_verify_header(cache)) { - cache->need_compress = TRUE; + cache->need_compress_file_seq = + cache->hdr->file_seq != 0 ? + cache->hdr->file_seq : (uint32_t)-1; return -1; } @@ -249,10 +255,10 @@ if (MAIL_INDEX_IS_IN_MEMORY(cache->index)) return 0; - cache->fd = open(cache->filepath, O_RDWR); + cache->fd = nfs_safe_open(cache->filepath, O_RDWR); if (cache->fd == -1) { if (errno == ENOENT) { - cache->need_compress = TRUE; + cache->need_compress_file_seq = (uint32_t)-1; return 0; } @@ -327,7 +333,7 @@ struct mail_cache *cache; cache = mail_cache_alloc(index); - cache->need_compress = TRUE; + cache->need_compress_file_seq = (uint32_t)-1; return cache; } @@ -449,14 +455,14 @@ if (cont_percentage >= COMPRESS_CONTINUED_PERCENTAGE && hdr->used_file_size >= COMPRESS_MIN_SIZE) { /* too many continued rows, compress */ - cache->need_compress = TRUE; + cache->need_compress_file_seq = hdr->file_seq; } /* see if we've reached the max. deleted space in file */ max_del_space = hdr->used_file_size / 100 * COMPRESS_PERCENTAGE; if (hdr->deleted_space >= max_del_space && hdr->used_file_size >= COMPRESS_MIN_SIZE) - cache->need_compress = TRUE; + cache->need_compress_file_seq = hdr->file_seq; } int mail_cache_unlock(struct mail_cache *cache)