Compare commits

..

71 Commits

Author SHA1 Message Date
Leo Yuriev
e1e17fd6a4 mdbx: Merge branch 'master' into stable/0.1 2018-06-14 13:54:01 +03:00
Leo Yuriev
b6e605b8da mdbx: bump version to v0.1.5 2018-06-14 13:53:05 +03:00
Leo Yuriev
2f983b281d mdbx: drop MDBX_DEVEL.
Change-Id: I5fc1a240e7909b8ecaf2ef19a83a9e59ea5609ba
2018-06-13 11:37:56 +03:00
Leo Yuriev
efdcbd8c35 mdbx: disable non-blocking DB-close under Windows.
Change-Id: If6579467132439b6b627e756f67f6bd35fed8b4f
2018-06-13 02:46:18 +03:00
Leo Yuriev
634efbe34b mdbx: don't block close_env() if other write-txn running.
Change-Id: I1d19afcc245578681b8bc3ee3966ac38bc596ec4
2018-06-12 13:18:17 +03:00
Leo Yuriev
17d3e7190c mdbx: Merge branch 'master' into stable/0.1
Change-Id: I7460e6a8b42c9bbeadfdf20d326c31c1d4a98969
2018-06-01 16:42:48 +03:00
Leo Yuriev
fdc248384e mdbx: skip meta if usedbytes beyond oef.
Change-Id: I1e95136bce7169b7ed612f9746d0cdec43caca14
2018-06-01 13:27:20 +03:00
Leo Yuriev
38369bd24b mdbx: force steady-sync when shrinking DB (fix corruption bug).
Change-Id: I636ee2ad04f28d4038d74bdf2c7061ab885f4b82
2018-06-01 13:15:21 +03:00
Leo Yuriev
22d8b0b2e1 mdbx: Merge branch 'master' into stable/0.1
Change-Id: Idd1af2c07b48bfb1f335aa31a52bed4bd68514ac
2018-05-29 03:14:07 +03:00
dartraiden
515adb674b mdbx: fix typos and punctuation 2018-05-29 03:00:48 +03:00
Leo Yuriev
f99df1ca35 mdbx: update .gitignore
Change-Id: I880b5ccca285394845300a600e2722a915f37cfe
2018-05-28 21:34:45 +03:00
Leo Yuriev
ab4c9c9db0 mdbx: return MDBX_CORRUPTED instead of crash if MDBX_DUPSORT mismatch.
Change-Id: I439a3c859dbfcfbe33a3db077c3e8200a1417c31
2018-05-28 20:04:48 +03:00
Leo Yuriev
b68ed8600c mdbx: more refine/fix README.
Change-Id: Icd26630d9d907fc5cdfd08b39a5226e78e982ffb
2018-05-25 00:00:58 +03:00
Leo Yuriev
9384d0efa6 mdbx: Merge branch 'master' into stable/0.1
Change-Id: I3318b330e4aa5fd0db4642af6ef81e69814f0cc5
2018-05-22 12:03:57 +03:00
Leo Yuriev
4214436d4b mdbx: fix/refine README.
Change-Id: I33817021ef5c74f0fd074d5ca6b61fd993e3d9f4
2018-05-22 12:01:35 +03:00
Leo Yuriev
ffafd5be10 mdbx: disable warning #5045 for MSVC (minor). 2018-05-21 16:36:41 +03:00
Leo Yuriev
e86bd88751 mdbx: disable warning #5045 for MSVC (minor). 2018-05-21 16:31:36 +03:00
Leo Yuriev
eb4090c534 mdbx: update Project Status. 2018-05-10 14:05:48 +03:00
Leo Yuriev
bea1349dd4 mdbx: bump internal version info to v0.1.4 2018-05-04 13:21:18 +03:00
Leo Yuriev
d0ddc8569b mdbx-windows: fix lck_reader_alive_check().
Change-Id: Icbc54d9b3003f70bba573a3807c5161380339460
2018-05-04 02:17:21 +03:00
Leo Yuriev
f1edd1579a mdbx: fix wrong freeDB search.
Avoid search freeDB while tree is updating.

This resolves https://github.com/leo-yuriev/libmdbx/issues/31
Bug was inherited from LMDB.

Change-Id: I0b12f8d9b88bca5aa26ca27db81df9b72c6a19b7
2018-04-25 03:01:12 +03:00
Leo Yuriev
47cc2b1c10 mdbx-cmake: fix version inside CMakeLists.txt
This resolves https://github.com/leo-yuriev/libmdbx/issues/32
2018-04-18 12:58:56 +03:00
Leo Yuriev
d127c28e83 mdbx-windows: fix srw-release if rdt-lock failed (minor/paranoia). 2018-04-12 00:56:58 +03:00
Leo Yuriev
159d676429 mdbx: fix typo in mdbx_chk output. 2018-04-10 21:12:41 +03:00
Leo Yuriev
f4a9018690 mdbx: bump internal version info to v0.1.3
Change-Id: I7db311c812d531f6628101715f6658005db3ea24
2018-04-03 20:37:07 +03:00
Leo Yuriev
f8eb423d36 mdbx-make: remote '-O3' for Elbrus (done by __hot attributes).
Change-Id: I6a3afeaf1ddf6d231941aae023dff89046bc4349
2018-04-03 20:06:45 +03:00
Leo Yuriev
797ae9d1db mdbx: minor fix debug-output for mdbx_thread_key_create().
Change-Id: I718130cf2385b6221187cbcdeedd9d48d05289bb
2018-04-03 20:04:10 +03:00
Leo Yuriev
f08c7ccac0 mdbx-make: rename mdbx_test and link with dso-library.
Change-Id: I39a04f82bc31c0865a8d02379a596048518205cd
2018-04-03 19:28:12 +03:00
Leo Yuriev
864be54f01 mdbx: fix/rework rthc counting.
Change-Id: I97fd5bd6dc1a46658138d82db10e937c9595d81f
2018-04-03 19:28:12 +03:00
Leo Yuriev
571b50622e mdbx: restore workaround for glibc's bug #21031.
Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=21031

