mirror of
https://github.com/isar/libmdbx.git
synced 2024-10-29 23:19:20 +08:00
lmdb: provide both interfaces - advanced 'mdbx' and original 'lmdb'.
This commit is contained in:
parent
09c140c1f4
commit
68171d5f5d
10
.gitignore
vendored
10
.gitignore
vendored
@ -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
|
||||
|
151
Makefile
151
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
|
||||
|
65
lmdb.h
65
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 <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
@ -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);
|
||||
* </ul>
|
||||
*/
|
||||
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);
|
||||
* </ul>
|
||||
*/
|
||||
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
|
||||
|
379
mdb.c
379
mdb.c
@ -37,8 +37,8 @@
|
||||
# define MDB_DEBUG 0
|
||||
#endif
|
||||
|
||||
#include "reopen.h"
|
||||
#include "barriers.h"
|
||||
#include "./reopen.h"
|
||||
#include "./barriers.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -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 = <caller locked the reader mutex>. */
|
||||
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"
|
||||
|
174
mdb_chk.c
174
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* mdb_chk.c - memory-mapped database check tool */
|
||||
/* mdbx_chk.c - memory-mapped database check tool */
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
@ -29,8 +29,8 @@
|
||||
#include <malloc.h>
|
||||
#include <time.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include "lmdb.h"
|
||||
#include "mdbx.h"
|
||||
|
||||
static void
|
||||
sighandle(int sig)
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include "lmdb.h"
|
||||
#include "mdbx.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define Z "I"
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include "lmdb.h"
|
||||
#include "mdbx.h"
|
||||
|
||||
#define PRINT 1
|
||||
#define NOHDR 2
|
||||
|
58
mdb_stat.c
58
mdb_stat.c
@ -15,18 +15,18 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
|
123
mdbx.h
Normal file
123
mdbx.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright (c) 2015 Leonid Yuriev <leo@yuriev.ru>.
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
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 <lmdb.h> 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 <mdbx.h> 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_ */
|
29
midl.c
29
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) {
|
||||
|
30
midl.h
30
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 */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
2
mtest0.c
2
mtest0.c
@ -17,7 +17,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#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))
|
||||
|
2
mtest1.c
2
mtest1.c
@ -26,7 +26,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#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))
|
||||
|
2
mtest2.c
2
mtest2.c
@ -20,7 +20,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#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))
|
||||
|
2
mtest3.c
2
mtest3.c
@ -20,7 +20,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#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))
|
||||
|
2
mtest4.c
2
mtest4.c
@ -20,7 +20,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#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))
|
||||
|
2
mtest5.c
2
mtest5.c
@ -20,7 +20,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#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))
|
||||
|
2
mtest6.c
2
mtest6.c
@ -20,7 +20,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#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))
|
||||
|
7
reopen.h
7
reopen.h
@ -31,9 +31,7 @@
|
||||
# define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANSIDECL_H
|
||||
# include <ansidecl.h>
|
||||
#endif
|
||||
#include <ansidecl.h>
|
||||
|
||||
#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
|
||||
|
Loading…
Reference in New Issue
Block a user