mdbx: merge branch 'devel' (crutches for Wine).

Change-Id: I1779bc6987449e403216584cdd2846e910f34c8a
This commit is contained in:
Leo Yuriev
2020-02-28 19:05:00 +03:00
8 changed files with 92 additions and 75 deletions

View File

@@ -19,14 +19,9 @@ message(STATUS "libmdbx version is ${MDBX_VERSION}")
if(MDBX_ALLOY_MODE)
set(LIBMDBX_SOURCES alloy.c)
else()
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
set(LIBMDBX_OSAL windows)
else()
set(LIBMDBX_OSAL posix)
endif()
set(LIBMDBX_SOURCES
elements/options.h elements/defs.h elements/internals.h elements/osal.h
elements/core.c elements/osal.c elements/lck-${LIBMDBX_OSAL}.c)
elements/core.c elements/osal.c elements/lck-posix.c elements/lck-windows.c)
endif()
list(APPEND LIBMDBX_SOURCES ../mdbx.h
"${CMAKE_CURRENT_SOURCE_DIR}/elements/version.c"

View File

@@ -3184,12 +3184,12 @@ static const char *__mdbx_strerr(int errnum) {
"MDBX_READERS_FULL: Too many readers (maxreaders reached)",
NULL /* MDBX_TLS_FULL (-30789): unused in MDBX */,
"MDBX_TXN_FULL: Transaction has too many dirty pages,"
" i.e transaction too big",
" i.e transaction is too big",
"MDBX_CURSOR_FULL: Internal error - Cursor stack limit reached",
"MDBX_PAGE_FULL: Internal error - Page has no more space",
"MDBX_MAP_RESIZED: Database contents grew beyond environment mapsize"
" and engine was unable to extend mapping,"
" e.g. since address space is unavailable or busy",
"MDBX_UNABLE_EXTEND_MAPSIZE: Database engine was unable to extend"
" mapping, e.g. since address space is unavailable or busy,"
" or Operation system not supported such operations"
"MDBX_INCOMPATIBLE: Environment or database is not compatible"
" with the requested operation or the specified flags",
"MDBX_BAD_RSLOT: Invalid reuse of reader locktable slot,"
@@ -4662,6 +4662,8 @@ static __cold int mdbx_mapresize(MDBX_env *env, const pgno_t used_pgno,
* the local threads for safe remap.
* 2) At least on Windows 10 1803 the entire mapped section is unavailable
* for short time during NtExtendSection() or VirtualAlloc() execution.
* 3) Under Wine runtime environment on Linux a section extending is not
* supported. Therefore thread suspending is always required.
*
* THEREFORE LOCAL THREADS SUSPENDING IS ALWAYS REQUIRED! */
array_onstack.limit = ARRAY_LENGTH(array_onstack.handles);
@@ -4760,7 +4762,7 @@ bailout:
}
#endif /* MDBX_USE_VALGRIND */
} else {
if (rc != MDBX_RESULT_TRUE) {
if (rc != MDBX_UNABLE_EXTEND_MAPSIZE) {
mdbx_error("failed resize datafile/mapping: "
"present %" PRIuPTR " -> %" PRIuPTR ", "
"limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
@@ -5248,7 +5250,7 @@ skip_cache:
rc = MDBX_NOTFOUND;
if (flags & MDBX_ALLOC_NEW) {
rc = MDBX_MAP_FULL;
if (next <= txn->mt_geo.upper) {
if (next <= txn->mt_geo.upper && txn->mt_geo.grow) {
mdbx_assert(env, next > txn->mt_end_pgno);
pgno_t aligned = pgno_align2os_pgno(
env, pgno_add(next, txn->mt_geo.grow - next % txn->mt_geo.grow));
@@ -5269,7 +5271,6 @@ skip_cache:
mdbx_error("unable growth datafile to %" PRIaPGNO " pages (+%" PRIaPGNO
"), errcode %d",
aligned, aligned - txn->mt_end_pgno, rc);
rc = (rc == MDBX_RESULT_TRUE) ? MDBX_MAP_FULL : rc;
} else {
mdbx_debug("gc-alloc: next %u > upper %u", next, txn->mt_geo.upper);
}
@@ -6049,20 +6050,22 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
if (txn->mt_geo.upper > MAX_PAGENO ||
bytes2pgno(env, pgno2bytes(env, txn->mt_geo.upper)) !=
txn->mt_geo.upper) {
rc = MDBX_MAP_RESIZED;
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
goto bailout;
}
rc = mdbx_mapresize(env, txn->mt_next_pgno, txn->mt_end_pgno,
txn->mt_geo.upper);
if (rc != MDBX_SUCCESS) {
if (rc == MDBX_RESULT_TRUE)
rc = MDBX_MAP_RESIZED;
if (rc != MDBX_SUCCESS)
goto bailout;
}
}
if (txn->mt_flags & MDBX_RDONLY) {
#if defined(_WIN32) || defined(_WIN64)
if (size > env->me_dbgeo.lower && env->me_dbgeo.shrink) {
if ((size > env->me_dbgeo.lower && env->me_dbgeo.shrink) ||
(mdbx_RunningUnderWine() &&
/* under Wine acquisition of remap_guard is always required,
* since Wine don't support section extending,
* i.e. in both cases unmap+map are required. */
size < env->me_dbgeo.upper && env->me_dbgeo.grow)) {
txn->mt_flags |= MDBX_SHRINK_ALLOWED;
mdbx_srwlock_AcquireShared(&env->me_remap_guard);
}

View File

@@ -12,6 +12,8 @@
* <http://www.OpenLDAP.org/license.html>.
*/
#if !(defined(_WIN32) || defined(_WIN64)) /* !Windows LCK-implementation */
#include "internals.h"
#include <sys/sem.h>
@@ -803,3 +805,10 @@ void mdbx_txn_unlock(MDBX_env *env) {
mdbx_panic("%s() failed: err %d\n", __func__, rc);
mdbx_jitter4testing(true);
}
#else
#ifdef _MSC_VER
#pragma warning(disable : 4206) /* nonstandard extension used: translation \
unit is empty */
#endif /* _MSC_VER (warnings) */
#endif /* !Windows LCK-implementation */

View File

@@ -12,17 +12,15 @@
* <http://www.OpenLDAP.org/license.html>.
*/
#include "internals.h"
#if defined(_WIN32) || defined(_WIN64) /* Windows LCK-implementation */
/* PREAMBLE FOR WINDOWS:
*
* We are not concerned for performance here.
* If you are running Windows a performance could NOT be the goal.
* Otherwise please use Linux.
*
* Regards,
* LY
*/
* Otherwise please use Linux. */
#include "internals.h"
static void mdbx_winnt_import(void);
@@ -367,22 +365,24 @@ mdbx_resume_threads_after_remap(mdbx_handle_array_t *array) {
*/
static void lck_unlock(MDBX_env *env) {
int rc;
int err;
if (env->me_lfd != INVALID_HANDLE_VALUE) {
/* double `unlock` for robustly remove overlapped shared/exclusive locks */
while (funlock(env->me_lfd, LCK_LOWER))
;
rc = GetLastError();
assert(rc == ERROR_NOT_LOCKED);
(void)rc;
err = GetLastError();
assert(err == ERROR_NOT_LOCKED ||
(mdbx_RunningUnderWine() && err == ERROR_LOCK_VIOLATION));
(void)err;
SetLastError(ERROR_SUCCESS);
while (funlock(env->me_lfd, LCK_UPPER))
;
rc = GetLastError();
assert(rc == ERROR_NOT_LOCKED);
(void)rc;
err = GetLastError();
assert(err == ERROR_NOT_LOCKED ||
(mdbx_RunningUnderWine() && err == ERROR_LOCK_VIOLATION));
(void)err;
SetLastError(ERROR_SUCCESS);
}
@@ -391,23 +391,26 @@ static void lck_unlock(MDBX_env *env) {
* releases such locks via deferred queues) */
while (funlock(env->me_lazy_fd, LCK_BODY))
;
rc = GetLastError();
assert(rc == ERROR_NOT_LOCKED);
(void)rc;
err = GetLastError();
assert(err == ERROR_NOT_LOCKED ||
(mdbx_RunningUnderWine() && err == ERROR_LOCK_VIOLATION));
(void)err;
SetLastError(ERROR_SUCCESS);
while (funlock(env->me_lazy_fd, LCK_META))
;
rc = GetLastError();
assert(rc == ERROR_NOT_LOCKED);
(void)rc;
err = GetLastError();
assert(err == ERROR_NOT_LOCKED ||
(mdbx_RunningUnderWine() && err == ERROR_LOCK_VIOLATION));
(void)err;
SetLastError(ERROR_SUCCESS);
while (funlock(env->me_lazy_fd, LCK_WHOLE))
;
rc = GetLastError();
assert(rc == ERROR_NOT_LOCKED);
(void)rc;
err = GetLastError();
assert(err == ERROR_NOT_LOCKED ||
(mdbx_RunningUnderWine() && err == ERROR_LOCK_VIOLATION));
(void)err;
SetLastError(ERROR_SUCCESS);
}
}
@@ -748,11 +751,11 @@ static void mdbx_winnt_import(void) {
const HINSTANCE hKernel32dll = GetModuleHandleA("kernel32.dll");
GET_PROC_ADDR(hKernel32dll, GetFileInformationByHandleEx);
GET_PROC_ADDR(hKernel32dll, SetFileInformationByHandle);
GET_PROC_ADDR(hKernel32dll, GetTickCount64);
if (!mdbx_GetTickCount64)
mdbx_GetTickCount64 = stub_GetTickCount64;
if (!mdbx_RunningUnderWine()) {
GET_PROC_ADDR(hKernel32dll, SetFileInformationByHandle);
GET_PROC_ADDR(hKernel32dll, GetVolumeInformationByHandleW);
GET_PROC_ADDR(hKernel32dll, GetFinalPathNameByHandleW);
GET_PROC_ADDR(hKernel32dll, PrefetchVirtualMemory);
@@ -794,3 +797,5 @@ static void mdbx_winnt_import(void) {
mdbx_srwlock_ReleaseExclusive = stub_srwlock_ReleaseExclusive;
}
}
#endif /* Windows LCK-implementation */

View File

@@ -1300,7 +1300,8 @@ MDBX_INTERNAL_FUNC int mdbx_mmap(const int flags, mdbx_mmap_t *map,
if (!NT_SUCCESS(err))
return ntstatus2errcode(err);
SIZE_T ViewSize = (flags & MDBX_RDONLY) ? 0 : limit;
SIZE_T ViewSize =
(flags & MDBX_RDONLY) ? 0 : mdbx_RunningUnderWine() ? size : limit;
err = NtMapViewOfSection(
map->section, GetCurrentProcess(), &map->address,
/* ZeroBits */ 0,
@@ -1403,7 +1404,7 @@ MDBX_INTERNAL_FUNC int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t size,
if (!(flags & MDBX_RDONLY) && limit == map->limit && size > map->current) {
/* growth rw-section */
if (!mdbx_NtExtendSection)
return ERROR_CALL_NOT_IMPLEMENTED /* workaround for Wine */;
return MDBX_UNABLE_EXTEND_MAPSIZE /* workaround for Wine */;
SectionSize.QuadPart = size;
status = mdbx_NtExtendSection(map->section, &SectionSize);
if (!NT_SUCCESS(status))
@@ -1421,7 +1422,7 @@ MDBX_INTERNAL_FUNC int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t size,
status = NtAllocateVirtualMemory(GetCurrentProcess(), &BaseAddress, 0,
&RegionSize, MEM_RESERVE, PAGE_NOACCESS);
if (status == /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018)
return MDBX_RESULT_TRUE;
return MDBX_UNABLE_EXTEND_MAPSIZE;
if (!NT_SUCCESS(status))
return ntstatus2errcode(status);
@@ -1539,8 +1540,8 @@ retry_mapview:;
if (map->address && (size != map->current || limit != map->limit)) {
/* try remap with previously size and limit,
* but will return MDBX_RESULT_TRUE on success */
rc = MDBX_RESULT_TRUE;
* but will return MDBX_UNABLE_EXTEND_MAPSIZE on success */
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
size = map->current;
limit = map->limit;
goto retry_file_and_section;
@@ -1563,7 +1564,7 @@ retry_mapview:;
if (flags & MDBX_RDONLY) {
map->current = (filesize > limit) ? limit : (size_t)filesize;
if (map->current != size)
rc = MDBX_RESULT_TRUE;
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
} else if (filesize != size) {
rc = mdbx_ftruncate(map->fd, size);
if (rc != MDBX_SUCCESS)
@@ -1580,7 +1581,7 @@ retry_mapview:;
case EAGAIN:
case ENOMEM:
case EFAULT /* MADV_DODUMP / MADV_DONTDUMP are mixed for mmap-range */:
rc = MDBX_RESULT_TRUE;
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
}
return rc;
}
@@ -1599,7 +1600,7 @@ retry_mapview:;
#else /* MREMAP_MAYMOVE */
/* TODO: Perhaps here it is worth to implement suspend/resume threads
* and perform unmap/map as like for Windows. */
rc = MDBX_RESULT_TRUE;
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
#endif /* !MREMAP_MAYMOVE */
}
#endif