Mercurial > dovecot > original-hg > dovecot-1.2
changeset 7371:55712d36224b HEAD
Added support for dotlocks.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 07 Mar 2008 08:15:35 +0200 |
parents | d51565e31ceb |
children | 2201fd4548e3 |
files | src/plugins/fts-squat/squat-trie-private.h src/plugins/fts-squat/squat-trie.c src/plugins/fts-squat/squat-trie.h src/plugins/fts-squat/squat-uidlist.c |
diffstat | 4 files changed, 113 insertions(+), 41 deletions(-) [+] |
line wrap: on
line diff
--- a/src/plugins/fts-squat/squat-trie-private.h Fri Mar 07 07:38:41 2008 +0200 +++ b/src/plugins/fts-squat/squat-trie-private.h Fri Mar 07 08:15:35 2008 +0200 @@ -1,10 +1,12 @@ #ifndef SQUAT_TRIE_PRIVATE_H #define SQUAT_TRIE_PRIVATE_H +#include "file-dotlock.h" #include "squat-trie.h" #define SQUAT_TRIE_VERSION 2 #define SQUAT_TRIE_LOCK_TIMEOUT 60 +#define SQUAT_TRIE_DOTLOCK_STALE_TIMEOUT (15*60) struct squat_file_header { uint8_t version; @@ -114,12 +116,14 @@ size_t node_alloc_size; unsigned int unmapped_child_count; + enum squat_index_flags flags; enum file_lock_method lock_method; uint32_t uidvalidity; char *path; int fd; struct file_cache *file_cache; + struct dotlock_settings dotlock_set; uoff_t locked_file_size; const void *data; @@ -130,7 +134,6 @@ unsigned char default_normalize_map[256]; - unsigned int mmap_disable:1; unsigned int corrupted:1; };
--- a/src/plugins/fts-squat/squat-trie.c Fri Mar 07 07:38:41 2008 +0200 +++ b/src/plugins/fts-squat/squat-trie.c Fri Mar 07 08:15:35 2008 +0200 @@ -36,6 +36,7 @@ struct squat_uidlist_build_context *uidlist_build_ctx; struct file_lock *file_lock; + struct dotlock *dotlock; uint32_t first_uid; unsigned int compress_nodes:1; @@ -126,7 +127,7 @@ struct squat_trie * squat_trie_init(const char *path, uint32_t uidvalidity, - enum file_lock_method lock_method, bool mmap_disable) + enum file_lock_method lock_method, enum squat_index_flags flags) { struct squat_trie *trie; @@ -136,8 +137,14 @@ trie->fd = -1; trie->lock_method = lock_method; trie->uidvalidity = uidvalidity; - trie->mmap_disable = mmap_disable; + trie->flags = flags; squat_trie_normalize_map_build(trie); + + trie->dotlock_set.use_excl_lock = + (flags & SQUAT_INDEX_FLAG_DOTLOCK_USE_EXCL) != 0; + trie->dotlock_set.nfs_flush = (flags & SQUAT_INDEX_FLAG_NFS_FLUSH) != 0; + trie->dotlock_set.timeout = SQUAT_TRIE_LOCK_TIMEOUT; + trie->dotlock_set.stale_timeout = SQUAT_TRIE_DOTLOCK_STALE_TIMEOUT; return trie; } @@ -254,16 +261,26 @@ } static int squat_trie_lock(struct squat_trie *trie, int lock_type, - struct file_lock **file_lock_r) + struct file_lock **file_lock_r, + struct dotlock **dotlock_r) { int ret; + *file_lock_r = NULL; + *dotlock_r = NULL; + while (trie->fd != -1) { - ret = file_wait_lock(trie->fd, trie->path, lock_type, - trie->lock_method, SQUAT_TRIE_LOCK_TIMEOUT, - file_lock_r); + if (trie->lock_method != FILE_LOCK_METHOD_DOTLOCK) { + ret = file_wait_lock(trie->fd, trie->path, lock_type, + trie->lock_method, + SQUAT_TRIE_LOCK_TIMEOUT, + file_lock_r); + } else { + ret = file_dotlock_create(&trie->dotlock_set, + trie->path, 0, dotlock_r); + } if (ret == 0) { - i_error("file_wait_lock(%s) failed: %m", trie->path); + i_error("squat trie %s: Locking timed out", trie->path); return 0; } if (ret < 0) @@ -275,7 +292,10 @@ if (ret == 0) return 1; - file_unlock(file_lock_r); + if (*file_lock_r != NULL) + file_unlock(file_lock_r); + else + file_dotlock_delete(dotlock_r); if (ret < 0) return -1; @@ -1348,7 +1368,9 @@ squat_trie_iterate_deinit(iter); /* lock the trie before we rename uidlist */ - if (squat_trie_lock(ctx->trie, F_WRLCK, &ctx->file_lock) <= 0) + i_assert(ctx->file_lock == NULL && ctx->dotlock == NULL); + if (squat_trie_lock(ctx->trie, F_WRLCK, + &ctx->file_lock, &ctx->dotlock) <= 0) ret = -1; return squat_uidlist_rebuild_finish(rebuild_ctx, ret < 0); } @@ -1381,7 +1403,7 @@ } i_assert(trie->fd != -1); - if (trie->mmap_disable) { + if ((trie->flags & SQUAT_INDEX_FLAG_MMAP_DISABLE) != 0) { ret = pread_full(trie->fd, &trie->hdr, sizeof(trie->hdr), 0); if (ret <= 0) { if (ret < 0) { @@ -1424,19 +1446,24 @@ static int squat_trie_map(struct squat_trie *trie, bool building) { struct file_lock *file_lock = NULL; + struct dotlock *dotlock = NULL; bool changed; int ret; if (trie->fd != -1) { - if (squat_trie_lock(trie, F_RDLCK, &file_lock) <= 0) + if (squat_trie_lock(trie, F_RDLCK, &file_lock, &dotlock) <= 0) return -1; - if (trie->mmap_disable && trie->file_cache == NULL) + if ((trie->flags & SQUAT_INDEX_FLAG_MMAP_DISABLE) != 0 && + trie->file_cache == NULL) trie->file_cache = file_cache_new(trie->fd); } ret = squat_trie_map_header(trie); if (ret == 0) { - file_lock_free(&file_lock); + if (file_lock != NULL) + file_unlock(&file_lock); + else + file_dotlock_delete(&dotlock); squat_trie_delete(trie); squat_trie_close(trie); squat_trie_header_init(trie); @@ -1468,6 +1495,8 @@ if (file_lock != NULL) file_unlock(&file_lock); + if (dotlock != NULL) + file_dotlock_delete(&dotlock); if (ret < 0) return -1; @@ -1513,10 +1542,11 @@ static int squat_trie_write_lock(struct squat_trie_build_context *ctx) { - if (ctx->file_lock != NULL) + if (ctx->file_lock != NULL || ctx->dotlock != NULL) return 0; - if (squat_trie_lock(ctx->trie, F_WRLCK, &ctx->file_lock) <= 0) + if (squat_trie_lock(ctx->trie, F_WRLCK, + &ctx->file_lock, &ctx->dotlock) <= 0) return -1; return 0; } @@ -1540,13 +1570,19 @@ i_error("creat(%s) failed: %m", path); return -1; } - ret = file_wait_lock(fd, path, F_WRLCK, trie->lock_method, - SQUAT_TRIE_LOCK_TIMEOUT, &file_lock); - if (ret <= 0) { - if (ret == 0) - i_error("file_wait_lock(%s) failed: %m", path); - (void)close(fd); - return -1; + if (trie->lock_method != FILE_LOCK_METHOD_DOTLOCK) { + ret = file_wait_lock(fd, path, F_WRLCK, + trie->lock_method, + SQUAT_TRIE_LOCK_TIMEOUT, + &file_lock); + if (ret <= 0) { + if (ret == 0) { + i_error("file_wait_lock(%s) failed: %m", + path); + } + (void)close(fd); + return -1; + } } output = o_stream_create_fd(fd, 0, FALSE); @@ -1614,7 +1650,8 @@ if (ret < 0) { if (unlink(path) < 0 && errno != ENOENT) i_error("unlink(%s) failed: %m", path); - file_lock_free(&file_lock); + if (file_lock != NULL) + file_lock_free(&file_lock); } else { squat_trie_close_fd(trie); trie->fd = fd; @@ -1659,6 +1696,8 @@ else file_lock_free(&ctx->file_lock); } + if (ctx->dotlock != NULL) + file_dotlock_delete(&ctx->dotlock); squat_uidlist_build_deinit(&ctx->uidlist_build_ctx); i_free(ctx);
--- a/src/plugins/fts-squat/squat-trie.h Fri Mar 07 07:38:41 2008 +0200 +++ b/src/plugins/fts-squat/squat-trie.h Fri Mar 07 08:15:35 2008 +0200 @@ -4,6 +4,12 @@ #include "file-lock.h" #include "seq-range-array.h" +enum squat_index_flags { + SQUAT_INDEX_FLAG_MMAP_DISABLE = 0x01, + SQUAT_INDEX_FLAG_NFS_FLUSH = 0x02, + SQUAT_INDEX_FLAG_DOTLOCK_USE_EXCL = 0x04 +}; + enum squat_index_type { SQUAT_INDEX_TYPE_HEADER = 0x01, SQUAT_INDEX_TYPE_BODY = 0x02 @@ -13,7 +19,8 @@ struct squat_trie * squat_trie_init(const char *path, uint32_t uidvalidity, - enum file_lock_method lock_method, bool mmap_disable); + enum file_lock_method lock_method, + enum squat_index_flags flags); void squat_trie_deinit(struct squat_trie **trie); void squat_trie_refresh(struct squat_trie *trie);
--- a/src/plugins/fts-squat/squat-uidlist.c Fri Mar 07 07:38:41 2008 +0200 +++ b/src/plugins/fts-squat/squat-uidlist.c Fri Mar 07 08:15:35 2008 +0200 @@ -39,6 +39,7 @@ struct file_cache *file_cache; struct file_lock *file_lock; + struct dotlock *dotlock; uoff_t locked_file_size; void *mmap_base; @@ -438,7 +439,7 @@ return 1; } - if (!uidlist->trie->mmap_disable) { + if ((uidlist->trie->flags & SQUAT_INDEX_FLAG_MMAP_DISABLE) == 0) { if (mmap_hdr == NULL || uidlist->building || uidlist->mmap_size < mmap_hdr->used_file_size) { if (squat_uidlist_mmap(uidlist) < 0) @@ -466,7 +467,8 @@ uidlist->data = NULL; uidlist->data_size = 0; } - if (uidlist->file_cache == NULL && uidlist->trie->mmap_disable) + if (uidlist->file_cache == NULL && + (uidlist->trie->flags & SQUAT_INDEX_FLAG_MMAP_DISABLE) != 0) uidlist->file_cache = file_cache_new(uidlist->fd); return squat_uidlist_map_header(uidlist); } @@ -516,6 +518,8 @@ file_cache_free(&uidlist->file_cache); if (uidlist->file_lock != NULL) file_lock_free(&uidlist->file_lock); + if (uidlist->dotlock != NULL) + file_dotlock_delete(&uidlist->dotlock); if (uidlist->fd != -1) { if (close(uidlist->fd) < 0) i_error("close(%s) failed: %m", uidlist->path); @@ -569,13 +573,22 @@ for (;;) { i_assert(uidlist->fd != -1); i_assert(uidlist->file_lock == NULL); + i_assert(uidlist->dotlock == NULL); - ret = file_wait_lock(uidlist->fd, uidlist->path, F_WRLCK, - uidlist->trie->lock_method, - SQUAT_TRIE_LOCK_TIMEOUT, - &uidlist->file_lock); + if (uidlist->trie->lock_method != FILE_LOCK_METHOD_DOTLOCK) { + ret = file_wait_lock(uidlist->fd, uidlist->path, + F_WRLCK, + uidlist->trie->lock_method, + SQUAT_TRIE_LOCK_TIMEOUT, + &uidlist->file_lock); + } else { + ret = file_dotlock_create(&uidlist->trie->dotlock_set, + uidlist->path, 0, + &uidlist->dotlock); + } if (ret == 0) { - i_error("file_wait_lock(%s) failed: %m", uidlist->path); + i_error("squat uidlist %s: Locking timed out", + uidlist->path); return 0; } if (ret < 0) @@ -585,7 +598,10 @@ if (ret == 0) break; - file_unlock(&uidlist->file_lock); + if (uidlist->file_lock != NULL) + file_unlock(&uidlist->file_lock); + else + file_dotlock_delete(&uidlist->dotlock); if (ret < 0) return -1; @@ -642,18 +658,22 @@ struct squat_uidlist_build_context **ctx_r) { struct squat_uidlist_build_context *ctx; + int ret; i_assert(!uidlist->building); - if (squat_uidlist_open_or_create(uidlist) < 0) { + ret = squat_uidlist_open_or_create(uidlist); + if (ret == 0 && + lseek(uidlist->fd, uidlist->hdr.used_file_size, SEEK_SET) < 0) { + i_error("lseek(%s) failed: %m", uidlist->path); + ret = -1; + } + + if (ret < 0) { if (uidlist->file_lock != NULL) file_unlock(&uidlist->file_lock); - return -1; - } - if (lseek(uidlist->fd, uidlist->hdr.used_file_size, SEEK_SET) < 0) { - i_error("lseek(%s) failed: %m", uidlist->path); - if (uidlist->file_lock != NULL) - file_unlock(&uidlist->file_lock); + if (uidlist->dotlock != NULL) + file_dotlock_delete(&uidlist->dotlock); return -1; } @@ -828,7 +848,10 @@ i_assert(ctx->uidlist->building); ctx->uidlist->building = FALSE; - file_unlock(&ctx->uidlist->file_lock); + if (ctx->uidlist->file_lock != NULL) + file_unlock(&ctx->uidlist->file_lock); + else + file_dotlock_delete(&ctx->uidlist->dotlock); if (ctx->need_reopen) (void)squat_uidlist_open(ctx->uidlist);