mdbx: fix/rework exclusive-locking for Windows.

Change-Id: I1b129a10ed7523024481480647317f1643f2ea70
This commit is contained in:
Leonid Yuriev 2017-07-19 09:12:46 +03:00 committed by Leo Yuriev
parent 17e8429a29
commit c8a5df650b
4 changed files with 43 additions and 26 deletions

View File

@ -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); }

View File

@ -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) */

View File

@ -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. */

View File

@ -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);