mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-06-08 16:22:09 -04:00
Merge branch 'mdb.RE/1.0' into ITS9009
This commit is contained in:
commit
9903af916f
28 changed files with 4979 additions and 1212 deletions
1
libraries/liblmdb/.gitignore
vendored
1
libraries/liblmdb/.gitignore
vendored
|
|
@ -5,6 +5,7 @@ mdb_copy
|
|||
mdb_stat
|
||||
mdb_dump
|
||||
mdb_load
|
||||
mdb_drop
|
||||
*.lo
|
||||
*.[ao]
|
||||
*.so
|
||||
|
|
|
|||
|
|
@ -1,303 +1,3 @@
|
|||
LMDB 0.9 Change Log
|
||||
LMDB 1.0 Change Log
|
||||
|
||||
LMDB 0.9.35 Release (2026/01/27)
|
||||
ITS#10434 - Fix typo affecting Mac OSX
|
||||
|
||||
LMDB 0.9.34 Release (2026/01/26)
|
||||
ITS#9564 - fix race condition freeing spilled pages at end of transaction
|
||||
ITS#10222 - Update mdb_dump(1) and mdb_load(1) man pages for append (-a) option
|
||||
ITS#10275 - mdb_load: add -Q option to use NOSYNC
|
||||
ITS#10296 - fix fdatasync on MacOS
|
||||
ITS#10342 - fix memleak in mdb_txn_begin for nested txns
|
||||
ITS#10346 - fix mdb_env_copy2 with values > (2GB-16)
|
||||
ITS#10355 - fix mplay build on musl
|
||||
ITS#10396 - fix mdb_cursor_del0 with multiple DUPSORT cursors
|
||||
ITS#10419 - add support for NetBSD
|
||||
ITS#10420 - add support for Haiku
|
||||
ITS#10421 - mdb_load: check for malicious input
|
||||
|
||||
LMDB 0.9.33 Release (2024/05/21)
|
||||
ITS#9037 mdb_page_search: fix error code when DBI record is missing
|
||||
ITS#10198 For win32, stop passing ignored parameter
|
||||
ITS#10212 Fix meta page usage by read only tools
|
||||
|
||||
LMDB 0.9.32 Release (2024/01/29)
|
||||
ITS#9378 - Add ability to replay log and replay log tool
|
||||
ITS#10095 - partial revert of ITS#9278. The patch was incorrect and introduced numerous race conditions.
|
||||
ITS#10125 - mdb_load: fix cursor reinit in Append mode
|
||||
ITS#10137 - Allow users to define MDB_IDL_LOGN
|
||||
|
||||
LMDB 0.9.31 Release (2023/07/10)
|
||||
ITS#8447 - Fix cursor_put(MDB_CURRENT) on DUPSORT DB with different sized data
|
||||
|
||||
LMDB 0.9.30 Release (2023/02/08)
|
||||
ITS#9806 - LMDB page_split: key threshold depends on page size
|
||||
ITS#9916 - avoid gcc optimization bug on sparc64 linux
|
||||
ITS#9919 - Mark infrequently used functions as cold
|
||||
ITS#9723 - clear C_EOF on cursor with MDB_FIRST_DUP
|
||||
ITS#9030 - Use sys/cachectl.h rather than asm/cachectl.h on mips
|
||||
|
||||
LMDB 0.9.29 Release (2021/03/16)
|
||||
ITS#9461 refix ITS#9376
|
||||
ITS#9500 fix regression from ITS#8662
|
||||
|
||||
LMDB 0.9.28 Release (2021/02/04)
|
||||
ITS#8662 add -a append option to mdb_load
|
||||
|
||||
LMDB 0.9.27 Release (2020/10/26)
|
||||
ITS#9376 fix repeated DUPSORT cursor deletes
|
||||
|
||||
LMDB 0.9.26 Release (2020/08/11)
|
||||
ITS#9278 fix robust mutex cleanup for FreeBSD
|
||||
|
||||
LMDB 0.9.25 Release (2020/01/30)
|
||||
ITS#9068 fix mdb_dump/load backslashes in printable content
|
||||
ITS#9118 add MAP_NOSYNC for FreeBSD
|
||||
ITS#9155 free mt_spill_pgs in non-nested txn on end
|
||||
|
||||
LMDB 0.9.24 Release (2019/07/24)
|
||||
ITS#8969 Tweak mdb_page_split
|
||||
ITS#8975 WIN32 fix writemap set_mapsize crash
|
||||
ITS#9007 Fix loose pages in WRITEMAP
|
||||
|
||||
LMDB 0.9.23 Release (2018/12/19)
|
||||
ITS#8756 Fix loose pages in dirty list
|
||||
ITS#8831 Fix mdb_load flag init
|
||||
ITS#8844 Fix mdb_env_close in forked process
|
||||
Documentation
|
||||
ITS#8857 mdb_cursor_del doesn't invalidate cursor
|
||||
ITS#8908 GET_MULTIPLE etc don't change passed in key
|
||||
|
||||
LMDB 0.9.22 Release (2018/03/22)
|
||||
Fix MDB_DUPSORT alignment bug (ITS#8819)
|
||||
Fix regression with new db from 0.9.19 (ITS#8760)
|
||||
Fix liblmdb to build on Solaris (ITS#8612)
|
||||
Fix delete behavior with DUPSORT DB (ITS#8622)
|
||||
Fix mdb_cursor_get/mdb_cursor_del behavior (ITS#8722)
|
||||
|
||||
LMDB 0.9.21 Release (2017/06/01)
|
||||
Fix xcursor after cursor_del (ITS#8622)
|
||||
|
||||
LMDB 0.9.20 (Withdrawn)
|
||||
Fix mdb_load with escaped plaintext (ITS#8558)
|
||||
Fix mdb_cursor_last / mdb_put interaction (ITS#8557)
|
||||
|
||||
LMDB 0.9.19 Release (2016/12/28)
|
||||
Fix mdb_env_cwalk cursor init (ITS#8424)
|
||||
Fix robust mutexes on Solaris 10/11 (ITS#8339)
|
||||
Tweak Win32 error message buffer
|
||||
Fix MDB_GET_BOTH on non-dup record (ITS#8393)
|
||||
Optimize mdb_drop
|
||||
Fix xcursors after mdb_cursor_del (ITS#8406)
|
||||
Fix MDB_NEXT_DUP after mdb_cursor_del (ITS#8412)
|
||||
Fix mdb_cursor_put resetting C_EOF (ITS#8489)
|
||||
Fix mdb_env_copyfd2 to return EPIPE on SIGPIPE (ITS#8504)
|
||||
Fix mdb_env_copy with empty DB (ITS#8209)
|
||||
Fix behaviors with fork (ITS#8505)
|
||||
Fix mdb_dbi_open with mainDB cursors (ITS#8542)
|
||||
Fix robust mutexes on kFreeBSD (ITS#8554)
|
||||
Fix utf8_to_utf16 error checks (ITS#7992)
|
||||
Fix F_NOCACHE on MacOS, error is non-fatal (ITS#7682)
|
||||
Build
|
||||
Make shared lib suffix overridable (ITS#8481)
|
||||
Documentation
|
||||
Cleanup doxygen nits
|
||||
Note reserved vs actual mem/disk usage
|
||||
|
||||
|
||||
LMDB 0.9.18 Release (2016/02/05)
|
||||
Fix robust mutex detection on glibc 2.10-11 (ITS#8330)
|
||||
Fix page_search_root assert on FreeDB (ITS#8336)
|
||||
Fix MDB_APPENDDUP vs. rewrite(single item) (ITS#8334)
|
||||
Fix mdb_copy of large files on Windows
|
||||
Fix subcursor move after delete (ITS#8355)
|
||||
Fix mdb_midl_shirnk off-by-one (ITS#8363)
|
||||
Check for utf8_to_utf16 failures (ITS#7992)
|
||||
Catch strdup failure in mdb_dbi_open
|
||||
Build
|
||||
Additional makefile var tweaks (ITS#8169)
|
||||
Documentation
|
||||
Add Getting Started page
|
||||
Update WRITEMAP description
|
||||
|
||||
|
||||
LMDB 0.9.17 Release (2015/11/30)
|
||||
Fix ITS#7377 catch calloc failure
|
||||
Fix ITS#8237 regression from ITS#7589
|
||||
Fix ITS#8238 page_split for DUPFIXED pages
|
||||
Fix ITS#8221 MDB_PAGE_FULL on delete/rebalance
|
||||
Fix ITS#8258 rebalance/split assert
|
||||
Fix ITS#8263 cursor_put cursor tracking
|
||||
Fix ITS#8264 cursor_del cursor tracking
|
||||
Fix ITS#8310 cursor_del cursor tracking
|
||||
Fix ITS#8299 mdb_del cursor tracking
|
||||
Fix ITS#8300 mdb_del cursor tracking
|
||||
Fix ITS#8304 mdb_del cursor tracking
|
||||
Fix ITS#7771 fakepage cursor tracking
|
||||
Fix ITS#7789 ensure mapsize >= pages in use
|
||||
Fix ITS#7971 mdb_txn_renew0() new reader slots
|
||||
Fix ITS#7969 use __sync_synchronize on non-x86
|
||||
Fix ITS#8311 page_split from update_key
|
||||
Fix ITS#8312 loose pages in nested txn
|
||||
Fix ITS#8313 mdb_rebalance dummy cursor
|
||||
Fix ITS#8315 dirty_room in nested txn
|
||||
Fix ITS#8323 dirty_list in nested txn
|
||||
Fix ITS#8316 page_merge cursor tracking
|
||||
Fix ITS#8321 cursor tracking
|
||||
Fix ITS#8319 mdb_load error messages
|
||||
Fix ITS#8320 mdb_load plaintext input
|
||||
Added mdb_txn_id() (ITS#7994)
|
||||
Added robust mutex support
|
||||
Miscellaneous cleanup/simplification
|
||||
Build
|
||||
Create install dirs if needed (ITS#8256)
|
||||
Fix ThreadProc decl on Win32/MSVC (ITS#8270)
|
||||
Added ssize_t typedef for MSVC (ITS#8067)
|
||||
Use ANSI apis on Windows (ITS#8069)
|
||||
Use O_SYNC if O_DSYNC,MDB_DSYNC are not defined (ITS#7209)
|
||||
Allow passing AR to make (ITS#8168)
|
||||
Allow passing mandir to make install (ITS#8169)
|
||||
|
||||
LMDB 0.9.16 Release (2015/08/14)
|
||||
Fix cursor EOF bug (ITS#8190)
|
||||
Fix handling of subDB records (ITS#8181)
|
||||
Fix mdb_midl_shrink() usage (ITS#8200)
|
||||
|
||||
LMDB 0.9.15 Release (2015/06/19)
|
||||
Fix txn init (ITS#7961,#7987)
|
||||
Fix MDB_PREV_DUP (ITS#7955,#7671)
|
||||
Fix compact of empty env (ITS#7956)
|
||||
Fix mdb_copy file mode
|
||||
Fix mdb_env_close() after failed mdb_env_open()
|
||||
Fix mdb_rebalance collapsing root (ITS#8062)
|
||||
Fix mdb_load with large values (ITS#8066)
|
||||
Fix to retry writes on EINTR (ITS#8106)
|
||||
Fix mdb_cursor_del on empty DB (ITS#8109)
|
||||
Fix MDB_INTEGERDUP key compare (ITS#8117)
|
||||
Fix error handling (ITS#7959,#8157,etc.)
|
||||
Fix race conditions (ITS#7969,7970)
|
||||
Added workaround for fdatasync bug in ext3fs
|
||||
Build
|
||||
Don't use -fPIC for static lib
|
||||
Update .gitignore (ITS#7952,#7953)
|
||||
Cleanup for "make test" (ITS#7841), "make clean", mtest*.c
|
||||
Misc. Android/Windows cleanup
|
||||
Documentation
|
||||
Fix MDB_APPEND doc
|
||||
Fix MDB_MAXKEYSIZE doc (ITS#8156)
|
||||
Fix mdb_cursor_put,mdb_cursor_del EACCES description
|
||||
Fix mdb_env_sync(MDB_RDONLY env) doc (ITS#8021)
|
||||
Clarify MDB_WRITEMAP doc (ITS#8021)
|
||||
Clarify mdb_env_open doc
|
||||
Clarify mdb_dbi_open doc
|
||||
|
||||
LMDB 0.9.14 Release (2014/09/20)
|
||||
Fix to support 64K page size (ITS#7713)
|
||||
Fix to persist decreased as well as increased mapsizes (ITS#7789)
|
||||
Fix cursor bug when deleting last node of a DUPSORT key
|
||||
Fix mdb_env_info to return FIXEDMAP address
|
||||
Fix ambiguous error code from writing to closed DBI (ITS#7825)
|
||||
Fix mdb_copy copying past end of file (ITS#7886)
|
||||
Fix cursor bugs from page_merge/rebalance
|
||||
Fix to dirty fewer pages in deletes (mdb_page_loose())
|
||||
Fix mdb_dbi_open creating subDBs (ITS#7917)
|
||||
Fix mdb_cursor_get(_DUP) with single value (ITS#7913)
|
||||
Fix Windows compat issues in mtests (ITS#7879)
|
||||
Add compacting variant of mdb_copy
|
||||
Add BigEndian integer key compare code
|
||||
Add mdb_dump/mdb_load utilities
|
||||
|
||||
LMDB 0.9.13 Release (2014/06/18)
|
||||
Fix mdb_page_alloc unlimited overflow page search
|
||||
Documentation
|
||||
Re-fix MDB_CURRENT doc (ITS#7793)
|
||||
Fix MDB_GET_MULTIPLE/MDB_NEXT_MULTIPLE doc
|
||||
|
||||
LMDB 0.9.12 Release (2014/06/13)
|
||||
Fix MDB_GET_BOTH regression (ITS#7875,#7681)
|
||||
Fix MDB_MULTIPLE writing multiple keys (ITS#7834)
|
||||
Fix mdb_rebalance (ITS#7829)
|
||||
Fix mdb_page_split (ITS#7815)
|
||||
Fix md_entries count (ITS#7861,#7828,#7793)
|
||||
Fix MDB_CURRENT (ITS#7793)
|
||||
Fix possible crash on Windows DLL detach
|
||||
Misc code cleanup
|
||||
Documentation
|
||||
mdb_cursor_put: cursor moves on error (ITS#7771)
|
||||
|
||||
|
||||
LMDB 0.9.11 Release (2014/01/15)
|
||||
Add mdb_env_set_assert() (ITS#7775)
|
||||
Fix: invalidate txn on page allocation errors (ITS#7377)
|
||||
Fix xcursor tracking in mdb_cursor_del0() (ITS#7771)
|
||||
Fix corruption from deletes (ITS#7756)
|
||||
Fix Windows/MSVC build issues
|
||||
Raise safe limit of max MDB_MAXKEYSIZE
|
||||
Misc code cleanup
|
||||
Documentation
|
||||
Remove spurious note about non-overlapping flags (ITS#7665)
|
||||
|
||||
LMDB 0.9.10 Release (2013/11/12)
|
||||
Add MDB_NOMEMINIT option
|
||||
Fix mdb_page_split() again (ITS#7589)
|
||||
Fix MDB_NORDAHEAD definition (ITS#7734)
|
||||
Fix mdb_cursor_del() positioning (ITS#7733)
|
||||
Partial fix for larger page sizes (ITS#7713)
|
||||
Fix Windows64/MSVC build issues
|
||||
|
||||
LMDB 0.9.9 Release (2013/10/24)
|
||||
Add mdb_env_get_fd()
|
||||
Add MDB_NORDAHEAD option
|
||||
Add MDB_NOLOCK option
|
||||
Avoid wasting space in mdb_page_split() (ITS#7589)
|
||||
Fix mdb_page_merge() cursor fixup (ITS#7722)
|
||||
Fix mdb_cursor_del() on last delete (ITS#7718)
|
||||
Fix adding WRITEMAP on existing env (ITS#7715)
|
||||
Fix nested txns (ITS#7515)
|
||||
Fix mdb_env_copy() O_DIRECT bug (ITS#7682)
|
||||
Fix mdb_cursor_set(SET_RANGE) return code (ITS#7681)
|
||||
Fix mdb_rebalance() cursor fixup (ITS#7701)
|
||||
Misc code cleanup
|
||||
Documentation
|
||||
Note that by default, readers need write access
|
||||
|
||||
|
||||
LMDB 0.9.8 Release (2013/09/09)
|
||||
Allow mdb_env_set_mapsize() on an open environment
|
||||
Fix mdb_dbi_flags() (ITS#7672)
|
||||
Fix mdb_page_unspill() in nested txns
|
||||
Fix mdb_cursor_get(CURRENT|NEXT) after a delete
|
||||
Fix mdb_cursor_get(DUP) to always return key (ITS#7671)
|
||||
Fix mdb_cursor_del() to always advance to next item (ITS#7670)
|
||||
Fix mdb_cursor_set(SET_RANGE) for tree with single page (ITS#7681)
|
||||
Fix mdb_env_copy() retry open if O_DIRECT fails (ITS#7682)
|
||||
Tweak mdb_page_spill() to be less aggressive
|
||||
Documentation
|
||||
Update caveats since mdb_reader_check() added in 0.9.7
|
||||
|
||||
LMDB 0.9.7 Release (2013/08/17)
|
||||
Don't leave stale lockfile on failed RDONLY open (ITS#7664)
|
||||
Fix mdb_page_split() ref beyond cursor depth
|
||||
Fix read txn data race (ITS#7635)
|
||||
Fix mdb_rebalance (ITS#7536, #7538)
|
||||
Fix mdb_drop() (ITS#7561)
|
||||
Misc DEBUG macro fixes
|
||||
Add MDB_NOTLS envflag
|
||||
Add mdb_env_copyfd()
|
||||
Add mdb_txn_env() (ITS#7660)
|
||||
Add mdb_dbi_flags() (ITS#7661)
|
||||
Add mdb_env_get_maxkeysize()
|
||||
Add mdb_env_reader_list()/mdb_env_reader_check()
|
||||
Add mdb_page_spill/unspill, remove hard txn size limit
|
||||
Use shorter names for semaphores (ITS#7615)
|
||||
Build
|
||||
Fix install target (ITS#7656)
|
||||
Documentation
|
||||
Misc updates for cursors, DB handles, data lifetime
|
||||
|
||||
LMDB 0.9.6 Release (2013/02/25)
|
||||
Many fixes/enhancements
|
||||
|
||||
LMDB 0.9.5 Release (2012/11/30)
|
||||
Renamed from libmdb to liblmdb
|
||||
Many fixes/enhancements
|
||||
LMDB 1.0.0 Release (2026/04/28)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
# platforms; you should not need to change any of these.
|
||||
# Read their descriptions in mdb.c if you do:
|
||||
#
|
||||
# - MDB_USE_POSIX_SEM
|
||||
# - MDB_USE_POSIX_MUTEX, MDB_USE_POSIX_SEM, MDB_USE_SYSV_SEM
|
||||
# - MDB_DSYNC
|
||||
# - MDB_FDATASYNC
|
||||
# - MDB_FDATASYNC_WORKS
|
||||
|
|
@ -24,9 +24,18 @@ W = -W -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized
|
|||
THREADS = -pthread
|
||||
OPT = -O2 -g
|
||||
CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS)
|
||||
LDLIBS =
|
||||
SOLIBS =
|
||||
LDFLAGS = $(THREADS)
|
||||
LDLIBS =
|
||||
SOLIBS =
|
||||
SOEXT = .so
|
||||
LDL = -ldl
|
||||
|
||||
LIBVER = 1
|
||||
ABIVER = 0
|
||||
VEREXT = $(LIBVER).$(ABIVER)
|
||||
LMDB_VERSION = 1.0.0
|
||||
SOFULL = $(SOEXT).$(VEREXT)
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = $(prefix)
|
||||
bindir = $(exec_prefix)/bin
|
||||
|
|
@ -38,11 +47,20 @@ mandir = $(datarootdir)/man
|
|||
########################################################################
|
||||
|
||||
IHDRS = lmdb.h
|
||||
ILIBS = liblmdb.a liblmdb$(SOEXT)
|
||||
IPROGS = mdb_stat mdb_copy mdb_dump mdb_load
|
||||
IDOCS = mdb_stat.1 mdb_copy.1 mdb_dump.1 mdb_load.1
|
||||
ILIBS = liblmdb.a
|
||||
ILIBS2 = liblmdb$(SOFULL)
|
||||
IPROGS = mdb_stat mdb_copy mdb_dump mdb_load mdb_drop
|
||||
IDOCS = mdb_stat.1 mdb_copy.1 mdb_dump.1 mdb_load.1 mdb_drop.1
|
||||
PROGS = $(IPROGS) mtest mtest2 mtest3 mtest4 mtest5
|
||||
all: $(ILIBS) $(PROGS)
|
||||
RPROGS = mtest_remap mtest_enc mtest_enc2
|
||||
SOVER = liblmdb$(SOEXT).$(LIBVER)
|
||||
VERSION_OPT = -Wl,-soname,$(SOVER)
|
||||
# For MacOSX:
|
||||
#VERSION_OPT = -Wl,-current_version,$(VEREXT)
|
||||
|
||||
all: $(ILIBS) $(ILIBS2) $(PROGS) lmdb.pc
|
||||
# Requires CPPFLAGS=-DMDB_VL32 and/or -DMDB_RPAGE_CACHE
|
||||
rall: all $(RPROGS)
|
||||
|
||||
install: $(ILIBS) $(IPROGS) $(IHDRS)
|
||||
mkdir -p $(DESTDIR)$(bindir)
|
||||
|
|
@ -51,35 +69,56 @@ install: $(ILIBS) $(IPROGS) $(IHDRS)
|
|||
mkdir -p $(DESTDIR)$(mandir)/man1
|
||||
for f in $(IPROGS); do cp $$f $(DESTDIR)$(bindir); done
|
||||
for f in $(ILIBS); do cp $$f $(DESTDIR)$(libdir); done
|
||||
for f in $(ILIBS2); do cp $$f $(DESTDIR)$(libdir); \
|
||||
i=`basename -s .$(ABIVER) $$f`; rm -f $(DESTDIR)$(libdir)/$$i; \
|
||||
ln -s $$f $(DESTDIR)$(libdir)/$$i; \
|
||||
i=`basename -s .$(LIBVER) $$i`; rm -f $(DESTDIR)$(libdir)/$$i; \
|
||||
ln -s $$f $(DESTDIR)$(libdir)/$$i; done
|
||||
for f in $(IHDRS); do cp $$f $(DESTDIR)$(includedir); done
|
||||
for f in $(IDOCS); do cp $$f $(DESTDIR)$(mandir)/man1; done
|
||||
|
||||
clean:
|
||||
rm -rf $(PROGS) *.[ao] *.[ls]o *~ testdb
|
||||
rm -rf $(PROGS) $(RPROGS) *.[ao] *.[ls]o *.so.* *~ testdb
|
||||
|
||||
test: all
|
||||
rm -rf testdb && mkdir testdb
|
||||
./mtest && ./mdb_stat testdb
|
||||
|
||||
liblmdb.a: mdb.o midl.o
|
||||
$(AR) rs $@ mdb.o midl.o
|
||||
liblmdb.a: mdb.o midl.o module.o
|
||||
$(AR) rs $@ mdb.o midl.o module.o
|
||||
|
||||
liblmdb$(SOEXT): mdb.lo midl.lo
|
||||
liblmdb$(SOFULL): mdb.lo midl.lo module.lo
|
||||
# $(CC) $(LDFLAGS) -pthread -shared -Wl,-Bsymbolic -o $@ mdb.o midl.o $(SOLIBS)
|
||||
$(CC) $(LDFLAGS) -pthread -shared -o $@ mdb.lo midl.lo $(SOLIBS)
|
||||
$(CC) $(LDFLAGS) -shared $(VERSION_OPT) -o $@ mdb.lo midl.lo module.lo $(SOLIBS) $(LDL)
|
||||
rm -f liblmdb$(SOEXT); ln -s $@ liblmdb$(SOEXT)
|
||||
rm -f $(SOVER); ln -s $@ $(SOVER)
|
||||
|
||||
mdb_stat: mdb_stat.o liblmdb.a
|
||||
$(CC) $(LDFLAGS) -o $@ $^ $(LDL)
|
||||
mdb_copy: mdb_copy.o liblmdb.a
|
||||
$(CC) $(LDFLAGS) -o $@ $^ $(LDL)
|
||||
mdb_dump: mdb_dump.o liblmdb.a
|
||||
$(CC) $(LDFLAGS) -o $@ $^ $(LDL)
|
||||
mdb_load: mdb_load.o liblmdb.a
|
||||
$(CC) $(LDFLAGS) -o $@ $^ $(LDL)
|
||||
mdb_drop: mdb_drop.o liblmdb.a
|
||||
$(CC) $(LDFLAGS) -o $@ $^ $(LDL)
|
||||
mtest: mtest.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
|
||||
mtest_remap: mtest_remap.o liblmdb.a
|
||||
mtest_enc: mtest_enc.o chacha8.o liblmdb.a
|
||||
mtest_enc2: mtest_enc2.o liblmdb.a crypto.lm
|
||||
$(CC) $(LDFLAGS) -pthread -o $@ mtest_enc2.o liblmdb.a $(LDL)
|
||||
|
||||
mplay: mplay.o liblmdb.a
|
||||
|
||||
crypto.lm: crypto.c
|
||||
$(CC) -shared $(CFLAGS) -o $@ $^ -lsodium
|
||||
|
||||
mdb.o: mdb.c lmdb.h midl.h
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c
|
||||
|
||||
|
|
@ -92,12 +131,28 @@ mdb.lo: mdb.c lmdb.h midl.h
|
|||
midl.lo: midl.c midl.h
|
||||
$(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c midl.c -o $@
|
||||
|
||||
module.lo: module.c lmdb.h
|
||||
$(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c module.c -o $@
|
||||
|
||||
%: %.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
||||
|
||||
%.o: %.c lmdb.h
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
|
||||
|
||||
lmdb.pc: Makefile
|
||||
@echo "prefix=$(prefix)" > $@
|
||||
@echo "exec_prefix=$(exec_prefix)" >>$@
|
||||
@echo "includedir=$(includedir)" >>$@
|
||||
@echo "libdir=$(libdir)" >>$@
|
||||
@echo >>$@
|
||||
@echo "Name: lmdb (OpenLDAP)" >>$@
|
||||
@echo "Description: OpenLDAP Lightning Memory Mapped Database library" >>$@
|
||||
@echo "URL: https://www.openldap.org" >>$@
|
||||
@echo "Version: $(LMDB_VERSION)" >>$@
|
||||
@echo "Cflags: $(THREADS) $(XCFLAGS)" >>$@
|
||||
@echo "Libs: $(LDL)" >>$@
|
||||
|
||||
COV_FLAGS=-fprofile-arcs -ftest-coverage
|
||||
COV_OBJS=xmdb.o xmidl.o
|
||||
|
||||
|
|
|
|||
183
libraries/liblmdb/chacha8.c
Normal file
183
libraries/liblmdb/chacha8.c
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
chacha-merged.c version 20080118
|
||||
D. J. Bernstein
|
||||
Public domain.
|
||||
*/
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "chacha8.h"
|
||||
#if 0
|
||||
#include "common/int-util.h"
|
||||
#include "warnings.h"
|
||||
#endif
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define SWAP32LE(x) (x)
|
||||
#else
|
||||
#define SWAP32LE(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \
|
||||
(((uint32_t) (x) & 0x0000ff00) << 8) | \
|
||||
(((uint32_t) (x) & 0x00ff0000) >> 8) | \
|
||||
(((uint32_t) (x) & 0xff000000) >> 24))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following macros are used to obtain exact-width results.
|
||||
*/
|
||||
#define U8V(v) ((uint8_t)(v) & UINT8_C(0xFF))
|
||||
#define U32V(v) ((uint32_t)(v) & UINT32_C(0xFFFFFFFF))
|
||||
|
||||
/*
|
||||
* The following macros load words from an array of bytes with
|
||||
* different types of endianness, and vice versa.
|
||||
*/
|
||||
#define U8TO32_LITTLE(p) SWAP32LE(((uint32_t*)(p))[0])
|
||||
#define U32TO8_LITTLE(p, v) (((uint32_t*)(p))[0] = SWAP32LE(v))
|
||||
|
||||
#define ROTATE(v,c) (rol32(v,c))
|
||||
#define XOR(v,w) ((v) ^ (w))
|
||||
#define PLUS(v,w) (U32V((v) + (w)))
|
||||
#define PLUSONE(v) (PLUS((v),1))
|
||||
|
||||
#define QUARTERROUND(a,b,c,d) \
|
||||
a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
|
||||
c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
|
||||
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
|
||||
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
|
||||
|
||||
static const char sigma[] = "expand 32-byte k";
|
||||
|
||||
static uint32_t rol32(uint32_t x, int r) {
|
||||
return (x << (r & 31)) | (x >> (-r & 31));
|
||||
}
|
||||
|
||||
void chacha8(const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher) {
|
||||
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
|
||||
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
|
||||
char* ctarget = 0;
|
||||
char tmp[64];
|
||||
int i;
|
||||
|
||||
if (!length) return;
|
||||
|
||||
j0 = U8TO32_LITTLE(sigma + 0);
|
||||
j1 = U8TO32_LITTLE(sigma + 4);
|
||||
j2 = U8TO32_LITTLE(sigma + 8);
|
||||
j3 = U8TO32_LITTLE(sigma + 12);
|
||||
j4 = U8TO32_LITTLE(key + 0);
|
||||
j5 = U8TO32_LITTLE(key + 4);
|
||||
j6 = U8TO32_LITTLE(key + 8);
|
||||
j7 = U8TO32_LITTLE(key + 12);
|
||||
j8 = U8TO32_LITTLE(key + 16);
|
||||
j9 = U8TO32_LITTLE(key + 20);
|
||||
j10 = U8TO32_LITTLE(key + 24);
|
||||
j11 = U8TO32_LITTLE(key + 28);
|
||||
j12 = 0;
|
||||
j13 = 0;
|
||||
j14 = U8TO32_LITTLE(iv + 0);
|
||||
j15 = U8TO32_LITTLE(iv + 4);
|
||||
|
||||
for (;;) {
|
||||
if (length < 64) {
|
||||
memcpy(tmp, data, length);
|
||||
data = tmp;
|
||||
ctarget = cipher;
|
||||
cipher = tmp;
|
||||
}
|
||||
x0 = j0;
|
||||
x1 = j1;
|
||||
x2 = j2;
|
||||
x3 = j3;
|
||||
x4 = j4;
|
||||
x5 = j5;
|
||||
x6 = j6;
|
||||
x7 = j7;
|
||||
x8 = j8;
|
||||
x9 = j9;
|
||||
x10 = j10;
|
||||
x11 = j11;
|
||||
x12 = j12;
|
||||
x13 = j13;
|
||||
x14 = j14;
|
||||
x15 = j15;
|
||||
for (i = 8;i > 0;i -= 2) {
|
||||
QUARTERROUND( x0, x4, x8,x12)
|
||||
QUARTERROUND( x1, x5, x9,x13)
|
||||
QUARTERROUND( x2, x6,x10,x14)
|
||||
QUARTERROUND( x3, x7,x11,x15)
|
||||
QUARTERROUND( x0, x5,x10,x15)
|
||||
QUARTERROUND( x1, x6,x11,x12)
|
||||
QUARTERROUND( x2, x7, x8,x13)
|
||||
QUARTERROUND( x3, x4, x9,x14)
|
||||
}
|
||||
x0 = PLUS( x0, j0);
|
||||
x1 = PLUS( x1, j1);
|
||||
x2 = PLUS( x2, j2);
|
||||
x3 = PLUS( x3, j3);
|
||||
x4 = PLUS( x4, j4);
|
||||
x5 = PLUS( x5, j5);
|
||||
x6 = PLUS( x6, j6);
|
||||
x7 = PLUS( x7, j7);
|
||||
x8 = PLUS( x8, j8);
|
||||
x9 = PLUS( x9, j9);
|
||||
x10 = PLUS(x10,j10);
|
||||
x11 = PLUS(x11,j11);
|
||||
x12 = PLUS(x12,j12);
|
||||
x13 = PLUS(x13,j13);
|
||||
x14 = PLUS(x14,j14);
|
||||
x15 = PLUS(x15,j15);
|
||||
|
||||
x0 = XOR( x0,U8TO32_LITTLE((uint8_t*)data + 0));
|
||||
x1 = XOR( x1,U8TO32_LITTLE((uint8_t*)data + 4));
|
||||
x2 = XOR( x2,U8TO32_LITTLE((uint8_t*)data + 8));
|
||||
x3 = XOR( x3,U8TO32_LITTLE((uint8_t*)data + 12));
|
||||
x4 = XOR( x4,U8TO32_LITTLE((uint8_t*)data + 16));
|
||||
x5 = XOR( x5,U8TO32_LITTLE((uint8_t*)data + 20));
|
||||
x6 = XOR( x6,U8TO32_LITTLE((uint8_t*)data + 24));
|
||||
x7 = XOR( x7,U8TO32_LITTLE((uint8_t*)data + 28));
|
||||
x8 = XOR( x8,U8TO32_LITTLE((uint8_t*)data + 32));
|
||||
x9 = XOR( x9,U8TO32_LITTLE((uint8_t*)data + 36));
|
||||
x10 = XOR(x10,U8TO32_LITTLE((uint8_t*)data + 40));
|
||||
x11 = XOR(x11,U8TO32_LITTLE((uint8_t*)data + 44));
|
||||
x12 = XOR(x12,U8TO32_LITTLE((uint8_t*)data + 48));
|
||||
x13 = XOR(x13,U8TO32_LITTLE((uint8_t*)data + 52));
|
||||
x14 = XOR(x14,U8TO32_LITTLE((uint8_t*)data + 56));
|
||||
x15 = XOR(x15,U8TO32_LITTLE((uint8_t*)data + 60));
|
||||
|
||||
j12 = PLUSONE(j12);
|
||||
if (!j12)
|
||||
{
|
||||
j13 = PLUSONE(j13);
|
||||
/* stopping at 2^70 bytes per iv is user's responsibility */
|
||||
}
|
||||
|
||||
U32TO8_LITTLE(cipher + 0,x0);
|
||||
U32TO8_LITTLE(cipher + 4,x1);
|
||||
U32TO8_LITTLE(cipher + 8,x2);
|
||||
U32TO8_LITTLE(cipher + 12,x3);
|
||||
U32TO8_LITTLE(cipher + 16,x4);
|
||||
U32TO8_LITTLE(cipher + 20,x5);
|
||||
U32TO8_LITTLE(cipher + 24,x6);
|
||||
U32TO8_LITTLE(cipher + 28,x7);
|
||||
U32TO8_LITTLE(cipher + 32,x8);
|
||||
U32TO8_LITTLE(cipher + 36,x9);
|
||||
U32TO8_LITTLE(cipher + 40,x10);
|
||||
U32TO8_LITTLE(cipher + 44,x11);
|
||||
U32TO8_LITTLE(cipher + 48,x12);
|
||||
U32TO8_LITTLE(cipher + 52,x13);
|
||||
U32TO8_LITTLE(cipher + 56,x14);
|
||||
U32TO8_LITTLE(cipher + 60,x15);
|
||||
|
||||
if (length <= 64) {
|
||||
if (length < 64) {
|
||||
memcpy(ctarget, cipher, length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
length -= 64;
|
||||
cipher += 64;
|
||||
data = (uint8_t*)data + 64;
|
||||
}
|
||||
}
|
||||
8
libraries/liblmdb/chacha8.h
Normal file
8
libraries/liblmdb/chacha8.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define CHACHA8_KEY_SIZE 32
|
||||
#define CHACHA8_IV_SIZE 8
|
||||
|
||||
void chacha8(const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher);
|
||||
|
||||
77
libraries/liblmdb/crypto.c
Normal file
77
libraries/liblmdb/crypto.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* crypto.c - LMDB encryption helper module */
|
||||
/*
|
||||
* Copyright 2020-2024 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the Symas
|
||||
* Dual-Use License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* source distribution.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
#include "lmdb.h"
|
||||
|
||||
#define KEYBYTES crypto_aead_chacha20poly1305_ietf_KEYBYTES
|
||||
#define NONCEBYTES crypto_aead_chacha20poly1305_ietf_NPUBBYTES
|
||||
#define MACBYTES crypto_aead_chacha20poly1305_ietf_ABYTES
|
||||
|
||||
MDB_crypto_hooks MDB_crypto;
|
||||
|
||||
static int mcf_str2key(const char *passwd, MDB_val *key)
|
||||
{
|
||||
crypto_hash_sha256_state state;
|
||||
|
||||
crypto_hash_sha256_init(&state);
|
||||
crypto_hash_sha256_update(&state, (const unsigned char *)"Just a Constant", sizeof("Just a Constant"));
|
||||
crypto_hash_sha256_update(&state, (const unsigned char *)passwd, strlen(passwd));
|
||||
crypto_hash_sha256_final(&state, key->mv_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ENC(dst, src, mac, key, iv) \
|
||||
crypto_aead_chacha20poly1305_ietf_encrypt_detached(dst->mv_data, mac, &mlen, \
|
||||
src->mv_data, src->mv_size, NULL, 0, NULL, iv, key)
|
||||
|
||||
#define DEC(dst, src, mac, key, iv) \
|
||||
crypto_aead_chacha20poly1305_ietf_decrypt_detached(dst->mv_data, NULL, src->mv_data, \
|
||||
src->mv_size, mac, NULL, 0, iv, key)
|
||||
|
||||
static int mcf_encfunc(const MDB_val *src, MDB_val *dst, const MDB_val *key, int encdec)
|
||||
{
|
||||
unsigned char iv[NONCEBYTES];
|
||||
mdb_size_t *ptr;
|
||||
int ivl, rc;
|
||||
unsigned long long mlen;
|
||||
|
||||
/* the nonce is only 12 bytes */
|
||||
ptr = key[1].mv_data;
|
||||
ivl = ptr[0] & 0xffffffff;
|
||||
memcpy(iv, &ivl, 4);
|
||||
memcpy(iv+4, ptr+1, sizeof(mdb_size_t));
|
||||
|
||||
if (encdec) {
|
||||
rc = ENC(dst, src, key[2].mv_data, key[0].mv_data, iv);
|
||||
} else {
|
||||
rc = DEC(dst, src, key[2].mv_data, key[0].mv_data, iv);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const MDB_crypto_funcs mcf_table = {
|
||||
mcf_str2key,
|
||||
mcf_encfunc,
|
||||
NULL,
|
||||
KEYBYTES,
|
||||
MACBYTES,
|
||||
0
|
||||
};
|
||||
|
||||
MDB_crypto_funcs *MDB_crypto()
|
||||
{
|
||||
return (MDB_crypto_funcs *)&mcf_table;
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ databases should only be opened once, by the first transaction in
|
|||
the process. After the first transaction completes, the database
|
||||
handles can freely be used by all subsequent transactions.
|
||||
|
||||
Within a transaction, #mdb_get() and #mdb_put() can store single
|
||||
Within a transaction, #mdb_get() can retrieve and #mdb_put() can store single
|
||||
key/value pairs if that is all you need to do (but see \ref Cursors
|
||||
below if you want to do more).
|
||||
|
||||
|
|
|
|||
|
|
@ -53,14 +53,15 @@
|
|||
*
|
||||
* Fix: Check for stale readers periodically, using the
|
||||
* #mdb_reader_check function or the \ref mdb_stat_1 "mdb_stat" tool.
|
||||
* Stale writers will be cleared automatically on some systems:
|
||||
* Stale writers will be cleared automatically on most systems:
|
||||
* - Windows - automatic
|
||||
* - BSD, systems using SysV semaphores - automatic
|
||||
* - Linux, systems using POSIX mutexes with Robust option - automatic
|
||||
* - not on BSD, systems using POSIX semaphores.
|
||||
* Otherwise just make all programs using the database close it;
|
||||
* the lockfile is always reset on first open of the environment.
|
||||
*
|
||||
* - On BSD systems or others configured with MDB_USE_POSIX_SEM,
|
||||
* - On BSD systems or others configured with MDB_USE_SYSV_SEM or
|
||||
* MDB_USE_POSIX_SEM,
|
||||
* startup can fail due to semaphores owned by another userid.
|
||||
*
|
||||
* Fix: Open and close the database as the user which owns the
|
||||
|
|
@ -135,7 +136,7 @@
|
|||
*
|
||||
* @author Howard Chu, Symas Corporation.
|
||||
*
|
||||
* @copyright Copyright 2011-2021 Howard Chu, Symas Corp. All rights reserved.
|
||||
* @copyright Copyright 2011-2026 Howard Chu, Symas Corp. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the OpenLDAP
|
||||
|
|
@ -166,6 +167,8 @@
|
|||
#define _LMDB_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -178,6 +181,37 @@ typedef int mdb_mode_t;
|
|||
typedef mode_t mdb_mode_t;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define MDB_FMT_Z "I"
|
||||
#else
|
||||
# define MDB_FMT_Z "z" /**< printf/scanf format modifier for size_t */
|
||||
#endif
|
||||
|
||||
#if !defined(MDB_RPAGE_CACHE) || (defined(MDB_VL32) && !(MDB_RPAGE_CACHE))
|
||||
/** Support #MDB_REMAP_CHUNKS. Implied by MDB_VL32. Define as 0 to disable. */
|
||||
#define MDB_RPAGE_CACHE 1
|
||||
#endif
|
||||
|
||||
#ifndef MDB_VL32
|
||||
/** Unsigned type used for mapsize, entry counts and page/transaction IDs.
|
||||
*
|
||||
* It is normally size_t, hence the name. Defining MDB_VL32 makes it
|
||||
* uint64_t, but do not try this unless you know what you are doing.
|
||||
*/
|
||||
typedef size_t mdb_size_t;
|
||||
# define MDB_SIZE_MAX SIZE_MAX /**< max #mdb_size_t */
|
||||
/** #mdb_size_t printf formats, \b t = one of [diouxX] without quotes */
|
||||
# define MDB_PRIy(t) MDB_FMT_Z #t
|
||||
/** #mdb_size_t scanf formats, \b t = one of [dioux] without quotes */
|
||||
# define MDB_SCNy(t) MDB_FMT_Z #t
|
||||
#else
|
||||
typedef uint64_t mdb_size_t;
|
||||
# define MDB_SIZE_MAX UINT64_MAX
|
||||
# define MDB_PRIy(t) PRI##t##64
|
||||
# define MDB_SCNy(t) SCN##t##64
|
||||
# define mdb_env_create mdb_env_create_vl32 /**< Prevent mixing with non-VL32 builds */
|
||||
#endif
|
||||
|
||||
/** An abstraction for a file handle.
|
||||
* On POSIX systems file handles are small integers. On Windows
|
||||
* they're opaque pointers.
|
||||
|
|
@ -190,17 +224,17 @@ typedef int mdb_filehandle_t;
|
|||
|
||||
/** @defgroup mdb LMDB API
|
||||
* @{
|
||||
* @brief OpenLDAP Lightning Memory-Mapped Database Manager
|
||||
* @brief Symas Lightning Memory-Mapped Database Manager
|
||||
*/
|
||||
/** @defgroup Version Version Macros
|
||||
* @{
|
||||
*/
|
||||
/** Library major version */
|
||||
#define MDB_VERSION_MAJOR 0
|
||||
#define MDB_VERSION_MAJOR 1
|
||||
/** Library minor version */
|
||||
#define MDB_VERSION_MINOR 9
|
||||
#define MDB_VERSION_MINOR 0
|
||||
/** Library patch version */
|
||||
#define MDB_VERSION_PATCH 35
|
||||
#define MDB_VERSION_PATCH 0
|
||||
|
||||
/** Combine args a,b,c into a single integer for easy version comparisons */
|
||||
#define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c))
|
||||
|
|
@ -210,7 +244,7 @@ typedef int mdb_filehandle_t;
|
|||
MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
|
||||
|
||||
/** The release date of this library version */
|
||||
#define MDB_VERSION_DATE "Jan 27, 2026"
|
||||
#define MDB_VERSION_DATE "April 28, 2026"
|
||||
|
||||
/** A stringifier for the version info */
|
||||
#define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")"
|
||||
|
|
@ -278,11 +312,40 @@ typedef int (MDB_cmp_func)(const MDB_val *a, const MDB_val *b);
|
|||
*/
|
||||
typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *relctx);
|
||||
|
||||
#if MDB_RPAGE_CACHE
|
||||
/** @brief A callback function used to encrypt/decrypt pages in the env.
|
||||
*
|
||||
* Encrypt or decrypt the data in src and store the result in dst using the
|
||||
* provided key. The result must be the same number of bytes as the input.
|
||||
* @param[in] src The input data to be transformed.
|
||||
* @param[out] dst Storage for the result.
|
||||
* @param[in] key An array of three values: key[0] is the encryption key,
|
||||
* key[1] is the initialization vector, and key[2] is the authentication
|
||||
* data, if any.
|
||||
* @param[in] encdec 1 to encrypt, 0 to decrypt.
|
||||
* @return A non-zero error value on failure and 0 on success.
|
||||
*/
|
||||
typedef int (MDB_enc_func)(const MDB_val *src, MDB_val *dst, const MDB_val *key, int encdec);
|
||||
|
||||
/** @brief A callback function used to checksum pages in the env.
|
||||
*
|
||||
* Compute the checksum of the data in src and store the result in dst,
|
||||
* An optional key may be used with keyed hash algorithms.
|
||||
* @param[in] src The input data to be transformed.
|
||||
* @param[out] dst Storage for the result.
|
||||
* @param[in] key An encryption key, if encryption was configured. This
|
||||
* parameter will be NULL if there is no key.
|
||||
*/
|
||||
typedef void (MDB_sum_func)(const MDB_val *src, MDB_val *dst, const MDB_val *key);
|
||||
#endif
|
||||
|
||||
/** @defgroup mdb_env Environment Flags
|
||||
* @{
|
||||
*/
|
||||
/** mmap at a fixed address (experimental) */
|
||||
#define MDB_FIXEDMAP 0x01
|
||||
/** encrypted DB - read-only flag, set by #mdb_env_set_encrypt() */
|
||||
#define MDB_ENCRYPT 0x2000U
|
||||
/** no environment directory */
|
||||
#define MDB_NOSUBDIR 0x4000
|
||||
/** don't fsync after commit */
|
||||
|
|
@ -303,6 +366,10 @@ 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
|
||||
/** use the previous snapshot rather than the latest one */
|
||||
#define MDB_PREVSNAPSHOT 0x2000000
|
||||
/** don't use a single mmap, remap individual chunks (needs MDB_RPAGE_CACHE) */
|
||||
#define MDB_REMAP_CHUNKS 0x4000000
|
||||
/** @} */
|
||||
|
||||
/** @defgroup mdb_dbi_open Database Flags
|
||||
|
|
@ -312,7 +379,8 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel
|
|||
#define MDB_REVERSEKEY 0x02
|
||||
/** use sorted duplicates */
|
||||
#define MDB_DUPSORT 0x04
|
||||
/** numeric keys in native byte order: either unsigned int or size_t.
|
||||
/** numeric keys in native byte order, either unsigned int or #mdb_size_t.
|
||||
* (lmdb expects 32-bit int <= size_t <= 32/64-bit mdb_size_t.)
|
||||
* The keys must all be of the same size. */
|
||||
#define MDB_INTEGERKEY 0x08
|
||||
/** with #MDB_DUPSORT, sorted dup items have fixed size */
|
||||
|
|
@ -448,8 +516,30 @@ typedef enum MDB_cursor_op {
|
|||
#define MDB_BAD_VALSIZE (-30781)
|
||||
/** The specified DBI was changed unexpectedly */
|
||||
#define MDB_BAD_DBI (-30780)
|
||||
/** Unexpected problem - txn should abort */
|
||||
#define MDB_PROBLEM (-30779)
|
||||
/** Page checksum incorrect */
|
||||
#define MDB_BAD_CHECKSUM (-30778)
|
||||
/** Encryption/decryption failed */
|
||||
#define MDB_CRYPTO_FAIL (-30777)
|
||||
/** Environment encryption mismatch */
|
||||
#define MDB_ENV_ENCRYPTION (-30776)
|
||||
/** Transaction was already prepared */
|
||||
#define MDB_TXN_PENDING (-30775)
|
||||
/** Environment can't rollback the last transaction */
|
||||
#define MDB_CANT_ROLLBACK (-30774)
|
||||
/** Can't drop main DBI while other DBIs are open */
|
||||
#define MDB_DBIS_BUSY (-30773)
|
||||
/** Write was incomplete */
|
||||
#define MDB_SHORT_WRITE (-30772)
|
||||
/** Env is busy, can't use previous snapshot */
|
||||
#define MDB_ENV_BUSY (-30771)
|
||||
/** Env or txn is read-only, can't write */
|
||||
#define MDB_IS_READONLY (-30770)
|
||||
/** Requested map address is unavailable */
|
||||
#define MDB_ADDR_BUSY (-30769)
|
||||
/** The last defined error code */
|
||||
#define MDB_LAST_ERRCODE MDB_BAD_DBI
|
||||
#define MDB_LAST_ERRCODE MDB_ADDR_BUSY
|
||||
/** @} */
|
||||
|
||||
/** @brief Statistics for a database in the environment */
|
||||
|
|
@ -457,18 +547,18 @@ typedef struct MDB_stat {
|
|||
unsigned int ms_psize; /**< Size of a database page.
|
||||
This is currently the same for all databases. */
|
||||
unsigned int ms_depth; /**< Depth (height) of the B-tree */
|
||||
size_t ms_branch_pages; /**< Number of internal (non-leaf) pages */
|
||||
size_t ms_leaf_pages; /**< Number of leaf pages */
|
||||
size_t ms_overflow_pages; /**< Number of overflow pages */
|
||||
size_t ms_entries; /**< Number of data items */
|
||||
mdb_size_t ms_branch_pages; /**< Number of internal (non-leaf) pages */
|
||||
mdb_size_t ms_leaf_pages; /**< Number of leaf pages */
|
||||
mdb_size_t ms_overflow_pages; /**< Number of overflow pages */
|
||||
mdb_size_t ms_entries; /**< Number of data items */
|
||||
} MDB_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 */
|
||||
void *me_mapaddr; /**< Address of map */
|
||||
mdb_size_t me_mapsize; /**< Size of the data memory map */
|
||||
mdb_size_t me_last_pgno; /**< ID of the last used page */
|
||||
mdb_size_t me_last_txnid; /**< ID of the last committed transaction */
|
||||
unsigned int me_maxreaders; /**< max reader slots in the environment */
|
||||
unsigned int me_numreaders; /**< max reader slots used in the environment */
|
||||
} MDB_envinfo;
|
||||
|
|
@ -614,6 +704,12 @@ int mdb_env_create(MDB_env **env);
|
|||
* caller is expected to overwrite all of the memory that was
|
||||
* reserved in that case.
|
||||
* This flag may be changed at any time using #mdb_env_set_flags().
|
||||
* <li>#MDB_PREVSNAPSHOT
|
||||
* Open the environment with the previous snapshot rather than the latest
|
||||
* one. This loses the latest transaction, but may help work around some
|
||||
* types of corruption. If opened with write access, this must be the
|
||||
* only process using the environment. This flag is automatically reset
|
||||
* after a write transaction is successfully committed.
|
||||
* </ul>
|
||||
* @param[in] mode The UNIX permissions to set on created files and semaphores.
|
||||
* This parameter is ignored on Windows.
|
||||
|
|
@ -705,6 +801,55 @@ int mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags);
|
|||
*/
|
||||
int mdb_env_copyfd2(MDB_env *env, mdb_filehandle_t fd, unsigned int flags);
|
||||
|
||||
/** @brief Perform incremental dump of an LMDB environment to the
|
||||
* specified file descriptor.
|
||||
*
|
||||
* This function may be used to make an incremental backup of an
|
||||
* existing environment.
|
||||
* @note This call can trigger significant file size growth if run in
|
||||
* parallel with write transactions, because it employs a read-only
|
||||
* transaction. See long-lived transactions under @ref caveats_sec.
|
||||
* @param[in] env An environment handle returned by #mdb_env_create(). It
|
||||
* must have already been opened successfully.
|
||||
* @param[in] fd The filedescriptor to write the copy to. It must
|
||||
* have already been opened for Write access.
|
||||
* @param[in] txnid The transaction ID of a previous backup. It must
|
||||
* be greater than zero.
|
||||
* @return A non-zero error value on failure and 0 on success.
|
||||
*/
|
||||
int mdb_env_incr_dumpfd(MDB_env *env, mdb_filehandle_t fd, size_t txnid);
|
||||
|
||||
/** @brief Perform incremental dump of an LMDB environment to the
|
||||
* specified file.
|
||||
*
|
||||
* This function may be used to make an incremental backup of an
|
||||
* existing environment.
|
||||
* @note This call can trigger significant file size growth if run in
|
||||
* parallel with write transactions, because it employs a read-only
|
||||
* transaction. See long-lived transactions under @ref caveats_sec.
|
||||
* @param[in] env An environment handle returned by #mdb_env_create(). It
|
||||
* must have already been opened successfully.
|
||||
* @param[in] path The name of the file to write the copy to. It must
|
||||
* not already exist.
|
||||
* @param[in] txnid The transaction ID of a previous backup. It must
|
||||
* be greater than zero.
|
||||
* @return A non-zero error value on failure and 0 on success.
|
||||
*/
|
||||
int mdb_env_incr_dump(MDB_env *env, const char *path, size_t txnid);
|
||||
|
||||
/** @brief Reload an incremental dump of an LMDB environment from the
|
||||
* specified file descriptor.
|
||||
*
|
||||
* This function may be used to load an incremental backup of an
|
||||
* existing environment.
|
||||
* @note No other tasks may access the environment while this runs.
|
||||
* @param[in] env An environment handle returned by #mdb_env_create(). It
|
||||
* must have already been opened successfully, using #MDB_WRITEMAP.
|
||||
* @param[in] fd The filedescriptor to read the backup from.
|
||||
* @return A non-zero error value on failure and 0 on success.
|
||||
*/
|
||||
int mdb_env_incr_loadfd(MDB_env *env, mdb_filehandle_t fd);
|
||||
|
||||
/** @brief Return statistics about the LMDB environment.
|
||||
*
|
||||
* @param[in] env An environment handle returned by #mdb_env_create()
|
||||
|
|
@ -842,7 +987,17 @@ int mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *fd);
|
|||
* an active write transaction.
|
||||
* </ul>
|
||||
*/
|
||||
int mdb_env_set_mapsize(MDB_env *env, size_t size);
|
||||
int mdb_env_set_mapsize(MDB_env *env, mdb_size_t size);
|
||||
|
||||
|
||||
/** @brief Set the size of DB pages in bytes.
|
||||
*
|
||||
* The size defaults to the OS page size. Smaller or larger values may be
|
||||
* desired depending on the size of keys and values being used. Also, an
|
||||
* explicit size may need to be set when using filesystems like ZFS which
|
||||
* don't use the OS page size.
|
||||
*/
|
||||
int mdb_env_set_pagesize(MDB_env *env, int size);
|
||||
|
||||
/** @brief Set the maximum number of threads/reader slots for the environment.
|
||||
*
|
||||
|
|
@ -936,6 +1091,31 @@ typedef void MDB_assert_func(MDB_env *env, const char *msg);
|
|||
*/
|
||||
int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func);
|
||||
|
||||
#if MDB_RPAGE_CACHE
|
||||
/** @brief Set encryption on an environment.
|
||||
*
|
||||
* This must be called before #mdb_env_open().
|
||||
* It implicitly sets #MDB_REMAP_CHUNKS on the env.
|
||||
* @param[in] env An environment handle returned by #mdb_env_create().
|
||||
* @param[in] func An #MDB_enc_func function.
|
||||
* @param[in] key The encryption key.
|
||||
* @param[in] size The size of authentication data in bytes, if any.
|
||||
* Set this to zero for unauthenticated encryption mechanisms.
|
||||
* @return A non-zero error value on failure and 0 on success.
|
||||
*/
|
||||
int mdb_env_set_encrypt(MDB_env *env, MDB_enc_func *func, const MDB_val *key, unsigned int size);
|
||||
|
||||
/** @brief Set checksums on an environment.
|
||||
*
|
||||
* This must be called before #mdb_env_open().
|
||||
* @param[in] env An environment handle returned by #mdb_env_create().
|
||||
* @param[in] func An #MDB_sum_func function.
|
||||
* @param[in] size The size of computed checksum values, in bytes.
|
||||
* @return A non-zero error value on failure and 0 on success.
|
||||
*/
|
||||
int mdb_env_set_checksum(MDB_env *env, MDB_sum_func *func, unsigned int size);
|
||||
#endif
|
||||
|
||||
/** @brief Create a transaction for use with the environment.
|
||||
*
|
||||
* The transaction handle may be discarded using #mdb_txn_abort() or #mdb_txn_commit().
|
||||
|
|
@ -949,12 +1129,20 @@ int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func);
|
|||
* as its parent. Transactions may be nested to any level. A parent
|
||||
* transaction and its cursors may not issue any other operations than
|
||||
* mdb_txn_commit and mdb_txn_abort while it has active child transactions.
|
||||
* @note A parent transaction with read-only child transactions must not
|
||||
* issue any operations while it has active child transactions, not even
|
||||
* #mdb_txn_commit() nor #mdb_txn_abort(). Child transactions must be
|
||||
* aborted prior to performing actions with the parent one.
|
||||
* @param[in] flags Special options for this transaction. This parameter
|
||||
* must be set to 0 or by bitwise OR'ing together one or more of the
|
||||
* values described here.
|
||||
* <ul>
|
||||
* <li>#MDB_RDONLY
|
||||
* This transaction will not perform any write operations.
|
||||
* <li>#MDB_NOSYNC
|
||||
* Don't flush system buffers to disk when committing this transaction.
|
||||
* <li>#MDB_NOMETASYNC
|
||||
* Flush system buffers but omit metadata flush when committing this transaction.
|
||||
* </ul>
|
||||
* @param[out] txn Address where the new #MDB_txn handle will be stored
|
||||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
|
|
@ -987,7 +1175,15 @@ MDB_env *mdb_txn_env(MDB_txn *txn);
|
|||
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
||||
* @return A transaction ID, valid if input is an active transaction.
|
||||
*/
|
||||
size_t mdb_txn_id(MDB_txn *txn);
|
||||
mdb_size_t mdb_txn_id(MDB_txn *txn);
|
||||
|
||||
/** @brief Retrieve the transaction's flags
|
||||
*
|
||||
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
||||
* @param[out] flags Address where the flags will be returned.
|
||||
* @return A non-zero error value on failure and 0 on success.
|
||||
*/
|
||||
int mdb_txn_flags(MDB_txn *txn, unsigned int *flags);
|
||||
|
||||
/** @brief Commit all the operations of a transaction into the database.
|
||||
*
|
||||
|
|
@ -1007,6 +1203,55 @@ size_t mdb_txn_id(MDB_txn *txn);
|
|||
*/
|
||||
int mdb_txn_commit(MDB_txn *txn);
|
||||
|
||||
/** @brief Prepare to commit all the operations of a transaction into the database.
|
||||
*
|
||||
* This function exists to support two-phase commit protocols.
|
||||
* All writes in the transaction are persisted to storage, but the final
|
||||
* metapage update is not performed. All cursors on the transaction will be
|
||||
* closed. Only #mdb_txn_abort() or #mdb_txn_commit() are valid after this
|
||||
* call. It is assumed that once the regular data pages are successfully written
|
||||
* by this call, the metapage update from a subsequent commit cannot fail, but
|
||||
* hardware-level media failures could still break this assumption.
|
||||
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
||||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
* errors are:
|
||||
* <ul>
|
||||
* <li>EINVAL - an invalid parameter was specified.
|
||||
* <li>ENOSPC - no more disk space.
|
||||
* <li>EIO - a low-level I/O error occurred while writing.
|
||||
* <li>ENOMEM - out of memory.
|
||||
* <li>#MDB_TXN_PENDING - the transaction has already been prepared.
|
||||
* It can only be aborted or committed.
|
||||
* </ul>
|
||||
*/
|
||||
int mdb_txn_prepare(MDB_txn *txn);
|
||||
|
||||
/** @brief Rollback the last committed transaction in the environment.
|
||||
*
|
||||
* This function exists to support two-phase commit protocols.
|
||||
* The metapage update for the last committed transaction will be zeroed,
|
||||
* so its changes will be ignored. It should only be used when the local
|
||||
* phase of a multi-phase transaction has fully committed, but some other
|
||||
* remote phase which successfully prepared has failed to commit.
|
||||
* This function may not be called twice in a row. No other operations
|
||||
* may be performed on the environment, by any processes, between the
|
||||
* preceding #mdb_txn_commit() and this call.
|
||||
* @param[in] env An environment handle returned by #mdb_env_create().
|
||||
* @param[in] txnid The ID of the transaction to rollback, obtained from
|
||||
* #mdb_txnid() on the previous transaction.
|
||||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
* errors are:
|
||||
* <ul>
|
||||
* <li>EINVAL - an invalid parameter was specified.
|
||||
* <li>ENOSPC - no more disk space.
|
||||
* <li>EIO - a low-level I/O error occurred while writing.
|
||||
* <li>#MDB_CANT_ROLLBACK - a rollback has already been done, there is
|
||||
* no other valid metapage to roll back to, or another transaction
|
||||
* has already been committed over the specified txnid.
|
||||
* </ul>
|
||||
*/
|
||||
int mdb_env_rollback(MDB_env *env, mdb_size_t txnid);
|
||||
|
||||
/** @brief Abandon all the operations of the transaction instead of saving them.
|
||||
*
|
||||
* The transaction handle is freed. It and its cursors must not be used
|
||||
|
|
@ -1017,7 +1262,7 @@ int mdb_txn_commit(MDB_txn *txn);
|
|||
*/
|
||||
void mdb_txn_abort(MDB_txn *txn);
|
||||
|
||||
/** @brief Reset a read-only transaction.
|
||||
/** @brief Reset a non-nested read-only transaction.
|
||||
*
|
||||
* Abort the transaction like #mdb_txn_abort(), but keep the transaction
|
||||
* handle. #mdb_txn_renew() may reuse the handle. This saves allocation
|
||||
|
|
@ -1036,11 +1281,11 @@ void mdb_txn_abort(MDB_txn *txn);
|
|||
*/
|
||||
void mdb_txn_reset(MDB_txn *txn);
|
||||
|
||||
/** @brief Renew a read-only transaction.
|
||||
/** @brief Renew a non-nested read-only transaction.
|
||||
*
|
||||
* This acquires a new reader lock for a transaction handle that had been
|
||||
* released by #mdb_txn_reset(). It must be called before a reset transaction
|
||||
* may be used again.
|
||||
* may be used again. Nested read-only transactions cannot be renewed.
|
||||
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
||||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
* errors are:
|
||||
|
|
@ -1079,6 +1324,8 @@ int mdb_txn_renew(MDB_txn *txn);
|
|||
* To use named databases (with name != NULL), #mdb_env_set_maxdbs()
|
||||
* must be called before opening the environment. Database names are
|
||||
* keys in the unnamed database, and may be read but not written.
|
||||
* @note Names are C strings and stored with their NUL terminator included.
|
||||
* In LMDB 0.9 the NUL terminator was omitted.
|
||||
*
|
||||
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
||||
* @param[in] name The name of the database to open. If only a single
|
||||
|
|
@ -1097,7 +1344,8 @@ int mdb_txn_renew(MDB_txn *txn);
|
|||
* keys must be unique and may have only a single data item.
|
||||
* <li>#MDB_INTEGERKEY
|
||||
* Keys are binary integers in native byte order, either unsigned int
|
||||
* or size_t, and will be sorted as such.
|
||||
* or #mdb_size_t, and will be sorted as such.
|
||||
* (lmdb expects 32-bit int <= size_t <= 32/64-bit mdb_size_t.)
|
||||
* The keys must all be of the same size.
|
||||
* <li>#MDB_DUPFIXED
|
||||
* This flag may only be used in combination with #MDB_DUPSORT. This option
|
||||
|
|
@ -1423,6 +1671,13 @@ MDB_txn *mdb_cursor_txn(MDB_cursor *cursor);
|
|||
*/
|
||||
MDB_dbi mdb_cursor_dbi(MDB_cursor *cursor);
|
||||
|
||||
/** @brief Check if the cursor is pointing to a named database record.
|
||||
*
|
||||
* @param[in] cursor A cursor handle returned by #mdb_cursor_open()
|
||||
* @return 1 if current record is a named database, 0 otherwise.
|
||||
*/
|
||||
int mdb_cursor_is_db(MDB_cursor *cursor);
|
||||
|
||||
/** @brief Retrieve by cursor.
|
||||
*
|
||||
* This function retrieves key/data pairs from the database. The address and length
|
||||
|
|
@ -1542,7 +1797,7 @@ int mdb_cursor_del(MDB_cursor *cursor, unsigned int flags);
|
|||
* <li>EINVAL - cursor is not initialized, or an invalid parameter was specified.
|
||||
* </ul>
|
||||
*/
|
||||
int mdb_cursor_count(MDB_cursor *cursor, size_t *countp);
|
||||
int mdb_cursor_count(MDB_cursor *cursor, mdb_size_t *countp);
|
||||
|
||||
/** @brief Compare two data items according to a particular database.
|
||||
*
|
||||
|
|
@ -1594,12 +1849,81 @@ int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx);
|
|||
int mdb_reader_check(MDB_env *env, int *dead);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup crypto LMDB Encryption Helper API
|
||||
* @{
|
||||
* @brief Helpers for setting up encryption
|
||||
*/
|
||||
|
||||
/** @brief A function for converting a string into an encryption key.
|
||||
*
|
||||
* @param[in] passwd The string to be converted.
|
||||
* @param[in,out] key The resulting key. The caller must
|
||||
* provide the space for the key.
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
typedef int (MDB_str2key_func)(const char *passwd, MDB_val *key);
|
||||
|
||||
/** @brief A structure for dynamically loaded crypto modules.
|
||||
*
|
||||
* This is the information that the command line tools expect
|
||||
* in order to operate on encrypted or checksummed environments.
|
||||
*/
|
||||
typedef struct MDB_crypto_funcs {
|
||||
MDB_str2key_func *mcf_str2key;
|
||||
MDB_enc_func *mcf_encfunc;
|
||||
MDB_sum_func *mcf_sumfunc;
|
||||
int mcf_keysize; /**< The size of an encryption key, in bytes */
|
||||
int mcf_esumsize; /**< The size of the MAC, for authenticated encryption */
|
||||
int mcf_sumsize; /**< The size of the checksum, for plain checksums */
|
||||
} MDB_crypto_funcs;
|
||||
|
||||
/** @brief The function that returns the #MDB_crypto_funcs structure.
|
||||
*
|
||||
* The command line tools expect this function to be named "MDB_crypto".
|
||||
* It must be exported by the dynamic module so that the tools can use it.
|
||||
* @return A pointer to a #MDB_crypto_funcs structure.
|
||||
*/
|
||||
typedef MDB_crypto_funcs *(MDB_crypto_hooks)(void);
|
||||
|
||||
/** @brief Load a dynamically loadable module.
|
||||
*
|
||||
* @param[in] file The pathname of the module to load.
|
||||
* @param[in] symname The name of a symbol to resolve in the module.
|
||||
* @param[out] mcf_ptr The crypto hooks returned from the module.
|
||||
* @param[out] errmsg Messages for any errors from trying to load the module.
|
||||
* @return The handle to the loadable module that can be unloaded by #mdb_modunload(),
|
||||
* or NULL if loading failed.
|
||||
*/
|
||||
void *mdb_modload(const char *file, const char *symname,
|
||||
MDB_crypto_funcs **mcf_ptr, char **errmsg);
|
||||
|
||||
/** @brief Unload a dynamically loaded module.
|
||||
*
|
||||
* All environments that used the functions in the module must be closed
|
||||
* before unloading the module.
|
||||
* @param[in] handle The handle returned by #mdb_modload().
|
||||
*/
|
||||
void mdb_modunload(void *handle);
|
||||
|
||||
/** @brief Set an environment to use the given crypto functions.
|
||||
*
|
||||
* This is just a wrapper around #mdb_env_set_encrypt() to ease use of
|
||||
* dynamically loaded crypto functions.
|
||||
* @param[in] env An environment handle returned by #mdb_env_create()
|
||||
* @param[in] funcs The crypto hooks retrieved by #mdb_modload().
|
||||
* @param[in] passphrase The secret used to generate the encryption key for the environment.
|
||||
*/
|
||||
void mdb_modsetup(MDB_env *env, MDB_crypto_funcs *cf, const char *passphrase);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** @page tools LMDB Command Line Tools
|
||||
The following describes the command line tools that are available for LMDB.
|
||||
\li \ref mdb_copy_1
|
||||
\li \ref mdb_drop_1
|
||||
\li \ref mdb_dump_1
|
||||
\li \ref mdb_load_1
|
||||
\li \ref mdb_stat_1
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_COPY 1 "2014/07/01" "LMDB 0.9.14"
|
||||
.\" Copyright 2012-2021 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.TH MDB_COPY 1 "2026/04/28" "LMDB 1.0.0"
|
||||
.\" Copyright 2012-2026 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_copy \- LMDB environment copy tool
|
||||
|
|
@ -11,6 +11,14 @@ mdb_copy \- LMDB environment copy tool
|
|||
.BR \-c ]
|
||||
[\c
|
||||
.BR \-n ]
|
||||
[\c
|
||||
.BR \-L ]
|
||||
[\c
|
||||
.BR \-v ]
|
||||
[\c
|
||||
.BI \-m \ module
|
||||
[\c
|
||||
.BI \-w \ password\fR]]
|
||||
.B srcpath
|
||||
[\c
|
||||
.BR dstpath ]
|
||||
|
|
@ -40,6 +48,23 @@ Currently it fails if the environment has suffered a page leak.
|
|||
.TP
|
||||
.BR \-n
|
||||
Open LDMB environment(s) which do not use subdirectories.
|
||||
.TP
|
||||
.BR \-L
|
||||
Access the LMDB environment without any locking. If concurrent
|
||||
access is anticipated, the caller must manage all concurrency itself.
|
||||
.TP
|
||||
.BR \-v
|
||||
Use the previous environment state instead of the latest state.
|
||||
This may be useful if the latest state has been corrupted.
|
||||
.TP
|
||||
.BI \-m \ module
|
||||
Load the specified dynamic module to utilize cryptographic functions.
|
||||
This is required to operate on environments that have been configured
|
||||
with page-level checksums or encryption.
|
||||
.TP
|
||||
.BI \-w \ password
|
||||
Specify the password for an encrypted environment. This is only
|
||||
used if a cryptography module has been loaded.
|
||||
|
||||
.SH DIAGNOSTICS
|
||||
Exit status is zero if no errors occur.
|
||||
|
|
|
|||
|
|
@ -34,24 +34,40 @@ int main(int argc,char * argv[])
|
|||
const char *progname = argv[0], *act;
|
||||
unsigned flags = MDB_RDONLY;
|
||||
unsigned cpflags = 0;
|
||||
char *module = NULL, *password = NULL;
|
||||
void *mlm = NULL;
|
||||
char *errmsg;
|
||||
|
||||
for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) {
|
||||
if (argv[1][1] == 'n' && argv[1][2] == '\0')
|
||||
flags |= MDB_NOSUBDIR;
|
||||
else if (argv[1][1] == 'L' && argv[1][2] == '\0')
|
||||
flags |= MDB_NOLOCK;
|
||||
else if (argv[1][1] == 'v' && argv[1][2] == '\0')
|
||||
flags |= MDB_PREVSNAPSHOT;
|
||||
else if (argv[1][1] == 'c' && argv[1][2] == '\0')
|
||||
cpflags |= MDB_CP_COMPACT;
|
||||
else if (argv[1][1] == 'V' && argv[1][2] == '\0') {
|
||||
printf("%s\n", MDB_VERSION_STRING);
|
||||
exit(0);
|
||||
} else if (argv[1][1] == 'm' && argv[1][2] == '\0') {
|
||||
module = argv[2];
|
||||
argc--;
|
||||
argv++;
|
||||
} else if (argv[1][1] == 'w' && argv[1][2] == '\0') {
|
||||
password = argv[2];
|
||||
argc--;
|
||||
argv++;
|
||||
} else
|
||||
argc = 0;
|
||||
}
|
||||
|
||||
if (argc<2 || argc>3) {
|
||||
fprintf(stderr, "usage: %s [-V] [-c] [-n] srcpath [dstpath]\n", progname);
|
||||
fprintf(stderr, "usage: %s [-V] [-c] [-n] [-L] [-v] [-m module [-w password]] srcpath [dstpath]\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
#ifdef SIGPIPE
|
||||
signal(SIGPIPE, sighandle);
|
||||
#endif
|
||||
|
|
@ -64,6 +80,15 @@ int main(int argc,char * argv[])
|
|||
act = "opening environment";
|
||||
rc = mdb_env_create(&env);
|
||||
if (rc == MDB_SUCCESS) {
|
||||
if (module) {
|
||||
MDB_crypto_funcs *mcf;
|
||||
mlm = mdb_modload(module, NULL, &mcf, &errmsg);
|
||||
if (!mlm) {
|
||||
fprintf(stderr, "Failed to load crypto module: %s\n", errmsg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
mdb_modsetup(env, mcf, password);
|
||||
}
|
||||
rc = mdb_env_open(env, argv[1], flags, 0600);
|
||||
}
|
||||
if (rc == MDB_SUCCESS) {
|
||||
|
|
@ -77,6 +102,8 @@ int main(int argc,char * argv[])
|
|||
fprintf(stderr, "%s: %s failed, error %d (%s)\n",
|
||||
progname, act, rc, mdb_strerror(rc));
|
||||
mdb_env_close(env);
|
||||
if (mlm)
|
||||
mdb_modunload(mlm);
|
||||
|
||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
59
libraries/liblmdb/mdb_drop.1
Normal file
59
libraries/liblmdb/mdb_drop.1
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
.TH MDB_DROP 1 "2026/04/28" "LMDB 1.0.0"
|
||||
.\" Copyright 2014-2026 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_drop \- LMDB database delete tool
|
||||
.SH SYNOPSIS
|
||||
.B mdb_drop
|
||||
[\c
|
||||
.BR \-V ]
|
||||
[\c
|
||||
.BR \-n ]
|
||||
[\c
|
||||
.BR \-L ]
|
||||
[\c
|
||||
.BR \-d ]
|
||||
[\c
|
||||
.BI \-m \ module
|
||||
[\c
|
||||
.BI \-w \ password\fR]]
|
||||
[\c
|
||||
.BI \-s \ subdb\fR]
|
||||
.BR \ envpath
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.B mdb_drop
|
||||
utility empties or deletes a database in the specified
|
||||
environment.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR \-V
|
||||
Write the library version number to the standard output, and exit.
|
||||
.TP
|
||||
.BR \-n
|
||||
Operate on an LMDB environment which does not use subdirectories.
|
||||
.TP
|
||||
.BR \-L
|
||||
Access the LMDB environment without any locking. If concurrent
|
||||
access is anticipated, the caller must manage all concurrency itself.
|
||||
.TP
|
||||
.BR \-d
|
||||
Delete the specified database, don't just empty it.
|
||||
.TP
|
||||
.BI \-m \ module
|
||||
Load the specified dynamic module to utilize cryptographic functions.
|
||||
This is required to operate on environments that have been configured
|
||||
with page-level checksums or encryption.
|
||||
.TP
|
||||
.BI \-w \ password
|
||||
Specify the password for an encrypted environment. This is only
|
||||
used if a cryptography module has been loaded.
|
||||
.TP
|
||||
.BR \-s \ subdb
|
||||
Operate on a specific subdatabase. If no database is specified, only the main database is dropped.
|
||||
.SH DIAGNOSTICS
|
||||
Exit status is zero if no errors occur.
|
||||
Errors result in a non-zero exit status and
|
||||
a diagnostic message being written to standard error.
|
||||
.SH AUTHOR
|
||||
Howard Chu of Symas Corporation <http://www.symas.com>
|
||||
159
libraries/liblmdb/mdb_drop.c
Normal file
159
libraries/liblmdb/mdb_drop.c
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
/* mdb_drop.c - memory-mapped database delete tool */
|
||||
/*
|
||||
* Copyright 2016-2021 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the OpenLDAP
|
||||
* Public License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* top-level directory of the distribution or, alternatively, at
|
||||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include "lmdb.h"
|
||||
|
||||
static volatile sig_atomic_t gotsig;
|
||||
|
||||
static void dumpsig( int sig )
|
||||
{
|
||||
gotsig=1;
|
||||
}
|
||||
|
||||
static void usage(char *prog)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-V] [-n] [-L] [-d] [-m module [-w password]] [-s subdb] dbpath\n", prog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, rc;
|
||||
MDB_env *env;
|
||||
MDB_txn *txn;
|
||||
MDB_dbi dbi;
|
||||
char *prog = argv[0];
|
||||
char *envname;
|
||||
char *subname = NULL;
|
||||
int envflags = 0, delete = 0;
|
||||
char *module = NULL, *password = NULL;
|
||||
void *mlm = NULL;
|
||||
char *errmsg;
|
||||
|
||||
if (argc < 2) {
|
||||
usage(prog);
|
||||
}
|
||||
|
||||
/* -d: delete the db, don't just empty it
|
||||
* -s: drop the named subDB
|
||||
* -n: use NOSUBDIR flag on env_open
|
||||
* -L: use NOLOCK flag on env_open
|
||||
* -V: print version and exit
|
||||
* (default) empty the main DB
|
||||
*/
|
||||
while ((i = getopt(argc, argv, "dm:nLs:w:V")) != EOF) {
|
||||
switch(i) {
|
||||
case 'V':
|
||||
printf("%s\n", MDB_VERSION_STRING);
|
||||
exit(0);
|
||||
break;
|
||||
case 'd':
|
||||
delete = 1;
|
||||
break;
|
||||
case 'n':
|
||||
envflags |= MDB_NOSUBDIR;
|
||||
break;
|
||||
case 'L':
|
||||
envflags |= MDB_NOLOCK;
|
||||
break;
|
||||
case 's':
|
||||
subname = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
module = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
password = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(prog);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind != argc - 1)
|
||||
usage(prog);
|
||||
|
||||
#ifdef SIGPIPE
|
||||
signal(SIGPIPE, dumpsig);
|
||||
#endif
|
||||
#ifdef SIGHUP
|
||||
signal(SIGHUP, dumpsig);
|
||||
#endif
|
||||
signal(SIGINT, dumpsig);
|
||||
signal(SIGTERM, dumpsig);
|
||||
|
||||
envname = argv[optind];
|
||||
rc = mdb_env_create(&env);
|
||||
if (rc) {
|
||||
fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (module) {
|
||||
MDB_crypto_funcs *mcf;
|
||||
mlm = mdb_modload(module, NULL, &mcf, &errmsg);
|
||||
if (!mlm) {
|
||||
fprintf(stderr, "Failed to load crypto module: %s\n", errmsg);
|
||||
goto env_close;
|
||||
}
|
||||
mdb_modsetup(env, mcf, password);
|
||||
}
|
||||
|
||||
mdb_env_set_maxdbs(env, 2);
|
||||
|
||||
rc = mdb_env_open(env, envname, envflags, 0664);
|
||||
if (rc) {
|
||||
fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
|
||||
rc = mdb_txn_begin(env, NULL, 0, &txn);
|
||||
if (rc) {
|
||||
fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
|
||||
rc = mdb_open(txn, subname, 0, &dbi);
|
||||
if (rc) {
|
||||
fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto txn_abort;
|
||||
}
|
||||
|
||||
rc = mdb_drop(txn, dbi, delete);
|
||||
if (rc) {
|
||||
fprintf(stderr, "mdb_drop failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto txn_abort;
|
||||
}
|
||||
rc = mdb_txn_commit(txn);
|
||||
if (rc) {
|
||||
fprintf(stderr, "mdb_txn_commit failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto txn_abort;
|
||||
}
|
||||
txn = NULL;
|
||||
|
||||
txn_abort:
|
||||
if (txn)
|
||||
mdb_txn_abort(txn);
|
||||
env_close:
|
||||
mdb_env_close(env);
|
||||
if (mlm)
|
||||
mdb_modunload(mlm);
|
||||
|
||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_DUMP 1 "2015/09/30" "LMDB 0.9.17"
|
||||
.\" Copyright 2014-2021 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.TH MDB_DUMP 1 "2026/04/28" "LMDB 1.0.0"
|
||||
.\" Copyright 2014-2026 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_dump \- LMDB environment export tool
|
||||
|
|
@ -10,12 +10,22 @@ mdb_dump \- LMDB environment export tool
|
|||
[\c
|
||||
.BI \-f \ file\fR]
|
||||
[\c
|
||||
.BI \-i \ txnid\fR]
|
||||
[\c
|
||||
.BR \-l ]
|
||||
[\c
|
||||
.BR \-n ]
|
||||
[\c
|
||||
.BR \-v ]
|
||||
[\c
|
||||
.BR \-L ]
|
||||
[\c
|
||||
.BR \-p ]
|
||||
[\c
|
||||
.BI \-m \ module
|
||||
[\c
|
||||
.BI \-w \ password\fR]]
|
||||
[\c
|
||||
.BR \-a \ |
|
||||
.BI \-s \ subdb\fR]
|
||||
.BR \ envpath
|
||||
|
|
@ -35,12 +45,26 @@ Write the library version number to the standard output, and exit.
|
|||
.BR \-f \ file
|
||||
Write to the specified file instead of to the standard output.
|
||||
.TP
|
||||
.BR \-i \ txnid
|
||||
Perform an incremental backup. Only pages that have been modified
|
||||
after the given transaction ID will be written in the dump.
|
||||
|
||||
Note: This is a raw binary dump of the database pages, not the portable output format.
|
||||
.TP
|
||||
.BR \-l
|
||||
List the databases stored in the environment. Just the
|
||||
names will be listed, no data will be output.
|
||||
.TP
|
||||
.BR \-n
|
||||
Dump an LMDB database which does not use subdirectories.
|
||||
Dump an LMDB environment which does not use subdirectories.
|
||||
.TP
|
||||
.BR \-v
|
||||
Use the previous environment state instead of the latest state.
|
||||
This may be useful if the latest state has been corrupted.
|
||||
.TP
|
||||
.BR \-L
|
||||
Access the LMDB environment without any locking. If concurrent access is
|
||||
anticipated, the caller must manage all concurrency itself.
|
||||
.TP
|
||||
.BR \-p
|
||||
If characters in either the key or data items are printing characters (as
|
||||
|
|
@ -51,6 +75,15 @@ Note: different systems may have different notions about what characters
|
|||
are considered printing characters, and databases dumped in this manner may
|
||||
be less portable to external systems.
|
||||
.TP
|
||||
.BI \-m \ module
|
||||
Load the specified dynamic module to utilize cryptographic functions.
|
||||
This is required to operate on environments that have been configured
|
||||
with page-level checksums or encryption.
|
||||
.TP
|
||||
.BI \-w \ password
|
||||
Specify the password for an encrypted environment. This is only
|
||||
used if a cryptography module has been loaded.
|
||||
.TP
|
||||
.BR \-a
|
||||
Dump all of the subdatabases in the environment.
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -21,11 +21,14 @@
|
|||
#include "lmdb.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define Z "I"
|
||||
#include <windows.h>
|
||||
#define MDB_STDOUT GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
#else
|
||||
#define Z "z"
|
||||
#define MDB_STDOUT 1
|
||||
#endif
|
||||
|
||||
#define Yu MDB_PRIy(u)
|
||||
|
||||
#define PRINT 1
|
||||
static int mode;
|
||||
|
||||
|
|
@ -80,7 +83,7 @@ static void text(MDB_val *v)
|
|||
putchar('\n');
|
||||
}
|
||||
|
||||
static void byte(MDB_val *v)
|
||||
static void dobyte(MDB_val *v)
|
||||
{
|
||||
unsigned char *c, *end;
|
||||
|
||||
|
|
@ -117,7 +120,7 @@ static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name)
|
|||
if (name)
|
||||
printf("database=%s\n", name);
|
||||
printf("type=btree\n");
|
||||
printf("mapsize=%" Z "u\n", info.me_mapsize);
|
||||
printf("mapsize=%"Yu"\n", info.me_mapsize);
|
||||
if (info.me_mapaddr)
|
||||
printf("mapaddr=%p\n", info.me_mapaddr);
|
||||
printf("maxreaders=%u\n", info.me_maxreaders);
|
||||
|
|
@ -135,7 +138,7 @@ static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name)
|
|||
rc = mdb_cursor_open(txn, dbi, &mc);
|
||||
if (rc) return rc;
|
||||
|
||||
while ((rc = mdb_cursor_get(mc, &key, &data, MDB_NEXT) == MDB_SUCCESS)) {
|
||||
while ((rc = mdb_cursor_get(mc, &key, &data, MDB_NEXT)) == MDB_SUCCESS) {
|
||||
if (gotsig) {
|
||||
rc = EINTR;
|
||||
break;
|
||||
|
|
@ -144,8 +147,8 @@ static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name)
|
|||
text(&key);
|
||||
text(&data);
|
||||
} else {
|
||||
byte(&key);
|
||||
byte(&data);
|
||||
dobyte(&key);
|
||||
dobyte(&data);
|
||||
}
|
||||
}
|
||||
printf("DATA=END\n");
|
||||
|
|
@ -157,7 +160,7 @@ static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name)
|
|||
|
||||
static void usage(char *prog)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb] dbpath\n", prog);
|
||||
fprintf(stderr, "usage: %s [-V] [-f output] [-i txnid] [-l] [-n] [-L] [-p] [-v] [-m module [-w password]] [-a|-s subdb] dbpath\n", prog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -168,23 +171,29 @@ int main(int argc, char *argv[])
|
|||
MDB_txn *txn;
|
||||
MDB_dbi dbi;
|
||||
char *prog = argv[0];
|
||||
char *envname;
|
||||
char *envname, *outname = NULL;
|
||||
char *subname = NULL;
|
||||
size_t txnid = 0;
|
||||
int alldbs = 0, envflags = 0, list = 0;
|
||||
char *module = NULL, *password = NULL, *errmsg;
|
||||
void *mlm = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
usage(prog);
|
||||
}
|
||||
|
||||
/* -a: dump main DB and all subDBs
|
||||
/* -a: dump all subDBs
|
||||
* -s: dump only the named subDB
|
||||
* -n: use NOSUBDIR flag on env_open
|
||||
* -n: use NOLOCK flag on env_open
|
||||
* -p: use printable characters
|
||||
* -f: write to file instead of stdout
|
||||
* -i: do incremental dump from txnid
|
||||
* -v: use previous snapshot
|
||||
* -V: print version and exit
|
||||
* (default) dump only the main DB
|
||||
*/
|
||||
while ((i = getopt(argc, argv, "af:lnps:V")) != EOF) {
|
||||
while ((i = getopt(argc, argv, "af:i:lm:nLps:vw:V")) != EOF) {
|
||||
switch(i) {
|
||||
case 'V':
|
||||
printf("%s\n", MDB_VERSION_STRING);
|
||||
|
|
@ -199,8 +208,11 @@ int main(int argc, char *argv[])
|
|||
alldbs++;
|
||||
break;
|
||||
case 'f':
|
||||
if (freopen(optarg, "w", stdout) == NULL) {
|
||||
fprintf(stderr, "%s: %s: reopen: %s\n",
|
||||
outname = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
if (sscanf(optarg, "%" Yu "i", &txnid) != 1 || !txnid) {
|
||||
fprintf(stderr, "%s: %s: invalid txnid: %s\n",
|
||||
prog, optarg, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -208,6 +220,12 @@ int main(int argc, char *argv[])
|
|||
case 'n':
|
||||
envflags |= MDB_NOSUBDIR;
|
||||
break;
|
||||
case 'v':
|
||||
envflags |= MDB_PREVSNAPSHOT;
|
||||
break;
|
||||
case 'L':
|
||||
envflags |= MDB_NOLOCK;
|
||||
break;
|
||||
case 'p':
|
||||
mode |= PRINT;
|
||||
break;
|
||||
|
|
@ -216,6 +234,12 @@ int main(int argc, char *argv[])
|
|||
usage(prog);
|
||||
subname = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
module = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
password = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(prog);
|
||||
}
|
||||
|
|
@ -240,6 +264,16 @@ int main(int argc, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (module) {
|
||||
MDB_crypto_funcs *mcf;
|
||||
mlm = mdb_modload(module, NULL, &mcf, &errmsg);
|
||||
if (!mlm) {
|
||||
fprintf(stderr, "Failed to load crypto module: %s\n", errmsg);
|
||||
goto env_close;
|
||||
}
|
||||
mdb_modsetup(env, mcf, password);
|
||||
}
|
||||
|
||||
if (alldbs || subname) {
|
||||
mdb_env_set_maxdbs(env, 2);
|
||||
}
|
||||
|
|
@ -250,15 +284,31 @@ int main(int argc, char *argv[])
|
|||
goto env_close;
|
||||
}
|
||||
|
||||
if (txnid) {
|
||||
if (outname)
|
||||
rc = mdb_env_incr_dump(env, outname, txnid);
|
||||
else
|
||||
rc = mdb_env_incr_dumpfd(env, MDB_STDOUT, txnid);
|
||||
if (rc)
|
||||
fprintf(stderr, "mdb_env_incr_dump failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
|
||||
if (outname && freopen(outname, "w", stdout) == NULL) {
|
||||
fprintf(stderr, "%s: %s: reopen: %s\n",
|
||||
prog, outname, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
|
||||
if (rc) {
|
||||
fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
|
||||
rc = mdb_open(txn, subname, 0, &dbi);
|
||||
rc = mdb_dbi_open(txn, subname, 0, &dbi);
|
||||
if (rc) {
|
||||
fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
fprintf(stderr, "mdb_dbi_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto txn_abort;
|
||||
}
|
||||
|
||||
|
|
@ -273,27 +323,22 @@ int main(int argc, char *argv[])
|
|||
goto txn_abort;
|
||||
}
|
||||
while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT_NODUP)) == 0) {
|
||||
char *str;
|
||||
MDB_dbi db2;
|
||||
if (memchr(key.mv_data, '\0', key.mv_size))
|
||||
if (!mdb_cursor_is_db(cursor))
|
||||
continue;
|
||||
count++;
|
||||
str = malloc(key.mv_size+1);
|
||||
memcpy(str, key.mv_data, key.mv_size);
|
||||
str[key.mv_size] = '\0';
|
||||
rc = mdb_open(txn, str, 0, &db2);
|
||||
rc = mdb_dbi_open(txn, key.mv_data, 0, &db2);
|
||||
if (rc == MDB_SUCCESS) {
|
||||
if (list) {
|
||||
printf("%s\n", str);
|
||||
printf("%s\n", (char *)key.mv_data);
|
||||
list++;
|
||||
} else {
|
||||
rc = dumpit(txn, db2, str);
|
||||
rc = dumpit(txn, db2, key.mv_data);
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
mdb_close(env, db2);
|
||||
mdb_dbi_close(env, db2);
|
||||
}
|
||||
free(str);
|
||||
if (rc) continue;
|
||||
}
|
||||
mdb_cursor_close(cursor);
|
||||
|
|
@ -314,6 +359,8 @@ txn_abort:
|
|||
mdb_txn_abort(txn);
|
||||
env_close:
|
||||
mdb_env_close(env);
|
||||
if (mlm)
|
||||
mdb_modunload(mlm);
|
||||
|
||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_LOAD 1 "2015/09/30" "LMDB 0.9.17"
|
||||
.\" Copyright 2014-2021 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.TH MDB_LOAD 1 "2026/04/28" "LMDB 1.0.0"
|
||||
.\" Copyright 2014-2026 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_load \- LMDB environment import tool
|
||||
|
|
@ -12,8 +12,16 @@ mdb_load \- LMDB environment import tool
|
|||
[\c
|
||||
.BI \-f \ file\fR]
|
||||
[\c
|
||||
.BR \-i ]
|
||||
[\c
|
||||
.BR \-n ]
|
||||
[\c
|
||||
.BI \-m \ module
|
||||
[\c
|
||||
.BI \-w \ password\fR]]
|
||||
[\c
|
||||
.BR \-L ]
|
||||
[\c
|
||||
.BI \-s \ subdb\fR]
|
||||
[\c
|
||||
.BR \-N ]
|
||||
|
|
@ -51,8 +59,24 @@ on a database that uses custom compare functions.
|
|||
.BR \-f \ file
|
||||
Read from the specified file instead of from the standard input.
|
||||
.TP
|
||||
.BR \-i
|
||||
Load an incremental backup.
|
||||
.TP
|
||||
.BR \-n
|
||||
Load an LMDB database which does not use subdirectories.
|
||||
Load an LMDB environment which does not use subdirectories.
|
||||
.TP
|
||||
.BI \-m \ module
|
||||
Load the specified dynamic module to utilize cryptographic functions.
|
||||
This is required to operate on environments that have been configured
|
||||
with page-level checksums or encryption.
|
||||
.TP
|
||||
.BI \-w \ password
|
||||
Specify the password for an encrypted environment. This is only
|
||||
used if a cryptography module has been loaded.
|
||||
.TP
|
||||
.BR \-L
|
||||
Access the LMDB environment without any locking. If concurrent access is
|
||||
anticipated, the caller must manage all concurrency itself.
|
||||
.TP
|
||||
.BR \-s \ subdb
|
||||
Load a specific subdatabase. If no database is specified, data is loaded into the main database.
|
||||
|
|
|
|||
|
|
@ -19,13 +19,20 @@
|
|||
#include <unistd.h>
|
||||
#include "lmdb.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define MDB_STDIN GetStdHandle(STD_INPUT_HANDLE)
|
||||
#else
|
||||
#define MDB_STDIN 0
|
||||
#endif
|
||||
|
||||
#define PRINT 1
|
||||
#define NOHDR 2
|
||||
static int mode;
|
||||
|
||||
static char *subname = NULL;
|
||||
|
||||
static size_t lineno;
|
||||
static mdb_size_t lineno;
|
||||
static int version;
|
||||
|
||||
static int flags;
|
||||
|
|
@ -39,11 +46,9 @@ static MDB_envinfo info;
|
|||
static MDB_val kbuf, dbuf;
|
||||
static MDB_val k0buf;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define Z "I"
|
||||
#else
|
||||
#define Z "z"
|
||||
#endif
|
||||
static unsigned int pagesize;
|
||||
|
||||
#define Yu MDB_PRIy(u)
|
||||
|
||||
#define STRLENOF(s) (sizeof(s)-1)
|
||||
|
||||
|
|
@ -75,7 +80,7 @@ static void readhdr(void)
|
|||
if (!strncmp(dbuf.mv_data, "VERSION=", STRLENOF("VERSION="))) {
|
||||
version=atoi((char *)dbuf.mv_data+STRLENOF("VERSION="));
|
||||
if (version > 3) {
|
||||
fprintf(stderr, "%s: line %" Z "d: unsupported VERSION %d\n",
|
||||
fprintf(stderr, "%s: line %"Yu": unsupported VERSION %d\n",
|
||||
prog, lineno, version);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -85,7 +90,7 @@ static void readhdr(void)
|
|||
if (!strncmp((char *)dbuf.mv_data+STRLENOF("FORMAT="), "print", STRLENOF("print")))
|
||||
mode |= PRINT;
|
||||
else if (strncmp((char *)dbuf.mv_data+STRLENOF("FORMAT="), "bytevalue", STRLENOF("bytevalue"))) {
|
||||
fprintf(stderr, "%s: line %" Z "d: unsupported FORMAT %s\n",
|
||||
fprintf(stderr, "%s: line %"Yu": unsupported FORMAT %s\n",
|
||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("FORMAT="));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -96,7 +101,7 @@ static void readhdr(void)
|
|||
subname = strdup((char *)dbuf.mv_data+STRLENOF("database="));
|
||||
} else if (!strncmp(dbuf.mv_data, "type=", STRLENOF("type="))) {
|
||||
if (strncmp((char *)dbuf.mv_data+STRLENOF("type="), "btree", STRLENOF("btree"))) {
|
||||
fprintf(stderr, "%s: line %" Z "d: unsupported type %s\n",
|
||||
fprintf(stderr, "%s: line %"Yu": unsupported type %s\n",
|
||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("type="));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -106,7 +111,7 @@ static void readhdr(void)
|
|||
if (ptr) *ptr = '\0';
|
||||
i = sscanf((char *)dbuf.mv_data+STRLENOF("mapaddr="), "%p", &info.me_mapaddr);
|
||||
if (i != 1) {
|
||||
fprintf(stderr, "%s: line %" Z "d: invalid mapaddr %s\n",
|
||||
fprintf(stderr, "%s: line %"Yu": invalid mapaddr %s\n",
|
||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapaddr="));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -114,9 +119,10 @@ static void readhdr(void)
|
|||
int i;
|
||||
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
||||
if (ptr) *ptr = '\0';
|
||||
i = sscanf((char *)dbuf.mv_data+STRLENOF("mapsize="), "%" Z "u", &info.me_mapsize);
|
||||
i = sscanf((char *)dbuf.mv_data+STRLENOF("mapsize="),
|
||||
"%" MDB_SCNy(u), &info.me_mapsize);
|
||||
if (i != 1) {
|
||||
fprintf(stderr, "%s: line %" Z "d: invalid mapsize %s\n",
|
||||
fprintf(stderr, "%s: line %"Yu": invalid mapsize %s\n",
|
||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapsize="));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -126,10 +132,21 @@ static void readhdr(void)
|
|||
if (ptr) *ptr = '\0';
|
||||
i = sscanf((char *)dbuf.mv_data+STRLENOF("maxreaders="), "%u", &info.me_maxreaders);
|
||||
if (i != 1) {
|
||||
fprintf(stderr, "%s: line %" Z "d: invalid maxreaders %s\n",
|
||||
fprintf(stderr, "%s: line %"Yu": invalid maxreaders %s\n",
|
||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("maxreaders="));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (!strncmp(dbuf.mv_data, "db_pagesize=", STRLENOF("db_pagesize="))) {
|
||||
int i;
|
||||
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
||||
if (ptr) *ptr = '\0';
|
||||
i = sscanf((char *)dbuf.mv_data+STRLENOF("db_pagesize="),
|
||||
"%u", &pagesize);
|
||||
if (i != 1) {
|
||||
fprintf(stderr, "%s: line %"Yu": invalid pagesize %s\n",
|
||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("db_pagesize="));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
for (i=0; dbflags[i].bit; i++) {
|
||||
|
|
@ -142,12 +159,12 @@ static void readhdr(void)
|
|||
if (!dbflags[i].bit) {
|
||||
ptr = memchr(dbuf.mv_data, '=', dbuf.mv_size);
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "%s: line %" Z "d: unexpected format\n",
|
||||
fprintf(stderr, "%s: line %"Yu": unexpected format\n",
|
||||
prog, lineno);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
*ptr = '\0';
|
||||
fprintf(stderr, "%s: line %" Z "d: unrecognized keyword ignored: %s\n",
|
||||
fprintf(stderr, "%s: line %"Yu": unrecognized keyword ignored: %s\n",
|
||||
prog, lineno, (char *)dbuf.mv_data);
|
||||
}
|
||||
}
|
||||
|
|
@ -157,7 +174,7 @@ static void readhdr(void)
|
|||
|
||||
static void badend(void)
|
||||
{
|
||||
fprintf(stderr, "%s: line %" Z "d: unexpected end of input\n",
|
||||
fprintf(stderr, "%s: line %"Yu": unexpected end of input\n",
|
||||
prog, lineno);
|
||||
}
|
||||
|
||||
|
|
@ -221,7 +238,7 @@ badend:
|
|||
buf->mv_data = realloc(buf->mv_data, buf->mv_size*2);
|
||||
if (!buf->mv_data) {
|
||||
Eof = 1;
|
||||
fprintf(stderr, "%s: line %" Z "d: out of memory, line too long\n",
|
||||
fprintf(stderr, "%s: line %"Yu": out of memory, line too long\n",
|
||||
prog, lineno);
|
||||
return EOF;
|
||||
}
|
||||
|
|
@ -285,7 +302,7 @@ badend:
|
|||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-V] [-a] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog);
|
||||
fprintf(stderr, "usage: %s [-V] [-a] [-f input] [-i] [-n] [-L] [-m module [-w password]] [-s name] [-N] [-Q] [-T] dbpath\n", prog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -303,8 +320,10 @@ int main(int argc, char *argv[])
|
|||
MDB_dbi dbi;
|
||||
char *envname;
|
||||
int envflags = MDB_NOSYNC, putflags = 0;
|
||||
int dohdr = 0, append = 0;
|
||||
int dohdr = 0, append = 0, incr = 0;
|
||||
MDB_val prevk;
|
||||
char *module = NULL, *password = NULL, *errmsg;
|
||||
void *mlm = NULL;
|
||||
|
||||
prog = argv[0];
|
||||
|
||||
|
|
@ -314,14 +333,17 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* -a: append records in input order
|
||||
* -f: load file instead of stdin
|
||||
* -i: load an incremental dump
|
||||
* -m: dynamically load a module
|
||||
* -n: use NOSUBDIR flag on env_open
|
||||
* -L: use NOLOCK flag on env_open
|
||||
* -s: load into named subDB
|
||||
* -N: use NOOVERWRITE on puts
|
||||
* -Q: quick mode using NOSYNC
|
||||
* -T: read plaintext
|
||||
* -V: print version and exit
|
||||
*/
|
||||
while ((i = getopt(argc, argv, "af:ns:NQTV")) != EOF) {
|
||||
while ((i = getopt(argc, argv, "af:im:nLs:w:NQTV")) != EOF) {
|
||||
switch(i) {
|
||||
case 'V':
|
||||
printf("%s\n", MDB_VERSION_STRING);
|
||||
|
|
@ -337,9 +359,15 @@ int main(int argc, char *argv[])
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
incr = 1;
|
||||
break;
|
||||
case 'n':
|
||||
envflags |= MDB_NOSUBDIR;
|
||||
break;
|
||||
case 'L':
|
||||
envflags |= MDB_NOLOCK;
|
||||
break;
|
||||
case 's':
|
||||
subname = strdup(optarg);
|
||||
break;
|
||||
|
|
@ -352,6 +380,12 @@ int main(int argc, char *argv[])
|
|||
case 'T':
|
||||
mode |= NOHDR | PRINT;
|
||||
break;
|
||||
case 'm':
|
||||
module = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
password = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
|
@ -359,6 +393,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (optind != argc - 1)
|
||||
usage();
|
||||
envname = argv[optind];
|
||||
|
||||
dbuf.mv_size = 4096;
|
||||
dbuf.mv_data = malloc(dbuf.mv_size);
|
||||
|
|
@ -366,12 +401,31 @@ int main(int argc, char *argv[])
|
|||
if (!(mode & NOHDR))
|
||||
readhdr();
|
||||
|
||||
envname = argv[optind];
|
||||
rc = mdb_env_create(&env);
|
||||
if (rc) {
|
||||
fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (module) {
|
||||
MDB_crypto_funcs *mcf;
|
||||
mlm = mdb_modload(module, NULL, &mcf, &errmsg);
|
||||
if (!mlm) {
|
||||
fprintf(stderr, "Failed to load crypto module: %s\n", errmsg);
|
||||
goto env_close;
|
||||
}
|
||||
mdb_modsetup(env, mcf, password);
|
||||
}
|
||||
|
||||
if (incr) {
|
||||
envflags |= MDB_WRITEMAP;
|
||||
rc = mdb_env_open(env, envname, envflags, 0664);
|
||||
if (rc)
|
||||
goto openfail;
|
||||
rc = mdb_env_incr_loadfd(env, MDB_STDIN);
|
||||
if (rc)
|
||||
fprintf(stderr, "mdb_env_incr_load failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
|
||||
mdb_env_set_maxdbs(env, 2);
|
||||
|
||||
|
|
@ -381,11 +435,15 @@ int main(int argc, char *argv[])
|
|||
if (info.me_mapsize)
|
||||
mdb_env_set_mapsize(env, info.me_mapsize);
|
||||
|
||||
if (pagesize)
|
||||
mdb_env_set_pagesize(env, pagesize);
|
||||
|
||||
if (info.me_mapaddr)
|
||||
envflags |= MDB_FIXEDMAP;
|
||||
|
||||
rc = mdb_env_open(env, envname, envflags, 0664);
|
||||
if (rc) {
|
||||
openfail:
|
||||
fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
|
|
@ -399,7 +457,6 @@ int main(int argc, char *argv[])
|
|||
while(!Eof) {
|
||||
MDB_val key, data;
|
||||
int batch = 0;
|
||||
flags = 0;
|
||||
int appflag;
|
||||
|
||||
if (!dohdr) {
|
||||
|
|
@ -438,9 +495,13 @@ int main(int argc, char *argv[])
|
|||
|
||||
rc = readline(&data, &dbuf);
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s: line %" Z "d: failed to read key value\n", prog, lineno);
|
||||
fprintf(stderr, "%s: line %"Yu": failed to read key value\n", prog, lineno);
|
||||
goto txn_abort;
|
||||
}
|
||||
if (!key.mv_size) {
|
||||
fprintf(stderr, "%s: line %"Yu": zero-length key(ignored)\n", prog, lineno);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (append) {
|
||||
appflag = MDB_APPEND;
|
||||
|
|
@ -459,14 +520,14 @@ int main(int argc, char *argv[])
|
|||
if (rc == MDB_KEYEXIST && putflags)
|
||||
continue;
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s: line %" Z "d: mdb_cursor_put failed, error %d %s\n", prog, lineno, rc, mdb_strerror(rc));
|
||||
fprintf(stderr, "%s: line %"Yu": mdb_cursor_put failed, error %d %s\n", prog, lineno, rc, mdb_strerror(rc));
|
||||
goto txn_abort;
|
||||
}
|
||||
batch++;
|
||||
if (batch == 100) {
|
||||
rc = mdb_txn_commit(txn);
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n",
|
||||
fprintf(stderr, "%s: line %"Yu": txn_commit: %s\n",
|
||||
prog, lineno, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
|
|
@ -492,7 +553,7 @@ int main(int argc, char *argv[])
|
|||
rc = mdb_txn_commit(txn);
|
||||
txn = NULL;
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n",
|
||||
fprintf(stderr, "%s: line %"Yu": txn_commit: %s\n",
|
||||
prog, lineno, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
|
|
@ -510,6 +571,8 @@ txn_abort:
|
|||
mdb_txn_abort(txn);
|
||||
env_close:
|
||||
mdb_env_close(env);
|
||||
if (mlm)
|
||||
mdb_modunload(mlm);
|
||||
|
||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_STAT 1 "2015/09/30" "LMDB 0.9.17"
|
||||
.\" Copyright 2012-2021 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.TH MDB_STAT 1 "2026/04/28" "LMDB 1.0.0"
|
||||
.\" Copyright 2012-2026 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_stat \- LMDB environment status tool
|
||||
|
|
@ -14,6 +14,14 @@ mdb_stat \- LMDB environment status tool
|
|||
[\c
|
||||
.BR \-n ]
|
||||
[\c
|
||||
.BR \-v ]
|
||||
[\c
|
||||
.BI \-m \ module
|
||||
[\c
|
||||
.BI \-w \ password\fR]]
|
||||
[\c
|
||||
.BR \-L ]
|
||||
[\c
|
||||
.BR \-r [ r ]]
|
||||
[\c
|
||||
.BR \-a \ |
|
||||
|
|
@ -37,7 +45,24 @@ If \fB\-ff\fP is given, summarize each freelist entry.
|
|||
If \fB\-fff\fP is given, display the full list of page IDs in the freelist.
|
||||
.TP
|
||||
.BR \-n
|
||||
Display the status of an LMDB database which does not use subdirectories.
|
||||
Display the status of an LMDB environment which does not use subdirectories.
|
||||
.TP
|
||||
.BR \-v
|
||||
Use the previous environment state instead of the latest state.
|
||||
This may be useful if the latest state has been corrupted.
|
||||
.TP
|
||||
.BI \-m \ module
|
||||
Load the specified dynamic module to utilize cryptographic functions.
|
||||
This is required to operate on environments that have been configured
|
||||
with page-level checksums or encryption.
|
||||
.TP
|
||||
.BI \-w \ password
|
||||
Specify the password for an encrypted environment. This is only
|
||||
used if a cryptography module has been loaded.
|
||||
.TP
|
||||
.BR \-L
|
||||
Access the LMDB environment without any locking. If concurrent
|
||||
access is anticipated, the caller must manage all concurrency itself.
|
||||
.TP
|
||||
.BR \-r
|
||||
Display information about the environment reader table.
|
||||
|
|
|
|||
|
|
@ -17,27 +17,22 @@
|
|||
#include <unistd.h>
|
||||
#include "lmdb.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define Z "I"
|
||||
#else
|
||||
#define Z "z"
|
||||
#endif
|
||||
#define Z MDB_FMT_Z
|
||||
#define Yu MDB_PRIy(u)
|
||||
|
||||
static void prstat(MDB_stat *ms)
|
||||
{
|
||||
#if 0
|
||||
printf(" Page size: %u\n", ms->ms_psize);
|
||||
#endif
|
||||
printf(" Tree depth: %u\n", ms->ms_depth);
|
||||
printf(" Branch pages: %"Z"u\n", ms->ms_branch_pages);
|
||||
printf(" Leaf pages: %"Z"u\n", ms->ms_leaf_pages);
|
||||
printf(" Overflow pages: %"Z"u\n", ms->ms_overflow_pages);
|
||||
printf(" Entries: %"Z"u\n", ms->ms_entries);
|
||||
printf(" Branch pages: %"Yu"\n", ms->ms_branch_pages);
|
||||
printf(" Leaf pages: %"Yu"\n", ms->ms_leaf_pages);
|
||||
printf(" Overflow pages: %"Yu"\n", ms->ms_overflow_pages);
|
||||
printf(" Entries: %"Yu"\n", ms->ms_entries);
|
||||
}
|
||||
|
||||
static void usage(char *prog)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb] dbpath\n", prog);
|
||||
fprintf(stderr, "usage: %s [-V] [-n] [-L] [-e] [-r[r]] [-f[f[f]]] [-v] [-m module [-w password]] [-a|-s subdb] dbpath\n", prog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -53,6 +48,8 @@ int main(int argc, char *argv[])
|
|||
char *envname;
|
||||
char *subname = NULL;
|
||||
int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0;
|
||||
char *module = NULL, *password = NULL, *errmsg;
|
||||
void *mlm = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
usage(prog);
|
||||
|
|
@ -64,10 +61,12 @@ int main(int argc, char *argv[])
|
|||
* -f: print freelist info
|
||||
* -r: print reader info
|
||||
* -n: use NOSUBDIR flag on env_open
|
||||
* -L: use NOLOCK flag on env_open
|
||||
* -v: use previous snapshot
|
||||
* -V: print version and exit
|
||||
* (default) print stat of only the main DB
|
||||
*/
|
||||
while ((i = getopt(argc, argv, "Vaefnrs:")) != EOF) {
|
||||
while ((i = getopt(argc, argv, "Vaefm:nLrs:vw:")) != EOF) {
|
||||
switch(i) {
|
||||
case 'V':
|
||||
printf("%s\n", MDB_VERSION_STRING);
|
||||
|
|
@ -87,6 +86,12 @@ int main(int argc, char *argv[])
|
|||
case 'n':
|
||||
envflags |= MDB_NOSUBDIR;
|
||||
break;
|
||||
case 'v':
|
||||
envflags |= MDB_PREVSNAPSHOT;
|
||||
break;
|
||||
case 'L':
|
||||
envflags |= MDB_NOLOCK;
|
||||
break;
|
||||
case 'r':
|
||||
rdrinfo++;
|
||||
break;
|
||||
|
|
@ -95,6 +100,12 @@ int main(int argc, char *argv[])
|
|||
usage(prog);
|
||||
subname = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
module = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
password = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(prog);
|
||||
}
|
||||
|
|
@ -110,6 +121,16 @@ int main(int argc, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (module) {
|
||||
MDB_crypto_funcs *mcf;
|
||||
mlm = mdb_modload(module, NULL, &mcf, &errmsg);
|
||||
if (!mlm) {
|
||||
fprintf(stderr, "Failed to load crypto module: %s\n", errmsg);
|
||||
goto env_close;
|
||||
}
|
||||
mdb_modsetup(env, mcf, password);
|
||||
}
|
||||
|
||||
if (alldbs || subname) {
|
||||
mdb_env_set_maxdbs(env, 4);
|
||||
}
|
||||
|
|
@ -125,11 +146,11 @@ int main(int argc, char *argv[])
|
|||
(void)mdb_env_info(env, &mei);
|
||||
printf("Environment Info\n");
|
||||
printf(" Map address: %p\n", mei.me_mapaddr);
|
||||
printf(" Map size: %"Z"u\n", mei.me_mapsize);
|
||||
printf(" Map size: %"Yu"\n", mei.me_mapsize);
|
||||
printf(" Page size: %u\n", mst.ms_psize);
|
||||
printf(" Max pages: %"Z"u\n", mei.me_mapsize / mst.ms_psize);
|
||||
printf(" Number of pages used: %"Z"u\n", mei.me_last_pgno+1);
|
||||
printf(" Last transaction ID: %"Z"u\n", mei.me_last_txnid);
|
||||
printf(" Max pages: %"Yu"\n", mei.me_mapsize / mst.ms_psize);
|
||||
printf(" Number of pages used: %"Yu"\n", mei.me_last_pgno+1);
|
||||
printf(" Last transaction ID: %"Yu"\n", mei.me_last_txnid);
|
||||
printf(" Max readers: %u\n", mei.me_maxreaders);
|
||||
printf(" Number of readers used: %u\n", mei.me_numreaders);
|
||||
}
|
||||
|
|
@ -156,7 +177,7 @@ int main(int argc, char *argv[])
|
|||
if (freinfo) {
|
||||
MDB_cursor *cursor;
|
||||
MDB_val key, data;
|
||||
size_t pages = 0, *iptr;
|
||||
mdb_size_t pages = 0, *iptr;
|
||||
|
||||
printf("Freelist Status\n");
|
||||
dbi = 0;
|
||||
|
|
@ -176,7 +197,7 @@ int main(int argc, char *argv[])
|
|||
pages += *iptr;
|
||||
if (freinfo > 1) {
|
||||
char *bad = "";
|
||||
size_t pg, prev;
|
||||
mdb_size_t pg, prev;
|
||||
ssize_t i, j, span = 0;
|
||||
j = *iptr++;
|
||||
for (i = j, prev = 1; --i >= 0; ) {
|
||||
|
|
@ -187,25 +208,25 @@ int main(int argc, char *argv[])
|
|||
pg += span;
|
||||
for (; i >= span && iptr[i-span] == pg; span++, pg++) ;
|
||||
}
|
||||
printf(" Transaction %"Z"u, %"Z"d pages, maxspan %"Z"d%s\n",
|
||||
*(size_t *)key.mv_data, j, span, bad);
|
||||
printf(" Transaction %"Yu", %"Z"d pages, maxspan %"Z"d%s\n",
|
||||
*(mdb_size_t *)key.mv_data, j, span, bad);
|
||||
if (freinfo > 2) {
|
||||
for (--j; j >= 0; ) {
|
||||
pg = iptr[j];
|
||||
for (span=1; --j >= 0 && iptr[j] == pg+span; span++) ;
|
||||
printf(span>1 ? " %9"Z"u[%"Z"d]\n" : " %9"Z"u\n",
|
||||
printf(span>1 ? " %9"Yu"[%"Z"d]\n" : " %9"Yu"\n",
|
||||
pg, span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mdb_cursor_close(cursor);
|
||||
printf(" Free pages: %"Z"u\n", pages);
|
||||
printf(" Free pages: %"Yu"\n", pages);
|
||||
}
|
||||
|
||||
rc = mdb_open(txn, subname, 0, &dbi);
|
||||
rc = mdb_dbi_open(txn, subname, 0, &dbi);
|
||||
if (rc) {
|
||||
fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
fprintf(stderr, "mdb_dbi_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto txn_abort;
|
||||
}
|
||||
|
||||
|
|
@ -227,17 +248,12 @@ int main(int argc, char *argv[])
|
|||
goto txn_abort;
|
||||
}
|
||||
while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT_NODUP)) == 0) {
|
||||
char *str;
|
||||
MDB_dbi db2;
|
||||
if (memchr(key.mv_data, '\0', key.mv_size))
|
||||
if (!mdb_cursor_is_db(cursor))
|
||||
continue;
|
||||
str = malloc(key.mv_size+1);
|
||||
memcpy(str, key.mv_data, key.mv_size);
|
||||
str[key.mv_size] = '\0';
|
||||
rc = mdb_open(txn, str, 0, &db2);
|
||||
rc = mdb_dbi_open(txn, key.mv_data, 0, &db2);
|
||||
if (rc == MDB_SUCCESS)
|
||||
printf("Status of %s\n", str);
|
||||
free(str);
|
||||
printf("Status of %s\n", (char *)key.mv_data);
|
||||
if (rc) continue;
|
||||
rc = mdb_stat(txn, db2, &mst);
|
||||
if (rc) {
|
||||
|
|
@ -245,7 +261,7 @@ int main(int argc, char *argv[])
|
|||
goto txn_abort;
|
||||
}
|
||||
prstat(&mst);
|
||||
mdb_close(env, db2);
|
||||
mdb_dbi_close(env, db2);
|
||||
}
|
||||
mdb_cursor_close(cursor);
|
||||
}
|
||||
|
|
@ -253,11 +269,13 @@ int main(int argc, char *argv[])
|
|||
if (rc == MDB_NOTFOUND)
|
||||
rc = MDB_SUCCESS;
|
||||
|
||||
mdb_close(env, dbi);
|
||||
mdb_dbi_close(env, dbi);
|
||||
txn_abort:
|
||||
mdb_txn_abort(txn);
|
||||
env_close:
|
||||
mdb_env_close(env);
|
||||
if (mlm)
|
||||
mdb_modunload(mlm);
|
||||
|
||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2000-2026 The OpenLDAP Foundation.
|
||||
* Portions Copyright 2001-2021 Howard Chu, Symas Corp.
|
||||
* Portions Copyright 2001-2026 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -355,5 +355,98 @@ int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id )
|
|||
return 0;
|
||||
}
|
||||
|
||||
MDB_ID2L mdb_mid2l_alloc(int num)
|
||||
{
|
||||
MDB_ID2L ids = malloc((num+2) * sizeof(MDB_ID2));
|
||||
if (ids) {
|
||||
ids->mid = num;
|
||||
ids++;
|
||||
ids->mid = 0;
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
void mdb_mid2l_free(MDB_ID2L ids)
|
||||
{
|
||||
if (ids)
|
||||
free(ids-1);
|
||||
}
|
||||
|
||||
int mdb_mid2l_need( MDB_ID2L *idp, unsigned num )
|
||||
{
|
||||
MDB_ID2L ids = *idp;
|
||||
num += ids[0].mid;
|
||||
if (num > ids[-1].mid) {
|
||||
num = (num + num/4 + (256 + 2)) & -256;
|
||||
if (!(ids = realloc(ids-1, num * sizeof(MDB_ID2))))
|
||||
return ENOMEM;
|
||||
ids[0].mid = num - 2;
|
||||
*idp = ids+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MDB_RPAGE_CACHE
|
||||
unsigned mdb_mid3l_search( MDB_ID3L ids, MDB_ID id )
|
||||
{
|
||||
/*
|
||||
* binary search of id in ids
|
||||
* if found, returns position of id
|
||||
* if not found, returns first position greater than id
|
||||
*/
|
||||
unsigned base = 0;
|
||||
unsigned cursor = 1;
|
||||
int val = 0;
|
||||
unsigned n = (unsigned)ids[0].mid;
|
||||
|
||||
while( 0 < n ) {
|
||||
unsigned pivot = n >> 1;
|
||||
cursor = base + pivot + 1;
|
||||
val = CMP( id, ids[cursor].mid );
|
||||
|
||||
if( val < 0 ) {
|
||||
n = pivot;
|
||||
|
||||
} else if ( val > 0 ) {
|
||||
base = cursor;
|
||||
n -= pivot + 1;
|
||||
|
||||
} else {
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
if( val > 0 ) {
|
||||
++cursor;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
int mdb_mid3l_insert( MDB_ID3L ids, MDB_ID3 *id )
|
||||
{
|
||||
unsigned x, i;
|
||||
|
||||
x = mdb_mid3l_search( ids, id->mid );
|
||||
|
||||
if( x < 1 ) {
|
||||
/* internal error */
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ( x <= ids[0].mid && ids[x].mid == id->mid ) {
|
||||
/* duplicate */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* insert id */
|
||||
ids[0].mid++;
|
||||
for (i=(unsigned)ids[0].mid; i>x; i--)
|
||||
ids[i] = ids[i-1];
|
||||
ids[x] = *id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MDB_RPAGE_CACHE */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2000-2026 The OpenLDAP Foundation.
|
||||
* Portions Copyright 2001-2021 Howard Chu, Symas Corp.
|
||||
* Portions Copyright 2001-2026 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
#ifndef _MDB_MIDL_H_
|
||||
#define _MDB_MIDL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include "lmdb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -43,7 +43,7 @@ extern "C" {
|
|||
/** A generic unsigned ID number. These were entryIDs in back-bdb.
|
||||
* Preferably it should have the same size as a pointer.
|
||||
*/
|
||||
typedef size_t MDB_ID;
|
||||
typedef mdb_size_t MDB_ID;
|
||||
|
||||
/** An IDL is an ID List, a sorted array of IDs. The first
|
||||
* element of the array is a counter for how many actual
|
||||
|
|
@ -180,6 +180,28 @@ int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id );
|
|||
*/
|
||||
int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id );
|
||||
|
||||
MDB_ID2L mdb_mid2l_alloc(int num);
|
||||
|
||||
void mdb_mid2l_free(MDB_ID2L ids);
|
||||
|
||||
int mdb_mid2l_need( MDB_ID2L *idp, unsigned num );
|
||||
|
||||
#if MDB_RPAGE_CACHE
|
||||
typedef struct MDB_ID3 {
|
||||
MDB_ID mid; /**< The ID */
|
||||
void *mptr; /**< The pointer */
|
||||
void *menc; /**< Decrypted pointer */
|
||||
unsigned int mcnt; /**< Number of pages */
|
||||
unsigned short mref; /**< Refcounter */
|
||||
unsigned short muse; /**< Bitmap of used pages */
|
||||
} MDB_ID3;
|
||||
|
||||
typedef MDB_ID3 *MDB_ID3L;
|
||||
|
||||
unsigned mdb_mid3l_search( MDB_ID3L ids, MDB_ID id );
|
||||
int mdb_mid3l_insert( MDB_ID3L ids, MDB_ID3 *id );
|
||||
|
||||
#endif /* MDB_RPAGE_CACHE */
|
||||
/** @} */
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
98
libraries/liblmdb/module.c
Normal file
98
libraries/liblmdb/module.c
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/* module.c - helper for dynamically loading crypto module */
|
||||
/*
|
||||
* Copyright 2020-2021 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the Symas
|
||||
* Dual-Use License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* source distribution.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lmdb.h"
|
||||
|
||||
void *
|
||||
mdb_modload(const char *file, const char *name, MDB_crypto_funcs **mcf_ptr, char **errmsg)
|
||||
{
|
||||
MDB_crypto_hooks *hookfunc;
|
||||
void *ret = NULL;
|
||||
if (!name)
|
||||
name = "MDB_crypto";
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
HINSTANCE mlm = LoadLibrary(file);
|
||||
if (mlm) {
|
||||
hookfunc = GetProcAddress(mlm, name);
|
||||
if (hookfunc)
|
||||
*mcf_ptr = hookfunc();
|
||||
else {
|
||||
*errmsg = "Crypto hook function not found";
|
||||
FreeLibrary(mlm);
|
||||
mlm = NULL;
|
||||
}
|
||||
} else {
|
||||
*errmsg = GetLastError();
|
||||
}
|
||||
ret = (void *)mlm;
|
||||
}
|
||||
#else
|
||||
{
|
||||
void *mlm = dlopen(file, RTLD_NOW);
|
||||
if (mlm) {
|
||||
hookfunc = dlsym(mlm, name);
|
||||
if (hookfunc)
|
||||
*mcf_ptr = hookfunc();
|
||||
else {
|
||||
*errmsg = "Crypto hook function not found";
|
||||
dlclose(mlm);
|
||||
mlm = NULL;
|
||||
}
|
||||
} else {
|
||||
*errmsg = dlerror();
|
||||
}
|
||||
ret = mlm;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
mdb_modunload(void *mlm)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FreeLibrary((HINSTANCE)mlm);
|
||||
#else
|
||||
dlclose(mlm);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
mdb_modsetup(MDB_env *env, MDB_crypto_funcs *cf, const char *password)
|
||||
{
|
||||
MDB_val enckey = {0};
|
||||
if (cf->mcf_sumfunc) {
|
||||
mdb_env_set_checksum(env, cf->mcf_sumfunc, cf->mcf_sumsize);
|
||||
}
|
||||
if (cf->mcf_encfunc && password) {
|
||||
char keybuf[2048];
|
||||
enckey.mv_data = keybuf;
|
||||
enckey.mv_size = cf->mcf_keysize;
|
||||
if (cf->mcf_str2key)
|
||||
cf->mcf_str2key(password, &enckey);
|
||||
else
|
||||
strncpy(enckey.mv_data, password, enckey.mv_size);
|
||||
mdb_env_set_encrypt(env, cf->mcf_encfunc, &enckey, cf->mcf_esumsize);
|
||||
memset(enckey.mv_data, 0, enckey.mv_size);
|
||||
}
|
||||
}
|
||||
|
|
@ -28,8 +28,6 @@
|
|||
#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
|
||||
"%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
|
||||
|
||||
#define MDB_SCNy(t) "z" #t
|
||||
|
||||
#define SCMP(s) s, (sizeof(s)-1)
|
||||
char inbuf[8192];
|
||||
char *dbuf, *kbuf;
|
||||
|
|
@ -284,7 +282,7 @@ void child()
|
|||
} else if (!strncmp(ptr, SCMP("mdb_env_set_mapsize"))) {
|
||||
void *tenv;
|
||||
envpair *ep;
|
||||
size_t mapsize;
|
||||
mdb_size_t mapsize;
|
||||
sscanf(ptr+SOFF("mdb_env_set_mapsize"), "%p, %"MDB_SCNy(u), &tenv, &mapsize);
|
||||
ep = findenv(tenv);
|
||||
E(mdb_env_set_mapsize(ep->renv, mapsize));
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ int main(int argc,char * argv[])
|
|||
E(mdb_env_create(&env));
|
||||
E(mdb_env_set_maxreaders(env, 1));
|
||||
E(mdb_env_set_mapsize(env, 10485760));
|
||||
E(mdb_env_set_pagesize(env, 1024));
|
||||
E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP /*|MDB_NOSYNC*/, 0664));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
|
|
|
|||
190
libraries/liblmdb/mtest_enc.c
Normal file
190
libraries/liblmdb/mtest_enc.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* mtest_enc.c - memory-mapped database tester/toy with encryption */
|
||||
/*
|
||||
* Copyright 2011-2021 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the Symas
|
||||
* Dual-Use License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* source distribution.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "lmdb.h"
|
||||
#include "chacha8.h"
|
||||
|
||||
#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
|
||||
#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
|
||||
#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
|
||||
"%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
|
||||
|
||||
static int encfunc(const MDB_val *src, MDB_val *dst, const MDB_val *key, int encdec)
|
||||
{
|
||||
chacha8(src->mv_data, src->mv_size, key[0].mv_data, key[1].mv_data, dst->mv_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc,char * argv[])
|
||||
{
|
||||
int i = 0, j = 0, rc;
|
||||
MDB_env *env;
|
||||
MDB_dbi dbi;
|
||||
MDB_val key, data;
|
||||
MDB_txn *txn;
|
||||
MDB_stat mst;
|
||||
MDB_cursor *cursor, *cur2;
|
||||
MDB_cursor_op op;
|
||||
MDB_val enckey;
|
||||
int count;
|
||||
int *values;
|
||||
char sval[32] = "";
|
||||
char ekey[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
count = (rand()%384) + 64;
|
||||
values = (int *)malloc(count*sizeof(int));
|
||||
|
||||
for(i = 0;i<count;i++) {
|
||||
values[i] = rand()%1024;
|
||||
}
|
||||
|
||||
enckey.mv_data = ekey;
|
||||
enckey.mv_size = sizeof(ekey);
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
E(mdb_env_set_maxreaders(env, 1));
|
||||
E(mdb_env_set_mapsize(env, 10485760));
|
||||
E(mdb_env_set_encrypt(env, encfunc, &enckey, 0));
|
||||
E(mdb_env_open(env, "./testdb", 0 /*|MDB_NOSYNC*/, 0664));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_dbi_open(txn, NULL, 0, &dbi));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = sval;
|
||||
|
||||
printf("Adding %d values\n", count);
|
||||
for (i=0;i<count;i++) {
|
||||
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
|
||||
/* Set <data> in each iteration, since MDB_NOOVERWRITE may modify it */
|
||||
data.mv_size = sizeof(sval);
|
||||
data.mv_data = sval;
|
||||
if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE))) {
|
||||
j++;
|
||||
data.mv_size = sizeof(sval);
|
||||
data.mv_data = sval;
|
||||
}
|
||||
}
|
||||
if (j) printf("%d duplicates skipped\n", j);
|
||||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
j=0;
|
||||
key.mv_data = sval;
|
||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
||||
j++;
|
||||
txn=NULL;
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
sprintf(sval, "%03x ", values[i]);
|
||||
if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) {
|
||||
j--;
|
||||
mdb_txn_abort(txn);
|
||||
} else {
|
||||
E(mdb_txn_commit(txn));
|
||||
}
|
||||
}
|
||||
free(values);
|
||||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
printf("Cursor next\n");
|
||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
printf("Cursor last\n");
|
||||
E(mdb_cursor_get(cursor, &key, &data, MDB_LAST));
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
printf("Cursor prev\n");
|
||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
printf("Cursor last/prev\n");
|
||||
E(mdb_cursor_get(cursor, &key, &data, MDB_LAST));
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
E(mdb_cursor_get(cursor, &key, &data, MDB_PREV));
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
printf("Deleting with cursor\n");
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cur2));
|
||||
for (i=0; i<50; i++) {
|
||||
if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, MDB_NEXT)))
|
||||
break;
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
E(mdb_del(txn, dbi, &key, NULL));
|
||||
}
|
||||
|
||||
printf("Restarting cursor in txn\n");
|
||||
for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) {
|
||||
if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, op)))
|
||||
break;
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
mdb_cursor_close(cur2);
|
||||
E(mdb_txn_commit(txn));
|
||||
|
||||
printf("Restarting cursor outside txn\n");
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) {
|
||||
if (RES(MDB_NOTFOUND, mdb_cursor_get(cursor, &key, &data, op)))
|
||||
break;
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
|
||||
return 0;
|
||||
}
|
||||
190
libraries/liblmdb/mtest_enc2.c
Normal file
190
libraries/liblmdb/mtest_enc2.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* mtest_enc.c - memory-mapped database tester/toy with encryption */
|
||||
/*
|
||||
* Copyright 2011-2021 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the Symas
|
||||
* Dual-Use License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* source distribution.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "lmdb.h"
|
||||
|
||||
#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
|
||||
#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
|
||||
#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
|
||||
"%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
|
||||
|
||||
MDB_crypto_funcs *cf;
|
||||
|
||||
int main(int argc,char * argv[])
|
||||
{
|
||||
int i = 0, j = 0, rc;
|
||||
MDB_env *env;
|
||||
MDB_dbi dbi;
|
||||
MDB_val key, data;
|
||||
MDB_txn *txn;
|
||||
MDB_stat mst;
|
||||
MDB_cursor *cursor, *cur2;
|
||||
MDB_cursor_op op;
|
||||
int count;
|
||||
int *values;
|
||||
char sval[32] = "";
|
||||
char password[] = "This is my passphrase for now...";
|
||||
void *mlm;
|
||||
char *errmsg;
|
||||
MDB_crypto_funcs *mcf;
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
count = (rand()%384) + 64;
|
||||
values = (int *)malloc(count*sizeof(int));
|
||||
|
||||
for(i = 0;i<count;i++) {
|
||||
values[i] = rand()%1024;
|
||||
}
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
mlm = mdb_modload("./crypto.lm", NULL, &mcf, &errmsg);
|
||||
if (!mlm) {
|
||||
fprintf(stderr,"Failed to load crypto module: %s\n", errmsg);
|
||||
exit(1);
|
||||
}
|
||||
mdb_modsetup(env, mcf, password);
|
||||
E(mdb_env_set_maxreaders(env, 1));
|
||||
E(mdb_env_set_mapsize(env, 10485760));
|
||||
E(mdb_env_open(env, "./testdb", 0 /*|MDB_NOSYNC*/, 0664));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_dbi_open(txn, NULL, 0, &dbi));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = sval;
|
||||
|
||||
printf("Adding %d values\n", count);
|
||||
for (i=0;i<count;i++) {
|
||||
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
|
||||
/* Set <data> in each iteration, since MDB_NOOVERWRITE may modify it */
|
||||
data.mv_size = sizeof(sval);
|
||||
data.mv_data = sval;
|
||||
if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE))) {
|
||||
j++;
|
||||
data.mv_size = sizeof(sval);
|
||||
data.mv_data = sval;
|
||||
}
|
||||
}
|
||||
if (j) printf("%d duplicates skipped\n", j);
|
||||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
j=0;
|
||||
key.mv_data = sval;
|
||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
||||
j++;
|
||||
txn=NULL;
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
sprintf(sval, "%03x ", values[i]);
|
||||
if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) {
|
||||
j--;
|
||||
mdb_txn_abort(txn);
|
||||
} else {
|
||||
E(mdb_txn_commit(txn));
|
||||
}
|
||||
}
|
||||
free(values);
|
||||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
printf("Cursor next\n");
|
||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
printf("Cursor last\n");
|
||||
E(mdb_cursor_get(cursor, &key, &data, MDB_LAST));
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
printf("Cursor prev\n");
|
||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
printf("Cursor last/prev\n");
|
||||
E(mdb_cursor_get(cursor, &key, &data, MDB_LAST));
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
E(mdb_cursor_get(cursor, &key, &data, MDB_PREV));
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
printf("Deleting with cursor\n");
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cur2));
|
||||
for (i=0; i<50; i++) {
|
||||
if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, MDB_NEXT)))
|
||||
break;
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
E(mdb_del(txn, dbi, &key, NULL));
|
||||
}
|
||||
|
||||
printf("Restarting cursor in txn\n");
|
||||
for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) {
|
||||
if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, op)))
|
||||
break;
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
mdb_cursor_close(cur2);
|
||||
E(mdb_txn_commit(txn));
|
||||
|
||||
printf("Restarting cursor outside txn\n");
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) {
|
||||
if (RES(MDB_NOTFOUND, mdb_cursor_get(cursor, &key, &data, op)))
|
||||
break;
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
mdb_modunload(mlm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
177
libraries/liblmdb/mtest_remap.c
Normal file
177
libraries/liblmdb/mtest_remap.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/* mtest_remap.c - memory-mapped database tester/toy with page remapping */
|
||||
/*
|
||||
* Copyright 2011-2021 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the Symas
|
||||
* Dual-Use License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* source distribution.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "lmdb.h"
|
||||
#include "chacha8.h"
|
||||
|
||||
#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
|
||||
#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
|
||||
#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
|
||||
"%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
|
||||
|
||||
int main(int argc,char * argv[])
|
||||
{
|
||||
int i = 0, j = 0, rc;
|
||||
MDB_env *env;
|
||||
MDB_dbi dbi;
|
||||
MDB_val key, data;
|
||||
MDB_txn *txn;
|
||||
MDB_stat mst;
|
||||
MDB_cursor *cursor, *cur2;
|
||||
MDB_cursor_op op;
|
||||
int count;
|
||||
int *values;
|
||||
char sval[32] = "";
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
count = (rand()%384) + 64;
|
||||
values = (int *)malloc(count*sizeof(int));
|
||||
|
||||
for(i = 0;i<count;i++) {
|
||||
values[i] = rand()%1024;
|
||||
}
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
E(mdb_env_set_maxreaders(env, 1));
|
||||
E(mdb_env_set_mapsize(env, 10485760));
|
||||
E(mdb_env_open(env, "./testdb", MDB_REMAP_CHUNKS /*|MDB_NOSYNC*/, 0664));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_dbi_open(txn, NULL, 0, &dbi));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = sval;
|
||||
|
||||
printf("Adding %d values\n", count);
|
||||
for (i=0;i<count;i++) {
|
||||
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
|
||||
/* Set <data> in each iteration, since MDB_NOOVERWRITE may modify it */
|
||||
data.mv_size = sizeof(sval);
|
||||
data.mv_data = sval;
|
||||
if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE))) {
|
||||
j++;
|
||||
data.mv_size = sizeof(sval);
|
||||
data.mv_data = sval;
|
||||
}
|
||||
}
|
||||
if (j) printf("%d duplicates skipped\n", j);
|
||||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
j=0;
|
||||
key.mv_data = sval;
|
||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
||||
j++;
|
||||
txn=NULL;
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
sprintf(sval, "%03x ", values[i]);
|
||||
if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) {
|
||||
j--;
|
||||
mdb_txn_abort(txn);
|
||||
} else {
|
||||
E(mdb_txn_commit(txn));
|
||||
}
|
||||
}
|
||||
free(values);
|
||||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
printf("Cursor next\n");
|
||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
printf("Cursor last\n");
|
||||
E(mdb_cursor_get(cursor, &key, &data, MDB_LAST));
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
printf("Cursor prev\n");
|
||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
printf("Cursor last/prev\n");
|
||||
E(mdb_cursor_get(cursor, &key, &data, MDB_LAST));
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
E(mdb_cursor_get(cursor, &key, &data, MDB_PREV));
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
printf("Deleting with cursor\n");
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cur2));
|
||||
for (i=0; i<50; i++) {
|
||||
if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, MDB_NEXT)))
|
||||
break;
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
E(mdb_del(txn, dbi, &key, NULL));
|
||||
}
|
||||
|
||||
printf("Restarting cursor in txn\n");
|
||||
for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) {
|
||||
if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, op)))
|
||||
break;
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
mdb_cursor_close(cur2);
|
||||
E(mdb_txn_commit(txn));
|
||||
|
||||
printf("Restarting cursor outside txn\n");
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) {
|
||||
if (RES(MDB_NOTFOUND, mdb_cursor_get(cursor, &key, &data, op)))
|
||||
break;
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -4,6 +4,11 @@
|
|||
<title>mdb_copy - environment copy tool</title>
|
||||
<filename>mdb_copy.1</filename>
|
||||
</compound>
|
||||
<compound kind="page">
|
||||
<name>mdb_drop_1</name>
|
||||
<title>mdb_drop - database delete tool</title>
|
||||
<filename>mdb_drop.1</filename>
|
||||
</compound>
|
||||
<compound kind="page">
|
||||
<name>mdb_dump_1</name>
|
||||
<title>mdb_dump - environment export tool</title>
|
||||
|
|
|
|||
Loading…
Reference in a new issue