diff options
Diffstat (limited to 'src/lib-index/mail-index-lock.c')
-rw-r--r-- | src/lib-index/mail-index-lock.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/lib-index/mail-index-lock.c b/src/lib-index/mail-index-lock.c new file mode 100644 index 0000000..cdf62e4 --- /dev/null +++ b/src/lib-index/mail-index-lock.c @@ -0,0 +1,63 @@ +/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */ + +/* + Locking should never fail or timeout. Exclusive locks must be kept as short + time as possible. Shared locks can be long living, so if we can't get + exclusive lock directly, we'll recreate the index. That means the shared + lock holders can keep using the old file. + + lock_id is used to figure out if acquired lock is still valid. When index + file is reopened, the lock_id can become invalid. It doesn't matter however, + as no-one's going to modify the old file anymore. + + lock_id also tells us if we're referring to a shared or an exclusive lock. + This allows us to drop back to shared locking once all exclusive locks + are dropped. Shared locks have even numbers, exclusive locks have odd numbers. + The number is increased by two every time the lock is dropped or index file + is reopened. +*/ + +#include "lib.h" +#include "nfs-workarounds.h" +#include "mail-index-private.h" + +#define MAIL_INDEX_SHARED_LOCK_TIMEOUT 120 + +int mail_index_lock_fd(struct mail_index *index, const char *path, int fd, + int lock_type, unsigned int timeout_secs, + struct file_lock **lock_r) +{ + const char *error; + int ret; + + if (fd == -1) { + i_assert(MAIL_INDEX_IS_IN_MEMORY(index)); + return 1; + } + + struct file_lock_settings lock_set = { + .lock_method = index->set.lock_method, + }; + ret = file_wait_lock(fd, path, lock_type, &lock_set, timeout_secs, + lock_r, &error); + if (ret < 0) + e_error(index->event, "%s", error); + return ret; +} + +void mail_index_flush_read_cache(struct mail_index *index, const char *path, + int fd, bool locked) +{ + if ((index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) == 0) + return; + + /* Assume flock() is emulated with fcntl(), because that's how most + OSes work nowadays. */ + if (locked && + (index->set.lock_method == FILE_LOCK_METHOD_FCNTL || + index->set.lock_method == FILE_LOCK_METHOD_FLOCK)) { + nfs_flush_read_cache_locked(path, fd); + } else { + nfs_flush_read_cache_unlocked(path, fd); + } +} |