Merge pull request #339
54c785d
fixed ARM arch test to prevent breaking on short arch strings (Riccardo Spagni)a4254a4
updated vl32 to current (Riccardo Spagni)e6ab2df
updated in-source lmdb (Riccardo Spagni)ea08c76
open() flag O_DSYNC isn't on BSD, use O_SYNC (Thomas Winget)
This commit is contained in:
commit
dc624849bf
|
@ -46,20 +46,25 @@ function (die msg)
|
|||
endfunction ()
|
||||
|
||||
if (NOT ${ARCH} STREQUAL "")
|
||||
string(SUBSTRING ${ARCH} 0 5 ARM_TEST)
|
||||
string(TOLOWER ${ARM_TEST} ARM_TEST)
|
||||
string(SUBSTRING ${ARCH} 0 3 IS_ARM)
|
||||
string(TOLOWER ${IS_ARM} IS_ARM)
|
||||
|
||||
if (${IS_ARM} STREQUAL "arm")
|
||||
string(SUBSTRING ${ARCH} 0 5 ARM_TEST)
|
||||
string(TOLOWER ${ARM_TEST} ARM_TEST)
|
||||
|
||||
if (${ARM_TEST} STREQUAL "armv6")
|
||||
set(ARM6 1)
|
||||
else()
|
||||
set(ARM6 0)
|
||||
endif()
|
||||
if (${ARM_TEST} STREQUAL "armv6")
|
||||
set(ARM6 1)
|
||||
else()
|
||||
set(ARM6 0)
|
||||
endif()
|
||||
|
||||
if (${ARM_TEST} STREQUAL "armv7")
|
||||
set(ARM7 1)
|
||||
else()
|
||||
set(ARM7 0)
|
||||
endif()
|
||||
if (${ARM_TEST} STREQUAL "armv7")
|
||||
set(ARM7 1)
|
||||
else()
|
||||
set(ARM7 0)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32 OR ARM7 OR ARM6)
|
||||
|
|
|
@ -1,5 +1,33 @@
|
|||
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)
|
||||
|
|
|
@ -26,6 +26,13 @@
|
|||
# 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)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# - 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
|
||||
|
@ -42,18 +43,18 @@ install: $(ILIBS) $(IPROGS) $(IHDRS)
|
|||
for f in $(IDOCS); do cp $$f $(DESTDIR)$(prefix)/man/man1; done
|
||||
|
||||
clean:
|
||||
rm -rf $(PROGS) *.[ao] *.so *~ testdb
|
||||
rm -rf $(PROGS) *.[ao] *.[ls]o *~ testdb
|
||||
|
||||
test: all
|
||||
mkdir testdb
|
||||
rm -rf testdb && mkdir testdb
|
||||
./mtest && ./mdb_stat testdb
|
||||
|
||||
liblmdb.a: mdb.o midl.o
|
||||
ar rs $@ mdb.o midl.o
|
||||
|
||||
liblmdb.so: 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.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
|
||||
|
@ -67,10 +68,16 @@ mtest5: mtest5.o liblmdb.a
|
|||
mtest6: mtest6.o liblmdb.a
|
||||
|
||||
mdb.o: mdb.c lmdb.h midl.h
|
||||
$(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c mdb.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c
|
||||
|
||||
midl.o: midl.c midl.h
|
||||
$(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c midl.c
|
||||
$(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 $@
|
||||
|
|
|
@ -119,7 +119,7 @@
|
|||
*
|
||||
* @author Howard Chu, Symas Corporation.
|
||||
*
|
||||
* @copyright Copyright 2011-2014 Howard Chu, Symas Corp. All rights reserved.
|
||||
* @copyright 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
|
||||
|
@ -184,7 +184,7 @@ typedef int mdb_filehandle_t;
|
|||
/** Library minor version */
|
||||
#define MDB_VERSION_MINOR 9
|
||||
/** Library patch version */
|
||||
#define MDB_VERSION_PATCH 14
|
||||
#define MDB_VERSION_PATCH 15
|
||||
|
||||
/** Combine args a,b,c into a single integer for easy version comparisons */
|
||||
#define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c))
|
||||
|
@ -194,7 +194,7 @@ typedef int mdb_filehandle_t;
|
|||
MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
|
||||
|
||||
/** The release date of this library version */
|
||||
#define MDB_VERSION_DATE "September 20, 2014"
|
||||
#define MDB_VERSION_DATE "June 19, 2015"
|
||||
|
||||
/** A stringifier for the version info */
|
||||
#define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")"
|
||||
|
@ -296,12 +296,12 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel
|
|||
#define MDB_REVERSEKEY 0x02
|
||||
/** use sorted duplicates */
|
||||
#define MDB_DUPSORT 0x04
|
||||
/** numeric keys in native byte order.
|
||||
/** numeric keys in native byte order: either unsigned int or size_t.
|
||||
* The keys must all be of the same size. */
|
||||
#define MDB_INTEGERKEY 0x08
|
||||
/** with #MDB_DUPSORT, sorted dup items have fixed size */
|
||||
#define MDB_DUPFIXED 0x10
|
||||
/** with #MDB_DUPSORT, dups are numeric in native byte order */
|
||||
/** with #MDB_DUPSORT, dups are #MDB_INTEGERKEY-style integers */
|
||||
#define MDB_INTEGERDUP 0x20
|
||||
/** with #MDB_DUPSORT, use reverse string dups */
|
||||
#define MDB_REVERSEDUP 0x40
|
||||
|
@ -516,8 +516,8 @@ int mdb_env_create(MDB_env **env);
|
|||
* and uses fewer mallocs, but loses protection from application bugs
|
||||
* like wild pointer writes and other bad updates into the database.
|
||||
* Incompatible with nested transactions.
|
||||
* Processes with and without MDB_WRITEMAP on the same environment do
|
||||
* not cooperate well.
|
||||
* Do not mix processes with and without MDB_WRITEMAP on the same
|
||||
* environment. This can defeat durability (#mdb_env_sync etc).
|
||||
* <li>#MDB_NOMETASYNC
|
||||
* Flush system buffers to disk only once per transaction, omit the
|
||||
* metadata flush. Defer that until the system flushes files to disk,
|
||||
|
@ -588,8 +588,8 @@ int mdb_env_create(MDB_env **env);
|
|||
* reserved in that case.
|
||||
* This flag may be changed at any time using #mdb_env_set_flags().
|
||||
* </ul>
|
||||
* @param[in] mode The UNIX permissions to set on created files. This parameter
|
||||
* is ignored on Windows.
|
||||
* @param[in] mode The UNIX permissions to set on created files and semaphores.
|
||||
* This parameter is ignored on Windows.
|
||||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
* errors are:
|
||||
* <ul>
|
||||
|
@ -698,7 +698,8 @@ int mdb_env_info(MDB_env *env, MDB_envinfo *stat);
|
|||
* Data is always written to disk when #mdb_txn_commit() is called,
|
||||
* but the operating system may keep it buffered. LMDB always flushes
|
||||
* the OS buffers upon commit as well, unless the environment was
|
||||
* opened with #MDB_NOSYNC or in part #MDB_NOMETASYNC.
|
||||
* opened with #MDB_NOSYNC or in part #MDB_NOMETASYNC. This call is
|
||||
* not valid if the environment was opened with #MDB_RDONLY.
|
||||
* @param[in] env An environment handle returned by #mdb_env_create()
|
||||
* @param[in] force If non-zero, force a synchronous flush. Otherwise
|
||||
* if the environment has the #MDB_NOSYNC flag set the flushes
|
||||
|
@ -706,6 +707,7 @@ int mdb_env_info(MDB_env *env, MDB_envinfo *stat);
|
|||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
* errors are:
|
||||
* <ul>
|
||||
* <li>EACCES - the environment is read-only.
|
||||
* <li>EINVAL - an invalid parameter was specified.
|
||||
* <li>EIO - an error occurred during synchronization.
|
||||
* </ul>
|
||||
|
@ -1019,15 +1021,17 @@ int mdb_txn_renew(MDB_txn *txn);
|
|||
* The database handle may be discarded by calling #mdb_dbi_close().
|
||||
* The old database handle is returned if the database was already open.
|
||||
* The handle may only be closed once.
|
||||
*
|
||||
* The database handle will be private to the current transaction until
|
||||
* the transaction is successfully committed. If the transaction is
|
||||
* aborted the handle will be closed automatically.
|
||||
* After a successful commit the
|
||||
* handle will reside in the shared environment, and may be used
|
||||
* by other transactions. This function must not be called from
|
||||
* multiple concurrent transactions. A transaction that uses this function
|
||||
* must finish (either commit or abort) before any other transaction may
|
||||
* use this function.
|
||||
* After a successful commit the handle will reside in the shared
|
||||
* environment, and may be used by other transactions.
|
||||
*
|
||||
* This function must not be called from multiple concurrent
|
||||
* transactions in the same process. A transaction that uses
|
||||
* this function must finish (either commit or abort) before
|
||||
* any other transaction in the process may use this function.
|
||||
*
|
||||
* To use named databases (with name != NULL), #mdb_env_set_maxdbs()
|
||||
* must be called before opening the environment. Database names
|
||||
|
@ -1048,9 +1052,9 @@ int mdb_txn_renew(MDB_txn *txn);
|
|||
* keys may have multiple data items, stored in sorted order.) By default
|
||||
* keys must be unique and may have only a single data item.
|
||||
* <li>#MDB_INTEGERKEY
|
||||
* Keys are binary integers in native byte order. Setting this option
|
||||
* requires all keys to be the same size, typically sizeof(int)
|
||||
* or sizeof(size_t).
|
||||
* Keys are binary integers in native byte order, either unsigned int
|
||||
* or size_t, and will be sorted as such.
|
||||
* The keys must all be of the same size.
|
||||
* <li>#MDB_DUPFIXED
|
||||
* This flag may only be used in combination with #MDB_DUPSORT. This option
|
||||
* tells the library that the data items for this database are all the same
|
||||
|
@ -1058,8 +1062,8 @@ int mdb_txn_renew(MDB_txn *txn);
|
|||
* all data items are the same size, the #MDB_GET_MULTIPLE and #MDB_NEXT_MULTIPLE
|
||||
* cursor operations may be used to retrieve multiple items at once.
|
||||
* <li>#MDB_INTEGERDUP
|
||||
* This option specifies that duplicate data items are also integers, and
|
||||
* should be sorted as such.
|
||||
* This option specifies that duplicate data items are binary integers,
|
||||
* similar to #MDB_INTEGERKEY keys.
|
||||
* <li>#MDB_REVERSEDUP
|
||||
* This option specifies that duplicate data items should be compared as
|
||||
* strings in reverse order.
|
||||
|
@ -1270,10 +1274,9 @@ int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data);
|
|||
* LMDB does nothing else with this memory, the caller is expected
|
||||
* to modify all of the space requested.
|
||||
* <li>#MDB_APPEND - append the given key/data pair to the end of the
|
||||
* database. No key comparisons are performed. This option allows
|
||||
* fast bulk loading when keys are already known to be in the
|
||||
* correct order. Loading unsorted keys with this flag will cause
|
||||
* data corruption.
|
||||
* database. This option allows fast bulk loading when keys are
|
||||
* already known to be in the correct order. Loading unsorted keys
|
||||
* with this flag will cause a #MDB_KEYEXIST error.
|
||||
* <li>#MDB_APPENDDUP - as above, but for sorted dup data.
|
||||
* </ul>
|
||||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
|
@ -1449,7 +1452,7 @@ int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
|
|||
* <ul>
|
||||
* <li>#MDB_MAP_FULL - the database is full, see #mdb_env_set_mapsize().
|
||||
* <li>#MDB_TXN_FULL - the transaction has too many dirty pages.
|
||||
* <li>EACCES - an attempt was made to modify a read-only database.
|
||||
* <li>EACCES - an attempt was made to write in a read-only transaction.
|
||||
* <li>EINVAL - an invalid parameter was specified.
|
||||
* </ul>
|
||||
*/
|
||||
|
@ -1469,7 +1472,7 @@ int mdb_cursor_put(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
|
|||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
* errors are:
|
||||
* <ul>
|
||||
* <li>EACCES - an attempt was made to modify a read-only database.
|
||||
* <li>EACCES - an attempt was made to write in a read-only transaction.
|
||||
* <li>EINVAL - an invalid parameter was specified.
|
||||
* </ul>
|
||||
*/
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* BerkeleyDB API, but much simplified.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -79,6 +79,14 @@ extern int cacheflush(char *addr, int nbytes, int cache);
|
|||
#define CACHEFLUSH(addr, bytes, cache)
|
||||
#endif
|
||||
|
||||
#if defined(__linux) && !defined(MDB_FDATASYNC_WORKS)
|
||||
/** fdatasync is broken on ext3/ext4fs on older kernels, see
|
||||
* description in #mdb_env_open2 comments. You can safely
|
||||
* define MDB_FDATASYNC_WORKS if this code will only be run
|
||||
* on kernels 3.6 and newer.
|
||||
*/
|
||||
#define BROKEN_FDATASYNC
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
@ -438,12 +446,17 @@ static txnid_t mdb_debug_start;
|
|||
/** The version number for a database's lockfile format. */
|
||||
#define MDB_LOCK_VERSION 1
|
||||
|
||||
/** @brief The max size of a key we can write, or 0 for dynamic max.
|
||||
/** @brief The max size of a key we can write, or 0 for computed max.
|
||||
*
|
||||
* Define this as 0 to compute the max from the page size. 511
|
||||
* is default for backwards compat: liblmdb <= 0.9.10 can break
|
||||
* when modifying a DB with keys/dupsort data bigger than its max.
|
||||
* #MDB_DEVEL sets the default to 0.
|
||||
* This macro should normally be left alone or set to 0.
|
||||
* Note that a database with big keys or dupsort data cannot be
|
||||
* reliably modified by a liblmdb which uses a smaller max.
|
||||
* The default is 511 for backwards compat, or 0 when #MDB_DEVEL.
|
||||
*
|
||||
* Other values are allowed, for backwards compat. However:
|
||||
* A value bigger than the computed max can break if you do not
|
||||
* know what you are doing, and liblmdb <= 0.9.10 can break when
|
||||
* modifying a DB with keys/dupsort data bigger than its max.
|
||||
*
|
||||
* Data items in an #MDB_DUPSORT database are also limited to
|
||||
* this size, since they're actually keys of a sub-DB. Keys and
|
||||
|
@ -580,11 +593,11 @@ typedef struct MDB_rxbody {
|
|||
* started from so we can avoid overwriting any data used in that
|
||||
* particular version.
|
||||
*/
|
||||
txnid_t mrb_txnid;
|
||||
volatile txnid_t mrb_txnid;
|
||||
/** The process ID of the process owning this reader txn. */
|
||||
MDB_PID_T mrb_pid;
|
||||
volatile MDB_PID_T mrb_pid;
|
||||
/** The thread ID of the thread owning this txn. */
|
||||
MDB_THR_T mrb_tid;
|
||||
volatile MDB_THR_T mrb_tid;
|
||||
} MDB_rxbody;
|
||||
|
||||
/** The actual reader record, with cacheline padding. */
|
||||
|
@ -632,12 +645,12 @@ typedef struct MDB_txbody {
|
|||
* This is recorded here only for convenience; the value can always
|
||||
* be determined by reading the main database meta pages.
|
||||
*/
|
||||
txnid_t mtb_txnid;
|
||||
volatile txnid_t mtb_txnid;
|
||||
/** The number of slots that have been used in the reader table.
|
||||
* This always records the maximum count, it is not decremented
|
||||
* when readers release their slots.
|
||||
*/
|
||||
unsigned mtb_numreaders;
|
||||
volatile unsigned mtb_numreaders;
|
||||
} MDB_txbody;
|
||||
|
||||
/** The actual reader table definition. */
|
||||
|
@ -898,7 +911,7 @@ typedef struct MDB_meta {
|
|||
/** Stamp identifying this as an LMDB file. It must be set
|
||||
* to #MDB_MAGIC. */
|
||||
uint32_t mm_magic;
|
||||
/** Version number of this lock file. Must be set to #MDB_DATA_VERSION. */
|
||||
/** Version number of this file. Must be set to #MDB_DATA_VERSION. */
|
||||
uint32_t mm_version;
|
||||
void *mm_address; /**< address for fixed mapping */
|
||||
size_t mm_mapsize; /**< size of mmap region */
|
||||
|
@ -908,7 +921,7 @@ typedef struct MDB_meta {
|
|||
/** Any persistent environment flags. @ref mdb_env */
|
||||
#define mm_flags mm_dbs[0].md_flags
|
||||
pgno_t mm_last_pg; /**< last used page in file */
|
||||
txnid_t mm_txnid; /**< txnid that committed this page */
|
||||
volatile txnid_t mm_txnid; /**< txnid that committed this page */
|
||||
} MDB_meta;
|
||||
|
||||
/** Buffer for a stack-allocated meta page.
|
||||
|
@ -991,7 +1004,7 @@ struct MDB_txn {
|
|||
#ifdef VL32
|
||||
/** List of read-only pages */
|
||||
MDB_ID2L mt_rpages;
|
||||
#endif
|
||||
#endif
|
||||
/** Number of DB records in use. This number only ever increments;
|
||||
* we don't decrement it when individual DB handles are closed.
|
||||
*/
|
||||
|
@ -1103,6 +1116,8 @@ struct MDB_env {
|
|||
#define MDB_ENV_ACTIVE 0x20000000U
|
||||
/** me_txkey is set */
|
||||
#define MDB_ENV_TXKEY 0x10000000U
|
||||
/** fdatasync is unreliable */
|
||||
#define MDB_FSYNCONLY 0x08000000U
|
||||
uint32_t me_flags; /**< @ref mdb_env */
|
||||
unsigned int me_psize; /**< DB page size, inited from me_os_psize */
|
||||
unsigned int me_os_psize; /**< OS page size, from #GET_PAGESIZE */
|
||||
|
@ -1242,6 +1257,13 @@ static void mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi);
|
|||
static MDB_cmp_func mdb_cmp_memn, mdb_cmp_memnr, mdb_cmp_int, mdb_cmp_cint, mdb_cmp_long;
|
||||
/** @endcond */
|
||||
|
||||
/** Compare two items pointing at size_t's of unknown alignment. */
|
||||
#ifdef MISALIGNED_OK
|
||||
# define mdb_cmp_clong mdb_cmp_long
|
||||
#else
|
||||
# define mdb_cmp_clong mdb_cmp_cint
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static SECURITY_DESCRIPTOR mdb_null_sd;
|
||||
static SECURITY_ATTRIBUTES mdb_all_sa;
|
||||
|
@ -1323,7 +1345,7 @@ mdb_strerror(int err)
|
|||
buf[0] = 0;
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, err, 0, ptr, sizeof(buf), pad);
|
||||
NULL, err, 0, ptr, sizeof(buf), (va_list *)pad);
|
||||
return ptr;
|
||||
#else
|
||||
return strerror(err);
|
||||
|
@ -1555,7 +1577,12 @@ mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)
|
|||
int
|
||||
mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)
|
||||
{
|
||||
return txn->mt_dbxs[dbi].md_dcmp(a, b);
|
||||
MDB_cmp_func *dcmp = txn->mt_dbxs[dbi].md_dcmp;
|
||||
#if UINT_MAX < SIZE_MAX
|
||||
if (dcmp == mdb_cmp_int && a->mv_size == sizeof(size_t))
|
||||
dcmp = mdb_cmp_clong;
|
||||
#endif
|
||||
return dcmp(a, b);
|
||||
}
|
||||
|
||||
/** Allocate memory for a page.
|
||||
|
@ -2323,6 +2350,8 @@ int
|
|||
mdb_env_sync(MDB_env *env, int force)
|
||||
{
|
||||
int rc = 0;
|
||||
if (env->me_flags & MDB_RDONLY)
|
||||
return EACCES;
|
||||
if (force || !F_ISSET(env->me_flags, MDB_NOSYNC)) {
|
||||
if (env->me_flags & MDB_WRITEMAP) {
|
||||
int flags = ((env->me_flags & MDB_MAPASYNC) && !force)
|
||||
|
@ -2334,6 +2363,12 @@ mdb_env_sync(MDB_env *env, int force)
|
|||
rc = ErrCode();
|
||||
#endif
|
||||
} else {
|
||||
#ifdef BROKEN_FDATASYNC
|
||||
if (env->me_flags & MDB_FSYNCONLY) {
|
||||
if (fsync(env->me_fd))
|
||||
rc = ErrCode();
|
||||
} else
|
||||
#endif
|
||||
if (MDB_FDATASYNC(env->me_fd))
|
||||
rc = ErrCode();
|
||||
}
|
||||
|
@ -2489,15 +2524,11 @@ mdb_txn_renew0(MDB_txn *txn)
|
|||
MDB_env *env = txn->mt_env;
|
||||
MDB_txninfo *ti = env->me_txns;
|
||||
MDB_meta *meta;
|
||||
unsigned int i, nr;
|
||||
unsigned int i, nr, flags = txn->mt_flags;
|
||||
uint16_t x;
|
||||
int rc, new_notls = 0;
|
||||
|
||||
/* Setup db info */
|
||||
txn->mt_numdbs = env->me_numdbs;
|
||||
txn->mt_dbxs = env->me_dbxs; /* mostly static anyway */
|
||||
|
||||
if (txn->mt_flags & MDB_TXN_RDONLY) {
|
||||
if ((flags &= MDB_TXN_RDONLY) != 0) {
|
||||
if (!ti) {
|
||||
meta = env->me_metas[ mdb_env_pick_meta(env) ];
|
||||
txn->mt_txnid = meta->mm_txnid;
|
||||
|
@ -2543,10 +2574,14 @@ mdb_txn_renew0(MDB_txn *txn)
|
|||
return rc;
|
||||
}
|
||||
}
|
||||
txn->mt_txnid = r->mr_txnid = ti->mti_txnid;
|
||||
do /* LY: Retry on a race, ITS#7970. */
|
||||
r->mr_txnid = ti->mti_txnid;
|
||||
while(r->mr_txnid != ti->mti_txnid);
|
||||
txn->mt_txnid = r->mr_txnid;
|
||||
txn->mt_u.reader = r;
|
||||
meta = env->me_metas[txn->mt_txnid & 1];
|
||||
}
|
||||
txn->mt_dbxs = env->me_dbxs; /* mostly static anyway */
|
||||
} else {
|
||||
if (ti) {
|
||||
LOCK_MUTEX_W(env);
|
||||
|
@ -2562,6 +2597,9 @@ mdb_txn_renew0(MDB_txn *txn)
|
|||
if (txn->mt_txnid == mdb_debug_start)
|
||||
mdb_debug = 1;
|
||||
#endif
|
||||
txn->mt_child = NULL;
|
||||
txn->mt_loose_pgs = NULL;
|
||||
txn->mt_loose_count = 0;
|
||||
txn->mt_dirty_room = MDB_IDL_UM_MAX;
|
||||
txn->mt_u.dirty_list = env->me_dirty_list;
|
||||
txn->mt_u.dirty_list[0].mid = 0;
|
||||
|
@ -2578,6 +2616,10 @@ mdb_txn_renew0(MDB_txn *txn)
|
|||
/* Moved to here to avoid a data race in read TXNs */
|
||||
txn->mt_next_pgno = meta->mm_last_pg+1;
|
||||
|
||||
txn->mt_flags = flags;
|
||||
|
||||
/* Setup db info */
|
||||
txn->mt_numdbs = env->me_numdbs;
|
||||
for (i=2; i<txn->mt_numdbs; i++) {
|
||||
x = env->me_dbflags[i];
|
||||
txn->mt_dbs[i].md_flags = x & PERSISTENT_FLAGS;
|
||||
|
@ -2643,18 +2685,16 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
|
|||
}
|
||||
tsize = sizeof(MDB_ntxn);
|
||||
}
|
||||
size = tsize + env->me_maxdbs * (sizeof(MDB_db)+1);
|
||||
size = tsize;
|
||||
if (!(flags & MDB_RDONLY)) {
|
||||
if (!parent) {
|
||||
txn = env->me_txn0;
|
||||
txn->mt_flags = 0;
|
||||
txn = env->me_txn0; /* just reuse preallocated write txn */
|
||||
goto ok;
|
||||
}
|
||||
/* child txns use own copy of cursors */
|
||||
size += env->me_maxdbs * sizeof(MDB_cursor *);
|
||||
/* child txns use parent's dbiseqs */
|
||||
if (!parent)
|
||||
size += env->me_maxdbs * sizeof(unsigned int);
|
||||
}
|
||||
size += env->me_maxdbs * (sizeof(MDB_db)+1);
|
||||
|
||||
if ((txn = calloc(1, size)) == NULL) {
|
||||
DPRINTF(("calloc: %s", strerror(errno)));
|
||||
|
@ -2807,31 +2847,33 @@ mdb_txn_reset0(MDB_txn *txn, const char *act)
|
|||
txn->mt_numdbs = 0; /* close nothing if called again */
|
||||
txn->mt_dbxs = NULL; /* mark txn as reset */
|
||||
} else {
|
||||
mdb_cursors_close(txn, 0);
|
||||
pgno_t *pghead = env->me_pghead;
|
||||
|
||||
mdb_cursors_close(txn, 0);
|
||||
if (!(env->me_flags & MDB_WRITEMAP)) {
|
||||
mdb_dlist_free(txn);
|
||||
}
|
||||
mdb_midl_free(env->me_pghead);
|
||||
|
||||
if (txn->mt_parent) {
|
||||
if (!txn->mt_parent) {
|
||||
if (mdb_midl_shrink(&txn->mt_free_pgs))
|
||||
env->me_free_pgs = txn->mt_free_pgs;
|
||||
/* me_pgstate: */
|
||||
env->me_pghead = NULL;
|
||||
env->me_pglast = 0;
|
||||
|
||||
env->me_txn = NULL;
|
||||
/* The writer mutex was locked in mdb_txn_begin. */
|
||||
if (env->me_txns)
|
||||
UNLOCK_MUTEX_W(env);
|
||||
} else {
|
||||
txn->mt_parent->mt_child = NULL;
|
||||
env->me_pgstate = ((MDB_ntxn *)txn)->mnt_pgstate;
|
||||
mdb_midl_free(txn->mt_free_pgs);
|
||||
mdb_midl_free(txn->mt_spill_pgs);
|
||||
free(txn->mt_u.dirty_list);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mdb_midl_shrink(&txn->mt_free_pgs))
|
||||
env->me_free_pgs = txn->mt_free_pgs;
|
||||
env->me_pghead = NULL;
|
||||
env->me_pglast = 0;
|
||||
|
||||
env->me_txn = NULL;
|
||||
/* The writer mutex was locked in mdb_txn_begin. */
|
||||
if (env->me_txns)
|
||||
UNLOCK_MUTEX_W(env);
|
||||
mdb_midl_free(pghead);
|
||||
}
|
||||
#ifdef VL32
|
||||
{
|
||||
|
@ -3159,6 +3201,7 @@ mdb_page_flush(MDB_txn *txn, int keep)
|
|||
/* Write up to MDB_COMMIT_PAGES dirty pages at a time. */
|
||||
if (pos!=next_pos || n==MDB_COMMIT_PAGES || wsize+size>MAX_WRITE) {
|
||||
if (n) {
|
||||
retry_write:
|
||||
/* Write previous page(s) */
|
||||
#ifdef MDB_USE_PWRITEV
|
||||
wres = pwritev(env->me_fd, iov, n, wpos);
|
||||
|
@ -3166,8 +3209,11 @@ mdb_page_flush(MDB_txn *txn, int keep)
|
|||
if (n == 1) {
|
||||
wres = pwrite(env->me_fd, iov[0].iov_base, wsize, wpos);
|
||||
} else {
|
||||
retry_seek:
|
||||
if (lseek(env->me_fd, wpos, SEEK_SET) == -1) {
|
||||
rc = ErrCode();
|
||||
if (rc == EINTR)
|
||||
goto retry_seek;
|
||||
DPRINTF(("lseek: %s", strerror(rc)));
|
||||
return rc;
|
||||
}
|
||||
|
@ -3177,6 +3223,8 @@ mdb_page_flush(MDB_txn *txn, int keep)
|
|||
if (wres != wsize) {
|
||||
if (wres < 0) {
|
||||
rc = ErrCode();
|
||||
if (rc == EINTR)
|
||||
goto retry_write;
|
||||
DPRINTF(("Write error: %s", strerror(rc)));
|
||||
} else {
|
||||
rc = EIO; /* TODO: Use which error code? */
|
||||
|
@ -3546,7 +3594,8 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
|
|||
int len;
|
||||
#define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \
|
||||
len = pwrite(fd, ptr, size, pos); \
|
||||
rc = (len >= 0); } while(0)
|
||||
if (len == -1 && ErrCode() == EINTR) continue; \
|
||||
rc = (len >= 0); break; } while(1)
|
||||
#endif
|
||||
|
||||
DPUTS("writing new meta page");
|
||||
|
@ -3651,6 +3700,7 @@ mdb_env_write_meta(MDB_txn *txn)
|
|||
/* Write to the SYNC fd */
|
||||
mfd = env->me_flags & (MDB_NOSYNC|MDB_NOMETASYNC) ?
|
||||
env->me_fd : env->me_mfd;
|
||||
retry_write:
|
||||
#ifdef _WIN32
|
||||
{
|
||||
memset(&ov, 0, sizeof(ov));
|
||||
|
@ -3663,6 +3713,8 @@ mdb_env_write_meta(MDB_txn *txn)
|
|||
#endif
|
||||
if (rc != len) {
|
||||
rc = rc < 0 ? ErrCode() : EIO;
|
||||
if (rc == EINTR)
|
||||
goto retry_write;
|
||||
DPUTS("write failed, disk error?");
|
||||
/* On a failure, the pagecache still contains the new data.
|
||||
* Write some old data back, to prevent it from being used.
|
||||
|
@ -3894,6 +3946,32 @@ mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers)
|
|||
return MDB_SUCCESS;
|
||||
}
|
||||
|
||||
static int ESECT
|
||||
mdb_fsize(HANDLE fd, size_t *size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER fsize;
|
||||
|
||||
if (!GetFileSizeEx(fd, &fsize))
|
||||
return ErrCode();
|
||||
|
||||
*size = fsize.QuadPart;
|
||||
#else
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st))
|
||||
return ErrCode();
|
||||
|
||||
*size = st.st_size;
|
||||
#endif
|
||||
return MDB_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef BROKEN_FDATASYNC
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
|
||||
/** Further setup required for opening an LMDB environment
|
||||
*/
|
||||
static int ESECT
|
||||
|
@ -3911,6 +3989,53 @@ mdb_env_open2(MDB_env *env)
|
|||
else
|
||||
env->me_pidquery = PROCESS_QUERY_INFORMATION;
|
||||
#endif /* _WIN32 */
|
||||
#ifdef BROKEN_FDATASYNC
|
||||
/* ext3/ext4 fdatasync is broken on some older Linux kernels.
|
||||
* https://lkml.org/lkml/2012/9/3/83
|
||||
* Kernels after 3.6-rc6 are known good.
|
||||
* https://lkml.org/lkml/2012/9/10/556
|
||||
* See if the DB is on ext3/ext4, then check for new enough kernel
|
||||
* Kernels 2.6.32.60, 2.6.34.15, 3.2.30, and 3.5.4 are also known
|
||||
* to be patched.
|
||||
*/
|
||||
{
|
||||
struct statfs st;
|
||||
fstatfs(env->me_fd, &st);
|
||||
while (st.f_type == 0xEF53) {
|
||||
struct utsname uts;
|
||||
int i;
|
||||
uname(&uts);
|
||||
if (uts.release[0] < '3') {
|
||||
if (!strncmp(uts.release, "2.6.32.", 7)) {
|
||||
i = atoi(uts.release+7);
|
||||
if (i >= 60)
|
||||
break; /* 2.6.32.60 and newer is OK */
|
||||
} else if (!strncmp(uts.release, "2.6.34.", 7)) {
|
||||
i = atoi(uts.release+7);
|
||||
if (i >= 15)
|
||||
break; /* 2.6.34.15 and newer is OK */
|
||||
}
|
||||
} else if (uts.release[0] == '3') {
|
||||
i = atoi(uts.release+2);
|
||||
if (i > 5)
|
||||
break; /* 3.6 and newer is OK */
|
||||
if (i == 5) {
|
||||
i = atoi(uts.release+4);
|
||||
if (i >= 4)
|
||||
break; /* 3.5.4 and newer is OK */
|
||||
} else if (i == 2) {
|
||||
i = atoi(uts.release+4);
|
||||
if (i >= 30)
|
||||
break; /* 3.2.30 and newer is OK */
|
||||
}
|
||||
} else { /* 4.x and newer is OK */
|
||||
break;
|
||||
}
|
||||
env->me_flags |= MDB_FSYNCONLY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&meta, 0, sizeof(meta));
|
||||
|
||||
|
@ -4042,7 +4167,7 @@ PIMAGE_TLS_CALLBACK mdb_tls_cbp __attribute__((section (".CRT$XLB"))) = mdb_tls_
|
|||
extern const PIMAGE_TLS_CALLBACK mdb_tls_cbp;
|
||||
const PIMAGE_TLS_CALLBACK mdb_tls_cbp = mdb_tls_callback;
|
||||
#pragma const_seg()
|
||||
#else /* WIN32 */
|
||||
#else /* _WIN32 */
|
||||
#pragma comment(linker, "/INCLUDE:__tls_used")
|
||||
#pragma comment(linker, "/INCLUDE:_mdb_tls_cbp")
|
||||
#pragma data_seg(".CRT$XLB")
|
||||
|
@ -4092,7 +4217,7 @@ mdb_env_share_locks(MDB_env *env, int *excl)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/** Try to get exlusive lock, otherwise shared.
|
||||
/** Try to get exclusive lock, otherwise shared.
|
||||
* Maintain *excl = -1: no/unknown lock, 0: shared, 1: exclusive.
|
||||
*/
|
||||
static int ESECT
|
||||
|
@ -4233,7 +4358,6 @@ mdb_hash_enc(MDB_val *val, char *encbuf)
|
|||
* @param[in] env The LMDB environment.
|
||||
* @param[in] lpath The pathname of the file used for the lock region.
|
||||
* @param[in] mode The Unix permissions for the file, if we create it.
|
||||
* @param[out] excl Resulting file lock type: -1 none, 0 shared, 1 exclusive
|
||||
* @param[in,out] excl In -1, out lock type: -1 none, 0 shared, 1 exclusive
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
|
@ -4599,7 +4723,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
|
|||
if (!(flags & MDB_RDONLY)) {
|
||||
MDB_txn *txn;
|
||||
int tsize = sizeof(MDB_txn), size = tsize + env->me_maxdbs *
|
||||
(sizeof(MDB_db)+sizeof(MDB_cursor)+sizeof(unsigned int)+1);
|
||||
(sizeof(MDB_db)+sizeof(MDB_cursor *)+sizeof(unsigned int)+1);
|
||||
txn = calloc(1, size);
|
||||
if (txn) {
|
||||
txn->mt_dbs = (MDB_db *)((char *)txn + tsize);
|
||||
|
@ -4607,6 +4731,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
|
|||
txn->mt_dbiseqs = (unsigned int *)(txn->mt_cursors + env->me_maxdbs);
|
||||
txn->mt_dbflags = (unsigned char *)(txn->mt_dbiseqs + env->me_maxdbs);
|
||||
txn->mt_env = env;
|
||||
txn->mt_dbxs = env->me_dbxs;
|
||||
#ifdef VL32
|
||||
txn->mt_rpages = calloc(MDB_IDL_UM_SIZE, sizeof(MDB_ID2));
|
||||
if (!txn->mt_rpages) {
|
||||
|
@ -4639,13 +4764,15 @@ mdb_env_close0(MDB_env *env, int excl)
|
|||
return;
|
||||
|
||||
/* Doing this here since me_dbxs may not exist during mdb_env_close */
|
||||
for (i = env->me_maxdbs; --i > MAIN_DBI; )
|
||||
free(env->me_dbxs[i].md_name.mv_data);
|
||||
if (env->me_dbxs) {
|
||||
for (i = env->me_maxdbs; --i > MAIN_DBI; )
|
||||
free(env->me_dbxs[i].md_name.mv_data);
|
||||
free(env->me_dbxs);
|
||||
}
|
||||
|
||||
free(env->me_pbuf);
|
||||
free(env->me_dbiseqs);
|
||||
free(env->me_dbflags);
|
||||
free(env->me_dbxs);
|
||||
free(env->me_path);
|
||||
free(env->me_dirty_list);
|
||||
free(env->me_txn0);
|
||||
|
@ -4752,7 +4879,11 @@ mdb_cmp_long(const MDB_val *a, const MDB_val *b)
|
|||
*(size_t *)a->mv_data > *(size_t *)b->mv_data;
|
||||
}
|
||||
|
||||
/** Compare two items pointing at aligned unsigned int's */
|
||||
/** Compare two items pointing at aligned unsigned int's.
|
||||
*
|
||||
* This is also set as #MDB_INTEGERDUP|#MDB_DUPFIXED's #MDB_dbx.%md_dcmp,
|
||||
* but #mdb_cmp_clong() is called instead if the data type is size_t.
|
||||
*/
|
||||
static int
|
||||
mdb_cmp_int(const MDB_val *a, const MDB_val *b)
|
||||
{
|
||||
|
@ -4790,13 +4921,6 @@ mdb_cmp_cint(const MDB_val *a, const MDB_val *b)
|
|||
#endif
|
||||
}
|
||||
|
||||
/** Compare two items pointing at size_t's of unknown alignment. */
|
||||
#ifdef MISALIGNED_OK
|
||||
# define mdb_cmp_clong mdb_cmp_long
|
||||
#else
|
||||
# define mdb_cmp_clong mdb_cmp_cint
|
||||
#endif
|
||||
|
||||
/** Compare two items lexically */
|
||||
static int
|
||||
mdb_cmp_memn(const MDB_val *a, const MDB_val *b)
|
||||
|
@ -5432,6 +5556,7 @@ mdb_cursor_sibling(MDB_cursor *mc, int move_right)
|
|||
#ifdef VL32
|
||||
op = mc->mc_pg[mc->mc_top];
|
||||
#endif
|
||||
|
||||
mdb_cursor_pop(mc);
|
||||
DPRINTF(("parent page is page %"Z"u, index %u",
|
||||
mc->mc_pg[mc->mc_top]->mp_pgno, mc->mc_ki[mc->mc_top]));
|
||||
|
@ -5590,11 +5715,11 @@ mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
|
|||
}
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
|
||||
if (op == MDB_PREV_DUP)
|
||||
return MDB_NOTFOUND;
|
||||
}
|
||||
} else {
|
||||
mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
|
||||
if (op == MDB_PREV_DUP)
|
||||
return MDB_NOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5806,15 +5931,21 @@ set1:
|
|||
return rc;
|
||||
}
|
||||
} else if (op == MDB_GET_BOTH || op == MDB_GET_BOTH_RANGE) {
|
||||
MDB_val d2;
|
||||
if ((rc = mdb_node_read(mc->mc_txn, leaf, &d2)) != MDB_SUCCESS)
|
||||
MDB_val olddata;
|
||||
MDB_cmp_func *dcmp;
|
||||
if ((rc = mdb_node_read(mc->mc_txn, leaf, &olddata)) != MDB_SUCCESS)
|
||||
return rc;
|
||||
rc = mc->mc_dbx->md_dcmp(data, &d2);
|
||||
dcmp = mc->mc_dbx->md_dcmp;
|
||||
#if UINT_MAX < SIZE_MAX
|
||||
if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
|
||||
dcmp = mdb_cmp_clong;
|
||||
#endif
|
||||
rc = dcmp(data, &olddata);
|
||||
if (rc) {
|
||||
if (op == MDB_GET_BOTH || rc > 0)
|
||||
return MDB_NOTFOUND;
|
||||
rc = 0;
|
||||
*data = d2;
|
||||
*data = olddata;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -6324,16 +6455,17 @@ more:
|
|||
|
||||
/* Was a single item before, must convert now */
|
||||
if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
||||
MDB_cmp_func *dcmp;
|
||||
/* Just overwrite the current item */
|
||||
if (flags == MDB_CURRENT)
|
||||
goto current;
|
||||
|
||||
dcmp = mc->mc_dbx->md_dcmp;
|
||||
#if UINT_MAX < SIZE_MAX
|
||||
if (mc->mc_dbx->md_dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
|
||||
mc->mc_dbx->md_dcmp = mdb_cmp_clong;
|
||||
if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
|
||||
dcmp = mdb_cmp_clong;
|
||||
#endif
|
||||
/* does data match? */
|
||||
if (!mc->mc_dbx->md_dcmp(data, &olddata)) {
|
||||
if (!dcmp(data, &olddata)) {
|
||||
if (flags & MDB_NODUPDATA)
|
||||
return MDB_KEYEXIST;
|
||||
/* overwrite it */
|
||||
|
@ -7153,6 +7285,7 @@ mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
|
|||
mc->mc_snum = 0;
|
||||
mc->mc_top = 0;
|
||||
mc->mc_pg[0] = 0;
|
||||
mc->mc_ki[0] = 0;
|
||||
mc->mc_flags = 0;
|
||||
if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
|
||||
mdb_tassert(txn, mx != NULL);
|
||||
|
@ -7526,7 +7659,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
|||
cdst->mc_ki[cdst->mc_top] = 0;
|
||||
rc = mdb_update_key(cdst, &nullkey);
|
||||
cdst->mc_ki[cdst->mc_top] = ix;
|
||||
mdb_cassert(csrc, rc == MDB_SUCCESS);
|
||||
mdb_cassert(cdst, rc == MDB_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7782,12 +7915,12 @@ mdb_rebalance(MDB_cursor *mc)
|
|||
m3 = m2;
|
||||
if (m3 == mc || m3->mc_snum < mc->mc_snum) continue;
|
||||
if (m3->mc_pg[0] == mp) {
|
||||
m3->mc_snum--;
|
||||
m3->mc_top--;
|
||||
for (i=0; i<m3->mc_snum; i++) {
|
||||
m3->mc_pg[i] = m3->mc_pg[i+1];
|
||||
m3->mc_ki[i] = m3->mc_ki[i+1];
|
||||
}
|
||||
m3->mc_snum--;
|
||||
m3->mc_top--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7855,9 +7988,23 @@ mdb_rebalance(MDB_cursor *mc)
|
|||
if (mc->mc_ki[ptop] == 0) {
|
||||
rc = mdb_page_merge(&mn, mc);
|
||||
} else {
|
||||
MDB_cursor dummy;
|
||||
oldki += NUMKEYS(mn.mc_pg[mn.mc_top]);
|
||||
mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1;
|
||||
/* We want mdb_rebalance to find mn when doing fixups */
|
||||
if (mc->mc_flags & C_SUB) {
|
||||
dummy.mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi];
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = &dummy;
|
||||
dummy.mc_xcursor = (MDB_xcursor *)&mn;
|
||||
} else {
|
||||
mn.mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi];
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = &mn;
|
||||
}
|
||||
rc = mdb_page_merge(mc, &mn);
|
||||
if (mc->mc_flags & C_SUB)
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = dummy.mc_next;
|
||||
else
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = mn.mc_next;
|
||||
mdb_cursor_copy(&mn, mc);
|
||||
}
|
||||
mc->mc_flags &= ~C_EOF;
|
||||
|
@ -7884,6 +8031,13 @@ mdb_cursor_del0(MDB_cursor *mc)
|
|||
MDB_cursor *m2, *m3;
|
||||
MDB_dbi dbi = mc->mc_dbi;
|
||||
|
||||
/* DB is totally empty now, just bail out.
|
||||
* Other cursors adjustments were already done
|
||||
* by mdb_rebalance and aren't needed here.
|
||||
*/
|
||||
if (!mc->mc_snum)
|
||||
return rc;
|
||||
|
||||
mp = mc->mc_pg[mc->mc_top];
|
||||
nkeys = NUMKEYS(mp);
|
||||
|
||||
|
@ -8751,8 +8905,12 @@ mdb_env_copyfd1(MDB_env *env, HANDLE fd)
|
|||
/* Set metapage 1 */
|
||||
mm->mm_last_pg = txn->mt_next_pgno - freecount - 1;
|
||||
mm->mm_dbs[1] = txn->mt_dbs[1];
|
||||
mm->mm_dbs[1].md_root = mm->mm_last_pg;
|
||||
mm->mm_txnid = 1;
|
||||
if (mm->mm_last_pg > 1) {
|
||||
mm->mm_dbs[1].md_root = mm->mm_last_pg;
|
||||
mm->mm_txnid = 1;
|
||||
} else {
|
||||
mm->mm_dbs[1].md_root = P_INVALID;
|
||||
}
|
||||
}
|
||||
my.mc_wlen[0] = env->me_psize * 2;
|
||||
my.mc_txn = txn;
|
||||
|
@ -8847,21 +9005,13 @@ mdb_env_copyfd0(MDB_env *env, HANDLE fd)
|
|||
goto leave;
|
||||
|
||||
w2 = txn->mt_next_pgno * env->me_psize;
|
||||
#ifdef WIN32
|
||||
{
|
||||
LARGE_INTEGER fsize;
|
||||
GetFileSizeEx(env->me_fd, &fsize);
|
||||
if (w2 > fsize.QuadPart)
|
||||
w2 = fsize.QuadPart;
|
||||
size_t fsize = 0;
|
||||
if ((rc = mdb_fsize(env->me_fd, &fsize)))
|
||||
goto leave;
|
||||
if (w2 > fsize)
|
||||
w2 = fsize;
|
||||
}
|
||||
#else
|
||||
{
|
||||
struct stat st;
|
||||
fstat(env->me_fd, &st);
|
||||
if (w2 > (size_t)st.st_size)
|
||||
w2 = st.st_size;
|
||||
}
|
||||
#endif
|
||||
wsize = w2 - wsize;
|
||||
while (wsize > 0) {
|
||||
if (wsize > MAX_WRITE)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_COPY 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2012-2014 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_copy \- LMDB environment copy tool
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mdb_copy.c - memory-mapped database backup tool */
|
||||
/*
|
||||
* Copyright 2012 Howard Chu, Symas Corp.
|
||||
* Copyright 2012-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -64,7 +64,7 @@ int main(int argc,char * argv[])
|
|||
act = "opening environment";
|
||||
rc = mdb_env_create(&env);
|
||||
if (rc == MDB_SUCCESS) {
|
||||
rc = mdb_env_open(env, argv[1], flags, 0664);
|
||||
rc = mdb_env_open(env, argv[1], flags, 0600);
|
||||
}
|
||||
if (rc == MDB_SUCCESS) {
|
||||
act = "copying";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_DUMP 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2014 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_dump \- LMDB environment export tool
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mdb_dump.c - memory-mapped database dump tool */
|
||||
/*
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_LOAD 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2014 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_load \- LMDB environment import tool
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mdb_load.c - memory-mapped database load tool */
|
||||
/*
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -176,7 +176,7 @@ static int unhex(unsigned char *c2)
|
|||
static int readline(MDB_val *out, MDB_val *buf)
|
||||
{
|
||||
unsigned char *c1, *c2, *end;
|
||||
size_t len;
|
||||
size_t len, l2;
|
||||
int c;
|
||||
|
||||
if (!(mode & NOHDR)) {
|
||||
|
@ -206,6 +206,7 @@ badend:
|
|||
|
||||
c1 = buf->mv_data;
|
||||
len = strlen((char *)c1);
|
||||
l2 = len;
|
||||
|
||||
/* Is buffer too short? */
|
||||
while (c1[len-1] != '\n') {
|
||||
|
@ -217,17 +218,18 @@ badend:
|
|||
return EOF;
|
||||
}
|
||||
c1 = buf->mv_data;
|
||||
c1 += buf->mv_size;
|
||||
if (fgets((char *)c1, buf->mv_size, stdin) == NULL) {
|
||||
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 = strlen((char *)c1);
|
||||
len = l2;
|
||||
c1[--len] = '\0';
|
||||
end = c1 + len;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_STAT 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2012-2014 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_stat \- LMDB environment status tool
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mdb_stat.c - memory-mapped database status tool */
|
||||
/*
|
||||
* Copyright 2011-2013 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2000-2014 The OpenLDAP Foundation.
|
||||
* Copyright 2000-2015 The OpenLDAP Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2000-2014 The OpenLDAP Foundation.
|
||||
* Copyright 2000-2015 The OpenLDAP Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -58,7 +58,7 @@ typedef MDB_ID *MDB_IDL;
|
|||
#ifdef VL32
|
||||
#define MDB_IDL_LOGN 10 /* DB_SIZE is 2^10, UM_SIZE is 2^11 */
|
||||
#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
|
||||
#define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN)
|
||||
#define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -45,19 +45,22 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
E(mdb_env_set_maxreaders(env, 1));
|
||||
E(mdb_env_set_mapsize(env, 10485760));
|
||||
E(mdb_env_open(env, "./testdb", 0 /* MDB_FIXEDMAP |MDB_NOSYNC*/, 0664));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_open(txn, NULL, 0, &dbi));
|
||||
E(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;
|
||||
|
||||
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);
|
||||
|
@ -68,7 +71,7 @@ int main(int argc,char * argv[])
|
|||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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",
|
||||
|
@ -97,7 +100,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -128,6 +131,7 @@ int main(int argc,char * argv[])
|
|||
(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");
|
||||
|
@ -164,9 +168,9 @@ int main(int argc,char * argv[])
|
|||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest2.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -47,20 +47,22 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
E(mdb_env_set_maxreaders(env, 1));
|
||||
E(mdb_env_set_mapsize(env, 10485760));
|
||||
E(mdb_env_set_maxdbs(env, 4));
|
||||
E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_open(txn, "id1", MDB_CREATE, &dbi));
|
||||
E(mdb_dbi_open(txn, "id1", MDB_CREATE, &dbi));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = sval;
|
||||
data.mv_size = sizeof(sval);
|
||||
data.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++;
|
||||
}
|
||||
|
@ -68,7 +70,7 @@ int main(int argc,char * argv[])
|
|||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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",
|
||||
|
@ -97,7 +99,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -114,10 +116,9 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
mdb_env_close(env);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest3.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -53,8 +53,9 @@ int main(int argc,char * argv[])
|
|||
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_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
|
||||
E(mdb_dbi_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = kval;
|
||||
|
@ -73,7 +74,7 @@ int main(int argc,char * argv[])
|
|||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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",
|
||||
|
@ -107,7 +108,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -124,10 +125,9 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
mdb_env_close(env);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest4.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -51,8 +51,9 @@ int main(int argc,char * argv[])
|
|||
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_open(txn, "id4", MDB_CREATE|MDB_DUPSORT|MDB_DUPFIXED, &dbi));
|
||||
E(mdb_dbi_open(txn, "id4", MDB_CREATE|MDB_DUPSORT|MDB_DUPFIXED, &dbi));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = kval;
|
||||
|
@ -72,7 +73,7 @@ int main(int argc,char * argv[])
|
|||
|
||||
/* there should be one full page of dups now.
|
||||
*/
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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",
|
||||
|
@ -142,7 +143,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -159,10 +160,9 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
mdb_env_close(env);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest5.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -53,8 +53,9 @@ int main(int argc,char * argv[])
|
|||
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_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
|
||||
E(mdb_dbi_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
|
@ -75,7 +76,7 @@ int main(int argc,char * argv[])
|
|||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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",
|
||||
|
@ -109,7 +110,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -126,10 +127,9 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
mdb_env_close(env);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest6.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -31,7 +31,7 @@ int main(int argc,char * argv[])
|
|||
int i = 0, j = 0, rc;
|
||||
MDB_env *env;
|
||||
MDB_dbi dbi;
|
||||
MDB_val key, data;
|
||||
MDB_val key, data, sdata;
|
||||
MDB_txn *txn;
|
||||
MDB_stat mst;
|
||||
MDB_cursor *cursor;
|
||||
|
@ -46,33 +46,37 @@ int main(int argc,char * argv[])
|
|||
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_open(txn, "id6", MDB_CREATE|MDB_INTEGERKEY, &dbi));
|
||||
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;
|
||||
data.mv_size = mst.ms_psize / 4 - 30;
|
||||
data.mv_data = sval;
|
||||
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));
|
||||
|
@ -110,7 +114,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -127,9 +131,9 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
#endif
|
||||
mdb_env_close(env);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Do a line-by-line comparison of this and sample-mdb.txt
|
||||
*/
|
||||
/*
|
||||
* Copyright 2012 Howard Chu, Symas Corp.
|
||||
* Copyright 2012-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Do a line-by-line comparison of this and sample-bdb.txt
|
||||
*/
|
||||
/*
|
||||
* Copyright 2012 Howard Chu, Symas Corp.
|
||||
* Copyright 2012-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -32,7 +32,7 @@ int main(int argc,char * argv[])
|
|||
rc = mdb_env_create(&env);
|
||||
rc = mdb_env_open(env, "./testdb", 0, 0664);
|
||||
rc = mdb_txn_begin(env, NULL, 0, &txn);
|
||||
rc = mdb_open(txn, NULL, 0, &dbi);
|
||||
rc = mdb_dbi_open(txn, NULL, 0, &dbi);
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = sval;
|
||||
|
@ -56,7 +56,7 @@ int main(int argc,char * argv[])
|
|||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
leave:
|
||||
mdb_close(env, dbi);
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,31 @@
|
|||
LMDB 0.9 Change Log
|
||||
|
||||
LMDB 0.9.15 Release Engineering
|
||||
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)
|
||||
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)
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
# 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()
|
||||
|
||||
set (lmdb_sources
|
||||
mdb.c
|
||||
midl.c)
|
||||
|
|
|
@ -184,7 +184,7 @@ typedef int mdb_filehandle_t;
|
|||
/** Library minor version */
|
||||
#define MDB_VERSION_MINOR 9
|
||||
/** Library patch version */
|
||||
#define MDB_VERSION_PATCH 14
|
||||
#define MDB_VERSION_PATCH 15
|
||||
|
||||
/** Combine args a,b,c into a single integer for easy version comparisons */
|
||||
#define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c))
|
||||
|
@ -194,7 +194,7 @@ typedef int mdb_filehandle_t;
|
|||
MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
|
||||
|
||||
/** The release date of this library version */
|
||||
#define MDB_VERSION_DATE "September 20, 2014"
|
||||
#define MDB_VERSION_DATE "June 19, 2015"
|
||||
|
||||
/** A stringifier for the version info */
|
||||
#define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")"
|
||||
|
@ -296,12 +296,12 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel
|
|||
#define MDB_REVERSEKEY 0x02
|
||||
/** use sorted duplicates */
|
||||
#define MDB_DUPSORT 0x04
|
||||
/** numeric keys in native byte order.
|
||||
/** numeric keys in native byte order: either unsigned int or size_t.
|
||||
* The keys must all be of the same size. */
|
||||
#define MDB_INTEGERKEY 0x08
|
||||
/** with #MDB_DUPSORT, sorted dup items have fixed size */
|
||||
#define MDB_DUPFIXED 0x10
|
||||
/** with #MDB_DUPSORT, dups are numeric in native byte order */
|
||||
/** with #MDB_DUPSORT, dups are #MDB_INTEGERKEY-style integers */
|
||||
#define MDB_INTEGERDUP 0x20
|
||||
/** with #MDB_DUPSORT, use reverse string dups */
|
||||
#define MDB_REVERSEDUP 0x40
|
||||
|
@ -588,8 +588,8 @@ int mdb_env_create(MDB_env **env);
|
|||
* reserved in that case.
|
||||
* This flag may be changed at any time using #mdb_env_set_flags().
|
||||
* </ul>
|
||||
* @param[in] mode The UNIX permissions to set on created files. This parameter
|
||||
* is ignored on Windows.
|
||||
* @param[in] mode The UNIX permissions to set on created files and semaphores.
|
||||
* This parameter is ignored on Windows.
|
||||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
* errors are:
|
||||
* <ul>
|
||||
|
@ -1021,14 +1021,16 @@ int mdb_txn_renew(MDB_txn *txn);
|
|||
* The database handle may be discarded by calling #mdb_dbi_close().
|
||||
* The old database handle is returned if the database was already open.
|
||||
* The handle may only be closed once.
|
||||
*
|
||||
* The database handle will be private to the current transaction until
|
||||
* the transaction is successfully committed. If the transaction is
|
||||
* aborted the handle will be closed automatically.
|
||||
* After a successful commit the
|
||||
* handle will reside in the shared environment, and may be used
|
||||
* by other transactions. This function must not be called from
|
||||
* multiple concurrent transactions in the same process. A transaction
|
||||
* that uses this function must finish (either commit or abort) before
|
||||
* After a successful commit the handle will reside in the shared
|
||||
* environment, and may be used by other transactions.
|
||||
*
|
||||
* This function must not be called from multiple concurrent
|
||||
* transactions in the same process. A transaction that uses
|
||||
* this function must finish (either commit or abort) before
|
||||
* any other transaction in the process may use this function.
|
||||
*
|
||||
* To use named databases (with name != NULL), #mdb_env_set_maxdbs()
|
||||
|
@ -1050,9 +1052,9 @@ int mdb_txn_renew(MDB_txn *txn);
|
|||
* keys may have multiple data items, stored in sorted order.) By default
|
||||
* keys must be unique and may have only a single data item.
|
||||
* <li>#MDB_INTEGERKEY
|
||||
* Keys are binary integers in native byte order. Setting this option
|
||||
* requires all keys to be the same size, typically sizeof(int)
|
||||
* or sizeof(size_t).
|
||||
* Keys are binary integers in native byte order, either unsigned int
|
||||
* or size_t, and will be sorted as such.
|
||||
* The keys must all be of the same size.
|
||||
* <li>#MDB_DUPFIXED
|
||||
* This flag may only be used in combination with #MDB_DUPSORT. This option
|
||||
* tells the library that the data items for this database are all the same
|
||||
|
@ -1060,8 +1062,8 @@ int mdb_txn_renew(MDB_txn *txn);
|
|||
* all data items are the same size, the #MDB_GET_MULTIPLE and #MDB_NEXT_MULTIPLE
|
||||
* cursor operations may be used to retrieve multiple items at once.
|
||||
* <li>#MDB_INTEGERDUP
|
||||
* This option specifies that duplicate data items are also integers, and
|
||||
* should be sorted as such.
|
||||
* This option specifies that duplicate data items are binary integers,
|
||||
* similar to #MDB_INTEGERKEY keys.
|
||||
* <li>#MDB_REVERSEDUP
|
||||
* This option specifies that duplicate data items should be compared as
|
||||
* strings in reverse order.
|
||||
|
@ -1450,7 +1452,7 @@ int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
|
|||
* <ul>
|
||||
* <li>#MDB_MAP_FULL - the database is full, see #mdb_env_set_mapsize().
|
||||
* <li>#MDB_TXN_FULL - the transaction has too many dirty pages.
|
||||
* <li>EACCES - an attempt was made to modify a read-only database.
|
||||
* <li>EACCES - an attempt was made to write in a read-only transaction.
|
||||
* <li>EINVAL - an invalid parameter was specified.
|
||||
* </ul>
|
||||
*/
|
||||
|
@ -1470,7 +1472,7 @@ int mdb_cursor_put(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
|
|||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
* errors are:
|
||||
* <ul>
|
||||
* <li>EACCES - an attempt was made to modify a read-only database.
|
||||
* <li>EACCES - an attempt was made to write in a read-only transaction.
|
||||
* <li>EINVAL - an invalid parameter was specified.
|
||||
* </ul>
|
||||
*/
|
||||
|
|
|
@ -446,12 +446,17 @@ static txnid_t mdb_debug_start;
|
|||
/** The version number for a database's lockfile format. */
|
||||
#define MDB_LOCK_VERSION 1
|
||||
|
||||
/** @brief The max size of a key we can write, or 0 for dynamic max.
|
||||
/** @brief The max size of a key we can write, or 0 for computed max.
|
||||
*
|
||||
* Define this as 0 to compute the max from the page size. 511
|
||||
* is default for backwards compat: liblmdb <= 0.9.10 can break
|
||||
* when modifying a DB with keys/dupsort data bigger than its max.
|
||||
* #MDB_DEVEL sets the default to 0.
|
||||
* This macro should normally be left alone or set to 0.
|
||||
* Note that a database with big keys or dupsort data cannot be
|
||||
* reliably modified by a liblmdb which uses a smaller max.
|
||||
* The default is 511 for backwards compat, or 0 when #MDB_DEVEL.
|
||||
*
|
||||
* Other values are allowed, for backwards compat. However:
|
||||
* A value bigger than the computed max can break if you do not
|
||||
* know what you are doing, and liblmdb <= 0.9.10 can break when
|
||||
* modifying a DB with keys/dupsort data bigger than its max.
|
||||
*
|
||||
* Data items in an #MDB_DUPSORT database are also limited to
|
||||
* this size, since they're actually keys of a sub-DB. Keys and
|
||||
|
@ -1245,6 +1250,13 @@ static void mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi);
|
|||
static MDB_cmp_func mdb_cmp_memn, mdb_cmp_memnr, mdb_cmp_int, mdb_cmp_cint, mdb_cmp_long;
|
||||
/** @endcond */
|
||||
|
||||
/** Compare two items pointing at size_t's of unknown alignment. */
|
||||
#ifdef MISALIGNED_OK
|
||||
# define mdb_cmp_clong mdb_cmp_long
|
||||
#else
|
||||
# define mdb_cmp_clong mdb_cmp_cint
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static SECURITY_DESCRIPTOR mdb_null_sd;
|
||||
static SECURITY_ATTRIBUTES mdb_all_sa;
|
||||
|
@ -1558,7 +1570,12 @@ mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)
|
|||
int
|
||||
mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)
|
||||
{
|
||||
return txn->mt_dbxs[dbi].md_dcmp(a, b);
|
||||
MDB_cmp_func *dcmp = txn->mt_dbxs[dbi].md_dcmp;
|
||||
#if UINT_MAX < SIZE_MAX
|
||||
if (dcmp == mdb_cmp_int && a->mv_size == sizeof(size_t))
|
||||
dcmp = mdb_cmp_clong;
|
||||
#endif
|
||||
return dcmp(a, b);
|
||||
}
|
||||
|
||||
/** Allocate memory for a page.
|
||||
|
@ -2486,14 +2503,11 @@ mdb_txn_renew0(MDB_txn *txn)
|
|||
MDB_env *env = txn->mt_env;
|
||||
MDB_txninfo *ti = env->me_txns;
|
||||
MDB_meta *meta;
|
||||
unsigned int i, nr;
|
||||
unsigned int i, nr, flags = txn->mt_flags;
|
||||
uint16_t x;
|
||||
int rc, new_notls = 0;
|
||||
|
||||
if (txn->mt_flags & MDB_TXN_RDONLY) {
|
||||
/* Setup db info */
|
||||
txn->mt_numdbs = env->me_numdbs;
|
||||
txn->mt_dbxs = env->me_dbxs; /* mostly static anyway */
|
||||
if ((flags &= MDB_TXN_RDONLY) != 0) {
|
||||
if (!ti) {
|
||||
meta = env->me_metas[ mdb_env_pick_meta(env) ];
|
||||
txn->mt_txnid = meta->mm_txnid;
|
||||
|
@ -2546,6 +2560,7 @@ mdb_txn_renew0(MDB_txn *txn)
|
|||
txn->mt_u.reader = r;
|
||||
meta = env->me_metas[txn->mt_txnid & 1];
|
||||
}
|
||||
txn->mt_dbxs = env->me_dbxs; /* mostly static anyway */
|
||||
} else {
|
||||
if (ti) {
|
||||
LOCK_MUTEX_W(env);
|
||||
|
@ -2556,14 +2571,11 @@ mdb_txn_renew0(MDB_txn *txn)
|
|||
meta = env->me_metas[ mdb_env_pick_meta(env) ];
|
||||
txn->mt_txnid = meta->mm_txnid;
|
||||
}
|
||||
/* Setup db info */
|
||||
txn->mt_numdbs = env->me_numdbs;
|
||||
txn->mt_txnid++;
|
||||
#if MDB_DEBUG
|
||||
if (txn->mt_txnid == mdb_debug_start)
|
||||
mdb_debug = 1;
|
||||
#endif
|
||||
txn->mt_flags = 0;
|
||||
txn->mt_child = NULL;
|
||||
txn->mt_loose_pgs = NULL;
|
||||
txn->mt_loose_count = 0;
|
||||
|
@ -2583,6 +2595,10 @@ mdb_txn_renew0(MDB_txn *txn)
|
|||
/* Moved to here to avoid a data race in read TXNs */
|
||||
txn->mt_next_pgno = meta->mm_last_pg+1;
|
||||
|
||||
txn->mt_flags = flags;
|
||||
|
||||
/* Setup db info */
|
||||
txn->mt_numdbs = env->me_numdbs;
|
||||
for (i=2; i<txn->mt_numdbs; i++) {
|
||||
x = env->me_dbflags[i];
|
||||
txn->mt_dbs[i].md_flags = x & PERSISTENT_FLAGS;
|
||||
|
@ -3132,6 +3148,7 @@ mdb_page_flush(MDB_txn *txn, int keep)
|
|||
/* Write up to MDB_COMMIT_PAGES dirty pages at a time. */
|
||||
if (pos!=next_pos || n==MDB_COMMIT_PAGES || wsize+size>MAX_WRITE) {
|
||||
if (n) {
|
||||
retry_write:
|
||||
/* Write previous page(s) */
|
||||
#ifdef MDB_USE_PWRITEV
|
||||
wres = pwritev(env->me_fd, iov, n, wpos);
|
||||
|
@ -3139,8 +3156,11 @@ mdb_page_flush(MDB_txn *txn, int keep)
|
|||
if (n == 1) {
|
||||
wres = pwrite(env->me_fd, iov[0].iov_base, wsize, wpos);
|
||||
} else {
|
||||
retry_seek:
|
||||
if (lseek(env->me_fd, wpos, SEEK_SET) == -1) {
|
||||
rc = ErrCode();
|
||||
if (rc == EINTR)
|
||||
goto retry_seek;
|
||||
DPRINTF(("lseek: %s", strerror(rc)));
|
||||
return rc;
|
||||
}
|
||||
|
@ -3150,6 +3170,8 @@ mdb_page_flush(MDB_txn *txn, int keep)
|
|||
if (wres != wsize) {
|
||||
if (wres < 0) {
|
||||
rc = ErrCode();
|
||||
if (rc == EINTR)
|
||||
goto retry_write;
|
||||
DPRINTF(("Write error: %s", strerror(rc)));
|
||||
} else {
|
||||
rc = EIO; /* TODO: Use which error code? */
|
||||
|
@ -3519,7 +3541,8 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
|
|||
int len;
|
||||
#define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \
|
||||
len = pwrite(fd, ptr, size, pos); \
|
||||
rc = (len >= 0); } while(0)
|
||||
if (len == -1 && ErrCode() == EINTR) continue; \
|
||||
rc = (len >= 0); break; } while(1)
|
||||
#endif
|
||||
|
||||
DPUTS("writing new meta page");
|
||||
|
@ -3624,6 +3647,7 @@ mdb_env_write_meta(MDB_txn *txn)
|
|||
/* Write to the SYNC fd */
|
||||
mfd = env->me_flags & (MDB_NOSYNC|MDB_NOMETASYNC) ?
|
||||
env->me_fd : env->me_mfd;
|
||||
retry_write:
|
||||
#ifdef _WIN32
|
||||
{
|
||||
memset(&ov, 0, sizeof(ov));
|
||||
|
@ -3636,6 +3660,8 @@ mdb_env_write_meta(MDB_txn *txn)
|
|||
#endif
|
||||
if (rc != len) {
|
||||
rc = rc < 0 ? ErrCode() : EIO;
|
||||
if (rc == EINTR)
|
||||
goto retry_write;
|
||||
DPUTS("write failed, disk error?");
|
||||
/* On a failure, the pagecache still contains the new data.
|
||||
* Write some old data back, to prevent it from being used.
|
||||
|
@ -4761,7 +4787,11 @@ mdb_cmp_long(const MDB_val *a, const MDB_val *b)
|
|||
*(size_t *)a->mv_data > *(size_t *)b->mv_data;
|
||||
}
|
||||
|
||||
/** Compare two items pointing at aligned unsigned int's */
|
||||
/** Compare two items pointing at aligned unsigned int's.
|
||||
*
|
||||
* This is also set as #MDB_INTEGERDUP|#MDB_DUPFIXED's #MDB_dbx.%md_dcmp,
|
||||
* but #mdb_cmp_clong() is called instead if the data type is size_t.
|
||||
*/
|
||||
static int
|
||||
mdb_cmp_int(const MDB_val *a, const MDB_val *b)
|
||||
{
|
||||
|
@ -4799,13 +4829,6 @@ mdb_cmp_cint(const MDB_val *a, const MDB_val *b)
|
|||
#endif
|
||||
}
|
||||
|
||||
/** Compare two items pointing at size_t's of unknown alignment. */
|
||||
#ifdef MISALIGNED_OK
|
||||
# define mdb_cmp_clong mdb_cmp_long
|
||||
#else
|
||||
# define mdb_cmp_clong mdb_cmp_cint
|
||||
#endif
|
||||
|
||||
/** Compare two items lexically */
|
||||
static int
|
||||
mdb_cmp_memn(const MDB_val *a, const MDB_val *b)
|
||||
|
@ -5741,15 +5764,21 @@ set1:
|
|||
return rc;
|
||||
}
|
||||
} else if (op == MDB_GET_BOTH || op == MDB_GET_BOTH_RANGE) {
|
||||
MDB_val d2;
|
||||
if ((rc = mdb_node_read(mc->mc_txn, leaf, &d2)) != MDB_SUCCESS)
|
||||
MDB_val olddata;
|
||||
MDB_cmp_func *dcmp;
|
||||
if ((rc = mdb_node_read(mc->mc_txn, leaf, &olddata)) != MDB_SUCCESS)
|
||||
return rc;
|
||||
rc = mc->mc_dbx->md_dcmp(data, &d2);
|
||||
dcmp = mc->mc_dbx->md_dcmp;
|
||||
#if UINT_MAX < SIZE_MAX
|
||||
if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
|
||||
dcmp = mdb_cmp_clong;
|
||||
#endif
|
||||
rc = dcmp(data, &olddata);
|
||||
if (rc) {
|
||||
if (op == MDB_GET_BOTH || rc > 0)
|
||||
return MDB_NOTFOUND;
|
||||
rc = 0;
|
||||
*data = d2;
|
||||
*data = olddata;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -6259,16 +6288,17 @@ more:
|
|||
|
||||
/* Was a single item before, must convert now */
|
||||
if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
||||
MDB_cmp_func *dcmp;
|
||||
/* Just overwrite the current item */
|
||||
if (flags == MDB_CURRENT)
|
||||
goto current;
|
||||
|
||||
dcmp = mc->mc_dbx->md_dcmp;
|
||||
#if UINT_MAX < SIZE_MAX
|
||||
if (mc->mc_dbx->md_dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
|
||||
mc->mc_dbx->md_dcmp = mdb_cmp_clong;
|
||||
if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
|
||||
dcmp = mdb_cmp_clong;
|
||||
#endif
|
||||
/* does data match? */
|
||||
if (!mc->mc_dbx->md_dcmp(data, &olddata)) {
|
||||
if (!dcmp(data, &olddata)) {
|
||||
if (flags & MDB_NODUPDATA)
|
||||
return MDB_KEYEXIST;
|
||||
/* overwrite it */
|
||||
|
@ -7088,6 +7118,7 @@ mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
|
|||
mc->mc_snum = 0;
|
||||
mc->mc_top = 0;
|
||||
mc->mc_pg[0] = 0;
|
||||
mc->mc_ki[0] = 0;
|
||||
mc->mc_flags = 0;
|
||||
if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
|
||||
mdb_tassert(txn, mx != NULL);
|
||||
|
@ -7717,12 +7748,12 @@ mdb_rebalance(MDB_cursor *mc)
|
|||
m3 = m2;
|
||||
if (m3 == mc || m3->mc_snum < mc->mc_snum) continue;
|
||||
if (m3->mc_pg[0] == mp) {
|
||||
m3->mc_snum--;
|
||||
m3->mc_top--;
|
||||
for (i=0; i<m3->mc_snum; i++) {
|
||||
m3->mc_pg[i] = m3->mc_pg[i+1];
|
||||
m3->mc_ki[i] = m3->mc_ki[i+1];
|
||||
}
|
||||
m3->mc_snum--;
|
||||
m3->mc_top--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7790,9 +7821,23 @@ mdb_rebalance(MDB_cursor *mc)
|
|||
if (mc->mc_ki[ptop] == 0) {
|
||||
rc = mdb_page_merge(&mn, mc);
|
||||
} else {
|
||||
MDB_cursor dummy;
|
||||
oldki += NUMKEYS(mn.mc_pg[mn.mc_top]);
|
||||
mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1;
|
||||
/* We want mdb_rebalance to find mn when doing fixups */
|
||||
if (mc->mc_flags & C_SUB) {
|
||||
dummy.mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi];
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = &dummy;
|
||||
dummy.mc_xcursor = (MDB_xcursor *)&mn;
|
||||
} else {
|
||||
mn.mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi];
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = &mn;
|
||||
}
|
||||
rc = mdb_page_merge(mc, &mn);
|
||||
if (mc->mc_flags & C_SUB)
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = dummy.mc_next;
|
||||
else
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = mn.mc_next;
|
||||
mdb_cursor_copy(&mn, mc);
|
||||
}
|
||||
mc->mc_flags &= ~C_EOF;
|
||||
|
@ -7819,6 +7864,13 @@ mdb_cursor_del0(MDB_cursor *mc)
|
|||
MDB_cursor *m2, *m3;
|
||||
MDB_dbi dbi = mc->mc_dbi;
|
||||
|
||||
/* DB is totally empty now, just bail out.
|
||||
* Other cursors adjustments were already done
|
||||
* by mdb_rebalance and aren't needed here.
|
||||
*/
|
||||
if (!mc->mc_snum)
|
||||
return rc;
|
||||
|
||||
mp = mc->mc_pg[mc->mc_top];
|
||||
nkeys = NUMKEYS(mp);
|
||||
|
||||
|
|
|
@ -45,19 +45,22 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
E(mdb_env_set_maxreaders(env, 1));
|
||||
E(mdb_env_set_mapsize(env, 10485760));
|
||||
E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP /*|MDB_NOSYNC*/, 0664));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_open(txn, NULL, 0, &dbi));
|
||||
E(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;
|
||||
|
||||
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);
|
||||
|
@ -68,7 +71,7 @@ int main(int argc,char * argv[])
|
|||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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",
|
||||
|
@ -97,7 +100,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -128,6 +131,7 @@ int main(int argc,char * argv[])
|
|||
(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");
|
||||
|
@ -164,9 +168,9 @@ int main(int argc,char * argv[])
|
|||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -47,20 +47,22 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
E(mdb_env_set_maxreaders(env, 1));
|
||||
E(mdb_env_set_mapsize(env, 10485760));
|
||||
E(mdb_env_set_maxdbs(env, 4));
|
||||
E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
E(mdb_open(txn, "id1", MDB_CREATE, &dbi));
|
||||
E(mdb_dbi_open(txn, "id1", MDB_CREATE, &dbi));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = sval;
|
||||
data.mv_size = sizeof(sval);
|
||||
data.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++;
|
||||
}
|
||||
|
@ -68,7 +70,7 @@ int main(int argc,char * argv[])
|
|||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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",
|
||||
|
@ -97,7 +99,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -114,10 +116,9 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
mdb_env_close(env);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -53,8 +53,9 @@ int main(int argc,char * argv[])
|
|||
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_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
|
||||
E(mdb_dbi_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = kval;
|
||||
|
@ -73,7 +74,7 @@ int main(int argc,char * argv[])
|
|||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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",
|
||||
|
@ -107,7 +108,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -124,10 +125,9 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
mdb_env_close(env);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -51,8 +51,9 @@ int main(int argc,char * argv[])
|
|||
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_open(txn, "id4", MDB_CREATE|MDB_DUPSORT|MDB_DUPFIXED, &dbi));
|
||||
E(mdb_dbi_open(txn, "id4", MDB_CREATE|MDB_DUPSORT|MDB_DUPFIXED, &dbi));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = kval;
|
||||
|
@ -72,7 +73,7 @@ int main(int argc,char * argv[])
|
|||
|
||||
/* there should be one full page of dups now.
|
||||
*/
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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",
|
||||
|
@ -142,7 +143,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -159,10 +160,9 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
mdb_env_close(env);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -53,8 +53,9 @@ int main(int argc,char * argv[])
|
|||
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_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
|
||||
E(mdb_dbi_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
|
||||
E(mdb_cursor_open(txn, dbi, &cursor));
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
|
@ -75,7 +76,7 @@ int main(int argc,char * argv[])
|
|||
E(mdb_txn_commit(txn));
|
||||
E(mdb_env_stat(env, &mst));
|
||||
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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",
|
||||
|
@ -109,7 +110,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -126,10 +127,9 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
mdb_env_close(env);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ int main(int argc,char * argv[])
|
|||
int i = 0, j = 0, rc;
|
||||
MDB_env *env;
|
||||
MDB_dbi dbi;
|
||||
MDB_val key, data;
|
||||
MDB_val key, data, sdata;
|
||||
MDB_txn *txn;
|
||||
MDB_stat mst;
|
||||
MDB_cursor *cursor;
|
||||
|
@ -46,33 +46,37 @@ int main(int argc,char * argv[])
|
|||
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_open(txn, "id6", MDB_CREATE|MDB_INTEGERKEY, &dbi));
|
||||
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;
|
||||
data.mv_size = mst.ms_psize / 4 - 30;
|
||||
data.mv_data = sval;
|
||||
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));
|
||||
|
@ -110,7 +114,7 @@ int main(int argc,char * argv[])
|
|||
printf("Deleted %d values\n", j);
|
||||
|
||||
E(mdb_env_stat(env, &mst));
|
||||
E(mdb_txn_begin(env, NULL, 1, &txn));
|
||||
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) {
|
||||
|
@ -127,9 +131,9 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
mdb_dbi_close(env, dbi);
|
||||
#endif
|
||||
mdb_env_close(env);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ int main(int argc,char * argv[])
|
|||
rc = mdb_env_create(&env);
|
||||
rc = mdb_env_open(env, "./testdb", 0, 0664);
|
||||
rc = mdb_txn_begin(env, NULL, 0, &txn);
|
||||
rc = mdb_open(txn, NULL, 0, &dbi);
|
||||
rc = mdb_dbi_open(txn, NULL, 0, &dbi);
|
||||
|
||||
key.mv_size = sizeof(int);
|
||||
key.mv_data = sval;
|
||||
|
@ -56,7 +56,7 @@ int main(int argc,char * argv[])
|
|||
mdb_cursor_close(cursor);
|
||||
mdb_txn_abort(txn);
|
||||
leave:
|
||||
mdb_close(env, dbi);
|
||||
mdb_dbi_close(env, dbi);
|
||||
mdb_env_close(env);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue