dovecot: Rewrite index lock handling.
dovecot at dovecot.org
dovecot at dovecot.org
Sun Jul 1 22:05:19 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/eca7e29dce0d
changeset: 5854:eca7e29dce0d
user: Timo Sirainen <tss at iki.fi>
date: Sun Jul 01 22:05:09 2007 +0300
description:
Rewrite index lock handling.
diffstat:
12 files changed, 120 insertions(+), 144 deletions(-)
src/lib-index/mail-index-lock.c | 24 ++++---
src/lib-index/mail-index-map.c | 49 ++++++++++-----
src/lib-index/mail-index-private.h | 24 ++++---
src/lib-index/mail-index-sync-update.c | 5 +
src/lib-index/mail-index-sync.c | 24 ++-----
src/lib-index/mail-index-transaction.c | 5 -
src/lib-index/mail-index-view-private.h | 6 -
src/lib-index/mail-index-view-sync.c | 2
src/lib-index/mail-index-view.c | 90 ++++++++---------------------
src/lib-index/mail-index-write.c | 6 -
src/lib-index/mail-index.c | 18 ++---
src/lib-index/mail-transaction-log-file.c | 11 +--
diffs (truncated from 778 to 300 lines):
diff -r d9f319a9d6e0 -r eca7e29dce0d src/lib-index/mail-index-lock.c
--- a/src/lib-index/mail-index-lock.c Sun Jul 01 18:39:51 2007 +0300
+++ b/src/lib-index/mail-index-lock.c Sun Jul 01 22:05:09 2007 +0300
@@ -42,11 +42,11 @@ static int mail_index_lock(struct mail_i
if (lock_type == F_RDLCK && index->lock_type != F_UNLCK) {
index->shared_lock_count++;
- *lock_id_r = index->lock_id;
+ *lock_id_r = index->lock_id_counter;
ret = 1;
} else if (lock_type == F_WRLCK && index->lock_type == F_WRLCK) {
index->excl_lock_count++;
- *lock_id_r = index->lock_id + 1;
+ *lock_id_r = index->lock_id_counter + 1;
ret = 1;
} else {
ret = 0;
@@ -67,7 +67,7 @@ static int mail_index_lock(struct mail_i
index->shared_lock_count++;
index->lock_type = F_RDLCK;
- *lock_id_r = index->lock_id;
+ *lock_id_r = index->lock_id_counter;
return 1;
}
@@ -103,15 +103,15 @@ static int mail_index_lock(struct mail_i
return ret;
if (index->lock_type == F_UNLCK)
- index->lock_id += 2;
+ index->lock_id_counter += 2;
index->lock_type = lock_type;
if (lock_type == F_RDLCK) {
index->shared_lock_count++;
- *lock_id_r = index->lock_id;
+ *lock_id_r = index->lock_id_counter;
} else {
index->excl_lock_count++;
- *lock_id_r = index->lock_id + 1;
+ *lock_id_r = index->lock_id_counter + 1;
}
return 1;
@@ -140,8 +140,12 @@ int mail_index_try_lock_exclusive(struct
return mail_index_lock(index, F_WRLCK, 0, lock_id_r);
}
-void mail_index_unlock(struct mail_index *index, unsigned int lock_id)
+void mail_index_unlock(struct mail_index *index, unsigned int *_lock_id)
{
+ unsigned int lock_id = *_lock_id;
+
+ *_lock_id = 0;
+
if ((lock_id & 1) == 0) {
/* shared lock */
if (!mail_index_is_locked(index, lock_id)) {
@@ -154,7 +158,7 @@ void mail_index_unlock(struct mail_index
index->shared_lock_count--;
} else {
/* exclusive lock */
- i_assert(lock_id == index->lock_id + 1);
+ i_assert(lock_id == index->lock_id_counter + 1);
i_assert(index->excl_lock_count > 0);
i_assert(index->lock_type == F_WRLCK);
if (--index->excl_lock_count == 0 &&
@@ -166,7 +170,7 @@ void mail_index_unlock(struct mail_index
}
if (index->shared_lock_count == 0 && index->excl_lock_count == 0) {
- index->lock_id += 2;
+ index->lock_id_counter += 2;
index->lock_type = F_UNLCK;
if (index->lock_method != FILE_LOCK_METHOD_DOTLOCK) {
if (!MAIL_INDEX_IS_IN_MEMORY(index))
@@ -178,7 +182,7 @@ void mail_index_unlock(struct mail_index
bool mail_index_is_locked(struct mail_index *index, unsigned int lock_id)
{
- if ((index->lock_id ^ lock_id) <= 1 && lock_id != 0) {
+ if ((index->lock_id_counter ^ lock_id) <= 1 && lock_id != 0) {
i_assert(index->lock_type != F_UNLCK);
return TRUE;
}
diff -r d9f319a9d6e0 -r eca7e29dce0d src/lib-index/mail-index-map.c
--- a/src/lib-index/mail-index-map.c Sun Jul 01 18:39:51 2007 +0300
+++ b/src/lib-index/mail-index-map.c Sun Jul 01 22:05:09 2007 +0300
@@ -653,11 +653,11 @@ struct mail_index_map *mail_index_map_al
}
static int mail_index_map_latest_file(struct mail_index *index,
- struct mail_index_map **map,
- unsigned int *lock_id_r)
+ struct mail_index_map **map)
{
struct mail_index_map *new_map;
struct stat st;
+ unsigned int lock_id;
uoff_t file_size;
bool use_mmap;
int ret;
@@ -673,7 +673,7 @@ static int mail_index_map_latest_file(st
}
/* the index file is still open, lock it */
- if (mail_index_lock_shared(index, lock_id_r) < 0)
+ if (mail_index_lock_shared(index, &lock_id) < 0)
return -1;
if (fstat(index->fd, &st) == 0)
@@ -681,6 +681,7 @@ static int mail_index_map_latest_file(st
else {
if (errno != ESTALE) {
mail_index_set_syscall_error(index, "fstat()");
+ mail_index_unlock(index, &lock_id);
return -1;
}
file_size = (uoff_t)-1;
@@ -692,8 +693,13 @@ static int mail_index_map_latest_file(st
file_size > MAIL_INDEX_MMAP_MIN_SIZE;
new_map = mail_index_map_alloc(index);
- ret = use_mmap ? mail_index_mmap(new_map, file_size) :
- mail_index_read_map(new_map, file_size);
+ if (use_mmap) {
+ new_map->lock_id = lock_id;
+ ret = mail_index_mmap(new_map, file_size);
+ } else {
+ ret = mail_index_read_map(new_map, file_size);
+ mail_index_unlock(index, &lock_id);
+ }
if (ret > 0) {
/* make sure the header is ok before using this mapping */
ret = mail_index_check_header(new_map);
@@ -720,16 +726,13 @@ static int mail_index_map_latest_file(st
}
int mail_index_map(struct mail_index *index,
- enum mail_index_sync_handler_type type,
- unsigned int *lock_id_r)
-{
- unsigned int lock_id = 0;
+ enum mail_index_sync_handler_type type)
+{
int ret;
i_assert(index->lock_type != F_WRLCK);
i_assert(!index->mapping);
- *lock_id_r = 0;
index->mapping = TRUE;
if (index->map == NULL)
@@ -749,7 +752,7 @@ int mail_index_map(struct mail_index *in
any reason, we'll fallback to updating the existing mapping
from transaction logs (which we'll also do even if the
reopening succeeds) */
- (void)mail_index_map_latest_file(index, &index->map, &lock_id);
+ (void)mail_index_map_latest_file(index, &index->map);
/* if we're creating the index file, we don't have any
logs yet */
@@ -758,12 +761,6 @@ int mail_index_map(struct mail_index *in
transaction log */
ret = mail_index_sync_map(&index->map, type, TRUE);
}
-
- /* we need the lock only if we didn't move the map to memory */
- if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map))
- *lock_id_r = lock_id;
- else
- mail_index_unlock(index, lock_id);
}
index->mapping = FALSE;
@@ -780,12 +777,27 @@ void mail_index_unmap(struct mail_index_
i_assert(map->refcount == 0);
mail_index_map_clear(map);
+ mail_index_map_unlock(map);
+
if (map->extension_pool != NULL)
pool_unref(map->extension_pool);
if (array_is_created(&map->keyword_idx_map))
array_free(&map->keyword_idx_map);
buffer_free(map->hdr_copy_buf);
i_free(map);
+}
+
+int mail_index_map_lock(struct mail_index_map *map)
+{
+ if (map->lock_id != 0 || MAIL_INDEX_MAP_IS_IN_MEMORY(map))
+ return 0;
+
+ return mail_index_lock_shared(map->index, &map->lock_id);
+}
+
+void mail_index_map_unlock(struct mail_index_map *map)
+{
+ mail_index_unlock(map->index, &map->lock_id);
}
static void mail_index_map_copy(struct mail_index_map *dest,
@@ -882,7 +894,10 @@ void mail_index_map_move_to_memory(struc
if (map->mmap_base == NULL)
return;
+ i_assert(map->lock_id != 0);
+
mail_index_map_copy(map, map);
+ mail_index_map_unlock(map);
if (munmap(map->mmap_base, map->mmap_size) < 0)
i_error("munmap(index map) failed: %m");
diff -r d9f319a9d6e0 -r eca7e29dce0d src/lib-index/mail-index-private.h
--- a/src/lib-index/mail-index-private.h Sun Jul 01 18:39:51 2007 +0300
+++ b/src/lib-index/mail-index-private.h Sun Jul 01 22:05:09 2007 +0300
@@ -117,6 +117,7 @@ struct mail_index_map {
void *mmap_base;
size_t mmap_size, mmap_used_size;
+ unsigned int lock_id;
buffer_t *buffer;
buffer_t *hdr_copy_buf;
@@ -175,7 +176,7 @@ struct mail_index {
uoff_t fsck_log_head_file_offset;
int lock_type, shared_lock_count, excl_lock_count;
- unsigned int lock_id;
+ unsigned int lock_id_counter;
enum file_lock_method lock_method;
struct file_lock *file_lock;
@@ -235,7 +236,7 @@ int mail_index_lock_shared(struct mail_i
/* Returns 1 = ok, 0 = already locked, -1 = error. */
int mail_index_try_lock_exclusive(struct mail_index *index,
unsigned int *lock_id_r);
-void mail_index_unlock(struct mail_index *index, unsigned int lock_id);
+void mail_index_unlock(struct mail_index *index, unsigned int *lock_id);
/* Returns TRUE if given lock_id is valid. */
bool mail_index_is_locked(struct mail_index *index, unsigned int lock_id);
@@ -249,22 +250,23 @@ struct mail_index_map *mail_index_map_al
file and/or it may read the latest changes from transaction log. The log is
read up to EOF, but non-synced expunges are skipped.
- If mapping required reading the index file, it's shared locked and lock_id
- is returned. Otherwise returned lock_id is 0.
+ If we mmap()ed the index file, the map is returned locked.
Returns 1 = ok, 0 = corrupted, -1 = error. If non-fatal problems were found,
1 is returned but index->fsck=TRUE is set. */
int mail_index_map(struct mail_index *index,
- enum mail_index_sync_handler_type type,
- unsigned int *lock_id_r);
-/* Return the latest index file's header. This should be used only when you
- don't want to see later changes from transaction log.
- Returns 1 = ok, 0 = corrupted, -1 = error. */
-int mail_index_get_last_written_header(struct mail_index *index,
- struct mail_index_header *hdr_r);
+ enum mail_index_sync_handler_type type);
/* Unreference given mapping and unmap it if it's dropped to zero. */
void mail_index_unmap(struct mail_index_map **map);
+
+/* Lock the map if the data is mmaped and map is unlocked. */
+int mail_index_map_lock(struct mail_index_map *map);
+/* Unlock the map if it's locked. */
+void mail_index_map_unlock(struct mail_index_map *map);
+
+/* Clone a map. The returned map is always in memory. */
struct mail_index_map *mail_index_map_clone(const struct mail_index_map *map);
+/* Move a mmaped map to memory. */
void mail_index_map_move_to_memory(struct mail_index_map *map);
uint32_t mail_index_map_lookup_ext(struct mail_index_map *map,
diff -r d9f319a9d6e0 -r eca7e29dce0d src/lib-index/mail-index-sync-update.c
--- a/src/lib-index/mail-index-sync-update.c Sun Jul 01 18:39:51 2007 +0300
+++ b/src/lib-index/mail-index-sync-update.c Sun Jul 01 22:05:09 2007 +0300
@@ -706,6 +706,9 @@ int mail_index_sync_map(struct mail_inde
i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
+ if (mail_index_map_lock(map) < 0)
+ return -1;
+
if (!force) {
/* see if we'd prefer to reopen the index file instead of
syncing the current map from the transaction log */
@@ -734,7 +737,7 @@ int mail_index_sync_map(struct mail_inde
start_offset = type == MAIL_INDEX_SYNC_HANDLER_FILE ?
map->hdr.log_file_tail_offset : map->hdr.log_file_head_offset;
- view = mail_index_view_open_with_map(map);
+ view = mail_index_view_open_with_map(index, map);
ret = mail_transaction_log_view_set(view->log_view,
map->hdr.log_file_seq, start_offset,
(uint32_t)-1, (uoff_t)-1, &reset);
More information about the dovecot-cvs
mailing list