mirror of
https://github.com/isar/libmdbx.git
synced 2025-12-16 17:12:23 +08:00
Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f5ae79b51 | ||
|
|
86b1f2017a | ||
|
|
9b1cddf520 | ||
|
|
251d34d6e6 | ||
|
|
8358dda7f1 | ||
|
|
76e29c21f1 | ||
|
|
56222db3ba | ||
|
|
5072b45026 | ||
|
|
63449a44c5 | ||
|
|
ecffc831fa | ||
|
|
6c76af5181 | ||
|
|
061d3cc8fd | ||
|
|
6248b67f75 | ||
|
|
fbf55e17cb | ||
|
|
289f2896d0 | ||
|
|
4fed2d9fc0 | ||
|
|
9aa816dc73 | ||
|
|
f750086bc1 | ||
|
|
bd3f234bce | ||
|
|
dbf9873e63 | ||
|
|
4bd194f4c1 | ||
|
|
8a6de15346 | ||
|
|
60a6560a3b | ||
|
|
d1173a1596 | ||
|
|
2356f3281b | ||
|
|
2db93efb14 | ||
|
|
cd0d84dbb6 | ||
|
|
8214d674be | ||
|
|
0714c07e28 | ||
|
|
62a39d84b3 | ||
|
|
6009bac1ed | ||
|
|
e475db7ade | ||
|
|
01f65bc872 | ||
|
|
49d9779c84 | ||
|
|
a594f79e5f | ||
|
|
17fe5f106b | ||
|
|
db27654330 | ||
|
|
1cbad5bd3f | ||
|
|
08753b46a1 | ||
|
|
aeda2aa8c5 | ||
|
|
fb1d600597 | ||
|
|
c1ad86c368 | ||
|
|
7ea1a4e0e8 | ||
|
|
2c08ec21fd | ||
|
|
d159a8252d | ||
|
|
308548e226 | ||
|
|
a8c5daf46a | ||
|
|
898b6ee433 | ||
|
|
2ce9ace4d3 | ||
|
|
1ee1b269e6 | ||
|
|
ebcbcbfe31 | ||
|
|
b77f4faadd | ||
|
|
bf28856ac5 |
@@ -25,7 +25,7 @@
|
||||
|
||||
##
|
||||
## libmdbx = { Revised and extended descendant of Symas LMDB. }
|
||||
## Please see README.md at https://github.com/leo-yuriev/libmdbx
|
||||
## Please see README.md at https://github.com/erthink/libmdbx
|
||||
##
|
||||
## Libmdbx is superior to LMDB in terms of features and reliability,
|
||||
## not inferior in performance. libmdbx works on Linux, FreeBSD, MacOS X
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
##
|
||||
## libmdbx = { Revised and extended descendant of Symas LMDB. }
|
||||
## Please see README.md at https://github.com/leo-yuriev/libmdbx
|
||||
## Please see README.md at https://github.com/erthink/libmdbx
|
||||
##
|
||||
## Libmdbx is superior to LMDB in terms of features and reliability,
|
||||
## not inferior in performance. libmdbx works on Linux, FreeBSD, MacOS X
|
||||
|
||||
@@ -236,10 +236,7 @@ dist/@tmp-shared_internals.inc: src/elements/version.c $(ALLOY_DEPS) $(lastword
|
||||
|
||||
dist/mdbx.c: dist/@tmp-shared_internals.inc $(lastword $(MAKEFILE_LIST))
|
||||
mkdir -p dist && (cat dist/@tmp-shared_internals.inc \
|
||||
&& cat src/elements/core.c src/elements/osal.c src/elements/version.c \
|
||||
&& echo '#if defined(_WIN32) || defined(_WIN64)' \
|
||||
&& cat src/elements/lck-windows.c && echo '#else /* LCK-implementation */' \
|
||||
&& cat src/elements/lck-posix.c && echo '#endif /* LCK-implementation */' \
|
||||
&& cat src/elements/core.c src/elements/osal.c src/elements/version.c src/elements/lck-windows.c src/elements/lck-posix.c \
|
||||
) | grep -v -e '#include "' -e '#pragma once' | sed 's|@INCLUDE|#include|' > $@
|
||||
|
||||
define dist-tool-rule
|
||||
|
||||
53
README.md
53
README.md
@@ -1,3 +1,5 @@
|
||||
<!-- Required extensions: pymdownx.betterem, pymdownx.tilde, pymdownx.emoji, pymdownx.tasklist, pymdownx.superfences -->
|
||||
|
||||
libmdbx
|
||||
=======
|
||||
|
||||
@@ -7,15 +9,25 @@ database, with [permissive license](LICENSE).
|
||||
_MDBX_ has a specific set of properties and capabilities,
|
||||
focused on creating unique lightweight solutions with extraordinary performance.
|
||||
|
||||
1. Allows **swarm of multi-threaded processes to [ACID]((https://en.wikipedia.org/wiki/ACID))ly read and update** several key-value [maps](https://en.wikipedia.org/wiki/Associative_array) and [multimaps](https://en.wikipedia.org/wiki/Multimap) in a localy-shared database.
|
||||
1. Allows **swarm of multi-threaded processes to
|
||||
[ACID]((https://en.wikipedia.org/wiki/ACID))ly read and update** several
|
||||
key-value [maps](https://en.wikipedia.org/wiki/Associative_array) and
|
||||
[multimaps](https://en.wikipedia.org/wiki/Multimap) in a localy-shared
|
||||
database.
|
||||
|
||||
2. Provides **extraordinary performance**, minimal overhead through [Memory-Mapping](https://en.wikipedia.org/wiki/Memory-mapped_file) and `Olog(N)` operations costs by virtue of [B+ tree](https://en.wikipedia.org/wiki/B%2B_tree).
|
||||
2. Provides **extraordinary performance**, minimal overhead through
|
||||
[Memory-Mapping](https://en.wikipedia.org/wiki/Memory-mapped_file) and
|
||||
`Olog(N)` operations costs by virtue of [B+
|
||||
tree](https://en.wikipedia.org/wiki/B%2B_tree).
|
||||
|
||||
3. Requires **no maintenance and no crash recovery** since doesn't use [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging), but that might be a caveat for write-intensive workloads.
|
||||
3. Requires **no maintenance and no crash recovery** since doesn't use
|
||||
[WAL](https://en.wikipedia.org/wiki/Write-ahead_logging), but that might
|
||||
be a caveat for write-intensive workloads with durability requirements.
|
||||
|
||||
4. **Compact and friendly for fully embeddeding**. Only 25KLOC of `C11`, 64K x86 binary code,
|
||||
no internal threads neither processes, but implements a simplified variant of the
|
||||
[Berkeley DB](https://en.wikipedia.org/wiki/Berkeley_DB) and
|
||||
4. **Compact and friendly for fully embeddeding**. Only 25KLOC of `C11`,
|
||||
64K x86 binary code, no internal threads neither processes, but
|
||||
implements a simplified variant of the [Berkeley
|
||||
DB](https://en.wikipedia.org/wiki/Berkeley_DB) and
|
||||
[dbm](https://en.wikipedia.org/wiki/DBM_(computing)) API.
|
||||
|
||||
5. Enforces [serializability](https://en.wikipedia.org/wiki/Serializability) for
|
||||
@@ -47,8 +59,9 @@ _MithrilDB_ is rightly relevant name.
|
||||
> revolution is to provide a clearer and robust API, add more features and
|
||||
> new valuable properties of database.
|
||||
|
||||
[](https://travis-ci.org/leo-yuriev/libmdbx)
|
||||
[](https://ci.appveyor.com/project/leo-yuriev/libmdbx/branch/master)
|
||||
[](https://t.me/libmdbx)
|
||||
[](https://travis-ci.org/erthink/libmdbx)
|
||||
[](https://ci.appveyor.com/project/erthink/libmdbx/branch/master)
|
||||
[](https://scan.coverity.com/projects/reopen-libmdbx)
|
||||
|
||||
*The Future will (be) [Positive](https://www.ptsecurity.com). Всё будет хорошо.*
|
||||
@@ -183,6 +196,9 @@ the user's point of view.
|
||||
> _libmdbx_ manage the database size according to parameters specified
|
||||
> by `mdbx_env_set_geometry()` function,
|
||||
> ones include the growth step and the truncation threshold.
|
||||
>
|
||||
> Unfortunately, on-the-fly database size adjustment doesn't work under [Wine](https://en.wikipedia.org/wiki/Wine_(software))
|
||||
> due to its internal limitations and unimplemented functions, i.e. the `MDBX_UNABLE_EXTEND_MAPSIZE` error will be returned.
|
||||
|
||||
4. Automatic continuous zero-overhead database compactification.
|
||||
> During each commit _libmdbx_ merges suitable freeing pages into unallocated area
|
||||
@@ -266,12 +282,12 @@ named mutexes are used.
|
||||
|
||||
### History
|
||||
At first the development was carried out within the
|
||||
[ReOpenLDAP](https://github.com/leo-yuriev/ReOpenLDAP) project. About a
|
||||
[ReOpenLDAP](https://github.com/erthink/ReOpenLDAP) project. About a
|
||||
year later _libmdbx_ was separated into standalone project, which was
|
||||
[presented at Highload++ 2015
|
||||
conference](http://www.highload.ru/2015/abstracts/1831.html).
|
||||
|
||||
Since 2017 _libmdbx_ is used in [Fast Positive Tables](https://github.com/leo-yuriev/libfpta),
|
||||
Since 2017 _libmdbx_ is used in [Fast Positive Tables](https://github.com/erthink/libfpta),
|
||||
and development is funded by [Positive Technologies](https://www.ptsecurity.com).
|
||||
|
||||
### Acknowledgments
|
||||
@@ -407,9 +423,9 @@ For more information and API description see the [mdbx.h](mdbx.h) header.
|
||||
|
||||
| Runtime | GitHub | Author |
|
||||
| -------- | ------ | ------ |
|
||||
| Rust | [mdbx-rs](https://github.com/Kerollmops/mdbx-rs) | [@Kerollmops](https://github.com/Kerollmops) |
|
||||
| Java | [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) |
|
||||
| Rust | [mdbx-rs](https://github.com/Kerollmops/mdbx-rs) | [Clément Renault](https://github.com/Kerollmops) |
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -443,7 +459,7 @@ Here showed sum of performance metrics in 3 benchmarks:
|
||||
|
||||
2. Performance gap is too high to compare in any meaningful way.
|
||||
|
||||

|
||||

|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -452,7 +468,7 @@ Here showed sum of performance metrics in 3 benchmarks:
|
||||
Summary performance with concurrent read/search queries in 1-2-4-8
|
||||
threads on 4 CPU cores machine.
|
||||
|
||||

|
||||

|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -474,7 +490,7 @@ In the benchmark each transaction contains combined CRUD operations (2
|
||||
inserts, 1 read, 1 update, 1 delete). Benchmark starts on empty database
|
||||
and after full run the database contains 10,000 small key-value records.
|
||||
|
||||

|
||||

|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -501,7 +517,7 @@ and after full run the database contains 100,000 small key-value
|
||||
records.
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -525,7 +541,7 @@ In the benchmark each transaction contains combined CRUD operations (2
|
||||
inserts, 1 read, 1 update, 1 delete). Benchmark starts on empty database
|
||||
and after full run the database contains 10,000 small key-value records.
|
||||
|
||||

|
||||

|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -549,9 +565,8 @@ All benchmark data is gathered by
|
||||
[getrusage()](http://man7.org/linux/man-pages/man2/getrusage.2.html)
|
||||
syscall and by scanning data directory.
|
||||
|
||||

|
||||

|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### The [repository now only mirrored on the Github](https://abf.io/erthink/libmdbx) due to illegal discriminatory restrictions for Russian Crimea and for sovereign crimeans.
|
||||
<!-- Required extensions: pymdownx.betterem, pymdownx.tilde, pymdownx.emoji, pymdownx.tasklist, pymdownx.superfences -->
|
||||
#### This is a mirror of the origin repository that was moved to [abf.io](https://abf.io/erthink/) because of discriminatory restrictions for Russian Crimea.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: 0.6.0.{build}
|
||||
version: 0.7.0.{build}
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
|
||||
@@ -214,14 +214,6 @@ else()
|
||||
check_compiler_flag("-Ominimal" CC_HAS_OMINIMAL)
|
||||
check_compiler_flag("-ffunction-sections -fdata-sections" CC_HAS_SECTIONS)
|
||||
check_compiler_flag("-ffast-math" CC_HAS_FASTMATH)
|
||||
|
||||
# Check for an omp support
|
||||
set(CMAKE_REQUIRED_FLAGS "-fopenmp -Werror")
|
||||
check_cxx_source_compiles("int main(void) {
|
||||
#pragma omp parallel
|
||||
return 0;
|
||||
}" HAVE_OPENMP)
|
||||
set(CMAKE_REQUIRED_FLAGS "")
|
||||
endif()
|
||||
|
||||
# Check for LTO support by GCC
|
||||
@@ -367,7 +359,7 @@ if(CMAKE_COMPILER_IS_CLANG)
|
||||
set(CMAKE_CLANG_NM ${CMAKE_NM})
|
||||
endif()
|
||||
if (NOT CMAKE_CLANG_RANLIB)
|
||||
set(CMAKE_CLANG_RANLIB ${CMAKE_RANLIB })
|
||||
set(CMAKE_CLANG_RANLIB ${CMAKE_RANLIB})
|
||||
endif()
|
||||
message(STATUS "Assume Link-Time Optimization by CLANG/LLVM is available via ${CMAKE_TOOLCHAIN_FILE}")
|
||||
else()
|
||||
@@ -534,10 +526,6 @@ macro(setup_compile_flags)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(HAVE_OPENMP)
|
||||
add_compile_flags("C;CXX" "-fopenmp")
|
||||
endif()
|
||||
|
||||
if (ENABLE_ASAN)
|
||||
add_compile_flags("C;CXX" -fsanitize=address)
|
||||
endif()
|
||||
|
||||
245
mdbx.h
245
mdbx.h
@@ -201,6 +201,14 @@
|
||||
* necessary) in a child process would be both extreme complicated and so
|
||||
* fragile.
|
||||
*
|
||||
* Do not start more than one transaction for a one thread. If you think about
|
||||
* this, it's really strange to do something with two data snapshots at once,
|
||||
* which may be different. MDBX checks and preventing this by returning
|
||||
* corresponding error code (MDBX_TXN_OVERLAPPING, MDBX_BAD_RSLOT, MDBX_BUSY)
|
||||
* unless you using MDBX_NOTLS option on the environment. Nonetheless, with the
|
||||
* MDBX_NOTLS option, you must know exactly what you are doing, otherwise you
|
||||
* will get deadlocks or reading an alien data.
|
||||
*
|
||||
* Also note that a transaction is tied to one thread by default using Thread
|
||||
* Local Storage. If you want to pass read-only transactions across threads,
|
||||
* you can use the MDBX_NOTLS option on the environment. Nevertheless, a write
|
||||
@@ -298,19 +306,19 @@
|
||||
* - optimize (bulk) loading speed
|
||||
* - (temporarily) reduce robustness to gain even more speed
|
||||
* - gather statistics about the database
|
||||
* - define custom sort orders
|
||||
* - estimate size of range query result
|
||||
* - double perfomance by LIFO reclaiming on storages with write-back
|
||||
* - use sequences and canary markers
|
||||
* - use lack-of-space callback (aka OOM-KICK)
|
||||
* - use exclusive mode
|
||||
* - define custom sort orders (but this is recommended to be avoided)
|
||||
*
|
||||
*
|
||||
**** RESTRICTIONS & CAVEATS ***************************************************
|
||||
* in addition to those listed for some functions.
|
||||
*
|
||||
* - Troubleshooting the LCK-file.
|
||||
* 1. A broken LCK-file can cause sync issues, including appearance of
|
||||
* 1. A broken LCK-file can cause sync issues, including appearance of
|
||||
* wrong/inconsistent data for readers. When database opened in the
|
||||
* cooperative read-write mode the LCK-file requires to be mapped to
|
||||
* memory in read-write access. In this case it is always possible for
|
||||
@@ -327,14 +335,14 @@
|
||||
* Workaround: Just make all programs using the database close it;
|
||||
* the LCK-file is always reset on first open.
|
||||
*
|
||||
* 2. Stale reader transactions left behind by an aborted program cause
|
||||
* 2. Stale reader transactions left behind by an aborted program cause
|
||||
* further writes to grow the database quickly, and stale locks can
|
||||
* block further operation.
|
||||
* MDBX checks for stale readers while opening environment and before
|
||||
* growth the database. But in some cases, this may not be enough.
|
||||
*
|
||||
* Workaround: Check for stale readers periodically, using the
|
||||
* mdbx_reader_check() function or the mdbx_stat tool.
|
||||
* mdbx_reader_check() function or the mdbx_stat tool.
|
||||
*
|
||||
* 3. Stale writers will be cleared automatically by MDBX on supprted
|
||||
* platforms. But this is platform-specific, especially of
|
||||
@@ -379,10 +387,18 @@
|
||||
* The "next" version of libmdbx (MithrilDB) will solve this issue.
|
||||
*
|
||||
* - A thread can only use one transaction at a time, plus any nested
|
||||
* read-write transactions in the non-writemap mode. Each transaction
|
||||
* read-write transactions in the non-writemap mode. Each transaction
|
||||
* belongs to one thread. The MDBX_NOTLS flag changes this for read-only
|
||||
* transactions. See below.
|
||||
*
|
||||
* Do not start more than one transaction for a one thread. If you think
|
||||
* about this, it's really strange to do something with two data snapshots
|
||||
* at once, which may be different. MDBX checks and preventing this by
|
||||
* returning corresponding error code (MDBX_TXN_OVERLAPPING, MDBX_BAD_RSLOT,
|
||||
* MDBX_BUSY) unless you using MDBX_NOTLS option on the environment.
|
||||
* Nonetheless, with the MDBX_NOTLS option, you must know exactly what you
|
||||
* are doing, otherwise you will get deadlocks or reading an alien data.
|
||||
*
|
||||
* - Do not have open an MDBX database twice in the same process at the same
|
||||
* time. By default MDBX prevent this in most cases by tracking databases
|
||||
* opening and return MDBX_BUSY if anyone LCK-file is already open.
|
||||
@@ -451,7 +467,7 @@
|
||||
* above.
|
||||
*
|
||||
* - An MDBX database configuration will often reserve considerable unused
|
||||
* memory address space and maybe file size for future growth. This does
|
||||
* memory address space and maybe file size for future growth. This does
|
||||
* not use actual memory or disk space, but users may need to understand
|
||||
* the difference so they won't be scared off.
|
||||
*
|
||||
@@ -607,8 +623,8 @@ typedef pthread_t mdbx_tid_t;
|
||||
|
||||
#ifndef __dll_export
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#if defined(__GNUC__) || __has_attribute(dllexport)
|
||||
#define __dll_export __attribute__((dllexport))
|
||||
#if defined(__GNUC__) || __has_attribute(__dllexport__)
|
||||
#define __dll_export __attribute__((__dllexport__))
|
||||
#elif defined(_MSC_VER)
|
||||
#define __dll_export __declspec(dllexport)
|
||||
#else
|
||||
@@ -623,8 +639,8 @@ typedef pthread_t mdbx_tid_t;
|
||||
|
||||
#ifndef __dll_import
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#if defined(__GNUC__) || __has_attribute(dllimport)
|
||||
#define __dll_import __attribute__((dllimport))
|
||||
#if defined(__GNUC__) || __has_attribute(__dllimport__)
|
||||
#define __dll_import __attribute__((__dllimport__))
|
||||
#elif defined(_MSC_VER)
|
||||
#define __dll_import __declspec(dllimport)
|
||||
#else
|
||||
@@ -637,8 +653,9 @@ typedef pthread_t mdbx_tid_t;
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/* MDBX version 0.7.0, released 2020-03-18 */
|
||||
#define MDBX_VERSION_MAJOR 0
|
||||
#define MDBX_VERSION_MINOR 6
|
||||
#define MDBX_VERSION_MINOR 7
|
||||
|
||||
#ifndef LIBMDBX_API
|
||||
#if defined(LIBMDBX_EXPORTS)
|
||||
@@ -817,13 +834,24 @@ typedef struct iovec MDBX_val;
|
||||
* but MDBX_DBG_ASSERT, MDBX_DBG_AUDIT and MDBX_DBG_JITTER only if libmdbx
|
||||
* builded with MDBX_DEBUG. */
|
||||
|
||||
#define MDBX_DBG_ASSERT 1 /* Enable assertion checks */
|
||||
#define MDBX_DBG_AUDIT 2 /* Enable pages usage audit at commit transactions */
|
||||
#define MDBX_DBG_JITTER 4 /* Enable small random delays in critical points */
|
||||
#define MDBX_DBG_DUMP /* Include or not meta-pages in coredump files, MAY \
|
||||
affect performance in MDBX_WRITEMAP mode */ \
|
||||
8
|
||||
#define MDBX_DBG_LEGACY_MULTIOPEN 16 /* Enable multi-opening environment(s) */
|
||||
/* Enable assertion checks */
|
||||
#define MDBX_DBG_ASSERT 1
|
||||
|
||||
/* Enable pages usage audit at commit transactions */
|
||||
#define MDBX_DBG_AUDIT 2
|
||||
|
||||
/* Enable small random delays in critical points */
|
||||
#define MDBX_DBG_JITTER 4
|
||||
|
||||
/* Include or not meta-pages in coredump files,
|
||||
* MAY affect performance in MDBX_WRITEMAP mode */
|
||||
#define MDBX_DBG_DUMP 8
|
||||
|
||||
/* Allow multi-opening environment(s) */
|
||||
#define MDBX_DBG_LEGACY_MULTIOPEN 16
|
||||
|
||||
/* Allow read and write transactions overlapping for the same thread */
|
||||
#define MDBX_DBG_LEGACY_OVERLAP 32
|
||||
|
||||
/* A debug-logger callback function,
|
||||
* called before printing the message and aborting.
|
||||
@@ -833,7 +861,12 @@ typedef struct iovec MDBX_val;
|
||||
typedef void MDBX_debug_func(int loglevel, const char *function, int line,
|
||||
const char *msg, va_list args);
|
||||
|
||||
/* FIXME: Complete description */
|
||||
/* Don't change current settings */
|
||||
#define MDBX_LOG_DONTCHANGE (-1)
|
||||
#define MDBX_DBG_DONTCHANGE (-1)
|
||||
#define MDBX_LOGGER_DONTCHANGE ((MDBX_debug_func *)(intptr_t)-1)
|
||||
|
||||
/* Setup global log-level, debug options and debug logger. */
|
||||
LIBMDBX_API int mdbx_setup_debug(int loglevel, int flags,
|
||||
MDBX_debug_func *logger);
|
||||
|
||||
@@ -1170,10 +1203,11 @@ LIBMDBX_API const char *mdbx_dump_val(const MDBX_val *key, char *const buf,
|
||||
* In case single transaction after mdbx_env_sync, you may lose
|
||||
* transaction itself, but not a whole database.
|
||||
*
|
||||
* Nevertheless, MDBX_UTTERLY_NOSYNC provides ACID in case of a application
|
||||
* crash, and therefore may be very useful in scenarios where data
|
||||
* durability is not required over a system failure (e.g for short-lived
|
||||
* data), or if you can ignore such risk.
|
||||
* Nevertheless, MDBX_UTTERLY_NOSYNC provides "weak" durability in case of
|
||||
* an application crash (but no durability on system failure), and
|
||||
* therefore may be very useful in scenarios where data durability is not
|
||||
* required over a system failure (e.g for short-lived data), or if you can
|
||||
* take such risk.
|
||||
*
|
||||
* MDBX_UTTERLY_NOSYNC flag may be changed at any time using
|
||||
* mdbx_env_set_flags(), but don't has effect if passed to mdbx_txn_begin()
|
||||
@@ -1285,17 +1319,26 @@ LIBMDBX_API const char *mdbx_dump_val(const MDBX_val *key, char *const buf,
|
||||
/**** DATABASE FLAGS **********************************************************/
|
||||
/* Use reverse string keys */
|
||||
#define MDBX_REVERSEKEY 0x02u
|
||||
|
||||
/* Use sorted duplicates */
|
||||
#define MDBX_DUPSORT 0x04u
|
||||
|
||||
/* Numeric keys in native byte order, either uint32_t or uint64_t.
|
||||
* The keys must all be of the same size. */
|
||||
* The keys must all be of the same size and must be aligned while passing as
|
||||
* arguments. */
|
||||
#define MDBX_INTEGERKEY 0x08u
|
||||
|
||||
/* With MDBX_DUPSORT, sorted dup items have fixed size */
|
||||
#define MDBX_DUPFIXED 0x10u
|
||||
/* With MDBX_DUPSORT, dups are MDBX_INTEGERKEY-style integers */
|
||||
|
||||
/* With MDBX_DUPSORT, dups are MDBX_INTEGERKEY-style integers.
|
||||
* The data values must all be of the same size and must be aligned while
|
||||
* passing as arguments. */
|
||||
#define MDBX_INTEGERDUP 0x20u
|
||||
|
||||
/* With MDBX_DUPSORT, use reverse string dups */
|
||||
#define MDBX_REVERSEDUP 0x40u
|
||||
|
||||
/* Create DB if not already existing */
|
||||
#define MDBX_CREATE 0x40000u
|
||||
|
||||
@@ -1375,56 +1418,87 @@ typedef enum MDBX_cursor_op {
|
||||
|
||||
/* key/data pair already exists */
|
||||
#define MDBX_KEYEXIST (-30799)
|
||||
|
||||
/* key/data pair not found (EOF) */
|
||||
#define MDBX_NOTFOUND (-30798)
|
||||
|
||||
/* Requested page not found - this usually indicates corruption */
|
||||
#define MDBX_PAGE_NOTFOUND (-30797)
|
||||
|
||||
/* Database is corrupted (page was wrong type and so on) */
|
||||
#define MDBX_CORRUPTED (-30796)
|
||||
|
||||
/* Environment had fatal error (i.e. update of meta page failed and so on) */
|
||||
#define MDBX_PANIC (-30795)
|
||||
|
||||
/* DB file version mismatch with libmdbx */
|
||||
#define MDBX_VERSION_MISMATCH (-30794)
|
||||
|
||||
/* File is not a valid MDBX file */
|
||||
#define MDBX_INVALID (-30793)
|
||||
|
||||
/* Environment mapsize reached */
|
||||
#define MDBX_MAP_FULL (-30792)
|
||||
|
||||
/* Environment maxdbs reached */
|
||||
#define MDBX_DBS_FULL (-30791)
|
||||
|
||||
/* Environment maxreaders reached */
|
||||
#define MDBX_READERS_FULL (-30790)
|
||||
/* Txn has too many dirty pages */
|
||||
|
||||
/* Transaction has too many dirty pages, i.e transaction too big */
|
||||
#define MDBX_TXN_FULL (-30788)
|
||||
|
||||
/* Cursor stack too deep - internal error */
|
||||
#define MDBX_CURSOR_FULL (-30787)
|
||||
|
||||
/* Page has not enough space - internal error */
|
||||
#define MDBX_PAGE_FULL (-30786)
|
||||
/* Database contents grew beyond environment mapsize */
|
||||
#define MDBX_MAP_RESIZED (-30785)
|
||||
/* Operation and DB incompatible, or DB type changed. This can mean:
|
||||
|
||||
/* Database engine was unable to extend mapping, e.g. since address space
|
||||
* is unavailable or busy. This can mean:
|
||||
* - Database size extended by other process beyond to environment mapsize
|
||||
* and engine was unable to extend mapping while starting read transaction.
|
||||
* Environment should be reopened to continue.
|
||||
* - Engine was unable to extend mapping during write transaction
|
||||
* or explicit call of mdbx_env_set_geometry(). */
|
||||
#define MDBX_UNABLE_EXTEND_MAPSIZE (-30785)
|
||||
|
||||
/* Environment or database is not compatible with the requested operation
|
||||
* or the specified flags. This can mean:
|
||||
* - The operation expects an MDBX_DUPSORT / MDBX_DUPFIXED database.
|
||||
* - Opening a named DB when the unnamed DB has MDBX_DUPSORT/MDBX_INTEGERKEY.
|
||||
* - Accessing a data record as a database, or vice versa.
|
||||
* - The database was dropped and recreated with different flags. */
|
||||
#define MDBX_INCOMPATIBLE (-30784)
|
||||
/* Invalid reuse of reader locktable slot */
|
||||
|
||||
/* Invalid reuse of reader locktable slot,
|
||||
* e.g. read-transaction already run for current thread */
|
||||
#define MDBX_BAD_RSLOT (-30783)
|
||||
/* Transaction must abort, has a child, or is invalid */
|
||||
|
||||
/* Transaction is not valid for requested operation,
|
||||
* e.g. had errored and be must aborted, has a child, or is invalid */
|
||||
#define MDBX_BAD_TXN (-30782)
|
||||
/* Unsupported size of key/DB name/data, or wrong DUPFIXED size */
|
||||
|
||||
/* Invalid size or alignment of key or data for target database,
|
||||
* either invalid subDB name */
|
||||
#define MDBX_BAD_VALSIZE (-30781)
|
||||
/* The specified DBI was changed unexpectedly */
|
||||
|
||||
/* The specified DBI-handle is invalid
|
||||
* or changed by another thread/transaction */
|
||||
#define MDBX_BAD_DBI (-30780)
|
||||
/* Unexpected problem - txn should abort */
|
||||
|
||||
/* Unexpected internal error, transaction should be aborted */
|
||||
#define MDBX_PROBLEM (-30779)
|
||||
|
||||
/* The last LMDB-compatible defined error code */
|
||||
#define MDBX_LAST_LMDB_ERRCODE MDBX_PROBLEM
|
||||
|
||||
/* Another write transaction is running or environment is already used while
|
||||
* opening with MDBX_EXCLUSIVE flag */
|
||||
#define MDBX_BUSY (-30778)
|
||||
/* The last defined error code */
|
||||
#define MDBX_LAST_ERRCODE MDBX_BUSY
|
||||
|
||||
/* The mdbx_put() or mdbx_replace() was called for key,
|
||||
* that has more that one associated value. */
|
||||
/* The specified key has more than one associated value */
|
||||
#define MDBX_EMULTIVAL (-30421)
|
||||
|
||||
/* Bad signature of a runtime object(s), this can mean:
|
||||
@@ -1432,12 +1506,11 @@ typedef enum MDBX_cursor_op {
|
||||
* - ABI version mismatch (rare case); */
|
||||
#define MDBX_EBADSIGN (-30420)
|
||||
|
||||
/* Database should be recovered, but this could NOT be done automatically
|
||||
* right now (e.g. in readonly mode and so forth). */
|
||||
/* Database should be recovered, but this could NOT be done for now
|
||||
* since it opened in read-only mode */
|
||||
#define MDBX_WANNA_RECOVERY (-30419)
|
||||
|
||||
/* The given key value is mismatched to the current cursor position,
|
||||
* when mdbx_cursor_put() called with MDBX_CURRENT option. */
|
||||
/* The given key value is mismatched to the current cursor position */
|
||||
#define MDBX_EKEYMISMATCH (-30418)
|
||||
|
||||
/* Database is too large for current system,
|
||||
@@ -1448,6 +1521,9 @@ typedef enum MDBX_cursor_op {
|
||||
* e.g. a transaction that started by another thread. */
|
||||
#define MDBX_THREAD_MISMATCH (-30416)
|
||||
|
||||
/* Overlapping read and write transactions for the current thread */
|
||||
#define MDBX_TXN_OVERLAPPING (-30415)
|
||||
|
||||
/**** FUNCTIONS & RELATED STRUCTURES ******************************************/
|
||||
|
||||
/* Return a string describing a given error code.
|
||||
@@ -1574,8 +1650,8 @@ LIBMDBX_API int mdbx_env_open(MDBX_env *env, const char *pathname,
|
||||
*
|
||||
* [in] env An environment handle returned by mdbx_env_create(). It must
|
||||
* have already been opened successfully.
|
||||
* [in] dest The directory in which the copy will reside. This directory
|
||||
* must already exist and be writable but must otherwise be empty.
|
||||
* [in] dest The pathname of a file in which the copy will reside. This file
|
||||
* must not be already exist, but parent directory must be writable.
|
||||
* [in] flags Special options for this operation. This parameter must be set
|
||||
* to 0 or by bitwise OR'ing together one or more of the values
|
||||
* described here:
|
||||
@@ -1958,9 +2034,9 @@ LIBMDBX_API int mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *fd);
|
||||
* size. Besides, the upper bound defines the linear address space
|
||||
* reservation in each process that opens the database. Therefore changing
|
||||
* the upper bound is costly and may be required reopening environment in
|
||||
* case of MDBX_MAP_RESIZED errors, and so on. Therefore, this value should
|
||||
* be chosen reasonable as large as possible, to accommodate future growth
|
||||
* of the database.
|
||||
* case of MDBX_UNABLE_EXTEND_MAPSIZE errors, and so on. Therefore, this
|
||||
* value should be chosen reasonable as large as possible, to accommodate
|
||||
* future growth of the database.
|
||||
* - The growth step must be greater than zero to allow the database to grow,
|
||||
* but also reasonable not too small, since increasing the size by little
|
||||
* steps will result a large overhead.
|
||||
@@ -1980,6 +2056,7 @@ LIBMDBX_API int mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *fd);
|
||||
* - Windows does not provide the usual API to augment a memory-mapped file
|
||||
* (that is, a memory-mapped partition), but only by using "Native API"
|
||||
* in an undocumented way.
|
||||
*
|
||||
* MDBX bypasses all Windows issues, but at a cost:
|
||||
* - Ability to resize database on the fly requires an additional lock
|
||||
* and release SlimReadWriteLock during each read-only transaction.
|
||||
@@ -2000,10 +2077,10 @@ LIBMDBX_API int mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *fd);
|
||||
*
|
||||
* If the mapsize is increased by another process, MDBX silently and
|
||||
* transparently adopt these changes at next transaction start. However,
|
||||
* mdbx_txn_begin() will return MDBX_MAP_RESIZED if new mapping size could not
|
||||
* be applied for current process (for instance if address space is busy).
|
||||
* Therefore, in the case of MDBX_MAP_RESIZED error you need close and reopen
|
||||
* the environment to resolve error.
|
||||
* mdbx_txn_begin() will return MDBX_UNABLE_EXTEND_MAPSIZE if new mapping size
|
||||
* could not be applied for current process (for instance if address space
|
||||
* is busy). Therefore, in the case of MDBX_UNABLE_EXTEND_MAPSIZE error you
|
||||
* need close and reopen the environment to resolve error.
|
||||
*
|
||||
* NOTE: Actual values may be different than your have specified because of
|
||||
* rounding to specified database page size, the system page size and/or the
|
||||
@@ -2034,13 +2111,13 @@ LIBMDBX_API int mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *fd);
|
||||
* database is used by other processes or threaded
|
||||
* (i.e. just pass -1 in this argument except absolutely
|
||||
* necessity). Otherwise you must be ready for
|
||||
* MDBX_MAP_RESIZED error(s), unexpected pauses during
|
||||
* remapping and/or system errors like "addtress busy",
|
||||
* and so on. In other words, there is no way to handle
|
||||
* a growth of the upper bound robustly because there may
|
||||
* be a lack of appropriate system resources (which are
|
||||
* extremely volatile in a multi-process multi-threaded
|
||||
* environment).
|
||||
* MDBX_UNABLE_EXTEND_MAPSIZE error(s), unexpected pauses
|
||||
* during remapping and/or system errors like "addtress
|
||||
* busy", and so on. In other words, there is no way to
|
||||
* handle a growth of the upper bound robustly because
|
||||
* there may be a lack of appropriate system resources
|
||||
* (which are extremely volatile in a multi-process
|
||||
* multi-threaded environment).
|
||||
*
|
||||
* [in] growth_step The growth step in bytes, must be greater than zero
|
||||
* to allow the database to grow.
|
||||
@@ -2232,7 +2309,8 @@ LIBMDBX_API void *mdbx_env_get_userctx(MDBX_env *env);
|
||||
* possible errors are:
|
||||
* - MDBX_PANIC = a fatal error occurred earlier and the environment
|
||||
* must be shut down.
|
||||
* - MDBX_MAP_RESIZED = another process wrote data beyond this MDBX_env's
|
||||
* - MDBX_UNABLE_EXTEND_MAPSIZE
|
||||
* = another process wrote data beyond this MDBX_env's
|
||||
* mapsize and this environment's map must be resized
|
||||
* as well. See mdbx_env_set_mapsize().
|
||||
* - MDBX_READERS_FULL = a read-only transaction was requested and the reader
|
||||
@@ -2466,9 +2544,6 @@ typedef int(MDBX_cmp_func)(const MDBX_val *a, const MDBX_val *b);
|
||||
* In contrast to LMDB, the MDBX allow this function to be called from multiple
|
||||
* concurrent transactions or threads in the same process.
|
||||
*
|
||||
* Legacy mdbx_dbi_open() correspond to calling mdbx_dbi_open_ex() with the null
|
||||
* keycmp and datacmp arguments.
|
||||
*
|
||||
* To use named database (with name != NULL), mdbx_env_set_maxdbs()
|
||||
* must be called before opening the environment. Table names are
|
||||
* keys in the internal unnamed database, and may be read but not written.
|
||||
@@ -2490,7 +2565,7 @@ typedef int(MDBX_cmp_func)(const MDBX_val *a, const MDBX_val *b);
|
||||
* - MDBX_INTEGERKEY
|
||||
* Keys are binary integers in native byte order, either uin32_t or
|
||||
* uint64_t, and will be sorted as such. The keys must all be of the
|
||||
* same size.
|
||||
* same size and must be aligned while passing as arguments.
|
||||
* - MDBX_DUPFIXED
|
||||
* This flag may only be used in combination with MDBX_DUPSORT. This
|
||||
* option tells the library that the data items for this database are
|
||||
@@ -2500,7 +2575,8 @@ typedef int(MDBX_cmp_func)(const MDBX_val *a, const MDBX_val *b);
|
||||
* to retrieve multiple items at once.
|
||||
* - MDBX_INTEGERDUP
|
||||
* This option specifies that duplicate data items are binary integers,
|
||||
* similar to MDBX_INTEGERKEY keys.
|
||||
* similar to MDBX_INTEGERKEY keys. The data values must all be of the
|
||||
* same size and must be aligned while passing as arguments.
|
||||
* - MDBX_REVERSEDUP
|
||||
* This option specifies that duplicate data items should be compared as
|
||||
* strings in reverse order (the comparison is performed in the direction
|
||||
@@ -2509,10 +2585,24 @@ typedef int(MDBX_cmp_func)(const MDBX_val *a, const MDBX_val *b);
|
||||
* Create the named database if it doesn't exist. This option is not
|
||||
* allowed in a read-only transaction or a read-only environment.
|
||||
*
|
||||
* [out] dbi Address where the new MDBX_dbi handle will be stored.
|
||||
*
|
||||
* For mdbx_dbi_open_ex() additional arguments allow you to set custom
|
||||
* comparison functions for keys and values (for multimaps).
|
||||
* However, I recommend not using custom comparison functions, but instead
|
||||
* converting the keys to one of the forms that are suitable for built-in
|
||||
* comparators (for instance take look to the mdbx_key_from_xxx()
|
||||
* functions). The reasons to not using custom comparators are:
|
||||
* - The order of records could not be validated without your code.
|
||||
* So mdbx_chk utility will reports "wrong order" errors
|
||||
* and the '-i' option is required to ignore ones.
|
||||
* - A records could not be ordered or sorted without your code.
|
||||
* So mdbx_load utility should be used with '-a' option to preserve
|
||||
* input data order.
|
||||
*
|
||||
* [in] keycmp Optional custom key comparison function for a database.
|
||||
* [in] datacmp Optional custom data comparison function for a database, takes
|
||||
* effect only if database was opened with the MDB_DUPSORT flag.
|
||||
* [out] dbi Address where the new MDBX_dbi handle will be stored.
|
||||
*
|
||||
* Returns A non-zero error value on failure and 0 on success, some
|
||||
* possible errors are:
|
||||
@@ -2530,6 +2620,25 @@ LIBMDBX_API int mdbx_dbi_open_ex(MDBX_txn *txn, const char *name,
|
||||
LIBMDBX_API int mdbx_dbi_open(MDBX_txn *txn, const char *name, unsigned flags,
|
||||
MDBX_dbi *dbi);
|
||||
|
||||
/* Key-making functions to avoid custom comparators.
|
||||
*
|
||||
* The mdbx_key_from_jsonInteger() build key which are comparable with
|
||||
* keys created by mdbx_key_from_double(). So this allow mix int64 and IEEE754
|
||||
* double values in one index for JSON-numbers with restriction for integer
|
||||
* numbers range corresponding to RFC-7159 (i.e. [-(2**53)+1, (2**53)-1].
|
||||
* See bottom of page 6 at https://tools.ietf.org/html/rfc7159 */
|
||||
LIBMDBX_API uint64_t mdbx_key_from_jsonInteger(const int64_t json_integer);
|
||||
LIBMDBX_API uint64_t mdbx_key_from_double(const double ieee754_64bit);
|
||||
LIBMDBX_API uint64_t mdbx_key_from_ptrdouble(const double *const ieee754_64bit);
|
||||
LIBMDBX_API uint32_t mdbx_key_from_float(const float ieee754_32bit);
|
||||
LIBMDBX_API uint32_t mdbx_key_from_ptrfloat(const float *const ieee754_32bit);
|
||||
__inline uint64_t mdbx_key_from_int64(const int64_t i64) {
|
||||
return UINT64_C(0x8000000000000000) + i64;
|
||||
}
|
||||
__inline uint32_t mdbx_key_from_int32(const int32_t i32) {
|
||||
return UINT32_C(0x80000000) + i32;
|
||||
}
|
||||
|
||||
/* Retrieve statistics for a database.
|
||||
*
|
||||
* [in] txn A transaction handle returned by mdbx_txn_begin().
|
||||
@@ -3377,7 +3486,7 @@ typedef uint_fast64_t mdbx_attr_t;
|
||||
* [in] flags Options for this operation. This parameter must be set to 0
|
||||
* or one of the values described here:
|
||||
*
|
||||
* - MDBX_CURRENT
|
||||
* - MDBX_CURRENT
|
||||
* Replace the item at the current cursor position. The key parameter
|
||||
* must still be provided, and must match it, otherwise the function
|
||||
* return MDBX_EKEYMISMATCH.
|
||||
@@ -3459,8 +3568,8 @@ LIBMDBX_API int mdbx_put_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
|
||||
*
|
||||
* Returns A non-zero error value on failure and 0 on success, some
|
||||
* possible errors are:
|
||||
* - MDBX_NOTFOUND = the key-value pair was not in the database.
|
||||
* - MDBX_EINVAL = an invalid parameter was specified. */
|
||||
* - MDBX_NOTFOUND = the key-value pair was not in the database.
|
||||
* - MDBX_EINVAL = an invalid parameter was specified. */
|
||||
LIBMDBX_API int mdbx_set_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
|
||||
MDBX_val *data, mdbx_attr_t attr);
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
1103
src/elements/core.c
1103
src/elements/core.c
File diff suppressed because it is too large
Load Diff
@@ -118,10 +118,8 @@
|
||||
# define __noinline __attribute__((__noinline__))
|
||||
# elif defined(_MSC_VER)
|
||||
# define __noinline __declspec(noinline)
|
||||
# elif defined(__SUNPRO_C) || defined(__sun) || defined(sun)
|
||||
# define __noinline inline
|
||||
# elif !defined(__INTEL_COMPILER)
|
||||
# define __noinline /* FIXME ? */
|
||||
# else
|
||||
# define __noinline
|
||||
# endif
|
||||
#endif /* __noinline */
|
||||
|
||||
@@ -142,33 +140,33 @@
|
||||
#endif /* __maybe_unused */
|
||||
|
||||
#if !defined(__noop) && !defined(_MSC_VER)
|
||||
# define __noop(...) do {} while(0)
|
||||
# define __noop(...) do {} while(0)
|
||||
#endif /* __noop */
|
||||
|
||||
#ifndef __fallthrough
|
||||
# if __GNUC_PREREQ(7, 0) || __has_attribute(__fallthrough__)
|
||||
# define __fallthrough __attribute__((__fallthrough__))
|
||||
# else
|
||||
# define __fallthrough __noop()
|
||||
# endif
|
||||
# if __GNUC_PREREQ(7, 0) || __has_attribute(__fallthrough__)
|
||||
# define __fallthrough __attribute__((__fallthrough__))
|
||||
# else
|
||||
# define __fallthrough __noop()
|
||||
# endif
|
||||
#endif /* __fallthrough */
|
||||
|
||||
#ifndef __unreachable
|
||||
# if __GNUC_PREREQ(4,5) || __has_builtin(__builtin_unreachable)
|
||||
# define __unreachable() __builtin_unreachable()
|
||||
# elif defined(_MSC_VER)
|
||||
# define __unreachable() __assume(0)
|
||||
# else
|
||||
# define __unreachable() __noop()
|
||||
# endif
|
||||
# if __GNUC_PREREQ(4,5) || __has_builtin(__builtin_unreachable)
|
||||
# define __unreachable() __builtin_unreachable()
|
||||
# elif defined(_MSC_VER)
|
||||
# define __unreachable() __assume(0)
|
||||
# else
|
||||
# define __unreachable() __noop()
|
||||
# endif
|
||||
#endif /* __unreachable */
|
||||
|
||||
#ifndef __prefetch
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# define __prefetch(ptr) __builtin_prefetch(ptr)
|
||||
# else
|
||||
# define __prefetch(ptr) __noop(ptr)
|
||||
# endif
|
||||
# if defined(__GNUC__) || defined(__clang__) || __has_builtin(__builtin_prefetch)
|
||||
# define __prefetch(ptr) __builtin_prefetch(ptr)
|
||||
# else
|
||||
# define __prefetch(ptr) __noop(ptr)
|
||||
# endif
|
||||
#endif /* __prefetch */
|
||||
|
||||
#ifndef __noreturn
|
||||
@@ -237,15 +235,13 @@
|
||||
|
||||
#ifndef __optimize
|
||||
# if defined(__OPTIMIZE__)
|
||||
# if defined(__clang__) && !__has_attribute(__optimize__)
|
||||
# define __optimize(ops)
|
||||
# elif defined(__GNUC__) || __has_attribute(__optimize__)
|
||||
# if (defined(__GNUC__) && !defined(__clang__)) || __has_attribute(__optimize__)
|
||||
# define __optimize(ops) __attribute__((__optimize__(ops)))
|
||||
# else
|
||||
# define __optimize(ops)
|
||||
# endif
|
||||
# else
|
||||
# define __optimize(ops)
|
||||
# define __optimize(ops)
|
||||
# endif
|
||||
#endif /* __optimize */
|
||||
|
||||
@@ -309,21 +305,10 @@
|
||||
# endif
|
||||
#endif /* unlikely */
|
||||
|
||||
/* Workaround for Coverity Scan */
|
||||
#if defined(__COVERITY__) && __GNUC_PREREQ(7, 0) && !defined(__cplusplus)
|
||||
typedef float _Float32;
|
||||
typedef double _Float32x;
|
||||
typedef double _Float64;
|
||||
typedef long double _Float64x;
|
||||
typedef float _Float128 __attribute__((__mode__(__TF__)));
|
||||
typedef __complex__ float __cfloat128 __attribute__ ((__mode__ (__TC__)));
|
||||
typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
|
||||
#endif /* Workaround for Coverity Scan */
|
||||
|
||||
#ifndef __printf_args
|
||||
# if defined(__GNUC__) || __has_attribute(__format__)
|
||||
# define __printf_args(format_index, first_arg) \
|
||||
__attribute__((__format__(printf, format_index, first_arg)))
|
||||
__attribute__((__format__(__printf__, format_index, first_arg)))
|
||||
# else
|
||||
# define __printf_args(format_index, first_arg)
|
||||
# endif
|
||||
|
||||
@@ -1165,7 +1165,7 @@ MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr);
|
||||
((rc) != MDBX_RESULT_TRUE && (rc) != MDBX_RESULT_FALSE)
|
||||
|
||||
/* Internal error codes, not exposed outside libmdbx */
|
||||
#define MDBX_NO_ROOT (MDBX_LAST_ERRCODE + 10)
|
||||
#define MDBX_NO_ROOT (MDBX_LAST_LMDB_ERRCODE + 10)
|
||||
|
||||
/* Debugging output value of a cursor DBI: Negative in a sub-cursor. */
|
||||
#define DDBI(mc) \
|
||||
@@ -1318,3 +1318,14 @@ static __maybe_unused __inline void mdbx_jitter4testing(bool tiny) {
|
||||
(void)tiny;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __pure_function __always_inline __maybe_unused bool
|
||||
is_powerof2(size_t x) {
|
||||
return (x & (x - 1)) == 0;
|
||||
}
|
||||
|
||||
static __pure_function __always_inline __maybe_unused size_t
|
||||
roundup_powerof2(size_t value, size_t granularity) {
|
||||
assert(is_powerof2(granularity));
|
||||
return (value + granularity - 1) & ~(granularity - 1);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -717,6 +720,7 @@ static uint64_t WINAPI stub_GetTickCount64(void) {
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#ifndef MDBX_ALLOY
|
||||
MDBX_NtExtendSection mdbx_NtExtendSection;
|
||||
MDBX_GetFileInformationByHandleEx mdbx_GetFileInformationByHandleEx;
|
||||
MDBX_GetVolumeInformationByHandleW mdbx_GetVolumeInformationByHandleW;
|
||||
MDBX_GetFinalPathNameByHandleW mdbx_GetFinalPathNameByHandleW;
|
||||
@@ -732,7 +736,47 @@ MDBX_ReclaimVirtualMemory mdbx_ReclaimVirtualMemory;
|
||||
#endif /* MDBX_ALLOY */
|
||||
|
||||
static void mdbx_winnt_import(void) {
|
||||
const HINSTANCE hNtdll = GetModuleHandleA("ntdll.dll");
|
||||
|
||||
#define GET_PROC_ADDR(dll, ENTRY) \
|
||||
mdbx_##ENTRY = (MDBX_##ENTRY)GetProcAddress(dll, #ENTRY)
|
||||
|
||||
if (GetProcAddress(hNtdll, "wine_get_version")) {
|
||||
assert(mdbx_RunningUnderWine());
|
||||
} else {
|
||||
GET_PROC_ADDR(hNtdll, NtFsControlFile);
|
||||
GET_PROC_ADDR(hNtdll, NtExtendSection);
|
||||
assert(!mdbx_RunningUnderWine());
|
||||
}
|
||||
|
||||
const HINSTANCE hKernel32dll = GetModuleHandleA("kernel32.dll");
|
||||
GET_PROC_ADDR(hKernel32dll, GetFileInformationByHandleEx);
|
||||
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);
|
||||
}
|
||||
|
||||
#if 0 /* LY: unused for now */
|
||||
if (!mdbx_RunningUnderWine()) {
|
||||
GET_PROC_ADDR(hKernel32dll, DiscardVirtualMemory);
|
||||
GET_PROC_ADDR(hKernel32dll, OfferVirtualMemory);
|
||||
GET_PROC_ADDR(hKernel32dll, ReclaimVirtualMemory);
|
||||
}
|
||||
if (!mdbx_DiscardVirtualMemory)
|
||||
mdbx_DiscardVirtualMemory = stub_DiscardVirtualMemory;
|
||||
if (!mdbx_OfferVirtualMemory)
|
||||
mdbx_OfferVirtualMemory = stub_OfferVirtualMemory;
|
||||
if (!mdbx_ReclaimVirtualMemory)
|
||||
mdbx_ReclaimVirtualMemory = stub_ReclaimVirtualMemory;
|
||||
#endif /* unused for now */
|
||||
|
||||
#undef GET_PROC_ADDR
|
||||
|
||||
const MDBX_srwlock_function init =
|
||||
(MDBX_srwlock_function)GetProcAddress(hKernel32dll, "InitializeSRWLock");
|
||||
if (init != NULL) {
|
||||
@@ -752,27 +796,6 @@ static void mdbx_winnt_import(void) {
|
||||
mdbx_srwlock_AcquireExclusive = stub_srwlock_AcquireExclusive;
|
||||
mdbx_srwlock_ReleaseExclusive = stub_srwlock_ReleaseExclusive;
|
||||
}
|
||||
|
||||
#define GET_KERNEL32_PROC(ENTRY) \
|
||||
mdbx_##ENTRY = (MDBX_##ENTRY)GetProcAddress(hKernel32dll, #ENTRY)
|
||||
GET_KERNEL32_PROC(GetFileInformationByHandleEx);
|
||||
GET_KERNEL32_PROC(GetVolumeInformationByHandleW);
|
||||
GET_KERNEL32_PROC(GetFinalPathNameByHandleW);
|
||||
GET_KERNEL32_PROC(SetFileInformationByHandle);
|
||||
GET_KERNEL32_PROC(PrefetchVirtualMemory);
|
||||
GET_KERNEL32_PROC(GetTickCount64);
|
||||
if (!mdbx_GetTickCount64)
|
||||
mdbx_GetTickCount64 = stub_GetTickCount64;
|
||||
#if 0 /* LY: unused for now */
|
||||
GET_KERNEL32_PROC(DiscardVirtualMemory);
|
||||
if (!mdbx_DiscardVirtualMemory)
|
||||
mdbx_DiscardVirtualMemory = stub_DiscardVirtualMemory;
|
||||
GET_KERNEL32_PROC(OfferVirtualMemory);
|
||||
GET_KERNEL32_PROC(ReclaimVirtualMemory);
|
||||
#endif /* unused for now */
|
||||
#undef GET_KERNEL32_PROC
|
||||
|
||||
const HINSTANCE hNtdll = GetModuleHandleA("ntdll.dll");
|
||||
mdbx_NtFsControlFile =
|
||||
(MDBX_NtFsControlFile)GetProcAddress(hNtdll, "NtFsControlFile");
|
||||
}
|
||||
|
||||
#endif /* Windows LCK-implementation */
|
||||
|
||||
@@ -67,23 +67,6 @@ typedef struct _SECTION_BASIC_INFORMATION {
|
||||
LARGE_INTEGER SectionSize;
|
||||
} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
|
||||
|
||||
typedef enum _SECTION_INFORMATION_CLASS {
|
||||
SectionBasicInformation,
|
||||
SectionImageInformation,
|
||||
SectionRelocationInformation, // name:wow64:whNtQuerySection_SectionRelocationInformation
|
||||
MaxSectionInfoClass
|
||||
} SECTION_INFORMATION_CLASS;
|
||||
|
||||
extern NTSTATUS NTAPI NtQuerySection(
|
||||
IN HANDLE SectionHandle, IN SECTION_INFORMATION_CLASS InformationClass,
|
||||
OUT PVOID InformationBuffer, IN ULONG InformationBufferSize,
|
||||
OUT PULONG ResultLength OPTIONAL);
|
||||
|
||||
extern NTSTATUS NTAPI NtExtendSection(IN HANDLE SectionHandle,
|
||||
IN PLARGE_INTEGER NewSectionSize);
|
||||
|
||||
typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT;
|
||||
|
||||
extern NTSTATUS NTAPI NtMapViewOfSection(
|
||||
IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress,
|
||||
IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize,
|
||||
@@ -324,12 +307,13 @@ MDBX_INTERNAL_FUNC int mdbx_asprintf(char **strp, const char *fmt, ...) {
|
||||
#ifndef mdbx_memalign_alloc
|
||||
MDBX_INTERNAL_FUNC int mdbx_memalign_alloc(size_t alignment, size_t bytes,
|
||||
void **result) {
|
||||
assert(is_powerof2(alignment) && alignment >= sizeof(void *));
|
||||
#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 defined(_ISOC11_SOURCE)
|
||||
*result = aligned_alloc(alignment, bytes);
|
||||
*result = aligned_alloc(alignment, roundup_powerof2(bytes, alignment));
|
||||
return *result ? MDBX_SUCCESS : errno;
|
||||
#elif _POSIX_VERSION >= 200112L
|
||||
*result = nullptr;
|
||||
@@ -1001,6 +985,9 @@ MDBX_INTERNAL_FUNC int mdbx_check_fs_rdonly(mdbx_filehandle_t handle,
|
||||
|
||||
static int mdbx_check_fs_local(mdbx_filehandle_t handle, int flags) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (mdbx_RunningUnderWine() && !(flags & MDBX_EXCLUSIVE))
|
||||
return ERROR_NOT_CAPABLE /* workaround for Wine */;
|
||||
|
||||
if (GetFileType(handle) != FILE_TYPE_DISK)
|
||||
return ERROR_FILE_OFFLINE;
|
||||
|
||||
@@ -1313,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,
|
||||
@@ -1415,8 +1403,10 @@ 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 MDBX_UNABLE_EXTEND_MAPSIZE /* workaround for Wine */;
|
||||
SectionSize.QuadPart = size;
|
||||
status = NtExtendSection(map->section, &SectionSize);
|
||||
status = mdbx_NtExtendSection(map->section, &SectionSize);
|
||||
if (!NT_SUCCESS(status))
|
||||
return ntstatus2errcode(status);
|
||||
map->current = size;
|
||||
@@ -1432,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);
|
||||
|
||||
@@ -1550,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;
|
||||
@@ -1574,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)
|
||||
@@ -1591,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;
|
||||
}
|
||||
@@ -1610,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
|
||||
@@ -1806,20 +1796,20 @@ static uint64_t windows_bootime(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LSTATUS mdbx_RegGetValue(HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpValue,
|
||||
static LSTATUS mdbx_RegGetValue(HKEY hkey, LPCSTR lpSubKey, LPCSTR lpValue,
|
||||
DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
|
||||
LPDWORD pcbData) {
|
||||
LSTATUS rc =
|
||||
RegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData);
|
||||
RegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData);
|
||||
if (rc != ERROR_FILE_NOT_FOUND)
|
||||
return rc;
|
||||
|
||||
rc = RegGetValueW(hkey, lpSubKey, lpValue,
|
||||
rc = RegGetValueA(hkey, lpSubKey, lpValue,
|
||||
dwFlags | 0x00010000 /* RRF_SUBKEY_WOW6464KEY */, pdwType,
|
||||
pvData, pcbData);
|
||||
if (rc != ERROR_FILE_NOT_FOUND)
|
||||
return rc;
|
||||
return RegGetValueW(hkey, lpSubKey, lpValue,
|
||||
return RegGetValueA(hkey, lpSubKey, lpValue,
|
||||
dwFlags | 0x00020000 /* RRF_SUBKEY_WOW6432KEY */, pdwType,
|
||||
pvData, pcbData);
|
||||
}
|
||||
@@ -1932,30 +1922,30 @@ __cold MDBX_INTERNAL_FUNC bin128_t mdbx_osal_bootid(void) {
|
||||
char DigitalProductId[248];
|
||||
} buf;
|
||||
|
||||
static const wchar_t HKLM_MicrosoftCryptography[] =
|
||||
L"SOFTWARE\\Microsoft\\Cryptography";
|
||||
static const char HKLM_MicrosoftCryptography[] =
|
||||
"SOFTWARE\\Microsoft\\Cryptography";
|
||||
DWORD len = sizeof(buf);
|
||||
/* Windows is madness and must die */
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_MicrosoftCryptography,
|
||||
L"MachineGuid", RRF_RT_ANY, NULL, &buf.MachineGuid,
|
||||
"MachineGuid", RRF_RT_ANY, NULL, &buf.MachineGuid,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf))
|
||||
got_machineid = bootid_parse_uuid(&bin, &buf.MachineGuid, len);
|
||||
|
||||
if (!got_machineid) {
|
||||
/* again, Windows is madness */
|
||||
static const wchar_t HKLM_WindowsNT[] =
|
||||
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
|
||||
static const wchar_t HKLM_WindowsNT_DPK[] =
|
||||
L"SOFTWARE\\Microsoft\\Windows "
|
||||
L"NT\\CurrentVersion\\DefaultProductKey";
|
||||
static const wchar_t HKLM_WindowsNT_DPK2[] =
|
||||
L"SOFTWARE\\Microsoft\\Windows "
|
||||
L"NT\\CurrentVersion\\DefaultProductKey2";
|
||||
static const char HKLM_WindowsNT[] =
|
||||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
|
||||
static const char HKLM_WindowsNT_DPK[] =
|
||||
"SOFTWARE\\Microsoft\\Windows "
|
||||
"NT\\CurrentVersion\\DefaultProductKey";
|
||||
static const char HKLM_WindowsNT_DPK2[] =
|
||||
"SOFTWARE\\Microsoft\\Windows "
|
||||
"NT\\CurrentVersion\\DefaultProductKey2";
|
||||
|
||||
len = sizeof(buf);
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_WindowsNT,
|
||||
L"DigitalProductId", RRF_RT_ANY, NULL,
|
||||
"DigitalProductId", RRF_RT_ANY, NULL,
|
||||
&buf.DigitalProductId, &len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
@@ -1963,7 +1953,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t mdbx_osal_bootid(void) {
|
||||
}
|
||||
len = sizeof(buf);
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_WindowsNT_DPK,
|
||||
L"DigitalProductId", RRF_RT_ANY, NULL,
|
||||
"DigitalProductId", RRF_RT_ANY, NULL,
|
||||
&buf.DigitalProductId, &len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
@@ -1971,7 +1961,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t mdbx_osal_bootid(void) {
|
||||
}
|
||||
len = sizeof(buf);
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_WindowsNT_DPK2,
|
||||
L"DigitalProductId", RRF_RT_ANY, NULL,
|
||||
"DigitalProductId", RRF_RT_ANY, NULL,
|
||||
&buf.DigitalProductId, &len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
@@ -1979,11 +1969,11 @@ __cold MDBX_INTERNAL_FUNC bin128_t mdbx_osal_bootid(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static const wchar_t HKLM_PrefetcherParams[] =
|
||||
L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory "
|
||||
L"Management\\PrefetchParameters";
|
||||
static const char HKLM_PrefetcherParams[] =
|
||||
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory "
|
||||
"Management\\PrefetchParameters";
|
||||
len = sizeof(buf);
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, L"BootId",
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BootId",
|
||||
RRF_RT_DWORD, NULL, &buf.BootId,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 1 && len < sizeof(buf)) {
|
||||
@@ -1992,7 +1982,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t mdbx_osal_bootid(void) {
|
||||
}
|
||||
|
||||
len = sizeof(buf);
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, L"BaseTime",
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BaseTime",
|
||||
RRF_RT_DWORD, NULL, &buf.BaseTime,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len >= sizeof(buf.BaseTime) && buf.BaseTime) {
|
||||
|
||||
@@ -760,6 +760,7 @@ MDBX_INTERNAL_FUNC int mdbx_rpid_clear(MDBX_env *env);
|
||||
MDBX_INTERNAL_FUNC int mdbx_rpid_check(MDBX_env *env, uint32_t pid);
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
typedef union MDBX_srwlock {
|
||||
struct {
|
||||
long volatile readerCount;
|
||||
@@ -849,6 +850,16 @@ typedef DWORD(WINAPI *MDBX_OfferVirtualMemory(
|
||||
MDBX_INTERNAL_VAR MDBX_OfferVirtualMemory mdbx_OfferVirtualMemory;
|
||||
#endif /* unused for now */
|
||||
|
||||
typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT;
|
||||
|
||||
typedef NTSTATUS(NTAPI *MDBX_NtExtendSection)(IN HANDLE SectionHandle,
|
||||
IN PLARGE_INTEGER NewSectionSize);
|
||||
MDBX_INTERNAL_VAR MDBX_NtExtendSection mdbx_NtExtendSection;
|
||||
|
||||
static __inline bool mdbx_RunningUnderWine(void) {
|
||||
return !mdbx_NtExtendSection;
|
||||
}
|
||||
|
||||
#endif /* Windows */
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Copyright 2015-2020 Leonid Yuriev <leo@yuriev.ru>.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_CHK 1 "2020-01-20" "MDBX 0.6.x"
|
||||
.TH MDBX_CHK 1 "2020-03-18" "MDBX 0.7.x"
|
||||
.SH NAME
|
||||
mdbx_chk \- MDBX checking tool
|
||||
.SH SYNOPSIS
|
||||
@@ -84,4 +84,4 @@ if no quiet mode was requested.
|
||||
.BR mdbx_dump (1),
|
||||
.BR mdbx_load (1)
|
||||
.SH AUTHOR
|
||||
Leonid Yuriev <https://github.com/leo-yuriev>
|
||||
Leonid Yuriev <https://github.com/erthink>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_COPY 1 "2020-01-20" "MDBX 0.6.x"
|
||||
.TH MDBX_COPY 1 "2020-03-18" "MDBX 0.7.x"
|
||||
.SH NAME
|
||||
mdbx_copy \- MDBX environment copy tool
|
||||
.SH SYNOPSIS
|
||||
@@ -63,4 +63,4 @@ free during copying cannot be reused until the copy is done.
|
||||
.BR mdbx_load (1)
|
||||
.SH AUTHOR
|
||||
Howard Chu of Symas Corporation <http://www.symas.com>,
|
||||
Leonid Yuriev <https://github.com/leo-yuriev>
|
||||
Leonid Yuriev <https://github.com/erthink>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_DUMP 1 "2020-01-20" "MDBX 0.6.x"
|
||||
.TH MDBX_DUMP 1 "2020-03-18" "MDBX 0.7.x"
|
||||
.SH NAME
|
||||
mdbx_dump \- MDBX environment export tool
|
||||
.SH SYNOPSIS
|
||||
@@ -88,4 +88,4 @@ utility to load the database using the correct comparison functions.
|
||||
.BR mdbx_stat (1)
|
||||
.SH AUTHOR
|
||||
Howard Chu of Symas Corporation <http://www.symas.com>,
|
||||
Leonid Yuriev <https://github.com/leo-yuriev>
|
||||
Leonid Yuriev <https://github.com/erthink>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_LOAD 1 "2020-01-20" "MDBX 0.6.x"
|
||||
.TH MDBX_LOAD 1 "2020-03-18" "MDBX 0.7.x"
|
||||
.SH NAME
|
||||
mdbx_load \- MDBX environment import tool
|
||||
.SH SYNOPSIS
|
||||
@@ -99,4 +99,4 @@ a diagnostic message being written to standard error.
|
||||
.BR mdbx_copy (1)
|
||||
.SH AUTHOR
|
||||
Howard Chu of Symas Corporation <http://www.symas.com>,
|
||||
Leonid Yuriev <https://github.com/leo-yuriev>
|
||||
Leonid Yuriev <https://github.com/erthink>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_STAT 1 "2020-01-20" "MDBX 0.6.x"
|
||||
.TH MDBX_STAT 1 "2020-03-18" "MDBX 0.7.x"
|
||||
.SH NAME
|
||||
mdbx_stat \- MDBX environment status tool
|
||||
.SH SYNOPSIS
|
||||
@@ -72,4 +72,4 @@ a diagnostic message being written to standard error.
|
||||
.BR mdbx_load (1)
|
||||
.SH AUTHOR
|
||||
Howard Chu of Symas Corporation <http://www.symas.com>,
|
||||
Leonid Yuriev <https://github.com/leo-yuriev>
|
||||
Leonid Yuriev <https://github.com/erthink>
|
||||
|
||||
@@ -559,6 +559,12 @@ static int process_db(MDBX_dbi dbi_handle, char *dbi_name, visitor *handler,
|
||||
uint64_t record_count = 0, dups = 0;
|
||||
uint64_t key_bytes = 0, data_bytes = 0;
|
||||
|
||||
if ((MDBX_TXN_FINISHED | MDBX_TXN_ERROR) & mdbx_txn_flags(txn)) {
|
||||
print(" ! abort processing '%s' due to a previous error\n",
|
||||
dbi_name ? dbi_name : "@MAIN");
|
||||
return MDBX_BAD_TXN;
|
||||
}
|
||||
|
||||
if (dbi_handle == ~0u) {
|
||||
rc = mdbx_dbi_open(txn, dbi_name, 0, &dbi_handle);
|
||||
if (rc) {
|
||||
|
||||
@@ -339,7 +339,8 @@ static void usage(void) {
|
||||
"dbpath\n"
|
||||
" -V\t\tprint version and exit\n"
|
||||
" -q\t\tbe quiet\n"
|
||||
" -a\t\tappend records in input order\n"
|
||||
" -a\t\tappend records in input order (required for custom "
|
||||
"comparators)\n"
|
||||
" -f file\tread from file instead of stdin\n"
|
||||
" -s name\tload into named subDB\n"
|
||||
" -N\t\tuse NOOVERWRITE on puts\n"
|
||||
|
||||
@@ -53,7 +53,7 @@ bool testcase_jitter::run() {
|
||||
err = mdbx_env_set_geometry(
|
||||
db_guard.get(), -1, -1,
|
||||
coin4size ? upper_limit * 2 / 3 : upper_limit * 3 / 2, -1, -1, -1);
|
||||
if (err != MDBX_SUCCESS && err != MDBX_RESULT_TRUE &&
|
||||
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE &&
|
||||
err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE)
|
||||
failure_perror("mdbx_env_set_geometry-1", err);
|
||||
}
|
||||
@@ -62,7 +62,7 @@ bool testcase_jitter::run() {
|
||||
err = mdbx_env_set_geometry(
|
||||
db_guard.get(), -1, -1,
|
||||
!coin4size ? upper_limit * 2 / 3 : upper_limit * 3 / 2, -1, -1, -1);
|
||||
if (err != MDBX_SUCCESS && err != MDBX_RESULT_TRUE &&
|
||||
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE &&
|
||||
err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE)
|
||||
failure_perror("mdbx_env_set_geometry-2", err);
|
||||
|
||||
@@ -76,7 +76,7 @@ bool testcase_jitter::run() {
|
||||
jitter_delay();
|
||||
err =
|
||||
mdbx_env_set_geometry(db_guard.get(), -1, -1, upper_limit, -1, -1, -1);
|
||||
if (err != MDBX_SUCCESS && err != MDBX_RESULT_TRUE &&
|
||||
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE &&
|
||||
err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE)
|
||||
failure_perror("mdbx_env_set_geometry-3", err);
|
||||
|
||||
|
||||
@@ -336,20 +336,22 @@ static void periodic_stat(void) {
|
||||
prev_del_time = mdbx_del_time;
|
||||
}
|
||||
|
||||
// static void periodic_add_rec() {
|
||||
// for (int i = 0; i < 10240; i++) {
|
||||
// if (ids_count <= REC_COUNT) {
|
||||
// int64_t id = obj_id++;
|
||||
// create_record(id);
|
||||
// add_id_to_pool(id);
|
||||
// }
|
||||
// if (ids_count > REC_COUNT) {
|
||||
// int64_t id = get_id_from_pool();
|
||||
// delete_record(id);
|
||||
// }
|
||||
// }
|
||||
// periodic_stat();
|
||||
//}
|
||||
#if 0 /* unused */
|
||||
static void periodic_add_rec() {
|
||||
for (int i = 0; i < 10240; i++) {
|
||||
if (ids_count <= REC_COUNT) {
|
||||
int64_t id = obj_id++;
|
||||
create_record(id);
|
||||
add_id_to_pool(id);
|
||||
}
|
||||
if (ids_count > REC_COUNT) {
|
||||
int64_t id = get_id_from_pool();
|
||||
delete_record(id);
|
||||
}
|
||||
}
|
||||
periodic_stat();
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc;
|
||||
@@ -358,14 +360,12 @@ int main(int argc, char **argv) {
|
||||
char filename[PATH_MAX];
|
||||
int i;
|
||||
|
||||
mkdir(opt_db_path, 0775);
|
||||
|
||||
strcpy(filename, opt_db_path);
|
||||
strcat(filename, "/mdbx.dat");
|
||||
strcat(filename, MDBX_DATANAME);
|
||||
remove(filename);
|
||||
|
||||
strcpy(filename, opt_db_path);
|
||||
strcat(filename, "/mdbx.lck");
|
||||
strcat(filename, MDBX_LOCKNAME);
|
||||
remove(filename);
|
||||
|
||||
puts("Open DB...");
|
||||
@@ -394,14 +394,14 @@ int main(int argc, char **argv) {
|
||||
id = get_id_from_pool();
|
||||
delete_record(id);
|
||||
}
|
||||
// for (i = 0; i < 50; i++) {
|
||||
// int64_t id = obj_id++;
|
||||
// create_record(id);
|
||||
// add_id_to_pool(id);
|
||||
// }
|
||||
// int64_t id = obj_id++;
|
||||
// create_record(id);
|
||||
// add_id_to_pool(id);
|
||||
for (i = 0; i < 50; i++) {
|
||||
int64_t id = obj_id++;
|
||||
create_record(id);
|
||||
add_id_to_pool(id);
|
||||
}
|
||||
int64_t id = obj_id++;
|
||||
create_record(id);
|
||||
add_id_to_pool(id);
|
||||
int64_t now = getClockUs();
|
||||
if ((now - t) > 10000000L) {
|
||||
periodic_stat();
|
||||
|
||||
Reference in New Issue
Block a user