summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-10-24 20:51:44 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-10-24 20:51:44 +0300
commitf17907dd5c586022660dd27fcd6397dd22b2e365 (patch)
treec9c0a7aed6e613624359b4c4a3f4baa699dd90c9 /libs
parent499311e7496c195473e3fde816d7419c98dc5cd2 (diff)
libmdbx:
- fix for a possible crash after database compaction; - merge with master
Diffstat (limited to 'libs')
-rw-r--r--libs/libmdbx/src/README.md7
-rw-r--r--libs/libmdbx/src/dll.vcxproj50
-rw-r--r--libs/libmdbx/src/mdbx.h2
-rw-r--r--libs/libmdbx/src/src/bits.h10
-rw-r--r--libs/libmdbx/src/src/lck-posix.c14
-rw-r--r--libs/libmdbx/src/src/lck-windows.c62
-rw-r--r--libs/libmdbx/src/src/mdbx.c294
-rw-r--r--libs/libmdbx/src/src/osal.c182
-rw-r--r--libs/libmdbx/src/src/osal.h109
-rw-r--r--libs/libmdbx/src/src/tools/mdbx_chk.c18
-rw-r--r--libs/libmdbx/src/src/tools/mdbx_chk.vcxproj2
-rw-r--r--libs/libmdbx/src/src/tools/mdbx_copy.vcxproj2
-rw-r--r--libs/libmdbx/src/src/tools/mdbx_dump.c7
-rw-r--r--libs/libmdbx/src/src/tools/mdbx_dump.vcxproj2
-rw-r--r--libs/libmdbx/src/src/tools/mdbx_load.c15
-rw-r--r--libs/libmdbx/src/src/tools/mdbx_load.vcxproj2
-rw-r--r--libs/libmdbx/src/src/tools/mdbx_stat.c4
-rw-r--r--libs/libmdbx/src/src/tools/mdbx_stat.vcxproj2
-rw-r--r--libs/libmdbx/src/src/tools/wingetopt.c4
19 files changed, 531 insertions, 257 deletions
diff --git a/libs/libmdbx/src/README.md b/libs/libmdbx/src/README.md
index 7c07de316e..a2a6ab7ac3 100644
--- a/libs/libmdbx/src/README.md
+++ b/libs/libmdbx/src/README.md
@@ -32,7 +32,12 @@ libmdbx
6. [Asynchronous lazy data flushing](https://sites.fas.harvard.edu/~cs265/papers/kathuria-2008.pdf) to disk(s);
7. etc...
-Don't miss [Java Native Interface](https://github.com/castortech/mdbxjni) by [Castor Technologies](https://castortech.com/).
+Don't miss libmdbx for other runtimes.
+
+| Runtime | GitHub | Author |
+| ------------- | ------------- | ------------- |
+| JVM | [mdbxjni](https://github.com/castortech/mdbxjni) | [Castor Technologies](https://castortech.com/) |
+| .NET | [mdbx.NET](https://github.com/wangjia184/mdbx.NET) | [Jerry Wang](https://github.com/wangjia184) |
-----
diff --git a/libs/libmdbx/src/dll.vcxproj b/libs/libmdbx/src/dll.vcxproj
index 746de67bd9..812e1e65a8 100644
--- a/libs/libmdbx/src/dll.vcxproj
+++ b/libs/libmdbx/src/dll.vcxproj
@@ -73,6 +73,7 @@
<TargetName>mdbx</TargetName>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <CustomBuildBeforeTargets>PreLinkEvent</CustomBuildBeforeTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
@@ -80,22 +81,25 @@
<TargetName>mdbx</TargetName>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <CustomBuildBeforeTargets>PreLinkEvent</CustomBuildBeforeTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<TargetName>mdbx</TargetName>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <CustomBuildBeforeTargets>PreLinkEvent</CustomBuildBeforeTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<TargetName>mdbx</TargetName>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <CustomBuildBeforeTargets>PreLinkEvent</CustomBuildBeforeTargets>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
- <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;%(PreprocessorDefinitions);MDBX_DEBUG=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions);MDBX_DEBUG=1</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>EnableAllWarnings</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@@ -107,11 +111,18 @@
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
+ <AdditionalDependencies>ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
+ <CustomBuildStep>
+ <Message>Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget)</Message>
+ <Outputs>$(IntermediateOutputPath)mdbx_ntdll_extra.lib</Outputs>
+ <Inputs>$(ProjectDir)src/ntdll.def</Inputs>
+ <Command>lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget)</Command>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
- <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>EnableAllWarnings</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@@ -122,6 +133,9 @@
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>true</WholeProgramOptimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <AssemblerOutput>All</AssemblerOutput>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
@@ -130,7 +144,15 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <AdditionalDependencies>ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Link>
+ <CustomBuildStep>
+ <Message>Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget)</Message>
+ <Outputs>$(IntermediateOutputPath)mdbx_ntdll_extra.lib</Outputs>
+ <Inputs>$(ProjectDir)src/ntdll.def</Inputs>
+ <Command>lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget)</Command>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -140,15 +162,24 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>EnableAllWarnings</WarningLevel>
- <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;%(PreprocessorDefinitions);MDBX_DEBUG=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions);MDBX_DEBUG=1</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<StringPooling>true</StringPooling>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
+ <Link>
+ <AdditionalDependencies>ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <CustomBuildStep>
+ <Message>Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget)</Message>
+ <Outputs>$(IntermediateOutputPath)mdbx_ntdll_extra.lib</Outputs>
+ <Inputs>$(ProjectDir)src/ntdll.def</Inputs>
+ <Command>lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget)</Command>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
- <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<StringPooling>true</StringPooling>
<Optimization>Full</Optimization>
@@ -158,10 +189,21 @@
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>true</WholeProgramOptimization>
<WarningLevel>EnableAllWarnings</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <AssemblerOutput>All</AssemblerOutput>
</ClCompile>
<Link>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <AdditionalDependencies>ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Link>
+ <CustomBuildStep>
+ <Message>Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget)</Message>
+ <Outputs>$(IntermediateOutputPath)mdbx_ntdll_extra.lib</Outputs>
+ <Inputs>$(ProjectDir)src/ntdll.def</Inputs>
+ <Command>lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget)</Command>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\lck-windows.c" />
diff --git a/libs/libmdbx/src/mdbx.h b/libs/libmdbx/src/mdbx.h
index 283f595df6..120d6847e4 100644
--- a/libs/libmdbx/src/mdbx.h
+++ b/libs/libmdbx/src/mdbx.h
@@ -212,6 +212,7 @@ extern LIBMDBX_API const mdbx_version_info mdbx_version;
extern LIBMDBX_API const mdbx_build_info mdbx_build;
#if defined(_WIN32) || defined(_WIN64)
+#ifndef MDBX_BUILD_DLL
/* Dll initialization callback for ability to dynamically load MDBX DLL by
* LoadLibrary() on Windows versions before Windows Vista. This function MUST be
@@ -227,6 +228,7 @@ extern LIBMDBX_API const mdbx_build_info mdbx_build;
void LIBMDBX_API NTAPI mdbx_dll_callback(PVOID module, DWORD reason,
PVOID reserved);
#endif /* MDBX_CONFIG_MANUAL_TLS_CALLBACK */
+#endif /* MDBX_BUILD_DLL */
#endif /* Windows */
/* The name of the lock file in the DB environment */
diff --git a/libs/libmdbx/src/src/bits.h b/libs/libmdbx/src/src/bits.h
index d1c27bc5ab..3d3e392180 100644
--- a/libs/libmdbx/src/src/bits.h
+++ b/libs/libmdbx/src/src/bits.h
@@ -476,10 +476,10 @@ typedef struct MDBX_lockinfo {
(uint16_t)(MDBX_LOCKINFO_WHOLE_SIZE + MDBX_CACHELINE_SIZE - 1))
#define MDBX_DATA_MAGIC ((MDBX_MAGIC << 8) + MDBX_DATA_VERSION)
-#define MDBX_DATA_DEBUG ((MDBX_MAGIC << 8) + 255)
+#define MDBX_DATA_MAGIC_DEVEL ((MDBX_MAGIC << 8) + 255)
#define MDBX_LOCK_MAGIC ((MDBX_MAGIC << 8) + MDBX_LOCK_VERSION)
-#define MDBX_LOCK_DEBUG ((MDBX_MAGIC << 8) + 255)
+#define MDBX_LOCK_MAGIC_DEVEL ((MDBX_MAGIC << 8) + 255)
#ifndef MDBX_ASSUME_MALLOC_OVERHEAD
#define MDBX_ASSUME_MALLOC_OVERHEAD (sizeof(void *) * 2u)
@@ -870,6 +870,9 @@ void mdbx_panic(const char *fmt, ...)
#endif /* NDEBUG */
#endif /* MDBX_DEBUG */
+LIBMDBX_API void mdbx_assert_fail(const MDBX_env *env, const char *msg,
+ const char *func, int line);
+
#define mdbx_print(fmt, ...) \
mdbx_debug_log(MDBX_DBG_PRINT, NULL, 0, fmt, ##__VA_ARGS__)
@@ -969,6 +972,9 @@ void mdbx_panic(const char *fmt, ...)
/* assert(3) variant in transaction context */
#define mdbx_tassert(txn, expr) mdbx_assert((txn)->mt_env, expr)
+#undef assert
+#define assert(expr) mdbx_assert(NULL, expr)
+
/*----------------------------------------------------------------------------*/
/* Internal prototypes */
diff --git a/libs/libmdbx/src/src/lck-posix.c b/libs/libmdbx/src/src/lck-posix.c
index 0aa9d85078..9743955311 100644
--- a/libs/libmdbx/src/src/lck-posix.c
+++ b/libs/libmdbx/src/src/lck-posix.c
@@ -126,7 +126,8 @@ int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid) {
/*---------------------------------------------------------------------------*/
-static int mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, int rc);
+static int mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex,
+ const int rc);
int __cold mdbx_lck_init(MDBX_env *env) {
pthread_mutexattr_t ma;
@@ -297,9 +298,10 @@ int __cold mdbx_lck_seize(MDBX_env *env) {
#endif
static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex,
- int rc) {
+ const int err) {
+ int rc = err;
#if MDBX_USE_ROBUST
- if (rc == EOWNERDEAD) {
+ if (err == EOWNERDEAD) {
/* We own the mutex. Clean up after dead previous owner. */
int rlocked = (env->me_lck && mutex == &env->me_lck->mti_rmutex);
@@ -331,10 +333,8 @@ static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex,
}
#endif /* MDBX_USE_ROBUST */
- mdbx_error("mutex (un)lock failed, %s", mdbx_strerror(rc));
- if (rc != EDEADLK) {
+ mdbx_error("mutex (un)lock failed, %s", mdbx_strerror(err));
+ if (rc != EDEADLK)
env->me_flags |= MDBX_FATAL_ERROR;
- rc = MDBX_PANIC;
- }
return rc;
}
diff --git a/libs/libmdbx/src/src/lck-windows.c b/libs/libmdbx/src/src/lck-windows.c
index 7da0755916..c019a6d547 100644
--- a/libs/libmdbx/src/src/lck-windows.c
+++ b/libs/libmdbx/src/src/lck-windows.c
@@ -26,11 +26,29 @@
static void mdbx_winnt_import(void);
+#ifdef MDBX_BUILD_DLL
+/* DEBUG/CHECKED builds still require MSVC's CRT for runtime checks.
+ *
+ * Therefore we don't define dll's entry point for debug/checked builds by MSVC.
+ * In this case MSVC's will automatically use DllMainCRTStartup() from CRT
+ * library, which also automatically call DllMain() from our mdbx.dll
+ *
+ * On the other side, for RELEASE builds
+ * we explicitly define DllMain() as the entry point and don't linking with
+ * any CRT libraries (IgnoreAllDefaultLibraries = Yes). */
+#if !defined(_MSC_VER) || defined(NDEBUG)
+#pragma comment(linker, "/ENTRY:DllMain")
+#endif
+
+BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID reserved)
+#else
#if !MDBX_CONFIG_MANUAL_TLS_CALLBACK
static
#endif /* !MDBX_CONFIG_MANUAL_TLS_CALLBACK */
void NTAPI
- mdbx_dll_callback(PVOID module, DWORD reason, PVOID reserved) {
+ mdbx_dll_callback(PVOID module, DWORD reason, PVOID reserved)
+#endif /* MDBX_BUILD_DLL */
+{
(void)reserved;
switch (reason) {
case DLL_PROCESS_ATTACH:
@@ -47,9 +65,12 @@ static
mdbx_rthc_thread_dtor(module);
break;
}
+#ifdef MDBX_BUILD_DLL
+ return TRUE;
+#endif
}
-#if !MDBX_CONFIG_MANUAL_TLS_CALLBACK
+#if !defined(MDBX_BUILD_DLL) && !MDBX_CONFIG_MANUAL_TLS_CALLBACK
/* *INDENT-OFF* */
/* clang-format off */
#if defined(_MSC_VER)
@@ -87,7 +108,7 @@ static
#endif
/* *INDENT-ON* */
/* clang-format on */
-#endif /* !MDBX_CONFIG_MANUAL_TLS_CALLBACK */
+#endif /* !defined(MDBX_BUILD_DLL) && !MDBX_CONFIG_MANUAL_TLS_CALLBACK */
/*----------------------------------------------------------------------------*/
@@ -191,12 +212,12 @@ static int suspend_and_append(mdbx_handle_array_t **array,
const DWORD ThreadId) {
const unsigned limit = (*array)->limit;
if ((*array)->count == limit) {
- void *ptr = realloc((limit > ARRAY_LENGTH((*array)->handles))
- ? *array
- : /* don't free initial array on the stack */ NULL,
- sizeof(mdbx_handle_array_t) +
- sizeof(HANDLE) *
- (limit * 2 - ARRAY_LENGTH((*array)->handles)));
+ void *ptr = mdbx_realloc(
+ (limit > ARRAY_LENGTH((*array)->handles))
+ ? *array
+ : /* don't free initial array on the stack */ NULL,
+ sizeof(mdbx_handle_array_t) +
+ sizeof(HANDLE) * (limit * 2 - ARRAY_LENGTH((*array)->handles)));
if (!ptr)
return MDBX_ENOMEM;
if (limit == ARRAY_LENGTH((*array)->handles))
@@ -205,12 +226,19 @@ static int suspend_and_append(mdbx_handle_array_t **array,
(*array)->limit = limit * 2;
}
- HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, ThreadId);
+ HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
+ FALSE, ThreadId);
if (hThread == NULL)
return GetLastError();
+
if (SuspendThread(hThread) == -1) {
+ int err = GetLastError();
+ DWORD ExitCode;
+ if (err == /* workaround for Win10 UCRT bug */ ERROR_ACCESS_DENIED ||
+ !GetExitCodeThread(hThread, &ExitCode) || ExitCode != STILL_ACTIVE)
+ err = MDBX_SUCCESS;
CloseHandle(hThread);
- return GetLastError();
+ return err;
}
(*array)->handles[(*array)->count++] = hThread;
@@ -295,9 +323,15 @@ int mdbx_suspend_threads_before_remap(MDBX_env *env,
int mdbx_resume_threads_after_remap(mdbx_handle_array_t *array) {
int rc = MDBX_SUCCESS;
for (unsigned i = 0; i < array->count; ++i) {
- if (ResumeThread(array->handles[i]) == -1)
- rc = GetLastError();
- CloseHandle(array->handles[i]);
+ const HANDLE hThread = array->handles[i];
+ if (ResumeThread(hThread) == -1) {
+ const int err = GetLastError();
+ DWORD ExitCode;
+ if (err != /* workaround for Win10 UCRT bug */ ERROR_ACCESS_DENIED &&
+ GetExitCodeThread(hThread, &ExitCode) && ExitCode == STILL_ACTIVE)
+ rc = err;
+ }
+ CloseHandle(hThread);
}
return rc;
}
diff --git a/libs/libmdbx/src/src/mdbx.c b/libs/libmdbx/src/src/mdbx.c
index 0d06f1a191..b0111895bf 100644
--- a/libs/libmdbx/src/src/mdbx.c
+++ b/libs/libmdbx/src/src/mdbx.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
* and other libmdbx authors: please see AUTHORS file.
* All rights reserved.
@@ -40,9 +40,6 @@
/*----------------------------------------------------------------------------*/
/* Internal inlines */
-#undef assert
-#define assert(expr) mdbx_assert(NULL, expr)
-
static __inline bool mdbx_is_power2(size_t x) { return (x & (x - 1)) == 0; }
static __inline size_t mdbx_roundup2(size_t value, size_t granularity) {
@@ -531,7 +528,7 @@ __cold void mdbx_rthc_global_dtor(void) {
rthc_limit = rthc_count = 0;
if (rthc_table != rthc_table_static)
- free(rthc_table);
+ mdbx_free(rthc_table);
rthc_table = nullptr;
mdbx_rthc_unlock();
@@ -560,8 +557,8 @@ __cold int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin,
rthc_limit);
if (rthc_count == rthc_limit) {
rthc_entry_t *new_table =
- realloc((rthc_table == rthc_table_static) ? nullptr : rthc_table,
- sizeof(rthc_entry_t) * rthc_limit * 2);
+ mdbx_realloc((rthc_table == rthc_table_static) ? nullptr : rthc_table,
+ sizeof(rthc_entry_t) * rthc_limit * 2);
if (new_table == nullptr) {
rc = MDBX_ENOMEM;
goto bailout;
@@ -609,7 +606,7 @@ __cold void mdbx_rthc_remove(const mdbx_thread_key_t key) {
if (--rthc_count > 0)
rthc_table[i] = rthc_table[rthc_count];
else if (rthc_table != rthc_table_static) {
- free(rthc_table);
+ mdbx_free(rthc_table);
rthc_table = rthc_table_static;
rthc_limit = RTHC_INITIAL_LIMIT;
}
@@ -641,7 +638,7 @@ static __inline pgno_t bytes2pnl(const size_t bytes) {
static MDBX_PNL mdbx_pnl_alloc(size_t size) {
const size_t bytes = pnl2bytes(size);
- MDBX_PNL pl = malloc(bytes);
+ MDBX_PNL pl = mdbx_malloc(bytes);
if (likely(pl)) {
#if __GLIBC_PREREQ(2, 12)
const size_t bytes = malloc_usable_size(pl);
@@ -656,7 +653,7 @@ static MDBX_PNL mdbx_pnl_alloc(size_t size) {
static void mdbx_pnl_free(MDBX_PNL pl) {
if (likely(pl))
- free(pl - 1);
+ mdbx_free(pl - 1);
}
/* Shrink the PNL to the default size if it has grown larger */
@@ -668,7 +665,7 @@ static void mdbx_pnl_shrink(MDBX_PNL *ppl) {
if (unlikely(MDBX_PNL_ALLOCLEN(*ppl) >
MDBX_PNL_INITIAL + MDBX_CACHELINE_SIZE / sizeof(pgno_t))) {
const size_t bytes = pnl2bytes(MDBX_PNL_INITIAL);
- MDBX_PNL pl = realloc(*ppl - 1, bytes);
+ MDBX_PNL pl = mdbx_realloc(*ppl - 1, bytes);
if (likely(pl)) {
#if __GLIBC_PREREQ(2, 12)
const size_t bytes = malloc_usable_size(pl);
@@ -694,7 +691,7 @@ static int mdbx_pnl_reserve(MDBX_PNL *ppl, const size_t wanna) {
? wanna + wanna - allocated
: MDBX_PNL_MAX;
const size_t bytes = pnl2bytes(size);
- MDBX_PNL pl = realloc(*ppl - 1, bytes);
+ MDBX_PNL pl = mdbx_realloc(*ppl - 1, bytes);
if (likely(pl)) {
#if __GLIBC_PREREQ(2, 12)
const size_t bytes = malloc_usable_size(pl);
@@ -935,7 +932,7 @@ static __inline size_t bytes2txl(const size_t bytes) {
static MDBX_TXL mdbx_txl_alloc(void) {
const size_t bytes = txl2bytes(MDBX_TXL_INITIAL);
- MDBX_TXL tl = malloc(bytes);
+ MDBX_TXL tl = mdbx_malloc(bytes);
if (likely(tl)) {
#if __GLIBC_PREREQ(2, 12)
const size_t bytes = malloc_usable_size(tl);
@@ -950,7 +947,7 @@ static MDBX_TXL mdbx_txl_alloc(void) {
static void mdbx_txl_free(MDBX_TXL tl) {
if (likely(tl))
- free(tl - 1);
+ mdbx_free(tl - 1);
}
static int mdbx_txl_reserve(MDBX_TXL *ptl, const size_t wanna) {
@@ -967,7 +964,7 @@ static int mdbx_txl_reserve(MDBX_TXL *ptl, const size_t wanna) {
? wanna + wanna - allocated
: MDBX_TXL_MAX;
const size_t bytes = txl2bytes(size);
- MDBX_TXL tl = realloc(*ptl - 1, bytes);
+ MDBX_TXL tl = mdbx_realloc(*ptl - 1, bytes);
if (likely(tl)) {
#if __GLIBC_PREREQ(2, 12)
const size_t bytes = malloc_usable_size(tl);
@@ -1328,7 +1325,7 @@ const char *__cold mdbx_strerror_r(int errnum, char *buf, size_t buflen) {
if (!msg) {
if (!buflen || buflen > INT_MAX)
return NULL;
-#ifdef _MSC_VER
+#if defined(_WIN32) || defined(_WIN64)
size_t size = FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (DWORD)buflen,
@@ -1357,7 +1354,7 @@ const char *__cold mdbx_strerror_r(int errnum, char *buf, size_t buflen) {
const char *__cold mdbx_strerror(int errnum) {
const char *msg = __mdbx_strerr(errnum);
if (!msg) {
-#ifdef _MSC_VER
+#if defined(_WIN32) || defined(_WIN64)
static char buffer[1024];
size_t size = FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
@@ -1389,6 +1386,28 @@ void __cold mdbx_debug_log(int type, const char *function, int line,
if (mdbx_debug_logger)
mdbx_debug_logger(type, function, line, fmt, args);
else {
+#if defined(_WIN32) || defined(_WIN64)
+ if (IsDebuggerPresent()) {
+ int prefix_len = 0;
+ char *prefix = nullptr;
+ if (function && line > 0)
+ prefix_len = mdbx_asprintf(&prefix, "%s:%d ", function, line);
+ else if (function)
+ prefix_len = mdbx_asprintf(&prefix, "%s: ", function);
+ else if (line > 0)
+ prefix_len = mdbx_asprintf(&prefix, "%d: ", line);
+ if (prefix_len > 0 && prefix) {
+ OutputDebugStringA(prefix);
+ mdbx_free(prefix);
+ }
+ char *msg = nullptr;
+ int msg_len = mdbx_vasprintf(&msg, fmt, args);
+ if (msg_len > 0 && msg) {
+ OutputDebugStringA(msg);
+ mdbx_free(msg);
+ }
+ }
+#else
if (function && line > 0)
fprintf(stderr, "%s:%d ", function, line);
else if (function)
@@ -1397,6 +1416,7 @@ void __cold mdbx_debug_log(int type, const char *function, int line,
fprintf(stderr, "%d: ", line);
vfprintf(stderr, fmt, args);
fflush(stderr);
+#endif
}
va_end(args);
}
@@ -1577,7 +1597,7 @@ static MDBX_page *mdbx_page_malloc(MDBX_txn *txn, unsigned num) {
env->me_dpages = np->mp_next;
} else {
size = pgno2bytes(env, num);
- np = malloc(size);
+ np = mdbx_malloc(size);
if (unlikely(!np)) {
txn->mt_flags |= MDBX_TXN_ERROR;
return np;
@@ -1615,7 +1635,7 @@ static void mdbx_dpage_free(MDBX_env *env, MDBX_page *dp, unsigned pages) {
} else {
/* large pages just get freed directly */
VALGRIND_MEMPOOL_FREE(env, dp);
- free(dp);
+ mdbx_free(dp);
}
}
@@ -1639,7 +1659,9 @@ static size_t bytes_align2os_bytes(const MDBX_env *env, size_t bytes) {
static void __cold mdbx_kill_page(MDBX_env *env, MDBX_page *mp) {
const size_t len = env->me_psize - PAGEHDRSZ;
- void *ptr = (env->me_flags & MDBX_WRITEMAP) ? &mp->mp_data : alloca(len);
+ void *ptr = (env->me_flags & MDBX_WRITEMAP)
+ ? &mp->mp_data
+ : (void *)((uint8_t *)env->me_pbuf + env->me_psize);
memset(ptr, 0x6F /* 'o', 111 */, len);
if (ptr != &mp->mp_data)
(void)mdbx_pwrite(env->me_fd, ptr, len,
@@ -2273,18 +2295,20 @@ bailout:
VALGRIND_CREATE_BLOCK(env->me_map, env->me_mapsize, "mdbx");
}
#endif
- } else if (rc != MDBX_RESULT_TRUE) {
- mdbx_error("failed resize datafile/mapping: "
- "present %" PRIuPTR " -> %" PRIuPTR ", "
- "limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
- env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, limit_bytes,
- rc);
} else {
- mdbx_notice("unable resize datafile/mapping: "
- "present %" PRIuPTR " -> %" PRIuPTR ", "
- "limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
- env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, limit_bytes,
- rc);
+ if (rc != MDBX_RESULT_TRUE) {
+ mdbx_error("failed resize datafile/mapping: "
+ "present %" PRIuPTR " -> %" PRIuPTR ", "
+ "limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
+ env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper,
+ limit_bytes, rc);
+ } else {
+ mdbx_notice("unable resize datafile/mapping: "
+ "present %" PRIuPTR " -> %" PRIuPTR ", "
+ "limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
+ env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper,
+ limit_bytes, rc);
+ }
if (!env->me_dxb_mmap.address) {
env->me_flags |= MDBX_FATAL_ERROR;
if (env->me_txn)
@@ -2299,7 +2323,7 @@ bailout:
if (suspended) {
err = mdbx_resume_threads_after_remap(suspended);
if (suspended != &array_onstack)
- free(suspended);
+ mdbx_free(suspended);
}
#else
int err = mdbx_fastmutex_release(&env->me_remap_guard);
@@ -3025,7 +3049,7 @@ static int mdbx_cursor_shadow(MDBX_txn *src, MDBX_txn *dst) {
if (mc->mc_xcursor)
size += sizeof(MDBX_xcursor);
for (; mc; mc = bk->mc_next) {
- bk = malloc(size);
+ bk = mdbx_malloc(size);
if (unlikely(!bk))
return MDBX_ENOMEM;
*bk = *mc;
@@ -3082,11 +3106,11 @@ static void mdbx_cursors_eot(MDBX_txn *txn, unsigned merge) {
*mx = *(MDBX_xcursor *)(bk + 1);
}
bk->mc_signature = 0;
- free(bk);
+ mdbx_free(bk);
}
if (stage == MDBX_MC_WAIT4EOT) {
mc->mc_signature = 0;
- free(mc);
+ mdbx_free(mc);
} else {
mc->mc_signature = MDBX_MC_READY4CLOSE;
mc->mc_flags = 0 /* reset C_UNTRACK */;
@@ -3139,6 +3163,16 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
rc = mdbx_rdt_lock(env);
if (unlikely(MDBX_IS_ERROR(rc)))
return rc;
+ if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) {
+ mdbx_rdt_unlock(env);
+ return MDBX_PANIC;
+ }
+#if defined(_WIN32) || defined(_WIN64)
+ if (unlikely(!env->me_map)) {
+ mdbx_rdt_unlock(env);
+ return MDBX_EPERM;
+ }
+#endif /* Windows */
rc = MDBX_SUCCESS;
if (unlikely(env->me_live_reader != env->me_pid)) {
@@ -3237,6 +3271,16 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
rc = mdbx_txn_lock(env, F_ISSET(flags, MDBX_TRYTXN));
if (unlikely(rc))
return rc;
+ if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) {
+ mdbx_txn_unlock(env);
+ return MDBX_PANIC;
+ }
+#if defined(_WIN32) || defined(_WIN64)
+ if (unlikely(!env->me_map)) {
+ mdbx_txn_unlock(env);
+ return MDBX_EPERM;
+ }
+#endif /* Windows */
mdbx_jitter4testing(false);
MDBX_meta *meta = mdbx_meta_head(env);
@@ -3296,8 +3340,11 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
goto bailout;
}
rc = mdbx_mapresize(env, txn->mt_end_pgno, upper_pgno);
- if (rc != MDBX_SUCCESS)
+ if (rc != MDBX_SUCCESS) {
+ if (rc == MDBX_RESULT_TRUE)
+ rc = MDBX_MAP_RESIZED;
goto bailout;
+ }
}
txn->mt_owner = mdbx_thread_self();
return MDBX_SUCCESS;
@@ -3345,6 +3392,7 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
if (unlikely(!env || !ret))
return MDBX_EINVAL;
+ *ret = NULL;
if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
return MDBX_EBADSIGN;
@@ -3354,8 +3402,12 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
if (unlikely(env->me_flags & MDBX_FATAL_ERROR))
return MDBX_PANIC;
+#if !defined(_WIN32) && !defined(_WIN64)
+ /* Don't check env->me_map until lock to avoid race with re-mapping for
+ * shrinking */
if (unlikely(!env->me_map))
return MDBX_EPERM;
+#endif /* Windows */
flags &= MDBX_TXN_BEGIN_FLAGS;
flags |= env->me_flags & MDBX_WRITEMAP;
@@ -3366,16 +3418,21 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
if (parent) {
if (unlikely(parent->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EINVAL;
+ return MDBX_EBADSIGN;
if (unlikely(parent->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
+#if defined(_WIN32) || defined(_WIN64)
+ if (unlikely(!env->me_map))
+ return MDBX_EPERM;
+#endif /* Windows */
+
/* Nested transactions: Max 1 child, write txns only, no writemap */
flags |= parent->mt_flags;
- if (unlikely(flags & (MDBX_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED))) {
+ if (unlikely(flags & (MDBX_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED)))
return (parent->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EINVAL : MDBX_BAD_TXN;
- }
+
/* Child txns save MDBX_pgstate and use own copy of cursors */
size = env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + 1);
size += tsize = sizeof(MDBX_ntxn);
@@ -3392,7 +3449,7 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
return MDBX_BUSY;
goto renew;
}
- if (unlikely((txn = malloc(size)) == NULL)) {
+ if (unlikely((txn = mdbx_malloc(size)) == NULL)) {
mdbx_debug("calloc: %s", "failed");
return MDBX_ENOMEM;
}
@@ -3407,11 +3464,12 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
unsigned i;
txn->mt_cursors = (MDBX_cursor **)(txn->mt_dbs + env->me_maxdbs);
txn->mt_dbiseqs = parent->mt_dbiseqs;
- txn->mt_rw_dirtylist = malloc(sizeof(MDBX_DP) * (MDBX_DPL_TXNFULL + 1));
+ txn->mt_rw_dirtylist =
+ mdbx_malloc(sizeof(MDBX_DP) * (MDBX_DPL_TXNFULL + 1));
if (!txn->mt_rw_dirtylist ||
!(txn->mt_befree_pages = mdbx_pnl_alloc(MDBX_PNL_INITIAL))) {
- free(txn->mt_rw_dirtylist);
- free(txn);
+ mdbx_free(txn->mt_rw_dirtylist);
+ mdbx_free(txn);
return MDBX_ENOMEM;
}
txn->mt_txnid = parent->mt_txnid;
@@ -3452,10 +3510,12 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
rc = mdbx_txn_renew0(txn, flags);
}
- if (unlikely(rc)) {
+ if (unlikely(rc != MDBX_SUCCESS)) {
if (txn != env->me_txn0)
- free(txn);
+ mdbx_free(txn);
} else {
+ mdbx_assert(env,
+ (txn->mt_flags & ~(MDBX_TXN_RDONLY | MDBX_TXN_WRITEMAP)) == 0);
txn->mt_signature = MDBX_MT_SIGNATURE;
*ret = txn;
mdbx_debug("begin txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO
@@ -3516,7 +3576,7 @@ static void mdbx_dbis_update(MDBX_txn *txn, int keep) {
mdbx_assert(env, env->me_dbflags[i] == 0);
env->me_dbiseqs[i]++;
env->me_dbxs[i].md_name.iov_base = NULL;
- free(ptr);
+ mdbx_free(ptr);
}
}
}
@@ -3601,7 +3661,7 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
env->me_pgstate = ((MDBX_ntxn *)txn)->mnt_pgstate;
mdbx_pnl_free(txn->mt_befree_pages);
mdbx_pnl_free(txn->mt_spill_pages);
- free(txn->mt_rw_dirtylist);
+ mdbx_free(txn->mt_rw_dirtylist);
}
mdbx_pnl_free(pghead);
@@ -3610,7 +3670,7 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
mdbx_assert(env, txn == env->me_txn0 || txn->mt_owner == 0);
if ((mode & MDBX_END_FREE) != 0 && txn != env->me_txn0) {
txn->mt_signature = 0;
- free(txn);
+ mdbx_free(txn);
}
return MDBX_SUCCESS;
@@ -3646,7 +3706,7 @@ int mdbx_txn_abort(MDBX_txn *txn) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN;
- if (unlikely(txn->mt_owner && txn->mt_owner != mdbx_thread_self()))
+ if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY))
@@ -4498,7 +4558,7 @@ static int mdbx_page_flush(MDBX_txn *txn, pgno_t keep) {
/* Write previous page(s) */
rc = mdbx_pwritev(env->me_fd, iov, n, wpos, wsize);
if (unlikely(rc != MDBX_SUCCESS)) {
- mdbx_debug("Write error: %s", strerror(rc));
+ mdbx_debug("Write error: %s", mdbx_strerror(rc));
return rc;
}
n = 0;
@@ -4691,7 +4751,7 @@ int mdbx_txn_commit(MDBX_txn *txn) {
pn >>= 1;
y = mdbx_dpl_search(dst, pn);
if (y <= dst->length && dst[y].pgno == pn) {
- free(dst[y].ptr);
+ mdbx_free(dst[y].ptr);
while (y < dst->length) {
dst[y] = dst[y + 1];
y++;
@@ -4726,11 +4786,11 @@ int mdbx_txn_commit(MDBX_txn *txn) {
while (yp < dst[x].pgno)
dst[i--] = dst[x--];
if (yp == dst[x].pgno)
- free(dst[x--].ptr);
+ mdbx_free(dst[x--].ptr);
}
mdbx_tassert(txn, i == x);
dst->length = len;
- free(txn->mt_rw_dirtylist);
+ mdbx_free(txn->mt_rw_dirtylist);
parent->mt_dirtyroom = txn->mt_dirtyroom;
if (txn->mt_spill_pages) {
if (parent->mt_spill_pages) {
@@ -4754,7 +4814,7 @@ int mdbx_txn_commit(MDBX_txn *txn) {
parent->mt_child = NULL;
mdbx_pnl_free(((MDBX_ntxn *)txn)->mnt_pgstate.mf_reclaimed_pglist);
txn->mt_signature = 0;
- free(txn);
+ mdbx_free(txn);
return rc;
}
@@ -4836,8 +4896,10 @@ int mdbx_txn_commit(MDBX_txn *txn) {
rc = mdbx_sync_locked(
env, env->me_flags | txn->mt_flags | MDBX_SHRINK_ALLOWED, &meta);
}
- if (unlikely(rc != MDBX_SUCCESS))
+ if (unlikely(rc != MDBX_SUCCESS)) {
+ env->me_flags |= MDBX_FATAL_ERROR;
goto fail;
+ }
if (likely(env->me_lck))
env->me_lck->mti_readers_refresh_flag = false;
@@ -4905,7 +4967,8 @@ static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta,
mdbx_info("meta[%u] was updated, re-read it", meta_number);
}
- if (page.mp_meta.mm_magic_and_version != MDBX_DATA_MAGIC && page.mp_meta.mm_magic_and_version != MDBX_DATA_DEBUG) {
+ if (page.mp_meta.mm_magic_and_version != MDBX_DATA_MAGIC &&
+ page.mp_meta.mm_magic_and_version != MDBX_DATA_MAGIC_DEVEL) {
mdbx_error("meta[%u] has invalid magic/version %" PRIx64, meta_number,
page.mp_meta.mm_magic_and_version);
return ((page.mp_meta.mm_magic_and_version >> 8) != MDBX_MAGIC)
@@ -5466,7 +5529,7 @@ static void __cold mdbx_setup_pagesize(MDBX_env *env, const size_t pagesize) {
}
int __cold mdbx_env_create(MDBX_env **penv) {
- MDBX_env *env = calloc(1, sizeof(MDBX_env));
+ MDBX_env *env = mdbx_calloc(1, sizeof(MDBX_env));
if (!env)
return MDBX_ENOMEM;
@@ -5513,7 +5576,7 @@ int __cold mdbx_env_create(MDBX_env **penv) {
return MDBX_SUCCESS;
bailout:
- free(env);
+ mdbx_free(env);
*penv = nullptr;
return rc;
}
@@ -5867,13 +5930,13 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) {
return err;
}
- void *buffer = calloc(NUM_METAS, env->me_psize);
+ void *buffer = mdbx_calloc(NUM_METAS, env->me_psize);
if (!buffer)
return MDBX_ENOMEM;
meta = mdbx_init_metas(env, buffer)->mp_meta;
err = mdbx_pwrite(env->me_fd, buffer, env->me_psize * NUM_METAS, 0);
- free(buffer);
+ mdbx_free(buffer);
if (unlikely(err != MDBX_SUCCESS))
return err;
@@ -6168,9 +6231,7 @@ static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname,
mdbx_assert(env, env->me_fd != INVALID_HANDLE_VALUE);
mdbx_assert(env, env->me_lfd == INVALID_HANDLE_VALUE);
- const int open_flags =
- (env->me_flags & MDBX_EXCLUSIVE) ? O_RDWR : O_RDWR | O_CREAT;
- int err = mdbx_openfile(lck_pathname, open_flags, mode, &env->me_lfd,
+ int err = mdbx_openfile(lck_pathname, O_RDWR | O_CREAT, mode, &env->me_lfd,
(env->me_flags & MDBX_EXCLUSIVE) ? true : false);
if (err != MDBX_SUCCESS) {
if (!(err == MDBX_ENOFILE && (env->me_flags & MDBX_EXCLUSIVE)) &&
@@ -6277,7 +6338,8 @@ static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname,
env->me_lck->mti_magic_and_version = MDBX_LOCK_MAGIC;
env->me_lck->mti_os_and_format = MDBX_LOCK_FORMAT;
} else {
- if (env->me_lck->mti_magic_and_version != MDBX_LOCK_MAGIC && env->me_lck->mti_magic_and_version != MDBX_LOCK_DEBUG) {
+ if (env->me_lck->mti_magic_and_version != MDBX_LOCK_MAGIC &&
+ env->me_lck->mti_magic_and_version != MDBX_LOCK_MAGIC_DEVEL) {
mdbx_error("lock region has invalid magic/version");
return ((env->me_lck->mti_magic_and_version >> 8) != MDBX_MAGIC)
? MDBX_INVALID
@@ -6333,7 +6395,7 @@ int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
} else {
len_full = len + sizeof(MDBX_LOCKNAME) + len + sizeof(MDBX_DATANAME);
}
- char *lck_pathname = malloc(len_full);
+ char *lck_pathname = mdbx_malloc(len_full);
if (!lck_pathname)
return MDBX_ENOMEM;
@@ -6357,7 +6419,8 @@ int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
MDBX_COALESCE | MDBX_LIFORECLAIM | MDBX_NOMEMINIT);
} else {
if (!((env->me_free_pgs = mdbx_pnl_alloc(MDBX_PNL_INITIAL)) &&
- (env->me_dirtylist = calloc(MDBX_DPL_TXNFULL + 1, sizeof(MDBX_DP)))))
+ (env->me_dirtylist =
+ mdbx_calloc(MDBX_DPL_TXNFULL + 1, sizeof(MDBX_DP)))))
rc = MDBX_ENOMEM;
}
@@ -6367,9 +6430,9 @@ int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
goto bailout;
env->me_path = mdbx_strdup(path);
- env->me_dbxs = calloc(env->me_maxdbs, sizeof(MDBX_dbx));
- env->me_dbflags = calloc(env->me_maxdbs, sizeof(env->me_dbflags[0]));
- env->me_dbiseqs = calloc(env->me_maxdbs, sizeof(env->me_dbiseqs[0]));
+ env->me_dbxs = mdbx_calloc(env->me_maxdbs, sizeof(MDBX_dbx));
+ env->me_dbflags = mdbx_calloc(env->me_maxdbs, sizeof(env->me_dbflags[0]));
+ env->me_dbiseqs = mdbx_calloc(env->me_maxdbs, sizeof(env->me_dbiseqs[0]));
if (!(env->me_dbxs && env->me_path && env->me_dbflags && env->me_dbiseqs)) {
rc = MDBX_ENOMEM;
goto bailout;
@@ -6448,7 +6511,8 @@ int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
size =
tsize + env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) +
sizeof(unsigned) + 1);
- if ((env->me_pbuf = calloc(1, env->me_psize)) && (txn = calloc(1, size))) {
+ if ((env->me_pbuf = mdbx_calloc(2, env->me_psize)) &&
+ (txn = mdbx_calloc(1, size))) {
txn->mt_dbs = (MDBX_db *)((char *)txn + tsize);
txn->mt_cursors = (MDBX_cursor **)(txn->mt_dbs + env->me_maxdbs);
txn->mt_dbiseqs = (unsigned *)(txn->mt_cursors + env->me_maxdbs);
@@ -6486,7 +6550,7 @@ bailout:
mdbx_env_close0(env);
env->me_flags = saved_me_flags | MDBX_FATAL_ERROR;
}
- free(lck_pathname);
+ mdbx_free(lck_pathname);
return rc;
}
@@ -6499,18 +6563,18 @@ static void __cold mdbx_env_close0(MDBX_env *env) {
/* Doing this here since me_dbxs may not exist during mdbx_env_close */
if (env->me_dbxs) {
for (unsigned i = env->me_maxdbs; --i >= CORE_DBS;)
- free(env->me_dbxs[i].md_name.iov_base);
- free(env->me_dbxs);
+ mdbx_free(env->me_dbxs[i].md_name.iov_base);
+ mdbx_free(env->me_dbxs);
}
- free(env->me_pbuf);
- free(env->me_dbiseqs);
- free(env->me_dbflags);
- free(env->me_path);
- free(env->me_dirtylist);
+ mdbx_free(env->me_pbuf);
+ mdbx_free(env->me_dbiseqs);
+ mdbx_free(env->me_dbflags);
+ mdbx_free(env->me_path);
+ mdbx_free(env->me_dirtylist);
if (env->me_txn0) {
mdbx_txl_free(env->me_txn0->mt_lifo_reclaimed);
- free(env->me_txn0);
+ mdbx_free(env->me_txn0);
}
mdbx_pnl_free(env->me_free_pgs);
@@ -6578,7 +6642,7 @@ int __cold mdbx_env_close_ex(MDBX_env *env, int dont_sync) {
ASAN_UNPOISON_MEMORY_REGION(&dp->mp_next, sizeof(dp->mp_next));
VALGRIND_MAKE_MEM_DEFINED(&dp->mp_next, sizeof(dp->mp_next));
env->me_dpages = dp->mp_next;
- free(dp);
+ mdbx_free(dp);
}
mdbx_env_close0(env);
@@ -6595,7 +6659,7 @@ int __cold mdbx_env_close_ex(MDBX_env *env, int dont_sync) {
env->me_pid = 0;
env->me_signature = 0;
- free(env);
+ mdbx_free(env);
return rc;
}
@@ -6927,13 +6991,20 @@ mapped:
p = pgno2page(env, pgno);
done:
- if (unlikely(p->mp_pgno != pgno))
+ if (unlikely(p->mp_pgno != pgno)) {
+ mdbx_error("mismatch pgno %" PRIaPGNO " (actual) != %" PRIaPGNO
+ " (expected)",
+ p->mp_pgno, pgno);
return MDBX_CORRUPTED;
+ }
if (unlikely(p->mp_upper < p->mp_lower ||
PAGEHDRSZ + p->mp_upper > env->me_psize) &&
- !IS_OVERFLOW(p))
+ !IS_OVERFLOW(p)) {
+ mdbx_error("invalid page lower(%u)/upper(%u), pg-limit %u", p->mp_lower,
+ p->mp_upper, env->me_psize - PAGEHDRSZ);
return MDBX_CORRUPTED;
+ }
/* TODO: more checks here, including p->mp_validator */
*ret = p;
@@ -9393,10 +9464,10 @@ int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cursor **ret) {
: sizeof(MDBX_cursor);
MDBX_cursor *mc;
- if (likely((mc = malloc(size)) != NULL)) {
+ if (likely((mc = mdbx_malloc(size)) != NULL)) {
int rc = mdbx_cursor_init(mc, txn, dbi);
if (unlikely(rc != MDBX_SUCCESS)) {
- free(mc);
+ mdbx_free(mc);
return rc;
}
if (txn->mt_cursors) {
@@ -9508,7 +9579,7 @@ void mdbx_cursor_close(MDBX_cursor *mc) {
*prev = mc->mc_next;
}
mc->mc_signature = 0;
- free(mc);
+ mdbx_free(mc);
} else {
/* cursor closed before nested txn ends */
mdbx_cassert(mc, mc->mc_signature == MDBX_MC_SIGNATURE);
@@ -11248,7 +11319,7 @@ static int __cold mdbx_env_cwalk(mdbx_copy *my, pgno_t *pg, int flags) {
return rc;
/* Make cursor pages writable */
- buf = ptr = malloc(pgno2bytes(my->mc_env, mc.mc_snum));
+ buf = ptr = mdbx_malloc(pgno2bytes(my->mc_env, mc.mc_snum));
if (buf == NULL)
return MDBX_ENOMEM;
@@ -11373,7 +11444,7 @@ static int __cold mdbx_env_cwalk(mdbx_copy *my, pgno_t *pg, int flags) {
}
}
done:
- free(buf);
+ mdbx_free(buf);
return rc;
}
@@ -11545,7 +11616,7 @@ int __cold mdbx_env_copy(MDBX_env *env, const char *dest_path, unsigned flags) {
} else {
size_t len = strlen(dest_path);
len += sizeof(MDBX_DATANAME);
- dxb_pathname = malloc(len);
+ dxb_pathname = mdbx_malloc(len);
if (!dxb_pathname)
return MDBX_ENOMEM;
sprintf(dxb_pathname, "%s" MDBX_DATANAME, dest_path);
@@ -11578,7 +11649,7 @@ int __cold mdbx_env_copy(MDBX_env *env, const char *dest_path, unsigned flags) {
}
if (dxb_pathname != dest_path)
- free(dxb_pathname);
+ mdbx_free(dxb_pathname);
return rc;
}
@@ -11897,7 +11968,7 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags,
int err = mdbx_fastmutex_acquire(&env->me_dbi_lock);
if (unlikely(err != MDBX_SUCCESS)) {
- free(namedup);
+ mdbx_free(namedup);
return err;
}
@@ -11961,7 +12032,7 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags,
if (unlikely(rc != MDBX_SUCCESS)) {
mdbx_tassert(txn, (dbflag & DB_CREAT) == 0);
bailout:
- free(namedup);
+ mdbx_free(namedup);
} else {
txn->mt_dbiseqs[slot] = (env->me_dbiseqs[slot] += 1);
txn->mt_dbflags[slot] = (uint8_t)dbflag;
@@ -12032,7 +12103,7 @@ static int mdbx_dbi_close_locked(MDBX_env *env, MDBX_dbi dbi) {
mdbx_compiler_barrier();
env->me_dbiseqs[dbi]++;
env->me_dbxs[dbi].md_name.iov_base = NULL;
- free(ptr);
+ mdbx_free(ptr);
return MDBX_SUCCESS;
}
@@ -12391,7 +12462,14 @@ int __cold mdbx_reader_check0(MDBX_env *env, int rdt_locked, int *dead) {
}
const unsigned snap_nreaders = lck->mti_numreaders;
- mdbx_pid_t *pids = alloca((snap_nreaders + 1) * sizeof(mdbx_pid_t));
+ mdbx_pid_t pidsbuf_onstask[142];
+ mdbx_pid_t *const pids =
+ (snap_nreaders < ARRAY_LENGTH(pidsbuf_onstask))
+ ? pidsbuf_onstask
+ : mdbx_malloc((snap_nreaders + 1) * sizeof(mdbx_pid_t));
+ if (unlikely(!pids))
+ return MDBX_ENOMEM;
+
pids[0] = 0;
int rc = MDBX_SUCCESS, count = 0;
@@ -12457,6 +12535,9 @@ int __cold mdbx_reader_check0(MDBX_env *env, int rdt_locked, int *dead) {
if (rdt_locked < 0)
mdbx_rdt_unlock(env);
+ if (pids != pidsbuf_onstask)
+ mdbx_free(pids);
+
if (dead)
*dead = count;
return rc;
@@ -12747,9 +12828,20 @@ static int __cold mdbx_env_walk(mdbx_walk_ctx_t *ctx, const char *dbi,
MDBX_db db;
memcpy(&db, NODEDATA(node), sizeof(db));
- char *name = memcpy(alloca(namelen + 1), NODEKEY(node), namelen);
- name[namelen] = 0;
- rc = mdbx_env_walk(ctx, name, db.md_root, deep + 1);
+
+ char namebuf_onstask[142];
+ char *const name = (namelen < sizeof(namebuf_onstask))
+ ? namebuf_onstask
+ : mdbx_malloc(namelen + 1);
+ if (name) {
+ memcpy(name, NODEKEY(node), namelen);
+ name[namelen] = 0;
+ rc = mdbx_env_walk(ctx, name, db.md_root, deep + 1);
+ if (name != namebuf_onstask)
+ mdbx_free(name);
+ } else {
+ rc = MDBX_ENOMEM;
+ }
} break;
case F_SUBDATA | F_DUPDATA /* dupsorted sub-tree */: {
@@ -13276,6 +13368,14 @@ int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result,
if (unlikely(TXN_DBI_CHANGED(txn, dbi)))
return MDBX_BAD_DBI;
+ if (unlikely(txn->mt_dbflags[dbi] & DB_STALE)) {
+ MDBX_cursor_couple cx;
+ /* Stale, must read the DB's root. cursor_init does it for us. */
+ int rc = mdbx_cursor_init(&cx.outer, txn, dbi);
+ if (unlikely(rc != MDBX_SUCCESS))
+ return rc;
+ }
+
MDBX_db *dbs = &txn->mt_dbs[dbi];
if (likely(result))
*result = dbs->md_seq;
diff --git a/libs/libmdbx/src/src/osal.c b/libs/libmdbx/src/src/osal.c
index 738a179465..b39eea4be8 100644
--- a/libs/libmdbx/src/src/osal.c
+++ b/libs/libmdbx/src/src/osal.c
@@ -53,6 +53,9 @@ static int ntstatus2errcode(NTSTATUS status) {
* declare them here. Using these APIs also means we must link to
* ntdll.dll, which is not linked by default in user code. */
#pragma comment(lib, "ntdll.lib")
+#ifdef MDBX_AVOID_CRT
+#pragma comment(lib, "mdbx_ntdll_extra.lib")
+#endif
extern NTSTATUS NTAPI NtCreateSection(
OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess,
@@ -137,6 +140,15 @@ typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 {
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS)0xC0000010L)
#endif
+#ifndef FILE_DEVICE_FILE_SYSTEM
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#endif
+
+#ifndef FSCTL_GET_EXTERNAL_BACKING
+#define FSCTL_GET_EXTERNAL_BACKING \
+ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 196, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#endif
+
#endif /* _WIN32 || _WIN64 */
/*----------------------------------------------------------------------------*/
@@ -145,13 +157,8 @@ typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 {
/* Prototype should match libc runtime. ISO POSIX (2003) & LSB 3.1 */
__nothrow __noreturn void __assert_fail(const char *assertion, const char *file,
unsigned line, const char *function);
-#else
-__extern_C __declspec(dllimport) void __cdecl _assert(char const *message,
- char const *filename,
- unsigned line);
#endif /* _MSC_VER */
-#ifndef mdbx_assert_fail
void __cold mdbx_assert_fail(const MDBX_env *env, const char *msg,
const char *func, int line) {
#if MDBX_DEBUG
@@ -165,49 +172,57 @@ void __cold mdbx_assert_fail(const MDBX_env *env, const char *msg,
if (mdbx_debug_logger)
mdbx_debug_log(MDBX_DBG_ASSERT, func, line, "assert: %s\n", msg);
-#ifndef _MSC_VER
- __assert_fail(msg, "mdbx", line, func);
+ else {
+#if defined(_WIN32) || defined(_WIN64)
+ char *message = nullptr;
+ const int num = mdbx_asprintf(&message, "\r\nMDBX-ASSERTION: %s, %s:%u",
+ msg, func ? func : "unknown", line);
+ if (num < 1 || !message)
+ message = "<troubles with assertion-message preparation>";
+ OutputDebugStringA(message);
+ if (IsDebuggerPresent())
+ DebugBreak();
#else
- _assert(msg, func, line);
-#endif /* _MSC_VER */
+ __assert_fail(msg, "mdbx", line, func);
+#endif
+ }
+
+#if defined(_WIN32) || defined(_WIN64)
+ FatalExit(ERROR_UNHANDLED_ERROR);
+#else
+ abort();
+#endif
}
-#endif /* mdbx_assert_fail */
__cold void mdbx_panic(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
-#ifdef _MSC_VER
- if (IsDebuggerPresent()) {
- OutputDebugStringA("\r\n" FIXME "\r\n");
- FatalExit(ERROR_UNHANDLED_ERROR);
- }
-#elif _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L || \
- (__GLIBC_PREREQ(1, 0) && !__GLIBC_PREREQ(2, 10) && defined(_GNU_SOURCE))
- vdprintf(STDERR_FILENO, fmt, ap);
-#else
-#error FIXME
-#endif
+
+ char *message = nullptr;
+ const int num = mdbx_vasprintf(&message, fmt, ap);
va_end(ap);
+ if (num < 1 || !message)
+ message = "<troubles with panic-message preparation>";
+
+#if defined(_WIN32) || defined(_WIN64)
+ OutputDebugStringA("\r\nMDBX-PANIC: ");
+ OutputDebugStringA(message);
+ if (IsDebuggerPresent())
+ DebugBreak();
+ FatalExit(ERROR_UNHANDLED_ERROR);
+#else
+ __assert_fail(message, "mdbx", 0, "panic");
abort();
+#endif
}
/*----------------------------------------------------------------------------*/
-#ifndef mdbx_asprintf
-int mdbx_asprintf(char **strp, const char *fmt, ...) {
- va_list ap, ones;
-
- va_start(ap, fmt);
+#ifndef mdbx_vasprintf
+int mdbx_vasprintf(char **strp, const char *fmt, va_list ap) {
+ va_list ones;
va_copy(ones, ap);
-#ifdef _MSC_VER
- int needed = _vscprintf(fmt, ap);
-#elif defined(vsnprintf) || defined(_BSD_SOURCE) || _XOPEN_SOURCE >= 500 || \
- defined(_ISOC99_SOURCE) || _POSIX_C_SOURCE >= 200112L
int needed = vsnprintf(nullptr, 0, fmt, ap);
-#else
-#error FIXME
-#endif
- va_end(ap);
if (unlikely(needed < 0 || needed >= INT_MAX)) {
*strp = nullptr;
@@ -215,34 +230,44 @@ int mdbx_asprintf(char **strp, const char *fmt, ...) {
return needed;
}
- *strp = malloc(needed + 1);
+ *strp = mdbx_malloc(needed + 1);
if (unlikely(*strp == nullptr)) {
va_end(ones);
+#if defined(_WIN32) || defined(_WIN64)
SetLastError(MDBX_ENOMEM);
+#else
+ errno = MDBX_ENOMEM;
+#endif
return -1;
}
-#if defined(vsnprintf) || defined(_BSD_SOURCE) || _XOPEN_SOURCE >= 500 || \
- defined(_ISOC99_SOURCE) || _POSIX_C_SOURCE >= 200112L
int actual = vsnprintf(*strp, needed + 1, fmt, ones);
-#else
-#error FIXME
-#endif
va_end(ones);
assert(actual == needed);
if (unlikely(actual < 0)) {
- free(*strp);
+ mdbx_free(*strp);
*strp = nullptr;
}
return actual;
}
+#endif /* mdbx_vasprintf */
+
+#ifndef mdbx_asprintf
+int mdbx_asprintf(char **strp, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ int rc = mdbx_vasprintf(strp, fmt, ap);
+ va_end(ap);
+ return rc;
+}
#endif /* mdbx_asprintf */
#ifndef mdbx_memalign_alloc
int mdbx_memalign_alloc(size_t alignment, size_t bytes, void **result) {
-#if _MSC_VER
- *result = _aligned_malloc(bytes, alignment);
+#if defined(_WIN32) || defined(_WIN64)
+ (void)alignment;
+ *result = VirtualAlloc(NULL, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
return *result ? MDBX_SUCCESS : MDBX_ENOMEM /* ERROR_OUTOFMEMORY */;
#elif __GLIBC_PREREQ(2, 16) || __STDC_VERSION__ >= 201112L
*result = memalign(alignment, bytes);
@@ -258,14 +283,26 @@ int mdbx_memalign_alloc(size_t alignment, size_t bytes, void **result) {
#ifndef mdbx_memalign_free
void mdbx_memalign_free(void *ptr) {
-#if _MSC_VER
- _aligned_free(ptr);
+#if defined(_WIN32) || defined(_WIN64)
+ VirtualFree(ptr, 0, MEM_RELEASE);
#else
- free(ptr);
+ mdbx_free(ptr);
#endif
}
#endif /* mdbx_memalign_free */
+#ifndef mdbx_strdup
+char *mdbx_strdup(const char *str) {
+ if (!str)
+ return NULL;
+ size_t bytes = strlen(str) + 1;
+ char *dup = mdbx_malloc(bytes);
+ if (dup)
+ memcpy(dup, str, bytes);
+ return dup;
+}
+#endif /* mdbx_strdup */
+
/*----------------------------------------------------------------------------*/
int mdbx_condmutex_init(mdbx_condmutex_t *condmutex) {
@@ -797,33 +834,47 @@ int mdbx_check4nonlocal(mdbx_filehandle_t handle, int flags) {
}
if (mdbx_GetVolumeInformationByHandleW && mdbx_GetFinalPathNameByHandleW) {
- WCHAR PathBuffer[INT16_MAX];
+ WCHAR *PathBuffer = mdbx_malloc(sizeof(WCHAR) * INT16_MAX);
+ if (!PathBuffer)
+ return MDBX_ENOMEM;
+
+ int rc = MDBX_SUCCESS;
DWORD VolumeSerialNumber, FileSystemFlags;
if (!mdbx_GetVolumeInformationByHandleW(handle, PathBuffer, INT16_MAX,
&VolumeSerialNumber, NULL,
- &FileSystemFlags, NULL, 0))
- return GetLastError();
+ &FileSystemFlags, NULL, 0)) {
+ rc = GetLastError();
+ goto bailout;
+ }
if ((flags & MDBX_RDONLY) == 0) {
- if (FileSystemFlags & (FILE_SEQUENTIAL_WRITE_ONCE |
- FILE_READ_ONLY_VOLUME | FILE_VOLUME_IS_COMPRESSED))
- return ERROR_REMOTE_STORAGE_MEDIA_ERROR;
+ if (FileSystemFlags &
+ (FILE_SEQUENTIAL_WRITE_ONCE | FILE_READ_ONLY_VOLUME |
+ FILE_VOLUME_IS_COMPRESSED)) {
+ rc = ERROR_REMOTE_STORAGE_MEDIA_ERROR;
+ goto bailout;
+ }
}
if (!mdbx_GetFinalPathNameByHandleW(handle, PathBuffer, INT16_MAX,
- FILE_NAME_NORMALIZED | VOLUME_NAME_NT))
- return GetLastError();
+ FILE_NAME_NORMALIZED |
+ VOLUME_NAME_NT)) {
+ rc = GetLastError();
+ goto bailout;
+ }
if (_wcsnicmp(PathBuffer, L"\\Device\\Mup\\", 12) == 0) {
- if (!(flags & MDBX_EXCLUSIVE))
- return ERROR_REMOTE_STORAGE_MEDIA_ERROR;
+ if (!(flags & MDBX_EXCLUSIVE)) {
+ rc = ERROR_REMOTE_STORAGE_MEDIA_ERROR;
+ goto bailout;
+ }
} else if (mdbx_GetFinalPathNameByHandleW(handle, PathBuffer, INT16_MAX,
FILE_NAME_NORMALIZED |
VOLUME_NAME_DOS)) {
UINT DriveType = GetDriveTypeW(PathBuffer);
if (DriveType == DRIVE_NO_ROOT_DIR &&
- wcsncmp(PathBuffer, L"\\\\?\\", 4) == 0 &&
- wcsncmp(PathBuffer + 5, L":\\", 2) == 0) {
+ _wcsnicmp(PathBuffer, L"\\\\?\\", 4) == 0 &&
+ _wcsnicmp(PathBuffer + 5, L":\\", 2) == 0) {
PathBuffer[7] = 0;
DriveType = GetDriveTypeW(PathBuffer + 4);
}
@@ -837,7 +888,7 @@ int mdbx_check4nonlocal(mdbx_filehandle_t handle, int flags) {
case DRIVE_REMOTE:
default:
if (!(flags & MDBX_EXCLUSIVE))
- return ERROR_REMOTE_STORAGE_MEDIA_ERROR;
+ rc = ERROR_REMOTE_STORAGE_MEDIA_ERROR;
// fall through
case DRIVE_REMOVABLE:
case DRIVE_FIXED:
@@ -845,6 +896,9 @@ int mdbx_check4nonlocal(mdbx_filehandle_t handle, int flags) {
break;
}
}
+ bailout:
+ mdbx_free(PathBuffer);
+ return rc;
}
#else
(void)handle;
@@ -1019,11 +1073,11 @@ int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t size, size_t limit) {
&ReservedSize, MEM_RESERVE, PAGE_NOACCESS);
if (!NT_SUCCESS(status)) {
ReservedAddress = NULL;
- if (status != /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018 ||
- limit == map->length)
+ if (status != /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018)
goto bailout_ntstatus /* no way to recovery */;
- /* assume we can change base address if mapping size changed */
+ /* assume we can change base address if mapping size changed or prev address
+ * couldn't be used */
map->address = NULL;
}
@@ -1080,8 +1134,8 @@ retry_mapview:;
if (!NT_SUCCESS(status)) {
if (status == /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018 &&
- map->address && limit != map->length) {
- /* try remap at another base address, but only if the limit is changing */
+ map->address) {
+ /* try remap at another base address */
map->address = NULL;
goto retry_mapview;
}
diff --git a/libs/libmdbx/src/src/osal.h b/libs/libmdbx/src/src/osal.h
index 065128103e..50416d960c 100644
--- a/libs/libmdbx/src/src/osal.h
+++ b/libs/libmdbx/src/src/osal.h
@@ -28,10 +28,16 @@
#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \
* mode specified; termination on exception is \
* not guaranteed. Specify /EHsc */
+#endif /* _MSC_VER (warnings) */
+
+#if defined(_WIN32) || defined(_WIN64)
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
-#endif /* _MSC_VER (warnings) */
+#if !defined(_NO_CRT_STDIO_INLINE) && defined(MDBX_BUILD_DLL)
+#define _NO_CRT_STDIO_INLINE
+#endif
+#endif /* Windows */
/*----------------------------------------------------------------------------*/
/* C99 includes */
@@ -84,7 +90,47 @@ typedef struct {
HANDLE event;
} mdbx_condmutex_t;
typedef CRITICAL_SECTION mdbx_fastmutex_t;
+
+#ifdef MDBX_AVOID_CRT
+#ifndef mdbx_malloc
+static inline void *mdbx_malloc(size_t bytes) {
+ return LocalAlloc(LMEM_FIXED, bytes);
+}
+#endif /* mdbx_malloc */
+
+#ifndef mdbx_calloc
+static inline void *mdbx_calloc(size_t nelem, size_t size) {
+ return LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, nelem * size);
+}
+#endif /* mdbx_calloc */
+
+#ifndef mdbx_realloc
+static inline void *mdbx_realloc(void *ptr, size_t bytes) {
+ return LocalReAlloc(ptr, bytes, LMEM_MOVEABLE);
+}
+#endif /* mdbx_realloc */
+
+#ifndef mdbx_free
+#define mdbx_free LocalFree
+#endif /* mdbx_free */
#else
+#define mdbx_malloc malloc
+#define mdbx_calloc calloc
+#define mdbx_realloc realloc
+#define mdbx_free free
+#define mdbx_strdup _strdup
+#endif /* MDBX_AVOID_CRT */
+
+#ifndef snprintf
+#define snprintf _snprintf /* ntdll */
+#endif
+
+#ifndef vsnprintf
+#define vsnprintf _vsnprintf /* ntdll */
+#endif
+
+#else /*----------------------------------------------------------------------*/
+
#include <pthread.h>
#include <signal.h>
#include <sys/file.h>
@@ -103,6 +149,11 @@ typedef struct {
pthread_cond_t cond;
} mdbx_condmutex_t;
typedef pthread_mutex_t mdbx_fastmutex_t;
+#define mdbx_malloc malloc
+#define mdbx_calloc calloc
+#define mdbx_realloc realloc
+#define mdbx_free free
+#define mdbx_strdup strdup
#endif /* Platform */
/* *INDENT-OFF* */
@@ -379,36 +430,14 @@ static __inline void mdbx_invalidate_cache(void *addr, size_t nbytes) {
/*----------------------------------------------------------------------------*/
/* libc compatibility stuff */
-#ifndef mdbx_assert_fail
-void mdbx_assert_fail(const MDBX_env *env, const char *msg, const char *func,
- int line);
-#endif /* mdbx_assert_fail */
-
#if __GLIBC_PREREQ(2, 1)
#define mdbx_asprintf asprintf
+#define mdbx_vasprintf vasprintf
#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 */
-
-#ifdef _ASSERTE
-#undef assert
-#define assert _ASSERTE
+__printf_args(2, 3) int mdbx_asprintf(char **strp, const char *fmt, ...);
+int mdbx_vasprintf(char **strp, const char *fmt, va_list ap);
#endif
-#endif /* _MSC_VER */
-
/*----------------------------------------------------------------------------*/
/* OS abstraction layer stuff */
@@ -428,13 +457,9 @@ static __inline size_t mdbx_syspagesize(void) {
#endif
}
-static __inline char *mdbx_strdup(const char *str) {
-#ifdef _MSC_VER
- return _strdup(str);
-#else
- return strdup(str);
+#ifndef mdbx_strdup
+LIBMDBX_API char *mdbx_strdup(const char *str);
#endif
-}
static __inline int mdbx_get_errno(void) {
#if defined(_WIN32) || defined(_WIN64)
@@ -445,8 +470,12 @@ static __inline int mdbx_get_errno(void) {
return rc;
}
+#ifndef mdbx_memalign_alloc
int mdbx_memalign_alloc(size_t alignment, size_t bytes, void **result);
+#endif
+#ifndef mdbx_memalign_free
void mdbx_memalign_free(void *ptr);
+#endif
int mdbx_condmutex_init(mdbx_condmutex_t *condmutex);
int mdbx_condmutex_lock(mdbx_condmutex_t *condmutex);
@@ -564,14 +593,12 @@ int mdbx_rpid_set(MDBX_env *env);
int mdbx_rpid_clear(MDBX_env *env);
#if defined(_WIN32) || defined(_WIN64)
-typedef struct MDBX_srwlock {
- union {
- struct {
- long volatile readerCount;
- long volatile writerCount;
- };
- RTL_SRWLOCK native;
+typedef union MDBX_srwlock {
+ struct {
+ long volatile readerCount;
+ long volatile writerCount;
};
+ RTL_SRWLOCK native;
} MDBX_srwlock;
typedef void(WINAPI *MDBX_srwlock_function)(MDBX_srwlock *);
@@ -652,6 +679,7 @@ static __inline uint32_t mdbx_atomic_add32(volatile uint32_t *p, uint32_t v) {
return __sync_fetch_and_add(p, v);
#else
#ifdef _MSC_VER
+ STATIC_ASSERT(sizeof(volatile long) == sizeof(volatile uint32_t));
return _InterlockedExchangeAdd((volatile long *)p, v);
#endif
#ifdef __APPLE__
@@ -692,7 +720,8 @@ static __inline bool mdbx_atomic_compare_and_swap32(volatile uint32_t *p,
return __sync_bool_compare_and_swap(p, c, v);
#else
#ifdef _MSC_VER
- return c == _InterlockedCompareExchange((volatile long*)p, v, c);
+ STATIC_ASSERT(sizeof(volatile long) == sizeof(volatile uint32_t));
+ return c == _InterlockedCompareExchange((volatile long *)p, v, c);
#endif
#ifdef __APPLE__
return c == OSAtomicCompareAndSwap32Barrier(c, v, (volatile int32_t *)p);
diff --git a/libs/libmdbx/src/src/tools/mdbx_chk.c b/libs/libmdbx/src/src/tools/mdbx_chk.c
index ddaff0ab4b..6614bdb219 100644
--- a/libs/libmdbx/src/src/tools/mdbx_chk.c
+++ b/libs/libmdbx/src/src/tools/mdbx_chk.c
@@ -1,4 +1,4 @@
-/* mdbx_chk.c - memory-mapped database check tool */
+/* mdbx_chk.c - memory-mapped database check tool */
/*
* Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
@@ -141,12 +141,12 @@ static void
static void pagemap_cleanup(void) {
for (int i = CORE_DBS; ++i < MAX_DBI;) {
if (walk.dbi[i].name) {
- free((void *)walk.dbi[i].name);
+ mdbx_free((void *)walk.dbi[i].name);
walk.dbi[i].name = NULL;
}
}
- free(walk.pagemap);
+ mdbx_free(walk.pagemap);
walk.pagemap = NULL;
}
@@ -164,7 +164,7 @@ static walk_dbi_t *pagemap_lookup_dbi(const char *dbi_name, bool silent) {
return NULL;
}
- dbi->name = strdup(dbi_name);
+ dbi->name = mdbx_strdup(dbi_name);
if (verbose > 1 && !silent) {
print(" - found '%s' area\n", dbi_name);
fflush(NULL);
@@ -190,7 +190,7 @@ static void
break;
if (!p) {
- p = calloc(1, sizeof(*p));
+ p = mdbx_calloc(1, sizeof(*p));
p->caption = msg;
p->pr_next = problems_list;
problems_list = p;
@@ -233,7 +233,7 @@ static uint64_t problems_pop(struct problem *list) {
count += problems_list->count;
print("%s%s (%" PRIu64 ")", i ? ", " : "", problems_list->caption,
problems_list->count);
- free(problems_list);
+ mdbx_free(problems_list);
problems_list = p;
}
print("\n");
@@ -497,13 +497,13 @@ static int handle_maindb(const uint64_t record_number, const MDBX_val *key,
return handle_userdb(record_number, key, data);
}
- name = malloc(key->iov_len + 1);
+ name = mdbx_malloc(key->iov_len + 1);
memcpy(name, key->iov_base, key->iov_len);
name[key->iov_len] = '\0';
userdb_count++;
rc = process_db(~0u, name, handle_userdb, false);
- free(name);
+ mdbx_free(name);
if (rc != MDBX_INCOMPATIBLE)
return rc;
@@ -1093,7 +1093,7 @@ int main(int argc, char *argv[]) {
print("Traversal b-tree by txn#%" PRIaTXN "...\n", txn->mt_txnid);
fflush(NULL);
- walk.pagemap = calloc((size_t)lastpgno, sizeof(*walk.pagemap));
+ walk.pagemap = mdbx_calloc((size_t)lastpgno, sizeof(*walk.pagemap));
if (!walk.pagemap) {
rc = errno ? errno : MDBX_ENOMEM;
error("calloc failed, error %d %s\n", rc, mdbx_strerror(rc));
diff --git a/libs/libmdbx/src/src/tools/mdbx_chk.vcxproj b/libs/libmdbx/src/src/tools/mdbx_chk.vcxproj
index d4cc420d36..e6c2686286 100644
--- a/libs/libmdbx/src/src/tools/mdbx_chk.vcxproj
+++ b/libs/libmdbx/src/src/tools/mdbx_chk.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
diff --git a/libs/libmdbx/src/src/tools/mdbx_copy.vcxproj b/libs/libmdbx/src/src/tools/mdbx_copy.vcxproj
index 6910060fcb..d47513c204 100644
--- a/libs/libmdbx/src/src/tools/mdbx_copy.vcxproj
+++ b/libs/libmdbx/src/src/tools/mdbx_copy.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
diff --git a/libs/libmdbx/src/src/tools/mdbx_dump.c b/libs/libmdbx/src/src/tools/mdbx_dump.c
index c854e0ad15..d16215622e 100644
--- a/libs/libmdbx/src/src/tools/mdbx_dump.c
+++ b/libs/libmdbx/src/src/tools/mdbx_dump.c
@@ -203,7 +203,8 @@ int main(int argc, char *argv[]) {
break;
case 'f':
if (freopen(optarg, "w", stdout) == NULL) {
- fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, strerror(errno));
+ fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg,
+ mdbx_strerror(errno));
exit(EXIT_FAILURE);
}
break;
@@ -292,7 +293,7 @@ int main(int argc, char *argv[]) {
if (memchr(key.iov_base, '\0', key.iov_len))
continue;
count++;
- str = malloc(key.iov_len + 1);
+ str = mdbx_malloc(key.iov_len + 1);
memcpy(str, key.iov_base, key.iov_len);
str[key.iov_len] = '\0';
rc = mdbx_dbi_open(txn, str, 0, &db2);
@@ -307,7 +308,7 @@ int main(int argc, char *argv[]) {
}
mdbx_dbi_close(env, db2);
}
- free(str);
+ mdbx_free(str);
if (rc)
continue;
}
diff --git a/libs/libmdbx/src/src/tools/mdbx_dump.vcxproj b/libs/libmdbx/src/src/tools/mdbx_dump.vcxproj
index b44eb19328..6978a2c22d 100644
--- a/libs/libmdbx/src/src/tools/mdbx_dump.vcxproj
+++ b/libs/libmdbx/src/src/tools/mdbx_dump.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
diff --git a/libs/libmdbx/src/src/tools/mdbx_load.c b/libs/libmdbx/src/src/tools/mdbx_load.c
index a18b50c491..697e3e166f 100644
--- a/libs/libmdbx/src/src/tools/mdbx_load.c
+++ b/libs/libmdbx/src/src/tools/mdbx_load.c
@@ -110,8 +110,8 @@ static void readhdr(void) {
if (ptr)
*ptr = '\0';
if (subname)
- free(subname);
- subname = strdup((char *)dbuf.iov_base + STRLENOF("database="));
+ mdbx_free(subname);
+ subname = mdbx_strdup((char *)dbuf.iov_base + STRLENOF("database="));
} else if (!strncmp(dbuf.iov_base, "type=", STRLENOF("type="))) {
if (strncmp((char *)dbuf.iov_base + STRLENOF("type="), "btree",
STRLENOF("btree"))) {
@@ -237,7 +237,7 @@ static int readline(MDBX_val *out, MDBX_val *buf) {
/* Is buffer too short? */
while (c1[len - 1] != '\n') {
- buf->iov_base = realloc(buf->iov_base, buf->iov_len * 2);
+ buf->iov_base = mdbx_realloc(buf->iov_base, buf->iov_len * 2);
if (!buf->iov_base) {
Eof = 1;
fprintf(stderr, "%s: line %" PRIiSIZE ": out of memory, line too long\n",
@@ -340,7 +340,8 @@ int main(int argc, char *argv[]) {
break;
case 'f':
if (freopen(optarg, "r", stdin) == NULL) {
- fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, strerror(errno));
+ fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg,
+ mdbx_strerror(errno));
exit(EXIT_FAILURE);
}
break;
@@ -348,7 +349,7 @@ int main(int argc, char *argv[]) {
envflags |= MDBX_NOSUBDIR;
break;
case 's':
- subname = strdup(optarg);
+ subname = mdbx_strdup(optarg);
break;
case 'N':
putflags = MDBX_NOOVERWRITE | MDBX_NODUPDATA;
@@ -378,7 +379,7 @@ int main(int argc, char *argv[]) {
#endif /* !WINDOWS */
dbuf.iov_len = 4096;
- dbuf.iov_base = malloc(dbuf.iov_len);
+ dbuf.iov_base = mdbx_malloc(dbuf.iov_len);
if (!(mode & NOHDR))
readhdr();
@@ -418,7 +419,7 @@ int main(int argc, char *argv[]) {
}
kbuf.iov_len = mdbx_env_get_maxkeysize(env) * 2 + 2;
- kbuf.iov_base = malloc(kbuf.iov_len);
+ kbuf.iov_base = mdbx_malloc(kbuf.iov_len);
while (!Eof) {
if (user_break) {
diff --git a/libs/libmdbx/src/src/tools/mdbx_load.vcxproj b/libs/libmdbx/src/src/tools/mdbx_load.vcxproj
index 6af6cc457c..05a100fc64 100644
--- a/libs/libmdbx/src/src/tools/mdbx_load.vcxproj
+++ b/libs/libmdbx/src/src/tools/mdbx_load.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
diff --git a/libs/libmdbx/src/src/tools/mdbx_stat.c b/libs/libmdbx/src/src/tools/mdbx_stat.c
index a219b9ec0e..95a6cdd23c 100644
--- a/libs/libmdbx/src/src/tools/mdbx_stat.c
+++ b/libs/libmdbx/src/src/tools/mdbx_stat.c
@@ -356,13 +356,13 @@ int main(int argc, char *argv[]) {
MDBX_dbi db2;
if (memchr(key.iov_base, '\0', key.iov_len))
continue;
- str = malloc(key.iov_len + 1);
+ str = mdbx_malloc(key.iov_len + 1);
memcpy(str, key.iov_base, key.iov_len);
str[key.iov_len] = '\0';
rc = mdbx_dbi_open(txn, str, 0, &db2);
if (rc == MDBX_SUCCESS)
printf("Status of %s\n", str);
- free(str);
+ mdbx_free(str);
if (rc)
continue;
rc = mdbx_dbi_stat(txn, db2, &mst, sizeof(mst));
diff --git a/libs/libmdbx/src/src/tools/mdbx_stat.vcxproj b/libs/libmdbx/src/src/tools/mdbx_stat.vcxproj
index 1adcefde89..4027491d39 100644
--- a/libs/libmdbx/src/src/tools/mdbx_stat.vcxproj
+++ b/libs/libmdbx/src/src/tools/mdbx_stat.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
diff --git a/libs/libmdbx/src/src/tools/wingetopt.c b/libs/libmdbx/src/src/tools/wingetopt.c
index 6ed6dc3cc8..7feb223fc1 100644
--- a/libs/libmdbx/src/src/tools/wingetopt.c
+++ b/libs/libmdbx/src/src/tools/wingetopt.c
@@ -55,7 +55,7 @@ char *optarg;
int getopt(int argc, char *const argv[], const char *opts) {
static int sp = 1;
int c;
- char *cp;
+ const char *cp;
if (sp == 1) {
if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
@@ -66,7 +66,7 @@ int getopt(int argc, char *const argv[], const char *opts) {
}
}
optopt = c = argv[optind][sp];
- if (c == ':' || (cp = (char *)strchr(opts, c)) == NULL) {
+ if (c == ':' || (cp = strchr(opts, c)) == NULL) {
ERR(": illegal option -- ", c);
if (argv[optind][++sp] == '\0') {
optind++;