mdbx: add mdbx_get_errno_checked().

This commit is contained in:
Leo Yuriev 2017-05-15 12:08:04 +03:00
parent 533e01cc93
commit 00081298d6
3 changed files with 102 additions and 86 deletions

View File

@ -128,7 +128,7 @@ static __inline BOOL funlock(mdbx_filehandle_t fd, off_t offset, size_t bytes) {
int mdbx_txn_lock(MDB_env *env) {
if (flock(env->me_fd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_BODY))
return MDB_SUCCESS;
return GetLastError();
return mdbx_get_errno_checked();
}
void mdbx_txn_unlock(MDB_env *env) {
@ -154,7 +154,7 @@ int mdbx_rdt_lock(MDB_env *env) {
/* transite from S-? (used) to S-E (locked), e.g. exlcusive lock upper-part */
if (flock(env->me_lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER))
return MDB_SUCCESS;
return GetLastError();
return mdbx_get_errno_checked();
}
void mdbx_rdt_unlock(MDB_env *env) {
@ -195,7 +195,7 @@ static int internal_seize_lck(HANDLE lfd) {
/* 1) now on ?-? (free), get ?-E (middle) */
mdbx_jitter4testing(false);
if (!flock(lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER)) {
rc = GetLastError() /* 2) something went wrong, give up */;
rc = mdbx_get_errno_checked() /* 2) something went wrong, give up */;
mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
"?-?(free) >> ?-E(middle)", rc);
return rc;
@ -207,22 +207,21 @@ static int internal_seize_lck(HANDLE lfd) {
return MDBX_RESULT_TRUE; /* 4) got E-E (exclusive), done */
/* 5) still on ?-E (middle) */
rc = GetLastError();
rc = mdbx_get_errno_checked();
mdbx_jitter4testing(false);
if (rc != ERROR_SHARING_VIOLATION && rc != ERROR_LOCK_VIOLATION) {
/* 6) something went wrong, give up */
if (!funlock(lfd, LCK_UPPER)) {
rc = GetLastError();
if (!funlock(lfd, LCK_UPPER))
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
"?-E(middle) >> ?-?(free)", rc);
}
"?-E(middle) >> ?-?(free)", GetLastError());
return rc;
}
/* 7) still on ?-E (middle), try S-E (locked) */
mdbx_jitter4testing(false);
rc = flock(lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER) ? MDBX_RESULT_FALSE
: GetLastError();
rc = flock(lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER)
? MDBX_RESULT_FALSE
: mdbx_get_errno_checked();
mdbx_jitter4testing(false);
if (rc != MDBX_RESULT_FALSE)
@ -231,11 +230,9 @@ static int internal_seize_lck(HANDLE lfd) {
/* 8) now on S-E (locked) or still on ?-E (middle),
* transite to S-? (used) or ?-? (free) */
if (!funlock(lfd, LCK_UPPER)) {
rc = GetLastError();
if (!funlock(lfd, LCK_UPPER))
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
"X-E(locked/middle) >> X-?(used/free)", rc);
}
"X-E(locked/middle) >> X-?(used/free)", GetLastError());
/* 9) now on S-? (used, DONE) or ?-? (free, FAILURE) */
return rc;
@ -249,7 +246,7 @@ int mdbx_lck_seize(MDB_env *env) {
/* LY: without-lck mode (e.g. on read-only filesystem) */
mdbx_jitter4testing(false);
if (!flock(env->me_fd, LCK_SHARED | LCK_DONTWAIT, LCK_WHOLE)) {
rc = GetLastError();
rc = mdbx_get_errno_checked();
mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, "without-lck", rc);
return rc;
}
@ -266,18 +263,16 @@ int mdbx_lck_seize(MDB_env *env) {
* - we can't lock meta-pages, otherwise other process could get an error
* while opening db in valid (non-conflict) mode. */
if (!flock(env->me_fd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_BODY)) {
rc = GetLastError();
rc = mdbx_get_errno_checked();
mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
"lock-against-without-lck", rc);
mdbx_jitter4testing(false);
mdbx_lck_destroy(env);
} else {
mdbx_jitter4testing(false);
if (!funlock(env->me_fd, LCK_BODY)) {
rc = GetLastError();
if (!funlock(env->me_fd, LCK_BODY))
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
"unlock-against-without-lck", rc);
}
"unlock-against-without-lck", GetLastError());
}
}
@ -291,24 +286,20 @@ int mdbx_lck_downgrade(MDB_env *env) {
if (env->me_lfd != INVALID_HANDLE_VALUE) {
/* 1) must be at E-E (exclusive), transite to ?_E (middle) */
if (!funlock(env->me_lfd, LCK_LOWER)) {
rc = GetLastError();
if (!funlock(env->me_lfd, LCK_LOWER))
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
"E-E(exclusive) >> ?-E(middle)", rc);
}
"E-E(exclusive) >> ?-E(middle)", GetLastError());
/* 2) now at ?-E (middle), transite to S-E (locked) */
if (!flock(env->me_lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER)) {
rc = GetLastError() /* 3) something went wrong, give up */;
rc = mdbx_get_errno_checked() /* 3) something went wrong, give up */;
return rc;
}
/* 4) got S-E (locked), continue transition to S-? (used) */
if (!funlock(env->me_lfd, LCK_UPPER)) {
rc = GetLastError();
if (!funlock(env->me_lfd, LCK_UPPER))
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
"S-E(locked) >> S-?(used)", rc);
}
"S-E(locked) >> S-?(used)", GetLastError());
}
return MDB_SUCCESS /* 5) now at S-? (used), done */;
}
@ -320,14 +311,14 @@ void mdbx_lck_destroy(MDB_env *env) {
/* double `unlock` for robustly remove overlapped shared/exclusive locks */
while (funlock(env->me_lfd, LCK_LOWER))
;
rc = GetLastError();
rc = mdbx_get_errno_checked();
assert(rc == ERROR_NOT_LOCKED);
(void)rc;
SetLastError(ERROR_SUCCESS);
while (funlock(env->me_lfd, LCK_UPPER))
;
rc = GetLastError();
rc = mdbx_get_errno_checked();
assert(rc == ERROR_NOT_LOCKED);
(void)rc;
SetLastError(ERROR_SUCCESS);
@ -338,21 +329,21 @@ void mdbx_lck_destroy(MDB_env *env) {
* releases such locks via deferred queues) */
while (funlock(env->me_fd, LCK_BODY))
;
rc = GetLastError();
rc = mdbx_get_errno_checked();
assert(rc == ERROR_NOT_LOCKED);
(void)rc;
SetLastError(ERROR_SUCCESS);
while (funlock(env->me_fd, LCK_META))
;
rc = GetLastError();
rc = mdbx_get_errno_checked();
assert(rc == ERROR_NOT_LOCKED);
(void)rc;
SetLastError(ERROR_SUCCESS);
while (funlock(env->me_fd, LCK_WHOLE))
;
rc = GetLastError();
rc = mdbx_get_errno_checked();
assert(rc == ERROR_NOT_LOCKED);
(void)rc;
SetLastError(ERROR_SUCCESS);
@ -386,7 +377,7 @@ int mdbx_rpid_check(MDB_env *env, mdbx_pid_t pid) {
rc = WaitForSingleObject(hProcess, 0);
CloseHandle(hProcess);
} else {
rc = GetLastError();
rc = mdbx_get_errno_checked();
}
switch (rc) {

View File

@ -22,7 +22,7 @@ static int waitstatus2errcode(DWORD result) {
case WAIT_OBJECT_0:
return MDB_SUCCESS;
case WAIT_FAILED:
return GetLastError();
return mdbx_get_errno_checked();
case WAIT_ABANDONED:
return ERROR_ABANDONED_WAIT_0;
case WAIT_IO_COMPLETION:
@ -167,7 +167,7 @@ void mdbx_memalign_free(void *ptr) {
int mdbx_mutex_init(mdbx_mutex_t *mutex) {
#if defined(_WIN32) || defined(_WIN64)
*mutex = CreateMutex(NULL, FALSE, NULL);
return *mutex ? MDB_SUCCESS : GetLastError();
return *mutex ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return pthread_mutex_init(mutex, NULL);
#endif
@ -175,7 +175,7 @@ int mdbx_mutex_init(mdbx_mutex_t *mutex) {
int mdbx_mutex_destroy(mdbx_mutex_t *mutex) {
#if defined(_WIN32) || defined(_WIN64)
return CloseHandle(*mutex) ? MDB_SUCCESS : GetLastError();
return CloseHandle(*mutex) ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return pthread_mutex_destroy(mutex);
#endif
@ -192,7 +192,7 @@ int mdbx_mutex_lock(mdbx_mutex_t *mutex) {
int mdbx_mutex_unlock(mdbx_mutex_t *mutex) {
#if defined(_WIN32) || defined(_WIN64)
return ReleaseMutex(*mutex) ? MDB_SUCCESS : GetLastError();
return ReleaseMutex(*mutex) ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return pthread_mutex_unlock(mutex);
#endif
@ -203,7 +203,7 @@ int mdbx_mutex_unlock(mdbx_mutex_t *mutex) {
int mdbx_cond_init(mdbx_cond_t *cond) {
#if defined(_WIN32) || defined(_WIN64)
*cond = CreateEvent(NULL, FALSE, FALSE, NULL);
return *cond ? MDB_SUCCESS : GetLastError();
return *cond ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return pthread_cond_init(cond, NULL);
#endif
@ -212,7 +212,7 @@ int mdbx_cond_init(mdbx_cond_t *cond) {
#ifndef mdbx_cond_destroy
int mdbx_cond_destroy(mdbx_cond_t *cond) {
#if defined(_WIN32) || defined(_WIN64)
return CloseHandle(*cond) ? MDB_SUCCESS : GetLastError();
return CloseHandle(*cond) ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return pthread_cond_destroy(cond);
#endif
@ -221,7 +221,7 @@ int mdbx_cond_destroy(mdbx_cond_t *cond) {
int mdbx_cond_signal(mdbx_cond_t *cond) {
#if defined(_WIN32) || defined(_WIN64)
return SetEvent(*cond) ? MDB_SUCCESS : GetLastError();
return SetEvent(*cond) ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return pthread_cond_signal(cond);
#endif
@ -286,14 +286,14 @@ int mdbx_openfile(const char *pathname, int flags, mode_t mode,
CreationDisposition, FlagsAndAttributes, NULL);
if (*fd == INVALID_HANDLE_VALUE)
return GetLastError();
if ((flags & O_CREAT) && GetLastError() != ERROR_ALREADY_EXISTS) {
return mdbx_get_errno_checked();
if ((flags & O_CREAT) && mdbx_get_errno_checked() != ERROR_ALREADY_EXISTS) {
/* set FILE_ATTRIBUTE_NOT_CONTENT_INDEXED for new file */
DWORD FileAttributes = GetFileAttributesA(pathname);
if (FileAttributes == INVALID_FILE_ATTRIBUTES ||
!SetFileAttributesA(pathname, FileAttributes |
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)) {
int rc = GetLastError();
int rc = mdbx_get_errno_checked();
CloseHandle(*fd);
*fd = INVALID_HANDLE_VALUE;
return rc;
@ -318,7 +318,7 @@ int mdbx_openfile(const char *pathname, int flags, mode_t mode,
int mdbx_closefile(mdbx_filehandle_t fd) {
#if defined(_WIN32) || defined(_WIN64)
return CloseHandle(fd) ? MDB_SUCCESS : GetLastError();
return CloseHandle(fd) ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return (close(fd) == 0) ? MDB_SUCCESS : errno;
#endif
@ -336,7 +336,7 @@ int mdbx_pread(mdbx_filehandle_t fd, void *buf, size_t bytes, off_t offset) {
DWORD read = 0;
if (unlikely(!ReadFile(fd, buf, (DWORD)bytes, &read, &ov))) {
int rc = GetLastError();
int rc = mdbx_get_errno_checked();
return (rc == MDB_SUCCESS) ? /* paranoia */ ERROR_READ_FAULT : rc;
}
#else
@ -363,7 +363,7 @@ int mdbx_pwrite(mdbx_filehandle_t fd, const void *buf, size_t bytes,
DWORD written;
if (likely(WriteFile(fd, buf, (DWORD)bytes, &written, &ov)))
return (bytes == written) ? MDB_SUCCESS : ERROR_WRITE_FAULT;
return GetLastError();
return mdbx_get_errno_checked();
#else
int rc;
ssize_t written;
@ -418,7 +418,7 @@ int mdbx_write(mdbx_filehandle_t fd, const void *buf, size_t bytes) {
#if defined(_WIN32) || defined(_WIN64)
DWORD written;
if (unlikely(!WriteFile(fd, ptr, (DWORD)chunk, &written, NULL)))
return GetLastError();
return mdbx_get_errno_checked();
#else
ssize_t written = write(fd, ptr, chunk);
if (written < 0) {
@ -452,7 +452,7 @@ int mdbx_write(mdbx_filehandle_t fd, const void *buf, size_t bytes) {
int mdbx_filesync(mdbx_filehandle_t fd, bool fullsync) {
#if defined(_WIN32) || defined(_WIN64)
(void)fullsync;
return FlushFileBuffers(fd) ? MDB_SUCCESS : GetLastError();
return FlushFileBuffers(fd) ? MDB_SUCCESS : mdbx_get_errno_checked();
#elif __GLIBC_PREREQ(2, 16) || _BSD_SOURCE || _XOPEN_SOURCE || \
(__GLIBC_PREREQ(2, 8) && _POSIX_C_SOURCE >= 200112L)
for (;;) {
@ -478,7 +478,7 @@ int mdbx_filesize(mdbx_filehandle_t fd, off_t *length) {
#if defined(_WIN32) || defined(_WIN64)
BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle(fd, &info))
return GetLastError();
return mdbx_get_errno_checked();
*length = info.nFileSizeLow | (uint64_t)info.nFileIndexHigh << 32;
#else
struct stat st;
@ -497,7 +497,7 @@ int mdbx_ftruncate(mdbx_filehandle_t fd, off_t length) {
li.QuadPart = length;
return (SetFilePointerEx(fd, li, NULL, FILE_BEGIN) && SetEndOfFile(fd))
? MDB_SUCCESS
: GetLastError();
: mdbx_get_errno_checked();
#else
return ftruncate(fd, length) == 0 ? MDB_SUCCESS : errno;
#endif
@ -508,7 +508,7 @@ int mdbx_ftruncate(mdbx_filehandle_t fd, off_t length) {
int mdbx_thread_key_create(mdbx_thread_key_t *key) {
#if defined(_WIN32) || defined(_WIN64)
*key = TlsAlloc();
return (*key != TLS_OUT_OF_INDEXES) ? MDB_SUCCESS : GetLastError();
return (*key != TLS_OUT_OF_INDEXES) ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return pthread_key_create(key, mdbx_rthc_dtor);
#endif
@ -551,7 +551,7 @@ int mdbx_thread_create(mdbx_thread_t *thread,
void *arg) {
#if defined(_WIN32) || defined(_WIN64)
*thread = CreateThread(NULL, 0, start_routine, arg, 0, NULL);
return *thread ? MDB_SUCCESS : GetLastError();
return *thread ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return pthread_create(thread, NULL, start_routine, arg);
#endif
@ -573,7 +573,7 @@ int mdbx_msync(void *addr, size_t length, int async) {
#if defined(_WIN32) || defined(_WIN64)
if (async)
return MDB_SUCCESS;
return FlushViewOfFile(addr, length) ? MDB_SUCCESS : GetLastError();
return FlushViewOfFile(addr, length) ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return (msync(addr, length, async ? MS_ASYNC : MS_SYNC) == 0) ? MDB_SUCCESS
: errno;
@ -597,10 +597,10 @@ int mdbx_mmap(void **address, size_t length, int rw, mdbx_filehandle_t fd) {
HANDLE h = CreateFileMapping(fd, NULL, rw ? PAGE_READWRITE : PAGE_READONLY,
HIGH_DWORD(length), (DWORD)length, NULL);
if (!h)
return GetLastError();
return mdbx_get_errno_checked();
*address = MapViewOfFileEx(h, rw ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0,
length, *address);
int rc = (*address != MAP_FAILED) ? MDB_SUCCESS : GetLastError();
int rc = (*address != MAP_FAILED) ? MDB_SUCCESS : mdbx_get_errno_checked();
CloseHandle(h);
return rc;
#else
@ -613,7 +613,7 @@ int mdbx_mmap(void **address, size_t length, int rw, mdbx_filehandle_t fd) {
int mdbx_munmap(void *address, size_t length) {
#if defined(_WIN32) || defined(_WIN64)
(void)length;
return UnmapViewOfFile(address) ? MDB_SUCCESS : GetLastError();
return UnmapViewOfFile(address) ? MDB_SUCCESS : mdbx_get_errno_checked();
#else
return (munmap(address, length) == 0) ? MDB_SUCCESS : errno;
#endif
@ -621,7 +621,8 @@ int mdbx_munmap(void *address, size_t length) {
int mdbx_mlock(const void *address, size_t length) {
#if defined(_WIN32) || defined(_WIN64)
return VirtualLock((void *)address, length) ? MDB_SUCCESS : GetLastError();
return VirtualLock((void *)address, length) ? MDB_SUCCESS
: mdbx_get_errno_checked();
#else
return (mlock(address, length) == 0) ? MDB_SUCCESS : errno;
#endif

View File

@ -307,6 +307,31 @@ static __inline void mdbx_invalidate_cache(void *addr, size_t nbytes) {
/*----------------------------------------------------------------------------*/
#ifndef mdbx_assert_fail
void mdbx_assert_fail(MDB_env *env, const char *msg, const char *func,
int line);
#endif /* mdbx_assert_fail */
#if __GLIBC_PREREQ(2, 1)
#define mdbx_asprintf asprintf
#else
int mdbx_asprintf(char **strp, const char *fmt, ...);
#endif
#ifdef _MSC_VER
#ifndef snprintf
#define snprintf(buffer, buffer_size, format, ...) \
_snprintf_s(buffer, buffer_size, _TRUNCATE, format, __VA_ARGS__)
#endif /* snprintf */
#ifndef vsnprintf
#define vsnprintf(buffer, buffer_size, format, args) \
_vsnprintf_s(buffer, buffer_size, _TRUNCATE, format, args)
#endif /* vsnprintf */
#endif /* _MSC_VER */
/*----------------------------------------------------------------------------*/
/* max bytes to write in one call */
#define MAX_WRITE UINT32_C(0x3fff0000)
@ -331,6 +356,30 @@ static __inline char *mdbx_strdup(const char *str) {
#endif
}
static __inline int mdbx_get_errno(void) {
#if defined(_WIN32) || defined(_WIN64)
DWORD rc = GetLastError();
#else
int rc = errno;
#endif
return rc;
}
static __inline int __mdbx_get_errno_checked(const char *file, unsigned line) {
#if defined(_WIN32) || defined(_WIN64)
DWORD rc = GetLastError();
if (unlikely(rc == MDBX_EINVAL))
mdbx_assert_fail(nullptr, "unexpected ERROR_INVALID_PARAMETER", file, line);
#else
int rc = errno;
if (unlikely(rc == MDBX_EINVAL))
mdbx_assert_fail(nullptr, "unexpected EINVAL", file, line);
#endif
return rc;
}
#define mdbx_get_errno_checked() __mdbx_get_errno_checked(__FILE__, __LINE__)
int mdbx_memalign_alloc(size_t alignment, size_t bytes, void **result);
void mdbx_memalign_free(void *ptr);
@ -387,19 +436,6 @@ void mdbx_osal_jitter(bool tiny);
/*----------------------------------------------------------------------------*/
#ifndef mdbx_assert_fail
void mdbx_assert_fail(MDB_env *env, const char *msg, const char *func,
int line);
#endif /* mdbx_assert_fail */
#if __GLIBC_PREREQ(2, 1)
#define mdbx_asprintf asprintf
#else
int mdbx_asprintf(char **strp, const char *fmt, ...);
#endif
/*----------------------------------------------------------------------------*/
#if defined(_WIN32) || defined(_WIN64)
#undef MDBX_OSAL_LOCK
#define MDBX_OSAL_LOCK_SIGN MDBX_TETRAD('f', 'l', 'c', 'k')
@ -433,20 +469,6 @@ int mdbx_rpid_check(MDB_env *env, mdbx_pid_t pid);
/*----------------------------------------------------------------------------*/
#ifdef _MSC_VER
#ifndef snprintf
#define snprintf(buffer, buffer_size, format, ...) \
_snprintf_s(buffer, buffer_size, _TRUNCATE, format, __VA_ARGS__)
#endif /* snprintf */
#ifndef vsnprintf
#define vsnprintf(buffer, buffer_size, format, args) \
_vsnprintf_s(buffer, buffer_size, _TRUNCATE, format, args)
#endif /* vsnprintf */
#endif /* _MSC_VER */
/*----------------------------------------------------------------------------*/
#if (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__) && \
(__GNUC_PREREQ(4, 9) || __CLANG_PREREQ(3, 8) || \
!(defined(__GNUC__) || defined(__clang__)))
@ -460,6 +482,8 @@ int mdbx_rpid_check(MDB_env *env, mdbx_pid_t pid);
'size_t' to 'LONGLONG' */
#pragma warning(disable : 4244) /* 'return': conversion from 'LONGLONG' to \
'std::size_t', possible loss of data */
#pragma warning(disable : 4267) /* 'function': conversion from 'size_t' to \
'long', possible loss of data */
#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedCompareExchange)
#pragma intrinsic(_InterlockedExchangeAdd64, _InterlockedCompareExchange64)
#elif defined(__APPLE__)