Change-Id: I6cf9e037cc2fc298096b78ec96773f19478ed5c0
2018-04-03 17:44:18 +03:00
Leo Yuriev
36a86bbc6e mdbx: fix cursor tracking inside mdbx_rebalance(). 2018-03-26 20:20:14 +03:00
Leo Yuriev
ae708aab13 mdbx: update README.md 2018-03-26 14:17:35 +03:00
Leo Yuriev
02fc5fe158 mdbx: update internal version info. 2018-03-23 17:23:28 +03:00
Leo Yuriev
45f159ddd3 mdbx: mdbx_cursor_put(MDBX_APPEND+MDBX_NOOVERWRITE) should return MDBX_KEYEXIST instead of MDBX_EKEYMISMATCH.
When MDBX_APPEND is used the ordering of keys is important.
Therefore MDBX_EKEYMISMATCH should me returned when given key <= last.

On the other hand, if MDBX_NOOVERWRITE is also used
then the MDBX_KEYEXIST should be returned, but not MDBX_EKEYMISMATCH.
2018-03-23 17:21:27 +03:00
Leo Yuriev
6758348046 mdbx: import intrin-includes from t1ha. 2018-03-22 21:11:26 +03:00
Leo Yuriev
09ab6dd777 mdbx-make: add cross-compile targets for testing. 2018-03-22 21:11:26 +03:00
Leo Yuriev
61a2c56784 mdbx: fix/rework cache-line alignment. 2018-03-22 21:11:26 +03:00
Leo Yuriev
6a074cb85a mdbx: fix unaligned access to mp_ptrs[] on fake-page.
Based on http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=commitdiff;h=e77918a903d980ff789b7e32f71725481e870510
2018-03-22 21:11:26 +03:00
Leo Yuriev
dbc87a8a5e mdbx: refine MDBX_CACHE_IS_COHERENT. 2018-03-22 20:38:20 +03:00
Leo Yuriev
3a42b76fb8 mdbx-tests: fix entropy_ticks() for multiarch. 2018-03-22 20:38:18 +03:00
Leo Yuriev
c52a57dac5 mdbx: fix for MIPS cacheflush(). 2018-03-22 20:37:50 +03:00
Leo Yuriev
5ce40269b3 mdbx: fix gcc warning (minor). 2018-03-22 20:37:50 +03:00
Leo Yuriev
3d320253cd mdbx-tests: drop duplicate sysdep-includes. 2018-03-21 22:19:17 +03:00
Leo Yuriev
86274513f9 mdbx: more __has_include(). 2018-03-21 22:19:17 +03:00
Leo Yuriev
f5571e4027 mdbx: import byte-order macros from t1ha. 2018-03-21 22:19:17 +03:00
Leo Yuriev
62ae928b40 mdbx: add neutral __ia32__ and __amd64__ marcos. 2018-03-21 22:18:57 +03:00
Leo Yuriev
a282965aa0 mdbx: add check __ALIGNED__ for UNALIGNED_OK macro. 2018-03-21 21:10:57 +03:00
Leo Yuriev
3c5cc40c77 mdbx: fix README typos. 2018-03-21 14:13:54 +03:00
Leo Yuriev
475da5bcfe mdbx: make mdbx_txn_lock() and mdbx_txn_unlock() exportable for mdbx_chk. 2018-03-20 22:19:32 +03:00
Leo Yuriev
679fb56787 mdbx: lookup suitable txnid for rollback to avoid meta-pages clashes. 2018-03-20 22:16:15 +03:00
Leo Yuriev
dd6cb30820 mdbx-chk: directly use mdbx_txn_lock() for write/recovery mode. 2018-03-20 21:37:42 +03:00
Leo Yuriev
8d748a845b mdbx-tests: fix default value for inject_writefaultn. 2018-03-19 21:26:14 +03:00
Leo Yuriev
5872174db6 mdbx-tests: refine temp-dir for unix. 2018-03-19 21:01:05 +03:00
Leo Yuriev
52283d8c44 mdbx-tests: unify testdb name. 2018-03-19 20:50:30 +03:00
Leo Yuriev
838856f688 mdbx-tests: add osal_tempdir(). 2018-03-19 20:50:30 +03:00
Leo Yuriev
0aa07cc09b mdbx-tests: drop unused tableid variable (minor). 2018-03-19 20:20:47 +03:00
Leo Yuriev
e8dd15088a mdbx: add __ARM_FEATURE_UNALIGNED __e2k__ for UNALIGNED_OK. 2018-03-19 19:59:00 +03:00
Leo Yuriev
d0e1c02a8a mdbx-chk: rework/fix read-write mode. 2018-03-19 18:08:45 +03:00
Leo Yuriev
b2213c86fe mdbx-build: add check-fault target. 2018-03-19 18:08:45 +03:00
Leo Yuriev
9ccd551ebc mdbx-tests: minor refine log-levels. 2018-03-19 18:08:45 +03:00
Leo Yuriev
a2ec7f2be1 mdbx: add mdbx_txn_flags(). 2018-03-19 18:08:45 +03:00
Leo Yuriev
d63c2484fe mdbx-tests: add --inject-writefault=N option. 2018-03-19 18:08:45 +03:00
Leo Yuriev
638ed91e3e mdbx-tests: add log_flush(). 2018-03-19 16:51:10 +03:00
Leo Yuriev
64613c9061 mdbx: fix minor memleak (Coverity). 2018-03-19 16:16:31 +03:00
Leo Yuriev
c05d179035 mdbx: temporary workaround for Elbrus's libc bug.
https://bugs.mcst.ru/bugzilla/show_bug.cgi?id=2820
2018-03-19 15:05:56 +03:00
Leo Yuriev
195b53374e mdbx: fix #pragma pack(pop) balance.
Thanks to <Sergey.V.Barannikov@mcst.ru>.
2018-03-14 16:05:43 +03:00
Leo Yuriev
f521b6615e mdbx: fix #endif's comment (cosmetics). 2018-03-14 15:32:32 +03:00
Leo Yuriev
9bbc62f5a0 mdbx: refine internal warnings control. 2018-03-14 15:16:49 +03:00
Leo Yuriev
8c96b1e73b mdbx: fix missing MDBX_DEVEL=0. 2018-03-14 15:07:16 +03:00
Leo Yuriev
436b4870e8 mdbx: -O3 by default for Elbrus. 2018-03-14 15:04:07 +03:00
Leo Yuriev
483c4abb3f mdbx: remove Elbrus's alignment_reduction_ignored workaround. 2018-03-14 14:57:46 +03:00
30 changed files with 1282 additions and 618 deletions

