summaryrefslogtreecommitdiff
path: root/plugins/Dbx_mdbx
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-03-30 22:50:46 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-03-30 22:50:46 +0300
commit628f23ab62e342bb0b1dddedb563e7f13faf9528 (patch)
tree55c97c8453e2dc0036dfa65fb5eb268c886ada13 /plugins/Dbx_mdbx
parent67cd8dbde997606b40bd7dc2712ccc4c66d8d06f (diff)
merge with the final version of libmdbx
Diffstat (limited to 'plugins/Dbx_mdbx')
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/Makefile65
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/README-RU.md23
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/README.md24
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/TODO.md2
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/mdbx.h45
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/bits.h100
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/defs.h10
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c215
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/osal.h178
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c42
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/version.c4
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/base.h8
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/config.cc7
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/config.h3
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/log.cc2
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/log.h1
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/main.cc17
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc19
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc6
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/osal.h1
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/test.cc24
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/test.h2
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/utils.cc134
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/test/utils.h30
24 files changed, 648 insertions, 314 deletions
diff --git a/plugins/Dbx_mdbx/src/libmdbx/Makefile b/plugins/Dbx_mdbx/src/libmdbx/Makefile
index c434dbdd56..0552412ed0 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/Makefile
+++ b/plugins/Dbx_mdbx/src/libmdbx/Makefile
@@ -23,23 +23,21 @@ suffix ?=
CC ?= gcc
CXX ?= g++
-XCFLAGS ?= -DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1
+ifeq ($(shell (export LC_ALL=C; ($(CC) --version 2>&1; $(CC) -v 2>&1) | grep -q -i 'e2k' && echo yes)),yes)
+CFLAGS ?= -O3 -g3 -Wall -Werror -Wextra -ffunction-sections -fPIC -fvisibility=hidden
+else
CFLAGS ?= -O2 -g3 -Wall -Werror -Wextra -ffunction-sections -fPIC -fvisibility=hidden
-CFLAGS += -D_GNU_SOURCE=1 -std=gnu11 -pthread $(XCFLAGS)
-
-# temporary workaround for lcc's bug
-TARGET_ARCH_e2k = $(shell (export LC_ALL=C; ($(CC) --version 2>&1; $(CC) -v 2>&1) | grep -q -i 'e2k' && echo yes || echo no))
-ifeq ($(TARGET_ARCH_e2k),yes)
-TARGET_ARCH := e2k
-CFLAGS += -mtune=native -Wno-alignment-reduction-ignored
endif
+XCFLAGS ?= -DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1
+CFLAGS += -D_GNU_SOURCE=1 -std=gnu11 -pthread $(XCFLAGS)
CXXFLAGS = -std=c++11 $(filter-out -std=gnu11,$(CFLAGS))
-TESTDB ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-check.db
-TESTLOG ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-check.log
+TESTDB ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-test.db
+TESTLOG ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-test.log
# LY: '--no-as-needed,-lrt' for ability to built with modern glibc, but then run with the old
LDFLAGS ?= -Wl,--gc-sections,-z,relro,-O,--no-as-needed,-lrt
+EXE_LDFLAGS ?= $(LDFLAGS) -static
# LY: just for benchmarking
IOARENA ?= $(shell \
@@ -90,6 +88,12 @@ clean:
check: all
rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; test/test --pathname=$(TESTDB) --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) && ./mdbx_chk -vvn $(TESTDB)
+check-singleprocess: all
+ rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; test/test --pathname=$(TESTDB) --dont-cleanup-after --hill | tee -a $(TESTLOG) | tail -n 42) && ./mdbx_chk -vvn $(TESTDB)
+
+check-fault: all
+ rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; test/test --pathname=$(TESTDB) --inject-writefault=42 --dump-config --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) && ./mdbx_chk -vvn $(TESTDB)
+
define core-rule
$(patsubst %.c,%.o,$(1)): $(1) $(CORE_INC) mdbx.h Makefile
$(CC) $(CFLAGS) -c $(1) -o $$@
@@ -111,10 +115,12 @@ libmdbx.so: $(CORE_OBJ)
$(CC) $(CFLAGS) -save-temps $^ -pthread -shared $(LDFLAGS) -o $@
mdbx_%: src/tools/mdbx_%.c libmdbx.a
- $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
+ $(CC) $(CFLAGS) $^ $(EXE_LDFLAGS) -o $@
test/test: $(TEST_OBJ) libmdbx.a
- $(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
+ $(CXX) $(CXXFLAGS) $^ $(EXE_LDFLAGS) -o $@
+
+###############################################################################
ifneq ($(wildcard $(IOARENA)),)
@@ -163,6 +169,8 @@ bench-quartet: bench-mdbx_$(NN).txt bench-lmdb_$(NN).txt bench-rocksdb_$(NN).txt
endif
+###############################################################################
+
ci-rule = ( CC=$$(which $1); if [ -n "$$CC" ]; then \
echo -n "probe by $2 ($$(readlink -f $$(which $$CC))): " && \
$(MAKE) clean >$1.log 2>$1.err && \
@@ -178,3 +186,36 @@ ci:
@$(call ci-rule,gcc,GCC)
@$(call ci-rule,clang,clang LLVM)
@$(call ci-rule,icc,Intel C)
+
+###############################################################################
+
+CROSS_LIST = alpha-linux-gnu-gcc mips-linux-gnu-gcc \
+ powerpc64-linux-gnu-gcc powerpc-linux-gnu-gcc \
+ arm-linux-gnueabihf-gcc aarch64-linux-gnu-gcc
+
+# hppa-linux-gnu-gcc - don't supported by current qemu release
+# s390x-linux-gnu-gcc - qemu troubles (hang/abort)
+# sh4-linux-gnu-gcc - qemu troubles (pread syscall, etc)
+# mips64-linux-gnuabi64-gcc - qemu troubles (pread syscall, etc)
+# sparc64-linux-gnu-gcc - qemu troubles (fcntl for F_SETLK/F_GETLK)
+CROSS_LIST_NOQEMU = hppa-linux-gnu-gcc s390x-linux-gnu-gcc \
+ sh4-linux-gnu-gcc mips64-linux-gnuabi64-gcc sparc64-linux-gnu-gcc
+
+cross-gcc:
+ @echo "CORRESPONDING CROSS-COMPILERs ARE REQUIRED."
+ @echo "FOR INSTANCE: apt install g++-aarch64-linux-gnu g++-alpha-linux-gnu g++-arm-linux-gnueabihf g++-hppa-linux-gnu g++-mips-linux-gnu g++-mips64-linux-gnuabi64 g++-powerpc-linux-gnu g++-powerpc64-linux-gnu g++-s390x-linux-gnu g++-sh4-linux-gnu"
+ @for CC in $(CROSS_LIST_NOQEMU) $(CROSS_LIST); do \
+ echo "===================== $$CC"; \
+ $(MAKE) clean && CC=$$CC CXX=$$(echo $$CC | sed 's/-gcc/-g++/') EXE_LDFLAGS=-static $(MAKE) all || exit $$?; \
+ done
+
+#
+# Unfortunately qemu don't provide robust support for futexes.
+# Therefore it is impossible to run full multi-process tests.
+cross-qemu:
+ @echo "CORRESPONDING CROSS-COMPILERs AND QEMUs ARE REQUIRED."
+ @echo "FOR INSTANCE: apt install binfmt-support qemu-user-static qemu-user qemu-system-arm qemu-system-mips qemu-system-misc qemu-system-ppc qemu-system-sparc g++-aarch64-linux-gnu g++-alpha-linux-gnu g++-arm-linux-gnueabihf g++-hppa-linux-gnu g++-mips-linux-gnu g++-mips64-linux-gnuabi64 g++-powerpc-linux-gnu g++-powerpc64-linux-gnu g++-s390x-linux-gnu g++-sh4-linux-gnu"
+ @for CC in $(CROSS_LIST); do \
+ echo "===================== $$CC + qemu"; \
+ $(MAKE) clean && CC=$$CC CXX=$$(echo $$CC | sed 's/-gcc/-g++/') EXE_LDFLAGS=-static $(MAKE) check-singleprocess || exit $$?; \
+ done
diff --git a/plugins/Dbx_mdbx/src/libmdbx/README-RU.md b/plugins/Dbx_mdbx/src/libmdbx/README-RU.md
index 679146fd81..095a25984f 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/README-RU.md
+++ b/plugins/Dbx_mdbx/src/libmdbx/README-RU.md
@@ -12,13 +12,24 @@ and [by Yandex](https://translate.yandex.ru/translate?url=https%3A%2F%2Fgithub.c
### Project Status
-**Now MDBX is under _active development_** and until 2018Q2 is expected a big
-change both of API and database format. Unfortunately those update will lead to
-loss of compatibility with previous versions.
-The aim of this revolution in providing a clearer robust API and adding new
-features, including the database properties.
+**Сейчас MDBX _активно перерабатывается_** и к середине 2018
+ожидается большое измените как API, так и формата базы данных.
+К сожалению, обновление приведет к потере совместимости с
+предыдущими версиями.
+Цель этой революции в обеспечении более четкого надежного
+API и добавлении новых функции, а также в наделении базы данных
+новыми свойствами.
+
+В настоящее время MDBX предназначена для Linux, а также
+поддерживает Windows (начиная с Windows Server 2008) в качестве
+дополнительно платформы. Поддержка других ОС может быть
+обеспечена на коммерческой основе. Однако такие
+усовершенствования (т. е. pull-requests) могут быть приняты в
+мейнстрим только в том случае, если будет доступен
+соответствующий публичный и бесплатный сервис непрерывной
+интеграции (aka Countinious Integration).
## Содержание
@@ -43,7 +54,7 @@ features, including the database properties.
_libmdbx_ - это встраиваемый key-value движок хранения со специфическим
набором свойств и возможностей, ориентированный на создание уникальных
-легковесных решений с предельной производительностью.
+легковесных решений с предельной производительностью под Linux и Windows.
_libmdbx_ позволяет множеству процессов совместно читать и обновлять
несколько key-value таблиц с соблюдением [ACID](https://ru.wikipedia.org/wiki/ACID),
diff --git a/plugins/Dbx_mdbx/src/libmdbx/README.md b/plugins/Dbx_mdbx/src/libmdbx/README.md
index fb5e2e7538..216c997f08 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/README.md
+++ b/plugins/Dbx_mdbx/src/libmdbx/README.md
@@ -9,9 +9,17 @@ libmdbx
### Project Status
-**MDBX is under _active development_**, database format and API aren't stable
-at least until 2018Q2. New version won't be backwards compatible.
-Main focus of the rework is to provide clear and robust API and new features.
+**MDBX is under _active development_**, database format and
+API aren't stable at least until 2018Q3. New version won't be
+backwards compatible. Main focus of the rework is to provide
+clear and robust API and new features.
+
+Nowadays MDBX intended for Linux and support Windows (since
+Windows Server 2008) as complementary platform. Support for
+other OS could be implemented on commercial basis. However such
+enhancements (i.e. pull requests) could be accepted in
+mainstream only when corresponding public and free Countinious
+Integration service will be available.
## Contents
@@ -34,7 +42,7 @@ Main focus of the rework is to provide clear and robust API and new features.
## Overview
-_libmdbx_ is an embedded lightweight key-value database engine oriented for performance.
+_libmdbx_ is an embedded lightweight key-value database engine oriented for performance under Linux and Windows.
_libmdbx_ allows multiple processes to read and update several key-value tables concurrently,
while being [ACID](https://en.wikipedia.org/wiki/ACID)-compliant, with minimal overhead and operation cost of Olog(N).
@@ -233,7 +241,7 @@ scanning data directory.
Because of this syncing data to disk might be quite resource intensive and be main performance bottleneck
during intensive write workload.
> As compromise _libmdbx_ allows several modes of lazy and/or periodic syncing, including `MAPASYNC` mode, which modificate
- > data in memory and asynchronously syncs data to disc, moment to sync is picked by OS.
+ > data in memory and asynchronously syncs data to disk, moment to sync is picked by OS.
>
> Although this should be used with care, synchronous transactions in a DB with transaction journal will require 2 IOPS
> minimum (probably 3-4 in practice) because of filesystem overhead, overhead depends on filesystem, not on record
@@ -339,7 +347,7 @@ Improvements over LMDB
This allows to minimize reclaim loop and make it execution time independent from total page count.
This results in OS kernel cache mechanisms working with maximum efficiency.
- In case of using disc controllers or storages with
+ In case of using disk controllers or storages with
[BBWC](https://en.wikipedia.org/wiki/Disk_buffer#Write_acceleration) this may greatly improve
write performance.
@@ -378,7 +386,7 @@ Improvements over LMDB
9. Check if there is a row with data after current cursor position via `mdbx_cursor_eof()`.
-10. Ability to explicitly request update of current record without creating new record. Implemented as `MDBX_CURRENT` flag
+10. Ability to explicitly request update of present record without creating new record. Implemented as `MDBX_CURRENT` flag
for `mdbx_put()`.
11. Ability to update or delete record and get previous value via `mdbx_replace()` Also can update specific multi-value.
@@ -419,7 +427,7 @@ Improvements over LMDB
22. Additional error code `MDBX_EMULTIVAL`, which is returned by `mdbx_put()` and
`mdbx_replace()` in case is ambiguous update or delete.
-23. Ability to get value by key and duplicates count by `mdbx_get_ex()`
+23. Ability to get value by key and duplicates count by `mdbx_get_ex()`.
24. Functions `mdbx_cursor_on_first() and mdbx_cursor_on_last(), which allows to know if cursor is currently on first or
last position respectively.
diff --git a/plugins/Dbx_mdbx/src/libmdbx/TODO.md b/plugins/Dbx_mdbx/src/libmdbx/TODO.md
index 1af7e004bb..32c4f0ac25 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/TODO.md
+++ b/plugins/Dbx_mdbx/src/libmdbx/TODO.md
@@ -21,7 +21,7 @@
Тесты
=====
- [ ] Тестирование поддержки lockless-режима.
-- [ ] Додумать имя и размещение тестовой БД по-умолчанию.
+- [x] Додумать имя и размещение тестовой БД по-умолчанию.
- [ ] Реализовать cleanup в тесте.
- [ ] usage для теста.
- [ ] Логирование в файл, плюс более полный progress bar.
diff --git a/plugins/Dbx_mdbx/src/libmdbx/mdbx.h b/plugins/Dbx_mdbx/src/libmdbx/mdbx.h
index 2cf3273b06..36146fb685 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/mdbx.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/mdbx.h
@@ -982,6 +982,15 @@ LIBMDBX_API int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
* [in] txn A transaction handle returned by mdbx_txn_begin() */
LIBMDBX_API MDBX_env *mdbx_txn_env(MDBX_txn *txn);
+/* Return the transaction's flags.
+ *
+ * This returns the flags associated with this transaction.
+ *
+ * [in] txn A transaction handle returned by mdbx_txn_begin()
+ *
+ * Returns A transaction flags, valid if input is an active transaction. */
+LIBMDBX_API int mdbx_txn_flags(MDBX_txn *txn);
+
/* Return the transaction's ID.
*
* This returns the identifier associated with this transaction. For a
@@ -1818,6 +1827,42 @@ LIBMDBX_API int mdbx_cursor_get_attr(MDBX_cursor *mc, MDBX_val *key,
LIBMDBX_API int mdbx_get_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
MDBX_val *data, mdbx_attr_t *attrptr);
+/*----------------------------------------------------------------------------*/
+/* LY: temporary workaround for Elbrus's memcmp() bug. */
+#ifndef __GLIBC_PREREQ
+#if defined(__GLIBC__) && defined(__GLIBC_MINOR__)
+#define __GLIBC_PREREQ(maj, min) \
+ ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))
+#else
+#define __GLIBC_PREREQ(maj, min) (0)
+#endif
+#endif /* __GLIBC_PREREQ */
+#if defined(__e2k__) && !__GLIBC_PREREQ(2, 24)
+LIBMDBX_API int mdbx_e2k_memcmp_bug_workaround(const void *s1, const void *s2,
+ size_t n);
+LIBMDBX_API int mdbx_e2k_strcmp_bug_workaround(const char *s1, const char *s2);
+LIBMDBX_API int mdbx_e2k_strncmp_bug_workaround(const char *s1, const char *s2,
+ size_t n);
+LIBMDBX_API size_t mdbx_e2k_strlen_bug_workaround(const char *s);
+LIBMDBX_API size_t mdbx_e2k_strnlen_bug_workaround(const char *s,
+ size_t maxlen);
+#include <string.h>
+#include <strings.h>
+#undef memcmp
+#define memcmp mdbx_e2k_memcmp_bug_workaround
+#undef bcmp
+#define bcmp mdbx_e2k_memcmp_bug_workaround
+#undef strcmp
+#define strcmp mdbx_e2k_strcmp_bug_workaround
+#undef strncmp
+#define strncmp mdbx_e2k_strncmp_bug_workaround
+#undef strlen
+#define strlen mdbx_e2k_strlen_bug_workaround
+#undef strnlen
+#define strnlen mdbx_e2k_strnlen_bug_workaround
+
+#endif /* Elbrus's memcmp() bug. */
+
#ifdef __cplusplus
}
#endif
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/bits.h b/plugins/Dbx_mdbx/src/libmdbx/src/bits.h
index 67def2ed90..7f69cdc066 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/bits.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/bits.h
@@ -55,6 +55,7 @@
#pragma warning(disable : 4310) /* cast truncates constant value */
#pragma warning(disable : 4820) /* bytes padding added after data member for aligment */
#pragma warning(disable : 4548) /* expression before comma has no effect; expected expression with side - effect */
+#pragma warning(disable : 4366) /* the result of the unary '&' operator may be unaligned */
#endif /* _MSC_VER (warnings) */
#include "../mdbx.h"
@@ -89,26 +90,29 @@
#endif /* __SANITIZE_THREAD__ */
#if __has_warning("-Wconstant-logical-operand")
-#if defined(__clang__)
-#pragma clang diagnostic ignored "-Wconstant-logical-operand"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wconstant-logical-operand"
-#else
-#pragma warning disable "constant-logical-operand"
-#endif
+# if defined(__clang__)
+# pragma clang diagnostic ignored "-Wconstant-logical-operand"
+# elif defined(__GNUC__)
+# pragma GCC diagnostic ignored "-Wconstant-logical-operand"
+# else
+# pragma warning disable "constant-logical-operand"
+# endif
#endif /* -Wconstant-logical-operand */
-#if __has_warning("-Walignment-reduction-ignored") || defined(__e2k__) || defined(__ICC)
-#if defined(__ICC)
-#pragma warning(disable: 3453 1366)
-#elif defined(__clang__)
-#pragma clang diagnostic ignored "-Walignment-reduction-ignored"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Walignment-reduction-ignored"
-#else
-#pragma warning disable "alignment-reduction-ignored"
-#endif
-#endif /* -Wno-constant-logical-operand */
+#if defined(__LCC__) && (__LCC__ <= 121)
+ /* bug #2798 */
+# pragma diag_suppress alignment_reduction_ignored
+#elif defined(__ICC)
+# pragma warning(disable: 3453 1366)
+#elif __has_warning("-Walignment-reduction-ignored")
+# if defined(__clang__)
+# pragma clang diagnostic ignored "-Walignment-reduction-ignored"
+# elif defined(__GNUC__)
+# pragma GCC diagnostic ignored "-Walignment-reduction-ignored"
+# else
+# pragma warning disable "alignment-reduction-ignored"
+# endif
+#endif /* -Walignment-reduction-ignored */
#include "./osal.h"
@@ -249,7 +253,7 @@ typedef struct MDBX_reader {
uint8_t pad[MDBX_CACHELINE_SIZE -
(sizeof(txnid_t) + sizeof(mdbx_pid_t) + sizeof(mdbx_tid_t)) %
MDBX_CACHELINE_SIZE];
-} __cache_aligned MDBX_reader;
+} MDBX_reader;
/* Information about a single database in the environment. */
typedef struct MDBX_db {
@@ -407,47 +411,53 @@ typedef struct MDBX_lockinfo {
/* Flags which environment was opened. */
volatile uint32_t mti_envmode;
- union {
#ifdef MDBX_OSAL_LOCK
+ /* Mutex protecting write access to this table. */
+ union {
MDBX_OSAL_LOCK mti_wmutex;
-#endif
- uint64_t align_wmutex;
+ uint8_t pad_mti_wmutex[MDBX_OSAL_LOCK_SIZE % sizeof(size_t)];
};
+#endif
+#define MDBX_lockinfo_SIZE_A \
+ (8 /* mti_magic_and_version */ + 4 /* mti_os_and_format */ + \
+ 4 /* mti_envmode */ + MDBX_OSAL_LOCK_SIZE /* mti_wmutex */ + \
+ MDBX_OSAL_LOCK_SIZE % sizeof(size_t) /* pad_mti_wmutex */)
- union {
- /* The number of slots that have been used in the reader table.
- * This always records the maximum count, it is not decremented
- * when readers release their slots. */
- volatile unsigned __cache_aligned mti_numreaders;
- uint64_t align_numreaders;
- };
+ /* cache-line alignment */
+ uint8_t
+ pad_a[MDBX_CACHELINE_SIZE - MDBX_lockinfo_SIZE_A % MDBX_CACHELINE_SIZE];
+
+ /* The number of slots that have been used in the reader table.
+ * This always records the maximum count, it is not decremented
+ * when readers release their slots. */
+ volatile unsigned mti_numreaders;
- union {
#ifdef MDBX_OSAL_LOCK
- /* Mutex protecting access to this table. */
+ /* Mutex protecting readers registration access to this table. */
+ union {
MDBX_OSAL_LOCK mti_rmutex;
-#endif
- uint64_t align_rmutex;
+ uint8_t pad_mti_rmutex[MDBX_OSAL_LOCK_SIZE % sizeof(size_t)];
};
+#endif
- union {
- volatile txnid_t mti_oldest;
- uint64_t align_oldest;
- };
+ volatile txnid_t mti_oldest;
+ volatile uint32_t mti_readers_refresh_flag;
- union {
- volatile uint32_t mti_readers_refresh_flag;
- uint64_t align_reader_finished_flag;
- };
+#define MDBX_lockinfo_SIZE_B \
+ (sizeof(unsigned) /* mti_numreaders */ + \
+ MDBX_OSAL_LOCK_SIZE /* mti_rmutex */ + sizeof(txnid_t) /* mti_oldest */ + \
+ sizeof(uint32_t) /* mti_readers_refresh_flag */ + \
+ MDBX_OSAL_LOCK_SIZE % sizeof(size_t) /* pad_mti_rmutex */)
- uint8_t pad_align[MDBX_CACHELINE_SIZE - sizeof(uint64_t) * 7];
+ /* cache-line alignment */
+ uint8_t
+ pad_b[MDBX_CACHELINE_SIZE - MDBX_lockinfo_SIZE_B % MDBX_CACHELINE_SIZE];
+
+ MDBX_reader mti_readers[1];
- MDBX_reader __cache_aligned mti_readers[1];
} MDBX_lockinfo;
-#ifdef _MSC_VER
#pragma pack(pop)
-#endif /* MSVC: Enable aligment */
#define MDBX_LOCKINFO_WHOLE_SIZE \
((sizeof(MDBX_lockinfo) + MDBX_CACHELINE_SIZE - 1) & \
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/defs.h b/plugins/Dbx_mdbx/src/libmdbx/src/defs.h
index 7c3bc1d540..6da5a96363 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/defs.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/defs.h
@@ -192,16 +192,6 @@
# endif
#endif /* __prefetch */
-#ifndef __aligned
-# if defined(__GNUC__) || __has_attribute(aligned)
-# define __aligned(N) __attribute__((aligned(N)))
-# elif defined(_MSC_VER)
-# define __aligned(N) __declspec(align(N))
-# else
-# define __aligned(N)
-# endif
-#endif /* __aligned */
-
#ifndef __noreturn
# if defined(__GNUC__) || __has_attribute(noreturn)
# define __noreturn __attribute__((noreturn))
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c b/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c
index aac32704a9..7845e6d733 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c
@@ -37,6 +37,117 @@
#include "./bits.h"
+/* LY: temporary workaround for Elbrus's memcmp() bug. */
+#if defined(__e2k__) && !__GLIBC_PREREQ(2, 24)
+int __hot mdbx_e2k_memcmp_bug_workaround(const void *s1, const void *s2,
+ size_t n) {
+ if (unlikely(n > 42
+ /* LY: align followed access if reasonable possible */ &&
+ (((uintptr_t)s1) & 7) != 0 &&
+ (((uintptr_t)s1) & 7) == (((uintptr_t)s2) & 7))) {
+ if (((uintptr_t)s1) & 1) {
+ const int diff = *(uint8_t *)s1 - *(uint8_t *)s2;
+ if (diff)
+ return diff;
+ s1 = (char *)s1 + 1;
+ s2 = (char *)s2 + 1;
+ n -= 1;
+ }
+
+ if (((uintptr_t)s1) & 2) {
+ const uint16_t a = *(uint16_t *)s1;
+ const uint16_t b = *(uint16_t *)s2;
+ if (likely(a != b))
+ return (__builtin_bswap16(a) > __builtin_bswap16(b)) ? 1 : -1;
+ s1 = (char *)s1 + 2;
+ s2 = (char *)s2 + 2;
+ n -= 2;
+ }
+
+ if (((uintptr_t)s1) & 4) {
+ const uint32_t a = *(uint32_t *)s1;
+ const uint32_t b = *(uint32_t *)s2;
+ if (likely(a != b))
+ return (__builtin_bswap32(a) > __builtin_bswap32(b)) ? 1 : -1;
+ s1 = (char *)s1 + 4;
+ s2 = (char *)s2 + 4;
+ n -= 4;
+ }
+ }
+
+ while (n >= 8) {
+ const uint64_t a = *(uint64_t *)s1;
+ const uint64_t b = *(uint64_t *)s2;
+ if (likely(a != b))
+ return (__builtin_bswap64(a) > __builtin_bswap64(b)) ? 1 : -1;
+ s1 = (char *)s1 + 8;
+ s2 = (char *)s2 + 8;
+ n -= 8;
+ }
+
+ if (n & 4) {
+ const uint32_t a = *(uint32_t *)s1;
+ const uint32_t b = *(uint32_t *)s2;
+ if (likely(a != b))
+ return (__builtin_bswap32(a) > __builtin_bswap32(b)) ? 1 : -1;
+ s1 = (char *)s1 + 4;
+ s2 = (char *)s2 + 4;
+ }
+
+ if (n & 2) {
+ const uint16_t a = *(uint16_t *)s1;
+ const uint16_t b = *(uint16_t *)s2;
+ if (likely(a != b))
+ return (__builtin_bswap16(a) > __builtin_bswap16(b)) ? 1 : -1;
+ s1 = (char *)s1 + 2;
+ s2 = (char *)s2 + 2;
+ }
+
+ return (n & 1) ? *(uint8_t *)s1 - *(uint8_t *)s2 : 0;
+}
+
+int __hot mdbx_e2k_strcmp_bug_workaround(const char *s1, const char *s2) {
+ while (true) {
+ int diff = *(uint8_t *)s1 - *(uint8_t *)s2;
+ if (likely(diff != 0) || *s1 == '\0')
+ return diff;
+ s1 += 1;
+ s2 += 1;
+ }
+}
+
+int __hot mdbx_e2k_strncmp_bug_workaround(const char *s1, const char *s2,
+ size_t n) {
+ while (n > 0) {
+ int diff = *(uint8_t *)s1 - *(uint8_t *)s2;
+ if (likely(diff != 0) || *s1 == '\0')
+ return diff;
+ s1 += 1;
+ s2 += 1;
+ n -= 1;
+ }
+ return 0;
+}
+
+size_t __hot mdbx_e2k_strlen_bug_workaround(const char *s) {
+ size_t n = 0;
+ while (*s) {
+ s += 1;
+ n += 1;
+ }
+ return n;
+}
+
+size_t __hot mdbx_e2k_strnlen_bug_workaround(const char *s, size_t maxlen) {
+ size_t n = 0;
+ while (maxlen > n && *s) {
+ s += 1;
+ n += 1;
+ }
+ return n;
+}
+#endif /* Elbrus's memcmp() bug. */
+
/*----------------------------------------------------------------------------*/
/* rthc (tls keys and destructors) */
@@ -2507,6 +2618,12 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
return MDBX_PANIC;
}
+ STATIC_ASSERT(sizeof(MDBX_reader) == MDBX_CACHELINE_SIZE);
+ STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_numreaders) % MDBX_CACHELINE_SIZE ==
+ 0);
+ STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE ==
+ 0);
+
pgno_t upper_pgno = 0;
if (flags & MDBX_TXN_RDONLY) {
txn->mt_flags = MDBX_TXN_RDONLY;
@@ -2562,9 +2679,6 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
}
}
- STATIC_ASSERT(sizeof(MDBX_reader) == MDBX_CACHELINE_SIZE);
- STATIC_ASSERT(
- offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE == 0);
r = &env->me_lck->mti_readers[slot];
/* Claim the reader slot, carefully since other code
* uses the reader table un-mutexed: First reset the
@@ -2876,6 +2990,13 @@ uint64_t mdbx_txn_id(MDBX_txn *txn) {
return txn->mt_txnid;
}
+int mdbx_txn_flags(MDBX_txn *txn) {
+ if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE))
+ return -1;
+
+ return txn->mt_flags;
+}
+
/* Export or close DBI handles opened in this txn. */
static void mdbx_dbis_update(MDBX_txn *txn, int keep) {
MDBX_dbi n = txn->mt_numdbs;
@@ -4042,7 +4163,7 @@ static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta) {
STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE);
if (mapsize_max > MAX_MAPSIZE ||
MAX_PAGENO < mdbx_roundup2((size_t)mapsize_max, env->me_os_psize) /
- (uint64_t)page.mp_meta.mm_psize) {
+ (size_t)page.mp_meta.mm_psize) {
const uint64_t used_bytes =
page.mp_meta.mm_geo.next * (uint64_t)page.mp_meta.mm_psize;
if (page.mp_meta.mm_geo.next - 1 > MAX_PAGENO ||
@@ -4644,13 +4765,13 @@ LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower,
if (pagesize < 0) {
pagesize = env->me_os_psize;
- if (pagesize > MAX_PAGESIZE)
+ if ((uintptr_t)pagesize > MAX_PAGESIZE)
pagesize = MAX_PAGESIZE;
- mdbx_assert(env, pagesize >= MIN_PAGESIZE);
+ mdbx_assert(env, (uintptr_t)pagesize >= MIN_PAGESIZE);
}
}
- if (pagesize < MIN_PAGESIZE || pagesize > MAX_PAGESIZE ||
+ if (pagesize < (intptr_t)MIN_PAGESIZE || pagesize > (intptr_t)MAX_PAGESIZE ||
!mdbx_is_power2(pagesize)) {
rc = MDBX_EINVAL;
goto bailout;
@@ -4684,7 +4805,7 @@ LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower,
size_upper = pagesize * MAX_PAGENO;
}
- if (unlikely(size_lower < MIN_MAPSIZE || size_lower > size_upper)) {
+ if (unlikely(size_lower < (intptr_t)MIN_MAPSIZE || size_lower > size_upper)) {
rc = MDBX_EINVAL;
goto bailout;
}
@@ -4991,7 +5112,7 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) {
filesize_before_mmap,
bytes2pgno(env, (size_t)filesize_before_mmap));
} else {
- mdbx_notice("filesize mismatch (expect %" PRIuPTR "/%" PRIaPGNO
+ mdbx_notice("filesize mismatch (expect %" PRIuSIZE "/%" PRIaPGNO
", have %" PRIu64 "/%" PRIaPGNO ")",
expected_bytes, bytes2pgno(env, expected_bytes),
filesize_before_mmap,
@@ -5007,11 +5128,11 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) {
if (env->me_flags & MDBX_RDONLY) {
mdbx_notice("ignore filesize mismatch in readonly-mode");
} else {
- mdbx_info("resize datafile to %" PRIu64 " bytes, %" PRIaPGNO " pages",
+ mdbx_info("resize datafile to %" PRIuSIZE " bytes, %" PRIaPGNO " pages",
expected_bytes, bytes2pgno(env, expected_bytes));
err = mdbx_ftruncate(env->me_fd, expected_bytes);
if (unlikely(err != MDBX_SUCCESS)) {
- mdbx_error("error %d, while resize datafile to %" PRIu64
+ mdbx_error("error %d, while resize datafile to %" PRIuSIZE
" bytes, %" PRIaPGNO " pages",
rc, expected_bytes, bytes2pgno(env, expected_bytes));
return err;
@@ -5048,15 +5169,30 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) {
return MDBX_WANNA_RECOVERY /* LY: could not recovery/rollback */;
}
+ const MDBX_meta *const meta0 = METAPAGE(env, 0);
+ const MDBX_meta *const meta1 = METAPAGE(env, 1);
+ const MDBX_meta *const meta2 = METAPAGE(env, 2);
+ txnid_t undo_txnid = 0;
+ while (
+ (head != meta0 && mdbx_meta_txnid_fluid(env, meta0) == undo_txnid) ||
+ (head != meta1 && mdbx_meta_txnid_fluid(env, meta1) == undo_txnid) ||
+ (head != meta2 && mdbx_meta_txnid_fluid(env, meta2) == undo_txnid))
+ undo_txnid += 1;
+ if (unlikely(undo_txnid >= meta.mm_txnid_a)) {
+ mdbx_fatal("rollback failed: no suitable txnid (0,1,2) < %" PRIaTXN,
+ meta.mm_txnid_a);
+ return MDBX_PANIC /* LY: could not recovery/rollback */;
+ }
+
/* LY: rollback weak checkpoint */
- mdbx_trace("rollback: from %" PRIaTXN ", to %" PRIaTXN, head_txnid,
- meta.mm_txnid_a);
+ mdbx_trace("rollback: from %" PRIaTXN ", to %" PRIaTXN " as %" PRIaTXN,
+ head_txnid, meta.mm_txnid_a, undo_txnid);
mdbx_ensure(env, head_txnid == mdbx_meta_txnid_stable(env, head));
if (env->me_flags & MDBX_WRITEMAP) {
- head->mm_txnid_a = 0;
+ head->mm_txnid_a = undo_txnid;
head->mm_datasync_sign = MDBX_DATASIGN_WEAK;
- head->mm_txnid_b = 0;
+ head->mm_txnid_b = undo_txnid;
const size_t offset =
((uint8_t *)container_of(head, MDBX_page, mp_meta)) -
env->me_dxb_mmap.dxb;
@@ -5066,7 +5202,7 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) {
err = mdbx_msync(&env->me_dxb_mmap, paged_offset, paged_length, false);
} else {
MDBX_meta rollback = *head;
- mdbx_meta_set_txnid(env, &rollback, 0);
+ mdbx_meta_set_txnid(env, &rollback, undo_txnid);
rollback.mm_datasync_sign = MDBX_DATASIGN_WEAK;
err = mdbx_pwrite(env->me_fd, &rollback, sizeof(MDBX_meta),
(uint8_t *)head - (uint8_t *)env->me_map);
@@ -5075,7 +5211,7 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) {
return err;
mdbx_invalidate_cache(env->me_map, pgno2bytes(env, NUM_METAS));
- mdbx_ensure(env, 0 == mdbx_meta_txnid_fluid(env, head));
+ mdbx_ensure(env, undo_txnid == mdbx_meta_txnid_fluid(env, head));
mdbx_ensure(env, 0 == mdbx_meta_eq_mask(env));
continue;
}
@@ -7059,7 +7195,8 @@ int mdbx_cursor_put(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
} else {
rc = mdbx_cursor_set(mc, key, &d2, MDBX_SET, &exact);
}
- if ((flags & MDBX_NOOVERWRITE) && rc == 0) {
+ if ((flags & MDBX_NOOVERWRITE) &&
+ (rc == MDBX_SUCCESS || rc == MDBX_EKEYMISMATCH)) {
mdbx_debug("duplicate key [%s]", DKEY(key));
*data = d2;
return MDBX_KEYEXIST;
@@ -7273,9 +7410,11 @@ int mdbx_cursor_put(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
memcpy((char *)mp + mp->mp_upper + PAGEHDRSZ,
(char *)fp + fp->mp_upper + PAGEHDRSZ,
olddata.iov_len - fp->mp_upper - PAGEHDRSZ);
+ memcpy((char *)(&mp->mp_ptrs), (char *)(&fp->mp_ptrs),
+ NUMKEYS(fp) * sizeof(mp->mp_ptrs[0]));
for (i = 0; i < NUMKEYS(fp); i++) {
- mdbx_cassert(mc, fp->mp_ptrs[i] + offset <= UINT16_MAX);
- mp->mp_ptrs[i] = (indx_t)(fp->mp_ptrs[i] + offset);
+ mdbx_cassert(mc, mp->mp_ptrs[i] + offset <= UINT16_MAX);
+ mp->mp_ptrs[i] += (indx_t)offset;
}
}
}
@@ -8796,27 +8935,22 @@ static int mdbx_rebalance(MDBX_cursor *mc) {
if (unlikely(rc))
return rc;
/* Adjust cursors pointing to mp */
+ const MDBX_dbi dbi = mc->mc_dbi;
+ for (MDBX_cursor *m2 = mc->mc_txn->mt_cursors[dbi]; m2;
+ m2 = m2->mc_next) {
+ MDBX_cursor *m3 =
+ (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2;
+ if (!(m3->mc_flags & C_INITIALIZED) || (m3->mc_snum < mc->mc_snum))
+ continue;
+ if (m3->mc_pg[0] == mp) {
+ m3->mc_snum = 0;
+ m3->mc_top = 0;
+ m3->mc_flags &= ~C_INITIALIZED;
+ }
+ }
mc->mc_snum = 0;
mc->mc_top = 0;
mc->mc_flags &= ~C_INITIALIZED;
- {
- MDBX_cursor *m2, *m3;
- MDBX_dbi dbi = mc->mc_dbi;
-
- for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) {
- if (mc->mc_flags & C_SUB)
- m3 = &m2->mc_xcursor->mx_cursor;
- else
- m3 = m2;
- if (!(m3->mc_flags & C_INITIALIZED) || (m3->mc_snum < mc->mc_snum))
- continue;
- if (m3->mc_pg[0] == mp) {
- m3->mc_snum = 0;
- m3->mc_top = 0;
- m3->mc_flags &= ~C_INITIALIZED;
- }
- }
- }
} else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) {
int i;
mdbx_debug("collapsing root page!");
@@ -10349,13 +10483,13 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags,
!strncmp(table_name, txn->mt_dbxs[scan].md_name.iov_base, len)) {
*dbi = scan;
rc = mdbx_dbi_bind(txn, scan, user_flags, keycmp, datacmp);
- goto unlock_return_rc;
+ goto bailout;
}
}
if (unlikely(slot >= env->me_maxdbs)) {
rc = MDBX_DBS_FULL;
- goto unlock_return_rc;
+ goto bailout;
}
unsigned dbflag = DB_FRESH | DB_VALID | DB_USRVALID;
@@ -10405,7 +10539,6 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags,
*dbi = slot;
}
-unlock_return_rc:
mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS);
return rc;
}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/osal.h b/plugins/Dbx_mdbx/src/libmdbx/src/osal.h
index 54559388c9..e01311cb01 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/osal.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/osal.h
@@ -103,24 +103,47 @@ typedef struct {
typedef pthread_mutex_t mdbx_fastmutex_t;
#endif /* Platform */
-#ifndef SSIZE_MAX
-#define SSIZE_MAX INTPTR_MAX
-#endif
-
-#ifdef HAVE_SYS_STAT_H
+/* *INDENT-OFF* */
+/* clang-format off */
+#if defined(HAVE_SYS_STAT_H) || __has_include(<sys/stat.h>)
#include <sys/stat.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
+#if defined(HAVE_SYS_TYPES_H) || __has_include(<sys/types.h>)
#include <sys/types.h>
#endif
-#ifdef HAVE_SYS_FILE_H
+#if defined(HAVE_SYS_FILE_H) || __has_include(<sys/file.h>)
#include <sys/file.h>
#endif
+/* *INDENT-ON* */
+/* clang-format on */
+
+#ifndef SSIZE_MAX
+#define SSIZE_MAX INTPTR_MAX
+#endif
+
+#if defined(i386) || defined(__386) || defined(__i386) || defined(__i386__) || \
+ defined(i486) || defined(__i486) || defined(__i486__) || \
+ defined(i586) | defined(__i586) || defined(__i586__) || defined(i686) || \
+ defined(__i686) || defined(__i686__) || defined(_M_IX86) || \
+ defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || \
+ defined(__INTEL__) || defined(__x86_64) || defined(__x86_64__) || \
+ defined(__amd64__) || defined(__amd64) || defined(_M_X64) || \
+ defined(_M_AMD64) || defined(__IA32__) || defined(__INTEL__)
+#ifndef __ia32__
+/* LY: define neutral __ia32__ for x86 and x86-64 archs */
+#define __ia32__ 1
+#endif /* __ia32__ */
+#if !defined(__amd64__) && (defined(__x86_64) || defined(__x86_64__) || \
+ defined(__amd64) || defined(_M_X64))
+/* LY: define trusty __amd64__ for all AMD64/x86-64 arch */
+#define __amd64__ 1
+#endif /* __amd64__ */
+#endif /* all x86 */
#if !defined(UNALIGNED_OK)
-#if defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || \
- defined(_M_X64) || defined(i386) || defined(_X86_) || defined(__i386__) || \
- defined(_X86_64_)
+#if (defined(__ia32__) || defined(__e2k__) || \
+ defined(__ARM_FEATURE_UNALIGNED)) && \
+ !defined(__ALIGNED__)
#define UNALIGNED_OK 1
#else
#define UNALIGNED_OK 0
@@ -135,26 +158,15 @@ typedef pthread_mutex_t mdbx_fastmutex_t;
/*----------------------------------------------------------------------------*/
/* Compiler's includes for builtins/intrinsics */
-#ifdef _MSC_VER
-
-#if _MSC_FULL_VER < 190024215
-#if _MSC_FULL_VER < 180040629 && defined(_M_IX86)
-#error Please use Visual Studio 2015 (MSC 19.0) or newer for 32-bit target.
-#else
-#pragma message( \
- "It is recommended to use Visual Studio 2015 (MSC 19.0) or newer.")
-#endif
-#endif
-
+#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
#include <intrin.h>
-
#elif __GNUC_PREREQ(4, 4) || defined(__clang__)
-#if defined(__i386__) || defined(__x86_64__)
-#include <cpuid.h>
+#if defined(__ia32__) || defined(__e2k__)
#include <x86intrin.h>
-#endif
-#elif defined(__INTEL_COMPILER)
-#include <intrin.h>
+#endif /* __ia32__ */
+#if defined(__ia32__)
+#include <cpuid.h>
+#endif /* __ia32__ */
#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun)
#include <mbarrier.h>
#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \
@@ -173,8 +185,10 @@ typedef pthread_mutex_t mdbx_fastmutex_t;
#pragma gcc_extensions
#elif defined(__SNC__)
/* Sony PS3 - troubles ? */
+#elif defined(__hppa__) || defined(__hppa)
+#include <machine/inline.h>
#else
-#error Unknown C compiler, please use GNU C 5.x or newer
+#error Unsupported C compiler, please use GNU C 4.4 or newer
#endif /* Compiler */
/*----------------------------------------------------------------------------*/
@@ -183,44 +197,69 @@ typedef pthread_mutex_t mdbx_fastmutex_t;
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
!defined(__ORDER_BIG_ENDIAN__)
-#if defined(HAVE_ENDIAN_H)
+/* *INDENT-OFF* */
+/* clang-format off */
+#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || defined(__ANDROID__) || \
+ defined(HAVE_ENDIAN_H) || __has_include(<endian.h>)
#include <endian.h>
-#elif defined(HAVE_SYS_PARAM_H)
-#include <sys/param.h> /* for endianness */
-#elif defined(HAVE_NETINET_IN_H) && defined(HAVE_RESOLV_H)
-#include <netinet/in.h>
-#include <resolv.h> /* defines BYTE_ORDER on HPUX and Solaris */
-#endif
+#elif defined(__APPLE__) || defined(__MACH__) || defined(__OpenBSD__) || \
+ defined(HAVE_MACHINE_ENDIAN_H) || __has_include(<machine/endian.h>)
+#include <machine/endian.h>
+#elif defined(HAVE_SYS_ISA_DEFS_H) || __has_include(<sys/isa_defs.h>)
+#include <sys/isa_defs.h>
+#elif (defined(HAVE_SYS_TYPES_H) && defined(HAVE_SYS_ENDIAN_H)) || \
+ (__has_include(<sys/types.h>) && __has_include(<sys/endian.h>))
+#include <sys/endian.h>
+#include <sys/types.h>
+#elif defined(__bsdi__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
+ defined(__NETBSD__) || defined(__NetBSD__) || \
+ defined(HAVE_SYS_PARAM_H) || __has_include(<sys/param.h>)
+#include <sys/param.h>
+#endif /* OS */
+/* *INDENT-ON* */
+/* clang-format on */
#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)
#define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN
#define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN
#define __BYTE_ORDER__ __BYTE_ORDER
+#elif defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
+#define __ORDER_LITTLE_ENDIAN__ _LITTLE_ENDIAN
+#define __ORDER_BIG_ENDIAN__ _BIG_ENDIAN
+#define __BYTE_ORDER__ _BYTE_ORDER
#else
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __ORDER_BIG_ENDIAN__ 4321
-#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) || \
+
+#if defined(__LITTLE_ENDIAN__) || \
+ (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \
defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
defined(__MIPSEL__) || defined(_MIPSEL) || defined(__MIPSEL) || \
- defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || \
- defined(_M_X64) || defined(i386) || defined(_X86_) || defined(__i386__) || \
- defined(_X86_64_) || defined(_M_ARM) || defined(_M_ARM64) || \
- defined(__e2k__)
+ defined(_M_ARM) || defined(_M_ARM64) || defined(__e2k__) || \
+ defined(__elbrus_4c__) || defined(__elbrus_8c__) || defined(__bfin__) || \
+ defined(__BFIN__) || defined(__ia64__) || defined(_IA64) || \
+ defined(__IA64__) || defined(__ia64) || defined(_M_IA64) || \
+ defined(__itanium__) || defined(__ia32__) || defined(__CYGWIN__) || \
+ defined(_WIN64) || defined(_WIN32) || defined(__TOS_WIN__) || \
+ defined(__WINDOWS__)
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
-#elif defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) || defined(__ARMEB__) || \
- defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(__MIPSEB__) || \
- defined(_MIPSEB) || defined(__MIPSEB) || defined(_M_IA64)
+
+#elif defined(__BIG_ENDIAN__) || \
+ (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \
+ defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
+ defined(__MIPSEB__) || defined(_MIPSEB) || defined(__MIPSEB) || \
+ defined(__m68k__) || defined(M68000) || defined(__hppa__) || \
+ defined(__hppa) || defined(__HPPA__) || defined(__sparc__) || \
+ defined(__sparc) || defined(__370__) || defined(__THW_370__) || \
+ defined(__s390__) || defined(__s390x__) || defined(__SYSC_ZARCH__)
#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
+
#else
#error __BYTE_ORDER__ should be defined.
-#endif
-#endif
-#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */
+#endif /* Arch */
-#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ && \
- __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
-#error Unsupported byte order.
#endif
+#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */
/*----------------------------------------------------------------------------*/
/* Memory/Compiler barriers, cache coherence */
@@ -286,17 +325,14 @@ static __inline void mdbx_memory_barrier(void) {
/*----------------------------------------------------------------------------*/
/* Cache coherence and invalidation */
-#if defined(__i386__) || defined(__x86_64__) || defined(_M_AMD64) || \
- defined(_M_IX86) || defined(__i386) || defined(__amd64) || \
- defined(i386) || defined(__x86_64) || defined(_AMD64_) || defined(_M_X64)
-#define MDBX_CACHE_IS_COHERENT 1
-#elif defined(__hppa) || defined(__hppa__)
-#define MDBX_CACHE_IS_COHERENT 1
-#endif
-
#ifndef MDBX_CACHE_IS_COHERENT
+#if defined(__ia32__) || defined(__e2k__) || defined(__hppa) || \
+ defined(__hppa__)
+#define MDBX_CACHE_IS_COHERENT 1
+#else
#define MDBX_CACHE_IS_COHERENT 0
#endif
+#endif /* MDBX_CACHE_IS_COHERENT */
#ifndef MDBX_CACHELINE_SIZE
#if defined(SYSTEM_CACHE_ALIGNMENT_SIZE)
@@ -308,29 +344,29 @@ static __inline void mdbx_memory_barrier(void) {
#endif
#endif /* MDBX_CACHELINE_SIZE */
-#ifndef __cache_aligned
-#define __cache_aligned __aligned(MDBX_CACHELINE_SIZE)
-#endif
-
#if MDBX_CACHE_IS_COHERENT
#define mdbx_coherent_barrier() mdbx_compiler_barrier()
#else
#define mdbx_coherent_barrier() mdbx_memory_barrier()
#endif
-#if defined(__mips) && defined(__linux)
+#if defined(__mips) || defined(__mips__) || defined(__mips64) || \
+ defined(__mips64) || defined(_M_MRX000) || defined(_MIPS_)
/* Only MIPS has explicit cache control */
-#include <asm/cachectl.h>
+#include <sys/cachectl.h>
#endif
static __inline void mdbx_invalidate_cache(void *addr, size_t nbytes) {
mdbx_coherent_barrier();
-#if defined(__mips) && defined(__linux)
+#if defined(__mips) || defined(__mips__) || defined(__mips64) || \
+ defined(__mips64) || defined(_M_MRX000) || defined(_MIPS_)
+#if defined(DCACHE)
/* MIPS has cache coherency issues.
* Note: for any nbytes >= on-chip cache size, entire is flushed. */
cacheflush(addr, nbytes, DCACHE);
-#elif defined(_M_MRX000) || defined(_MIPS_)
+#else
#error "Sorry, cacheflush() for MIPS not implemented"
+#endif /* __mips__ */
#else
/* LY: assume no relevant mmap/dcache issues. */
(void)addr;
@@ -504,7 +540,13 @@ void mdbx_osal_jitter(bool tiny);
#else
#define MDBX_OSAL_LOCK pthread_mutex_t
#define MDBX_OSAL_LOCK_SIGN UINT32_C(0x8017)
-#endif
+#endif /* MDBX_OSAL_LOCK */
+
+#ifdef MDBX_OSAL_LOCK
+#define MDBX_OSAL_LOCK_SIZE sizeof(MDBX_OSAL_LOCK)
+#else
+#define MDBX_OSAL_LOCK_SIZE 0
+#endif /* MDBX_OSAL_LOCK_SIZE */
int mdbx_lck_init(MDBX_env *env);
@@ -516,8 +558,8 @@ void mdbx_lck_destroy(MDBX_env *env);
int mdbx_rdt_lock(MDBX_env *env);
void mdbx_rdt_unlock(MDBX_env *env);
-int mdbx_txn_lock(MDBX_env *env, bool dontwait);
-void mdbx_txn_unlock(MDBX_env *env);
+LIBMDBX_API int mdbx_txn_lock(MDBX_env *env, bool dontwait);
+LIBMDBX_API void mdbx_txn_unlock(MDBX_env *env);
int mdbx_rpid_set(MDBX_env *env);
int mdbx_rpid_clear(MDBX_env *env);
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c
index 054e6e979e..681ee63d46 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c
@@ -77,7 +77,7 @@ int exclusive = 2;
int envflags = MDBX_RDONLY;
MDBX_env *env;
-MDBX_txn *txn, *locktxn;
+MDBX_txn *txn;
MDBX_envinfo envinfo;
MDBX_stat envstat;
size_t maxkeysize, userdb_count, skipped_subdb;
@@ -763,6 +763,7 @@ int main(int argc, char *argv[]) {
char *envname;
int problems_maindb = 0, problems_freedb = 0, problems_meta = 0;
int dont_traversal = 0;
+ bool locked = false;
double elapsed;
#if defined(_WIN32) || defined(_WIN64)
@@ -836,8 +837,8 @@ int main(int argc, char *argv[]) {
#endif /* !WINDOWS */
envname = argv[optind];
- print("Running mdbx_chk for '%s' in %s mode...\n", envname,
- (envflags & MDBX_RDONLY) ? "read-only" : "write-lock");
+ print("Running mdbx_chk for 'read-%s' in %s mode...\n", envname,
+ (envflags & MDBX_RDONLY) ? "read" : "write");
fflush(NULL);
rc = mdbx_env_create(&env);
@@ -862,13 +863,19 @@ int main(int argc, char *argv[]) {
if (verbose)
print(" - %s mode\n", exclusive ? "monopolistic" : "cooperative");
- if (!(envflags & MDBX_RDONLY)) {
- rc = mdbx_txn_begin(env, NULL, 0, &locktxn);
- if (rc) {
- error("mdbx_txn_begin(lock-write) failed, error %d %s\n", rc,
- mdbx_strerror(rc));
+ if ((envflags & MDBX_RDONLY) == 0) {
+ rc = mdbx_txn_lock(env, false);
+ if (rc != MDBX_SUCCESS) {
+ error("mdbx_txn_lock failed, error %d %s\n", rc, mdbx_strerror(rc));
goto bailout;
}
+ locked = true;
+ }
+
+ rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn);
+ if (rc) {
+ error("mdbx_txn_begin() failed, error %d %s\n", rc, mdbx_strerror(rc));
+ goto bailout;
}
rc = mdbx_env_get_maxkeysize(env);
@@ -879,13 +886,6 @@ int main(int argc, char *argv[]) {
}
maxkeysize = rc;
- rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn);
- if (rc) {
- error("mdbx_txn_begin(read-only) failed, error %d %s\n", rc,
- mdbx_strerror(rc));
- goto bailout;
- }
-
rc = mdbx_env_info(env, &envinfo, sizeof(envinfo));
if (rc) {
error("mdbx_env_info failed, error %d %s\n", rc, mdbx_strerror(rc));
@@ -950,14 +950,14 @@ int main(int argc, char *argv[]) {
if (verbose)
print(" - performs full check recent-txn-id with meta-pages\n");
problems_meta += check_meta_head(true);
- } else if (locktxn) {
+ } else if (locked) {
if (verbose)
print(" - performs lite check recent-txn-id with meta-pages (not a "
"monopolistic mode)\n");
problems_meta += check_meta_head(false);
} else if (verbose) {
print(" - skip check recent-txn-id with meta-pages (monopolistic or "
- "write-lock mode only)\n");
+ "read-write mode only)\n");
}
if (!dont_traversal) {
@@ -1079,7 +1079,7 @@ int main(int argc, char *argv[]) {
}
if (problems_maindb == 0 && problems_freedb == 0) {
- if (!dont_traversal && (exclusive || locktxn)) {
+ if (!dont_traversal && (exclusive || (envflags & MDBX_RDONLY) == 0)) {
if (walk.pgcount != lastpgno - freedb_pages) {
error("used pages mismatch (%" PRIu64 " != %" PRIu64 ")\n",
walk.pgcount, lastpgno - freedb_pages);
@@ -1090,7 +1090,7 @@ int main(int argc, char *argv[]) {
}
} else if (verbose) {
print(" - skip check used and gc pages (btree-traversal with "
- "monopolistic or write-lock mode only)\n");
+ "monopolistic or read-write mode only)\n");
}
if (!process_db(MAIN_DBI, NULL, handle_maindb, true)) {
@@ -1102,8 +1102,8 @@ int main(int argc, char *argv[]) {
bailout:
if (txn)
mdbx_txn_abort(txn);
- if (locktxn)
- mdbx_txn_abort(locktxn);
+ if (locked)
+ mdbx_txn_unlock(env);
if (env)
mdbx_env_close(env);
fflush(NULL);
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/version.c b/plugins/Dbx_mdbx/src/libmdbx/src/version.c
index 3b2ffdba76..c325be5878 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/version.c
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/version.c
@@ -18,8 +18,8 @@
#error "API version mismatch!"
#endif
-#define MDBX_VERSION_RELEASE 0
-#define MDBX_VERSION_REVISION 0
+#define MDBX_VERSION_RELEASE 2
+#define MDBX_VERSION_REVISION 1
/*LIBMDBX_EXPORTS*/ const mdbx_version_info mdbx_version = {
MDBX_VERSION_MAJOR,
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/base.h b/plugins/Dbx_mdbx/src/libmdbx/test/base.h
index 63554e730d..f0c6043220 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/base.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/base.h
@@ -76,14 +76,6 @@
#include <unordered_set>
#include <vector>
-#ifdef _MSC_VER
-#include <intrin.h>
-#endif
-
-#if defined(__i386__) || defined(__x86_64__)
-#include <x86intrin.h>
-#endif
-
#include "../mdbx.h"
#include "../src/defs.h"
#include "../src/osal.h"
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/config.cc b/plugins/Dbx_mdbx/src/libmdbx/test/config.cc
index 2b9c6e5a0c..cbff68ce4e 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/config.cc
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/config.cc
@@ -278,8 +278,6 @@ void dump(const char *title) {
logging::local_suffix indent(title);
for (auto i = global::actors.begin(); i != global::actors.end(); ++i) {
- const std::string tableid =
- i->space_id ? "MAINDB" : ("SUB#" + std::to_string(i->space_id));
log_info("#%u, testcase %s, space_id/table %u\n", i->actor_id,
testcase2str(i->testcase), i->space_id);
indent.push();
@@ -326,6 +324,11 @@ void dump(const char *title) {
else
log_info("no-delay\n");
+ if (i->params.inject_writefaultn)
+ log_info("inject-writefault on %u ops\n", i->params.inject_writefaultn);
+ else
+ log_info("no-inject-writefault\n");
+
log_info("limits: readers %u, tables %u\n", i->params.max_readers,
i->params.max_tables);
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/config.h b/plugins/Dbx_mdbx/src/libmdbx/test/config.h
index 5efd31100a..86f37fbed8 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/config.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/config.h
@@ -218,6 +218,7 @@ struct actor_params_pod {
unsigned delaystart;
unsigned waitfor_nops;
+ unsigned inject_writefaultn;
unsigned max_readers;
unsigned max_tables;
@@ -244,7 +245,7 @@ void dump(const char *title = "config-dump: ");
struct actor_params : public config::actor_params_pod {
std::string pathname_log;
std::string pathname_db;
- void set_defaults(void);
+ void set_defaults(const std::string &tmpdir);
};
struct actor_config : public config::actor_config_pod {
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/log.cc b/plugins/Dbx_mdbx/src/libmdbx/test/log.cc
index 8697effd8f..6ad33ced35 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/log.cc
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/log.cc
@@ -285,3 +285,5 @@ void log_trouble(const char *where, const char *what, int errnum) {
bool log_enabled(const logging::loglevel priority) {
return (priority >= logging::level);
}
+
+void log_flush(void) { fflushall(); }
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/log.h b/plugins/Dbx_mdbx/src/libmdbx/test/log.h
index c321f3ce91..81eaf2ca91 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/log.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/log.h
@@ -81,6 +81,7 @@ void __printf_args(1, 2) log_warning(const char *msg, ...);
void __printf_args(1, 2) log_error(const char *msg, ...);
void log_trouble(const char *where, const char *what, int errnum);
+void log_flush(void);
bool log_enabled(const logging::loglevel priority);
#ifdef _DEBUG
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/main.cc b/plugins/Dbx_mdbx/src/libmdbx/test/main.cc
index adf60aae62..98461a245d 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/main.cc
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/main.cc
@@ -22,21 +22,16 @@ void __noreturn usage(void) {
//-----------------------------------------------------------------------------
-void actor_params::set_defaults(void) {
+void actor_params::set_defaults(const std::string &tmpdir) {
pathname_log = "";
loglevel =
#ifdef NDEBUG
- logging::notice;
+ logging::info;
#else
logging::trace;
#endif
- pathname_db =
-#ifdef __linux__
- "/dev/shm/test_tmpdb.mdbx";
-#else
- "test_tmpdb.mdbx";
-#endif
+ pathname_db = tmpdir + "mdbx-test.db";
mode_flags = MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NORDAHEAD |
MDBX_NOMEMINIT | MDBX_COALESCE | MDBX_LIFORECLAIM;
table_flags = MDBX_DUPSORT;
@@ -65,6 +60,7 @@ void actor_params::set_defaults(void) {
delaystart = 0;
waitfor_nops = 0;
+ inject_writefaultn = 0;
drop_table = false;
@@ -135,7 +131,7 @@ int main(int argc, char *const argv[]) {
: EXIT_FAILURE;
actor_params params;
- params.set_defaults();
+ params.set_defaults(osal_tempdir());
global::config::dump_config = true;
logging::setup((logging::loglevel)params.loglevel, "main");
unsigned last_space_id = 0;
@@ -219,6 +215,9 @@ int main(int argc, char *const argv[]) {
if (config::parse_option(argc, argv, narg, "wait4ops", params.waitfor_nops,
config::decimal))
continue;
+ if (config::parse_option(argc, argv, narg, "inject-writefault",
+ params.inject_writefaultn, config::decimal))
+ continue;
if (config::parse_option(argc, argv, narg, "drop", params.drop_table))
continue;
if (config::parse_option(argc, argv, narg, "dump-config",
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc b/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc
index 7625e0f419..8132e267ef 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc
@@ -272,3 +272,22 @@ void osal_udelay(unsigned us) {
}
bool osal_istty(int fd) { return isatty(fd) == 1; }
+
+std::string osal_tempdir(void) {
+ const char *tempdir = getenv("TMPDIR");
+ if (!tempdir)
+ tempdir = getenv("TMP");
+ if (!tempdir)
+ tempdir = getenv("TEMPDIR");
+ if (!tempdir)
+ tempdir = getenv("TEMP");
+ if (tempdir) {
+ std::string dir(tempdir);
+ if (!dir.empty() && dir.at(dir.length() - 1) != '/')
+ dir.append("/");
+ return dir;
+ }
+ if (access("/dev/shm/", R_OK | W_OK | X_OK) == 0)
+ return "/dev/shm/";
+ return "";
+}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc b/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc
index b1a8928cbb..5d2e51a66d 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc
@@ -305,3 +305,9 @@ void osal_udelay(unsigned us) {
}
bool osal_istty(int fd) { return _isatty(fd) != 0; }
+
+std::string osal_tempdir(void) {
+ char buf[MAX_PATH + 1];
+ DWORD len = GetTempPathA(sizeof(buf), buf);
+ return std::string(buf, len);
+}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/osal.h b/plugins/Dbx_mdbx/src/libmdbx/test/osal.h
index f75aae3831..c27282a656 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/osal.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/osal.h
@@ -31,6 +31,7 @@ int osal_delay(unsigned seconds);
void osal_udelay(unsigned us);
void osal_yield(void);
bool osal_istty(int fd);
+std::string osal_tempdir(void);
#ifdef _MSC_VER
#ifndef STDIN_FILENO
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/test.cc b/plugins/Dbx_mdbx/src/libmdbx/test/test.cc
index 8700d74add..02986b3d1a 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/test.cc
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/test.cc
@@ -123,7 +123,7 @@ void testcase::db_prepare() {
if (config.params.loglevel <= logging::verbose)
mdbx_dbg_opts |= MDBX_DBG_PRINT;
int rc = mdbx_setup_debug(mdbx_dbg_opts, mdbx_logger);
- log_info("set mdbx debug-opts: 0x%02x", rc);
+ log_trace("set mdbx debug-opts: 0x%02x", rc);
MDBX_env *env = nullptr;
rc = mdbx_env_create(&env);
@@ -204,6 +204,7 @@ void testcase::txn_end(bool abort) {
if (unlikely(rc != MDBX_SUCCESS))
failure_perror("mdbx_txn_abort()", rc);
} else {
+ txn_inject_writefault(txn);
int rc = mdbx_txn_commit(txn);
if (unlikely(rc != MDBX_SUCCESS))
failure_perror("mdbx_txn_commit()", rc);
@@ -218,6 +219,27 @@ void testcase::txn_restart(bool abort, bool readonly, unsigned flags) {
txn_begin(readonly, flags);
}
+void testcase::txn_inject_writefault(void) {
+ if (txn_guard)
+ txn_inject_writefault(txn_guard.get());
+}
+
+void testcase::txn_inject_writefault(MDBX_txn *txn) {
+ if (config.params.inject_writefaultn && txn) {
+ if (config.params.inject_writefaultn <= nops_completed &&
+ (mdbx_txn_flags(txn) & MDBX_RDONLY) == 0) {
+ log_info("== txn_inject_writefault(): got %u nops or more, inject FAULT",
+ config.params.inject_writefaultn);
+ log_flush();
+#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS)
+ TerminateProcess(GetCurrentProcess(), 42);
+#else
+ raise(SIGKILL);
+#endif
+ }
+ }
+}
+
bool testcase::wait4start() {
if (config.wait4id) {
log_trace(">> wait4start(%u)", config.wait4id);
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/test.h b/plugins/Dbx_mdbx/src/libmdbx/test/test.h
index 4158aba457..ef1c4caa47 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/test.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/test.h
@@ -107,6 +107,8 @@ protected:
void txn_begin(bool readonly, unsigned flags = 0);
void txn_end(bool abort);
void txn_restart(bool abort, bool readonly, unsigned flags = 0);
+ void txn_inject_writefault(void);
+ void txn_inject_writefault(MDBX_txn *txn);
void fetch_canary();
void update_canary(uint64_t increment);
void kick_progress(bool active) const;
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc b/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc
index 96866f61b7..0855c7eef3 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc
@@ -14,44 +14,10 @@
#include "test.h"
#include <float.h>
-#ifdef HAVE_IEEE754_H
+#if defined(HAVE_IEEE754_H) || __has_include(<ieee754.h>)
#include <ieee754.h>
#endif
-/* Compiler's includes for builtins/intrinsics */
-#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
-#include <intrin.h>
-#elif __GNUC_PREREQ(4, 4) || defined(__clang__)
-#if defined(__ia32__) || defined(__e2k__)
-#include <x86intrin.h>
-#endif /* __ia32__ */
-#if defined(__ia32__)
-#include <cpuid.h>
-#endif /* __ia32__ */
-#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun)
-#include <mbarrier.h>
-#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \
- (defined(HP_IA64) || defined(__ia64))
-#include <machine/sys/inline.h>
-#elif defined(__IBMC__) && defined(__powerpc)
-#include <atomic.h>
-#elif defined(_AIX)
-#include <builtins.h>
-#include <sys/atomic_op.h>
-#elif (defined(__osf__) && defined(__DECC)) || defined(__alpha)
-#include <c_asm.h>
-#include <machine/builtins.h>
-#elif defined(__MWERKS__)
-/* CodeWarrior - troubles ? */
-#pragma gcc_extensions
-#elif defined(__SNC__)
-/* Sony PS3 - troubles ? */
-#elif defined(__hppa__) || defined(__hppa)
-#include <machine/inline.h>
-#else
-#error Unsupported C compiler, please use GNU C 4.4 or newer
-#endif /* Compiler */
-
std::string format(const char *fmt, ...) {
va_list ap, ones;
va_start(ap, fmt);
@@ -127,8 +93,22 @@ bool hex2data(const char *hex_begin, const char *hex_end, void *ptr,
//-----------------------------------------------------------------------------
+/* TODO: replace my 'libmera' fomr t1ha. */
uint64_t entropy_ticks(void) {
+#if defined(EMSCRIPTEN)
+ return (uint64_t)emscripten_get_now();
+#endif /* EMSCRIPTEN */
+
+#if defined(__APPLE__) || defined(__MACH__)
+ return mach_absolute_time();
+#endif /* defined(__APPLE__) || defined(__MACH__) */
+
+#if defined(__sun__) || defined(__sun)
+ return gethrtime();
+#endif /* __sun__ */
+
#if defined(__GNUC__) || defined(__clang__)
+
#if defined(__ia64__)
uint64_t ticks;
__asm __volatile("mov %0=ar.itc" : "=r"(ticks));
@@ -145,29 +125,81 @@ uint64_t entropy_ticks(void) {
uint64_t ticks;
__asm __volatile("rpcc %0" : "=r"(ticks));
return ticks;
-#elif defined(__sparc_v9__)
- uint64_t ticks;
- __asm __volatile("rd %%tick, %0" : "=r"(ticks));
- return ticks;
-#elif defined(__powerpc64__) || defined(__ppc64__)
+#elif defined(__sparc__) || defined(__sparc) || defined(__sparc64__) || \
+ defined(__sparc64) || defined(__sparc_v8plus__) || \
+ defined(__sparc_v8plus) || defined(__sparc_v8plusa__) || \
+ defined(__sparc_v8plusa) || defined(__sparc_v9__) || defined(__sparc_v9)
+
+ union {
+ uint64_t u64;
+ struct {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ uint32_t h, l;
+#else
+ uint32_t l, h;
+#endif
+ } u32;
+ } cycles;
+
+#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || \
+ defined(__sparc_v9__) || defined(__sparc_v8plus) || \
+ defined(__sparc_v8plusa) || defined(__sparc_v9)
+
+#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul || \
+ defined(__sparc64__) || defined(__sparc64)
+ __asm __volatile("rd %%tick, %0" : "=r"(cycles.u64));
+#else
+ __asm __volatile("rd %%tick, %1; srlx %1, 32, %0"
+ : "=r"(cycles.u32.h), "=r"(cycles.u32.l));
+#endif /* __sparc64__ */
+
+#else
+ __asm __volatile(".byte 0x83, 0x41, 0x00, 0x00; mov %%g1, %0"
+ : "=r"(cycles.u64)
+ :
+ : "%g1");
+#endif /* __sparc8plus__ || __sparc_v9__ */
+ return cycles.u64;
+
+#elif (defined(__powerpc64__) || defined(__ppc64__) || defined(__ppc64) || \
+ defined(__powerpc64))
uint64_t ticks;
__asm __volatile("mfspr %0, 268" : "=r"(ticks));
return ticks;
-#elif defined(__ppc__) || defined(__powerpc__)
- unsigned tbl, tbu;
-
- /* LY: Here not a problem if a high-part (tbu)
- * would been updated during reading. */
- __asm __volatile("mftb %0" : "=r"(tbl));
- __asm __volatile("mftbu %0" : "=r"(tbu));
-
- return (((uin64_t)tbu0) << 32) | tbl;
+#elif (defined(__powerpc__) || defined(__ppc__) || defined(__powerpc) || \
+ defined(__ppc))
+#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul
+ uint64_t ticks;
+ __asm __volatile("mftb %0" : "=r"(ticks));
+ *now = ticks;
+#else
+ uint64_t ticks;
+ uint32_t low, high_before, high_after;
+ __asm __volatile("mftbu %0; mftb %1; mftbu %2"
+ : "=r"(high_before), "=r"(low), "=r"(high_after));
+ ticks = (uint64_t)high_after << 32;
+ ticks |= low & /* zeroes if high part has changed */
+ ~(high_before - high_after);
+#endif
+#elif defined(__aarch64__) || (defined(__ARM_ARCH) && __ARM_ARCH > 7)
+ uint64_t virtual_timer;
+ __asm __volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer));
+ return virtual_timer;
+#elif defined(__ARM_ARCH) && __ARM_ARCH > 5 && __ARM_ARCH < 8
+ unsigned long pmccntr;
+ __asm __volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
+ return pmccntr;
+#elif defined(__mips__) || defined(__mips) || defined(_R4000)
+ unsigned count;
+ __asm __volatile("rdhwr %0, $2" : "=r"(count));
+ return count;
#endif /* arch selector */
#endif /* __GNUC__ || __clang__ */
-#if defined(__e2k__) || defined(__elbrus__) || defined(_M_IX86) || \
- defined(_M_X64) || defined(__x86_64__) || defined(__i386__)
+#if defined(__e2k__) || defined(__ia32__)
return __rdtsc();
+#elif defined(_M_ARM)
+ return __rdpmccntr64();
#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS)
LARGE_INTEGER PerformanceCount;
if (QueryPerformanceCounter(&PerformanceCount))
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/utils.h b/plugins/Dbx_mdbx/src/libmdbx/test/utils.h
index 176823c60b..5d62909fd5 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/test/utils.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/test/utils.h
@@ -17,33 +17,8 @@
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
!defined(__ORDER_BIG_ENDIAN__)
-#ifndef _MSC_VER
-#include <sys/param.h> /* for endianness */
-#endif
-#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)
-#define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN
-#define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN
-#define __BYTE_ORDER__ __BYTE_ORDER
-#else
-#define __ORDER_LITTLE_ENDIAN__ 1234
-#define __ORDER_BIG_ENDIAN__ 4321
-#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) || \
- defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
- defined(__MIPSEL__) || defined(_MIPSEL) || defined(__MIPSEL) || \
- defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || \
- defined(_M_X64) || defined(i386) || defined(_X86_) || defined(__i386__) || \
- defined(_X86_64_) || defined(_M_ARM) || defined(_M_ARM64) || \
- defined(__e2k__)
-#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
-#elif defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) || defined(__ARMEB__) || \
- defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(__MIPSEB__) || \
- defined(_MIPSEB) || defined(__MIPSEB) || defined(_M_IA64)
-#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
-#else
#error __BYTE_ORDER__ should be defined.
#endif
-#endif
-#endif
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ && \
__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
@@ -274,7 +249,7 @@ static __inline void memory_barrier(void) {
#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */
#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
__mf();
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__ia32__)
_mm_mfence();
#else
#error "Unknown target for Intel Compiler, please report to us."
@@ -293,8 +268,7 @@ static __inline void memory_barrier(void) {
}
static __inline void cpu_relax() {
-#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || \
- defined(_M_X64)
+#if defined(__ia32__)
_mm_pause();
#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || \
defined(YieldProcessor)