diff --git a/src/lck-windows.c b/src/lck-windows.c index 1de72935..7654f635 100644 --- a/src/lck-windows.c +++ b/src/lck-windows.c @@ -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) { diff --git a/src/osal.c b/src/osal.c index 17bc602f..459b9f49 100644 --- a/src/osal.c +++ b/src/osal.c @@ -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 diff --git a/src/osal.h b/src/osal.h index 414bde14..39c4de88 100644 --- a/src/osal.h +++ b/src/osal.h @@ -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__)