3
.gitignore vendored
View File

@@ -16,6 +16,7 @@ Win32/
build-*
cmake-build-*
core
example
libmdbx.creator.user
mdbx-dll.VC.VC.opendb
mdbx-dll.VC.db
@@ -25,7 +26,7 @@ mdbx_copy
mdbx_dump
mdbx_load
mdbx_stat
ootest/test
mdbx_test
test.log
test/test.vcxproj.user
test/tmp.db

View File

@@ -1,17 +1,22 @@
cmake_minimum_required(VERSION 2.8.7)
set(TARGET mdbx)
project(${TARGET})
# FIXME/TODO: Same as https://github.com/leo-yuriev/libfpta
set(MDBX_VERSION_MAJOR 0)
set(MDBX_VERSION_MINOR 0)
set(MDBX_VERSION_PATCH 0)
set(MDBX_VERSION_STRING ${MDBX_VERSION_MAJOR}.${MDBX_VERSION_MINOR}.${MDBX_VERSION_PATCH})
message(WARNING "
***************************************************************
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.
***************************************************************
")
add_definitions(-DMDBX_VERSION_MAJOR=${MDBX_VERSION_MAJOR})
add_definitions(-DMDBX_VERSION_MINOR=${MDBX_VERSION_MINOR})
add_definitions(-DMDBX_VERSION_PATCH=${MDBX_VERSION_PATCH})
set(MDBX_VERSION_MAJOR 0)
set(MDBX_VERSION_MINOR 1)
set(MDBX_VERSION_RELEASE 3)
set(MDBX_VERSION_REVISION 1)
set(MDBX_VERSION_STRING ${MDBX_VERSION_MAJOR}.${MDBX_VERSION_MINOR}.${MDBX_VERSION_RELEASE})
enable_language(C)
enable_language(CXX)
@@ -34,7 +39,6 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-constant-logical-operand")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections")

View File

