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); 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); } 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) if (env->me_lfd == INVALID_HANDLE_VALUE)
return MDBX_SUCCESS; /* readonly database in readonly filesystem */ 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)) if (flock(env->me_lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER))
return MDBX_SUCCESS; return MDBX_SUCCESS;
return GetLastError(); return GetLastError();
@ -168,18 +168,18 @@ void mdbx_rdt_unlock(MDBX_env *env) {
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/* global `initial` lock for lockfile initialization, /* global `initial` lock for lockfile initialization,
* exclusive/shared locking first cacheline */ * exclusive/shared locking first cacheline */
/* FIXME: locking schema/algo descritpion. /* FIXME: locking schema/algo descritpion.
?-? = free ?-? = free
S-? = used S-? = used
E-? E-? = exclusive-read
?-S ?-S
?-E = middle ?-E = middle
S-S S-S
S-E = locked S-E = locked
E-S E-S
E-E = exclusive E-E = exclusive-write
*/ */
int mdbx_lck_init(MDBX_env *env) { int mdbx_lck_init(MDBX_env *env) {
@ -187,8 +187,9 @@ int mdbx_lck_init(MDBX_env *env) {
return MDBX_SUCCESS; return MDBX_SUCCESS;
} }
/* Seize state as exclusive (E-E and returns MDBX_RESULT_TRUE) /* Seize state as 'exclusive-write' (E-E and returns MDBX_RESULT_TRUE)
* or used (S-? and returns MDBX_RESULT_FALSE), otherwise returns an error */ * or as 'used' (S-? and returns MDBX_RESULT_FALSE), otherwise returns an error
*/
static int internal_seize_lck(HANDLE lfd) { static int internal_seize_lck(HANDLE lfd) {
int rc; int rc;
assert(lfd != INVALID_HANDLE_VALUE); assert(lfd != INVALID_HANDLE_VALUE);
@ -202,10 +203,10 @@ static int internal_seize_lck(HANDLE lfd) {
return rc; return rc;
} }
/* 3) now on ?-E (middle), try E-E (exclusive) */ /* 3) now on ?-E (middle), try E-E (exclusive-write) */
mdbx_jitter4testing(false); mdbx_jitter4testing(false);
if (flock(lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER)) 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) */ /* 5) still on ?-E (middle) */
rc = GetLastError(); rc = GetLastError();
@ -279,32 +280,43 @@ int mdbx_lck_seize(MDBX_env *env) {
return rc; return rc;
} }
int mdbx_lck_downgrade(MDBX_env *env) { int mdbx_lck_downgrade(MDBX_env *env, bool complete) {
/* Transite from exclusive state (E-E) to used (S-?) */ /* Transite from exclusive state (E-?) to used (S-?) */
assert(env->me_fd != INVALID_HANDLE_VALUE); assert(env->me_fd != INVALID_HANDLE_VALUE);
assert(env->me_lfd != 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)) if (!funlock(env->me_lfd, LCK_LOWER))
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_, 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)) { 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; 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)) if (!funlock(env->me_lfd, LCK_UPPER))
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_, mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
"S-E(locked) >> S-?(used)", GetLastError()); "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) { 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_fd != INVALID_HANDLE_VALUE);
assert(env->me_lfd != 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_, mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
"S-E(locked) >> ?-E(middle)", GetLastError()); "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); mdbx_jitter4testing(false);
if (flock(env->me_lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER)) 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) */ /* 5) still on ?-E (middle) */
int rc = GetLastError(); int rc = GetLastError();
@ -324,7 +336,7 @@ int mdbx_lck_upgrade(MDBX_env *env) {
if (rc != ERROR_SHARING_VIOLATION && rc != ERROR_LOCK_VIOLATION) { if (rc != ERROR_SHARING_VIOLATION && rc != ERROR_LOCK_VIOLATION) {
/* 6) something went wrong, report but continue */ /* 6) something went wrong, report but continue */
mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, 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) */ /* 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) { if (exclusive == NULL || *exclusive < 2) {
/* LY: downgrade lock only if exclusive access not requested. /* LY: downgrade lock only if exclusive access not requested.
* in case exclusive==1, just leave value as is. */ * in case exclusive==1, just leave value as is. */
rc = mdbx_lck_downgrade(env); rc = mdbx_lck_downgrade(env, true);
mdbx_debug("lck-downgrade: rc %i ", rc); 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) if (rc != MDBX_SUCCESS)
goto bailout; goto bailout;
}
} else { } else {
if (exclusive) { if (exclusive) {
/* LY: just indicate that is not an exclusive access. */ /* 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_init(MDBX_env *env);
int mdbx_lck_seize(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); int mdbx_lck_upgrade(MDBX_env *env);
void mdbx_lck_destroy(MDBX_env *env); void mdbx_lck_destroy(MDBX_env *env);