mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-02 01:34:12 +08:00
mdbx: merge branch 'osx-try'.
This resolves https://github.com/leo-yuriev/libmdbx/issues/49. Change-Id: Ib20c3898e99ca229f10e7d41cda3989b8b4a832c
This commit is contained in:
commit
6f0a11f155
@ -7,6 +7,7 @@ compiler:
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
script: if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make all check; fi
|
||||
|
||||
|
57
Makefile
57
Makefile
@ -23,6 +23,7 @@ suffix ?=
|
||||
|
||||
CC ?= gcc
|
||||
CXX ?= g++
|
||||
LD ?= ld
|
||||
CFLAGS ?= -O2 -g3 -Wall -Werror -Wextra -ffunction-sections -fPIC -fvisibility=hidden
|
||||
|
||||
XCFLAGS ?= -DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1
|
||||
@ -32,8 +33,8 @@ 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,-O1,--no-as-needed,-lrt
|
||||
EXE_LDFLAGS ?= -pthread -lrt
|
||||
LDFLAGS ?= $(shell $(LD) --help 2>/dev/null | grep -q -- --gc-sections && echo '-Wl,--gc-sections,-z,relro,-O1')$(shell $(LD) --help 2>/dev/null | grep -q -- -dead_strip && echo '-Wl,-dead_strip')
|
||||
EXE_LDFLAGS ?= -pthread
|
||||
|
||||
# LY: just for benchmarking
|
||||
IOARENA ?= $(shell \
|
||||
@ -44,33 +45,51 @@ NN ?= 25000000
|
||||
|
||||
########################################################################
|
||||
|
||||
HEADERS := mdbx.h
|
||||
LIBRARIES := libmdbx.a libmdbx.so
|
||||
TOOLS := mdbx_stat mdbx_copy mdbx_dump mdbx_load mdbx_chk
|
||||
MANPAGES := mdbx_stat.1 mdbx_copy.1 mdbx_dump.1 mdbx_load.1
|
||||
SHELL := /bin/bash
|
||||
|
||||
ifdef MSVC
|
||||
UNAME := Windows
|
||||
LCK_IMPL := windows
|
||||
TEST_OSAL := windows
|
||||
TEST_ITER := 42
|
||||
else
|
||||
UNAME := $(shell uname -s 2>/dev/null || echo Unknown)
|
||||
define uname2lck
|
||||
case "`uname -s 2>/dev/null`" in
|
||||
case "$(UNAME)" in
|
||||
Linux) echo linux;;
|
||||
CYGWIN*|MINGW32*|MSYS*) echo windows;;
|
||||
CYGWIN*|MINGW32*|MSYS*|Windows*) echo windows;;
|
||||
*) echo posix;;
|
||||
esac
|
||||
endef
|
||||
define uname2osal
|
||||
case "`uname -s 2>/dev/null`" in
|
||||
CYGWIN*|MINGW32*|MSYS*) echo windows;;
|
||||
case "$(UNAME)" in
|
||||
CYGWIN*|MINGW32*|MSYS*|Windows*) echo windows;;
|
||||
*) echo unix;;
|
||||
esac
|
||||
endef
|
||||
define uname2titer
|
||||
case "$(UNAME)" in
|
||||
Darwin*|Mach*) echo 3;;
|
||||
*) echo 42;;
|
||||
esac
|
||||
endef
|
||||
define uname2suffix
|
||||
case "$(UNAME)" in
|
||||
Darwin*|Mach*) echo dylib;;
|
||||
CYGWIN*|MINGW32*|MSYS*|Windows*) echo dll;;
|
||||
*) echo so;;
|
||||
esac
|
||||
endef
|
||||
LCK_IMPL := $(shell $(uname2lck))
|
||||
TEST_OSAL := $(shell $(uname2osal))
|
||||
TEST_ITER := $(shell $(uname2titer))
|
||||
SO_SUFFIX := $(shell $(uname2suffix))
|
||||
endif
|
||||
|
||||
HEADERS := mdbx.h
|
||||
LIBRARIES := libmdbx.a libmdbx.$(SO_SUFFIX)
|
||||
TOOLS := mdbx_stat mdbx_copy mdbx_dump mdbx_load mdbx_chk
|
||||
MANPAGES := mdbx_stat.1 mdbx_copy.1 mdbx_dump.1 mdbx_load.1
|
||||
SHELL := /bin/bash
|
||||
|
||||
CORE_SRC := src/lck-$(LCK_IMPL).c $(filter-out $(wildcard src/lck-*.c), $(wildcard src/*.c))
|
||||
CORE_INC := $(wildcard src/*.h)
|
||||
CORE_OBJ := $(patsubst %.c,%.o,$(CORE_SRC))
|
||||
@ -82,10 +101,10 @@ TEST_OBJ := $(patsubst %.cc,%.o,$(TEST_SRC))
|
||||
|
||||
all: $(LIBRARIES) $(TOOLS) mdbx_test example
|
||||
|
||||
mdbx: libmdbx.a libmdbx.so
|
||||
mdbx: libmdbx.a libmdbx.$(SO_SUFFIX)
|
||||
|
||||
example: mdbx.h tutorial/sample-mdbx.c libmdbx.so
|
||||
$(CC) $(CFLAGS) -I. tutorial/sample-mdbx.c ./libmdbx.so -o example
|
||||
example: mdbx.h tutorial/sample-mdbx.c libmdbx.$(SO_SUFFIX)
|
||||
$(CC) $(CFLAGS) -I. tutorial/sample-mdbx.c ./libmdbx.$(SO_SUFFIX) -o example
|
||||
|
||||
tools: $(TOOLS)
|
||||
|
||||
@ -103,7 +122,7 @@ clean:
|
||||
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; ./mdbx_test --repeat=42 --pathname=$(TESTDB) --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) \
|
||||
rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --repeat=$(TEST_ITER) --pathname=$(TESTDB) --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) \
|
||||
&& ./mdbx_chk -vvn $(TESTDB) && ./mdbx_chk -vvn $(TESTDB)-copy
|
||||
|
||||
check-singleprocess: all
|
||||
@ -134,13 +153,13 @@ $(foreach file,$(TEST_SRC),$(eval $(call test-rule,$(file))))
|
||||
libmdbx.a: $(CORE_OBJ)
|
||||
$(AR) rs $@ $?
|
||||
|
||||
libmdbx.so: $(CORE_OBJ)
|
||||
libmdbx.$(SO_SUFFIX): $(CORE_OBJ)
|
||||
$(CC) $(CFLAGS) -save-temps $^ -pthread -shared $(LDFLAGS) -o $@
|
||||
|
||||
mdbx_%: src/tools/mdbx_%.c libmdbx.a
|
||||
$(CC) $(CFLAGS) $^ $(EXE_LDFLAGS) -o $@
|
||||
|
||||
mdbx_test: $(TEST_OBJ) libmdbx.so
|
||||
mdbx_test: $(TEST_OBJ) libmdbx.$(SO_SUFFIX)
|
||||
$(CXX) $(CXXFLAGS) $(TEST_OBJ) -Wl,-rpath . -L . -l mdbx $(EXE_LDFLAGS) -o $@
|
||||
|
||||
###############################################################################
|
||||
@ -166,7 +185,7 @@ bench-$(1)_$(2).txt: $(3) $(IOARENA) Makefile
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call bench-rule,mdbx,$(NN),libmdbx.so))
|
||||
$(eval $(call bench-rule,mdbx,$(NN),libmdbx.$(SO_SUFFIX)))
|
||||
|
||||
$(eval $(call bench-rule,sophia,$(NN)))
|
||||
$(eval $(call bench-rule,leveldb,$(NN)))
|
||||
|
10
src/bits.h
10
src/bits.h
@ -23,6 +23,12 @@
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
|
||||
#define MDBX_OSX_WANNA_DURABILITY 0 /* using fcntl(F_FULLFSYNC) with 5-10 times slowdown */
|
||||
#define MDBX_OSX_WANNA_SPEED 1 /* using fsync() with chance of data lost on power failure */
|
||||
#ifndef MDBX_OSX_SPEED_OR_DURABILITY
|
||||
#define MDBX_OSX_SPEED_OR_DURABILITY MDBX_OSX_WANNA_DURABILITY
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/* Should be defined before any includes */
|
||||
@ -30,6 +36,10 @@
|
||||
# define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define _DARWIN_C_SOURCE
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# if _MSC_VER < 1400
|
||||
# error "Microsoft Visual C++ 8.0 (Visual Studio 2005) or later version is required"
|
||||
|
@ -18,7 +18,7 @@
|
||||
* even though they don't support Robust Mutexes.
|
||||
* Compile with -DMDBX_USE_ROBUST=0. */
|
||||
#ifndef MDBX_USE_ROBUST
|
||||
#if defined(EOWNERDEAD) || _POSIX_C_SOURCE >= 200809L
|
||||
#if (defined(EOWNERDEAD) || _POSIX_C_SOURCE >= 200809L) && !defined(__APPLE__)
|
||||
#define MDBX_USE_ROBUST 1
|
||||
#else
|
||||
#define MDBX_USE_ROBUST 0
|
||||
|
52
src/mdbx.c
52
src/mdbx.c
@ -292,6 +292,16 @@ static CRITICAL_SECTION rthc_critical_section;
|
||||
#else
|
||||
int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, void *dso_symbol)
|
||||
__attribute__((weak));
|
||||
#ifdef __APPLE__ /* FIXME: Thread-Local Storage destructors & DSO-unloading */
|
||||
int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj,
|
||||
void *dso_symbol) {
|
||||
(void)dtor;
|
||||
(void)obj;
|
||||
(void)dso_symbol;
|
||||
return -1;
|
||||
}
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
static pthread_mutex_t mdbx_rthc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t mdbx_rthc_cond = PTHREAD_COND_INITIALIZER;
|
||||
static mdbx_thread_key_t mdbx_rthc_key;
|
||||
@ -515,9 +525,9 @@ __cold void mdbx_rthc_global_dtor(void) {
|
||||
mdbx_thread_key_delete(key);
|
||||
for (MDBX_reader *rthc = rthc_table[i].begin; rthc < rthc_table[i].end;
|
||||
++rthc) {
|
||||
mdbx_trace("== [%i] = key %u, %p ... %p, rthc %p (%+i), "
|
||||
mdbx_trace("== [%i] = key %zu, %p ... %p, rthc %p (%+i), "
|
||||
"rthc-pid %i, current-pid %i",
|
||||
i, key, rthc_table[i].begin, rthc_table[i].end, rthc,
|
||||
i, (size_t)key, rthc_table[i].begin, rthc_table[i].end, rthc,
|
||||
(int)(rthc - rthc_table[i].begin), rthc->mr_pid, self_pid);
|
||||
if (rthc->mr_pid == self_pid) {
|
||||
rthc->mr_pid = 0;
|
||||
@ -553,8 +563,8 @@ __cold int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin,
|
||||
return rc;
|
||||
|
||||
mdbx_rthc_lock();
|
||||
mdbx_trace(">> key 0x%x, rthc_count %u, rthc_limit %u", *key, rthc_count,
|
||||
rthc_limit);
|
||||
mdbx_trace(">> key %zu, rthc_count %u, rthc_limit %u", (size_t)*key,
|
||||
rthc_count, rthc_limit);
|
||||
if (rthc_count == rthc_limit) {
|
||||
rthc_entry_t *new_table =
|
||||
mdbx_realloc((rthc_table == rthc_table_static) ? nullptr : rthc_table,
|
||||
@ -568,13 +578,14 @@ __cold int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin,
|
||||
rthc_table = new_table;
|
||||
rthc_limit *= 2;
|
||||
}
|
||||
mdbx_trace("== [%i] = key %u, %p ... %p", rthc_count, *key, begin, end);
|
||||
mdbx_trace("== [%i] = key %zu, %p ... %p", rthc_count, (size_t)*key, begin,
|
||||
end);
|
||||
rthc_table[rthc_count].key = *key;
|
||||
rthc_table[rthc_count].begin = begin;
|
||||
rthc_table[rthc_count].end = end;
|
||||
++rthc_count;
|
||||
mdbx_trace("<< key 0x%x, rthc_count %u, rthc_limit %u", *key, rthc_count,
|
||||
rthc_limit);
|
||||
mdbx_trace("<< key %zu, rthc_count %u, rthc_limit %u", (size_t)*key,
|
||||
rthc_count, rthc_limit);
|
||||
mdbx_rthc_unlock();
|
||||
return MDBX_SUCCESS;
|
||||
|
||||
@ -587,8 +598,8 @@ bailout:
|
||||
__cold void mdbx_rthc_remove(const mdbx_thread_key_t key) {
|
||||
mdbx_thread_key_delete(key);
|
||||
mdbx_rthc_lock();
|
||||
mdbx_trace(">> key 0x%x, rthc_count %u, rthc_limit %u", key, rthc_count,
|
||||
rthc_limit);
|
||||
mdbx_trace(">> key %zu, rthc_count %u, rthc_limit %u", (size_t)key,
|
||||
rthc_count, rthc_limit);
|
||||
|
||||
for (unsigned i = 0; i < rthc_count; ++i) {
|
||||
if (key == rthc_table[i].key) {
|
||||
@ -614,8 +625,8 @@ __cold void mdbx_rthc_remove(const mdbx_thread_key_t key) {
|
||||
}
|
||||
}
|
||||
|
||||
mdbx_trace("<< key 0x%x, rthc_count %u, rthc_limit %u", key, rthc_count,
|
||||
rthc_limit);
|
||||
mdbx_trace("<< key %zu, rthc_count %u, rthc_limit %u", (size_t)key,
|
||||
rthc_count, rthc_limit);
|
||||
mdbx_rthc_unlock();
|
||||
}
|
||||
|
||||
@ -3030,7 +3041,7 @@ __cold static int mdbx_env_sync_ex(MDBX_env *env, int force, int nonblock) {
|
||||
int rc = (flags & MDBX_WRITEMAP)
|
||||
? mdbx_msync(&env->me_dxb_mmap, 0, usedbytes,
|
||||
flags & MDBX_MAPASYNC)
|
||||
: mdbx_filesync(env->me_fd, false);
|
||||
: mdbx_filesync(env->me_fd, MDBX_SYNC_DATA);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
return rc;
|
||||
|
||||
@ -5411,14 +5422,16 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
|
||||
goto fail;
|
||||
if ((flags & MDBX_MAPASYNC) == 0) {
|
||||
if (unlikely(pending->mm_geo.next > steady->mm_geo.now)) {
|
||||
rc = mdbx_filesize_sync(env->me_fd);
|
||||
rc = mdbx_filesync(env->me_fd, MDBX_SYNC_SIZE);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto fail;
|
||||
}
|
||||
env->me_sync_pending = 0;
|
||||
}
|
||||
} else {
|
||||
rc = mdbx_filesync(env->me_fd, pending->mm_geo.next > steady->mm_geo.now);
|
||||
rc = mdbx_filesync(env->me_fd, (pending->mm_geo.next > steady->mm_geo.now)
|
||||
? MDBX_SYNC_DATA | MDBX_SYNC_SIZE
|
||||
: MDBX_SYNC_DATA);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto fail;
|
||||
env->me_sync_pending = 0;
|
||||
@ -5566,7 +5579,7 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto fail;
|
||||
} else {
|
||||
rc = mdbx_filesync(env->me_fd, false);
|
||||
rc = mdbx_filesync(env->me_fd, MDBX_SYNC_DATA | MDBX_SYNC_IODQ);
|
||||
if (rc != MDBX_SUCCESS)
|
||||
goto undo;
|
||||
}
|
||||
@ -11814,12 +11827,15 @@ int __cold mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd,
|
||||
mdbx_txn_abort(read_txn);
|
||||
|
||||
if (likely(rc == MDBX_SUCCESS))
|
||||
rc = mdbx_filesync(fd, true);
|
||||
rc = mdbx_filesync(fd, MDBX_SYNC_DATA | MDBX_SYNC_SIZE);
|
||||
|
||||
/* Write actual meta */
|
||||
if (likely(rc == MDBX_SUCCESS))
|
||||
rc = mdbx_pwrite(fd, buffer, pgno2bytes(env, NUM_METAS), 0);
|
||||
|
||||
if (likely(rc == MDBX_SUCCESS))
|
||||
rc = mdbx_filesync(fd, MDBX_SYNC_DATA | MDBX_SYNC_IODQ);
|
||||
|
||||
mdbx_memalign_free(buffer);
|
||||
return rc;
|
||||
}
|
||||
@ -12860,7 +12876,7 @@ int __cold mdbx_setup_debug(int flags, MDBX_debug_func *logger) {
|
||||
unsigned ret = mdbx_runtime_flags;
|
||||
mdbx_runtime_flags = flags;
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) || defined(__gnu_linux__)
|
||||
if (flags & MDBX_DBG_DUMP) {
|
||||
int core_filter_fd = open("/proc/self/coredump_filter", O_TRUNC | O_RDWR);
|
||||
if (core_filter_fd >= 0) {
|
||||
@ -12883,7 +12899,7 @@ int __cold mdbx_setup_debug(int flags, MDBX_debug_func *logger) {
|
||||
close(core_filter_fd);
|
||||
}
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
#endif /* Linux */
|
||||
|
||||
mdbx_debug_logger = logger;
|
||||
return ret;
|
||||
|
67
src/osal.c
67
src/osal.c
@ -159,9 +159,14 @@ typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 {
|
||||
/* Prototype should match libc runtime. ISO POSIX (2003) & LSB 1.x-3.x */
|
||||
__nothrow __noreturn void __assert_fail(const char *assertion, const char *file,
|
||||
unsigned line, const char *function);
|
||||
#elif (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
|
||||
defined(__DragonFly__))
|
||||
#elif defined(__APPLE__) || defined(__MACH__)
|
||||
__nothrow __noreturn void __assert_rtn(const char *function, const char *file,
|
||||
int line, const char *assertion);
|
||||
#define __assert_fail(assertion, file, line, function) \
|
||||
__assert_rtn(function, file, line, assertion)
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
|
||||
defined(__DragonFly__)
|
||||
__nothrow __noreturn void __assert(const char *function, const char *file,
|
||||
int line, const char *assertion);
|
||||
#define __assert_fail(assertion, file, line, function) \
|
||||
@ -548,6 +553,9 @@ int mdbx_openfile(const char *pathname, int flags, mode_t mode,
|
||||
if (fd_flags != -1)
|
||||
(void)fcntl(*fd, F_SETFL, fd_flags | O_DIRECT);
|
||||
#endif /* O_DIRECT */
|
||||
#if defined(F_NOCACHE)
|
||||
(void)fcntl(*fd, F_NOCACHE, 1);
|
||||
#endif /* F_NOCACHE */
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -626,7 +634,7 @@ int mdbx_pwrite(mdbx_filehandle_t fd, const void *buf, size_t bytes,
|
||||
|
||||
int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, int iovcnt,
|
||||
uint64_t offset, size_t expected_written) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(__APPLE__)
|
||||
size_t written = 0;
|
||||
for (int i = 0; i < iovcnt; ++i) {
|
||||
int rc = mdbx_pwrite(fd, iov[i].iov_base, iov[i].iov_len, offset);
|
||||
@ -652,11 +660,23 @@ int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, int iovcnt,
|
||||
#endif
|
||||
}
|
||||
|
||||
int mdbx_filesync(mdbx_filehandle_t fd, bool filesize_changed) {
|
||||
int mdbx_filesync(mdbx_filehandle_t fd, enum mdbx_syncmode_bits mode_bits) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
(void)filesize_changed;
|
||||
return FlushFileBuffers(fd) ? MDBX_SUCCESS : GetLastError();
|
||||
return ((mode_bits & (MDBX_SYNC_DATA | MDBX_SYNC_IODQ)) == 0 ||
|
||||
FlushFileBuffers(fd))
|
||||
? MDBX_SUCCESS
|
||||
: GetLastError();
|
||||
#else
|
||||
|
||||
#if defined(__APPLE__) && \
|
||||
MDBX_OSX_SPEED_OR_DURABILITY == MDBX_OSX_WANNA_DURABILITY
|
||||
if (mode_bits & MDBX_SYNC_IODQ)
|
||||
return likely(fcntl(fd, F_FULLFSYNC) != -1) ? MDBX_SUCCESS : errno;
|
||||
#endif /* MacOS */
|
||||
#if defined(__linux__) || defined(__gnu_linux__)
|
||||
if (mode_bits == MDBX_SYNC_SIZE && linux_kernel_version >= 0x03060000)
|
||||
return MDBX_SUCCESS;
|
||||
#endif /* Linux */
|
||||
int rc;
|
||||
do {
|
||||
#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
|
||||
@ -665,12 +685,12 @@ int mdbx_filesync(mdbx_filehandle_t fd, bool filesize_changed) {
|
||||
*
|
||||
* For more info about of a corresponding fdatasync() bug
|
||||
* see http://www.spinics.net/lists/linux-ext4/msg33714.html */
|
||||
if (!filesize_changed) {
|
||||
if ((mode_bits & MDBX_SYNC_SIZE) == 0) {
|
||||
if (fdatasync(fd) == 0)
|
||||
return MDBX_SUCCESS;
|
||||
} else
|
||||
#else
|
||||
(void)filesize_changed;
|
||||
(void)mode_bits;
|
||||
#endif
|
||||
if (fsync(fd) == 0)
|
||||
return MDBX_SUCCESS;
|
||||
@ -680,22 +700,6 @@ int mdbx_filesync(mdbx_filehandle_t fd, bool filesize_changed) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int mdbx_filesize_sync(mdbx_filehandle_t fd) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
(void)fd;
|
||||
/* Nothing on Windows (i.e. newer 100% steady) */
|
||||
return MDBX_SUCCESS;
|
||||
#else
|
||||
for (;;) {
|
||||
if (fsync(fd) == 0)
|
||||
return MDBX_SUCCESS;
|
||||
int rc = errno;
|
||||
if (rc != EINTR)
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
@ -792,7 +796,13 @@ int mdbx_msync(mdbx_mmap_t *map, size_t offset, size_t length, int async) {
|
||||
return MDBX_SUCCESS;
|
||||
#endif /* Linux */
|
||||
const int mode = async ? MS_ASYNC : MS_SYNC;
|
||||
return (msync(ptr, length, mode) == 0) ? MDBX_SUCCESS : errno;
|
||||
int rc = (msync(ptr, length, mode) == 0) ? MDBX_SUCCESS : errno;
|
||||
#if defined(__APPLE__) && \
|
||||
MDBX_OSX_SPEED_OR_DURABILITY == MDBX_OSX_WANNA_DURABILITY
|
||||
if (rc == MDBX_SUCCESS && mode == MS_SYNC)
|
||||
rc = likely(fcntl(map->fd, F_FULLFSYNC) != -1) ? MDBX_SUCCESS : errno;
|
||||
#endif /* MacOS */
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1165,7 +1175,10 @@ retry_mapview:;
|
||||
return rc;
|
||||
#else
|
||||
if (limit != map->length) {
|
||||
#if defined(_GNU_SOURCE) && !defined(__FreeBSD__)
|
||||
#if defined(_GNU_SOURCE) && \
|
||||
!(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
|
||||
defined(__DragonFly__) || defined(__APPLE__) || defined(__MACH__))
|
||||
void *ptr = mremap(map->address, map->length, limit,
|
||||
/* LY: in case changing the mapping size calling code
|
||||
must guarantees the absence of competing threads, and
|
||||
|
10
src/osal.h
10
src/osal.h
@ -55,7 +55,7 @@
|
||||
#include <time.h>
|
||||
#if !(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
|
||||
defined(__DragonFly__))
|
||||
defined(__DragonFly__) || defined(__APPLE__) || defined(__MACH__))
|
||||
#include <malloc.h>
|
||||
#endif /* xBSD */
|
||||
|
||||
@ -522,7 +522,13 @@ int mdbx_thread_create(mdbx_thread_t *thread,
|
||||
void *arg);
|
||||
int mdbx_thread_join(mdbx_thread_t thread);
|
||||
|
||||
int mdbx_filesync(mdbx_filehandle_t fd, bool fullsync);
|
||||
enum mdbx_syncmode_bits {
|
||||
MDBX_SYNC_DATA = 1,
|
||||
MDBX_SYNC_SIZE = 2,
|
||||
MDBX_SYNC_IODQ = 4
|
||||
};
|
||||
|
||||
int mdbx_filesync(mdbx_filehandle_t fd, enum mdbx_syncmode_bits mode_bits);
|
||||
int mdbx_filesize_sync(mdbx_filehandle_t fd);
|
||||
int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length);
|
||||
int mdbx_fseek(mdbx_filehandle_t fd, uint64_t pos);
|
||||
|
@ -39,6 +39,10 @@
|
||||
#include <SDKDDKVer.h>
|
||||
#endif /* WINDOWS */
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define _DARWIN_C_SOURCE
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
@ -102,6 +102,22 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
|
||||
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
|
||||
int32_t &value, const int32_t minval, const int32_t maxval,
|
||||
const int32_t default_value = -1);
|
||||
|
||||
inline bool parse_option_intptr(int argc, char *const argv[], int &narg,
|
||||
const char *option, intptr_t &value,
|
||||
const intptr_t minval, const intptr_t maxval,
|
||||
const intptr_t default_value = -1) {
|
||||
static_assert(sizeof(intptr_t) == 4 || sizeof(intptr_t) == 8, "WTF?");
|
||||
if (sizeof(intptr_t) == 8)
|
||||
return parse_option(argc, argv, narg, option,
|
||||
*reinterpret_cast<int64_t *>(&value), int64_t(minval),
|
||||
int64_t(maxval), int64_t(default_value));
|
||||
else
|
||||
return parse_option(argc, argv, narg, option,
|
||||
*reinterpret_cast<int32_t *>(&value), int32_t(minval),
|
||||
int32_t(maxval), int32_t(default_value));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
24
test/darwin/LICENSE
Normal file
24
test/darwin/LICENSE
Normal file
@ -0,0 +1,24 @@
|
||||
Copyright (c) 2015, Aleksey Demakov
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
8
test/darwin/README.md
Normal file
8
test/darwin/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# DarwinPthreadBarrier
|
||||
|
||||
A pthread_barrier_t implementation for Mac OS/X
|
||||
|
||||
There is no pthread_barrier_t in Mac OS/X pthreads. This project fixes
|
||||
this omission by providing a simple-minded barrier implementation based
|
||||
on a pair of pthread_mutex_t and pthread_cond_t.
|
||||
|
112
test/darwin/pthread_barrier.c
Normal file
112
test/darwin/pthread_barrier.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Aleksey Demakov
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "pthread_barrier.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#define __unused __attribute__((unused))
|
||||
|
||||
int pthread_barrierattr_init(pthread_barrierattr_t *attr) {
|
||||
memset(attr, 0, sizeof(pthread_barrierattr_t));
|
||||
int m = pthread_mutexattr_init(&attr->mattr);
|
||||
int c = pthread_condattr_init(&attr->cattr);
|
||||
return m ? m : c;
|
||||
}
|
||||
|
||||
int pthread_barrierattr_destroy(pthread_barrierattr_t *attr) {
|
||||
int c = pthread_condattr_destroy(&attr->cattr);
|
||||
int m = pthread_mutexattr_destroy(&attr->mattr);
|
||||
return m ? m : c;
|
||||
}
|
||||
|
||||
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr,
|
||||
int *__restrict pshared) {
|
||||
return pthread_condattr_getpshared(&attr->cattr, pshared);
|
||||
}
|
||||
|
||||
int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) {
|
||||
int m = pthread_mutexattr_setpshared(&attr->mattr, pshared);
|
||||
int c = pthread_condattr_setpshared(&attr->cattr, pshared);
|
||||
return m ? m : c;
|
||||
}
|
||||
|
||||
int pthread_barrier_init(pthread_barrier_t *__restrict barrier,
|
||||
const pthread_barrierattr_t *__restrict attr,
|
||||
unsigned count) {
|
||||
if (count == 0)
|
||||
return errno = EINVAL;
|
||||
|
||||
int rc = pthread_mutex_init(&barrier->mutex, attr ? &attr->mattr : 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = pthread_cond_init(&barrier->cond, attr ? &attr->cattr : 0);
|
||||
if (rc) {
|
||||
int errno_save = errno;
|
||||
pthread_mutex_destroy(&barrier->mutex);
|
||||
errno = errno_save;
|
||||
return rc;
|
||||
}
|
||||
|
||||
barrier->limit = count;
|
||||
barrier->count = 0;
|
||||
barrier->phase = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_barrier_destroy(pthread_barrier_t *barrier) {
|
||||
pthread_mutex_destroy(&barrier->mutex);
|
||||
pthread_cond_destroy(&barrier->cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_barrier_wait(pthread_barrier_t *barrier) {
|
||||
int rc = pthread_mutex_lock(&barrier->mutex);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
barrier->count++;
|
||||
if (barrier->count >= barrier->limit) {
|
||||
barrier->phase++;
|
||||
barrier->count = 0;
|
||||
pthread_cond_broadcast(&barrier->cond);
|
||||
pthread_mutex_unlock(&barrier->mutex);
|
||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
} else {
|
||||
unsigned phase = barrier->phase;
|
||||
do
|
||||
pthread_cond_wait(&barrier->cond, &barrier->mutex);
|
||||
while (phase == barrier->phase);
|
||||
pthread_mutex_unlock(&barrier->mutex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __APPLE__ */
|
83
test/darwin/pthread_barrier.h
Normal file
83
test/darwin/pthread_barrier.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Aleksey Demakov
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PTHREAD_BARRIER_H
|
||||
#define PTHREAD_BARRIER_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
#define PTHREAD_BARRIER_SERIAL_THREAD (1)
|
||||
#endif
|
||||
|
||||
#if !defined(PTHREAD_PROCESS_PRIVATE)
|
||||
#define PTHREAD_PROCESS_PRIVATE (42)
|
||||
#endif
|
||||
#if !defined(PTHREAD_PROCESS_SHARED)
|
||||
#define PTHREAD_PROCESS_SHARED (43)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
pthread_mutexattr_t mattr;
|
||||
pthread_condattr_t cattr;
|
||||
} pthread_barrierattr_t;
|
||||
|
||||
typedef struct {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
unsigned int limit;
|
||||
unsigned int count;
|
||||
unsigned int phase;
|
||||
} pthread_barrier_t;
|
||||
|
||||
int pthread_barrierattr_init(pthread_barrierattr_t *attr);
|
||||
int pthread_barrierattr_destroy(pthread_barrierattr_t *attr);
|
||||
|
||||
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr,
|
||||
int *__restrict pshared);
|
||||
int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared);
|
||||
|
||||
int pthread_barrier_init(pthread_barrier_t *__restrict barrier,
|
||||
const pthread_barrierattr_t *__restrict attr,
|
||||
unsigned int count);
|
||||
int pthread_barrier_destroy(pthread_barrier_t *barrier);
|
||||
|
||||
int pthread_barrier_wait(pthread_barrier_t *barrier);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#endif /* PTHREAD_BARRIER_H */
|
20
test/main.cc
20
test/main.cc
@ -182,17 +182,19 @@ int main(int argc, char *const argv[]) {
|
||||
params.datalen_max = datalen_max;
|
||||
continue;
|
||||
}
|
||||
if (config::parse_option(argc, argv, narg, "size-lower", params.size_lower,
|
||||
mdbx_limits_dbsize_min(params.pagesize),
|
||||
mdbx_limits_dbsize_max(params.pagesize)))
|
||||
if (config::parse_option_intptr(argc, argv, narg, "size-lower",
|
||||
params.size_lower,
|
||||
mdbx_limits_dbsize_min(params.pagesize),
|
||||
mdbx_limits_dbsize_max(params.pagesize)))
|
||||
continue;
|
||||
if (config::parse_option(argc, argv, narg, "size-upper", params.size_upper,
|
||||
mdbx_limits_dbsize_min(params.pagesize),
|
||||
mdbx_limits_dbsize_max(params.pagesize)))
|
||||
if (config::parse_option_intptr(argc, argv, narg, "size-upper",
|
||||
params.size_upper,
|
||||
mdbx_limits_dbsize_min(params.pagesize),
|
||||
mdbx_limits_dbsize_max(params.pagesize)))
|
||||
continue;
|
||||
if (config::parse_option(argc, argv, narg, "size", params.size_now,
|
||||
mdbx_limits_dbsize_min(params.pagesize),
|
||||
mdbx_limits_dbsize_max(params.pagesize)))
|
||||
if (config::parse_option_intptr(argc, argv, narg, "size", params.size_now,
|
||||
mdbx_limits_dbsize_min(params.pagesize),
|
||||
mdbx_limits_dbsize_max(params.pagesize)))
|
||||
continue;
|
||||
if (config::parse_option(
|
||||
argc, argv, narg, "shrink-threshold", params.shrink_threshold, 0,
|
||||
|
@ -21,6 +21,10 @@
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "darwin/pthread_barrier.c"
|
||||
#endif
|
||||
|
||||
struct shared_t {
|
||||
pthread_barrier_t barrier;
|
||||
pthread_mutex_t mutex;
|
||||
|
25
test/ttl.cc
25
test/ttl.cc
@ -53,11 +53,26 @@ bool testcase_ttl::run() {
|
||||
*/
|
||||
|
||||
/* LY: для параметризации используем подходящие параметры, которые не имеют
|
||||
* здесь смысла в первоначальном значении */
|
||||
const unsigned window_max =
|
||||
(config.params.batch_read > 999) ? config.params.batch_read : 1000;
|
||||
const unsigned count_max =
|
||||
(config.params.batch_write > 999) ? config.params.batch_write : 1000;
|
||||
* здесь смысла в первоначальном значении. */
|
||||
const unsigned window_max_lower =
|
||||
#ifdef __APPLE__
|
||||
333;
|
||||
#else
|
||||
999;
|
||||
#endif
|
||||
const unsigned count_max_lower =
|
||||
#ifdef __APPLE__
|
||||
333;
|
||||
#else
|
||||
999;
|
||||
#endif
|
||||
|
||||
const unsigned window_max = (config.params.batch_read > window_max_lower)
|
||||
? config.params.batch_read
|
||||
: window_max_lower;
|
||||
const unsigned count_max = (config.params.batch_write > count_max_lower)
|
||||
? config.params.batch_write
|
||||
: count_max_lower;
|
||||
log_info("ttl: using `batch_read` value %u for window_max", window_max);
|
||||
log_info("ttl: using `batch_write` value %u for count_max", count_max);
|
||||
|
||||
|
@ -17,6 +17,9 @@
|
||||
#if defined(HAVE_IEEE754_H) || __has_include(<ieee754.h>)
|
||||
#include <ieee754.h>
|
||||
#endif
|
||||
#if defined(__APPLE__) || defined(__MACH__)
|
||||
#include <mach/mach_time.h>
|
||||
#endif /* defined(__APPLE__) || defined(__MACH__) */
|
||||
|
||||
std::string format(const char *fmt, ...) {
|
||||
va_list ap, ones;
|
||||
|
10
test/utils.h
10
test/utils.h
@ -247,18 +247,20 @@ struct simple_checksum {
|
||||
|
||||
simple_checksum() : value(0) {}
|
||||
|
||||
void push(uint32_t data) {
|
||||
void push(const uint32_t &data) {
|
||||
value += data * UINT64_C(9386433910765580089) + 1;
|
||||
value ^= value >> 41;
|
||||
value *= UINT64_C(0xBD9CACC22C6E9571);
|
||||
}
|
||||
|
||||
void push(uint64_t data) {
|
||||
void push(const uint64_t &data) {
|
||||
push((uint32_t)data);
|
||||
push((uint32_t)(data >> 32));
|
||||
}
|
||||
|
||||
void push(bool data) { push(data ? UINT32_C(0x780E) : UINT32_C(0xFA18E)); }
|
||||
void push(const bool data) {
|
||||
push(data ? UINT32_C(0x780E) : UINT32_C(0xFA18E));
|
||||
}
|
||||
|
||||
void push(const void *ptr, size_t bytes) {
|
||||
const uint8_t *data = (const uint8_t *)ptr;
|
||||
@ -271,7 +273,7 @@ struct simple_checksum {
|
||||
void push(const std::string &str) { push(str.data(), str.size()); }
|
||||
|
||||
void push(unsigned salt, const MDBX_val &val) {
|
||||
push(val.iov_len);
|
||||
push(unsigned(val.iov_len));
|
||||
push(salt);
|
||||
push(val.iov_base, val.iov_len);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user