Update liblmdb, unify 32/64 sources
This commit is contained in:
parent
d0e434f0d8
commit
ba4e217c90
|
@ -29,6 +29,6 @@
|
||||||
# We aren't even going to check the system for an installed LMDB driver, as it is too
|
# We aren't even going to check the system for an installed LMDB driver, as it is too
|
||||||
# critical a consensus component to rely on dynamically linked libraries
|
# critical a consensus component to rely on dynamically linked libraries
|
||||||
message(STATUS "Using ${ARCH_WIDTH}-bit LMDB from source tree")
|
message(STATUS "Using ${ARCH_WIDTH}-bit LMDB from source tree")
|
||||||
add_subdirectory(liblmdb${ARCH_WIDTH})
|
add_subdirectory(liblmdb)
|
||||||
set(LMDB_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/liblmdb${ARCH_WIDTH}" CACHE STRING "LMDB Include path")
|
set(LMDB_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/liblmdb" CACHE STRING "LMDB Include path")
|
||||||
set(LMDB_LIBRARY "lmdb" CACHE STRING "LMDB Library name")
|
set(LMDB_LIBRARY "lmdb" CACHE STRING "LMDB Library name")
|
||||||
|
|
|
@ -1,5 +1,57 @@
|
||||||
LMDB 0.9 Change Log
|
LMDB 0.9 Change Log
|
||||||
|
|
||||||
|
LMDB 0.9.18 Release Engineering
|
||||||
|
Fix robust mutex detection on glibc 2.10-11 (ITS#8330)
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
LMDB 0.9.15 Release (2015/06/19)
|
||||||
Fix txn init (ITS#7961,#7987)
|
Fix txn init (ITS#7961,#7987)
|
||||||
Fix MDB_PREV_DUP (ITS#7955,#7671)
|
Fix MDB_PREV_DUP (ITS#7955,#7671)
|
|
@ -27,7 +27,7 @@
|
||||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
if(FREEBSD)
|
if(FREEBSD)
|
||||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMDB_DSYNC=O_SYNC")
|
add_definitions(-DMDB_DSYNC=O_SYNC)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set (lmdb_sources
|
set (lmdb_sources
|
||||||
|
@ -41,3 +41,11 @@ add_library(lmdb
|
||||||
target_link_libraries(lmdb
|
target_link_libraries(lmdb
|
||||||
LINK_PRIVATE
|
LINK_PRIVATE
|
||||||
${CMAKE_THREAD_LIBS_INIT})
|
${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
if(WIN32)
|
||||||
|
target_link_libraries(lmdb
|
||||||
|
-lntdll)
|
||||||
|
endif()
|
||||||
|
if(${ARCH_WIDTH} EQUAL 32)
|
||||||
|
target_compile_definitions(lmdb
|
||||||
|
PUBLIC -DMDB_VL32)
|
||||||
|
endif()
|
|
@ -582,7 +582,7 @@ WARN_LOGFILE =
|
||||||
# directories like "/usr/src/myproject". Separate the files or directories
|
# directories like "/usr/src/myproject". Separate the files or directories
|
||||||
# with spaces.
|
# with spaces.
|
||||||
|
|
||||||
INPUT = lmdb.h midl.h mdb.c midl.c
|
INPUT = lmdb.h midl.h mdb.c midl.c intro.doc
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
|
@ -8,24 +8,31 @@
|
||||||
# platforms; you should not need to change any of these.
|
# platforms; you should not need to change any of these.
|
||||||
# Read their descriptions in mdb.c if you do:
|
# 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_DSYNC
|
||||||
# - MDB_FDATASYNC
|
# - MDB_FDATASYNC
|
||||||
# - MDB_FDATASYNC_WORKS
|
# - MDB_FDATASYNC_WORKS
|
||||||
# - MDB_USE_PWRITEV
|
# - MDB_USE_PWRITEV
|
||||||
|
# - MDB_USE_ROBUST
|
||||||
#
|
#
|
||||||
# There may be other macros in mdb.c of interest. You should
|
# There may be other macros in mdb.c of interest. You should
|
||||||
# read mdb.c before changing any of them.
|
# read mdb.c before changing any of them.
|
||||||
#
|
#
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
AR = ar
|
||||||
W = -W -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized
|
W = -W -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized
|
||||||
THREADS = -pthread
|
THREADS = -pthread
|
||||||
OPT = -O2 -g
|
OPT = -O2 -g
|
||||||
CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS)
|
CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS)
|
||||||
LDLIBS =
|
LDLIBS = # -lntdll # Windows needs ntdll
|
||||||
SOLIBS =
|
SOLIBS = # -lntdll
|
||||||
prefix = /usr/local
|
prefix = /usr/local
|
||||||
XCFLAGS = -DVL32
|
exec_prefix = $(prefix)
|
||||||
|
bindir = $(exec_prefix)/bin
|
||||||
|
libdir = $(exec_prefix)/lib
|
||||||
|
includedir = $(prefix)/include
|
||||||
|
datarootdir = $(prefix)/share
|
||||||
|
mandir = $(datarootdir)/man
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
|
@ -37,10 +44,14 @@ PROGS = $(IPROGS) mtest mtest2 mtest3 mtest4 mtest5
|
||||||
all: $(ILIBS) $(PROGS)
|
all: $(ILIBS) $(PROGS)
|
||||||
|
|
||||||
install: $(ILIBS) $(IPROGS) $(IHDRS)
|
install: $(ILIBS) $(IPROGS) $(IHDRS)
|
||||||
for f in $(IPROGS); do cp $$f $(DESTDIR)$(prefix)/bin; done
|
mkdir -p $(DESTDIR)$(bindir)
|
||||||
for f in $(ILIBS); do cp $$f $(DESTDIR)$(prefix)/lib; done
|
mkdir -p $(DESTDIR)$(libdir)
|
||||||
for f in $(IHDRS); do cp $$f $(DESTDIR)$(prefix)/include; done
|
mkdir -p $(DESTDIR)$(includedir)
|
||||||
for f in $(IDOCS); do cp $$f $(DESTDIR)$(prefix)/man/man1; done
|
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 $(IHDRS); do cp $$f $(DESTDIR)$(includedir); done
|
||||||
|
for f in $(IDOCS); do cp $$f $(DESTDIR)$(mandir)/man1; done
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(PROGS) *.[ao] *.[ls]o *~ testdb
|
rm -rf $(PROGS) *.[ao] *.[ls]o *~ testdb
|
||||||
|
@ -50,7 +61,7 @@ test: all
|
||||||
./mtest && ./mdb_stat testdb
|
./mtest && ./mdb_stat testdb
|
||||||
|
|
||||||
liblmdb.a: mdb.o midl.o
|
liblmdb.a: mdb.o midl.o
|
||||||
ar rs $@ mdb.o midl.o
|
$(AR) rs $@ mdb.o midl.o
|
||||||
|
|
||||||
liblmdb.so: mdb.lo midl.lo
|
liblmdb.so: mdb.lo midl.lo
|
||||||
# $(CC) $(LDFLAGS) -pthread -shared -Wl,-Bsymbolic -o $@ mdb.o midl.o $(SOLIBS)
|
# $(CC) $(LDFLAGS) -pthread -shared -Wl,-Bsymbolic -o $@ mdb.o midl.o $(SOLIBS)
|
|
@ -0,0 +1,192 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015 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>.
|
||||||
|
*/
|
||||||
|
/** @page starting Getting Started
|
||||||
|
|
||||||
|
LMDB is compact, fast, powerful, and robust and implements a simplified
|
||||||
|
variant of the BerkeleyDB (BDB) API. (BDB is also very powerful, and verbosely
|
||||||
|
documented in its own right.) After reading this page, the main
|
||||||
|
\ref mdb documentation should make sense. Thanks to Bert Hubert
|
||||||
|
for creating the
|
||||||
|
<a href="https://github.com/ahupowerdns/ahutils/blob/master/lmdb-semantics.md">
|
||||||
|
initial version</a> of this writeup.
|
||||||
|
|
||||||
|
Everything starts with an environment, created by #mdb_env_create().
|
||||||
|
Once created, this environment must also be opened with #mdb_env_open().
|
||||||
|
|
||||||
|
#mdb_env_open() gets passed a name which is interpreted as a directory
|
||||||
|
path. Note that this directory must exist already, it is not created
|
||||||
|
for you. Within that directory, a lock file and a storage file will be
|
||||||
|
generated. If you don't want to use a directory, you can pass the
|
||||||
|
#MDB_NOSUBDIR option, in which case the path you provided is used
|
||||||
|
directly as the data file, and another file with a "-lock" suffix
|
||||||
|
added will be used for the lock file.
|
||||||
|
|
||||||
|
Once the environment is open, a transaction can be created within it
|
||||||
|
using #mdb_txn_begin(). Transactions may be read-write or read-only,
|
||||||
|
and read-write transactions may be nested. A transaction must only
|
||||||
|
be used by one thread at a time. Transactions are always required,
|
||||||
|
even for read-only access. The transaction provides a consistent
|
||||||
|
view of the data.
|
||||||
|
|
||||||
|
Once a transaction has been created, a database can be opened within it
|
||||||
|
using #mdb_dbi_open(). If only one database will ever be used in the
|
||||||
|
environment, a NULL can be passed as the database name. For named
|
||||||
|
databases, the #MDB_CREATE flag must be used to create the database
|
||||||
|
if it doesn't already exist. Also, #mdb_env_set_maxdbs() must be
|
||||||
|
called after #mdb_env_create() and before #mdb_env_open() to set the
|
||||||
|
maximum number of named databases you want to support.
|
||||||
|
|
||||||
|
Note: a single transaction can open multiple databases. Generally
|
||||||
|
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
|
||||||
|
key/value pairs if that is all you need to do (but see \ref Cursors
|
||||||
|
below if you want to do more).
|
||||||
|
|
||||||
|
A key/value pair is expressed as two #MDB_val structures. This struct
|
||||||
|
has two fields, \c mv_size and \c mv_data. The data is a \c void pointer to
|
||||||
|
an array of \c mv_size bytes.
|
||||||
|
|
||||||
|
Because LMDB is very efficient (and usually zero-copy), the data returned
|
||||||
|
in an #MDB_val structure may be memory-mapped straight from disk. In
|
||||||
|
other words <b>look but do not touch</b> (or free() for that matter).
|
||||||
|
Once a transaction is closed, the values can no longer be used, so
|
||||||
|
make a copy if you need to keep them after that.
|
||||||
|
|
||||||
|
@section Cursors Cursors
|
||||||
|
|
||||||
|
To do more powerful things, we must use a cursor.
|
||||||
|
|
||||||
|
Within the transaction, a cursor can be created with #mdb_cursor_open().
|
||||||
|
With this cursor we can store/retrieve/delete (multiple) values using
|
||||||
|
#mdb_cursor_get(), #mdb_cursor_put(), and #mdb_cursor_del().
|
||||||
|
|
||||||
|
#mdb_cursor_get() positions itself depending on the cursor operation
|
||||||
|
requested, and for some operations, on the supplied key. For example,
|
||||||
|
to list all key/value pairs in a database, use operation #MDB_FIRST for
|
||||||
|
the first call to #mdb_cursor_get(), and #MDB_NEXT on subsequent calls,
|
||||||
|
until the end is hit.
|
||||||
|
|
||||||
|
To retrieve all keys starting from a specified key value, use #MDB_SET.
|
||||||
|
For more cursor operations, see the \ref mdb docs.
|
||||||
|
|
||||||
|
When using #mdb_cursor_put(), either the function will position the
|
||||||
|
cursor for you based on the \b key, or you can use operation
|
||||||
|
#MDB_CURRENT to use the current position of the cursor. Note that
|
||||||
|
\b key must then match the current position's key.
|
||||||
|
|
||||||
|
@subsection summary Summarizing the Opening
|
||||||
|
|
||||||
|
So we have a cursor in a transaction which opened a database in an
|
||||||
|
environment which is opened from a filesystem after it was
|
||||||
|
separately created.
|
||||||
|
|
||||||
|
Or, we create an environment, open it from a filesystem, create a
|
||||||
|
transaction within it, open a database within that transaction,
|
||||||
|
and create a cursor within all of the above.
|
||||||
|
|
||||||
|
Got it?
|
||||||
|
|
||||||
|
@section thrproc Threads and Processes
|
||||||
|
|
||||||
|
LMDB uses POSIX locks on files, and these locks have issues if one
|
||||||
|
process opens a file multiple times. Because of this, do not
|
||||||
|
#mdb_env_open() a file multiple times from a single process. Instead,
|
||||||
|
share the LMDB environment that has opened the file across all threads.
|
||||||
|
Otherwise, if a single process opens the same environment multiple times,
|
||||||
|
closing it once will remove all the locks held on it, and the other
|
||||||
|
instances will be vulnerable to corruption from other processes.
|
||||||
|
|
||||||
|
Also note that a transaction is tied to one thread by default using
|
||||||
|
Thread Local Storage. If you want to pass read-only transactions across
|
||||||
|
threads, you can use the #MDB_NOTLS option on the environment.
|
||||||
|
|
||||||
|
@section txns Transactions, Rollbacks, etc.
|
||||||
|
|
||||||
|
To actually get anything done, a transaction must be committed using
|
||||||
|
#mdb_txn_commit(). Alternatively, all of a transaction's operations
|
||||||
|
can be discarded using #mdb_txn_abort(). In a read-only transaction,
|
||||||
|
any cursors will \b not automatically be freed. In a read-write
|
||||||
|
transaction, all cursors will be freed and must not be used again.
|
||||||
|
|
||||||
|
For read-only transactions, obviously there is nothing to commit to
|
||||||
|
storage. The transaction still must eventually be aborted to close
|
||||||
|
any database handle(s) opened in it, or committed to keep the
|
||||||
|
database handles around for reuse in new transactions.
|
||||||
|
|
||||||
|
In addition, as long as a transaction is open, a consistent view of
|
||||||
|
the database is kept alive, which requires storage. A read-only
|
||||||
|
transaction that no longer requires this consistent view should
|
||||||
|
be terminated (committed or aborted) when the view is no longer
|
||||||
|
needed (but see below for an optimization).
|
||||||
|
|
||||||
|
There can be multiple simultaneously active read-only transactions
|
||||||
|
but only one that can write. Once a single read-write transaction
|
||||||
|
is opened, all further attempts to begin one will block until the
|
||||||
|
first one is committed or aborted. This has no effect on read-only
|
||||||
|
transactions, however, and they may continue to be opened at any time.
|
||||||
|
|
||||||
|
@section dupkeys Duplicate Keys
|
||||||
|
|
||||||
|
#mdb_get() and #mdb_put() respectively have no and only some support
|
||||||
|
for multiple key/value pairs with identical keys. If there are multiple
|
||||||
|
values for a key, #mdb_get() will only return the first value.
|
||||||
|
|
||||||
|
When multiple values for one key are required, pass the #MDB_DUPSORT
|
||||||
|
flag to #mdb_dbi_open(). In an #MDB_DUPSORT database, by default
|
||||||
|
#mdb_put() will not replace the value for a key if the key existed
|
||||||
|
already. Instead it will add the new value to the key. In addition,
|
||||||
|
#mdb_del() will pay attention to the value field too, allowing for
|
||||||
|
specific values of a key to be deleted.
|
||||||
|
|
||||||
|
Finally, additional cursor operations become available for
|
||||||
|
traversing through and retrieving duplicate values.
|
||||||
|
|
||||||
|
@section optim Some Optimization
|
||||||
|
|
||||||
|
If you frequently begin and abort read-only transactions, as an
|
||||||
|
optimization, it is possible to only reset and renew a transaction.
|
||||||
|
|
||||||
|
#mdb_txn_reset() releases any old copies of data kept around for
|
||||||
|
a read-only transaction. To reuse this reset transaction, call
|
||||||
|
#mdb_txn_renew() on it. Any cursors in this transaction must also
|
||||||
|
be renewed using #mdb_cursor_renew().
|
||||||
|
|
||||||
|
Note that #mdb_txn_reset() is similar to #mdb_txn_abort() and will
|
||||||
|
close any databases you opened within the transaction.
|
||||||
|
|
||||||
|
To permanently free a transaction, reset or not, use #mdb_txn_abort().
|
||||||
|
|
||||||
|
@section cleanup Cleaning Up
|
||||||
|
|
||||||
|
For read-only transactions, any cursors created within it must
|
||||||
|
be closed using #mdb_cursor_close().
|
||||||
|
|
||||||
|
It is very rarely necessary to close a database handle, and in
|
||||||
|
general they should just be left open.
|
||||||
|
|
||||||
|
@section onward The Full API
|
||||||
|
|
||||||
|
The full \ref mdb documentation lists further details, like how to:
|
||||||
|
|
||||||
|
\li size a database (the default limits are intentionally small)
|
||||||
|
\li drop and clean a database
|
||||||
|
\li detect and report errors
|
||||||
|
\li optimize (bulk) loading speed
|
||||||
|
\li (temporarily) reduce robustness to gain even more speed
|
||||||
|
\li gather statistics about the database
|
||||||
|
\li define custom sort orders
|
||||||
|
|
||||||
|
*/
|
|
@ -40,6 +40,9 @@
|
||||||
* corrupt the database. Of course if your application code is known to
|
* corrupt the database. Of course if your application code is known to
|
||||||
* be bug-free (...) then this is not an issue.
|
* be bug-free (...) then this is not an issue.
|
||||||
*
|
*
|
||||||
|
* If this is your first time using a transactional embedded key/value
|
||||||
|
* store, you may find the \ref starting page to be helpful.
|
||||||
|
*
|
||||||
* @section caveats_sec Caveats
|
* @section caveats_sec Caveats
|
||||||
* Troubleshooting the lock file, plus semaphores on BSD systems:
|
* Troubleshooting the lock file, plus semaphores on BSD systems:
|
||||||
*
|
*
|
||||||
|
@ -49,11 +52,16 @@
|
||||||
* stale locks can block further operation.
|
* stale locks can block further operation.
|
||||||
*
|
*
|
||||||
* Fix: Check for stale readers periodically, using the
|
* Fix: Check for stale readers periodically, using the
|
||||||
* #mdb_reader_check function or the \ref mdb_stat_1 "mdb_stat" tool. Or just
|
* #mdb_reader_check function or the \ref mdb_stat_1 "mdb_stat" tool.
|
||||||
* make all programs using the database close it; the lockfile
|
* Stale writers will be cleared automatically on most systems:
|
||||||
* is always reset on first open of the environment.
|
* - Windows - automatic
|
||||||
|
* - BSD, systems using SysV semaphores - automatic
|
||||||
|
* - Linux, systems using POSIX mutexes with Robust option - automatic
|
||||||
|
* 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.
|
* startup can fail due to semaphores owned by another userid.
|
||||||
*
|
*
|
||||||
* Fix: Open and close the database as the user which owns the
|
* Fix: Open and close the database as the user which owns the
|
||||||
|
@ -106,6 +114,9 @@
|
||||||
* for stale readers is performed or the lockfile is reset,
|
* for stale readers is performed or the lockfile is reset,
|
||||||
* since the process may not remove it from the lockfile.
|
* since the process may not remove it from the lockfile.
|
||||||
*
|
*
|
||||||
|
* This does not apply to write transactions if the system clears
|
||||||
|
* stale writers, see above.
|
||||||
|
*
|
||||||
* - If you do that anyway, do a periodic check for stale readers. Or
|
* - If you do that anyway, do a periodic check for stale readers. Or
|
||||||
* close the environment once in a while, so the lockfile can get reset.
|
* close the environment once in a while, so the lockfile can get reset.
|
||||||
*
|
*
|
||||||
|
@ -150,6 +161,7 @@
|
||||||
#define _LMDB_H_
|
#define _LMDB_H_
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -162,6 +174,13 @@ typedef int mdb_mode_t;
|
||||||
typedef mode_t mdb_mode_t;
|
typedef mode_t mdb_mode_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MDB_VL32
|
||||||
|
typedef uint64_t mdb_size_t;
|
||||||
|
#define mdb_env_create(env) mdb_env_create_vl32(env) /**< Prevent mixing with non-VL32 builds */
|
||||||
|
#else
|
||||||
|
typedef size_t mdb_size_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
/** An abstraction for a file handle.
|
/** An abstraction for a file handle.
|
||||||
* On POSIX systems file handles are small integers. On Windows
|
* On POSIX systems file handles are small integers. On Windows
|
||||||
* they're opaque pointers.
|
* they're opaque pointers.
|
||||||
|
@ -184,7 +203,7 @@ typedef int mdb_filehandle_t;
|
||||||
/** Library minor version */
|
/** Library minor version */
|
||||||
#define MDB_VERSION_MINOR 9
|
#define MDB_VERSION_MINOR 9
|
||||||
/** Library patch version */
|
/** Library patch version */
|
||||||
#define MDB_VERSION_PATCH 15
|
#define MDB_VERSION_PATCH 70
|
||||||
|
|
||||||
/** Combine args a,b,c into a single integer for easy version comparisons */
|
/** Combine args a,b,c into a single integer for easy version comparisons */
|
||||||
#define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c))
|
#define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c))
|
||||||
|
@ -194,7 +213,7 @@ typedef int mdb_filehandle_t;
|
||||||
MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
|
MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
|
||||||
|
|
||||||
/** The release date of this library version */
|
/** The release date of this library version */
|
||||||
#define MDB_VERSION_DATE "June 19, 2015"
|
#define MDB_VERSION_DATE "December 19, 2015"
|
||||||
|
|
||||||
/** A stringifier for the version info */
|
/** A stringifier for the version info */
|
||||||
#define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")"
|
#define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")"
|
||||||
|
@ -391,7 +410,7 @@ typedef enum MDB_cursor_op {
|
||||||
#define MDB_PAGE_NOTFOUND (-30797)
|
#define MDB_PAGE_NOTFOUND (-30797)
|
||||||
/** Located page was wrong type */
|
/** Located page was wrong type */
|
||||||
#define MDB_CORRUPTED (-30796)
|
#define MDB_CORRUPTED (-30796)
|
||||||
/** Update of meta page failed, probably I/O error */
|
/** Update of meta page failed or environment had fatal error */
|
||||||
#define MDB_PANIC (-30795)
|
#define MDB_PANIC (-30795)
|
||||||
/** Environment version mismatch */
|
/** Environment version mismatch */
|
||||||
#define MDB_VERSION_MISMATCH (-30794)
|
#define MDB_VERSION_MISMATCH (-30794)
|
||||||
|
@ -413,11 +432,18 @@ typedef enum MDB_cursor_op {
|
||||||
#define MDB_PAGE_FULL (-30786)
|
#define MDB_PAGE_FULL (-30786)
|
||||||
/** Database contents grew beyond environment mapsize */
|
/** Database contents grew beyond environment mapsize */
|
||||||
#define MDB_MAP_RESIZED (-30785)
|
#define MDB_MAP_RESIZED (-30785)
|
||||||
/** MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed */
|
/** Operation and DB incompatible, or DB type changed. This can mean:
|
||||||
|
* <ul>
|
||||||
|
* <li>The operation expects an #MDB_DUPSORT / #MDB_DUPFIXED database.
|
||||||
|
* <li>Opening a named DB when the unnamed DB has #MDB_DUPSORT / #MDB_INTEGERKEY.
|
||||||
|
* <li>Accessing a data record as a database, or vice versa.
|
||||||
|
* <li>The database was dropped and recreated with different flags.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
#define MDB_INCOMPATIBLE (-30784)
|
#define MDB_INCOMPATIBLE (-30784)
|
||||||
/** Invalid reuse of reader locktable slot */
|
/** Invalid reuse of reader locktable slot */
|
||||||
#define MDB_BAD_RSLOT (-30783)
|
#define MDB_BAD_RSLOT (-30783)
|
||||||
/** Transaction cannot recover - it must be aborted */
|
/** Transaction must abort, has a child, or is invalid */
|
||||||
#define MDB_BAD_TXN (-30782)
|
#define MDB_BAD_TXN (-30782)
|
||||||
/** Unsupported size of key/DB name/data, or wrong DUPFIXED size */
|
/** Unsupported size of key/DB name/data, or wrong DUPFIXED size */
|
||||||
#define MDB_BAD_VALSIZE (-30781)
|
#define MDB_BAD_VALSIZE (-30781)
|
||||||
|
@ -432,18 +458,18 @@ typedef struct MDB_stat {
|
||||||
unsigned int ms_psize; /**< Size of a database page.
|
unsigned int ms_psize; /**< Size of a database page.
|
||||||
This is currently the same for all databases. */
|
This is currently the same for all databases. */
|
||||||
unsigned int ms_depth; /**< Depth (height) of the B-tree */
|
unsigned int ms_depth; /**< Depth (height) of the B-tree */
|
||||||
size_t ms_branch_pages; /**< Number of internal (non-leaf) pages */
|
mdb_size_t ms_branch_pages; /**< Number of internal (non-leaf) pages */
|
||||||
size_t ms_leaf_pages; /**< Number of leaf pages */
|
mdb_size_t ms_leaf_pages; /**< Number of leaf pages */
|
||||||
size_t ms_overflow_pages; /**< Number of overflow pages */
|
mdb_size_t ms_overflow_pages; /**< Number of overflow pages */
|
||||||
size_t ms_entries; /**< Number of data items */
|
mdb_size_t ms_entries; /**< Number of data items */
|
||||||
} MDB_stat;
|
} MDB_stat;
|
||||||
|
|
||||||
/** @brief Information about the environment */
|
/** @brief Information about the environment */
|
||||||
typedef struct MDB_envinfo {
|
typedef struct MDB_envinfo {
|
||||||
void *me_mapaddr; /**< Address of map, if fixed */
|
void *me_mapaddr; /**< Address of map, if fixed */
|
||||||
size_t me_mapsize; /**< Size of the data memory map */
|
mdb_size_t me_mapsize; /**< Size of the data memory map */
|
||||||
size_t me_last_pgno; /**< ID of the last used page */
|
mdb_size_t me_last_pgno; /**< ID of the last used page */
|
||||||
size_t me_last_txnid; /**< ID of the last committed transaction */
|
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_maxreaders; /**< max reader slots in the environment */
|
||||||
unsigned int me_numreaders; /**< max reader slots used in the environment */
|
unsigned int me_numreaders; /**< max reader slots used in the environment */
|
||||||
} MDB_envinfo;
|
} MDB_envinfo;
|
||||||
|
@ -810,7 +836,7 @@ int mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *fd);
|
||||||
* an active write transaction.
|
* an active write transaction.
|
||||||
* </ul>
|
* </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 maximum number of threads/reader slots for the environment.
|
/** @brief Set the maximum number of threads/reader slots for the environment.
|
||||||
*
|
*
|
||||||
|
@ -923,6 +949,10 @@ int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func);
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>#MDB_RDONLY
|
* <li>#MDB_RDONLY
|
||||||
* This transaction will not perform any write operations.
|
* 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>
|
* </ul>
|
||||||
* @param[out] txn Address where the new #MDB_txn handle will be stored
|
* @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
|
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||||
|
@ -946,6 +976,17 @@ int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **
|
||||||
*/
|
*/
|
||||||
MDB_env *mdb_txn_env(MDB_txn *txn);
|
MDB_env *mdb_txn_env(MDB_txn *txn);
|
||||||
|
|
||||||
|
/** @brief Return the transaction's ID.
|
||||||
|
*
|
||||||
|
* This returns the identifier associated with this transaction. For a
|
||||||
|
* read-only transaction, this corresponds to the snapshot being read;
|
||||||
|
* concurrent readers will frequently have the same transaction ID.
|
||||||
|
*
|
||||||
|
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
||||||
|
* @return A transaction ID, valid if input is an active transaction.
|
||||||
|
*/
|
||||||
|
mdb_size_t mdb_txn_id(MDB_txn *txn);
|
||||||
|
|
||||||
/** @brief Commit all the operations of a transaction into the database.
|
/** @brief Commit all the operations of a transaction into the database.
|
||||||
*
|
*
|
||||||
* The transaction handle is freed. It and its cursors must not be used
|
* The transaction handle is freed. It and its cursors must not be used
|
||||||
|
@ -1034,8 +1075,9 @@ int mdb_txn_renew(MDB_txn *txn);
|
||||||
* any other transaction in the process may use this function.
|
* any other transaction in the process may use this function.
|
||||||
*
|
*
|
||||||
* To use named databases (with name != NULL), #mdb_env_set_maxdbs()
|
* To use named databases (with name != NULL), #mdb_env_set_maxdbs()
|
||||||
* must be called before opening the environment. Database names
|
* must be called before opening the environment. Database names are
|
||||||
* are kept as keys in the unnamed database.
|
* keys in the unnamed database, and may be read but not written.
|
||||||
|
*
|
||||||
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
* @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
|
* @param[in] name The name of the database to open. If only a single
|
||||||
* database is needed in the environment, this value may be NULL.
|
* database is needed in the environment, this value may be NULL.
|
||||||
|
@ -1272,7 +1314,8 @@ int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data);
|
||||||
* the next update operation or the transaction ends. This saves
|
* the next update operation or the transaction ends. This saves
|
||||||
* an extra memcpy if the data is being generated later.
|
* an extra memcpy if the data is being generated later.
|
||||||
* LMDB does nothing else with this memory, the caller is expected
|
* LMDB does nothing else with this memory, the caller is expected
|
||||||
* to modify all of the space requested.
|
* to modify all of the space requested. This flag must not be
|
||||||
|
* specified if the database was opened with #MDB_DUPSORT.
|
||||||
* <li>#MDB_APPEND - append the given key/data pair to the end of the
|
* <li>#MDB_APPEND - append the given key/data pair to the end of the
|
||||||
* database. This option allows fast bulk loading when keys are
|
* database. This option allows fast bulk loading when keys are
|
||||||
* already known to be in the correct order. Loading unsorted keys
|
* already known to be in the correct order. Loading unsorted keys
|
||||||
|
@ -1428,13 +1471,15 @@ int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
|
||||||
* the database supports duplicates (#MDB_DUPSORT).
|
* the database supports duplicates (#MDB_DUPSORT).
|
||||||
* <li>#MDB_RESERVE - reserve space for data of the given size, but
|
* <li>#MDB_RESERVE - reserve space for data of the given size, but
|
||||||
* don't copy the given data. Instead, return a pointer to the
|
* don't copy the given data. Instead, return a pointer to the
|
||||||
* reserved space, which the caller can fill in later. This saves
|
* reserved space, which the caller can fill in later - before
|
||||||
* an extra memcpy if the data is being generated later.
|
* the next update operation or the transaction ends. This saves
|
||||||
|
* an extra memcpy if the data is being generated later. This flag
|
||||||
|
* must not be specified if the database was opened with #MDB_DUPSORT.
|
||||||
* <li>#MDB_APPEND - append the given key/data pair to the end of the
|
* <li>#MDB_APPEND - append the given key/data pair to the end of the
|
||||||
* database. No key comparisons are performed. This option allows
|
* database. No key comparisons are performed. This option allows
|
||||||
* fast bulk loading when keys are already known to be in the
|
* fast bulk loading when keys are already known to be in the
|
||||||
* correct order. Loading unsorted keys with this flag will cause
|
* correct order. Loading unsorted keys with this flag will cause
|
||||||
* data corruption.
|
* a #MDB_KEYEXIST error.
|
||||||
* <li>#MDB_APPENDDUP - as above, but for sorted dup data.
|
* <li>#MDB_APPENDDUP - as above, but for sorted dup data.
|
||||||
* <li>#MDB_MULTIPLE - store multiple contiguous data elements in a
|
* <li>#MDB_MULTIPLE - store multiple contiguous data elements in a
|
||||||
* single request. This flag may only be specified if the database
|
* single request. This flag may only be specified if the database
|
File diff suppressed because it is too large
Load Diff
|
@ -5,7 +5,6 @@
|
||||||
mdb_dump \- LMDB environment export tool
|
mdb_dump \- LMDB environment export tool
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B mdb_dump
|
.B mdb_dump
|
||||||
.BR \ envpath
|
|
||||||
[\c
|
[\c
|
||||||
.BR \-V ]
|
.BR \-V ]
|
||||||
[\c
|
[\c
|
||||||
|
@ -19,6 +18,7 @@ mdb_dump \- LMDB environment export tool
|
||||||
[\c
|
[\c
|
||||||
.BR \-a \ |
|
.BR \-a \ |
|
||||||
.BI \-s \ subdb\fR]
|
.BI \-s \ subdb\fR]
|
||||||
|
.BR \ envpath
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
The
|
The
|
||||||
.B mdb_dump
|
.B mdb_dump
|
|
@ -25,6 +25,15 @@
|
||||||
#else
|
#else
|
||||||
#define Z "z"
|
#define Z "z"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MDB_VL32
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define Y "I64"
|
||||||
|
#else
|
||||||
|
#define Y "ll"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define Y Z
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PRINT 1
|
#define PRINT 1
|
||||||
static int mode;
|
static int mode;
|
||||||
|
@ -115,7 +124,7 @@ static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name)
|
||||||
if (name)
|
if (name)
|
||||||
printf("database=%s\n", name);
|
printf("database=%s\n", name);
|
||||||
printf("type=btree\n");
|
printf("type=btree\n");
|
||||||
printf("mapsize=%" Z "u\n", info.me_mapsize);
|
printf("mapsize=%" Y "u\n", info.me_mapsize);
|
||||||
if (info.me_mapaddr)
|
if (info.me_mapaddr)
|
||||||
printf("mapaddr=%p\n", info.me_mapaddr);
|
printf("mapaddr=%p\n", info.me_mapaddr);
|
||||||
printf("maxreaders=%u\n", info.me_maxreaders);
|
printf("maxreaders=%u\n", info.me_maxreaders);
|
||||||
|
@ -155,7 +164,7 @@ static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name)
|
||||||
|
|
||||||
static void usage(char *prog)
|
static void usage(char *prog)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: %s dbpath [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb]\n", prog);
|
fprintf(stderr, "usage: %s [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb] dbpath\n", prog);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
mdb_load \- LMDB environment import tool
|
mdb_load \- LMDB environment import tool
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B mdb_load
|
.B mdb_load
|
||||||
.BR \ envpath
|
|
||||||
[\c
|
[\c
|
||||||
.BR \-V ]
|
.BR \-V ]
|
||||||
[\c
|
[\c
|
||||||
|
@ -18,6 +17,7 @@ mdb_load \- LMDB environment import tool
|
||||||
.BR \-N ]
|
.BR \-N ]
|
||||||
[\c
|
[\c
|
||||||
.BR \-T ]
|
.BR \-T ]
|
||||||
|
.BR \ envpath
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
The
|
The
|
||||||
.B mdb_load
|
.B mdb_load
|
|
@ -43,6 +43,15 @@ static MDB_val kbuf, dbuf;
|
||||||
#else
|
#else
|
||||||
#define Z "z"
|
#define Z "z"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MDB_VL32
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define Y "I64"
|
||||||
|
#else
|
||||||
|
#define Y "ll"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define Y Z
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STRLENOF(s) (sizeof(s)-1)
|
#define STRLENOF(s) (sizeof(s)-1)
|
||||||
|
|
||||||
|
@ -112,7 +121,7 @@ static void readhdr(void)
|
||||||
int i;
|
int i;
|
||||||
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
||||||
if (ptr) *ptr = '\0';
|
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="), "%" Y "u", &info.me_mapsize);
|
||||||
if (i != 1) {
|
if (i != 1) {
|
||||||
fprintf(stderr, "%s: line %" Z "d: invalid mapsize %s\n",
|
fprintf(stderr, "%s: line %" Z "d: invalid mapsize %s\n",
|
||||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapsize="));
|
prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapsize="));
|
||||||
|
@ -276,7 +285,7 @@ badend:
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: %s dbpath [-V] [-f input] [-n] [-s name] [-N] [-T]\n", prog);
|
fprintf(stderr, "usage: %s [-V] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +336,7 @@ int main(int argc, char *argv[])
|
||||||
putflags = MDB_NOOVERWRITE|MDB_NODUPDATA;
|
putflags = MDB_NOOVERWRITE|MDB_NODUPDATA;
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
mode |= NOHDR;
|
mode |= NOHDR | PRINT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
|
@ -400,20 +409,22 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
rc = readline(&key, &kbuf);
|
rc = readline(&key, &kbuf);
|
||||||
if (rc == EOF)
|
if (rc) /* rc == EOF */
|
||||||
break;
|
break;
|
||||||
if (rc)
|
|
||||||
goto txn_abort;
|
|
||||||
|
|
||||||
rc = readline(&data, &dbuf);
|
rc = readline(&data, &dbuf);
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
fprintf(stderr, "%s: line %" Z "d: failed to read key value\n", prog, lineno);
|
||||||
goto txn_abort;
|
goto txn_abort;
|
||||||
|
}
|
||||||
|
|
||||||
rc = mdb_cursor_put(mc, &key, &data, putflags);
|
rc = mdb_cursor_put(mc, &key, &data, putflags);
|
||||||
if (rc == MDB_KEYEXIST && putflags)
|
if (rc == MDB_KEYEXIST && putflags)
|
||||||
continue;
|
continue;
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
fprintf(stderr, "mdb_cursor_put failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||||
goto txn_abort;
|
goto txn_abort;
|
||||||
|
}
|
||||||
batch++;
|
batch++;
|
||||||
if (batch == 100) {
|
if (batch == 100) {
|
||||||
rc = mdb_txn_commit(txn);
|
rc = mdb_txn_commit(txn);
|
|
@ -5,7 +5,6 @@
|
||||||
mdb_stat \- LMDB environment status tool
|
mdb_stat \- LMDB environment status tool
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B mdb_stat
|
.B mdb_stat
|
||||||
.BR \ envpath
|
|
||||||
[\c
|
[\c
|
||||||
.BR \-V ]
|
.BR \-V ]
|
||||||
[\c
|
[\c
|
||||||
|
@ -19,6 +18,7 @@ mdb_stat \- LMDB environment status tool
|
||||||
[\c
|
[\c
|
||||||
.BR \-a \ |
|
.BR \-a \ |
|
||||||
.BI \-s \ subdb\fR]
|
.BI \-s \ subdb\fR]
|
||||||
|
.BR \ envpath
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
The
|
The
|
||||||
.B mdb_stat
|
.B mdb_stat
|
|
@ -22,6 +22,15 @@
|
||||||
#else
|
#else
|
||||||
#define Z "z"
|
#define Z "z"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MDB_VL32
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define Y "I64"
|
||||||
|
#else
|
||||||
|
#define Y "ll"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define Y Z
|
||||||
|
#endif
|
||||||
|
|
||||||
static void prstat(MDB_stat *ms)
|
static void prstat(MDB_stat *ms)
|
||||||
{
|
{
|
||||||
|
@ -29,15 +38,15 @@ static void prstat(MDB_stat *ms)
|
||||||
printf(" Page size: %u\n", ms->ms_psize);
|
printf(" Page size: %u\n", ms->ms_psize);
|
||||||
#endif
|
#endif
|
||||||
printf(" Tree depth: %u\n", ms->ms_depth);
|
printf(" Tree depth: %u\n", ms->ms_depth);
|
||||||
printf(" Branch pages: %"Z"u\n", ms->ms_branch_pages);
|
printf(" Branch pages: %"Y"u\n", ms->ms_branch_pages);
|
||||||
printf(" Leaf pages: %"Z"u\n", ms->ms_leaf_pages);
|
printf(" Leaf pages: %"Y"u\n", ms->ms_leaf_pages);
|
||||||
printf(" Overflow pages: %"Z"u\n", ms->ms_overflow_pages);
|
printf(" Overflow pages: %"Y"u\n", ms->ms_overflow_pages);
|
||||||
printf(" Entries: %"Z"u\n", ms->ms_entries);
|
printf(" Entries: %"Y"u\n", ms->ms_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage(char *prog)
|
static void usage(char *prog)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: %s dbpath [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb]\n", prog);
|
fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb] dbpath\n", prog);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,11 +134,11 @@ int main(int argc, char *argv[])
|
||||||
(void)mdb_env_info(env, &mei);
|
(void)mdb_env_info(env, &mei);
|
||||||
printf("Environment Info\n");
|
printf("Environment Info\n");
|
||||||
printf(" Map address: %p\n", mei.me_mapaddr);
|
printf(" Map address: %p\n", mei.me_mapaddr);
|
||||||
printf(" Map size: %"Z"u\n", mei.me_mapsize);
|
printf(" Map size: %"Y"u\n", mei.me_mapsize);
|
||||||
printf(" Page size: %u\n", mst.ms_psize);
|
printf(" Page size: %u\n", mst.ms_psize);
|
||||||
printf(" Max pages: %"Z"u\n", mei.me_mapsize / mst.ms_psize);
|
printf(" Max pages: %"Y"u\n", mei.me_mapsize / mst.ms_psize);
|
||||||
printf(" Number of pages used: %"Z"u\n", mei.me_last_pgno+1);
|
printf(" Number of pages used: %"Y"u\n", mei.me_last_pgno+1);
|
||||||
printf(" Last transaction ID: %"Z"u\n", mei.me_last_txnid);
|
printf(" Last transaction ID: %"Y"u\n", mei.me_last_txnid);
|
||||||
printf(" Max readers: %u\n", mei.me_maxreaders);
|
printf(" Max readers: %u\n", mei.me_maxreaders);
|
||||||
printf(" Number of readers used: %u\n", mei.me_numreaders);
|
printf(" Number of readers used: %u\n", mei.me_numreaders);
|
||||||
}
|
}
|
|
@ -116,7 +116,7 @@ void mdb_midl_free(MDB_IDL ids)
|
||||||
free(ids-1);
|
free(ids-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdb_midl_shrink( MDB_IDL *idp )
|
void mdb_midl_shrink( MDB_IDL *idp )
|
||||||
{
|
{
|
||||||
MDB_IDL ids = *idp;
|
MDB_IDL ids = *idp;
|
||||||
if (*(--ids) > MDB_IDL_UM_MAX &&
|
if (*(--ids) > MDB_IDL_UM_MAX &&
|
||||||
|
@ -124,9 +124,7 @@ int mdb_midl_shrink( MDB_IDL *idp )
|
||||||
{
|
{
|
||||||
*ids++ = MDB_IDL_UM_MAX;
|
*ids++ = MDB_IDL_UM_MAX;
|
||||||
*idp = ids;
|
*idp = ids;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mdb_midl_grow( MDB_IDL *idp, int num )
|
static int mdb_midl_grow( MDB_IDL *idp, int num )
|
||||||
|
@ -356,5 +354,67 @@ int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MDB_VL32
|
||||||
|
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_VL32 */
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
/** @} */
|
/** @} */
|
|
@ -27,6 +27,7 @@
|
||||||
#define _MDB_MIDL_H_
|
#define _MDB_MIDL_H_
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -42,7 +43,11 @@ extern "C" {
|
||||||
/** A generic unsigned ID number. These were entryIDs in back-bdb.
|
/** A generic unsigned ID number. These were entryIDs in back-bdb.
|
||||||
* Preferably it should have the same size as a pointer.
|
* Preferably it should have the same size as a pointer.
|
||||||
*/
|
*/
|
||||||
|
#ifdef MDB_VL32
|
||||||
|
typedef uint64_t MDB_ID;
|
||||||
|
#else
|
||||||
typedef size_t MDB_ID;
|
typedef size_t MDB_ID;
|
||||||
|
#endif
|
||||||
|
|
||||||
/** An IDL is an ID List, a sorted array of IDs. The first
|
/** An IDL is an ID List, a sorted array of IDs. The first
|
||||||
* element of the array is a counter for how many actual
|
* element of the array is a counter for how many actual
|
||||||
|
@ -55,10 +60,10 @@ typedef MDB_ID *MDB_IDL;
|
||||||
/* IDL sizes - likely should be even bigger
|
/* IDL sizes - likely should be even bigger
|
||||||
* limiting factors: sizeof(ID), thread stack size
|
* limiting factors: sizeof(ID), thread stack size
|
||||||
*/
|
*/
|
||||||
#ifdef VL32
|
#ifdef MDB_VL32
|
||||||
#define MDB_IDL_LOGN 10 /* DB_SIZE is 2^10, UM_SIZE is 2^11 */
|
#define MDB_IDL_LOGN 10 /* DB_SIZE is 2^10, UM_SIZE is 2^11 */
|
||||||
#else
|
#else
|
||||||
#define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
|
#define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
|
||||||
#endif
|
#endif
|
||||||
#define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN)
|
#define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN)
|
||||||
#define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1))
|
#define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1))
|
||||||
|
@ -102,9 +107,8 @@ void mdb_midl_free(MDB_IDL ids);
|
||||||
/** Shrink an IDL.
|
/** Shrink an IDL.
|
||||||
* Return the IDL to the default size if it has grown larger.
|
* Return the IDL to the default size if it has grown larger.
|
||||||
* @param[in,out] idp Address of the IDL to shrink.
|
* @param[in,out] idp Address of the IDL to shrink.
|
||||||
* @return 0 on no change, non-zero if shrunk.
|
|
||||||
*/
|
*/
|
||||||
int mdb_midl_shrink(MDB_IDL *idp);
|
void mdb_midl_shrink(MDB_IDL *idp);
|
||||||
|
|
||||||
/** Make room for num additional elements in an IDL.
|
/** Make room for num additional elements in an IDL.
|
||||||
* @param[in,out] idp Address of the IDL.
|
* @param[in,out] idp Address of the IDL.
|
||||||
|
@ -182,6 +186,20 @@ int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id );
|
||||||
*/
|
*/
|
||||||
int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id );
|
int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id );
|
||||||
|
|
||||||
|
#ifdef MDB_VL32
|
||||||
|
typedef struct MDB_ID3 {
|
||||||
|
MDB_ID mid; /**< The ID */
|
||||||
|
void *mptr; /**< The pointer */
|
||||||
|
unsigned int mcnt; /**< Number of pages */
|
||||||
|
unsigned int mref; /**< Refcounter */
|
||||||
|
} 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_VL32 */
|
||||||
/** @} */
|
/** @} */
|
||||||
/** @} */
|
/** @} */
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
|
@ -1,20 +0,0 @@
|
||||||
mtest
|
|
||||||
mtest[23456]
|
|
||||||
testdb
|
|
||||||
mdb_copy
|
|
||||||
mdb_stat
|
|
||||||
*.[ao]
|
|
||||||
*.so
|
|
||||||
*.exe
|
|
||||||
*[~#]
|
|
||||||
*.bak
|
|
||||||
*.orig
|
|
||||||
*.rej
|
|
||||||
*.gcov
|
|
||||||
*.gcda
|
|
||||||
*.gcno
|
|
||||||
core
|
|
||||||
core.*
|
|
||||||
valgrind.*
|
|
||||||
man/
|
|
||||||
html/
|
|
|
@ -1,140 +0,0 @@
|
||||||
LMDB 0.9 Change Log
|
|
||||||
|
|
||||||
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
|
|
|
@ -1,46 +0,0 @@
|
||||||
# Copyright (c) 2014-2015, The Monero Project
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
# permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
# conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
# of conditions and the following disclaimer in the documentation and/or other
|
|
||||||
# materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be
|
|
||||||
# used to endorse or promote products derived from this software without specific
|
|
||||||
# prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
||||||
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
||||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
if(FREEBSD)
|
|
||||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMDB_DSYNC=O_SYNC")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# pass the VL32 flag so that we actually invoke the VL32 extensions
|
|
||||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVL32")
|
|
||||||
|
|
||||||
set (lmdb_sources
|
|
||||||
mdb.c
|
|
||||||
midl.c)
|
|
||||||
|
|
||||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
|
|
||||||
|
|
||||||
add_library(lmdb
|
|
||||||
${lmdb_sources})
|
|
||||||
target_link_libraries(lmdb
|
|
||||||
LINK_PRIVATE
|
|
||||||
${CMAKE_THREAD_LIBS_INIT})
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,77 +0,0 @@
|
||||||
.TH MDB_LOAD 1 "2014/06/20" "LMDB 0.9.14"
|
|
||||||
.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
|
||||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
|
||||||
.SH NAME
|
|
||||||
mdb_load \- LMDB environment import tool
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B mdb_load
|
|
||||||
.BR \ envpath
|
|
||||||
[\c
|
|
||||||
.BR \-V ]
|
|
||||||
[\c
|
|
||||||
.BI \-f \ file\fR]
|
|
||||||
[\c
|
|
||||||
.BR \-n ]
|
|
||||||
[\c
|
|
||||||
.BI \-s \ subdb\fR]
|
|
||||||
[\c
|
|
||||||
.BR \-N ]
|
|
||||||
[\c
|
|
||||||
.BR \-T ]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
The
|
|
||||||
.B mdb_load
|
|
||||||
utility reads from the standard input and loads it into the
|
|
||||||
LMDB environment
|
|
||||||
.BR envpath .
|
|
||||||
|
|
||||||
The input to
|
|
||||||
.B mdb_load
|
|
||||||
must be in the output format specified by the
|
|
||||||
.BR mdb_dump (1)
|
|
||||||
utility or as specified by the
|
|
||||||
.B -T
|
|
||||||
option below.
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.BR \-V
|
|
||||||
Write the library version number to the standard output, and exit.
|
|
||||||
.TP
|
|
||||||
.BR \-f \ file
|
|
||||||
Read from the specified file instead of from the standard input.
|
|
||||||
.TP
|
|
||||||
.BR \-n
|
|
||||||
Load an LMDB database which does not use subdirectories.
|
|
||||||
.TP
|
|
||||||
.BR \-s \ subdb
|
|
||||||
Load a specific subdatabase. If no database is specified, data is loaded into the main database.
|
|
||||||
.TP
|
|
||||||
.BR \-N
|
|
||||||
Don't overwrite existing records when loading into an already existing database; just skip them.
|
|
||||||
.TP
|
|
||||||
.BR \-T
|
|
||||||
Load data from simple text files. The input must be paired lines of text, where the first
|
|
||||||
line of the pair is the key item, and the second line of the pair is its corresponding
|
|
||||||
data item.
|
|
||||||
|
|
||||||
A simple escape mechanism, where newline and backslash (\\) characters are special, is
|
|
||||||
applied to the text input. Newline characters are interpreted as record separators.
|
|
||||||
Backslash characters in the text will be interpreted in one of two ways: If the backslash
|
|
||||||
character precedes another backslash character, the pair will be interpreted as a literal
|
|
||||||
backslash. If the backslash character precedes any other character, the two characters
|
|
||||||
following the backslash will be interpreted as a hexadecimal specification of a single
|
|
||||||
character; for example, \\0a is a newline character in the ASCII character set.
|
|
||||||
|
|
||||||
For this reason, any backslash or newline characters that naturally occur in the text
|
|
||||||
input must be escaped to avoid misinterpretation by
|
|
||||||
.BR mdb_load .
|
|
||||||
|
|
||||||
.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 "SEE ALSO"
|
|
||||||
.BR mdb_dump (1)
|
|
||||||
.SH AUTHOR
|
|
||||||
Howard Chu of Symas Corporation <http://www.symas.com>
|
|
|
@ -1,64 +0,0 @@
|
||||||
.TH MDB_STAT 1 "2014/06/20" "LMDB 0.9.14"
|
|
||||||
.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
|
||||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
|
||||||
.SH NAME
|
|
||||||
mdb_stat \- LMDB environment status tool
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B mdb_stat
|
|
||||||
.BR \ envpath
|
|
||||||
[\c
|
|
||||||
.BR \-V ]
|
|
||||||
[\c
|
|
||||||
.BR \-e ]
|
|
||||||
[\c
|
|
||||||
.BR \-f [ f [ f ]]]
|
|
||||||
[\c
|
|
||||||
.BR \-n ]
|
|
||||||
[\c
|
|
||||||
.BR \-r [ r ]]
|
|
||||||
[\c
|
|
||||||
.BR \-a \ |
|
|
||||||
.BI \-s \ subdb\fR]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
The
|
|
||||||
.B mdb_stat
|
|
||||||
utility displays the status of an LMDB environment.
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.BR \-V
|
|
||||||
Write the library version number to the standard output, and exit.
|
|
||||||
.TP
|
|
||||||
.BR \-e
|
|
||||||
Display information about the database environment.
|
|
||||||
.TP
|
|
||||||
.BR \-f
|
|
||||||
Display information about the environment freelist.
|
|
||||||
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.
|
|
||||||
.TP
|
|
||||||
.BR \-r
|
|
||||||
Display information about the environment reader table.
|
|
||||||
Shows the process ID, thread ID, and transaction ID for each active
|
|
||||||
reader slot. The process ID and transaction ID are in decimal, the
|
|
||||||
thread ID is in hexadecimal. The transaction ID is displayed as "-"
|
|
||||||
if the reader does not currently have a read transaction open.
|
|
||||||
If \fB\-rr\fP is given, check for stale entries in the reader
|
|
||||||
table and clear them. The reader table will be printed again
|
|
||||||
after the check is performed.
|
|
||||||
.TP
|
|
||||||
.BR \-a
|
|
||||||
Display the status of all of the subdatabases in the environment.
|
|
||||||
.TP
|
|
||||||
.BR \-s \ subdb
|
|
||||||
Display the status of a specific subdatabase.
|
|
||||||
.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 "SEE ALSO"
|
|
||||||
.BR mdb_copy (1)
|
|
||||||
.SH AUTHOR
|
|
||||||
Howard Chu of Symas Corporation <http://www.symas.com>
|
|
|
@ -1,263 +0,0 @@
|
||||||
/* mdb_stat.c - memory-mapped database status tool */
|
|
||||||
/*
|
|
||||||
* Copyright 2011-2015 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 <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "lmdb.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define Z "I"
|
|
||||||
#else
|
|
||||||
#define Z "z"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage(char *prog)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "usage: %s dbpath [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb]\n", prog);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int i, rc;
|
|
||||||
MDB_env *env;
|
|
||||||
MDB_txn *txn;
|
|
||||||
MDB_dbi dbi;
|
|
||||||
MDB_stat mst;
|
|
||||||
MDB_envinfo mei;
|
|
||||||
char *prog = argv[0];
|
|
||||||
char *envname;
|
|
||||||
char *subname = NULL;
|
|
||||||
int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0;
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
usage(prog);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -a: print stat of main DB and all subDBs
|
|
||||||
* -s: print stat of only the named subDB
|
|
||||||
* -e: print env info
|
|
||||||
* -f: print freelist info
|
|
||||||
* -r: print reader info
|
|
||||||
* -n: use NOSUBDIR flag on env_open
|
|
||||||
* -V: print version and exit
|
|
||||||
* (default) print stat of only the main DB
|
|
||||||
*/
|
|
||||||
while ((i = getopt(argc, argv, "Vaefnrs:")) != EOF) {
|
|
||||||
switch(i) {
|
|
||||||
case 'V':
|
|
||||||
printf("%s\n", MDB_VERSION_STRING);
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
if (subname)
|
|
||||||
usage(prog);
|
|
||||||
alldbs++;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
envinfo++;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
freinfo++;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
envflags |= MDB_NOSUBDIR;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
rdrinfo++;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
if (alldbs)
|
|
||||||
usage(prog);
|
|
||||||
subname = optarg;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage(prog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind != argc - 1)
|
|
||||||
usage(prog);
|
|
||||||
|
|
||||||
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 (alldbs || subname) {
|
|
||||||
mdb_env_set_maxdbs(env, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 0664);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
goto env_close;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (envinfo) {
|
|
||||||
(void)mdb_env_stat(env, &mst);
|
|
||||||
(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(" 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 readers: %u\n", mei.me_maxreaders);
|
|
||||||
printf(" Number of readers used: %u\n", mei.me_numreaders);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rdrinfo) {
|
|
||||||
printf("Reader Table Status\n");
|
|
||||||
rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout);
|
|
||||||
if (rdrinfo > 1) {
|
|
||||||
int dead;
|
|
||||||
mdb_reader_check(env, &dead);
|
|
||||||
printf(" %d stale readers cleared.\n", dead);
|
|
||||||
rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout);
|
|
||||||
}
|
|
||||||
if (!(subname || alldbs || freinfo))
|
|
||||||
goto env_close;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (freinfo) {
|
|
||||||
MDB_cursor *cursor;
|
|
||||||
MDB_val key, data;
|
|
||||||
size_t pages = 0, *iptr;
|
|
||||||
|
|
||||||
printf("Freelist Status\n");
|
|
||||||
dbi = 0;
|
|
||||||
rc = mdb_cursor_open(txn, dbi, &cursor);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
goto txn_abort;
|
|
||||||
}
|
|
||||||
rc = mdb_stat(txn, dbi, &mst);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
goto txn_abort;
|
|
||||||
}
|
|
||||||
prstat(&mst);
|
|
||||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
|
|
||||||
iptr = data.mv_data;
|
|
||||||
pages += *iptr;
|
|
||||||
if (freinfo > 1) {
|
|
||||||
char *bad = "";
|
|
||||||
size_t pg, prev;
|
|
||||||
ssize_t i, j, span = 0;
|
|
||||||
j = *iptr++;
|
|
||||||
for (i = j, prev = 1; --i >= 0; ) {
|
|
||||||
pg = iptr[i];
|
|
||||||
if (pg <= prev)
|
|
||||||
bad = " [bad sequence]";
|
|
||||||
prev = pg;
|
|
||||||
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);
|
|
||||||
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",
|
|
||||||
pg, span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
printf(" Free pages: %"Z"u\n", pages);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_stat(txn, dbi, &mst);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
goto txn_abort;
|
|
||||||
}
|
|
||||||
printf("Status of %s\n", subname ? subname : "Main DB");
|
|
||||||
prstat(&mst);
|
|
||||||
|
|
||||||
if (alldbs) {
|
|
||||||
MDB_cursor *cursor;
|
|
||||||
MDB_val key;
|
|
||||||
|
|
||||||
rc = mdb_cursor_open(txn, dbi, &cursor);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
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))
|
|
||||||
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);
|
|
||||||
if (rc == MDB_SUCCESS)
|
|
||||||
printf("Status of %s\n", str);
|
|
||||||
free(str);
|
|
||||||
if (rc) continue;
|
|
||||||
rc = mdb_stat(txn, db2, &mst);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
goto txn_abort;
|
|
||||||
}
|
|
||||||
prstat(&mst);
|
|
||||||
mdb_close(env, db2);
|
|
||||||
}
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == MDB_NOTFOUND)
|
|
||||||
rc = MDB_SUCCESS;
|
|
||||||
|
|
||||||
mdb_close(env, dbi);
|
|
||||||
txn_abort:
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
env_close:
|
|
||||||
mdb_env_close(env);
|
|
||||||
|
|
||||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
||||||
}
|
|
|
@ -1,360 +0,0 @@
|
||||||
/** @file midl.c
|
|
||||||
* @brief ldap bdb back-end ID List functions */
|
|
||||||
/* $OpenLDAP$ */
|
|
||||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
||||||
*
|
|
||||||
* Copyright 2000-2015 The OpenLDAP Foundation.
|
|
||||||
* 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 <limits.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "midl.h"
|
|
||||||
|
|
||||||
/** @defgroup internal LMDB Internals
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
/** @defgroup idls ID List Management
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
#define CMP(x,y) ( (x) < (y) ? -1 : (x) > (y) )
|
|
||||||
|
|
||||||
unsigned mdb_midl_search( MDB_IDL 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 = ids[0];
|
|
||||||
|
|
||||||
while( 0 < n ) {
|
|
||||||
unsigned pivot = n >> 1;
|
|
||||||
cursor = base + pivot + 1;
|
|
||||||
val = CMP( ids[cursor], id );
|
|
||||||
|
|
||||||
if( val < 0 ) {
|
|
||||||
n = pivot;
|
|
||||||
|
|
||||||
} else if ( val > 0 ) {
|
|
||||||
base = cursor;
|
|
||||||
n -= pivot + 1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( val > 0 ) {
|
|
||||||
++cursor;
|
|
||||||
}
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0 /* superseded by append/sort */
|
|
||||||
int mdb_midl_insert( MDB_IDL ids, MDB_ID id )
|
|
||||||
{
|
|
||||||
unsigned x, i;
|
|
||||||
|
|
||||||
x = mdb_midl_search( ids, id );
|
|
||||||
assert( x > 0 );
|
|
||||||
|
|
||||||
if( x < 1 ) {
|
|
||||||
/* internal error */
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( x <= ids[0] && ids[x] == id ) {
|
|
||||||
/* duplicate */
|
|
||||||
assert(0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ++ids[0] >= MDB_IDL_DB_MAX ) {
|
|
||||||
/* no room */
|
|
||||||
--ids[0];
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* insert id */
|
|
||||||
for (i=ids[0]; i>x; i--)
|
|
||||||
ids[i] = ids[i-1];
|
|
||||||
ids[x] = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MDB_IDL mdb_midl_alloc(int num)
|
|
||||||
{
|
|
||||||
MDB_IDL ids = malloc((num+2) * sizeof(MDB_ID));
|
|
||||||
if (ids) {
|
|
||||||
*ids++ = num;
|
|
||||||
*ids = 0;
|
|
||||||
}
|
|
||||||
return ids;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mdb_midl_free(MDB_IDL ids)
|
|
||||||
{
|
|
||||||
if (ids)
|
|
||||||
free(ids-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_midl_shrink( MDB_IDL *idp )
|
|
||||||
{
|
|
||||||
MDB_IDL ids = *idp;
|
|
||||||
if (*(--ids) > MDB_IDL_UM_MAX &&
|
|
||||||
(ids = realloc(ids, (MDB_IDL_UM_MAX+1) * sizeof(MDB_ID))))
|
|
||||||
{
|
|
||||||
*ids++ = MDB_IDL_UM_MAX;
|
|
||||||
*idp = ids;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mdb_midl_grow( MDB_IDL *idp, int num )
|
|
||||||
{
|
|
||||||
MDB_IDL idn = *idp-1;
|
|
||||||
/* grow it */
|
|
||||||
idn = realloc(idn, (*idn + num + 2) * sizeof(MDB_ID));
|
|
||||||
if (!idn)
|
|
||||||
return ENOMEM;
|
|
||||||
*idn++ += num;
|
|
||||||
*idp = idn;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_midl_need( MDB_IDL *idp, unsigned num )
|
|
||||||
{
|
|
||||||
MDB_IDL ids = *idp;
|
|
||||||
num += ids[0];
|
|
||||||
if (num > ids[-1]) {
|
|
||||||
num = (num + num/4 + (256 + 2)) & -256;
|
|
||||||
if (!(ids = realloc(ids-1, num * sizeof(MDB_ID))))
|
|
||||||
return ENOMEM;
|
|
||||||
*ids++ = num - 2;
|
|
||||||
*idp = ids;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_midl_append( MDB_IDL *idp, MDB_ID id )
|
|
||||||
{
|
|
||||||
MDB_IDL ids = *idp;
|
|
||||||
/* Too big? */
|
|
||||||
if (ids[0] >= ids[-1]) {
|
|
||||||
if (mdb_midl_grow(idp, MDB_IDL_UM_MAX))
|
|
||||||
return ENOMEM;
|
|
||||||
ids = *idp;
|
|
||||||
}
|
|
||||||
ids[0]++;
|
|
||||||
ids[ids[0]] = id;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app )
|
|
||||||
{
|
|
||||||
MDB_IDL ids = *idp;
|
|
||||||
/* Too big? */
|
|
||||||
if (ids[0] + app[0] >= ids[-1]) {
|
|
||||||
if (mdb_midl_grow(idp, app[0]))
|
|
||||||
return ENOMEM;
|
|
||||||
ids = *idp;
|
|
||||||
}
|
|
||||||
memcpy(&ids[ids[0]+1], &app[1], app[0] * sizeof(MDB_ID));
|
|
||||||
ids[0] += app[0];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n )
|
|
||||||
{
|
|
||||||
MDB_ID *ids = *idp, len = ids[0];
|
|
||||||
/* Too big? */
|
|
||||||
if (len + n > ids[-1]) {
|
|
||||||
if (mdb_midl_grow(idp, n | MDB_IDL_UM_MAX))
|
|
||||||
return ENOMEM;
|
|
||||||
ids = *idp;
|
|
||||||
}
|
|
||||||
ids[0] = len + n;
|
|
||||||
ids += len;
|
|
||||||
while (n)
|
|
||||||
ids[n--] = id++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge )
|
|
||||||
{
|
|
||||||
MDB_ID old_id, merge_id, i = merge[0], j = idl[0], k = i+j, total = k;
|
|
||||||
idl[0] = (MDB_ID)-1; /* delimiter for idl scan below */
|
|
||||||
old_id = idl[j];
|
|
||||||
while (i) {
|
|
||||||
merge_id = merge[i--];
|
|
||||||
for (; old_id < merge_id; old_id = idl[--j])
|
|
||||||
idl[k--] = old_id;
|
|
||||||
idl[k--] = merge_id;
|
|
||||||
}
|
|
||||||
idl[0] = total;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Quicksort + Insertion sort for small arrays */
|
|
||||||
|
|
||||||
#define SMALL 8
|
|
||||||
#define MIDL_SWAP(a,b) { itmp=(a); (a)=(b); (b)=itmp; }
|
|
||||||
|
|
||||||
void
|
|
||||||
mdb_midl_sort( MDB_IDL ids )
|
|
||||||
{
|
|
||||||
/* Max possible depth of int-indexed tree * 2 items/level */
|
|
||||||
int istack[sizeof(int)*CHAR_BIT * 2];
|
|
||||||
int i,j,k,l,ir,jstack;
|
|
||||||
MDB_ID a, itmp;
|
|
||||||
|
|
||||||
ir = (int)ids[0];
|
|
||||||
l = 1;
|
|
||||||
jstack = 0;
|
|
||||||
for(;;) {
|
|
||||||
if (ir - l < SMALL) { /* Insertion sort */
|
|
||||||
for (j=l+1;j<=ir;j++) {
|
|
||||||
a = ids[j];
|
|
||||||
for (i=j-1;i>=1;i--) {
|
|
||||||
if (ids[i] >= a) break;
|
|
||||||
ids[i+1] = ids[i];
|
|
||||||
}
|
|
||||||
ids[i+1] = a;
|
|
||||||
}
|
|
||||||
if (jstack == 0) break;
|
|
||||||
ir = istack[jstack--];
|
|
||||||
l = istack[jstack--];
|
|
||||||
} else {
|
|
||||||
k = (l + ir) >> 1; /* Choose median of left, center, right */
|
|
||||||
MIDL_SWAP(ids[k], ids[l+1]);
|
|
||||||
if (ids[l] < ids[ir]) {
|
|
||||||
MIDL_SWAP(ids[l], ids[ir]);
|
|
||||||
}
|
|
||||||
if (ids[l+1] < ids[ir]) {
|
|
||||||
MIDL_SWAP(ids[l+1], ids[ir]);
|
|
||||||
}
|
|
||||||
if (ids[l] < ids[l+1]) {
|
|
||||||
MIDL_SWAP(ids[l], ids[l+1]);
|
|
||||||
}
|
|
||||||
i = l+1;
|
|
||||||
j = ir;
|
|
||||||
a = ids[l+1];
|
|
||||||
for(;;) {
|
|
||||||
do i++; while(ids[i] > a);
|
|
||||||
do j--; while(ids[j] < a);
|
|
||||||
if (j < i) break;
|
|
||||||
MIDL_SWAP(ids[i],ids[j]);
|
|
||||||
}
|
|
||||||
ids[l+1] = ids[j];
|
|
||||||
ids[j] = a;
|
|
||||||
jstack += 2;
|
|
||||||
if (ir-i+1 >= j-l) {
|
|
||||||
istack[jstack] = ir;
|
|
||||||
istack[jstack-1] = i;
|
|
||||||
ir = j-1;
|
|
||||||
} else {
|
|
||||||
istack[jstack] = j-1;
|
|
||||||
istack[jstack-1] = l;
|
|
||||||
l = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned mdb_mid2l_search( MDB_ID2L 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_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id )
|
|
||||||
{
|
|
||||||
unsigned x, i;
|
|
||||||
|
|
||||||
x = mdb_mid2l_search( ids, id->mid );
|
|
||||||
|
|
||||||
if( x < 1 ) {
|
|
||||||
/* internal error */
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( x <= ids[0].mid && ids[x].mid == id->mid ) {
|
|
||||||
/* duplicate */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ids[0].mid >= MDB_IDL_UM_MAX ) {
|
|
||||||
/* too big */
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* insert id */
|
|
||||||
ids[0].mid++;
|
|
||||||
for (i=(unsigned)ids[0].mid; i>x; i--)
|
|
||||||
ids[i] = ids[i-1];
|
|
||||||
ids[x] = *id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id )
|
|
||||||
{
|
|
||||||
/* Too big? */
|
|
||||||
if (ids[0].mid >= MDB_IDL_UM_MAX) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
ids[0].mid++;
|
|
||||||
ids[ids[0].mid] = *id;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
/** @} */
|
|
|
@ -1,177 +0,0 @@
|
||||||
/* mtest.c - memory-mapped database tester/toy */
|
|
||||||
/*
|
|
||||||
* Copyright 2011-2015 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 <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()))
|
|
||||||
|
|
||||||
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", 0 /* MDB_FIXEDMAP |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;
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
Copyright 2011-2015 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>.
|
|
||||||
|
|
||||||
OpenLDAP is a registered trademark of the OpenLDAP Foundation.
|
|
||||||
|
|
||||||
Individual files and/or contributed packages may be copyright by
|
|
||||||
other parties and/or subject to additional restrictions.
|
|
||||||
|
|
||||||
This work also contains materials derived from public sources.
|
|
||||||
|
|
||||||
Additional information about OpenLDAP can be obtained at
|
|
||||||
<http://www.openldap.org/>.
|
|
|
@ -1,47 +0,0 @@
|
||||||
The OpenLDAP Public License
|
|
||||||
Version 2.8, 17 August 2003
|
|
||||||
|
|
||||||
Redistribution and use of this software and associated documentation
|
|
||||||
("Software"), with or without modification, are permitted provided
|
|
||||||
that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions in source form must retain copyright statements
|
|
||||||
and notices,
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce applicable copyright
|
|
||||||
statements and notices, this list of conditions, and the following
|
|
||||||
disclaimer in the documentation and/or other materials provided
|
|
||||||
with the distribution, and
|
|
||||||
|
|
||||||
3. Redistributions must contain a verbatim copy of this document.
|
|
||||||
|
|
||||||
The OpenLDAP Foundation may revise this license from time to time.
|
|
||||||
Each revision is distinguished by a version number. You may use
|
|
||||||
this Software under terms of this license revision or under the
|
|
||||||
terms of any subsequent revision of the license.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
|
|
||||||
CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
|
||||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
||||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
|
|
||||||
OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
The names of the authors and copyright holders must not be used in
|
|
||||||
advertising or otherwise to promote the sale, use or other dealing
|
|
||||||
in this Software without specific, written prior permission. Title
|
|
||||||
to copyright in this Software shall at all times remain with copyright
|
|
||||||
holders.
|
|
||||||
|
|
||||||
OpenLDAP is a registered trademark of the OpenLDAP Foundation.
|
|
||||||
|
|
||||||
Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
|
|
||||||
California, USA. All Rights Reserved. Permission to copy and
|
|
||||||
distribute verbatim copies of this document is granted.
|
|
|
@ -1,104 +0,0 @@
|
||||||
# Makefile for liblmdb (Lightning memory-mapped database library).
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
# Configuration. The compiler options must enable threaded compilation.
|
|
||||||
#
|
|
||||||
# Preprocessor macros (for CPPFLAGS) of interest...
|
|
||||||
# Note that the defaults should already be correct for most
|
|
||||||
# platforms; you should not need to change any of these.
|
|
||||||
# Read their descriptions in mdb.c if you do:
|
|
||||||
#
|
|
||||||
# - MDB_USE_POSIX_SEM
|
|
||||||
# - MDB_DSYNC
|
|
||||||
# - MDB_FDATASYNC
|
|
||||||
# - MDB_FDATASYNC_WORKS
|
|
||||||
# - MDB_USE_PWRITEV
|
|
||||||
#
|
|
||||||
# There may be other macros in mdb.c of interest. You should
|
|
||||||
# read mdb.c before changing any of them.
|
|
||||||
#
|
|
||||||
CC = gcc
|
|
||||||
W = -W -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized
|
|
||||||
THREADS = -pthread
|
|
||||||
OPT = -O2 -g
|
|
||||||
CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS)
|
|
||||||
LDLIBS =
|
|
||||||
SOLIBS =
|
|
||||||
prefix = /usr/local
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
IHDRS = lmdb.h
|
|
||||||
ILIBS = liblmdb.a liblmdb.so
|
|
||||||
IPROGS = mdb_stat mdb_copy mdb_dump mdb_load
|
|
||||||
IDOCS = mdb_stat.1 mdb_copy.1 mdb_dump.1 mdb_load.1
|
|
||||||
PROGS = $(IPROGS) mtest mtest2 mtest3 mtest4 mtest5
|
|
||||||
all: $(ILIBS) $(PROGS)
|
|
||||||
|
|
||||||
install: $(ILIBS) $(IPROGS) $(IHDRS)
|
|
||||||
for f in $(IPROGS); do cp $$f $(DESTDIR)$(prefix)/bin; done
|
|
||||||
for f in $(ILIBS); do cp $$f $(DESTDIR)$(prefix)/lib; done
|
|
||||||
for f in $(IHDRS); do cp $$f $(DESTDIR)$(prefix)/include; done
|
|
||||||
for f in $(IDOCS); do cp $$f $(DESTDIR)$(prefix)/man/man1; done
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(PROGS) *.[ao] *.[ls]o *~ 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.so: mdb.lo midl.lo
|
|
||||||
# $(CC) $(LDFLAGS) -pthread -shared -Wl,-Bsymbolic -o $@ mdb.o midl.o $(SOLIBS)
|
|
||||||
$(CC) $(LDFLAGS) -pthread -shared -o $@ mdb.lo midl.lo $(SOLIBS)
|
|
||||||
|
|
||||||
mdb_stat: mdb_stat.o liblmdb.a
|
|
||||||
mdb_copy: mdb_copy.o liblmdb.a
|
|
||||||
mdb_dump: mdb_dump.o liblmdb.a
|
|
||||||
mdb_load: mdb_load.o liblmdb.a
|
|
||||||
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
|
|
||||||
|
|
||||||
mdb.o: mdb.c lmdb.h midl.h
|
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c
|
|
||||||
|
|
||||||
midl.o: midl.c midl.h
|
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c midl.c
|
|
||||||
|
|
||||||
mdb.lo: mdb.c lmdb.h midl.h
|
|
||||||
$(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c mdb.c -o $@
|
|
||||||
|
|
||||||
midl.lo: midl.c midl.h
|
|
||||||
$(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c midl.c -o $@
|
|
||||||
|
|
||||||
%: %.o
|
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
|
||||||
|
|
||||||
%.o: %.c lmdb.h
|
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
|
|
||||||
|
|
||||||
COV_FLAGS=-fprofile-arcs -ftest-coverage
|
|
||||||
COV_OBJS=xmdb.o xmidl.o
|
|
||||||
|
|
||||||
coverage: xmtest
|
|
||||||
for i in mtest*.c [0-9]*.c; do j=`basename \$$i .c`; $(MAKE) $$j.o; \
|
|
||||||
gcc -o x$$j $$j.o $(COV_OBJS) -pthread $(COV_FLAGS); \
|
|
||||||
rm -rf testdb; mkdir testdb; ./x$$j; done
|
|
||||||
gcov xmdb.c
|
|
||||||
gcov xmidl.c
|
|
||||||
|
|
||||||
xmtest: mtest.o xmdb.o xmidl.o
|
|
||||||
gcc -o xmtest mtest.o xmdb.o xmidl.o -pthread $(COV_FLAGS)
|
|
||||||
|
|
||||||
xmdb.o: mdb.c lmdb.h midl.h
|
|
||||||
$(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -O0 $(COV_FLAGS) -c mdb.c -o $@
|
|
||||||
|
|
||||||
xmidl.o: midl.c midl.h
|
|
||||||
$(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -O0 $(COV_FLAGS) -c midl.c -o $@
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,54 +0,0 @@
|
||||||
.TH MDB_COPY 1 "2014/06/20" "LMDB 0.9.14"
|
|
||||||
.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
|
||||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
|
||||||
.SH NAME
|
|
||||||
mdb_copy \- LMDB environment copy tool
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B mdb_copy
|
|
||||||
[\c
|
|
||||||
.BR \-V ]
|
|
||||||
[\c
|
|
||||||
.BR \-c ]
|
|
||||||
[\c
|
|
||||||
.BR \-n ]
|
|
||||||
.B srcpath
|
|
||||||
[\c
|
|
||||||
.BR dstpath ]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
The
|
|
||||||
.B mdb_copy
|
|
||||||
utility copies an LMDB environment. The environment can
|
|
||||||
be copied regardless of whether it is currently in use.
|
|
||||||
No lockfile is created, since it gets recreated at need.
|
|
||||||
|
|
||||||
If
|
|
||||||
.I dstpath
|
|
||||||
is specified it must be the path of an empty directory
|
|
||||||
for storing the backup. Otherwise, the backup will be
|
|
||||||
written to stdout.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.BR \-V
|
|
||||||
Write the library version number to the standard output, and exit.
|
|
||||||
.TP
|
|
||||||
.BR \-c
|
|
||||||
Compact while copying. Only current data pages will be copied; freed
|
|
||||||
or unused pages will be omitted from the copy. This option will
|
|
||||||
slow down the backup process as it is more CPU-intensive.
|
|
||||||
.TP
|
|
||||||
.BR \-n
|
|
||||||
Open LDMB environment(s) which do not use subdirectories.
|
|
||||||
|
|
||||||
.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 CAVEATS
|
|
||||||
This utility can trigger significant file size growth if run
|
|
||||||
in parallel with write transactions, because pages which they
|
|
||||||
free during copying cannot be reused until the copy is done.
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR mdb_stat (1)
|
|
||||||
.SH AUTHOR
|
|
||||||
Howard Chu of Symas Corporation <http://www.symas.com>
|
|
|
@ -1,82 +0,0 @@
|
||||||
/* mdb_copy.c - memory-mapped database backup tool */
|
|
||||||
/*
|
|
||||||
* Copyright 2012-2015 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>.
|
|
||||||
*/
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#define MDB_STDOUT GetStdHandle(STD_OUTPUT_HANDLE)
|
|
||||||
#else
|
|
||||||
#define MDB_STDOUT 1
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include "lmdb.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
sighandle(int sig)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char * argv[])
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
MDB_env *env;
|
|
||||||
const char *progname = argv[0], *act;
|
|
||||||
unsigned flags = MDB_RDONLY;
|
|
||||||
unsigned cpflags = 0;
|
|
||||||
|
|
||||||
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] == '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
|
|
||||||
argc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc<2 || argc>3) {
|
|
||||||
fprintf(stderr, "usage: %s [-V] [-c] [-n] srcpath [dstpath]\n", progname);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SIGPIPE
|
|
||||||
signal(SIGPIPE, sighandle);
|
|
||||||
#endif
|
|
||||||
#ifdef SIGHUP
|
|
||||||
signal(SIGHUP, sighandle);
|
|
||||||
#endif
|
|
||||||
signal(SIGINT, sighandle);
|
|
||||||
signal(SIGTERM, sighandle);
|
|
||||||
|
|
||||||
act = "opening environment";
|
|
||||||
rc = mdb_env_create(&env);
|
|
||||||
if (rc == MDB_SUCCESS) {
|
|
||||||
rc = mdb_env_open(env, argv[1], flags, 0600);
|
|
||||||
}
|
|
||||||
if (rc == MDB_SUCCESS) {
|
|
||||||
act = "copying";
|
|
||||||
if (argc == 2)
|
|
||||||
rc = mdb_env_copyfd2(env, MDB_STDOUT, cpflags);
|
|
||||||
else
|
|
||||||
rc = mdb_env_copy2(env, argv[2], cpflags);
|
|
||||||
}
|
|
||||||
if (rc)
|
|
||||||
fprintf(stderr, "%s: %s failed, error %d (%s)\n",
|
|
||||||
progname, act, rc, mdb_strerror(rc));
|
|
||||||
mdb_env_close(env);
|
|
||||||
|
|
||||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
.TH MDB_DUMP 1 "2014/06/20" "LMDB 0.9.14"
|
|
||||||
.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
|
||||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
|
||||||
.SH NAME
|
|
||||||
mdb_dump \- LMDB environment export tool
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B mdb_dump
|
|
||||||
.BR \ envpath
|
|
||||||
[\c
|
|
||||||
.BR \-V ]
|
|
||||||
[\c
|
|
||||||
.BI \-f \ file\fR]
|
|
||||||
[\c
|
|
||||||
.BR \-l ]
|
|
||||||
[\c
|
|
||||||
.BR \-n ]
|
|
||||||
[\c
|
|
||||||
.BR \-p ]
|
|
||||||
[\c
|
|
||||||
.BR \-a \ |
|
|
||||||
.BI \-s \ subdb\fR]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
The
|
|
||||||
.B mdb_dump
|
|
||||||
utility reads a database and writes its contents to the
|
|
||||||
standard output using a portable flat-text format
|
|
||||||
understood by the
|
|
||||||
.BR mdb_load (1)
|
|
||||||
utility.
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.BR \-V
|
|
||||||
Write the library version number to the standard output, and exit.
|
|
||||||
.TP
|
|
||||||
.BR \-f \ file
|
|
||||||
Write to the specified file instead of to the standard output.
|
|
||||||
.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.
|
|
||||||
.TP
|
|
||||||
.BR \-p
|
|
||||||
If characters in either the key or data items are printing characters (as
|
|
||||||
defined by isprint(3)), output them directly. This option permits users to
|
|
||||||
use standard text editors and tools to modify the contents of databases.
|
|
||||||
|
|
||||||
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
|
|
||||||
.BR \-a
|
|
||||||
Dump all of the subdatabases in the environment.
|
|
||||||
.TP
|
|
||||||
.BR \-s \ subdb
|
|
||||||
Dump a specific subdatabase. If no database is specified, only the main database is dumped.
|
|
||||||
.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.
|
|
||||||
|
|
||||||
Dumping and reloading databases that use user-defined comparison functions
|
|
||||||
will result in new databases that use the default comparison functions.
|
|
||||||
\fBIn this case it is quite likely that the reloaded database will be
|
|
||||||
damaged beyond repair permitting neither record storage nor retrieval.\fP
|
|
||||||
|
|
||||||
The only available workaround is to modify the source for the
|
|
||||||
.BR mdb_load (1)
|
|
||||||
utility to load the database using the correct comparison functions.
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR mdb_load (1)
|
|
||||||
.SH AUTHOR
|
|
||||||
Howard Chu of Symas Corporation <http://www.symas.com>
|
|
|
@ -1,317 +0,0 @@
|
||||||
/* mdb_dump.c - memory-mapped database dump tool */
|
|
||||||
/*
|
|
||||||
* Copyright 2011-2015 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"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define Z "I"
|
|
||||||
#else
|
|
||||||
#define Z "z"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PRINT 1
|
|
||||||
static int mode;
|
|
||||||
|
|
||||||
typedef struct flagbit {
|
|
||||||
int bit;
|
|
||||||
char *name;
|
|
||||||
} flagbit;
|
|
||||||
|
|
||||||
flagbit dbflags[] = {
|
|
||||||
{ MDB_REVERSEKEY, "reversekey" },
|
|
||||||
{ MDB_DUPSORT, "dupsort" },
|
|
||||||
{ MDB_INTEGERKEY, "integerkey" },
|
|
||||||
{ MDB_DUPFIXED, "dupfixed" },
|
|
||||||
{ MDB_INTEGERDUP, "integerdup" },
|
|
||||||
{ MDB_REVERSEDUP, "reversedup" },
|
|
||||||
{ 0, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static volatile sig_atomic_t gotsig;
|
|
||||||
|
|
||||||
static void dumpsig( int sig )
|
|
||||||
{
|
|
||||||
gotsig=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char hexc[] = "0123456789abcdef";
|
|
||||||
|
|
||||||
static void hex(unsigned char c)
|
|
||||||
{
|
|
||||||
putchar(hexc[c >> 4]);
|
|
||||||
putchar(hexc[c & 0xf]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void text(MDB_val *v)
|
|
||||||
{
|
|
||||||
unsigned char *c, *end;
|
|
||||||
|
|
||||||
putchar(' ');
|
|
||||||
c = v->mv_data;
|
|
||||||
end = c + v->mv_size;
|
|
||||||
while (c < end) {
|
|
||||||
if (isprint(*c)) {
|
|
||||||
putchar(*c);
|
|
||||||
} else {
|
|
||||||
putchar('\\');
|
|
||||||
hex(*c);
|
|
||||||
}
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
putchar('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
static void byte(MDB_val *v)
|
|
||||||
{
|
|
||||||
unsigned char *c, *end;
|
|
||||||
|
|
||||||
putchar(' ');
|
|
||||||
c = v->mv_data;
|
|
||||||
end = c + v->mv_size;
|
|
||||||
while (c < end) {
|
|
||||||
hex(*c++);
|
|
||||||
}
|
|
||||||
putchar('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dump in BDB-compatible format */
|
|
||||||
static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name)
|
|
||||||
{
|
|
||||||
MDB_cursor *mc;
|
|
||||||
MDB_stat ms;
|
|
||||||
MDB_val key, data;
|
|
||||||
MDB_envinfo info;
|
|
||||||
unsigned int flags;
|
|
||||||
int rc, i;
|
|
||||||
|
|
||||||
rc = mdb_dbi_flags(txn, dbi, &flags);
|
|
||||||
if (rc) return rc;
|
|
||||||
|
|
||||||
rc = mdb_stat(txn, dbi, &ms);
|
|
||||||
if (rc) return rc;
|
|
||||||
|
|
||||||
rc = mdb_env_info(mdb_txn_env(txn), &info);
|
|
||||||
if (rc) return rc;
|
|
||||||
|
|
||||||
printf("VERSION=3\n");
|
|
||||||
printf("format=%s\n", mode & PRINT ? "print" : "bytevalue");
|
|
||||||
if (name)
|
|
||||||
printf("database=%s\n", name);
|
|
||||||
printf("type=btree\n");
|
|
||||||
printf("mapsize=%" Z "u\n", info.me_mapsize);
|
|
||||||
if (info.me_mapaddr)
|
|
||||||
printf("mapaddr=%p\n", info.me_mapaddr);
|
|
||||||
printf("maxreaders=%u\n", info.me_maxreaders);
|
|
||||||
|
|
||||||
if (flags & MDB_DUPSORT)
|
|
||||||
printf("duplicates=1\n");
|
|
||||||
|
|
||||||
for (i=0; dbflags[i].bit; i++)
|
|
||||||
if (flags & dbflags[i].bit)
|
|
||||||
printf("%s=1\n", dbflags[i].name);
|
|
||||||
|
|
||||||
printf("db_pagesize=%d\n", ms.ms_psize);
|
|
||||||
printf("HEADER=END\n");
|
|
||||||
|
|
||||||
rc = mdb_cursor_open(txn, dbi, &mc);
|
|
||||||
if (rc) return rc;
|
|
||||||
|
|
||||||
while ((rc = mdb_cursor_get(mc, &key, &data, MDB_NEXT) == MDB_SUCCESS)) {
|
|
||||||
if (gotsig) {
|
|
||||||
rc = EINTR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (mode & PRINT) {
|
|
||||||
text(&key);
|
|
||||||
text(&data);
|
|
||||||
} else {
|
|
||||||
byte(&key);
|
|
||||||
byte(&data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("DATA=END\n");
|
|
||||||
if (rc == MDB_NOTFOUND)
|
|
||||||
rc = MDB_SUCCESS;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage(char *prog)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "usage: %s dbpath [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb]\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 alldbs = 0, envflags = 0, list = 0;
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
usage(prog);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -a: dump main DB and all subDBs
|
|
||||||
* -s: dump only the named subDB
|
|
||||||
* -n: use NOSUBDIR flag on env_open
|
|
||||||
* -p: use printable characters
|
|
||||||
* -f: write to file instead of stdout
|
|
||||||
* -V: print version and exit
|
|
||||||
* (default) dump only the main DB
|
|
||||||
*/
|
|
||||||
while ((i = getopt(argc, argv, "af:lnps:V")) != EOF) {
|
|
||||||
switch(i) {
|
|
||||||
case 'V':
|
|
||||||
printf("%s\n", MDB_VERSION_STRING);
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
list = 1;
|
|
||||||
/*FALLTHROUGH*/;
|
|
||||||
case 'a':
|
|
||||||
if (subname)
|
|
||||||
usage(prog);
|
|
||||||
alldbs++;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
if (freopen(optarg, "w", stdout) == NULL) {
|
|
||||||
fprintf(stderr, "%s: %s: reopen: %s\n",
|
|
||||||
prog, optarg, strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
envflags |= MDB_NOSUBDIR;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
mode |= PRINT;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
if (alldbs)
|
|
||||||
usage(prog);
|
|
||||||
subname = 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 (alldbs || subname) {
|
|
||||||
mdb_env_set_maxdbs(env, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 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, 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);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
goto txn_abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alldbs) {
|
|
||||||
MDB_cursor *cursor;
|
|
||||||
MDB_val key;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
rc = mdb_cursor_open(txn, dbi, &cursor);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
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))
|
|
||||||
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);
|
|
||||||
if (rc == MDB_SUCCESS) {
|
|
||||||
if (list) {
|
|
||||||
printf("%s\n", str);
|
|
||||||
list++;
|
|
||||||
} else {
|
|
||||||
rc = dumpit(txn, db2, str);
|
|
||||||
if (rc)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mdb_close(env, db2);
|
|
||||||
}
|
|
||||||
free(str);
|
|
||||||
if (rc) continue;
|
|
||||||
}
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
if (!count) {
|
|
||||||
fprintf(stderr, "%s: %s does not contain multiple databases\n", prog, envname);
|
|
||||||
rc = MDB_NOTFOUND;
|
|
||||||
} else if (rc == MDB_NOTFOUND) {
|
|
||||||
rc = MDB_SUCCESS;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rc = dumpit(txn, dbi, subname);
|
|
||||||
}
|
|
||||||
if (rc && rc != MDB_NOTFOUND)
|
|
||||||
fprintf(stderr, "%s: %s: %s\n", prog, envname, mdb_strerror(rc));
|
|
||||||
|
|
||||||
mdb_close(env, dbi);
|
|
||||||
txn_abort:
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
env_close:
|
|
||||||
mdb_env_close(env);
|
|
||||||
|
|
||||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
||||||
}
|
|
|
@ -1,454 +0,0 @@
|
||||||
/* mdb_load.c - memory-mapped database load tool */
|
|
||||||
/*
|
|
||||||
* Copyright 2011-2015 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 <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "lmdb.h"
|
|
||||||
|
|
||||||
#define PRINT 1
|
|
||||||
#define NOHDR 2
|
|
||||||
static int mode;
|
|
||||||
|
|
||||||
static char *subname = NULL;
|
|
||||||
|
|
||||||
static size_t lineno;
|
|
||||||
static int version;
|
|
||||||
|
|
||||||
static int flags;
|
|
||||||
|
|
||||||
static char *prog;
|
|
||||||
|
|
||||||
static int Eof;
|
|
||||||
|
|
||||||
static MDB_envinfo info;
|
|
||||||
|
|
||||||
static MDB_val kbuf, dbuf;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define Z "I"
|
|
||||||
#else
|
|
||||||
#define Z "z"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define STRLENOF(s) (sizeof(s)-1)
|
|
||||||
|
|
||||||
typedef struct flagbit {
|
|
||||||
int bit;
|
|
||||||
char *name;
|
|
||||||
int len;
|
|
||||||
} flagbit;
|
|
||||||
|
|
||||||
#define S(s) s, STRLENOF(s)
|
|
||||||
|
|
||||||
flagbit dbflags[] = {
|
|
||||||
{ MDB_REVERSEKEY, S("reversekey") },
|
|
||||||
{ MDB_DUPSORT, S("dupsort") },
|
|
||||||
{ MDB_INTEGERKEY, S("integerkey") },
|
|
||||||
{ MDB_DUPFIXED, S("dupfixed") },
|
|
||||||
{ MDB_INTEGERDUP, S("integerdup") },
|
|
||||||
{ MDB_REVERSEDUP, S("reversedup") },
|
|
||||||
{ 0, NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static void readhdr(void)
|
|
||||||
{
|
|
||||||
char *ptr;
|
|
||||||
|
|
||||||
while (fgets(dbuf.mv_data, dbuf.mv_size, stdin) != NULL) {
|
|
||||||
lineno++;
|
|
||||||
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",
|
|
||||||
prog, lineno, version);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
} else if (!strncmp(dbuf.mv_data, "HEADER=END", STRLENOF("HEADER=END"))) {
|
|
||||||
break;
|
|
||||||
} else if (!strncmp(dbuf.mv_data, "format=", STRLENOF("format="))) {
|
|
||||||
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",
|
|
||||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("FORMAT="));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
} else if (!strncmp(dbuf.mv_data, "database=", STRLENOF("database="))) {
|
|
||||||
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
|
||||||
if (ptr) *ptr = '\0';
|
|
||||||
if (subname) free(subname);
|
|
||||||
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",
|
|
||||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("type="));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
} else if (!strncmp(dbuf.mv_data, "mapaddr=", STRLENOF("mapaddr="))) {
|
|
||||||
int i;
|
|
||||||
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
|
||||||
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",
|
|
||||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapaddr="));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
} else if (!strncmp(dbuf.mv_data, "mapsize=", STRLENOF("mapsize="))) {
|
|
||||||
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);
|
|
||||||
if (i != 1) {
|
|
||||||
fprintf(stderr, "%s: line %" Z "d: invalid mapsize %s\n",
|
|
||||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapsize="));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
} else if (!strncmp(dbuf.mv_data, "maxreaders=", STRLENOF("maxreaders="))) {
|
|
||||||
int i;
|
|
||||||
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
|
||||||
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",
|
|
||||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("maxreaders="));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int i;
|
|
||||||
for (i=0; dbflags[i].bit; i++) {
|
|
||||||
if (!strncmp(dbuf.mv_data, dbflags[i].name, dbflags[i].len) &&
|
|
||||||
((char *)dbuf.mv_data)[dbflags[i].len] == '=') {
|
|
||||||
flags |= dbflags[i].bit;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!dbflags[i].bit) {
|
|
||||||
ptr = memchr(dbuf.mv_data, '=', dbuf.mv_size);
|
|
||||||
if (!ptr) {
|
|
||||||
fprintf(stderr, "%s: line %" Z "d: unexpected format\n",
|
|
||||||
prog, lineno);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else {
|
|
||||||
*ptr = '\0';
|
|
||||||
fprintf(stderr, "%s: line %" Z "d: unrecognized keyword ignored: %s\n",
|
|
||||||
prog, lineno, (char *)dbuf.mv_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void badend(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s: line %" Z "d: unexpected end of input\n",
|
|
||||||
prog, lineno);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int unhex(unsigned char *c2)
|
|
||||||
{
|
|
||||||
int x, c;
|
|
||||||
x = *c2++ & 0x4f;
|
|
||||||
if (x & 0x40)
|
|
||||||
x -= 55;
|
|
||||||
c = x << 4;
|
|
||||||
x = *c2 & 0x4f;
|
|
||||||
if (x & 0x40)
|
|
||||||
x -= 55;
|
|
||||||
c |= x;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int readline(MDB_val *out, MDB_val *buf)
|
|
||||||
{
|
|
||||||
unsigned char *c1, *c2, *end;
|
|
||||||
size_t len, l2;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
if (!(mode & NOHDR)) {
|
|
||||||
c = fgetc(stdin);
|
|
||||||
if (c == EOF) {
|
|
||||||
Eof = 1;
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
if (c != ' ') {
|
|
||||||
lineno++;
|
|
||||||
if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) {
|
|
||||||
badend:
|
|
||||||
Eof = 1;
|
|
||||||
badend();
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
if (c == 'D' && !strncmp(buf->mv_data, "ATA=END", STRLENOF("ATA=END")))
|
|
||||||
return EOF;
|
|
||||||
goto badend;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) {
|
|
||||||
Eof = 1;
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
lineno++;
|
|
||||||
|
|
||||||
c1 = buf->mv_data;
|
|
||||||
len = strlen((char *)c1);
|
|
||||||
l2 = len;
|
|
||||||
|
|
||||||
/* Is buffer too short? */
|
|
||||||
while (c1[len-1] != '\n') {
|
|
||||||
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",
|
|
||||||
prog, lineno);
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
c1 = buf->mv_data;
|
|
||||||
c1 += l2;
|
|
||||||
if (fgets((char *)c1, buf->mv_size+1, stdin) == NULL) {
|
|
||||||
Eof = 1;
|
|
||||||
badend();
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
buf->mv_size *= 2;
|
|
||||||
len = strlen((char *)c1);
|
|
||||||
l2 += len;
|
|
||||||
}
|
|
||||||
c1 = c2 = buf->mv_data;
|
|
||||||
len = l2;
|
|
||||||
c1[--len] = '\0';
|
|
||||||
end = c1 + len;
|
|
||||||
|
|
||||||
if (mode & PRINT) {
|
|
||||||
while (c2 < end) {
|
|
||||||
if (*c2 == '\\') {
|
|
||||||
if (c2[1] == '\\') {
|
|
||||||
c1++; c2 += 2;
|
|
||||||
} else {
|
|
||||||
if (c2+3 > end || !isxdigit(c2[1]) || !isxdigit(c2[2])) {
|
|
||||||
Eof = 1;
|
|
||||||
badend();
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
*c1++ = unhex(++c2);
|
|
||||||
c2 += 2;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c1++; c2++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* odd length not allowed */
|
|
||||||
if (len & 1) {
|
|
||||||
Eof = 1;
|
|
||||||
badend();
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
while (c2 < end) {
|
|
||||||
if (!isxdigit(*c2) || !isxdigit(c2[1])) {
|
|
||||||
Eof = 1;
|
|
||||||
badend();
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
*c1++ = unhex(c2);
|
|
||||||
c2 += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c2 = out->mv_data = buf->mv_data;
|
|
||||||
out->mv_size = c1 - c2;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "usage: %s dbpath [-V] [-f input] [-n] [-s name] [-N] [-T]\n", prog);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int i, rc;
|
|
||||||
MDB_env *env;
|
|
||||||
MDB_txn *txn;
|
|
||||||
MDB_cursor *mc;
|
|
||||||
MDB_dbi dbi;
|
|
||||||
char *envname;
|
|
||||||
int envflags = 0, putflags = 0;
|
|
||||||
int dohdr = 0;
|
|
||||||
|
|
||||||
prog = argv[0];
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -f: load file instead of stdin
|
|
||||||
* -n: use NOSUBDIR flag on env_open
|
|
||||||
* -s: load into named subDB
|
|
||||||
* -N: use NOOVERWRITE on puts
|
|
||||||
* -T: read plaintext
|
|
||||||
* -V: print version and exit
|
|
||||||
*/
|
|
||||||
while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) {
|
|
||||||
switch(i) {
|
|
||||||
case 'V':
|
|
||||||
printf("%s\n", MDB_VERSION_STRING);
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
if (freopen(optarg, "r", stdin) == NULL) {
|
|
||||||
fprintf(stderr, "%s: %s: reopen: %s\n",
|
|
||||||
prog, optarg, strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
envflags |= MDB_NOSUBDIR;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
subname = strdup(optarg);
|
|
||||||
break;
|
|
||||||
case 'N':
|
|
||||||
putflags = MDB_NOOVERWRITE|MDB_NODUPDATA;
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
mode |= NOHDR;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind != argc - 1)
|
|
||||||
usage();
|
|
||||||
|
|
||||||
dbuf.mv_size = 4096;
|
|
||||||
dbuf.mv_data = malloc(dbuf.mv_size);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
mdb_env_set_maxdbs(env, 2);
|
|
||||||
|
|
||||||
if (info.me_maxreaders)
|
|
||||||
mdb_env_set_maxreaders(env, info.me_maxreaders);
|
|
||||||
|
|
||||||
if (info.me_mapsize)
|
|
||||||
mdb_env_set_mapsize(env, info.me_mapsize);
|
|
||||||
|
|
||||||
if (info.me_mapaddr)
|
|
||||||
envflags |= MDB_FIXEDMAP;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2;
|
|
||||||
kbuf.mv_data = malloc(kbuf.mv_size);
|
|
||||||
|
|
||||||
while(!Eof) {
|
|
||||||
MDB_val key, data;
|
|
||||||
int batch = 0;
|
|
||||||
flags = 0;
|
|
||||||
|
|
||||||
if (!dohdr) {
|
|
||||||
dohdr = 1;
|
|
||||||
} else if (!(mode & NOHDR))
|
|
||||||
readhdr();
|
|
||||||
|
|
||||||
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, flags|MDB_CREATE, &dbi);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
goto txn_abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = mdb_cursor_open(txn, dbi, &mc);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
goto txn_abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
rc = readline(&key, &kbuf);
|
|
||||||
if (rc == EOF)
|
|
||||||
break;
|
|
||||||
if (rc)
|
|
||||||
goto txn_abort;
|
|
||||||
|
|
||||||
rc = readline(&data, &dbuf);
|
|
||||||
if (rc)
|
|
||||||
goto txn_abort;
|
|
||||||
|
|
||||||
rc = mdb_cursor_put(mc, &key, &data, putflags);
|
|
||||||
if (rc == MDB_KEYEXIST && putflags)
|
|
||||||
continue;
|
|
||||||
if (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",
|
|
||||||
prog, lineno, 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_cursor_open(txn, dbi, &mc);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
||||||
goto txn_abort;
|
|
||||||
}
|
|
||||||
batch = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rc = mdb_txn_commit(txn);
|
|
||||||
txn = NULL;
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n",
|
|
||||||
prog, lineno, mdb_strerror(rc));
|
|
||||||
goto env_close;
|
|
||||||
}
|
|
||||||
mdb_dbi_close(env, dbi);
|
|
||||||
}
|
|
||||||
|
|
||||||
txn_abort:
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
env_close:
|
|
||||||
mdb_env_close(env);
|
|
||||||
|
|
||||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
||||||
}
|
|
|
@ -1,186 +0,0 @@
|
||||||
/** @file midl.h
|
|
||||||
* @brief LMDB ID List header file.
|
|
||||||
*
|
|
||||||
* This file was originally part of back-bdb but has been
|
|
||||||
* modified for use in libmdb. Most of the macros defined
|
|
||||||
* in this file are unused, just left over from the original.
|
|
||||||
*
|
|
||||||
* This file is only used internally in libmdb and its definitions
|
|
||||||
* are not exposed publicly.
|
|
||||||
*/
|
|
||||||
/* $OpenLDAP$ */
|
|
||||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
||||||
*
|
|
||||||
* Copyright 2000-2015 The OpenLDAP Foundation.
|
|
||||||
* 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>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _MDB_MIDL_H_
|
|
||||||
#define _MDB_MIDL_H_
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @defgroup internal LMDB Internals
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @defgroup idls ID List Management
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
/** 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;
|
|
||||||
|
|
||||||
/** An IDL is an ID List, a sorted array of IDs. The first
|
|
||||||
* element of the array is a counter for how many actual
|
|
||||||
* IDs are in the list. In the original back-bdb code, IDLs are
|
|
||||||
* sorted in ascending order. For libmdb IDLs are sorted in
|
|
||||||
* descending order.
|
|
||||||
*/
|
|
||||||
typedef MDB_ID *MDB_IDL;
|
|
||||||
|
|
||||||
/* IDL sizes - likely should be even bigger
|
|
||||||
* limiting factors: sizeof(ID), thread stack size
|
|
||||||
*/
|
|
||||||
#define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
|
|
||||||
#define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN)
|
|
||||||
#define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1))
|
|
||||||
|
|
||||||
#define MDB_IDL_DB_MAX (MDB_IDL_DB_SIZE-1)
|
|
||||||
#define MDB_IDL_UM_MAX (MDB_IDL_UM_SIZE-1)
|
|
||||||
|
|
||||||
#define MDB_IDL_SIZEOF(ids) (((ids)[0]+1) * sizeof(MDB_ID))
|
|
||||||
#define MDB_IDL_IS_ZERO(ids) ( (ids)[0] == 0 )
|
|
||||||
#define MDB_IDL_CPY( dst, src ) (memcpy( dst, src, MDB_IDL_SIZEOF( src ) ))
|
|
||||||
#define MDB_IDL_FIRST( ids ) ( (ids)[1] )
|
|
||||||
#define MDB_IDL_LAST( ids ) ( (ids)[(ids)[0]] )
|
|
||||||
|
|
||||||
/** Current max length of an #mdb_midl_alloc()ed IDL */
|
|
||||||
#define MDB_IDL_ALLOCLEN( ids ) ( (ids)[-1] )
|
|
||||||
|
|
||||||
/** Append ID to IDL. The IDL must be big enough. */
|
|
||||||
#define mdb_midl_xappend(idl, id) do { \
|
|
||||||
MDB_ID *xidl = (idl), xlen = ++(xidl[0]); \
|
|
||||||
xidl[xlen] = (id); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/** Search for an ID in an IDL.
|
|
||||||
* @param[in] ids The IDL to search.
|
|
||||||
* @param[in] id The ID to search for.
|
|
||||||
* @return The index of the first ID greater than or equal to \b id.
|
|
||||||
*/
|
|
||||||
unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id );
|
|
||||||
|
|
||||||
/** Allocate an IDL.
|
|
||||||
* Allocates memory for an IDL of the given size.
|
|
||||||
* @return IDL on success, NULL on failure.
|
|
||||||
*/
|
|
||||||
MDB_IDL mdb_midl_alloc(int num);
|
|
||||||
|
|
||||||
/** Free an IDL.
|
|
||||||
* @param[in] ids The IDL to free.
|
|
||||||
*/
|
|
||||||
void mdb_midl_free(MDB_IDL ids);
|
|
||||||
|
|
||||||
/** Shrink an IDL.
|
|
||||||
* Return the IDL to the default size if it has grown larger.
|
|
||||||
* @param[in,out] idp Address of the IDL to shrink.
|
|
||||||
* @return 0 on no change, non-zero if shrunk.
|
|
||||||
*/
|
|
||||||
int mdb_midl_shrink(MDB_IDL *idp);
|
|
||||||
|
|
||||||
/** Make room for num additional elements in an IDL.
|
|
||||||
* @param[in,out] idp Address of the IDL.
|
|
||||||
* @param[in] num Number of elements to make room for.
|
|
||||||
* @return 0 on success, ENOMEM on failure.
|
|
||||||
*/
|
|
||||||
int mdb_midl_need(MDB_IDL *idp, unsigned num);
|
|
||||||
|
|
||||||
/** Append an ID onto an IDL.
|
|
||||||
* @param[in,out] idp Address of the IDL to append to.
|
|
||||||
* @param[in] id The ID to append.
|
|
||||||
* @return 0 on success, ENOMEM if the IDL is too large.
|
|
||||||
*/
|
|
||||||
int mdb_midl_append( MDB_IDL *idp, MDB_ID id );
|
|
||||||
|
|
||||||
/** Append an IDL onto an IDL.
|
|
||||||
* @param[in,out] idp Address of the IDL to append to.
|
|
||||||
* @param[in] app The IDL to append.
|
|
||||||
* @return 0 on success, ENOMEM if the IDL is too large.
|
|
||||||
*/
|
|
||||||
int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app );
|
|
||||||
|
|
||||||
/** Append an ID range onto an IDL.
|
|
||||||
* @param[in,out] idp Address of the IDL to append to.
|
|
||||||
* @param[in] id The lowest ID to append.
|
|
||||||
* @param[in] n Number of IDs to append.
|
|
||||||
* @return 0 on success, ENOMEM if the IDL is too large.
|
|
||||||
*/
|
|
||||||
int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n );
|
|
||||||
|
|
||||||
/** Merge an IDL onto an IDL. The destination IDL must be big enough.
|
|
||||||
* @param[in] idl The IDL to merge into.
|
|
||||||
* @param[in] merge The IDL to merge.
|
|
||||||
*/
|
|
||||||
void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge );
|
|
||||||
|
|
||||||
/** Sort an IDL.
|
|
||||||
* @param[in,out] ids The IDL to sort.
|
|
||||||
*/
|
|
||||||
void mdb_midl_sort( MDB_IDL ids );
|
|
||||||
|
|
||||||
/** An ID2 is an ID/pointer pair.
|
|
||||||
*/
|
|
||||||
typedef struct MDB_ID2 {
|
|
||||||
MDB_ID mid; /**< The ID */
|
|
||||||
void *mptr; /**< The pointer */
|
|
||||||
} MDB_ID2;
|
|
||||||
|
|
||||||
/** An ID2L is an ID2 List, a sorted array of ID2s.
|
|
||||||
* The first element's \b mid member is a count of how many actual
|
|
||||||
* elements are in the array. The \b mptr member of the first element is unused.
|
|
||||||
* The array is sorted in ascending order by \b mid.
|
|
||||||
*/
|
|
||||||
typedef MDB_ID2 *MDB_ID2L;
|
|
||||||
|
|
||||||
/** Search for an ID in an ID2L.
|
|
||||||
* @param[in] ids The ID2L to search.
|
|
||||||
* @param[in] id The ID to search for.
|
|
||||||
* @return The index of the first ID2 whose \b mid member is greater than or equal to \b id.
|
|
||||||
*/
|
|
||||||
unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id );
|
|
||||||
|
|
||||||
|
|
||||||
/** Insert an ID2 into a ID2L.
|
|
||||||
* @param[in,out] ids The ID2L to insert into.
|
|
||||||
* @param[in] id The ID2 to insert.
|
|
||||||
* @return 0 on success, -1 if the ID was already present in the ID2L.
|
|
||||||
*/
|
|
||||||
int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id );
|
|
||||||
|
|
||||||
/** Append an ID2 into a ID2L.
|
|
||||||
* @param[in,out] ids The ID2L to append into.
|
|
||||||
* @param[in] id The ID2 to append.
|
|
||||||
* @return 0 on success, -2 if the ID2L is too big.
|
|
||||||
*/
|
|
||||||
int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id );
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
/** @} */
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif /* _MDB_MIDL_H_ */
|
|
|
@ -1,124 +0,0 @@
|
||||||
/* mtest2.c - memory-mapped database tester/toy */
|
|
||||||
/*
|
|
||||||
* Copyright 2011-2015 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>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Just like mtest.c, but using a subDB instead of the main DB */
|
|
||||||
|
|
||||||
#include <stdio.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()))
|
|
||||||
|
|
||||||
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;
|
|
||||||
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_set_maxdbs(env, 4));
|
|
||||||
E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
|
|
||||||
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
E(mdb_dbi_open(txn, "id1", MDB_CREATE, &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]);
|
|
||||||
data.mv_size = sizeof(sval);
|
|
||||||
data.mv_data = sval;
|
|
||||||
if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE)))
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
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 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");
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
|
|
||||||
mdb_dbi_close(env, dbi);
|
|
||||||
mdb_env_close(env);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,133 +0,0 @@
|
||||||
/* mtest3.c - memory-mapped database tester/toy */
|
|
||||||
/*
|
|
||||||
* Copyright 2011-2015 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>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Tests for sorted duplicate DBs */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.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()))
|
|
||||||
|
|
||||||
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;
|
|
||||||
int count;
|
|
||||||
int *values;
|
|
||||||
char sval[32];
|
|
||||||
char kval[sizeof(int)];
|
|
||||||
|
|
||||||
srand(time(NULL));
|
|
||||||
|
|
||||||
memset(sval, 0, sizeof(sval));
|
|
||||||
|
|
||||||
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_mapsize(env, 10485760));
|
|
||||||
E(mdb_env_set_maxdbs(env, 4));
|
|
||||||
E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
|
|
||||||
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
E(mdb_dbi_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
|
|
||||||
|
|
||||||
key.mv_size = sizeof(int);
|
|
||||||
key.mv_data = kval;
|
|
||||||
data.mv_size = sizeof(sval);
|
|
||||||
data.mv_data = sval;
|
|
||||||
|
|
||||||
printf("Adding %d values\n", count);
|
|
||||||
for (i=0;i<count;i++) {
|
|
||||||
if (!(i & 0x0f))
|
|
||||||
sprintf(kval, "%03x", values[i]);
|
|
||||||
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
|
|
||||||
if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA)))
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
|
|
||||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
|
||||||
j++;
|
|
||||||
txn=NULL;
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
sprintf(kval, "%03x", values[i & ~0x0f]);
|
|
||||||
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
|
|
||||||
key.mv_size = sizeof(int);
|
|
||||||
key.mv_data = kval;
|
|
||||||
data.mv_size = sizeof(sval);
|
|
||||||
data.mv_data = sval;
|
|
||||||
if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) {
|
|
||||||
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 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");
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
|
|
||||||
mdb_dbi_close(env, dbi);
|
|
||||||
mdb_env_close(env);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,168 +0,0 @@
|
||||||
/* mtest4.c - memory-mapped database tester/toy */
|
|
||||||
/*
|
|
||||||
* Copyright 2011-2015 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>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Tests for sorted duplicate DBs with fixed-size keys */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.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()))
|
|
||||||
|
|
||||||
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;
|
|
||||||
int count;
|
|
||||||
int *values;
|
|
||||||
char sval[8];
|
|
||||||
char kval[sizeof(int)];
|
|
||||||
|
|
||||||
memset(sval, 0, sizeof(sval));
|
|
||||||
|
|
||||||
count = 510;
|
|
||||||
values = (int *)malloc(count*sizeof(int));
|
|
||||||
|
|
||||||
for(i = 0;i<count;i++) {
|
|
||||||
values[i] = i*5;
|
|
||||||
}
|
|
||||||
|
|
||||||
E(mdb_env_create(&env));
|
|
||||||
E(mdb_env_set_mapsize(env, 10485760));
|
|
||||||
E(mdb_env_set_maxdbs(env, 4));
|
|
||||||
E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
|
|
||||||
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
E(mdb_dbi_open(txn, "id4", MDB_CREATE|MDB_DUPSORT|MDB_DUPFIXED, &dbi));
|
|
||||||
|
|
||||||
key.mv_size = sizeof(int);
|
|
||||||
key.mv_data = kval;
|
|
||||||
data.mv_size = sizeof(sval);
|
|
||||||
data.mv_data = sval;
|
|
||||||
|
|
||||||
printf("Adding %d values\n", count);
|
|
||||||
strcpy(kval, "001");
|
|
||||||
for (i=0;i<count;i++) {
|
|
||||||
sprintf(sval, "%07x", values[i]);
|
|
||||||
if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA)))
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if (j) printf("%d duplicates skipped\n", j);
|
|
||||||
E(mdb_txn_commit(txn));
|
|
||||||
E(mdb_env_stat(env, &mst));
|
|
||||||
|
|
||||||
/* there should be one full page of dups now.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* test all 3 branches of split code:
|
|
||||||
* 1: new key in lower half
|
|
||||||
* 2: new key at split point
|
|
||||||
* 3: new key in upper half
|
|
||||||
*/
|
|
||||||
|
|
||||||
key.mv_size = sizeof(int);
|
|
||||||
key.mv_data = kval;
|
|
||||||
data.mv_size = sizeof(sval);
|
|
||||||
data.mv_data = sval;
|
|
||||||
|
|
||||||
sprintf(sval, "%07x", values[3]+1);
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
(void)RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA));
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
|
|
||||||
sprintf(sval, "%07x", values[255]+1);
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
(void)RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA));
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
|
|
||||||
sprintf(sval, "%07x", values[500]+1);
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
(void)RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA));
|
|
||||||
E(mdb_txn_commit(txn));
|
|
||||||
|
|
||||||
/* Try MDB_NEXT_MULTIPLE */
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
|
||||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT_MULTIPLE)) == 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");
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
j=0;
|
|
||||||
|
|
||||||
for (i= count - 1; i > -1; i-= (rand()%3)) {
|
|
||||||
j++;
|
|
||||||
txn=NULL;
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
sprintf(sval, "%07x", values[i]);
|
|
||||||
key.mv_size = sizeof(int);
|
|
||||||
key.mv_data = kval;
|
|
||||||
data.mv_size = sizeof(sval);
|
|
||||||
data.mv_data = sval;
|
|
||||||
if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) {
|
|
||||||
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 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");
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
|
|
||||||
mdb_dbi_close(env, dbi);
|
|
||||||
mdb_env_close(env);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,135 +0,0 @@
|
||||||
/* mtest5.c - memory-mapped database tester/toy */
|
|
||||||
/*
|
|
||||||
* Copyright 2011-2015 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>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Tests for sorted duplicate DBs using cursor_put */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.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()))
|
|
||||||
|
|
||||||
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;
|
|
||||||
int count;
|
|
||||||
int *values;
|
|
||||||
char sval[32];
|
|
||||||
char kval[sizeof(int)];
|
|
||||||
|
|
||||||
srand(time(NULL));
|
|
||||||
|
|
||||||
memset(sval, 0, sizeof(sval));
|
|
||||||
|
|
||||||
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_mapsize(env, 10485760));
|
|
||||||
E(mdb_env_set_maxdbs(env, 4));
|
|
||||||
E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
|
|
||||||
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
E(mdb_dbi_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
|
|
||||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
|
||||||
|
|
||||||
key.mv_size = sizeof(int);
|
|
||||||
key.mv_data = kval;
|
|
||||||
data.mv_size = sizeof(sval);
|
|
||||||
data.mv_data = sval;
|
|
||||||
|
|
||||||
printf("Adding %d values\n", count);
|
|
||||||
for (i=0;i<count;i++) {
|
|
||||||
if (!(i & 0x0f))
|
|
||||||
sprintf(kval, "%03x", values[i]);
|
|
||||||
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
|
|
||||||
if (RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NODUPDATA)))
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if (j) printf("%d duplicates skipped\n", j);
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
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;
|
|
||||||
|
|
||||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
|
||||||
j++;
|
|
||||||
txn=NULL;
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
sprintf(kval, "%03x", values[i & ~0x0f]);
|
|
||||||
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
|
|
||||||
key.mv_size = sizeof(int);
|
|
||||||
key.mv_data = kval;
|
|
||||||
data.mv_size = sizeof(sval);
|
|
||||||
data.mv_data = sval;
|
|
||||||
if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) {
|
|
||||||
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 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");
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
|
|
||||||
mdb_dbi_close(env, dbi);
|
|
||||||
mdb_env_close(env);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,141 +0,0 @@
|
||||||
/* mtest6.c - memory-mapped database tester/toy */
|
|
||||||
/*
|
|
||||||
* Copyright 2011-2015 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>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Tests for DB splits and merges */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.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()))
|
|
||||||
|
|
||||||
char dkbuf[1024];
|
|
||||||
|
|
||||||
int main(int argc,char * argv[])
|
|
||||||
{
|
|
||||||
int i = 0, j = 0, rc;
|
|
||||||
MDB_env *env;
|
|
||||||
MDB_dbi dbi;
|
|
||||||
MDB_val key, data, sdata;
|
|
||||||
MDB_txn *txn;
|
|
||||||
MDB_stat mst;
|
|
||||||
MDB_cursor *cursor;
|
|
||||||
int count;
|
|
||||||
int *values;
|
|
||||||
long kval;
|
|
||||||
char *sval;
|
|
||||||
|
|
||||||
srand(time(NULL));
|
|
||||||
|
|
||||||
E(mdb_env_create(&env));
|
|
||||||
E(mdb_env_set_mapsize(env, 10485760));
|
|
||||||
E(mdb_env_set_maxdbs(env, 4));
|
|
||||||
E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
|
|
||||||
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
E(mdb_dbi_open(txn, "id6", MDB_CREATE|MDB_INTEGERKEY, &dbi));
|
|
||||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
|
||||||
E(mdb_stat(txn, dbi, &mst));
|
|
||||||
|
|
||||||
sval = calloc(1, mst.ms_psize / 4);
|
|
||||||
key.mv_size = sizeof(long);
|
|
||||||
key.mv_data = &kval;
|
|
||||||
sdata.mv_size = mst.ms_psize / 4 - 30;
|
|
||||||
sdata.mv_data = sval;
|
|
||||||
|
|
||||||
printf("Adding 12 values, should yield 3 splits\n");
|
|
||||||
for (i=0;i<12;i++) {
|
|
||||||
kval = i*5;
|
|
||||||
sprintf(sval, "%08x", kval);
|
|
||||||
data = sdata;
|
|
||||||
(void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE));
|
|
||||||
}
|
|
||||||
printf("Adding 12 more values, should yield 3 splits\n");
|
|
||||||
for (i=0;i<12;i++) {
|
|
||||||
kval = i*5+4;
|
|
||||||
sprintf(sval, "%08x", kval);
|
|
||||||
data = sdata;
|
|
||||||
(void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE));
|
|
||||||
}
|
|
||||||
printf("Adding 12 more values, should yield 3 splits\n");
|
|
||||||
for (i=0;i<12;i++) {
|
|
||||||
kval = i*5+1;
|
|
||||||
sprintf(sval, "%08x", kval);
|
|
||||||
data = sdata;
|
|
||||||
(void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE));
|
|
||||||
}
|
|
||||||
E(mdb_cursor_get(cursor, &key, &data, MDB_FIRST));
|
|
||||||
|
|
||||||
do {
|
|
||||||
printf("key: %p %s, data: %p %.*s\n",
|
|
||||||
key.mv_data, mdb_dkey(&key, dkbuf),
|
|
||||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
|
||||||
} while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0);
|
|
||||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
mdb_txn_commit(txn);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
j=0;
|
|
||||||
|
|
||||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
|
||||||
j++;
|
|
||||||
txn=NULL;
|
|
||||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
|
||||||
sprintf(kval, "%03x", values[i & ~0x0f]);
|
|
||||||
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
|
|
||||||
key.mv_size = sizeof(int);
|
|
||||||
key.mv_data = kval;
|
|
||||||
data.mv_size = sizeof(sval);
|
|
||||||
data.mv_data = sval;
|
|
||||||
if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) {
|
|
||||||
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 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");
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
|
|
||||||
mdb_dbi_close(env, dbi);
|
|
||||||
#endif
|
|
||||||
mdb_env_close(env);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
/* sample-bdb.txt - BerkeleyDB toy/sample
|
|
||||||
*
|
|
||||||
* Do a line-by-line comparison of this and sample-mdb.txt
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Copyright 2012-2015 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 <string.h>
|
|
||||||
#include <db.h>
|
|
||||||
|
|
||||||
int main(int argc,char * argv[])
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
DB_ENV *env;
|
|
||||||
DB *dbi;
|
|
||||||
DBT key, data;
|
|
||||||
DB_TXN *txn;
|
|
||||||
DBC *cursor;
|
|
||||||
char sval[32], kval[32];
|
|
||||||
|
|
||||||
/* Note: Most error checking omitted for simplicity */
|
|
||||||
|
|
||||||
#define FLAGS (DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_INIT_MPOOL|DB_CREATE|DB_THREAD)
|
|
||||||
rc = db_env_create(&env, 0);
|
|
||||||
rc = env->open(env, "./testdb", FLAGS, 0664);
|
|
||||||
rc = db_create(&dbi, env, 0);
|
|
||||||
rc = env->txn_begin(env, NULL, &txn, 0);
|
|
||||||
rc = dbi->open(dbi, txn, "test.bdb", NULL, DB_BTREE, DB_CREATE, 0664);
|
|
||||||
|
|
||||||
memset(&key, 0, sizeof(DBT));
|
|
||||||
memset(&data, 0, sizeof(DBT));
|
|
||||||
key.size = sizeof(int);
|
|
||||||
key.data = sval;
|
|
||||||
data.size = sizeof(sval);
|
|
||||||
data.data = sval;
|
|
||||||
|
|
||||||
sprintf(sval, "%03x %d foo bar", 32, 3141592);
|
|
||||||
rc = dbi->put(dbi, txn, &key, &data, 0);
|
|
||||||
rc = txn->commit(txn, 0);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "txn->commit: (%d) %s\n", rc, db_strerror(rc));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
rc = env->txn_begin(env, NULL, &txn, 0);
|
|
||||||
rc = dbi->cursor(dbi, txn, &cursor, 0);
|
|
||||||
key.flags = DB_DBT_USERMEM;
|
|
||||||
key.data = kval;
|
|
||||||
key.ulen = sizeof(kval);
|
|
||||||
data.flags = DB_DBT_USERMEM;
|
|
||||||
data.data = sval;
|
|
||||||
data.ulen = sizeof(sval);
|
|
||||||
while ((rc = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) {
|
|
||||||
printf("key: %p %.*s, data: %p %.*s\n",
|
|
||||||
key.data, (int) key.size, (char *) key.data,
|
|
||||||
data.data, (int) data.size, (char *) data.data);
|
|
||||||
}
|
|
||||||
rc = cursor->c_close(cursor);
|
|
||||||
rc = txn->abort(txn);
|
|
||||||
leave:
|
|
||||||
rc = dbi->close(dbi, 0);
|
|
||||||
rc = env->close(env, 0);
|
|
||||||
return rc;
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
/* sample-mdb.txt - MDB toy/sample
|
|
||||||
*
|
|
||||||
* Do a line-by-line comparison of this and sample-bdb.txt
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Copyright 2012-2015 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 "lmdb.h"
|
|
||||||
|
|
||||||
int main(int argc,char * argv[])
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
MDB_env *env;
|
|
||||||
MDB_dbi dbi;
|
|
||||||
MDB_val key, data;
|
|
||||||
MDB_txn *txn;
|
|
||||||
MDB_cursor *cursor;
|
|
||||||
char sval[32];
|
|
||||||
|
|
||||||
/* Note: Most error checking omitted for simplicity */
|
|
||||||
|
|
||||||
rc = mdb_env_create(&env);
|
|
||||||
rc = mdb_env_open(env, "./testdb", 0, 0664);
|
|
||||||
rc = mdb_txn_begin(env, NULL, 0, &txn);
|
|
||||||
rc = mdb_dbi_open(txn, NULL, 0, &dbi);
|
|
||||||
|
|
||||||
key.mv_size = sizeof(int);
|
|
||||||
key.mv_data = sval;
|
|
||||||
data.mv_size = sizeof(sval);
|
|
||||||
data.mv_data = sval;
|
|
||||||
|
|
||||||
sprintf(sval, "%03x %d foo bar", 32, 3141592);
|
|
||||||
rc = mdb_put(txn, dbi, &key, &data, 0);
|
|
||||||
rc = mdb_txn_commit(txn);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "mdb_txn_commit: (%d) %s\n", rc, mdb_strerror(rc));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
|
|
||||||
rc = 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);
|
|
||||||
}
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
mdb_txn_abort(txn);
|
|
||||||
leave:
|
|
||||||
mdb_dbi_close(env, dbi);
|
|
||||||
mdb_env_close(env);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
<tagfile>
|
|
||||||
<compound kind="page">
|
|
||||||
<name>mdb_copy_1</name>
|
|
||||||
<title>mdb_copy - environment copy tool</title>
|
|
||||||
<filename>mdb_copy.1</filename>
|
|
||||||
</compound>
|
|
||||||
<compound kind="page">
|
|
||||||
<name>mdb_dump_1</name>
|
|
||||||
<title>mdb_dump - environment export tool</title>
|
|
||||||
<filename>mdb_dump.1</filename>
|
|
||||||
</compound>
|
|
||||||
<compound kind="page">
|
|
||||||
<name>mdb_load_1</name>
|
|
||||||
<title>mdb_load - environment import tool</title>
|
|
||||||
<filename>mdb_load.1</filename>
|
|
||||||
</compound>
|
|
||||||
<compound kind="page">
|
|
||||||
<name>mdb_stat_1</name>
|
|
||||||
<title>mdb_stat - environment status tool</title>
|
|
||||||
<filename>mdb_stat.1</filename>
|
|
||||||
</compound>
|
|
||||||
</tagfile>
|
|
Loading…
Reference in New Issue