mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-04 18:04:13 +08:00
mdbx: fix/rework exclusive-locking for Windows.
Change-Id: I1b129a10ed7523024481480647317f1643f2ea70
This commit is contained in:
parent
17e8429a29
commit
c8a5df650b
@ -91,7 +91,9 @@ static __inline int mdbx_lck_shared(int lfd) {
|
||||
return mdbx_lck_op(lfd, F_SETLKW, F_RDLCK, 0, 1);
|
||||
}
|
||||
|
||||
int mdbx_lck_downgrade(MDBX_env *env) { return mdbx_lck_shared(env->me_lfd); }
|
||||
int mdbx_lck_downgrade(MDBX_env *env, bool complete) {
|
||||
return complete ? mdbx_lck_shared(env->me_lfd) : MDBX_SUCCESS;
|
||||
}
|
||||
|
||||
int mdbx_lck_upgrade(MDBX_env *env) { return mdbx_lck_exclusive(env->me_lfd); }
|
||||
|
||||
|
@ -152,7 +152,7 @@ int mdbx_rdt_lock(MDBX_env *env) {
|
||||
if (env->me_lfd == INVALID_HANDLE_VALUE)
|
||||
return MDBX_SUCCESS; /* readonly database in readonly filesystem */
|
||||
|
||||
/* transite from S-? (used) to S-E (locked), e.g. exlcusive lock upper-part */
|
||||
/* transite from S-? (used) to S-E (locked), e.g. exclusive lock upper-part */
|
||||
if (flock(env->me_lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER))
|
||||
return MDBX_SUCCESS;
|
||||
return GetLastError();
|
||||
@ -168,18 +168,18 @@ void mdbx_rdt_unlock(MDBX_env *env) {
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* global `initial` lock for lockfile initialization,
|
||||
* exclusive/shared locking first cacheline */
|
||||
* exclusive/shared locking first cacheline */
|
||||
|
||||
/* FIXME: locking schema/algo descritpion.
|
||||
?-? = free
|
||||
S-? = used
|
||||
E-?
|
||||
E-? = exclusive-read
|
||||
?-S
|
||||
?-E = middle
|
||||
S-S
|
||||
S-E = locked
|
||||
E-S
|
||||
E-E = exclusive
|
||||
E-E = exclusive-write
|
||||
*/
|
||||
|
||||
int mdbx_lck_init(MDBX_env *env) {
|
||||
@ -187,8 +187,9 @@ int mdbx_lck_init(MDBX_env *env) {
|
||||
return MDBX_SUCCESS;
|
||||
}
|
||||
|
||||
/* Seize state as exclusive (E-E and returns MDBX_RESULT_TRUE)
|
||||
* or used (S-? and returns MDBX_RESULT_FALSE), otherwise returns an error */
|
||||
/* Seize state as 'exclusive-write' (E-E and returns MDBX_RESULT_TRUE)
|
||||
* or as 'used' (S-? and returns MDBX_RESULT_FALSE), otherwise returns an error
|
||||
*/
|
||||
static int internal_seize_lck(HANDLE lfd) {
|
||||
int rc;
|
||||
assert(lfd != INVALID_HANDLE_VALUE);
|
||||
@ -202,10 +203,10 @@ static int internal_seize_lck(HANDLE lfd) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* 3) now on ?-E (middle), try E-E (exclusive) */
|
||||
/* 3) now on ?-E (middle), try E-E (exclusive-write) */
|
||||
mdbx_jitter4testing(false);
|
||||
if (flock(lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER))
|
||||
return MDBX_RESULT_TRUE; /* 4) got E-E (exclusive), done */
|
||||
return MDBX_RESULT_TRUE /* 4) got E-E (exclusive-write), done */;
|
||||
|
||||
/* 5) still on ?-E (middle) */
|
||||
rc = GetLastError();
|
||||
@ -279,32 +280,43 @@ int mdbx_lck_seize(MDBX_env *env) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
int mdbx_lck_downgrade(MDBX_env *env) {
|
||||
/* Transite from exclusive state (E-E) to used (S-?) */
|
||||
int mdbx_lck_downgrade(MDBX_env *env, bool complete) {
|
||||
/* Transite from exclusive state (E-?) to used (S-?) */
|
||||
assert(env->me_fd != INVALID_HANDLE_VALUE);
|
||||
assert(env->me_lfd != INVALID_HANDLE_VALUE);
|
||||
|
||||
/* 1) must be at E-E (exclusive), transite to ?_E (middle) */
|
||||
/* 1) must be at E-E (exclusive-write) */
|
||||
if (!complete) {
|
||||
/* transite from E-E to E_? (exclusive-read) */
|
||||
if (!funlock(env->me_lfd, LCK_UPPER))
|
||||
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
|
||||
"E-E(exclusive-write) >> E-?(exclusive-read)", GetLastError());
|
||||
return MDBX_SUCCESS /* 2) now at E-? (exclusive-read), done */;
|
||||
}
|
||||
|
||||
/* 3) now at E-E (exclusive-write), transite to ?_E (middle) */
|
||||
if (!funlock(env->me_lfd, LCK_LOWER))
|
||||
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
|
||||
"E-E(exclusive) >> ?-E(middle)", GetLastError());
|
||||
"E-E(exclusive-write) >> ?-E(middle)", GetLastError());
|
||||
|
||||
/* 2) now at ?-E (middle), transite to S-E (locked) */
|
||||
/* 4) now at ?-E (middle), transite to S-E (locked) */
|
||||
if (!flock(env->me_lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER)) {
|
||||
int rc = GetLastError() /* 3) something went wrong, give up */;
|
||||
int rc = GetLastError() /* 5) something went wrong, give up */;
|
||||
mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
|
||||
"?-E(middle) >> S-E(locked)", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* 4) got S-E (locked), continue transition to S-? (used) */
|
||||
/* 6) got S-E (locked), continue transition to S-? (used) */
|
||||
if (!funlock(env->me_lfd, LCK_UPPER))
|
||||
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
|
||||
"S-E(locked) >> S-?(used)", GetLastError());
|
||||
|
||||
return MDBX_SUCCESS /* 5) now at S-? (used), done */;
|
||||
return MDBX_SUCCESS /* 7) now at S-? (used), done */;
|
||||
}
|
||||
|
||||
int mdbx_lck_upgrade(MDBX_env *env) {
|
||||
/* Transite from locked state (S-E) to exclusive (E-E) */
|
||||
/* Transite from locked state (S-E) to exclusive-write (E-E) */
|
||||
assert(env->me_fd != INVALID_HANDLE_VALUE);
|
||||
assert(env->me_lfd != INVALID_HANDLE_VALUE);
|
||||
|
||||
@ -313,10 +325,10 @@ int mdbx_lck_upgrade(MDBX_env *env) {
|
||||
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
|
||||
"S-E(locked) >> ?-E(middle)", GetLastError());
|
||||
|
||||
/* 3) now on ?-E (middle), try E-E (exclusive) */
|
||||
/* 3) now on ?-E (middle), try E-E (exclusive-write) */
|
||||
mdbx_jitter4testing(false);
|
||||
if (flock(env->me_lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER))
|
||||
return MDBX_RESULT_TRUE; /* 4) got E-E (exclusive), done */
|
||||
return MDBX_RESULT_TRUE; /* 4) got E-E (exclusive-write), done */
|
||||
|
||||
/* 5) still on ?-E (middle) */
|
||||
int rc = GetLastError();
|
||||
@ -324,7 +336,7 @@ int mdbx_lck_upgrade(MDBX_env *env) {
|
||||
if (rc != ERROR_SHARING_VIOLATION && rc != ERROR_LOCK_VIOLATION) {
|
||||
/* 6) something went wrong, report but continue */
|
||||
mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
|
||||
"?-E(middle) >> E-E(exclusive)", rc);
|
||||
"?-E(middle) >> E-E(exclusive-write)", rc);
|
||||
}
|
||||
|
||||
/* 7) still on ?-E (middle), try restore S-E (locked) */
|
||||
|
11
src/mdbx.c
11
src/mdbx.c
@ -4906,11 +4906,14 @@ int __cold mdbx_env_open_ex(MDBX_env *env, const char *path, unsigned flags,
|
||||
if (exclusive == NULL || *exclusive < 2) {
|
||||
/* LY: downgrade lock only if exclusive access not requested.
|
||||
* in case exclusive==1, just leave value as is. */
|
||||
rc = mdbx_lck_downgrade(env);
|
||||
mdbx_debug("lck-downgrade: rc %i ", rc);
|
||||
if (rc != MDBX_SUCCESS)
|
||||
goto bailout;
|
||||
rc = mdbx_lck_downgrade(env, true);
|
||||
mdbx_debug("lck-downgrade-full: rc %i ", rc);
|
||||
} else {
|
||||
rc = mdbx_lck_downgrade(env, false);
|
||||
mdbx_debug("lck-downgrade-partial: rc %i ", rc);
|
||||
}
|
||||
if (rc != MDBX_SUCCESS)
|
||||
goto bailout;
|
||||
} else {
|
||||
if (exclusive) {
|
||||
/* LY: just indicate that is not an exclusive access. */
|
||||
|
@ -491,7 +491,7 @@ void mdbx_osal_jitter(bool tiny);
|
||||
int mdbx_lck_init(MDBX_env *env);
|
||||
|
||||
int mdbx_lck_seize(MDBX_env *env);
|
||||
int mdbx_lck_downgrade(MDBX_env *env);
|
||||
int mdbx_lck_downgrade(MDBX_env *env, bool complete);
|
||||
int mdbx_lck_upgrade(MDBX_env *env);
|
||||
void mdbx_lck_destroy(MDBX_env *env);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user