return FALSE;
if (ret == 0) {
/* doesn't exist, creating a new hash */
- if (mail_hash_lock_exclusive(hash, TRUE) <= 0)
+ if (mail_hash_lock_exclusive(hash,
+ MAIL_HASH_LOCK_FLAG_CREATE_MISSING) <= 0)
return FALSE;
ctx->thread_ctx.hash_trans =
mail_hash_transaction_begin(hash, status->messages);
if (can_use && !shared_lock) {
mail_hash_transaction_end(&hash_trans);
mail_hash_unlock(hash);
- if (mail_hash_lock_exclusive(hash, TRUE) <= 0)
+ if (mail_hash_lock_exclusive(hash,
+ MAIL_HASH_LOCK_FLAG_CREATE_MISSING) <= 0)
return FALSE;
shared_lock = TRUE;
goto again;
mail_thread_hash_cmp,
mail_thread_hash_remap,
tbox);
- if (mail_hash_lock_exclusive(hash, TRUE) <= 0)
+ if (mail_hash_lock_exclusive(hash,
+ MAIL_HASH_LOCK_FLAG_CREATE_MISSING) <= 0)
i_unreached();
ctx->thread_ctx.hash_trans =
mail_hash_transaction_begin(hash, 0);
/* init */
tbox->ctx = ctx = i_new(struct thread_context, 1);
- if (mail_hash_lock_exclusive(tbox->hash, FALSE) <= 0)
+ /* we can't wait the lock in here or we could deadlock. */
+ if (mail_hash_lock_exclusive(tbox->hash,
+ MAIL_HASH_LOCK_FLAG_TRY) <= 0)
return 0;
ctx->hash = tbox->hash;
}
static int
-mail_hash_lock_exclusive_fd(struct mail_hash *hash, bool create_missing)
+mail_hash_lock_exclusive_fd(struct mail_hash *hash,
+ enum mail_hash_lock_flags flags)
{
bool exists = TRUE;
int ret;
if (hash->index->lock_method == FILE_LOCK_METHOD_DOTLOCK) {
/* use dotlocking */
} else if (hash->fd == -1 && (ret = mail_hash_open_fd(hash)) <= 0) {
- if (ret < 0 || !create_missing)
+ if (ret < 0 ||
+ (flags & MAIL_HASH_LOCK_FLAG_CREATE_MISSING) == 0)
return ret;
/* the file doesn't exist - we need to use dotlocking */
exists = FALSE;
/* success / error */
return ret;
}
+ if ((flags & MAIL_HASH_LOCK_FLAG_TRY) != 0)
+ return 0;
/* already locked. if it's only read-locked, we can
overwrite the file. first wait for a shared lock. */
/* the file was created - we need to have it locked,
so retry this operation */
- (void)file_dotlock_delete(&hash->dotlock);
- return mail_hash_lock_exclusive_fd(hash,
- create_missing);
+ return mail_hash_lock_exclusive_fd(hash, flags);
}
}
/* other sessions are reading the file, we must not overwrite */
return 1;
}
-int mail_hash_lock_exclusive(struct mail_hash *hash, bool create_missing)
+int mail_hash_lock_exclusive(struct mail_hash *hash,
+ enum mail_hash_lock_flags flags)
{
+ bool create_missing = (flags & MAIL_HASH_LOCK_FLAG_CREATE_MISSING) != 0;
int ret;
i_assert(hash->lock_type == F_UNLCK);
return 1;
}
- if ((ret = mail_hash_lock_exclusive_fd(hash, create_missing)) <= 0) {
+ if ((ret = mail_hash_lock_exclusive_fd(hash, flags)) <= 0) {
mail_hash_unlock(hash);
return ret;
}
if (ret == 0 && create_missing) {
/* the broken file was unlinked - try again */
mail_hash_file_close(hash);
- return mail_hash_lock_exclusive(hash, create_missing);
+ return mail_hash_lock_exclusive(hash, flags);
}
return ret;
}
#define MAIL_HASH_RECORD_IS_DELETED(rec) \
((rec)->next_idx == (uint32_t)-1)
+enum mail_hash_lock_flags {
+ MAIL_HASH_LOCK_FLAG_TRY = 0x01,
+ MAIL_HASH_LOCK_FLAG_CREATE_MISSING = 0x02
+};
+
/* Returns 0 if the pointers are equal. */
typedef bool mail_hash_ctx_cmp_callback_t(struct mail_hash_transaction *trans,
const void *key, uint32_t idx,
/* Lock the file. Returns 1 if locking was successful, 0 if file doesn't exist,
-1 if error. */
int mail_hash_lock_shared(struct mail_hash *hash);
-int mail_hash_lock_exclusive(struct mail_hash *hash, bool create_missing);
+/* If FLAG_TRY_LOCK is set and file is already locked, return 0.
+ Otherwise return values are identical with mail_hash_lock_shared() */
+int mail_hash_lock_exclusive(struct mail_hash *hash,
+ enum mail_hash_lock_flags flags);
void mail_hash_unlock(struct mail_hash *hash);
struct mail_hash_transaction *