mirror of
https://github.com/isar/libmdbx.git
synced 2025-02-03 21:00:51 +08:00
mdbx: use flock() for share/exclusive lck.
This commit is contained in:
parent
1431e3e5bf
commit
6ee3aebc32
@ -74,6 +74,50 @@ static int mdbx_lck_op(mdbx_filehandle_t fd, int op, int lck, off_t offset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __inline int mdbx_lck_exclusive(int lfd) {
|
||||||
|
assert(lfd != INVALID_HANDLE_VALUE);
|
||||||
|
if (flock(lfd, LOCK_EX | LOCK_NB))
|
||||||
|
return errno;
|
||||||
|
return mdbx_lck_op(lfd, F_SETLK, F_WRLCK, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int mdbx_lck_shared(int lfd) {
|
||||||
|
assert(lfd != INVALID_HANDLE_VALUE);
|
||||||
|
while (flock(lfd, LOCK_SH)) {
|
||||||
|
int rc = errno;
|
||||||
|
if (rc != EINTR)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return mdbx_lck_op(lfd, F_SETLKW, F_RDLCK, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mdbx_lck_downgrade(MDB_env *env) { return mdbx_lck_shared(env->me_lfd); }
|
||||||
|
|
||||||
|
int mdbx_rpid_set(MDB_env *env) {
|
||||||
|
return mdbx_lck_op(env->me_lfd, F_SETLK, F_WRLCK, env->me_pid, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mdbx_rpid_clear(MDB_env *env) {
|
||||||
|
return mdbx_lck_op(env->me_lfd, F_SETLKW, F_UNLCK, env->me_pid, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checks reader by pid.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* MDBX_RESULT_TRUE, if pid is live (unable to acquire lock)
|
||||||
|
* MDBX_RESULT_FALSE, if pid is dead (lock acquired)
|
||||||
|
* or otherwise the errcode. */
|
||||||
|
int mdbx_rpid_check(MDB_env *env, mdbx_pid_t pid) {
|
||||||
|
int rc = mdbx_lck_op(env->me_lfd, F_GETLK, F_WRLCK, pid, 1);
|
||||||
|
if (rc == 0)
|
||||||
|
return MDBX_RESULT_FALSE;
|
||||||
|
if (rc < 0 && -rc == pid)
|
||||||
|
return MDBX_RESULT_TRUE;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int mdbx_mutex_failed(MDB_env *env, pthread_mutex_t *mutex, int rc);
|
static int mdbx_mutex_failed(MDB_env *env, pthread_mutex_t *mutex, int rc);
|
||||||
|
|
||||||
int mdbx_lck_init(MDB_env *env) {
|
int mdbx_lck_init(MDB_env *env) {
|
||||||
@ -117,8 +161,7 @@ bailout:
|
|||||||
void mdbx_lck_destroy(MDB_env *env) {
|
void mdbx_lck_destroy(MDB_env *env) {
|
||||||
if (env->me_lfd != INVALID_HANDLE_VALUE) {
|
if (env->me_lfd != INVALID_HANDLE_VALUE) {
|
||||||
/* try get exclusive access */
|
/* try get exclusive access */
|
||||||
if (env->me_lck &&
|
if (env->me_lck && mdbx_lck_exclusive(env->me_lfd) == 0) {
|
||||||
mdbx_lck_op(env->me_lfd, F_SETLK, F_WRLCK, 0, LCK_WHOLE) == 0) {
|
|
||||||
/* got exclusive, drown mutexes */
|
/* got exclusive, drown mutexes */
|
||||||
int rc = pthread_mutex_destroy(&env->me_lck->mti_rmutex);
|
int rc = pthread_mutex_destroy(&env->me_lck->mti_rmutex);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
@ -169,20 +212,20 @@ static int internal_seize_lck(int lfd) {
|
|||||||
assert(lfd != INVALID_HANDLE_VALUE);
|
assert(lfd != INVALID_HANDLE_VALUE);
|
||||||
|
|
||||||
/* try exclusive access */
|
/* try exclusive access */
|
||||||
int rc = mdbx_lck_op(lfd, F_SETLK, F_WRLCK, 0, 1);
|
int rc = mdbx_lck_exclusive(lfd);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
/* got exclusive */
|
/* got exclusive */
|
||||||
return MDBX_RESULT_TRUE;
|
return MDBX_RESULT_TRUE;
|
||||||
if (rc == EAGAIN || rc == EACCES || rc == EBUSY) {
|
if (rc == EAGAIN || rc == EACCES || rc == EBUSY || rc == EWOULDBLOCK) {
|
||||||
/* get shared access */
|
/* get shared access */
|
||||||
rc = mdbx_lck_op(lfd, F_SETLKW, F_RDLCK, 0, 1);
|
rc = mdbx_lck_shared(lfd);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
/* got shared, try exclusive again */
|
/* got shared, try exclusive again */
|
||||||
rc = mdbx_lck_op(lfd, F_SETLK, F_WRLCK, 0, 1);
|
rc = mdbx_lck_exclusive(lfd);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
/* now got exclusive */
|
/* now got exclusive */
|
||||||
return MDBX_RESULT_TRUE;
|
return MDBX_RESULT_TRUE;
|
||||||
if (rc == EAGAIN || rc == EACCES || rc == EBUSY)
|
if (rc == EAGAIN || rc == EACCES || rc == EBUSY || rc == EWOULDBLOCK)
|
||||||
/* unable exclusive, but stay shared */
|
/* unable exclusive, but stay shared */
|
||||||
return MDBX_RESULT_FALSE;
|
return MDBX_RESULT_FALSE;
|
||||||
}
|
}
|
||||||
@ -217,33 +260,6 @@ int mdbx_lck_seize(MDB_env *env) {
|
|||||||
return internal_seize_lck(env->me_lfd);
|
return internal_seize_lck(env->me_lfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_lck_downgrade(MDB_env *env) {
|
|
||||||
return mdbx_lck_op(env->me_lfd, F_SETLK, F_RDLCK, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdbx_rpid_set(MDB_env *env) {
|
|
||||||
return mdbx_lck_op(env->me_lfd, F_SETLK, F_WRLCK, env->me_pid, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdbx_rpid_clear(MDB_env *env) {
|
|
||||||
return mdbx_lck_op(env->me_lfd, F_SETLKW, F_UNLCK, env->me_pid, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Checks reader by pid.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* MDBX_RESULT_TRUE, if pid is live (unable to acquire lock)
|
|
||||||
* MDBX_RESULT_FALSE, if pid is dead (lock acquired)
|
|
||||||
* or otherwise the errcode. */
|
|
||||||
int mdbx_rpid_check(MDB_env *env, mdbx_pid_t pid) {
|
|
||||||
int rc = mdbx_lck_op(env->me_lfd, F_GETLK, F_WRLCK, pid, 1);
|
|
||||||
if (rc == 0)
|
|
||||||
return MDBX_RESULT_FALSE;
|
|
||||||
if (rc < 0 && -rc == pid)
|
|
||||||
return MDBX_RESULT_TRUE;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !__GLIBC_PREREQ(2, 12) && !defined(pthread_mutex_consistent)
|
#if !__GLIBC_PREREQ(2, 12) && !defined(pthread_mutex_consistent)
|
||||||
#define pthread_mutex_consistent(mutex) pthread_mutex_consistent_np(mutex)
|
#define pthread_mutex_consistent(mutex) pthread_mutex_consistent_np(mutex)
|
||||||
#endif
|
#endif
|
||||||
|
@ -68,6 +68,7 @@ typedef SSIZE_T ssize_t;
|
|||||||
#define THREAD_RESULT DWORD
|
#define THREAD_RESULT DWORD
|
||||||
#else
|
#else
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <sys/file.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user