@@ -23,23 +23,17 @@ suffix ?=
CC ?= gcc
CXX ?= g++
XCFLAGS ?= -DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1
CFLAGS ?= -O2 -g3 -Wall -Werror -Wextra -ffunction-sections -fPIC -fvisibility=hidden
XCFLAGS ?= -DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1
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
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 ?= -pthread -lrt
# LY: just for benchmarking
IOARENA ?= $(shell \
@@ -65,7 +59,7 @@ TEST_OBJ := $(patsubst %.cc,%.o,$(TEST_SRC))
.PHONY: mdbx all install clean check coverage
all: $(LIBRARIES) $(TOOLS) test/test example
all: $(LIBRARIES) $(TOOLS) mdbx_test example
mdbx: libmdbx.a libmdbx.so
@@ -85,10 +79,16 @@ install: $(LIBRARIES) $(TOOLS) $(HEADERS)
&& cp -t $(SANDBOX)$(mandir)/man1 $(MANPAGES)
clean:
rm -rf $(TOOLS) test/test @* *.[ao] *.[ls]o *~ tmp.db/* *.gcov *.log *.err src/*.o test/*.o
rm -rf $(TOOLS) mdbx_test @* *.[ao] *.[ls]o *~ tmp.db/* *.gcov *.log *.err src/*.o test/*.o
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)
rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_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; ./mdbx_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; ./mdbx_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
@@ -111,10 +111,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 $@
mdbx_test: $(TEST_OBJ) libmdbx.so
$(CXX) $(CXXFLAGS) $(TEST_OBJ) -Wl,-rpath . -L . -l mdbx $(EXE_LDFLAGS) -o $@
###############################################################################
ifneq ($(wildcard $(IOARENA)),)
@@ -163,6 +165,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 +182,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

View File

@@ -12,19 +12,30 @@ 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 Continuous Integration).
## Содержание
- [Обзор](#Обзор)
- [Сравнение с другими СУБД](#Сравнение-с-другими-СУБД)
- [История & Acknowledgements](#История)
- [История & Acknowledgments](#История)
- [Основные свойства](#Основные-свойства)
- [Сравнение производительности](#Сравнение-производительности)
- [Интегральная производительность](#Интегральная-производительность)
@@ -43,7 +54,7 @@ features, including the database properties.
_libmdbx_ - это встраиваемый key-value движок хранения со специфическим
набором свойств и возможностей, ориентированный на создание уникальных
легковесных решений с предельной производительностью.
легковесных решений с предельной производительностью под Linux и Windows.
_libmdbx_ позволяет множеству процессов совместно читать и обновлять
несколько key-value таблиц с соблюдением [ACID](https://ru.wikipedia.org/wiki/ACID),
@@ -51,8 +62,8 @@ _libmdbx_ позволяет множеству процессов совмес
_libmdbx_ обеспечивает
[serializability](https://en.wikipedia.org/wiki/Serializability)
изменений и согласованность данных после аварий. При этом транзакции
изменяющие данные никак не мешают операциям чтения и выполняются строго
изменений и согласованность данных после аварий. При этом транзакции,
изменяющие данные, никак не мешают операциям чтения и выполняются строго
последовательно с использованием единственного
[мьютекса](https://en.wikipedia.org/wiki/Mutual_exclusion).
@@ -90,7 +101,7 @@ Tables](https://github.com/leo-yuriev/libfpta), aka ["Позитивные
Technologies](https://www.ptsecurity.ru).
#### Acknowledgements
#### Acknowledgments
Howard Chu (Symas Corporation) - the author of LMDB,
from which originated the MDBX in 2015.
@@ -102,7 +113,7 @@ which was used for begin development of LMDB.
Основные свойства
=================
_libmdbx_ наследует все ключевые возможности и особенности от
_libmdbx_ наследует все ключевые возможности и особенности
своего прародителя [LMDB](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database),
но с устранением ряда описываемых далее проблем и архитектурных недочетов.
@@ -118,7 +129,7 @@ _libmdbx_ наследует все ключевые возможности и
[MVCC](https://ru.wikipedia.org/wiki/MVCC) и
[COW](https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%B8_%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8).
Изменения строго последовательны и не блокируются чтением,
конфликты между транзакциями не возможны.
конфликты между транзакциями невозможны.
При этом гарантируется чтение только зафиксированных данных, см [relaxing serializability](https://en.wikipedia.org/wiki/Serializability).
4. Чтение и поиск [без блокировок](https://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B0%D1%8F_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F),
@@ -182,7 +193,7 @@ github](https://github.com/pmwkaa/ioarena/tree/HL%2B%2B2015).
1. Такое сравнение не совсем правомочно, его следует делать с движками
ориентированными на хранение данных в памяти ([Tarantool](https://tarantool.io/), [Redis](https://redis.io/)).
2. Превосходство libmdbx становится еще более подавляющем, что мешает
2. Превосходство libmdbx становится еще более подавляющим, что мешает
восприятию информации.
![Comparison #1: Integral Performance](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-1.png)
@@ -206,7 +217,7 @@ github](https://github.com/pmwkaa/ioarena/tree/HL%2B%2B2015).
- Логарифмическая шкала справа и желтые интервальные отрезки
соответствуют времени выполнения транзакций. При этом каждый отрезок
показывает минимальное и максимальное время затраченное на выполнение
показывает минимальное и максимальное время, затраченное на выполнение
транзакций, а крестиком отмечено среднеквадратичное значение.
Выполняется **10.000 транзакций в режиме синхронной фиксации данных** на
@@ -232,7 +243,7 @@ github](https://github.com/pmwkaa/ioarena/tree/HL%2B%2B2015).
- Логарифмическая шкала справа и желтые интервальные отрезки
соответствуют времени выполнения транзакций. При этом каждый отрезок
показывает минимальное и максимальное время затраченное на выполнение
показывает минимальное и максимальное время, затраченное на выполнение
транзакций, а крестиком отмечено среднеквадратичное значение.
Выполняется **100.000 транзакций в режиме отложенной фиксации данных**
@@ -263,7 +274,7 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
- Логарифмическая шкала справа и желтые интервальные отрезки
соответствуют времени выполнения транзакций. При этом каждый отрезок
показывает минимальное и максимальное время затраченное на выполнение
показывает минимальное и максимальное время, затраченное на выполнение
транзакций, а крестиком отмечено среднеквадратичное значение.
Выполняется **1.000.000 транзакций в режиме асинхронной фиксации
@@ -272,7 +283,7 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
консистентны на момент завершения одной из транзакций, но допускается
потеря изменений из значительного количества последних транзакций. Во
всех движках при этом включался режим предполагающий минимальную
нагрузку на диск по-записи, и соответственно минимальную гарантию
нагрузку на диск по записи, и соответственно минимальную гарантию
сохранности данных. В _libmdbx_ при этом используется режим асинхронной
записи измененных страниц на диск посредством ядра ОС и системного
вызова [msync(MS_ASYNC)](https://linux.die.net/man/2/msync).
@@ -337,7 +348,7 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
> _libmdbx_ фиксация транзакции также требует от 2 IOPS. Однако, в БД с
> журналом кол-во IOPS будет меняться в зависимости от файловой системы,
> но не от кол-ва записей или их объема. Тогда как в _libmdbx_ кол-во
> будет расти логарифмически от кол-во записей/строк в БД (по высоте
> будет расти логарифмически от кол-ва записей/строк в БД (по высоте
> b+tree).
3. [COW](https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%B8_%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8)
@@ -353,7 +364,7 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
> значительного копирования данных в памяти и массы других затратных операций.
> Поэтому обусловленное этим недостатком падение производительности становится
> заметным только при отказе от фиксации изменений на диске.
> Соответственно, корректнее сказать что _libmdbx_ позволяет
> Соответственно, корректнее сказать, что _libmdbx_ позволяет
> получить персистентность ценой минимального падения производительности.
> Если же нет необходимости оперативно сохранять данные, то логичнее
> использовать `std::map`.
@@ -446,7 +457,7 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
Однако, при аварийном отключении питания или сбое в ядре ОС, на диске
может быть сохранена только часть измененных страниц БД. При этом с большой
вероятностью может оказаться так, что будут сохранены мета-страницы со
вероятностью может оказаться, что будут сохранены мета-страницы со
ссылками на страницы с новыми версиями данных, но не сами новые данные.
В этом случае БД будет безвозвратна разрушена, даже если до аварии
производилась полная синхронизация данных (посредством
@@ -460,11 +471,11 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
с переносом изменений после фиксации данных.
* При завершении транзакций, в зависимости от состояния
синхронности данных между диском и оперативной память,
синхронности данных между диском и оперативной памятью,
_libmdbx_ помечает точки фиксации либо как сильные (strong),
либо как слабые (weak). Так например, в режиме
`WRITEMAP+MAPSYNC` завершаемые транзакции помечаются как
слабые, а при явной синхронизации данных как сильные.
слабые, а при явной синхронизации данных - как сильные.
* В _libmdbx_ поддерживается не две, а три отдельные мета-страницы.
Это позволяет выполнять фиксацию транзакций с формированием как
@@ -478,20 +489,20 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
сильной фиксации. Этим обеспечивается гарантия сохранности БД.
Такая гарантия надежности не дается бесплатно. Для
сохранности данных, страницы формирующие крайний снимок с
сохранности данных, страницы, формирующие крайний снимок с
сильной фиксацией, не должны повторно использоваться
(перезаписываться) до формирования следующей сильной точки
фиксации. Таким образом, крайняя точка фиксации создает
описанный выше эффект "долгого чтения". Разница же здесь в том,
что при исчерпании свободных страниц ситуация будет
автоматически исправлена, посредством записи изменений на диск
и формированием новой сильной точки фиксации.
и формирования новой сильной точки фиксации.
Таким образом, в режиме безопасной асинхронной фиксации _libmdbx_ будет
всегда использовать новые страницы до исчерпания места в БД или до явного
формирования сильной точки фиксации посредством `mdbx_env_sync()`.
При этом суммарный трафик записи на диск будет примерно такой-же,
как если бы отдельно фиксировалась каждая транзакций.
При этом суммарный трафик записи на диск будет примерно такой же,
как если бы отдельно фиксировалась каждая транзакция.
В текущей версии _libmdbx_ вам предоставляется выбор между безопасным
режимом (по умолчанию) асинхронной фиксации, и режимом `UTTERLY_NOSYNC` когда
@@ -524,9 +535,9 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
Посредством `mdbx_env_set_oomfunc()` может быть установлен
внешний обработчик (callback), который будет вызван при
исчерпания свободных страниц из-за долгой операцией чтения.
исчерпании свободных страниц из-за долгой операцией чтения.
Обработчику будет передан PID и pthread_id виновника.
В свою очередь обработчик может предпринять одно из действий:
В свою очередь обработчик может предпринять одно из действий:
* нейтрализовать виновника (отправить сигнал kill #9), если
долгое чтение выполняется сторонним процессом;
@@ -534,7 +545,7 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
* отменить или перезапустить проблемную операцию чтения, если
операция выполняется одним из потоков текущего процесса;
* подождать некоторое время, в расчете что проблемная операция
* подождать некоторое время, в расчете на то, что проблемная операция
чтения будет штатно завершена;
* прервать текущую операцию изменения данных с возвратом кода
@@ -601,7 +612,7 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
19. Возможность посредством `mdbx_is_dirty()` определить находятся ли
некоторый ключ или данные в "грязной" странице БД. Таким образом,
избегая лишнего копирования данных перед выполнением модифицирующих
операций (значения в размещенные "грязных" страницах могут быть
операций (значения, размещенные в "грязных" страницах, могут быть
перезаписаны при изменениях, иначе они будут неизменны).
20. Корректное обновление текущей записи, в том числе сортированного
@@ -621,7 +632,7 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
>
> - обращение к уже освобожденной памяти;
> - попытки повторного освобождения памяти;
> - memory corruption and segfaults.
> - повреждение памяти и ошибки сегментации.
22. Дополнительный код ошибки `MDBX_EMULTIVAL`, который возвращается из
`mdbx_put()` и `mdbx_replace()` при попытке выполнить неоднозначное
@@ -655,7 +666,7 @@ _libmdbx_ при этом не ведет WAL, а передает весь ко
цикле обновления данных и записи на диск. Фактически _libmdbx_ выполняет
постоянную компактификацию данных, но не затрачивая на это
дополнительных ресурсов, а только освобождая их. При освобождении места
в БД и установки соответствующих параметров геометрии базы данных, также будет
в БД и установке соответствующих параметров геометрии базы данных, также будет
уменьшаться размер файла на диске, в том числе в **Windows**.
--------------------------------------------------------------------------------

View File

@@ -7,17 +7,33 @@ libmdbx
[![Build status](https://ci.appveyor.com/api/projects/status/ue94mlopn50dqiqg/branch/master?svg=true)](https://ci.appveyor.com/project/leo-yuriev/libmdbx/branch/master)
[![Coverity Scan Status](https://scan.coverity.com/projects/12915/badge.svg)](https://scan.coverity.com/projects/reopen-libmdbx)
### Project Status
## Project Status for now
**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.
- The stable versions ([_stable/0.0_](https://github.com/leo-yuriev/libmdbx/tree/stable/0.0) and [_stable/0.1_](https://github.com/leo-yuriev/libmdbx/tree/stable/0.1) branches) of _MDBX_ are frozen, i.e. no new features or API changes, but only bug fixes.
- The next version ([_devel_](https://github.com/leo-yuriev/libmdbx/tree/devel) branch) **is under active non-public development**, i.e. current API and set of features are extreme volatile.
- The immediate goal of development is formation of the stable API and the stable internal database format, which allows realise all PLANNED FEATURES:
1. Integrity check by [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree);
2. Support for [raw block devices](https://en.wikipedia.org/wiki/Raw_device);
3. Separate place (HDD) for large data items;
4. Using "[Roaring bitmaps](http://roaringbitmap.org/about/)" inside garbage collector;
5. Non-sequential reclaiming, like PostgreSQL's [Vacuum](https://www.postgresql.org/docs/9.1/static/sql-vacuum.html);
6. [Asynchronous lazy data flushing](https://sites.fas.harvard.edu/~cs265/papers/kathuria-2008.pdf) to disk(s);
7. etc...
-----
Nowadays MDBX intended for Linux, and support Windows (since
Windows Server 2008) as a 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 Continuous
Integration service will be available.
## Contents
- [Overview](#overview)
- [Comparison with other DBs](#comparison-with-other-dbs)
- [History & Acknowledgements](#history)
- [History & Acknowledgments](#history)
- [Main features](#main-features)
- [Performance comparison](#performance-comparison)
- [Integral performance](#integral-performance)
@@ -34,7 +50,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).
@@ -57,7 +73,7 @@ Because _libmdbx_ is currently overhauled, I think it's better to just link
### History
_libmdbx_ design is based on [Lightning Memory-Mapped Database](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database).
The _libmdbx_ design is based on [Lightning Memory-Mapped Database](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database).
Initial development was going in [ReOpenLDAP](https://github.com/leo-yuriev/ReOpenLDAP) project, about a year later it
received separate development effort and in autumn 2015 was isolated to separate project, which was
[presented at Highload++ 2015 conference](http://www.highload.ru/2015/abstracts/1831.html).
@@ -65,7 +81,7 @@ received separate development effort and in autumn 2015 was isolated to separate
Since early 2017 _libmdbx_ is used in [Fast Positive Tables](https://github.com/leo-yuriev/libfpta),
by [Positive Technologies](https://www.ptsecurity.com).
#### Acknowledgements
#### Acknowledgments
Howard Chu (Symas Corporation) - the author of LMDB,
from which originated the MDBX in 2015.
@@ -233,7 +249,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
@@ -261,7 +277,7 @@ scanning data directory.
#### Long-time read transactions problem
Garbage collection problem exists in all databases one way or another (e.g. VACUUM in PostgreSQL).
But in _libmbdx_ and LMDB it's even more important because of high performance and deliberate
But in _libmdbx_ and LMDB it's even more important because of high performance and deliberate
simplification of internals with emphasis on performance.
* Altering data during long read operation may exhaust available space on persistent storage.
@@ -297,7 +313,7 @@ _libmdbx_ addresses the problem, details below. Illustrations to this problem ca
In `WRITEMAP+MAPSYNC` mode dirty pages are written to persistent storage by kernel. This means that in case of application
crash OS kernel will write all dirty data to disk and nothing will be lost. But in case of hardware malfunction or OS kernel
fatal error only some dirty data might be synced to disk, and there is high probability that pages with metadata saved,
will point to non-saved, hence non-existent, data pages. In such situation DB is completely corrupted and can't be
will point to non-saved, hence non-existent, data pages. In such situation, DB is completely corrupted and can't be
repaired even if there was full sync before the crash via `mdbx_env_sync().
_libmdbx_ addresses this by fully reimplementing write path of data:
@@ -320,7 +336,7 @@ synchronization point. So last steady synchronization point creates "long-time r
of memory exhaustion the problem will be immediately addressed by flushing changes to persistent storage and forming new steady
synchronization point.
So in async-write mode _libmdbx_ will always use new pages until memory is exhausted or `mdbx_env_sync()`is invoked. Total
So in async-write mode _libmdbx_ will always use new pages until memory is exhausted or `mdbx_env_sync()` is invoked. Total
disk usage will be almost the same as in sync-write mode.
Current _libmdbx_ gives a choice of safe async-write mode (default) and `UTTERLY_NOSYNC` mode which may result in full DB
@@ -336,10 +352,10 @@ Improvements over LMDB
1. `LIFO RECLAIM` mode:
The newest pages are picked for reuse instead of the oldest.
This allows to minimize reclaim loop and make it execution time independent from total page count.
This allows to minimize reclaim loop and make it execution time independent of 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.
@@ -348,7 +364,7 @@ Improvements over LMDB
`mdbx_env_set_oomfunc()` allows to set a callback, which will be called
in the event of memory exhausting during long-time read transaction.
Callback will be invoked with PID and pthread_id of offending thread as parameters.
Callback can do any of this things to remedy the problem:
Callback can do any of these things to remedy the problem:
* wait for read transaction to finish normally;
@@ -378,7 +394,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.
@@ -392,7 +408,7 @@ Improvements over LMDB
15. Ability to close DB in "dirty" state (without data flush and creation of steady synchronization point)
via `mdbx_env_close_ex()`.
16. Ability to get addition info, including number of the oldest snapshot of DB, which is used by one of the readers.
16. Ability to get additional info, including number of the oldest snapshot of DB, which is used by one of the readers.
Implemented via `mdbx_env_info()`.
17. `mdbx_del()` doesn't ignore additional argument (specifier) `data`
@@ -401,7 +417,7 @@ Improvements over LMDB
18. Ability to open dbi-table with simultaneous setup of comparators for keys and values, via `mdbx_dbi_open_ex()`.
19. Ability to find out if key or value are in dirty page. This may be useful to make a decision to avoid
19. Ability to find out if key or value is in dirty page. This may be useful to make a decision to avoid
excessive CoW before updates. Implemented via `mdbx_is_dirty()`.
20. Correct update of current record in `MDBX_CURRENT` mode of `mdbx_cursor_put()`, including sorted duplicated.
@@ -419,7 +435,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.
@@ -432,12 +448,12 @@ Improvements over LMDB
27. Advanced dynamic control over DB size, including ability to choose page size via `mdbx_env_set_geometry()`,
including on Windows.
28. Three meta-pages instead two, this allows to guarantee consistently update weak sync-points without risking to
28. Three meta-pages instead of two, this allows to guarantee consistently update weak sync-points without risking to
corrupt last steady sync-point.
29. Automatic reclaim of freed pages to specific reserved space in the end of database file. This lowers amount of pages,
29. Automatic reclaim of freed pages to specific reserved space at the end of database file. This lowers amount of pages,
loaded to memory, used in update/flush loop. In fact _libmdbx_ constantly performs compactification of data,
but doesn't use addition resources for that. Space reclaim of DB and setup of database geometry parameters also decreases
but doesn't use additional resources for that. Space reclaim of DB and setup of database geometry parameters also decreases
size of the database on disk, including on Windows.
--------------------------------------------------------------------------------

View File

@@ -21,7 +21,7 @@
Тесты
=====
- [ ] Тестирование поддержки lockless-режима.
- [ ] Додумать имя и размещение тестовой БД по-умолчанию.
- [x] Додумать имя и размещение тестовой БД по-умолчанию.
- [ ] Реализовать cleanup в тесте.
- [ ] usage для теста.
- [ ] Логирование в файл, плюс более полный progress bar.
@@ -70,7 +70,7 @@
- [x] Привести в порядок volatile.
- [x] контроль meta.mapsize.
- [x] переработка формата: заголовки страниц, meta, clk...
- [x] зачистка Doxygen и бесполезных коментариев.
- [x] зачистка Doxygen и бесполезных комментариев.
- [x] Добавить поле типа контрольной суммы.
- [x] Добавить поле/флаг размера pgno_t.
- [x] Поменять сигнатуры.

View File

@@ -1,4 +1,4 @@
version: 0.1.2.{build}
version: 0.1.5.{build}
environment:
matrix:

45
mdbx.h
View File

@@ -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

View File

@@ -23,11 +23,6 @@
# undef NDEBUG
#endif
/* Features under development */
#ifndef MDBX_DEVEL
# define MDBX_DEVEL 1
#endif
/*----------------------------------------------------------------------------*/
/* Should be defined before any includes */
@@ -45,6 +40,9 @@
#if _MSC_VER > 1800
# pragma warning(disable : 4464) /* relative include path contains '..' */
#endif
#if _MSC_VER > 1913
# pragma warning(disable : 5045) /* Compiler will insert Spectre mitigation... */
#endif
#pragma warning(disable : 4710) /* 'xyz': function not inlined */
#pragma warning(disable : 4711) /* function 'xyz' selected for automatic inline expansion */
#pragma warning(disable : 4201) /* nonstandard extension used : nameless struct / union */
@@ -55,6 +53,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 +88,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"
@@ -137,9 +139,9 @@
#define MDBX_MAGIC UINT64_C(/* 56-bit prime */ 0x59659DBDEF4C11)
/* The version number for a database's datafile format. */
#define MDBX_DATA_VERSION ((MDBX_DEVEL) ? 255 : 2)
#define MDBX_DATA_VERSION 2
/* The version number for a database's lockfile format. */
#define MDBX_LOCK_VERSION ((MDBX_DEVEL) ? 255 : 2)
#define MDBX_LOCK_VERSION 2
/* handle for the DB used to track free pages. */
#define FREE_DBI 0
@@ -164,9 +166,7 @@ typedef uint32_t pgno_t;
/* A transaction ID. */
typedef uint64_t txnid_t;
#define PRIaTXN PRIi64
#if MDBX_DEVEL
#define MIN_TXNID (UINT64_MAX - UINT32_MAX)
#elif MDBX_DEBUG
#if MDBX_DEBUG
#define MIN_TXNID UINT64_C(0x100000000)
#else
#define MIN_TXNID UINT64_C(1)
@@ -249,7 +249,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 +407,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;
uint8_t pad_mti_wmutex[MDBX_OSAL_LOCK_SIZE % sizeof(size_t)];
};
#endif
uint64_t align_wmutex;
};
#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;
uint8_t pad_mti_rmutex[MDBX_OSAL_LOCK_SIZE % sizeof(size_t)];
};
#endif
uint64_t align_rmutex;
};
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) & \
@@ -938,13 +944,13 @@ static __inline void mdbx_jitter4testing(bool tiny) {
/* Internal prototypes and inlines */
int mdbx_reader_check0(MDBX_env *env, int rlocked, int *dead);
void mdbx_rthc_dtor(void *rthc);
void mdbx_rthc_lock(void);
void mdbx_rthc_unlock(void);
int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin,
MDBX_reader *end);
void mdbx_rthc_remove(mdbx_thread_key_t key);
void mdbx_rthc_cleanup(void);
void mdbx_rthc_remove(const mdbx_thread_key_t key);
void mdbx_rthc_global_init(void);
void mdbx_rthc_global_dtor(void);
void mdbx_rthc_thread_dtor(void *ptr);
static __inline bool mdbx_is_power2(size_t x) { return (x & (x - 1)) == 0; }

