mdbx: fix first-rdonly-blocker bug.

This commit is contained in:
Leo Yuriev 2017-05-26 20:28:09 +03:00
parent 5c3691eff1
commit 60fed8bbca
2 changed files with 16 additions and 7 deletions

View File

@ -337,7 +337,8 @@ typedef struct MDBX_lockinfo {
/* Format of this lock file. Must be set to MDBX_LOCK_FORMAT. */ /* Format of this lock file. Must be set to MDBX_LOCK_FORMAT. */
uint64_t mti_format; uint64_t mti_format;
/* Flags which environment was opened. */ /* Flags which environment was opened. */
uint64_t mti_envmode; uint32_t mti_envmode;
uint32_t mti_reserved;
#ifdef MDBX_OSAL_LOCK #ifdef MDBX_OSAL_LOCK
MDBX_OSAL_LOCK mti_wmutex; MDBX_OSAL_LOCK mti_wmutex;

View File

@ -4342,7 +4342,7 @@ int __cold mdbx_env_open_ex(MDBX_env *env, const char *path, unsigned flags,
const unsigned mode_flags = const unsigned mode_flags =
MDBX_WRITEMAP | MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC; MDBX_WRITEMAP | MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC;
if (lck_rc == MDBX_RESULT_TRUE) { if (lck_rc == MDBX_RESULT_TRUE) {
env->me_lck->mti_envmode = env->me_flags & mode_flags; env->me_lck->mti_envmode = env->me_flags & (mode_flags | MDBX_RDONLY);
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. */
@ -4356,11 +4356,19 @@ int __cold mdbx_env_open_ex(MDBX_env *env, const char *path, unsigned flags,
/* LY: just indicate that is not an exclusive access. */ /* LY: just indicate that is not an exclusive access. */
*exclusive = 0; *exclusive = 0;
} }
if ((env->me_flags & MDBX_RDONLY) == 0 && if ((env->me_flags & MDBX_RDONLY) == 0) {
((env->me_lck->mti_envmode ^ env->me_flags) & mode_flags) != 0) { while (env->me_lck->mti_envmode == MDBX_RDONLY) {
mdbx_error("current mode/flags incompatible with requested"); if (mdbx_atomic_compare_and_swap32(&env->me_lck->mti_envmode,
rc = MDBX_INCOMPATIBLE; MDBX_RDONLY,
goto bailout; env->me_flags & mode_flags))
break;
/* TODO: yield/relax cpu */
}
if ((env->me_lck->mti_envmode ^ env->me_flags) & mode_flags) {
mdbx_error("current mode/flags incompatible with requested");
rc = MDBX_INCOMPATIBLE;
goto bailout;
}
} }
} }