36
36
timeout_secs, lock_r);
39
static int mail_index_lock(struct mail_index *index, int lock_type,
40
unsigned int timeout_secs, unsigned int *lock_id_r)
44
i_assert(lock_type == F_RDLCK || lock_type == F_WRLCK);
46
if (lock_type == F_RDLCK && index->lock_type != F_UNLCK) {
47
index->shared_lock_count++;
48
*lock_id_r = index->lock_id_counter;
50
} else if (lock_type == F_WRLCK && index->lock_type == F_WRLCK) {
51
index->excl_lock_count++;
52
*lock_id_r = index->lock_id_counter + 1;
59
/* file is already locked */
63
if (index->lock_method == FILE_LOCK_METHOD_DOTLOCK &&
64
!MAIL_INDEX_IS_IN_MEMORY(index)) {
65
/* FIXME: exclusive locking will rewrite the index file every
66
time. shouldn't really be needed.. reading doesn't require
68
if (lock_type == F_WRLCK)
71
index->shared_lock_count++;
72
index->lock_type = F_RDLCK;
73
*lock_id_r = index->lock_id_counter;
77
if (index->file_lock == NULL) {
78
i_assert(index->lock_type == F_UNLCK);
79
ret = mail_index_lock_fd(index, index->filepath, index->fd,
80
lock_type, timeout_secs,
83
i_assert(index->lock_type == F_RDLCK && lock_type == F_WRLCK);
84
ret = file_lock_try_update(index->file_lock, lock_type);
89
if (index->lock_type == F_UNLCK)
90
index->lock_id_counter += 2;
91
index->lock_type = lock_type;
93
if (lock_type == F_RDLCK) {
94
index->shared_lock_count++;
95
*lock_id_r = index->lock_id_counter;
97
index->excl_lock_count++;
98
*lock_id_r = index->lock_id_counter + 1;
104
39
void mail_index_flush_read_cache(struct mail_index *index, const char *path,
105
40
int fd, bool locked)
117
52
nfs_flush_read_cache_unlocked(path, fd);
121
int mail_index_lock_shared(struct mail_index *index, unsigned int *lock_id_r)
123
unsigned int timeout_secs;
126
timeout_secs = I_MIN(MAIL_INDEX_SHARED_LOCK_TIMEOUT,
127
index->max_lock_timeout_secs);
128
ret = mail_index_lock(index, F_RDLCK, timeout_secs, lock_id_r);
130
mail_index_flush_read_cache(index, index->filepath,
137
mail_index_set_error(index,
138
"Timeout (%us) while waiting for shared lock for index file %s",
139
timeout_secs, index->filepath);
140
index->index_lock_timeout = TRUE;
144
int mail_index_try_lock_exclusive(struct mail_index *index,
145
unsigned int *lock_id_r)
149
if ((ret = mail_index_lock(index, F_WRLCK, 0, lock_id_r)) > 0) {
150
mail_index_flush_read_cache(index, index->filepath,
156
void mail_index_unlock(struct mail_index *index, unsigned int *_lock_id)
158
unsigned int lock_id = *_lock_id;
162
if ((lock_id & 1) == 0) {
164
if (!mail_index_is_locked(index, lock_id)) {
165
/* unlocking some older generation of the index file.
166
we've already closed the file so just ignore this. */
170
i_assert(index->shared_lock_count > 0);
171
index->shared_lock_count--;
174
i_assert(lock_id == index->lock_id_counter + 1);
175
i_assert(index->excl_lock_count > 0);
176
i_assert(index->lock_type == F_WRLCK);
177
if (--index->excl_lock_count == 0 &&
178
index->shared_lock_count > 0) {
179
/* drop back to a shared lock. */
180
index->lock_type = F_RDLCK;
181
(void)file_lock_try_update(index->file_lock, F_RDLCK);
185
if (index->shared_lock_count == 0 && index->excl_lock_count == 0) {
186
index->lock_id_counter += 2;
187
index->lock_type = F_UNLCK;
188
if (index->lock_method != FILE_LOCK_METHOD_DOTLOCK) {
189
if (!MAIL_INDEX_IS_IN_MEMORY(index))
190
file_unlock(&index->file_lock);
192
i_assert(index->file_lock == NULL);
196
bool mail_index_is_locked(struct mail_index *index, unsigned int lock_id)
198
if ((index->lock_id_counter ^ lock_id) <= 1 && lock_id != 0) {
199
i_assert(index->lock_type != F_UNLCK);