View File

@@ -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))

View File

@@ -32,18 +32,12 @@
/*----------------------------------------------------------------------------*/
/* rthc */
static pthread_mutex_t mdbx_rthc_mutex = PTHREAD_MUTEX_INITIALIZER;
void mdbx_rthc_lock(void) {
mdbx_ensure(NULL, pthread_mutex_lock(&mdbx_rthc_mutex) == 0);
static __cold __attribute__((constructor)) void mdbx_global_constructor(void) {
mdbx_rthc_global_init();
}
void mdbx_rthc_unlock(void) {
mdbx_ensure(NULL, pthread_mutex_unlock(&mdbx_rthc_mutex) == 0);
}
void __attribute__((destructor)) mdbx_global_destructor(void) {
mdbx_rthc_cleanup();
static __cold __attribute__((destructor)) void mdbx_global_destructor(void) {
mdbx_rthc_global_dtor();
}
/*----------------------------------------------------------------------------*/

View File

@@ -27,31 +27,24 @@
/*----------------------------------------------------------------------------*/
/* rthc */
static CRITICAL_SECTION rthc_critical_section;
static void NTAPI tls_callback(PVOID module, DWORD reason, PVOID reserved) {
(void)module;
(void)reserved;
switch (reason) {
case DLL_PROCESS_ATTACH:
InitializeCriticalSection(&rthc_critical_section);
mdbx_rthc_global_init();
break;
case DLL_PROCESS_DETACH:
DeleteCriticalSection(&rthc_critical_section);
mdbx_rthc_global_dtor();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
mdbx_rthc_cleanup();
mdbx_rthc_thread_dtor(module);
break;
}
}
void mdbx_rthc_lock(void) { EnterCriticalSection(&rthc_critical_section); }
void mdbx_rthc_unlock(void) { LeaveCriticalSection(&rthc_critical_section); }
/* *INDENT-OFF* */
/* clang-format off */
#if defined(_MSC_VER)
@@ -169,7 +162,10 @@ int mdbx_rdt_lock(MDBX_env *env) {
/* transite from S-? (used) to S-E (locked), e.g. exclusive lock upper-part */
if (flock(env->me_lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER))
return MDBX_SUCCESS;
return GetLastError();
int rc = GetLastError();
ReleaseSRWLockShared(&env->me_remap_guard);
return rc;
}
void mdbx_rdt_unlock(MDBX_env *env) {
@@ -550,10 +546,12 @@ int mdbx_rpid_clear(MDBX_env *env) {
* or otherwise the errcode. */
int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid) {
(void)env;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid);
int rc;
if (hProcess) {
if (likely(hProcess)) {
rc = WaitForSingleObject(hProcess, 0);
if (unlikely(rc == WAIT_FAILED))
rc = GetLastError();
CloseHandle(hProcess);
} else {
rc = GetLastError();

File diff suppressed because it is too large Load Diff

View File

@@ -700,39 +700,6 @@ int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length) {
/*----------------------------------------------------------------------------*/
int mdbx_thread_key_create(mdbx_thread_key_t *key) {
#if defined(_WIN32) || defined(_WIN64)
*key = TlsAlloc();
return (*key != TLS_OUT_OF_INDEXES) ? MDBX_SUCCESS : GetLastError();
#else
return pthread_key_create(key, mdbx_rthc_dtor);
#endif
}
void mdbx_thread_key_delete(mdbx_thread_key_t key) {
#if defined(_WIN32) || defined(_WIN64)
mdbx_ensure(NULL, TlsFree(key));
#else
mdbx_ensure(NULL, pthread_key_delete(key) == 0);
#endif
}
void *mdbx_thread_rthc_get(mdbx_thread_key_t key) {
#if defined(_WIN32) || defined(_WIN64)
return TlsGetValue(key);
#else
return pthread_getspecific(key);
#endif
}
void mdbx_thread_rthc_set(mdbx_thread_key_t key, const void *value) {
#if defined(_WIN32) || defined(_WIN64)
mdbx_ensure(NULL, TlsSetValue(key, (void *)value));
#else
mdbx_ensure(NULL, pthread_setspecific(key, value) == 0);
#endif
}
int mdbx_thread_create(mdbx_thread_t *thread,
THREAD_RESULT(THREAD_CALL *start_routine)(void *),
void *arg) {

View File

@@ -103,24 +103,47 @@ typedef struct {
typedef pthread_mutex_t mdbx_fastmutex_t;
#endif /* Platform */
/* *INDENT-OFF* */
/* clang-format off */
#if defined(HAVE_SYS_STAT_H) || __has_include(<sys/stat.h>)
#include <sys/stat.h>
#endif
#if defined(HAVE_SYS_TYPES_H) || __has_include(<sys/types.h>)
#include <sys/types.h>
#endif
#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
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#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,45 +197,70 @@ 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 /* Arch */
#endif
#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ && \
__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
#error Unsupported byte order.
#endif
/*----------------------------------------------------------------------------*/
/* 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;
@@ -433,10 +469,6 @@ int mdbx_thread_create(mdbx_thread_t *thread,
THREAD_RESULT(THREAD_CALL *start_routine)(void *),
void *arg);
int mdbx_thread_join(mdbx_thread_t thread);
int mdbx_thread_key_create(mdbx_thread_key_t *key);
void mdbx_thread_key_delete(mdbx_thread_key_t key);
void *mdbx_thread_rthc_get(mdbx_thread_key_t key);
void mdbx_thread_rthc_set(mdbx_thread_key_t key, const void *value);
int mdbx_filesync(mdbx_filehandle_t fd, bool fullsync);
int mdbx_filesize_sync(mdbx_filehandle_t fd);
@@ -504,7 +536,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 +554,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);

View File

@@ -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 %s in 'read-%s' mode...\n", envname,
(envflags & MDBX_RDONLY) ? "only" : "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);

View File

@@ -18,8 +18,8 @@
#error "API version mismatch!"
#endif
#define MDBX_VERSION_RELEASE 0
#define MDBX_VERSION_REVISION 0
#define MDBX_VERSION_RELEASE 5
#define MDBX_VERSION_REVISION 1
/*LIBMDBX_EXPORTS*/ const mdbx_version_info mdbx_version = {
MDBX_VERSION_MAJOR,

View File

@@ -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"

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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(); }

View File

@@ -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

View File

@@ -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",

View File

@@ -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 "";
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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))

View File

@@ -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)