Mercurial > dovecot > original-hg > dovecot-1.2
changeset 1817:f8c343c3d283 HEAD
We didn't notice cache compression immediately in other processes. Also some
other bugfixes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 20 Oct 2003 06:13:06 +0300 |
parents | af6c65fe9bf8 |
children | 7826e88c5679 |
files | src/lib-index/mail-cache.c src/lib-index/mail-index-file.c src/lib-index/mail-index.c src/lib-index/mail-index.h |
diffstat | 4 files changed, 89 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-cache.c Mon Oct 20 04:50:18 2003 +0300 +++ b/src/lib-index/mail-cache.c Mon Oct 20 06:13:06 2003 +0300 @@ -42,6 +42,8 @@ struct mail_cache_header { uint32_t indexid; + uint32_t sync_id; + uint32_t continued_record_count; uint32_t used_file_size; @@ -70,6 +72,7 @@ void *mmap_base; size_t mmap_length; uint32_t used_file_size; + uint32_t sync_id; struct mail_cache_header *header; @@ -249,6 +252,7 @@ if (cache->mmap_length < sizeof(struct mail_cache_header)) return mail_cache_set_corrupted(cache, "File too small"); cache->header = hdr = cache->mmap_base; + cache->sync_id = hdr->sync_id; if (cache->header->indexid != cache->index->indexid) { /* index id changed */ @@ -290,25 +294,33 @@ static int mmap_update_nocheck(struct mail_cache *cache, size_t offset, size_t size) { - if (cache->header != NULL && - cache->header->indexid != cache->index->indexid) { - /* indexid changed, most likely it was rebuilt. - try reopening. */ + struct stat st; + + /* if sync id has changed, the file has to be reopened. + note that if main index isn't locked, it may change again */ + if (cache->sync_id != cache->index->cache_sync_id && + cache->mmap_base != NULL) { if (!mail_cache_file_reopen(cache)) return -1; - - /* force mmap refresh */ - size = 0; } - if (size != 0 && offset < cache->mmap_length && - size <= cache->mmap_length - offset) { + if (offset < cache->mmap_length && + size <= cache->mmap_length - offset && + !cache->mmap_refresh) { /* already mapped */ - if (!cache->mmap_refresh) + if (size != 0 || cache->anon_mmap) return 1; - cache->mmap_refresh = FALSE; + /* requesting the whole file - see if we need to + re-mmap */ + if (fstat(cache->fd, &st) < 0) { + mail_cache_set_syscall_error(cache, "fstat()"); + return -1; + } + if ((uoff_t)st.st_size == cache->mmap_length) + return 1; } + cache->mmap_refresh = FALSE; if (cache->anon_mmap) return 1; @@ -346,14 +358,28 @@ static int mmap_update(struct mail_cache *cache, size_t offset, size_t size) { - int ret; + int synced, ret; + + for (synced = FALSE;; synced = TRUE) { + ret = mmap_update_nocheck(cache, offset, size); + if (ret > 0) + return TRUE; + if (ret < 0) + return FALSE; - ret = mmap_update_nocheck(cache, offset, size); - if (ret > 0) - return TRUE; - if (ret < 0) - return FALSE; - return mmap_verify_header(cache); + if (!mmap_verify_header(cache)) + return FALSE; + + /* see if cache file was rebuilt - do it only once to avoid + infinite looping */ + if (cache->header->sync_id == cache->index->cache_sync_id || + synced) + break; + + if (!mail_cache_file_reopen(cache)) + return FALSE; + } + return TRUE; } static int mail_cache_open_and_verify(struct mail_cache *cache, int silent) @@ -475,6 +501,7 @@ memset(&hdr, 0, sizeof(hdr)); hdr.indexid = index->indexid; + hdr.sync_id = index->cache_sync_id; hdr.used_file_size = uint32_to_nbo(sizeof(hdr)); cache = i_new(struct mail_cache, 1); @@ -688,6 +715,8 @@ /* update header */ hdr->indexid = cache->index->indexid; + hdr->sync_id = cache->sync_id = cache->index->cache_sync_id = + ++cache->index->header->cache_sync_id; hdr->used_file_size = uint32_to_nbo(offset); hdr->used_fields = used_fields; hdr->field_usage_start = uint32_to_nbo(ioloop_time); @@ -710,12 +739,19 @@ i_assert(cache->trans_ctx == NULL); + if (cache->anon_mmap) + return TRUE; + if (!cache->index->set_lock(cache->index, MAIL_LOCK_EXCLUSIVE)) return FALSE; if (mail_cache_lock(cache, TRUE) <= 0) return FALSE; +#ifdef DEBUG + i_warning("Compressing cache file %s", cache->filepath); +#endif + fd = file_dotlock_open(cache->filepath, NULL, MAIL_CACHE_LOCK_TIMEOUT, MAIL_CACHE_LOCK_STALE_TIMEOUT, NULL, NULL); if (fd == -1) { @@ -759,8 +795,12 @@ struct mail_cache_header hdr; int ret, fd; + i_assert(cache->index->lock_type == MAIL_LOCK_EXCLUSIVE); + memset(&hdr, 0, sizeof(hdr)); hdr.indexid = cache->index->indexid; + hdr.sync_id = cache->sync_id = cache->index->cache_sync_id + =++cache->index->header->cache_sync_id; hdr.used_file_size = uint32_to_nbo(sizeof(hdr)); cache->used_file_size = sizeof(hdr); @@ -840,9 +880,19 @@ } if (ret > 0) { - if (!mmap_verify_header(cache)) { + if (!mmap_update(cache, 0, 0)) { (void)mail_cache_unlock(cache); - ret = -1; + return -1; + } + if (cache->sync_id != cache->index->cache_sync_id) { + /* we have the cache file locked and sync_id still + doesn't match. it means we crashed between updating + cache file and updating sync_id in index header. + just update the sync_ids so they match. */ + i_warning("Updating broken sync_id in cache file %s", + cache->filepath); + cache->sync_id = cache->header->sync_id = + cache->index->cache_sync_id; } } return ret;
--- a/src/lib-index/mail-index-file.c Mon Oct 20 04:50:18 2003 +0300 +++ b/src/lib-index/mail-index-file.c Mon Oct 20 06:13:06 2003 +0300 @@ -142,7 +142,7 @@ return FALSE; } - index->header->sync_id++; + index->header->master_sync_id++; if (!mail_index_mmap_update(index)) return FALSE; } @@ -162,7 +162,7 @@ index->header->header_size = sizeof(struct mail_index_header); index->header->used_file_size += diff; - index->header->sync_id++; + index->header->master_sync_id++; if (!mail_index_fmdatasync(index, index->mmap_used_length)) return FALSE; @@ -201,7 +201,7 @@ if (ftruncate(index->fd, (off_t)index->mmap_full_length) < 0) return index_set_syscall_error(index, "ftruncate()"); - index->header->sync_id++; + index->header->master_sync_id++; } return TRUE;
--- a/src/lib-index/mail-index.c Mon Oct 20 04:50:18 2003 +0300 +++ b/src/lib-index/mail-index.c Mon Oct 20 06:13:06 2003 +0300 @@ -74,7 +74,9 @@ return FALSE; } - index->sync_id = hdr->sync_id; + index->master_sync_id = hdr->master_sync_id; + index->cache_sync_id = hdr->cache_sync_id; + index->log_sync_id = hdr->log_sync_id; index->sync_stamp = hdr->sync_stamp; index->sync_size = hdr->sync_size; index->mmap_used_length = hdr->used_file_size; @@ -89,6 +91,9 @@ if (index->mmap_base != NULL) { index->header = (struct mail_index_header *) index->mmap_base; + index->cache_sync_id = index->header->cache_sync_id; + index->log_sync_id = index->header->log_sync_id; + if (index->mmap_invalidate) { if (msync(index->mmap_base, index->mmap_used_length, @@ -99,7 +104,7 @@ } /* make sure file size hasn't changed */ - if (index->header->sync_id == index->sync_id) { + if (index->header->master_sync_id == index->master_sync_id) { index->mmap_used_length = index->header->used_file_size; if (index->mmap_used_length > index->mmap_full_length) { i_panic("Index file size was grown without " @@ -647,7 +652,7 @@ /* file size changed, let others know about it too by changing sync_id in header. */ - index->header->sync_id++; + index->header->master_sync_id++; if (!mail_index_mmap_update(index)) return FALSE;
--- a/src/lib-index/mail-index.h Mon Oct 20 04:50:18 2003 +0300 +++ b/src/lib-index/mail-index.h Mon Oct 20 06:13:06 2003 +0300 @@ -115,10 +115,12 @@ uint8_t compat_data[4]; uint32_t indexid; + uint32_t used_file_size; - uint32_t used_file_size; - uint32_t sync_id; /* re-mmap() when changed, required only - if file size is shrinked */ + /* file needs to be reopened if sync_ids change. */ + uint32_t master_sync_id; + uint32_t cache_sync_id; + uint32_t log_sync_id; uint32_t flags; @@ -281,7 +283,7 @@ char *mailbox_path; /* file/directory for mailbox location */ char *control_dir; /* destination for control files */ unsigned int indexid; - unsigned int sync_id; + unsigned int master_sync_id, cache_sync_id, log_sync_id; /* updated whenever exclusive lock is set/unset */ unsigned int excl_lock_counter; @@ -358,11 +360,11 @@ members.. */ #define MAIL_INDEX_PRIVATE_FILL \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, { 0, 0, 0 }, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, { 0, 0, 0 }, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0 #endif /* defaults - same as above but prefixed with mail_index_. */