From 68171d5f5d05275c925651ef73f671f3662c5471 Mon Sep 17 00:00:00 2001 From: Leo Yuriev Date: Tue, 13 Oct 2015 15:46:59 +0300 Subject: [PATCH] lmdb: provide both interfaces - advanced 'mdbx' and original 'lmdb'. --- .gitignore | 10 +- Makefile | 151 ++++++++++++--------- lmdb.h | 65 +++++++-- mdb.c | 379 ++++++++++++++++++++++++++++++++--------------------- mdb_chk.c | 174 ++++++++++++------------ mdb_copy.c | 2 +- mdb_dump.c | 2 +- mdb_load.c | 2 +- mdb_stat.c | 58 ++++---- mdbx.h | 123 +++++++++++++++++ midl.c | 29 ++-- midl.h | 30 +++-- mtest0.c | 2 +- mtest1.c | 2 +- mtest2.c | 2 +- mtest3.c | 2 +- mtest4.c | 2 +- mtest5.c | 2 +- mtest6.c | 2 +- reopen.h | 7 +- wbench.c | 2 +- 21 files changed, 664 insertions(+), 384 deletions(-) create mode 100644 mdbx.h diff --git a/.gitignore b/.gitignore index b584fe2a..2dbfc846 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,11 @@ mtest[0123456] wbench testdb -mdb_copy -mdb_stat -mdb_dump -mdb_load -mdb_chk +mdbx_copy +mdbx_stat +mdbx_dump +mdbx_load +mdbx_chk *.lo *.[ao] *.so diff --git a/Makefile b/Makefile index 4dc0eae1..ff4e4209 100644 --- a/Makefile +++ b/Makefile @@ -20,17 +20,26 @@ CC ?= gcc CFLAGS ?= -O2 -g -Wall -Werror -Wno-unused-parameter CFLAGS += -pthread -LDLIBS = -Wl,--no-as-needed -lrt prefix ?= /usr/local ######################################################################## -IHDRS = lmdb.h -ILIBS = liblmdb.a liblmdb.so -IPROGS = mdb_stat mdb_copy mdb_dump mdb_load mdb_chk -IDOCS = mdb_stat.1 mdb_copy.1 mdb_dump.1 mdb_load.1 -PROGS = $(IPROGS) mtest0 mtest1 mtest2 mtest3 mtest4 mtest5 mtest6 wbench -all: $(ILIBS) $(PROGS) +IHDRS := lmdb.h mdbx.h +ILIBS := libmdbx.a libmdbx.so +IPROGS := mdbx_stat mdbx_copy mdbx_dump mdbx_load mdbx_chk +IDOCS := mdb_stat.1 mdb_copy.1 mdb_dump.1 mdb_load.1 +PROGS := $(IPROGS) mtest0 mtest1 mtest2 mtest3 mtest4 mtest5 mtest6 wbench + +SRC_LMDB := mdb.c midl.c lmdb.h midl.h +SRC_MDBX := $(SRC_LMDB) mdbx.h + +.PHONY: mdbx lmdb all install clean test coverage + +all: $(ILIBS) $(IPROGS) + +mdbx: libmdbx.a libmdbx.so + +lmdb: liblmdb.a liblmdb.so install: $(ILIBS) $(IPROGS) $(IHDRS) mkdir -p $(DESTDIR)$(prefix)/bin @@ -43,73 +52,95 @@ install: $(ILIBS) $(IPROGS) $(IHDRS) for f in $(IDOCS); do cp $$f $(DESTDIR)$(prefix)/man/man1; done clean: - rm -rf $(PROGS) *.[ao] *.[ls]o *~ testdb/* + rm -rf $(PROGS) @* *.[ao] *.[ls]o *~ testdb/* *.gcov -test: all +test: mdbx $(PROGS) [ -d testdb ] || mkdir testdb && rm -f testdb/* \ - && echo "*** LMDB-TEST-0" && ./mtest0 && ./mdb_chk -v testdb \ - && echo "*** LMDB-TEST-1" && ./mtest1 && ./mdb_chk -v testdb \ - && echo "*** LMDB-TEST-2" && ./mtest2 && ./mdb_chk -v testdb \ - && echo "*** LMDB-TEST-3" && ./mtest3 && ./mdb_chk -v testdb \ - && echo "*** LMDB-TEST-4" && ./mtest4 && ./mdb_chk -v testdb \ - && echo "*** LMDB-TEST-5" && ./mtest5 && ./mdb_chk -v testdb \ - && echo "*** LMDB-TEST-6" && ./mtest6 && ./mdb_chk -v testdb \ + && echo "*** LMDB-TEST-0" && ./mtest0 && ./mdbx_chk -v testdb \ + && echo "*** LMDB-TEST-1" && ./mtest1 && ./mdbx_chk -v testdb \ + && echo "*** LMDB-TEST-2" && ./mtest2 && ./mdbx_chk -v testdb \ + && echo "*** LMDB-TEST-3" && ./mtest3 && ./mdbx_chk -v testdb \ + && echo "*** LMDB-TEST-4" && ./mtest4 && ./mdbx_chk -v testdb \ + && echo "*** LMDB-TEST-5" && ./mtest5 && ./mdbx_chk -v testdb \ + && echo "*** LMDB-TEST-6" && ./mtest6 && ./mdbx_chk -v testdb \ && echo "*** LMDB-TESTs - all done" -liblmdb.a: mdb.o midl.o - $(AR) rs $@ mdb.o midl.o +libmdbx.a: mdbx.o + $(AR) rs $@ $^ -liblmdb.so: mdb.lo midl.lo -# $(CC) $(LDFLAGS) -pthread -shared -Wl,-Bsymbolic -o $@ mdb.o midl.o $(SOLIBS) - $(CC) $(LDFLAGS) -pthread -shared -o $@ mdb.lo midl.lo $(SOLIBS) +libmdbx.so: mdbx.lo + $(CC) $(CFLAGS) $(LDFLAGS) -pthread -shared -o $@ $^ -mdb_stat: mdb_stat.o liblmdb.a -mdb_copy: mdb_copy.o liblmdb.a -mdb_dump: mdb_dump.o liblmdb.a -mdb_load: mdb_load.o liblmdb.a -mdb_chk: mdb_chk.o liblmdb.a -mtest0: mtest0.o liblmdb.a -mtest1: mtest1.o liblmdb.a -mtest2: mtest2.o liblmdb.a -mtest3: mtest3.o liblmdb.a -mtest4: mtest4.o liblmdb.a -mtest5: mtest5.o liblmdb.a -mtest6: mtest6.o liblmdb.a -wbench: wbench.o liblmdb.a +liblmdb.a: lmdb.o + $(AR) rs $@ $^ -mdb.o: mdb.c lmdb.h midl.h - $(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c +liblmdb.so: lmdb.lo + $(CC) $(CFLAGS) $(LDFLAGS) -pthread -shared -o $@ $^ -midl.o: midl.c midl.h - $(CC) $(CFLAGS) $(CPPFLAGS) -c midl.c +mdbx_stat: mdb_stat.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -mdb.lo: mdb.c lmdb.h midl.h - $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c mdb.c -o $@ +mdbx_copy: mdb_copy.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -midl.lo: midl.c midl.h - $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c midl.c -o $@ +mdbx_dump: mdb_dump.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +mdbx_load: mdb_load.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +mdbx_chk: mdb_chk.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -lrt + +mtest0: mtest0.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +mtest1: mtest1.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +mtest2: mtest2.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +mtest3: mtest3.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +mtest4: mtest4.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +mtest5: mtest5.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +mtest6: mtest6.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +wbench: wbench.o mdbx.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -lrt + +mdbx.o: $(SRC_MDBX) + $(CC) $(CFLAGS) -include mdbx.h -c mdb.c -o $@ + +mdbx.lo: $(SRC_MDBX) + $(CC) $(CFLAGS) -include mdbx.h -fPIC -c mdb.c -o $@ + +lmdb.o: $(SRC_LMDB) + $(CC) $(CFLAGS) -c mdb.c -o $@ + +lmdb.lo: $(SRC_LMDB) + $(CC) $(CFLAGS) -fPIC -c mdb.c -o $@ %: %.o - $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ + $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ -%.o: %.c lmdb.h - $(CC) $(CFLAGS) $(CPPFLAGS) -c $< +%.o: %.c lmdb.h mdbx.h + $(CC) $(CFLAGS) -c $< COV_FLAGS=-fprofile-arcs -ftest-coverage -COV_OBJS=xmdb.o xmidl.o -coverage: xmtest - for i in mtest*.c [0-9]*.c; do j=`basename \$$i .c`; $(MAKE) $$j.o; \ - gcc -o x$$j $$j.o $(COV_OBJS) -pthread $(COV_FLAGS); \ - rm -rf testdb; mkdir testdb; ./x$$j; done - gcov xmdb.c - gcov xmidl.c +@gcov-mdb.o: $(SRC_MDBX) + $(CC) $(CFLAGS) $(COV_FLAGS) -O0 -include mdbx.h -c mdb.c -o $@ -xmtest: mtest.o xmdb.o xmidl.o - gcc -o xmtest mtest.o xmdb.o xmidl.o -pthread $(COV_FLAGS) - -xmdb.o: mdb.c lmdb.h midl.h - $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -O0 $(COV_FLAGS) -c mdb.c -o $@ - -xmidl.o: midl.c midl.h - $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -O0 $(COV_FLAGS) -c midl.c -o $@ +coverage: @gcov-mdb.o + for t in mtest*.c; do x=`basename \$$t .c`; $(MAKE) $$x.o; \ + gcc -o @gcov-$$x $$x.o $^ -pthread $(COV_FLAGS); \ + rm -rf testdb; mkdir testdb; ./@gcov-$$x; done + gcov @gcov-mdb diff --git a/lmdb.h b/lmdb.h index 74ab55b2..040888e3 100644 --- a/lmdb.h +++ b/lmdb.h @@ -155,6 +155,10 @@ #ifndef _LMDB_H_ #define _LMDB_H_ +#ifndef MDBX_MODE_ENABLED +# define MDBX_MODE_ENABLED 0 +#endif /* MDBX_MODE_ENABLED */ + #include #include #include @@ -284,11 +288,15 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel #define MDB_NORDAHEAD 0x800000 /** don't initialize malloc'd memory before writing to datafile */ #define MDB_NOMEMINIT 0x1000000 + +#if MDBX_MODE_ENABLED /** aim to coalesce FreeDB records */ #define MDB_COALESCE 0x2000000 /** LIFO policy for reclaiming FreeDB records */ #define MDB_LIFORECLAIM 0x4000000 - /** make a steady-sync only on close and explicit env-sync */ +#endif /* MDBX_MODE_ENABLED */ + +/** make a steady-sync only on close and explicit env-sync */ #define MDB_UTTERLY_NOSYNC (MDB_NOSYNC|MDB_MAPASYNC) /** @} */ @@ -446,18 +454,31 @@ typedef struct MDB_stat { size_t ms_entries; /**< Number of data items */ } MDB_stat; +typedef struct MDBX_stat { + MDB_stat base; +#if MDBX_MODE_ENABLED + /* LY: TODO */ +#endif /* MDBX_MODE_ENABLED */ +} MDBX_stat; + /** @brief Information about the environment */ typedef struct MDB_envinfo { void *me_mapaddr; /**< Address of map, if fixed */ size_t me_mapsize; /**< Size of the data memory map */ size_t me_last_pgno; /**< ID of the last used page */ size_t me_last_txnid; /**< ID of the last committed transaction */ - size_t me_tail_txnid; /**< ID of the last reader transaction */ unsigned me_maxreaders; /**< max reader slots in the environment */ unsigned me_numreaders; /**< max reader slots used in the environment */ +} MDB_envinfo; + +typedef struct MDBX_envinfo { + MDB_envinfo base; +#if MDBX_MODE_ENABLED + size_t me_tail_txnid; /**< ID of the last reader transaction */ size_t me_meta1_txnid, me_meta1_sign; size_t me_meta2_txnid, me_meta2_sign; -} MDB_envinfo; +#endif /* MDBX_MODE_ENABLED */ +} MDBX_envinfo; /** @brief Return the LMDB library version information. * @@ -618,7 +639,9 @@ int mdb_env_create(MDB_env **env); * */ int mdb_env_open(MDB_env *env, const char *path, unsigned flags, mode_t mode); -int mdb_env_open_ex(MDB_env *env, const char *path, unsigned flags, mode_t mode, int *exclusive); +#if MDBX_MODE_ENABLED +int mdbx_env_open_ex(MDB_env *env, const char *path, unsigned flags, mode_t mode, int *exclusive); +#endif /* MDBX_MODE_ENABLED */ /** @brief Copy an LMDB environment to the specified path. * * This function may be used to make a backup of an existing environment. @@ -700,6 +723,9 @@ int mdb_env_copyfd2(MDB_env *env, mdb_filehandle_t fd, unsigned flags); * where the statistics will be copied */ int mdb_env_stat(MDB_env *env, MDB_stat *stat); +#if MDBX_MODE_ENABLED +int mdbx_env_stat(MDB_env *env, MDBX_stat *stat, size_t bytes); +#endif /* MDBX_MODE_ENABLED */ /** @brief Return information about the LMDB environment. * @@ -708,6 +734,9 @@ int mdb_env_stat(MDB_env *env, MDB_stat *stat); * where the information will be copied */ int mdb_env_info(MDB_env *env, MDB_envinfo *info); +#if MDBX_MODE_ENABLED +int mdbx_env_info(MDB_env *env, MDBX_envinfo *info, size_t bytes); +#endif /* MDBX_MODE_ENABLED */ /** @brief Flush the data buffers to disk. * @@ -744,7 +773,9 @@ int mdb_env_sync(MDB_env *env, int force); * checkpoint (meta-page update) will rolledback for consistency guarantee. */ void mdb_env_close(MDB_env *env); -void mdb_env_close_ex(MDB_env *env, int dont_sync); +#if MDBX_MODE_ENABLED +void mdbx_env_close_ex(MDB_env *env, int dont_sync); +#endif /* MDBX_MODE_ENABLED */ /** @brief Set environment flags. * @@ -927,6 +958,7 @@ typedef void MDB_assert_func(MDB_env *env, const char *msg, */ int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func); +#if MDBX_MODE_ENABLED /** @brief Set threshold to force flush the data buffers to disk, * even of #MDB_NOSYNC, #MDB_NOMETASYNC and #MDB_MAPASYNC flags * in the environment. @@ -944,7 +976,8 @@ int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func); * when a synchronous flush would be made. * @return A non-zero error value on failure and 0 on success. */ -int mdb_env_set_syncbytes(MDB_env *env, size_t bytes); +int mdbx_env_set_syncbytes(MDB_env *env, size_t bytes); +#endif /* MDBX_MODE_ENABLED */ /** @brief Create a transaction for use with the environment. * @@ -1149,6 +1182,9 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned flags, MDB_dbi *dbi); * */ int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *stat); +#if MDBX_MODE_ENABLED +int mdbx_stat(MDB_txn *txn, MDB_dbi dbi, MDBX_stat *stat, size_t bytes); +#endif /* MDBX_MODE_ENABLED */ /** @brief Retrieve the DB flags for a database handle. * @@ -1597,6 +1633,7 @@ int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx); */ int mdb_reader_check(MDB_env *env, int *dead); +#if MDBX_MODE_ENABLED /** @brief Returns a lag of the reading. * * Returns an information for estimate how much given read-only @@ -1606,7 +1643,7 @@ int mdb_reader_check(MDB_env *env, int *dead); * @param[out] percent Percentage of page allocation in the database. * @return Number of transactions committed after the given was started for read, or -1 on failure. */ -int mdb_txn_straggler(MDB_txn *txnm, int *percent); +int mdbx_txn_straggler(MDB_txn *txnm, int *percent); /** @brief A callback function for killing a laggard readers, * called in case of MDB_MAP_FULL error. @@ -1630,7 +1667,7 @@ typedef int (MDB_oom_func)(MDB_env *env, int pid, void* thread_id, size_t txn, u * @param[in] env An environment handle returned by #mdb_env_create(). * @param[in] oomfunc A #MDB_oom_func function or NULL to disable. */ -void mdb_env_set_oomfunc(MDB_env *env, MDB_oom_func *oom_func); +void mdbx_env_set_oomfunc(MDB_env *env, MDB_oom_func *oom_func); /** @brief Get the current oom_func callback. * @@ -1640,9 +1677,11 @@ void mdb_env_set_oomfunc(MDB_env *env, MDB_oom_func *oom_func); * @param[in] env An environment handle returned by #mdb_env_create(). * @return A #MDB_oom_func function or NULL if disabled. */ -MDB_oom_func* mdb_env_get_oomfunc(MDB_env *env); +MDB_oom_func* mdbx_env_get_oomfunc(MDB_env *env); +#endif /* MDBX_MODE_ENABLED */ /** @} */ +#if MDBX_MODE_ENABLED #define MDB_DBG_ASSERT 1 #define MDB_DBG_PRINT 2 #define MDB_DBG_TRACE 4 @@ -1656,12 +1695,13 @@ MDB_oom_func* mdb_env_get_oomfunc(MDB_env *env); typedef void MDB_debug_func(int type, const char *function, int line, const char *msg, va_list args); -int mdb_setup_debug(int flags, MDB_debug_func* logger, long edge_txn); +int mdbx_setup_debug(int flags, MDB_debug_func* logger, long edge_txn); typedef int MDB_pgvisitor_func(size_t pgno, unsigned pgnumber, void* ctx, const char* dbi, const char *type, int nentries, int payload_bytes, int header_bytes, int unused_bytes); -int mdb_env_pgwalk(MDB_txn *txn, MDB_pgvisitor_func* visitor, void* ctx); +int mdbx_env_pgwalk(MDB_txn *txn, MDB_pgvisitor_func* visitor, void* ctx); +#endif /* MDBX_MODE_ENABLED */ char* mdb_dkey(MDB_val *key, char *buf); @@ -1669,7 +1709,8 @@ char* mdb_dkey(MDB_val *key, char *buf); } #endif /** @page tools LMDB Command Line Tools - The following describes the command line tools that are available for LMDB. + The following describes the command line tools that are available for LMDBX. + \li \ref mdb_chk_1 \li \ref mdb_copy_1 \li \ref mdb_dump_1 \li \ref mdb_load_1 diff --git a/mdb.c b/mdb.c index 1b19574f..337bb6aa 100644 --- a/mdb.c +++ b/mdb.c @@ -37,8 +37,8 @@ # define MDB_DEBUG 0 #endif -#include "reopen.h" -#include "barriers.h" +#include "./reopen.h" +#include "./barriers.h" #include #include @@ -96,8 +96,19 @@ # define MISALIGNED_OK 1 #endif -#include "lmdb.h" -#include "midl.h" +#include "./lmdb.h" +#include "./midl.h" + +#if ! MDBX_MODE_ENABLED +# define MDB_COALESCE 0 +# define MDB_LIFORECLAIM 0 +# define MDB_DBG_ASSERT 0 +# define MDB_DBG_PRINT 0 +# define MDB_DBG_TRACE 0 +# define MDB_DBG_EXTRA 0 +# define MDB_DBG_AUDIT 0 +# define MDB_DBG_EDGE 0 +#endif #if (BYTE_ORDER == LITTLE_ENDIAN) == (BYTE_ORDER == BIG_ENDIAN) # error "Unknown or unsupported endianness (BYTE_ORDER)" @@ -105,17 +116,6 @@ # error "Two's complement, reasonably sized integer types, please" #endif -#ifdef __GNUC__ -/** Put infrequently used env functions in separate section */ -# ifdef __APPLE__ -# define ESECT __attribute__ ((section("__TEXT,text_env"))) -# else -# define ESECT __attribute__ ((section("text_env"))) -# endif -#else -# define ESECT -#endif - /** @defgroup internal LMDB Internals * @{ */ @@ -955,7 +955,9 @@ struct MDB_env { #endif uint64_t me_sync_pending; /**< Total dirty/commited bytes since the last mdb_env_sync() */ uint64_t me_sync_threshold; /**< Treshold of above to force synchronous flush */ +#if MDBX_MODE_ENABLED MDB_oom_func *me_oom_func; /**< Callback for kicking laggard readers */ +#endif #ifdef USE_VALGRIND int me_valgrind_handle; #endif @@ -1067,7 +1069,7 @@ static MDB_cmp_func mdb_cmp_memn, mdb_cmp_memnr, mdb_cmp_int_ai, mdb_cmp_int_a2, /** @endcond */ /** Return the library version info. */ -char * ESECT +char * __cold mdb_version(int *major, int *minor, int *patch) { if (major) *major = MDB_VERSION_MAJOR; @@ -1100,7 +1102,7 @@ static char *const mdb_errstr[] = { "MDB_BAD_DBI: The specified DBI handle was closed/changed unexpectedly", }; -char * ESECT +char * __cold mdb_strerror(int err) { int i; @@ -1115,6 +1117,8 @@ mdb_strerror(int err) return strerror(err); } +#if MDBX_MODE_ENABLED + int mdb_runtime_flags = MDB_DBG_PRINT #if MDB_DEBUG | MDB_DBG_ASSERT @@ -1132,12 +1136,17 @@ int mdb_runtime_flags = MDB_DBG_PRINT static MDB_debug_func *mdb_debug_logger; +#else /* MDBX_MODE_ENABLED */ +# define mdb_runtime_flags 0 +# define mdb_debug_logger ((void (*)(int, ...)) NULL) +#endif /* ! MDBX_MODE_ENABLED */ + #if MDB_DEBUG static txnid_t mdb_debug_edge; static void mdb_debug_log(int type, const char *function, int line, const char *fmt, ...); - static void ESECT + static void __cold mdb_assert_fail(MDB_env *env, const char *msg, const char *func, int line) { @@ -1168,8 +1177,9 @@ static MDB_debug_func *mdb_debug_logger; __assert_fail(msg, __FILE__, line, func) #endif /* MDB_DEBUG */ -int ESECT -mdb_setup_debug(int flags, MDB_debug_func* logger, long edge_txn) { +#if MDBX_MODE_ENABLED +int __cold +mdbx_setup_debug(int flags, MDB_debug_func* logger, long edge_txn) { unsigned ret = mdb_runtime_flags; if (flags != (int) MDB_DBG_DNT) mdb_runtime_flags = flags; @@ -1181,8 +1191,9 @@ mdb_setup_debug(int flags, MDB_debug_func* logger, long edge_txn) { #endif return ret; } +#endif /* MDBX_MODE_ENABLED */ -static void ESECT +static void __cold mdb_debug_log(int type, const char *function, int line, const char *fmt, ...) { @@ -1881,17 +1892,14 @@ mdb_find_oldest(MDB_env *env, int *laggard) return oldest; } -static int ESECT +static int __cold mdb_oomkick(MDB_env *env, txnid_t oldest) { int retry; txnid_t snap; for(retry = 0; ; ++retry) { - MDB_reader *r; - pthread_t tid; - pid_t pid; - int rc, reader; + int reader; if (mdb_reader_check(env, NULL)) break; @@ -1903,28 +1911,39 @@ mdb_oomkick(MDB_env *env, txnid_t oldest) if (reader < 0) return 0; - if (!env->me_oom_func) - break; +#if MDBX_MODE_ENABLED + { + MDB_reader *r; + pthread_t tid; + pid_t pid; + int rc; - r = &env->me_txns->mti_readers[ reader ]; - pid = r->mr_pid; - tid = r->mr_tid; - if (r->mr_txnid != oldest || pid <= 0) - continue; + if (!env->me_oom_func) + break; - rc = env->me_oom_func(env, pid, (void*) tid, oldest, - mdb_meta_head_w(env)->mm_txnid - oldest, retry); - if (rc < 0) - break; + r = &env->me_txns->mti_readers[ reader ]; + pid = r->mr_pid; + tid = r->mr_tid; + if (r->mr_txnid != oldest || pid <= 0) + continue; - if (rc) { - r->mr_txnid = (txnid_t)-1L; - if (rc > 1) { - r->mr_tid = 0; - r->mr_pid = 0; - mdb_coherent_barrier(); + rc = env->me_oom_func(env, pid, (void*) tid, oldest, + mdb_meta_head_w(env)->mm_txnid - oldest, retry); + if (rc < 0) + break; + + if (rc) { + r->mr_txnid = (txnid_t)-1L; + if (rc > 1) { + r->mr_tid = 0; + r->mr_pid = 0; + mdb_coherent_barrier(); + } } } +#else + break; +#endif /* MDBX_MODE_ENABLED */ } snap = mdb_find_oldest(env, NULL); @@ -2958,7 +2977,7 @@ mdb_dbis_update(MDB_txn *txn, int keep) } int -mdb_txn_straggler(MDB_txn *txn, int *percent) +mdbx_txn_straggler(MDB_txn *txn, int *percent) { MDB_env *env; MDB_meta *meta; @@ -3777,7 +3796,7 @@ fail: return rc; } -int ESECT +int __cold mdb_env_set_syncbytes(MDB_env *env, size_t bytes) { env->me_sync_threshold = bytes; return env->me_map ? mdb_env_sync(env, 0) : 0; @@ -3789,7 +3808,7 @@ mdb_env_set_syncbytes(MDB_env *env, size_t bytes) { * @param[out] meta address of where to store the meta information * @return 0 on success, non-zero on failure. */ -static int ESECT +static int __cold mdb_env_read_header(MDB_env *env, MDB_meta *meta) { MDB_metabuf pbuf; @@ -3848,7 +3867,7 @@ mdb_env_read_header(MDB_env *env, MDB_meta *meta) } /** Fill in most of the zeroed #MDB_meta for an empty database environment */ -static void ESECT +static void __cold mdb_env_init_meta0(MDB_env *env, MDB_meta *meta) { meta->mm_magic = MDB_MAGIC; @@ -3868,7 +3887,7 @@ mdb_env_init_meta0(MDB_env *env, MDB_meta *meta) * @param[in] meta the #MDB_meta to write * @return 0 on success, non-zero on failure. */ -static int ESECT +static int __cold mdb_env_init_meta(MDB_env *env, MDB_meta *meta) { MDB_page *p, *q; @@ -4063,7 +4082,7 @@ fail: return rc; } -int ESECT +int __cold mdb_env_create(MDB_env **env) { MDB_env *e; @@ -4083,7 +4102,7 @@ mdb_env_create(MDB_env **env) return MDB_SUCCESS; } -static int ESECT +static int __cold mdb_env_map(MDB_env *env, void *addr) { unsigned flags = env->me_flags; @@ -4133,7 +4152,7 @@ mdb_env_map(MDB_env *env, void *addr) return MDB_SUCCESS; } -int ESECT +int __cold mdb_env_set_mapsize(MDB_env *env, size_t size) { /* If env is already open, caller is responsible for making @@ -4171,7 +4190,7 @@ mdb_env_set_mapsize(MDB_env *env, size_t size) return MDB_SUCCESS; } -int ESECT +int __cold mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs) { if (env->me_map) @@ -4180,7 +4199,7 @@ mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs) return MDB_SUCCESS; } -int ESECT +int __cold mdb_env_set_maxreaders(MDB_env *env, unsigned readers) { if (env->me_map || readers < 1) @@ -4189,7 +4208,7 @@ mdb_env_set_maxreaders(MDB_env *env, unsigned readers) return MDB_SUCCESS; } -int ESECT +int __cold mdb_env_get_maxreaders(MDB_env *env, unsigned *readers) { if (!env || !readers) @@ -4198,7 +4217,7 @@ mdb_env_get_maxreaders(MDB_env *env, unsigned *readers) return MDB_SUCCESS; } -static int ESECT +static int __cold mdb_fsize(HANDLE fd, size_t *size) { struct stat st; @@ -4212,7 +4231,7 @@ mdb_fsize(HANDLE fd, size_t *size) /** Further setup required for opening an LMDB environment */ -static int ESECT +static int __cold mdb_env_open2(MDB_env *env, MDB_meta *meta) { unsigned flags = env->me_flags; @@ -4319,7 +4338,7 @@ mdb_env_reader_dest(void *ptr) } /** Downgrade the exclusive lock on the region back to shared */ -static int ESECT +static int __cold mdb_env_share_locks(MDB_env *env, int *excl, MDB_meta *meta) { struct flock lock_info; @@ -4341,7 +4360,7 @@ mdb_env_share_locks(MDB_env *env, int *excl, MDB_meta *meta) /** Try to get exclusive lock, otherwise shared. * Maintain *excl = -1: no/unknown lock, 0: shared, 1: exclusive. */ -static int ESECT +static int __cold mdb_env_excl_lock(MDB_env *env, int *excl) { int rc = 0; @@ -4436,7 +4455,7 @@ mdb_hash_val(MDB_val *val, mdb_hash_t hval) */ static const char mdb_a85[]= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"; -static void ESECT +static void __cold mdb_pack85(unsigned long l, char *out) { int i; @@ -4447,7 +4466,7 @@ mdb_pack85(unsigned long l, char *out) } } -static void ESECT +static void __cold mdb_hash_enc(MDB_val *val, char *encbuf) { mdb_hash_t h = mdb_hash_val(val, MDB_HASH_INIT); @@ -4465,7 +4484,7 @@ mdb_hash_enc(MDB_val *val, char *encbuf) * @param[in,out] excl In -1, out lock type: -1 none, 0 shared, 1 exclusive * @return 0 on success, non-zero on failure. */ -static int ESECT +static int __cold mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl) { int fdflags; @@ -4576,14 +4595,11 @@ fail: # error "Persistent DB flags & env flags overlap, but both go in mm_flags" #endif -int ESECT -mdb_env_open(MDB_env *env, const char *path, unsigned flags, mode_t mode) -{ - return mdb_env_open_ex(env, path, flags, mode, NULL); -} - -int ESECT -mdb_env_open_ex(MDB_env *env, const char *path, unsigned flags, mode_t mode, int *exclusive) +#if !MDBX_MODE_ENABLED +static +#endif /* !MDBX_MODE_ENABLED*/ +int __cold +mdbx_env_open_ex(MDB_env *env, const char *path, unsigned flags, mode_t mode, int *exclusive) { int oflags, rc, len, excl = -1; char *lpath, *dpath; @@ -4720,8 +4736,14 @@ leave: return rc; } +int __cold +mdb_env_open(MDB_env *env, const char *path, unsigned flags, mode_t mode) +{ + return mdbx_env_open_ex(env, path, flags, mode, NULL); +} + /** Destroy resources from mdb_env_open(), clear our readers & DBIs */ -static void ESECT +static void __cold mdb_env_close0(MDB_env *env) { int i; @@ -4791,14 +4813,11 @@ mdb_env_close0(MDB_env *env) env->me_flags &= ~(MDB_ENV_ACTIVE|MDB_ENV_TXKEY); } -void ESECT -mdb_env_close(MDB_env *env) -{ - mdb_env_close_ex(env, 0); -} - -void ESECT -mdb_env_close_ex(MDB_env *env, int dont_sync) +#if !MDBX_MODE_ENABLED +static +#endif /* !MDBX_MODE_ENABLED*/ +void __cold +mdbx_env_close_ex(MDB_env *env, int dont_sync) { MDB_page *dp; @@ -4819,6 +4838,12 @@ mdb_env_close_ex(MDB_env *env, int dont_sync) free(env); } +void __cold +mdb_env_close(MDB_env *env) +{ + mdbx_env_close_ex(env, 0); +} + /** Compare two items pointing at aligned unsigned int's. */ static long mdb_cmp_int_ai(const MDB_val *a, const MDB_val *b) @@ -8527,7 +8552,7 @@ typedef struct mdb_copy { } mdb_copy; /** Dedicated writer thread for compacting copy. */ -static void* ESECT +static void* __cold mdb_env_copythr(void *arg) { mdb_copy *my = arg; @@ -8585,7 +8610,7 @@ again: } /** Tell the writer thread there's a buffer ready to write */ -static int ESECT +static int __cold mdb_env_cthr_toggle(mdb_copy *my, int st) { int toggle = my->mc_toggle ^ 1; @@ -8604,7 +8629,7 @@ mdb_env_cthr_toggle(mdb_copy *my, int st) } /** Depth-first tree traversal for compacting copy. */ -static int ESECT +static int __cold mdb_env_cwalk(mdb_copy *my, pgno_t *pg, int flags) { MDB_cursor mc; @@ -8762,7 +8787,7 @@ done: } /** Copy environment with compaction. */ -static int ESECT +static int __cold mdb_env_copyfd1(MDB_env *env, HANDLE fd) { MDB_meta *mm; @@ -8858,7 +8883,7 @@ mdb_env_copyfd1(MDB_env *env, HANDLE fd) } /** Copy environment as-is. */ -static int ESECT +static int __cold mdb_env_copyfd0(MDB_env *env, HANDLE fd) { MDB_txn *txn = NULL; @@ -8949,7 +8974,7 @@ leave: return rc; } -int ESECT +int __cold mdb_env_copyfd2(MDB_env *env, HANDLE fd, unsigned flags) { if (flags & MDB_CP_COMPACT) @@ -8958,13 +8983,13 @@ mdb_env_copyfd2(MDB_env *env, HANDLE fd, unsigned flags) return mdb_env_copyfd0(env, fd); } -int ESECT +int __cold mdb_env_copyfd(MDB_env *env, HANDLE fd) { return mdb_env_copyfd2(env, fd, 0); } -int ESECT +int __cold mdb_env_copy2(MDB_env *env, const char *path, unsigned flags) { int rc, len; @@ -9019,13 +9044,13 @@ leave: return rc; } -int ESECT +int __cold mdb_env_copy(MDB_env *env, const char *path) { return mdb_env_copy2(env, path, 0); } -int ESECT +int __cold mdb_env_set_flags(MDB_env *env, unsigned flag, int onoff) { if (unlikely(flag & ~CHANGEABLE)) @@ -9037,7 +9062,7 @@ mdb_env_set_flags(MDB_env *env, unsigned flag, int onoff) return MDB_SUCCESS; } -int ESECT +int __cold mdb_env_get_flags(MDB_env *env, unsigned *arg) { if (unlikely(!env || !arg)) @@ -9047,7 +9072,7 @@ mdb_env_get_flags(MDB_env *env, unsigned *arg) return MDB_SUCCESS; } -int ESECT +int __cold mdb_env_set_userctx(MDB_env *env, void *ctx) { if (unlikely(!env)) @@ -9056,13 +9081,13 @@ mdb_env_set_userctx(MDB_env *env, void *ctx) return MDB_SUCCESS; } -void * ESECT +void * __cold mdb_env_get_userctx(MDB_env *env) { return env ? env->me_userctx : NULL; } -int ESECT +int __cold mdb_env_set_assert(MDB_env *env, MDB_assert_func *func) { if (unlikely(!env)) @@ -9073,7 +9098,7 @@ mdb_env_set_assert(MDB_env *env, MDB_assert_func *func) return MDB_SUCCESS; } -int ESECT +int __cold mdb_env_get_path(MDB_env *env, const char **arg) { if (unlikely(!env || !arg)) @@ -9083,7 +9108,7 @@ mdb_env_get_path(MDB_env *env, const char **arg) return MDB_SUCCESS; } -int ESECT +int __cold mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *arg) { if (unlikely(!env || !arg)) @@ -9099,7 +9124,7 @@ mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *arg) * @param[out] arg the address of an #MDB_stat structure to receive the stats. * @return 0, this function always succeeds. */ -static int ESECT +static int __cold mdb_stat0(MDB_env *env, MDB_db *db, MDB_stat *arg) { arg->ms_psize = env->me_psize; @@ -9112,61 +9137,99 @@ mdb_stat0(MDB_env *env, MDB_db *db, MDB_stat *arg) return MDB_SUCCESS; } -int ESECT +#if !MDBX_MODE_ENABLED +static +#endif /* !MDBX_MODE_ENABLED*/ +int __cold +mdbx_env_stat(MDB_env *env, MDBX_stat *arg, size_t bytes) +{ + MDB_meta *meta; + + if (unlikely(env == NULL || arg == NULL)) + return EINVAL; + if (unlikely(bytes != sizeof(MDBX_stat))) + return EINVAL; + + meta = mdb_meta_head_r(env); + return mdb_stat0(env, &meta->mm_dbs[MAIN_DBI], &arg->base); +} + +int __cold mdb_env_stat(MDB_env *env, MDB_stat *arg) +{ + return mdbx_env_stat(env, (MDBX_stat *) arg, sizeof(MDB_stat)); +} + +#if !MDBX_MODE_ENABLED +static +#endif /* !MDBX_MODE_ENABLED*/ +int __cold mdbx_env_info(MDB_env *env, MDBX_envinfo *arg, size_t bytes) { MDB_meta *meta; if (unlikely(env == NULL || arg == NULL)) return EINVAL; - meta = mdb_meta_head_r(env); - return mdb_stat0(env, &meta->mm_dbs[MAIN_DBI], arg); -} + if (bytes == sizeof(MDB_envinfo)) { + do { + meta = mdb_meta_head_r(env); + arg->base.me_last_txnid = meta->mm_txnid; + arg->base.me_last_pgno = meta->mm_last_pg; + arg->base.me_mapaddr = meta->mm_address; + arg->base.me_mapsize = env->me_mapsize; + arg->base.me_maxreaders = env->me_maxreaders; + arg->base.me_numreaders = env->me_txns->mti_numreaders; + } while (unlikely( arg->base.me_last_txnid != env->me_txns->mti_txnid)); +#if MDBX_MODE_ENABLED + } else if (bytes == sizeof(MDBX_envinfo)) { + MDB_meta *m1, *m2; + MDB_reader *r; + int i; -int ESECT -mdb_env_info(MDB_env *env, MDB_envinfo *arg) -{ - MDB_meta *meta, *m1, *m2; + m1 = METAPAGE_1(env); + m2 = METAPAGE_2(env); - if (unlikely(env == NULL || arg == NULL)) - return EINVAL; + do { + meta = mdb_meta_head_r(env); + arg->base.me_last_txnid = meta->mm_txnid; + arg->base.me_last_pgno = meta->mm_last_pg; + arg->me_meta1_txnid = m1->mm_txnid; + arg->me_meta1_sign = m1->mm_datasync_sign; + arg->me_meta2_txnid = m2->mm_txnid; + arg->me_meta2_sign = m2->mm_datasync_sign; + } while (unlikely( arg->base.me_last_txnid != env->me_txns->mti_txnid + || arg->me_meta1_sign != m1->mm_datasync_sign + || arg->me_meta2_sign != m2->mm_datasync_sign )); - m1 = METAPAGE_1(env); - m2 = METAPAGE_2(env); + arg->base.me_mapaddr = meta->mm_address; + arg->base.me_mapsize = env->me_mapsize; + arg->base.me_maxreaders = env->me_maxreaders; + arg->base.me_numreaders = env->me_txns->mti_numreaders; + arg->me_tail_txnid = 0; - arg->me_mapsize = env->me_mapsize; - arg->me_maxreaders = env->me_maxreaders; - arg->me_numreaders = env->me_txns->mti_numreaders; - - do { - meta = mdb_meta_head_r(env); - arg->me_meta1_txnid = m1->mm_txnid; - arg->me_meta1_sign = m1->mm_datasync_sign; - arg->me_meta2_txnid = m2->mm_txnid; - arg->me_meta2_sign = m2->mm_datasync_sign; - arg->me_last_pgno = meta->mm_last_pg; - arg->me_last_txnid = meta->mm_txnid; - } while (unlikely( meta->mm_txnid != env->me_txns->mti_txnid - || arg->me_meta1_sign != m1->mm_datasync_sign - || arg->me_meta2_sign != m2->mm_datasync_sign )); - - arg->me_mapaddr = meta->mm_address; - arg->me_tail_txnid = 0; - MDB_reader *r = env->me_txns->mti_readers; - int i; - arg->me_tail_txnid = arg->me_last_txnid; - for (i = arg->me_numreaders; --i >= 0; ) { - if (r[i].mr_pid) { - txnid_t mr = r[i].mr_txnid; - if (arg->me_tail_txnid > mr) - arg->me_tail_txnid = mr; + r = env->me_txns->mti_readers; + arg->me_tail_txnid = arg->base.me_last_txnid; + for (i = 0; i < arg->base.me_numreaders; ++i ) { + if (r[i].mr_pid) { + txnid_t mr = r[i].mr_txnid; + if (arg->me_tail_txnid > mr) + arg->me_tail_txnid = mr; + } } +#endif /* MDBX_MODE_ENABLED */ + } else { + return EINVAL; } return MDB_SUCCESS; } +int __cold +mdb_env_info(MDB_env *env, MDB_envinfo *arg) +{ + return mdbx_env_info(env, (MDBX_envinfo*) arg, sizeof(MDB_envinfo)); +} + /** Set the default comparison functions for a database. * Called immediately after a database is opened to set the defaults. * The user can then override them with #mdb_set_compare() or @@ -9293,12 +9356,18 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned flags, MDB_dbi *dbi) return rc; } -int ESECT -mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg) +#if ! MDBX_MODE_ENABLED +static +#endif +int __cold +mdbx_stat(MDB_txn *txn, MDB_dbi dbi, MDBX_stat *arg, size_t bytes) { if (!arg || unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID))) return EINVAL; + if (unlikely(bytes != sizeof(MDBX_stat))) + return EINVAL; + if (unlikely(txn->mt_flags & MDB_TXN_BLOCKED)) return MDB_BAD_TXN; @@ -9308,7 +9377,13 @@ mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg) /* Stale, must read the DB's root. cursor_init does it for us. */ mdb_cursor_init(&mc, txn, dbi, &mx); } - return mdb_stat0(txn->mt_env, &txn->mt_dbs[dbi], arg); + return mdb_stat0(txn->mt_env, &txn->mt_dbs[dbi], &arg->base); +} + +int __cold +mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg) +{ + return mdbx_stat(txn, dbi, (MDBX_stat*) arg, sizeof(MDB_stat)); } void mdb_dbi_close(MDB_env *env, MDB_dbi dbi) @@ -9511,13 +9586,13 @@ int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx) return MDB_SUCCESS; } -int ESECT +int __cold mdb_env_get_maxkeysize(MDB_env *env) { return ENV_MAXKEY(env); } -int ESECT +int __cold mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx) { unsigned i, rdrs; @@ -9560,7 +9635,7 @@ mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx) /** Insert pid into list if not already present. * return -1 if already present. */ -static int ESECT +static int __cold mdb_pid_insert(pid_t *ids, pid_t pid) { /* binary search of pid in list */ @@ -9597,7 +9672,7 @@ mdb_pid_insert(pid_t *ids, pid_t pid) return 0; } -int ESECT +int __cold mdb_reader_check(MDB_env *env, int *dead) { if (!env) @@ -9608,7 +9683,7 @@ mdb_reader_check(MDB_env *env, int *dead) } /** As #mdb_reader_check(). rlocked = . */ -static int ESECT +static int __cold mdb_reader_check0(MDB_env *env, int rlocked, int *dead) { pthread_mutex_t *rmutex = rlocked ? NULL : MDB_MUTEX(env, r); @@ -9662,7 +9737,7 @@ mdb_reader_check0(MDB_env *env, int rlocked, int *dead) return rc; } -static int ESECT +static int __cold mdb_mutex_failed(MDB_env *env, pthread_mutex_t *mutex, int rc) { #ifdef EOWNERDEAD @@ -9724,15 +9799,17 @@ static void mdb_mutex_unlock(MDB_env *env, pthread_mutex_t *mutex) { mdb_assert(env, rc == 0); } -void ESECT -mdb_env_set_oomfunc(MDB_env *env, MDB_oom_func *oomfunc) +#if MDBX_MODE_ENABLED + +void __cold +mdbx_env_set_oomfunc(MDB_env *env, MDB_oom_func *oomfunc) { if (env) env->me_oom_func = oomfunc; } -MDB_oom_func* ESECT -mdb_env_get_oomfunc(MDB_env *env) +MDB_oom_func* __cold +mdbx_env_get_oomfunc(MDB_env *env) { return env ? env->me_oom_func : NULL; } @@ -9747,7 +9824,7 @@ typedef struct mdb_walk_ctx mdb_walk_ctx_t; /** Depth-first tree traversal. */ -static int ESECT +static int __cold mdb_env_walk(mdb_walk_ctx_t *ctx, const char* dbi, pgno_t pg, int flags, int deep) { MDB_page *mp; @@ -9871,8 +9948,8 @@ mdb_env_walk(mdb_walk_ctx_t *ctx, const char* dbi, pgno_t pg, int flags, int dee nkeys, payload_size, header_size, unused_size + align_bytes); } -int ESECT -mdb_env_pgwalk(MDB_txn *txn, MDB_pgvisitor_func* visitor, void* user) +int __cold +mdbx_env_pgwalk(MDB_txn *txn, MDB_pgvisitor_func* visitor, void* user) { mdb_walk_ctx_t ctx; int rc; @@ -9892,4 +9969,8 @@ mdb_env_pgwalk(MDB_txn *txn, MDB_pgvisitor_func* visitor, void* user) return rc; } +#endif /* MDBX_MODE_ENABLED */ + /** @} */ + +#include "./midl.c" diff --git a/mdb_chk.c b/mdb_chk.c index 01fc8a85..b0a0a214 100644 --- a/mdb_chk.c +++ b/mdb_chk.c @@ -17,7 +17,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ -/* mdb_chk.c - memory-mapped database check tool */ +/* mdbx_chk.c - memory-mapped database check tool */ #include #include #include @@ -29,8 +29,8 @@ #include #include -#include "lmdb.h" #include "midl.h" +#include "mdbx.h" typedef struct flagbit { int bit; @@ -79,8 +79,8 @@ int exclusive = 2; MDB_env *env; MDB_txn *txn, *locktxn; -MDB_envinfo info; -MDB_stat stat; +MDBX_envinfo info; +MDBX_stat stat; size_t maxkeysize, reclaimable_pages, freedb_pages, lastpgno; size_t userdb_count, skipped_subdb; unsigned verbose, quiet; @@ -215,7 +215,7 @@ static int pgvisitor(size_t pgno, unsigned pgnumber, void* ctx, const char* dbi, { if (type) { size_t page_bytes = payload_bytes + header_bytes + unused_bytes; - size_t page_size = pgnumber * stat.ms_psize; + size_t page_size = pgnumber * stat.base.ms_psize; int index = pagemap_lookup_dbi(dbi); if (index < 0) return ENOMEM; @@ -233,11 +233,11 @@ static int pgvisitor(size_t pgno, unsigned pgnumber, void* ctx, const char* dbi, if (unused_bytes < 0 || (size_t) unused_bytes > page_size) problem_add("page", pgno, "illegal unused-bytes", "%zu < %i < %zu", - 0, unused_bytes, stat.ms_psize); + 0, unused_bytes, stat.base.ms_psize); - if (header_bytes < sizeof(long) || header_bytes >= stat.ms_psize - sizeof(long)) + if (header_bytes < sizeof(long) || header_bytes >= stat.base.ms_psize - sizeof(long)) problem_add("page", pgno, "illegal header-length", "%zu < %i < %zu", - sizeof(long), header_bytes, stat.ms_psize - sizeof(long)); + sizeof(long), header_bytes, stat.base.ms_psize - sizeof(long)); if (payload_bytes < 1) { if (nentries > 0) { problem_add("page", pgno, "zero size-of-entry", "payload %i bytes, %i entries", @@ -298,7 +298,7 @@ static int handle_freedb(size_t record_number, MDB_val *key, MDB_val* data) { if (key->mv_size != sizeof(txnid)) problem_add("entry", record_number, "wrong txn-id size", "key-size %zi", key->mv_size); - else if (txnid < 1 || txnid > info.me_last_txnid) + else if (txnid < 1 || txnid > info.base.me_last_txnid) problem_add("entry", record_number, "wrong txn-id", "%zu", txnid); if (data->mv_size < sizeof(size_t) || data->mv_size % sizeof(size_t)) @@ -316,9 +316,9 @@ static int handle_freedb(size_t record_number, MDB_val *key, MDB_val* data) { reclaimable_pages += number; for (i = number, prev = 1; --i >= 0; ) { pg = iptr[i]; - if (pg < 2 /* META_PAGE */ || pg > info.me_last_pgno) + if (pg < 2 /* META_PAGE */ || pg > info.base.me_last_pgno) problem_add("entry", record_number, "wrong idl entry", "2 < %zi < %zi", - pg, info.me_last_pgno); + pg, info.base.me_last_pgno); else if (pg <= prev) { bad = " [bad sequence]"; problem_add("entry", record_number, "bad sequence", "%zi <= %zi", @@ -375,7 +375,7 @@ static int handle_maindb(size_t record_number, MDB_val *key, MDB_val* data) { static int process_db(MDB_dbi dbi, char *name, visitor *handler, int silent) { MDB_cursor *mc; - MDB_stat ms; + MDBX_stat ms; MDB_val key, data; MDB_val prev_key, prev_data; unsigned flags; @@ -387,11 +387,11 @@ static int process_db(MDB_dbi dbi, char *name, visitor *handler, int silent) size_t key_bytes = 0, data_bytes = 0; if (0 > (int) dbi) { - rc = mdb_dbi_open(txn, name, 0, &dbi); + rc = mdbx_dbi_open(txn, name, 0, &dbi); if (rc) { if (!name || rc != MDB_INCOMPATIBLE) /* LY: mainDB's record is not a user's DB. */ { - error(" - mdb_open '%s' failed, error %d %s\n", - name ? name : "main", rc, mdb_strerror(rc)); + error(" - mdbx_open '%s' failed, error %d %s\n", + name ? name : "main", rc, mdbx_strerror(rc)); } return rc; } @@ -403,7 +403,7 @@ static int process_db(MDB_dbi dbi, char *name, visitor *handler, int silent) fflush(NULL); } skipped_subdb++; - mdb_dbi_close(env, dbi); + mdbx_dbi_close(env, dbi); return MDB_SUCCESS; } @@ -412,17 +412,17 @@ static int process_db(MDB_dbi dbi, char *name, visitor *handler, int silent) fflush(NULL); } - rc = mdb_dbi_flags(txn, dbi, &flags); + rc = mdbx_dbi_flags(txn, dbi, &flags); if (rc) { - error(" - mdb_dbi_flags failed, error %d %s\n", rc, mdb_strerror(rc)); - mdb_dbi_close(env, dbi); + error(" - mdbx_dbi_flags failed, error %d %s\n", rc, mdbx_strerror(rc)); + mdbx_dbi_close(env, dbi); return rc; } - rc = mdb_stat(txn, dbi, &ms); + rc = mdbx_stat(txn, dbi, &ms, sizeof(ms)); if (rc) { - error(" - mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); - mdb_dbi_close(env, dbi); + error(" - mdbx_stat failed, error %d %s\n", rc, mdbx_strerror(rc)); + mdbx_dbi_close(env, dbi); return rc; } @@ -437,23 +437,23 @@ static int process_db(MDB_dbi dbi, char *name, visitor *handler, int silent) } print(" (0x%02X)\n", flags); if (verbose > 1) { - print(" - page size %u, entries %zu\n", ms.ms_psize, ms.ms_entries); + print(" - page size %u, entries %zu\n", ms.base.ms_psize, ms.base.ms_entries); print(" - b-tree depth %u, pages: branch %zu, leaf %zu, overflow %zu\n", - ms.ms_depth, ms.ms_branch_pages, ms.ms_leaf_pages, ms.ms_overflow_pages); + ms.base.ms_depth, ms.base.ms_branch_pages, ms.base.ms_leaf_pages, ms.base.ms_overflow_pages); } } - rc = mdb_cursor_open(txn, dbi, &mc); + rc = mdbx_cursor_open(txn, dbi, &mc); if (rc) { - error(" - mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); - mdb_dbi_close(env, dbi); + error(" - mdbx_cursor_open failed, error %d %s\n", rc, mdbx_strerror(rc)); + mdbx_dbi_close(env, dbi); return rc; } saved_list = problems_push(); prev_key.mv_data = NULL; prev_data.mv_size = 0; - rc = mdb_cursor_get(mc, &key, &data, MDB_FIRST); + rc = mdbx_cursor_get(mc, &key, &data, MDB_FIRST); while (rc == MDB_SUCCESS) { if (gotsignal) { print(" - interrupted by signal\n"); @@ -485,7 +485,7 @@ static int process_db(MDB_dbi dbi, char *name, visitor *handler, int silent) "%zu != %zu", prev_data.mv_size, data.mv_size); } - int cmp = mdb_cmp(txn, dbi, &prev_key, &key); + int cmp = mdbx_cmp(txn, dbi, &prev_key, &key); if (cmp > 0) { problem_add("entry", record_count, "broken ordering of entries", NULL); } else if (cmp == 0) { @@ -493,7 +493,7 @@ static int process_db(MDB_dbi dbi, char *name, visitor *handler, int silent) if (! (flags & MDB_DUPSORT)) problem_add("entry", record_count, "duplicated entries", NULL); else if (flags & MDB_INTEGERDUP) { - cmp = mdb_dcmp(txn, dbi, &prev_data, &data); + cmp = mdbx_dcmp(txn, dbi, &prev_data, &data); if (cmp > 0) problem_add("entry", record_count, "broken ordering of multi-values", NULL); } @@ -517,16 +517,16 @@ static int process_db(MDB_dbi dbi, char *name, visitor *handler, int silent) prev_key = key; prev_data = data; - rc = mdb_cursor_get(mc, &key, &data, MDB_NEXT); + rc = mdbx_cursor_get(mc, &key, &data, MDB_NEXT); } if (rc != MDB_NOTFOUND) - error(" - mdb_cursor_get failed, error %d %s\n", rc, mdb_strerror(rc)); + error(" - mdbx_cursor_get failed, error %d %s\n", rc, mdbx_strerror(rc)); else rc = 0; - if (record_count != ms.ms_entries) + if (record_count != ms.base.ms_entries) problem_add("entry", record_count, "differentent number of entries", - "%zu != %zu", record_count, ms.ms_entries); + "%zu != %zu", record_count, ms.base.ms_entries); bailout: problems_count = problems_pop(saved_list); if (! silent && verbose) { @@ -535,8 +535,8 @@ bailout: fflush(NULL); } - mdb_cursor_close(mc); - mdb_dbi_close(env, dbi); + mdbx_cursor_close(mc); + mdbx_dbi_close(env, dbi); return rc || problems_count; } @@ -583,7 +583,7 @@ int main(int argc, char *argv[]) if (clock_gettime(CLOCK_MONOTONIC, ×tamp_start)) { rc = errno; - error("clock_gettime failed, error %d %s\n", rc, mdb_strerror(rc)); + error("clock_gettime failed, error %d %s\n", rc, mdbx_strerror(rc)); return EXIT_FAILURE_SYS; } @@ -638,97 +638,97 @@ int main(int argc, char *argv[]) signal(SIGTERM, signal_hanlder); envname = argv[optind]; - print("Running mdb_chk for '%s' in %s mode...\n", + print("Running mdbx_chk for '%s' in %s mode...\n", envname, (envflags & MDB_RDONLY) ? "read-only" : "write-lock"); fflush(NULL); - rc = mdb_env_create(&env); + rc = mdbx_env_create(&env); if (rc) { - error("mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); + error("mdbx_env_create failed, error %d %s\n", rc, mdbx_strerror(rc)); return rc < 0 ? EXIT_FAILURE_MDB : EXIT_FAILURE_SYS; } - rc = mdb_env_get_maxkeysize(env); + rc = mdbx_env_get_maxkeysize(env); if (rc < 0) { - error("mdb_env_get_maxkeysize failed, error %d %s\n", rc, mdb_strerror(rc)); + error("mdbx_env_get_maxkeysize failed, error %d %s\n", rc, mdbx_strerror(rc)); goto bailout; } maxkeysize = rc; - mdb_env_set_maxdbs(env, 3); + mdbx_env_set_maxdbs(env, 3); - rc = mdb_env_open_ex(env, envname, envflags, 0664, &exclusive); + rc = mdbx_env_open_ex(env, envname, envflags, 0664, &exclusive); if (rc) { - error("mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); + error("mdbx_env_open failed, error %d %s\n", rc, mdbx_strerror(rc)); goto bailout; } if (verbose) print(" - %s mode\n", exclusive ? "monopolistic" : "cooperative"); if (! (envflags & MDB_RDONLY)) { - rc = mdb_txn_begin(env, NULL, 0, &locktxn); + rc = mdbx_txn_begin(env, NULL, 0, &locktxn); if (rc) { - error("mdb_txn_begin(lock-write) failed, error %d %s\n", rc, mdb_strerror(rc)); + error("mdbx_txn_begin(lock-write) failed, error %d %s\n", rc, mdbx_strerror(rc)); goto bailout; } } - rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); + rc = mdbx_txn_begin(env, NULL, MDB_RDONLY, &txn); if (rc) { - error("mdb_txn_begin(read-only) failed, error %d %s\n", rc, mdb_strerror(rc)); + error("mdbx_txn_begin(read-only) failed, error %d %s\n", rc, mdbx_strerror(rc)); goto bailout; } - rc = mdb_env_info(env, &info); + rc = mdbx_env_info(env, &info, sizeof(info)); if (rc) { - error("mdb_env_info failed, error %d %s\n", rc, mdb_strerror(rc)); + error("mdbx_env_info failed, error %d %s\n", rc, mdbx_strerror(rc)); goto bailout; } - rc = mdb_env_stat(env, &stat); + rc = mdbx_env_stat(env, &stat, sizeof(stat)); if (rc) { - error("mdb_env_stat failed, error %d %s\n", rc, mdb_strerror(rc)); + error("mdbx_env_stat failed, error %d %s\n", rc, mdbx_strerror(rc)); goto bailout; } - lastpgno = info.me_last_pgno + 1; + lastpgno = info.base.me_last_pgno + 1; errno = 0; if (verbose) { double k = 1024.0; const char sf[] = "KMGTPEZY"; /* LY: Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta! */ - for(i = 0; sf[i+1] && info.me_mapsize / k > 1000.0; ++i) + for(i = 0; sf[i+1] && info.base.me_mapsize / k > 1000.0; ++i) k *= 1024; - print(" - map size %zu (%.2f %cb)\n", info.me_mapsize, - info.me_mapsize / k, sf[i]); - if (info.me_mapaddr) - print(" - mapaddr %p\n", info.me_mapaddr); + print(" - map size %zu (%.2f %cb)\n", info.base.me_mapsize, + info.base.me_mapsize / k, sf[i]); + if (info.base.me_mapaddr) + print(" - mapaddr %p\n", info.base.me_mapaddr); print(" - pagesize %u, max keysize %zu (%s), max readers %u\n", - stat.ms_psize, maxkeysize, + stat.base.ms_psize, maxkeysize, (maxkeysize == 511) ? "default" : (maxkeysize == 0) ? "devel" : "custom", - info.me_maxreaders); - print(" - transactions: last %zu, bottom %zu, lag reading %zi\n", info.me_last_txnid, - info.me_tail_txnid, info.me_last_txnid - info.me_tail_txnid); + info.base.me_maxreaders); + print(" - transactions: last %zu, bottom %zu, lag reading %zi\n", info.base.me_last_txnid, + info.me_tail_txnid, info.base.me_last_txnid - info.me_tail_txnid); print(" - meta-1: %s %zu, %s", meta_synctype(info.me_meta1_sign), info.me_meta1_txnid, meta_lt(info.me_meta1_txnid, info.me_meta1_sign, info.me_meta2_txnid, info.me_meta2_sign) ? "tail" : "head"); - if (info.me_meta1_txnid > info.me_last_txnid) + if (info.me_meta1_txnid > info.base.me_last_txnid) print(", rolled-back %zu (%zu >>> %zu)\n", - info.me_meta1_txnid - info.me_last_txnid, - info.me_meta1_txnid, info.me_last_txnid); + info.me_meta1_txnid - info.base.me_last_txnid, + info.me_meta1_txnid, info.base.me_last_txnid); print("\n"); print(" - meta-2: %s %zu, %s", meta_synctype(info.me_meta2_sign), info.me_meta2_txnid, meta_lt(info.me_meta2_txnid, info.me_meta2_sign, info.me_meta1_txnid, info.me_meta1_sign) ? "tail" : "head"); - if (info.me_meta2_txnid > info.me_last_txnid) + if (info.me_meta2_txnid > info.base.me_last_txnid) print(", rolled-back %zu (%zu >>> %zu)\n", - info.me_meta2_txnid - info.me_last_txnid, - info.me_meta2_txnid, info.me_last_txnid); + info.me_meta2_txnid - info.base.me_last_txnid, + info.me_meta2_txnid, info.base.me_last_txnid); print("\n"); } @@ -738,26 +738,26 @@ int main(int argc, char *argv[]) if (! meta_lt(info.me_meta1_txnid, info.me_meta1_sign, info.me_meta2_txnid, info.me_meta2_sign) - && info.me_meta1_txnid != info.me_last_txnid) { + && info.me_meta1_txnid != info.base.me_last_txnid) { print(" - meta-1 txn-id mismatch last-txn-id (%zi != %zi)\n", - info.me_meta1_txnid, info.me_last_txnid); + info.me_meta1_txnid, info.base.me_last_txnid); ++problems_meta; } if (! meta_lt(info.me_meta2_txnid, info.me_meta2_sign, info.me_meta1_txnid, info.me_meta1_sign) - && info.me_meta2_txnid != info.me_last_txnid) { + && info.me_meta2_txnid != info.base.me_last_txnid) { print(" - meta-2 txn-id mismatch last-txn-id (%zi != %zi)\n", - info.me_meta2_txnid, info.me_last_txnid); + info.me_meta2_txnid, info.base.me_last_txnid); ++problems_meta; } } else if (locktxn) { if (verbose) print(" - perform lite check last-txn-id with meta-pages (not a monopolistic mode)\n"); size_t last = (info.me_meta2_txnid > info.me_meta1_txnid) ? info.me_meta2_txnid : info.me_meta1_txnid; - if (last != info.me_last_txnid) { + if (last != info.base.me_last_txnid) { print(" - last-meta mismatch last-txn-id (%zi != %zi)\n", - last, info.me_last_txnid); + last, info.base.me_last_txnid); ++problems_meta; } } else if (verbose) { @@ -774,12 +774,12 @@ int main(int argc, char *argv[]) walk.pagemap = calloc(lastpgno, sizeof(*walk.pagemap)); if (! walk.pagemap) { rc = errno ? errno : ENOMEM; - error("calloc failed, error %d %s\n", rc, mdb_strerror(rc)); + error("calloc failed, error %d %s\n", rc, mdbx_strerror(rc)); goto bailout; } saved_list = problems_push(); - rc = mdb_env_pgwalk(txn, pgvisitor, NULL); + rc = mdbx_env_pgwalk(txn, pgvisitor, NULL); traversal_problems = problems_pop(saved_list); if (rc) { @@ -787,7 +787,7 @@ int main(int argc, char *argv[]) print(" - interrupted by signal\n"); fflush(NULL); } else { - error("mdb_env_pgwalk failed, error %d %s\n", rc, mdb_strerror(rc)); + error("mdbx_env_pgwalk failed, error %d %s\n", rc, mdbx_strerror(rc)); } goto bailout; } @@ -803,7 +803,7 @@ int main(int argc, char *argv[]) } if (verbose) { - size_t total_page_bytes = walk.pgcount * stat.ms_psize; + size_t total_page_bytes = walk.pgcount * stat.base.ms_psize; print(" - dbi pages: %zu total", walk.pgcount); if (verbose > 1) for (i = 1; i < MAX_DBI && walk.dbi_names[i]; ++i) @@ -816,7 +816,7 @@ int main(int argc, char *argv[]) total_page_bytes - walk.total_payload_bytes, (total_page_bytes - walk.total_payload_bytes) * 100.0 / total_page_bytes); for (i = 1; i < MAX_DBI && walk.dbi_names[i]; ++i) { - size_t dbi_bytes = walk.dbi_pages[i] * stat.ms_psize; + size_t dbi_bytes = walk.dbi_pages[i] * stat.base.ms_psize; print(" %s: subtotal %zu bytes (%.1f%%), payload %zu (%.1f%%), unused %zu (%.1f%%)", walk.dbi_names[i], dbi_bytes, dbi_bytes * 100.0 / total_page_bytes, @@ -848,13 +848,13 @@ int main(int argc, char *argv[]) problems_freedb = process_db(0 /* FREE_DBI */, "free", handle_freedb, 0); if (verbose) { - size_t value = info.me_mapsize / stat.ms_psize; + size_t value = info.base.me_mapsize / stat.base.ms_psize; double percent = value / 100.0; print(" - pages info: %zu total", value); print(", allocated %zu (%.1f%%)", lastpgno, lastpgno / percent); if (verbose > 1) { - value = info.me_mapsize / stat.ms_psize - lastpgno; + value = info.base.me_mapsize / stat.base.ms_psize - lastpgno; print(", remained %zu (%.1f%%)", value, value / percent); value = lastpgno - freedb_pages; @@ -868,7 +868,7 @@ int main(int argc, char *argv[]) print(", reclaimable %zu (%.1f%%)", reclaimable_pages, reclaimable_pages / percent); } - value = info.me_mapsize / stat.ms_psize - lastpgno + reclaimable_pages; + value = info.base.me_mapsize / stat.base.ms_psize - lastpgno + reclaimable_pages; print(", available %zu (%.1f%%)\n", value, value / percent); } @@ -892,11 +892,11 @@ int main(int argc, char *argv[]) bailout: if (txn) - mdb_txn_abort(txn); + mdbx_txn_abort(txn); if (locktxn) - mdb_txn_abort(locktxn); + mdbx_txn_abort(locktxn); if (env) - mdb_env_close(env); + mdbx_env_close(env); free(walk.pagemap); fflush(NULL); if (rc) { @@ -907,7 +907,7 @@ bailout: if (clock_gettime(CLOCK_MONOTONIC, ×tamp_finish)) { rc = errno; - error("clock_gettime failed, error %d %s\n", rc, mdb_strerror(rc)); + error("clock_gettime failed, error %d %s\n", rc, mdbx_strerror(rc)); return EXIT_FAILURE_SYS; } diff --git a/mdb_copy.c b/mdb_copy.c index 81271504..2d58f2e6 100644 --- a/mdb_copy.c +++ b/mdb_copy.c @@ -20,7 +20,7 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" static void sighandle(int sig) diff --git a/mdb_dump.c b/mdb_dump.c index b0ea31ea..c53866b4 100644 --- a/mdb_dump.c +++ b/mdb_dump.c @@ -18,7 +18,7 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" #ifdef _WIN32 #define Z "I" diff --git a/mdb_load.c b/mdb_load.c index fe2334a7..97e81e02 100644 --- a/mdb_load.c +++ b/mdb_load.c @@ -17,7 +17,7 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" #define PRINT 1 #define NOHDR 2 diff --git a/mdb_stat.c b/mdb_stat.c index a37e39a7..90a43c05 100644 --- a/mdb_stat.c +++ b/mdb_stat.c @@ -15,18 +15,18 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" -static void prstat(MDB_stat *ms) +static void prstat(MDBX_stat *ms) { #if 0 - printf(" Page size: %u\n", ms->ms_psize); + printf(" Page size: %u\n", ms->base.ms_psize); #endif - printf(" Tree depth: %u\n", ms->ms_depth); - printf(" Branch pages: %zu\n", ms->ms_branch_pages); - printf(" Leaf pages: %zu\n", ms->ms_leaf_pages); - printf(" Overflow pages: %zu\n", ms->ms_overflow_pages); - printf(" Entries: %zu\n", ms->ms_entries); + printf(" Tree depth: %u\n", ms->base.ms_depth); + printf(" Branch pages: %zu\n", ms->base.ms_branch_pages); + printf(" Leaf pages: %zu\n", ms->base.ms_leaf_pages); + printf(" Overflow pages: %zu\n", ms->base.ms_overflow_pages); + printf(" Entries: %zu\n", ms->base.ms_entries); } static void usage(char *prog) @@ -41,8 +41,8 @@ int main(int argc, char *argv[]) MDB_env *env; MDB_txn *txn; MDB_dbi dbi; - MDB_stat mst; - MDB_envinfo mei; + MDBX_stat mst; + MDBX_envinfo mei; char *prog = argv[0]; char *envname; char *subname = NULL; @@ -115,19 +115,19 @@ int main(int argc, char *argv[]) } if (envinfo) { - (void)mdb_env_stat(env, &mst); - (void)mdb_env_info(env, &mei); + (void)mdbx_env_stat(env, &mst, sizeof(mst)); + (void)mdbx_env_info(env, &mei, sizeof(mei)); printf("Environment Info\n"); - printf(" Map address: %p\n", mei.me_mapaddr); - printf(" Map size: %zu\n", mei.me_mapsize); - printf(" Page size: %u\n", mst.ms_psize); - printf(" Max pages: %zu\n", mei.me_mapsize / mst.ms_psize); - printf(" Number of pages used: %zu\n", mei.me_last_pgno+1); - printf(" Last transaction ID: %zu\n", mei.me_last_txnid); + printf(" Map address: %p\n", mei.base.me_mapaddr); + printf(" Map size: %zu\n", mei.base.me_mapsize); + printf(" Page size: %u\n", mst.base.ms_psize); + printf(" Max pages: %zu\n", mei.base.me_mapsize / mst.base.ms_psize); + printf(" Number of pages used: %zu\n", mei.base.me_last_pgno+1); + printf(" Last transaction ID: %zu\n", mei.base.me_last_txnid); printf(" Tail transaction ID: %zu (%zi)\n", - mei.me_tail_txnid, mei.me_tail_txnid - mei.me_last_txnid); - printf(" Max readers: %u\n", mei.me_maxreaders); - printf(" Number of readers used: %u\n", mei.me_numreaders); + mei.me_tail_txnid, mei.me_tail_txnid - mei.base.me_last_txnid); + printf(" Max readers: %u\n", mei.base.me_maxreaders); + printf(" Number of readers used: %u\n", mei.base.me_numreaders); } else { /* LY: zap warnings from gcc */ memset(&mst, 0, sizeof(mst)); @@ -166,7 +166,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } - rc = mdb_stat(txn, dbi, &mst); + rc = mdbx_stat(txn, dbi, &mst, sizeof(mst)); if (rc) { fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; @@ -206,18 +206,18 @@ int main(int argc, char *argv[]) } mdb_cursor_close(cursor); if (envinfo) { - size_t value = mei.me_mapsize / mst.ms_psize; + size_t value = mei.base.me_mapsize / mst.base.ms_psize; double percent = value / 100.0; printf("Page Allocation Info\n"); printf(" Max pages: %9zu 100%%\n", value); - value = mei.me_last_pgno+1; + value = mei.base.me_last_pgno+1; printf(" Number of pages used: %zu %.1f%%\n", value, value / percent); - value = mei.me_mapsize / mst.ms_psize - (mei.me_last_pgno+1); + value = mei.base.me_mapsize / mst.base.ms_psize - (mei.base.me_last_pgno+1); printf(" Remained: %zu %.1f%%\n", value, value / percent); - value = mei.me_last_pgno+1 - pages; + value = mei.base.me_last_pgno+1 - pages; printf(" Used now: %zu %.1f%%\n", value, value / percent); value = pages; @@ -229,7 +229,7 @@ int main(int argc, char *argv[]) value = reclaimable; printf(" Reclaimable: %zu %.1f%%\n", value, value / percent); - value = mei.me_mapsize / mst.ms_psize - (mei.me_last_pgno+1) + reclaimable; + value = mei.base.me_mapsize / mst.base.ms_psize - (mei.base.me_last_pgno+1) + reclaimable; printf(" Available: %zu %.1f%%\n", value, value / percent); } else printf(" Free pages: %zu\n", pages); @@ -241,7 +241,7 @@ int main(int argc, char *argv[]) goto txn_abort; } - rc = mdb_stat(txn, dbi, &mst); + rc = mdbx_stat(txn, dbi, &mst, sizeof(mst)); if (rc) { fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; @@ -271,7 +271,7 @@ int main(int argc, char *argv[]) printf("Status of %s\n", str); free(str); if (rc) continue; - rc = mdb_stat(txn, db2, &mst); + rc = mdbx_stat(txn, db2, &mst, sizeof(mst)); if (rc) { fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; diff --git a/mdbx.h b/mdbx.h new file mode 100644 index 00000000..2086b410 --- /dev/null +++ b/mdbx.h @@ -0,0 +1,123 @@ +/* + Copyright (c) 2015 Leonid Yuriev . + Copyright (c) 2015 Peter-Service R&D LLC. + + This file is part of ReOpenLDAP. + + ReOpenLDAP is free software; you can redistribute it and/or modify it under + the terms of the GNU Affero General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ReOpenLDAP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/* + This is solution to provide flexible compatibility with the original liblmdb. + Yeah, this way is partially ugly and madness... + + But, on the other hand, only this way allows provide both API with + minimal changes the source code of an applications, and the source + code of the library itself. Anyway, ideas are welcome! + + So, + + When needed drop-in replacement for liblmdb you should: + - 'make lmdb' to build liblmdb.so and liblmdb.a; + - #include and use mdb_* functions; + - linking with liblmdb.so оr liblmdb.a; + + = This provides nearly full compatibility with + original LMDB from Symas Corp. + But you should be noted - such compatibility + is not a goal for MDBX. + + When exactly the libmdbx is needed, you should: + - 'make mdbx' to build libmdbx.so and libmdbx.a; + - #include and use mdbx_* functions; + - linking with libmdbx.so оr libmdbx.a; + + = This allows using (linking) both MDBX and LMDB + simultaneously in the one application, for instance + to benchmarking and/or comparison. +*/ + +#ifndef _MDBX_H_ +#define _MDBX_H_ +#define MDBX_MODE_ENABLED 1 + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#define mdb_version mdbx_version +#define mdb_strerror mdbx_strerror +#define mdb_env_create mdbx_env_create +#define mdb_env_open mdbx_env_open +#define mdb_env_open_ex mdbx_env_open_ex +#define mdb_env_copy mdbx_env_copy +#define mdb_env_copyfd mdbx_env_copyfd +#define mdb_env_copy2 mdbx_env_copy2 +#define mdb_env_copyfd2 mdbx_env_copyfd2 +#define mdb_env_sync mdbx_env_sync +#define mdb_env_close mdbx_env_close +#define mdb_env_close_ex mdbx_env_close_ex +#define mdb_env_set_flags mdbx_env_set_flags +#define mdb_env_get_flags mdbx_env_get_flags +#define mdb_env_get_path mdbx_env_get_path +#define mdb_env_get_fd mdbx_env_get_fd +#define mdb_env_set_mapsize mdbx_env_set_mapsize +#define mdb_env_set_maxreaders mdbx_env_set_maxreaders +#define mdb_env_get_maxreaders mdbx_env_get_maxreaders +#define mdb_env_set_maxdbs mdbx_env_set_maxdbs +#define mdb_env_get_maxkeysize mdbx_env_get_maxkeysize +#define mdb_env_set_userctx mdbx_env_set_userctx +#define mdb_env_get_userctx mdbx_env_get_userctx +#define mdb_env_set_assert mdbx_env_set_assert +#define mdb_env_set_syncbytes mdbx_env_set_syncbytes +#define mdb_txn_begin mdbx_txn_begin +#define mdb_txn_env mdbx_txn_env +#define mdb_txn_id mdbx_txn_id +#define mdb_txn_commit mdbx_txn_commit +#define mdb_txn_abort mdbx_txn_abort +#define mdb_txn_reset mdbx_txn_reset +#define mdb_txn_renew mdbx_txn_renew +#define mdb_dbi_open mdbx_dbi_open +#define mdb_dbi_flags mdbx_dbi_flags +#define mdb_dbi_close mdbx_dbi_close +#define mdb_drop mdbx_drop +#define mdb_set_compare mdbx_set_compare +#define mdb_set_dupsort mdbx_set_dupsort +#define mdb_set_relfunc mdbx_set_relfunc +#define mdb_set_relctx mdbx_set_relctx +#define mdb_get mdbx_get +#define mdb_put mdbx_put +#define mdb_del mdbx_del +#define mdb_cursor_open mdbx_cursor_open +#define mdb_cursor_close mdbx_cursor_close +#define mdb_cursor_renew mdbx_cursor_renew +#define mdb_cursor_txn mdbx_cursor_txn +#define mdb_cursor_dbi mdbx_cursor_dbi +#define mdb_cursor_get mdbx_cursor_get +#define mdb_cursor_put mdbx_cursor_put +#define mdb_cursor_del mdbx_cursor_del +#define mdb_cursor_count mdbx_cursor_count +#define mdb_cmp mdbx_cmp +#define mdb_dcmp mdbx_dcmp +#define mdb_reader_list mdbx_reader_list +#define mdb_reader_check mdbx_reader_check +#define mdb_dkey mdbx_dkey + +/** Compat with version <= 0.9.4, avoid clash with libmdb from MDB Tools project */ +#define mdbx_open(txn,name,flags,dbi) mdbx_dbi_open(txn,name,flags,dbi) +#define mdbx_close(env,dbi) mdbx_dbi_close(env,dbi) + +#include "./lmdb.h" + +#endif /* _MDBX_H_ */ diff --git a/midl.c b/midl.c index 57a9d492..f1818fad 100644 --- a/midl.c +++ b/midl.c @@ -30,7 +30,7 @@ */ #define CMP(x,y) ( (x) < (y) ? -1 : (x) > (y) ) -unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id ) +static unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id ) { /* * binary search of id in ids @@ -66,7 +66,7 @@ unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id ) } #if 0 /* superseded by append/sort */ -int mdb_midl_insert( MDB_IDL ids, MDB_ID id ) +static int mdb_midl_insert( MDB_IDL ids, MDB_ID id ) { unsigned x, i; @@ -100,7 +100,7 @@ int mdb_midl_insert( MDB_IDL ids, MDB_ID id ) } #endif -MDB_IDL mdb_midl_alloc(int num) +static MDB_IDL mdb_midl_alloc(int num) { MDB_IDL ids = malloc((num+2) * sizeof(MDB_ID)); if (ids) { @@ -110,13 +110,13 @@ MDB_IDL mdb_midl_alloc(int num) return ids; } -void mdb_midl_free(MDB_IDL ids) +static void mdb_midl_free(MDB_IDL ids) { if (ids) free(ids-1); } -void mdb_midl_shrink( MDB_IDL *idp ) +static void mdb_midl_shrink( MDB_IDL *idp ) { MDB_IDL ids = *idp; if (*(--ids) > MDB_IDL_UM_MAX && @@ -139,7 +139,7 @@ static int mdb_midl_grow( MDB_IDL *idp, int num ) return 0; } -int mdb_midl_need( MDB_IDL *idp, unsigned num ) +static int mdb_midl_need( MDB_IDL *idp, unsigned num ) { MDB_IDL ids = *idp; num += ids[0]; @@ -153,7 +153,7 @@ int mdb_midl_need( MDB_IDL *idp, unsigned num ) return 0; } -int mdb_midl_append( MDB_IDL *idp, MDB_ID id ) +static int mdb_midl_append( MDB_IDL *idp, MDB_ID id ) { MDB_IDL ids = *idp; /* Too big? */ @@ -167,7 +167,7 @@ int mdb_midl_append( MDB_IDL *idp, MDB_ID id ) return 0; } -int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app ) +static int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app ) { MDB_IDL ids = *idp; /* Too big? */ @@ -181,7 +181,7 @@ int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app ) return 0; } -int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n ) +static int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n ) { MDB_ID *ids = *idp, len = ids[0]; /* Too big? */ @@ -197,7 +197,7 @@ int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n ) return 0; } -void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge ) +static void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge ) { MDB_ID old_id, merge_id, i = merge[0], j = idl[0], k = i+j, total = k; idl[0] = (MDB_ID)-1; /* delimiter for idl scan below */ @@ -216,8 +216,7 @@ void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge ) #define SMALL 8 #define MIDL_SWAP(a,b) { itmp=(a); (a)=(b); (b)=itmp; } -void -mdb_midl_sort( MDB_IDL ids ) +static void mdb_midl_sort( MDB_IDL ids ) { /* Max possible depth of int-indexed tree * 2 items/level */ int istack[sizeof(int)*CHAR_BIT * 2]; @@ -277,7 +276,7 @@ mdb_midl_sort( MDB_IDL ids ) } } -unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id ) +static unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id ) { /* * binary search of id in ids @@ -312,7 +311,7 @@ unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id ) return cursor; } -int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id ) +static int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id ) { unsigned x, i; @@ -343,7 +342,7 @@ int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id ) return 0; } -int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id ) +static int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id ) { /* Too big? */ if (ids[0].mid >= MDB_IDL_UM_MAX) { diff --git a/midl.h b/midl.h index 2331e783..4053563d 100644 --- a/midl.h +++ b/midl.h @@ -71,6 +71,8 @@ typedef MDB_ID *MDB_IDL; /** Current max length of an #mdb_midl_alloc()ed IDL */ #define MDB_IDL_ALLOCLEN( ids ) ( (ids)[-1] ) +#ifdef MDBX_MODE_ENABLED + /** Append ID to IDL. The IDL must be big enough. */ #define mdb_midl_xappend(idl, id) do { \ MDB_ID *xidl = (idl), xlen = ++(xidl[0]); \ @@ -82,45 +84,45 @@ typedef MDB_ID *MDB_IDL; * @param[in] id The ID to search for. * @return The index of the first ID greater than or equal to \b id. */ -unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id ); +static unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id ); /** Allocate an IDL. * Allocates memory for an IDL of the given size. * @return IDL on success, NULL on failure. */ -MDB_IDL mdb_midl_alloc(int num); +static MDB_IDL mdb_midl_alloc(int num); /** Free an IDL. * @param[in] ids The IDL to free. */ -void mdb_midl_free(MDB_IDL ids); +static void mdb_midl_free(MDB_IDL ids); /** Shrink an IDL. * Return the IDL to the default size if it has grown larger. * @param[in,out] idp Address of the IDL to shrink. */ -void mdb_midl_shrink(MDB_IDL *idp); +static void mdb_midl_shrink(MDB_IDL *idp); /** Make room for num additional elements in an IDL. * @param[in,out] idp Address of the IDL. * @param[in] num Number of elements to make room for. * @return 0 on success, ENOMEM on failure. */ -int mdb_midl_need(MDB_IDL *idp, unsigned num); +static int mdb_midl_need(MDB_IDL *idp, unsigned num); /** Append an ID onto an IDL. * @param[in,out] idp Address of the IDL to append to. * @param[in] id The ID to append. * @return 0 on success, ENOMEM if the IDL is too large. */ -int mdb_midl_append( MDB_IDL *idp, MDB_ID id ); +static int mdb_midl_append( MDB_IDL *idp, MDB_ID id ); /** Append an IDL onto an IDL. * @param[in,out] idp Address of the IDL to append to. * @param[in] app The IDL to append. * @return 0 on success, ENOMEM if the IDL is too large. */ -int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app ); +static int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app ); /** Append an ID range onto an IDL. * @param[in,out] idp Address of the IDL to append to. @@ -128,18 +130,18 @@ int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app ); * @param[in] n Number of IDs to append. * @return 0 on success, ENOMEM if the IDL is too large. */ -int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n ); +static int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n ); /** Merge an IDL onto an IDL. The destination IDL must be big enough. * @param[in] idl The IDL to merge into. * @param[in] merge The IDL to merge. */ -void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge ); +static void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge ); /** Sort an IDL. * @param[in,out] ids The IDL to sort. */ -void mdb_midl_sort( MDB_IDL ids ); +static void mdb_midl_sort( MDB_IDL ids ); /** An ID2 is an ID/pointer pair. */ @@ -160,7 +162,7 @@ typedef MDB_ID2 *MDB_ID2L; * @param[in] id The ID to search for. * @return The index of the first ID2 whose \b mid member is greater than or equal to \b id. */ -unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id ); +static unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id ); /** Insert an ID2 into a ID2L. @@ -168,14 +170,16 @@ unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id ); * @param[in] id The ID2 to insert. * @return 0 on success, -1 if the ID was already present in the ID2L. */ -int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id ); +static int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id ); /** Append an ID2 into a ID2L. * @param[in,out] ids The ID2L to append into. * @param[in] id The ID2 to append. * @return 0 on success, -2 if the ID2L is too big. */ -int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id ); +static int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id ); + +#endif /* #ifdef MDBX_MODE_ENABLED */ /** @} */ /** @} */ diff --git a/mtest0.c b/mtest0.c index 0fdd0898..436dc5b8 100644 --- a/mtest0.c +++ b/mtest0.c @@ -17,7 +17,7 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) diff --git a/mtest1.c b/mtest1.c index e531cacb..6cf8b63e 100644 --- a/mtest1.c +++ b/mtest1.c @@ -26,7 +26,7 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) diff --git a/mtest2.c b/mtest2.c index 5650af3f..2767bbdf 100644 --- a/mtest2.c +++ b/mtest2.c @@ -20,7 +20,7 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) diff --git a/mtest3.c b/mtest3.c index bbb0906e..fc3da795 100644 --- a/mtest3.c +++ b/mtest3.c @@ -20,7 +20,7 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) diff --git a/mtest4.c b/mtest4.c index c24a7034..4ba33e41 100644 --- a/mtest4.c +++ b/mtest4.c @@ -20,7 +20,7 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) diff --git a/mtest5.c b/mtest5.c index 877911ed..5a059c76 100644 --- a/mtest5.c +++ b/mtest5.c @@ -20,7 +20,7 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) diff --git a/mtest6.c b/mtest6.c index 51ac39e3..ccd745ed 100644 --- a/mtest6.c +++ b/mtest6.c @@ -20,7 +20,7 @@ #include #include #include -#include "lmdb.h" +#include "mdbx.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) diff --git a/reopen.h b/reopen.h index 31f2eb30..4c16d067 100644 --- a/reopen.h +++ b/reopen.h @@ -31,9 +31,7 @@ # define _GNU_SOURCE #endif -#ifdef HAVE_ANSIDECL_H -# include -#endif +#include #ifndef __has_attribute # define __has_attribute(x) (0) @@ -88,6 +86,9 @@ #ifndef __cold # if defined(__GNUC__) && !defined(__clang__) # define __cold __attribute__((cold, optimize("Os"))) +# elif defined(__GNUC__) + /* cland case, just put infrequently used functions in separate section */ +# define __cold __attribute__((section("text.cold"))) # else # define __cold # endif diff --git a/wbench.c b/wbench.c index 1b5f3794..5f73525f 100644 --- a/wbench.c +++ b/wbench.c @@ -27,7 +27,7 @@ #include #include -#include "lmdb.h" +#include "mdbx.h" #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))