mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-18 11:05:48 +08:00
Merge remote-tracking branch 'origin/mdb.master'
This commit is contained in:
commit
f6eacdbbc5
1
libraries/liblmdb/.gitignore
vendored
1
libraries/liblmdb/.gitignore
vendored
@ -5,6 +5,7 @@ mdb_copy
|
||||
mdb_stat
|
||||
*.[ao]
|
||||
*.so
|
||||
*.exe
|
||||
*[~#]
|
||||
*.bak
|
||||
*.orig
|
||||
|
@ -25,7 +25,7 @@ DOXYFILE_ENCODING = UTF-8
|
||||
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
|
||||
# by quotes) that should identify the project.
|
||||
|
||||
PROJECT_NAME = MDB
|
||||
PROJECT_NAME = LMDB
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
|
||||
# This could be handy for archiving the generated documentation or
|
||||
@ -1404,7 +1404,7 @@ SKIP_FUNCTION_MACROS = YES
|
||||
# If a tag file is not located in the directory in which doxygen
|
||||
# is run, you must also specify the path to the tagfile here.
|
||||
|
||||
TAGFILES =
|
||||
TAGFILES = tooltag=./man1
|
||||
|
||||
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
|
||||
# a tag file that is based on the input files it reads.
|
||||
|
@ -29,8 +29,8 @@ prefix = /usr/local
|
||||
|
||||
IHDRS = lmdb.h
|
||||
ILIBS = liblmdb.a liblmdb.so
|
||||
IPROGS = mdb_stat mdb_copy
|
||||
IDOCS = mdb_stat.1 mdb_copy.1
|
||||
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)
|
||||
|
||||
@ -56,6 +56,8 @@ liblmdb.so: mdb.o midl.o
|
||||
|
||||
mdb_stat: mdb_stat.o liblmdb.a
|
||||
mdb_copy: mdb_copy.o liblmdb.a
|
||||
mdb_dump: mdb_dump.o liblmdb.a
|
||||
mdb_load: mdb_load.o liblmdb.a
|
||||
mtest: mtest.o liblmdb.a
|
||||
mtest2: mtest2.o liblmdb.a
|
||||
mtest3: mtest3.o liblmdb.a
|
||||
|
@ -1,10 +1,10 @@
|
||||
/** @file lmdb.h
|
||||
* @brief Lightning memory-mapped database library
|
||||
*
|
||||
* @mainpage Lightning Memory-Mapped Database Manager (MDB)
|
||||
* @mainpage Lightning Memory-Mapped Database Manager (LMDB)
|
||||
*
|
||||
* @section intro_sec Introduction
|
||||
* MDB is a Btree-based database management library modeled loosely on the
|
||||
* LMDB is a Btree-based database management library modeled loosely on the
|
||||
* BerkeleyDB API, but much simplified. The entire database is exposed
|
||||
* in a memory map, and all data fetches return data directly
|
||||
* from the mapped memory, so no malloc's or memcpy's occur during
|
||||
@ -26,10 +26,10 @@
|
||||
* readers, and readers don't block writers.
|
||||
*
|
||||
* Unlike other well-known database mechanisms which use either write-ahead
|
||||
* transaction logs or append-only data writes, MDB requires no maintenance
|
||||
* transaction logs or append-only data writes, LMDB requires no maintenance
|
||||
* during operation. Both write-ahead loggers and append-only databases
|
||||
* require periodic checkpointing and/or compaction of their log or database
|
||||
* files otherwise they grow without bound. MDB tracks free pages within
|
||||
* files otherwise they grow without bound. LMDB tracks free pages within
|
||||
* the database and re-uses them for new write operations, so the database
|
||||
* size does not grow without bound in normal use.
|
||||
*
|
||||
@ -49,7 +49,7 @@
|
||||
* stale locks can block further operation.
|
||||
*
|
||||
* Fix: Check for stale readers periodically, using the
|
||||
* #mdb_reader_check function or the mdb_stat tool. Or just
|
||||
* #mdb_reader_check function or the \ref mdb_stat_1 "mdb_stat" tool. Or just
|
||||
* make all programs using the database close it; the lockfile
|
||||
* is always reset on first open of the environment.
|
||||
*
|
||||
@ -86,7 +86,7 @@
|
||||
*
|
||||
* - Use an MDB_env* in the process which opened it, without fork()ing.
|
||||
*
|
||||
* - Do not have open an MDB database twice in the same process at
|
||||
* - Do not have open an LMDB database twice in the same process at
|
||||
* the same time. Not even from a plain open() call - close()ing it
|
||||
* breaks flock() advisory locking.
|
||||
*
|
||||
@ -109,7 +109,7 @@
|
||||
* - 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.
|
||||
*
|
||||
* - Do not use MDB databases on remote filesystems, even between
|
||||
* - Do not use LMDB databases on remote filesystems, even between
|
||||
* processes on the same host. This breaks flock() on some OSes,
|
||||
* possibly memory map sync, and certainly sync between programs
|
||||
* on different hosts.
|
||||
@ -172,7 +172,7 @@ typedef void *mdb_filehandle_t;
|
||||
typedef int mdb_filehandle_t;
|
||||
#endif
|
||||
|
||||
/** @defgroup mdb MDB API
|
||||
/** @defgroup mdb LMDB API
|
||||
* @{
|
||||
* @brief OpenLDAP Lightning Memory-Mapped Database Manager
|
||||
*/
|
||||
@ -184,7 +184,7 @@ typedef int mdb_filehandle_t;
|
||||
/** Library minor version */
|
||||
#define MDB_VERSION_MINOR 9
|
||||
/** Library patch version */
|
||||
#define MDB_VERSION_PATCH 13
|
||||
#define MDB_VERSION_PATCH 14
|
||||
|
||||
/** 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,10 +194,10 @@ 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 "June 13, 2014"
|
||||
#define MDB_VERSION_DATE "June 20, 2014"
|
||||
|
||||
/** A stringifier for the version info */
|
||||
#define MDB_VERSTR(a,b,c,d) "MDB " #a "." #b "." #c ": (" d ")"
|
||||
#define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")"
|
||||
|
||||
/** A helper for the stringifier macro */
|
||||
#define MDB_VERFOO(a,b,c,d) MDB_VERSTR(a,b,c,d)
|
||||
@ -386,7 +386,7 @@ typedef enum MDB_cursor_op {
|
||||
#define MDB_PANIC (-30795)
|
||||
/** Environment version mismatch */
|
||||
#define MDB_VERSION_MISMATCH (-30794)
|
||||
/** File is not a valid MDB file */
|
||||
/** File is not a valid LMDB file */
|
||||
#define MDB_INVALID (-30793)
|
||||
/** Environment mapsize reached */
|
||||
#define MDB_MAP_FULL (-30792)
|
||||
@ -436,7 +436,7 @@ typedef struct MDB_envinfo {
|
||||
unsigned int me_numreaders; /**< max reader slots used in the environment */
|
||||
} MDB_envinfo;
|
||||
|
||||
/** @brief Return the mdb library version information.
|
||||
/** @brief Return the LMDB library version information.
|
||||
*
|
||||
* @param[out] major if non-NULL, the library major version number is copied here
|
||||
* @param[out] minor if non-NULL, the library minor version number is copied here
|
||||
@ -450,14 +450,14 @@ char *mdb_version(int *major, int *minor, int *patch);
|
||||
* This function is a superset of the ANSI C X3.159-1989 (ANSI C) strerror(3)
|
||||
* function. If the error code is greater than or equal to 0, then the string
|
||||
* returned by the system function strerror(3) is returned. If the error code
|
||||
* is less than 0, an error string corresponding to the MDB library error is
|
||||
* returned. See @ref errors for a list of MDB-specific error codes.
|
||||
* is less than 0, an error string corresponding to the LMDB library error is
|
||||
* returned. See @ref errors for a list of LMDB-specific error codes.
|
||||
* @param[in] err The error code
|
||||
* @retval "error message" The description of the error
|
||||
*/
|
||||
char *mdb_strerror(int err);
|
||||
|
||||
/** @brief Create an MDB environment handle.
|
||||
/** @brief Create an LMDB environment handle.
|
||||
*
|
||||
* This function allocates memory for a #MDB_env structure. To release
|
||||
* the allocated memory and discard the handle, call #mdb_env_close().
|
||||
@ -490,15 +490,15 @@ int mdb_env_create(MDB_env **env);
|
||||
* how the operating system has allocated memory to shared libraries and other uses.
|
||||
* The feature is highly experimental.
|
||||
* <li>#MDB_NOSUBDIR
|
||||
* By default, MDB creates its environment in a directory whose
|
||||
* By default, LMDB creates its environment in a directory whose
|
||||
* pathname is given in \b path, and creates its data and lock files
|
||||
* under that directory. With this option, \b path is used as-is for
|
||||
* the database main data file. The database lock file is the \b path
|
||||
* with "-lock" appended.
|
||||
* <li>#MDB_RDONLY
|
||||
* Open the environment in read-only mode. No write operations will be
|
||||
* allowed. MDB will still modify the lock file - except on read-only
|
||||
* filesystems, where MDB does not use locks.
|
||||
* allowed. LMDB will still modify the lock file - except on read-only
|
||||
* filesystems, where LMDB does not use locks.
|
||||
* <li>#MDB_WRITEMAP
|
||||
* Use a writeable memory map unless MDB_RDONLY is set. This is faster
|
||||
* and uses fewer mallocs, but loses protection from application bugs
|
||||
@ -542,7 +542,7 @@ int mdb_env_create(MDB_env **env);
|
||||
* the user synchronizes its use. Applications that multiplex many
|
||||
* user threads over individual OS threads need this option. Such an
|
||||
* application must also serialize the write transactions in an OS
|
||||
* thread, since MDB's write locking is unaware of the user threads.
|
||||
* thread, since LMDB's write locking is unaware of the user threads.
|
||||
* <li>#MDB_NOLOCK
|
||||
* Don't do any locking. If concurrent access is anticipated, the
|
||||
* caller must manage all concurrency itself. For proper operation
|
||||
@ -581,7 +581,7 @@ int mdb_env_create(MDB_env **env);
|
||||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
* errors are:
|
||||
* <ul>
|
||||
* <li>#MDB_VERSION_MISMATCH - the version of the MDB library doesn't match the
|
||||
* <li>#MDB_VERSION_MISMATCH - the version of the LMDB library doesn't match the
|
||||
* version that created the database environment.
|
||||
* <li>#MDB_INVALID - the environment file headers are corrupted.
|
||||
* <li>ENOENT - the directory specified by the path parameter doesn't exist.
|
||||
@ -591,7 +591,7 @@ int mdb_env_create(MDB_env **env);
|
||||
*/
|
||||
int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode);
|
||||
|
||||
/** @brief Copy an MDB environment to the specified path.
|
||||
/** @brief Copy an LMDB environment to the specified path.
|
||||
*
|
||||
* This function may be used to make a backup of an existing environment.
|
||||
* No lockfile is created, since it gets recreated at need.
|
||||
@ -607,7 +607,7 @@ int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t
|
||||
*/
|
||||
int mdb_env_copy(MDB_env *env, const char *path);
|
||||
|
||||
/** @brief Copy an MDB environment to the specified file descriptor.
|
||||
/** @brief Copy an LMDB environment to the specified file descriptor.
|
||||
*
|
||||
* This function may be used to make a backup of an existing environment.
|
||||
* No lockfile is created, since it gets recreated at need.
|
||||
@ -622,7 +622,7 @@ int mdb_env_copy(MDB_env *env, const char *path);
|
||||
*/
|
||||
int mdb_env_copyfd(MDB_env *env, mdb_filehandle_t fd);
|
||||
|
||||
/** @brief Return statistics about the MDB environment.
|
||||
/** @brief Return statistics about the LMDB environment.
|
||||
*
|
||||
* @param[in] env An environment handle returned by #mdb_env_create()
|
||||
* @param[out] stat The address of an #MDB_stat structure
|
||||
@ -630,7 +630,7 @@ int mdb_env_copyfd(MDB_env *env, mdb_filehandle_t fd);
|
||||
*/
|
||||
int mdb_env_stat(MDB_env *env, MDB_stat *stat);
|
||||
|
||||
/** @brief Return information about the MDB environment.
|
||||
/** @brief Return information about the LMDB environment.
|
||||
*
|
||||
* @param[in] env An environment handle returned by #mdb_env_create()
|
||||
* @param[out] stat The address of an #MDB_envinfo structure
|
||||
@ -641,7 +641,7 @@ int mdb_env_info(MDB_env *env, MDB_envinfo *stat);
|
||||
/** @brief Flush the data buffers to disk.
|
||||
*
|
||||
* Data is always written to disk when #mdb_txn_commit() is called,
|
||||
* but the operating system may keep it buffered. MDB always flushes
|
||||
* 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.
|
||||
* @param[in] env An environment handle returned by #mdb_env_create()
|
||||
@ -824,7 +824,7 @@ int mdb_env_set_userctx(MDB_env *env, void *ctx);
|
||||
*/
|
||||
void *mdb_env_get_userctx(MDB_env *env);
|
||||
|
||||
/** @brief A callback function for most MDB assert() failures,
|
||||
/** @brief A callback function for most LMDB assert() failures,
|
||||
* called before printing the message and aborting.
|
||||
*
|
||||
* @param[in] env An environment handle returned by #mdb_env_create().
|
||||
@ -1206,7 +1206,7 @@ int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data);
|
||||
* reserved space, which the caller can fill in later - before
|
||||
* the next update operation or the transaction ends. This saves
|
||||
* an extra memcpy if the data is being generated later.
|
||||
* MDB 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.
|
||||
* <li>#MDB_APPEND - append the given key/data pair to the end of the
|
||||
* database. No key comparisons are performed. This option allows
|
||||
@ -1478,4 +1478,12 @@ int mdb_reader_check(MDB_env *env, int *dead);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** @page tools LMDB Command Line Tools
|
||||
The following describes the command line tools that are available for LMDB.
|
||||
\li \ref mdb_copy_1
|
||||
\li \ref mdb_dump_1
|
||||
\li \ref mdb_load_1
|
||||
\li \ref mdb_stat_1
|
||||
*/
|
||||
|
||||
#endif /* _LMDB_H_ */
|
||||
|
@ -1,11 +1,11 @@
|
||||
/** @file mdb.c
|
||||
* @brief memory-mapped database library
|
||||
* @brief Lightning memory-mapped database library
|
||||
*
|
||||
* A Btree-based database management library modeled loosely on the
|
||||
* BerkeleyDB API, but much simplified.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2011-2013 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -145,7 +145,7 @@
|
||||
# error "Two's complement, reasonably sized integer types, please"
|
||||
#endif
|
||||
|
||||
/** @defgroup internal MDB Internals
|
||||
/** @defgroup internal LMDB Internals
|
||||
* @{
|
||||
*/
|
||||
/** @defgroup compat Compatibility Macros
|
||||
@ -381,7 +381,7 @@ static txnid_t mdb_debug_start;
|
||||
*/
|
||||
#define MDB_MINKEYS 2
|
||||
|
||||
/** A stamp that identifies a file as an MDB file.
|
||||
/** A stamp that identifies a file as an LMDB file.
|
||||
* There's nothing special about this value other than that it is easily
|
||||
* recognizable, and it will reflect any byte order mismatches.
|
||||
*/
|
||||
@ -568,7 +568,7 @@ typedef struct MDB_reader {
|
||||
* unlikely. If a collision occurs, the results are unpredictable.
|
||||
*/
|
||||
typedef struct MDB_txbody {
|
||||
/** Stamp identifying this as an MDB file. It must be set
|
||||
/** Stamp identifying this as an LMDB file. It must be set
|
||||
* to #MDB_MAGIC. */
|
||||
uint32_t mtb_magic;
|
||||
/** Format of this lock file. Must be set to #MDB_LOCK_FORMAT. */
|
||||
@ -650,6 +650,7 @@ typedef struct MDB_page {
|
||||
#define P_DIRTY 0x10 /**< dirty page, also set for #P_SUBP pages */
|
||||
#define P_LEAF2 0x20 /**< for #MDB_DUPFIXED records */
|
||||
#define P_SUBP 0x40 /**< for #MDB_DUPSORT sub-pages */
|
||||
#define P_LOOSE 0x4000 /**< page was dirtied then freed, can be reused */
|
||||
#define P_KEEP 0x8000 /**< leave this page alone during spill */
|
||||
/** @} */
|
||||
uint16_t mp_flags; /**< @ref mdb_page */
|
||||
@ -841,7 +842,7 @@ typedef struct MDB_db {
|
||||
* Pages 0-1 are meta pages. Transaction N writes meta page #(N % 2).
|
||||
*/
|
||||
typedef struct MDB_meta {
|
||||
/** Stamp identifying this as an MDB file. It must be set
|
||||
/** 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. */
|
||||
@ -898,6 +899,10 @@ struct MDB_txn {
|
||||
/** The list of pages that became unused during this transaction.
|
||||
*/
|
||||
MDB_IDL mt_free_pgs;
|
||||
/** The list of loose pages that became unused and may be reused
|
||||
* in this transaction.
|
||||
*/
|
||||
MDB_page *mt_loose_pgs;
|
||||
/** The sorted list of dirty pages we temporarily wrote to disk
|
||||
* because the dirty list was full. page numbers in here are
|
||||
* shifted left by 1, deleted slots have the LSB set.
|
||||
@ -1182,7 +1187,7 @@ mdb_version(int *major, int *minor, int *patch)
|
||||
return MDB_VERSION_STRING;
|
||||
}
|
||||
|
||||
/** Table of descriptions for MDB @ref errors */
|
||||
/** Table of descriptions for LMDB @ref errors */
|
||||
static char *const mdb_errstr[] = {
|
||||
"MDB_KEYEXIST: Key/data pair already exists",
|
||||
"MDB_NOTFOUND: No matching key/data pair found",
|
||||
@ -1190,7 +1195,7 @@ static char *const mdb_errstr[] = {
|
||||
"MDB_CORRUPTED: Located page was wrong type",
|
||||
"MDB_PANIC: Update of meta page failed",
|
||||
"MDB_VERSION_MISMATCH: Database environment version mismatch",
|
||||
"MDB_INVALID: File is not an MDB file",
|
||||
"MDB_INVALID: File is not an LMDB file",
|
||||
"MDB_MAP_FULL: Environment mapsize limit reached",
|
||||
"MDB_DBS_FULL: Environment maxdbs limit reached",
|
||||
"MDB_READERS_FULL: Environment maxreaders limit reached",
|
||||
@ -1485,7 +1490,6 @@ mdb_page_malloc(MDB_txn *txn, unsigned num)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Free a single page.
|
||||
* Saves single pages to a list, for future reuse.
|
||||
* (This is not used for multi-page overflow pages.)
|
||||
@ -1525,6 +1529,60 @@ mdb_dlist_free(MDB_txn *txn)
|
||||
dl[0].mid = 0;
|
||||
}
|
||||
|
||||
/** Loosen or free a single page.
|
||||
* Saves single pages to a list for future reuse
|
||||
* in this same txn. It has been pulled from the freeDB
|
||||
* and already resides on the dirty list, but has been
|
||||
* deleted. Use these pages first before pulling again
|
||||
* from the freeDB.
|
||||
*
|
||||
* If the page wasn't dirtied in this txn, just add it
|
||||
* to this txn's free list.
|
||||
*/
|
||||
static int
|
||||
mdb_page_loose(MDB_cursor *mc, MDB_page *mp)
|
||||
{
|
||||
int loose = 0;
|
||||
pgno_t pgno = mp->mp_pgno;
|
||||
|
||||
if ((mp->mp_flags & P_DIRTY) && mc->mc_dbi != FREE_DBI) {
|
||||
if (mc->mc_txn->mt_parent) {
|
||||
MDB_ID2 *dl = mc->mc_txn->mt_u.dirty_list;
|
||||
/* If txn has a parent, make sure the page is in our
|
||||
* dirty list.
|
||||
*/
|
||||
if (dl[0].mid) {
|
||||
unsigned x = mdb_mid2l_search(dl, pgno);
|
||||
if (x <= dl[0].mid && dl[x].mid == pgno) {
|
||||
if (mp != dl[x].mptr) { /* bad cursor? */
|
||||
mc->mc_flags &= ~(C_INITIALIZED|C_EOF);
|
||||
mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
|
||||
return MDB_CORRUPTED;
|
||||
}
|
||||
/* ok, it's ours */
|
||||
loose = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* no parent txn, so it's just ours */
|
||||
loose = 1;
|
||||
}
|
||||
}
|
||||
if (loose) {
|
||||
pgno_t *pp = (pgno_t *)mp->mp_ptrs;
|
||||
*pp = pgno;
|
||||
mp->mp_next = mc->mc_txn->mt_loose_pgs;
|
||||
mc->mc_txn->mt_loose_pgs = mp;
|
||||
mp->mp_flags |= P_LOOSE;
|
||||
} else {
|
||||
int rc = mdb_midl_append(&mc->mc_txn->mt_free_pgs, pgno);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return MDB_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set or clear P_KEEP in dirty, non-overflow, non-sub pages watched by txn.
|
||||
* @param[in] mc A cursor handle for the current operation.
|
||||
* @param[in] pflags Flags of the pages to update:
|
||||
@ -1573,6 +1631,12 @@ mdb_pages_xkeep(MDB_cursor *mc, unsigned pflags, int all)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Loose pages shouldn't be spilled */
|
||||
for (dp = txn->mt_loose_pgs; dp; dp=dp->mp_next) {
|
||||
if ((dp->mp_flags & Mask) == pflags)
|
||||
dp->mp_flags ^= P_KEEP;
|
||||
}
|
||||
|
||||
if (all) {
|
||||
/* Mark dirty root pages */
|
||||
for (i=0; i<txn->mt_numdbs; i++) {
|
||||
@ -1800,6 +1864,17 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
||||
MDB_cursor_op op;
|
||||
MDB_cursor m2;
|
||||
|
||||
/* If there are any loose pages, just use them */
|
||||
if (num == 1 && txn->mt_loose_pgs) {
|
||||
pgno_t *pp;
|
||||
np = txn->mt_loose_pgs;
|
||||
txn->mt_loose_pgs = np->mp_next;
|
||||
pp = (pgno_t *)np->mp_ptrs;
|
||||
np->mp_pgno = *pp;
|
||||
*mp = np;
|
||||
return MDB_SUCCESS;
|
||||
}
|
||||
|
||||
*mp = NULL;
|
||||
|
||||
/* If our dirty list is already full, we can't do anything */
|
||||
@ -2661,6 +2736,38 @@ mdb_freelist_save(MDB_txn *txn)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Dispose of loose pages. Usually they will have all
|
||||
* been used up by the time we get here.
|
||||
*/
|
||||
if (txn->mt_loose_pgs) {
|
||||
MDB_page *mp = txn->mt_loose_pgs;
|
||||
pgno_t *pp;
|
||||
/* Just return them to freeDB */
|
||||
if (env->me_pghead) {
|
||||
int i, j;
|
||||
mop = env->me_pghead;
|
||||
while(mp) {
|
||||
pgno_t pg;
|
||||
pp = (pgno_t *)mp->mp_ptrs;
|
||||
pg = *pp;
|
||||
j = mop[0] + 1;
|
||||
for (i = mop[0]; i && mop[i] < pg; i--)
|
||||
mop[j--] = mop[i];
|
||||
mop[j] = pg;
|
||||
mop[0] += 1;
|
||||
mp = mp->mp_next;
|
||||
}
|
||||
} else {
|
||||
/* Oh well, they were wasted. Put on freelist */
|
||||
while(mp) {
|
||||
pp = (pgno_t *)mp->mp_ptrs;
|
||||
mdb_midl_append(&txn->mt_free_pgs, *pp);
|
||||
mp = mp->mp_next;
|
||||
}
|
||||
}
|
||||
txn->mt_loose_pgs = NULL;
|
||||
}
|
||||
|
||||
/* MDB_RESERVE cancels meminit in ovpage malloc (when no WRITEMAP) */
|
||||
clean_limit = (env->me_flags & (MDB_NOMEMINIT|MDB_WRITEMAP))
|
||||
? SSIZE_MAX : maxfree_1pg;
|
||||
@ -3555,7 +3662,7 @@ mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers)
|
||||
return MDB_SUCCESS;
|
||||
}
|
||||
|
||||
/** Further setup required for opening an MDB environment
|
||||
/** Further setup required for opening an LMDB environment
|
||||
*/
|
||||
static int
|
||||
mdb_env_open2(MDB_env *env)
|
||||
@ -3891,7 +3998,7 @@ mdb_hash_enc(MDB_val *val, char *encbuf)
|
||||
#endif
|
||||
|
||||
/** Open and/or initialize the lock region for the environment.
|
||||
* @param[in] env The MDB environment.
|
||||
* @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
|
||||
@ -4542,7 +4649,16 @@ mdb_cmp_cint(const MDB_val *a, const MDB_val *b)
|
||||
} while(!x && u > (unsigned short *)a->mv_data);
|
||||
return x;
|
||||
#else
|
||||
return memcmp(a->mv_data, b->mv_data, a->mv_size);
|
||||
unsigned short *u, *c, *end;
|
||||
int x;
|
||||
|
||||
end = (unsigned short *) ((char *) a->mv_data + a->mv_size);
|
||||
u = (unsigned short *)a->mv_data;
|
||||
c = (unsigned short *)b->mv_data;
|
||||
do {
|
||||
x = *u++ - *c++;
|
||||
} while(!x && u < end);
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -7054,20 +7170,20 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
MDB_node *s2;
|
||||
MDB_val bkey;
|
||||
/* must find the lowest key below dst */
|
||||
rc = mdb_page_search_lowest(cdst);
|
||||
mdb_cursor_copy(cdst, &mn);
|
||||
rc = mdb_page_search_lowest(&mn);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (IS_LEAF2(cdst->mc_pg[cdst->mc_top])) {
|
||||
bkey.mv_size = cdst->mc_db->md_pad;
|
||||
bkey.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, bkey.mv_size);
|
||||
if (IS_LEAF2(mn.mc_pg[mn.mc_top])) {
|
||||
bkey.mv_size = mn.mc_db->md_pad;
|
||||
bkey.mv_data = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, bkey.mv_size);
|
||||
} else {
|
||||
s2 = NODEPTR(cdst->mc_pg[cdst->mc_top], 0);
|
||||
s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0);
|
||||
bkey.mv_size = NODEKSZ(s2);
|
||||
bkey.mv_data = NODEKEY(s2);
|
||||
}
|
||||
cdst->mc_snum = snum--;
|
||||
cdst->mc_top = snum;
|
||||
mdb_cursor_copy(cdst, &mn);
|
||||
mn.mc_snum = snum--;
|
||||
mn.mc_top = snum;
|
||||
mn.mc_ki[snum] = 0;
|
||||
rc = mdb_update_key(&mn, &bkey);
|
||||
if (rc)
|
||||
@ -7183,14 +7299,17 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
static int
|
||||
mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
{
|
||||
int rc;
|
||||
indx_t i, j;
|
||||
MDB_node *srcnode;
|
||||
MDB_page *psrc, *pdst;
|
||||
MDB_node *srcnode;
|
||||
MDB_val key, data;
|
||||
unsigned nkeys;
|
||||
unsigned nkeys;
|
||||
int rc;
|
||||
indx_t i, j;
|
||||
|
||||
DPRINTF(("merging page %"Z"u into %"Z"u", csrc->mc_pg[csrc->mc_top]->mp_pgno,
|
||||
cdst->mc_pg[cdst->mc_top]->mp_pgno));
|
||||
psrc = csrc->mc_pg[csrc->mc_top];
|
||||
pdst = cdst->mc_pg[cdst->mc_top];
|
||||
|
||||
DPRINTF(("merging page %"Z"u into %"Z"u", psrc->mp_pgno, pdst->mp_pgno));
|
||||
|
||||
mdb_cassert(csrc, csrc->mc_snum > 1); /* can't merge root page */
|
||||
mdb_cassert(csrc, cdst->mc_snum > 1);
|
||||
@ -7201,36 +7320,35 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
|
||||
/* Move all nodes from src to dst.
|
||||
*/
|
||||
j = nkeys = NUMKEYS(cdst->mc_pg[cdst->mc_top]);
|
||||
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
|
||||
j = nkeys = NUMKEYS(pdst);
|
||||
if (IS_LEAF2(psrc)) {
|
||||
key.mv_size = csrc->mc_db->md_pad;
|
||||
key.mv_data = METADATA(csrc->mc_pg[csrc->mc_top]);
|
||||
for (i = 0; i < NUMKEYS(csrc->mc_pg[csrc->mc_top]); i++, j++) {
|
||||
key.mv_data = METADATA(psrc);
|
||||
for (i = 0; i < NUMKEYS(psrc); i++, j++) {
|
||||
rc = mdb_node_add(cdst, j, &key, NULL, 0, 0);
|
||||
if (rc != MDB_SUCCESS)
|
||||
return rc;
|
||||
key.mv_data = (char *)key.mv_data + key.mv_size;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < NUMKEYS(csrc->mc_pg[csrc->mc_top]); i++, j++) {
|
||||
srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], i);
|
||||
if (i == 0 && IS_BRANCH(csrc->mc_pg[csrc->mc_top])) {
|
||||
unsigned int snum = csrc->mc_snum;
|
||||
for (i = 0; i < NUMKEYS(psrc); i++, j++) {
|
||||
srcnode = NODEPTR(psrc, i);
|
||||
if (i == 0 && IS_BRANCH(psrc)) {
|
||||
MDB_cursor mn;
|
||||
MDB_node *s2;
|
||||
mdb_cursor_copy(csrc, &mn);
|
||||
/* must find the lowest key below src */
|
||||
rc = mdb_page_search_lowest(csrc);
|
||||
rc = mdb_page_search_lowest(&mn);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
|
||||
key.mv_size = csrc->mc_db->md_pad;
|
||||
key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
|
||||
if (IS_LEAF2(mn.mc_pg[mn.mc_top])) {
|
||||
key.mv_size = mn.mc_db->md_pad;
|
||||
key.mv_data = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, key.mv_size);
|
||||
} else {
|
||||
s2 = NODEPTR(csrc->mc_pg[csrc->mc_top], 0);
|
||||
s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0);
|
||||
key.mv_size = NODEKSZ(s2);
|
||||
key.mv_data = NODEKEY(s2);
|
||||
}
|
||||
csrc->mc_snum = snum--;
|
||||
csrc->mc_top = snum;
|
||||
} else {
|
||||
key.mv_size = srcnode->mn_ksize;
|
||||
key.mv_data = NODEKEY(srcnode);
|
||||
@ -7245,8 +7363,8 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
}
|
||||
|
||||
DPRINTF(("dst page %"Z"u now has %u keys (%.1f%% filled)",
|
||||
cdst->mc_pg[cdst->mc_top]->mp_pgno, NUMKEYS(cdst->mc_pg[cdst->mc_top]),
|
||||
(float)PAGEFILL(cdst->mc_txn->mt_env, cdst->mc_pg[cdst->mc_top]) / 10));
|
||||
pdst->mp_pgno, NUMKEYS(pdst),
|
||||
(float)PAGEFILL(cdst->mc_txn->mt_env, pdst) / 10));
|
||||
|
||||
/* Unlink the src page from parent and add to free list.
|
||||
*/
|
||||
@ -7262,11 +7380,14 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
}
|
||||
csrc->mc_top++;
|
||||
|
||||
rc = mdb_midl_append(&csrc->mc_txn->mt_free_pgs,
|
||||
csrc->mc_pg[csrc->mc_top]->mp_pgno);
|
||||
psrc = csrc->mc_pg[csrc->mc_top];
|
||||
/* If not operating on FreeDB, allow this page to be reused
|
||||
* in this txn. Otherwise just add to free list.
|
||||
*/
|
||||
rc = mdb_page_loose(csrc, psrc);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (IS_LEAF(csrc->mc_pg[csrc->mc_top]))
|
||||
if (IS_LEAF(psrc))
|
||||
csrc->mc_db->md_leaf_pages--;
|
||||
else
|
||||
csrc->mc_db->md_branch_pages--;
|
||||
@ -7274,7 +7395,6 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
/* Adjust other cursors pointing to mp */
|
||||
MDB_cursor *m2, *m3;
|
||||
MDB_dbi dbi = csrc->mc_dbi;
|
||||
MDB_page *mp = cdst->mc_pg[cdst->mc_top];
|
||||
|
||||
for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
|
||||
if (csrc->mc_flags & C_SUB)
|
||||
@ -7283,8 +7403,8 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
m3 = m2;
|
||||
if (m3 == csrc) continue;
|
||||
if (m3->mc_snum < csrc->mc_snum) continue;
|
||||
if (m3->mc_pg[csrc->mc_top] == csrc->mc_pg[csrc->mc_top]) {
|
||||
m3->mc_pg[csrc->mc_top] = mp;
|
||||
if (m3->mc_pg[csrc->mc_top] == psrc) {
|
||||
m3->mc_pg[csrc->mc_top] = pdst;
|
||||
m3->mc_ki[csrc->mc_top] += nkeys;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
.TH MDB_COPY 1 "2012/12/12" "LMDB 0.9.5"
|
||||
.\" Copyright 2012 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.TH MDB_COPY 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2012-2014 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 \-n ]
|
||||
.B srcpath
|
||||
[\c
|
||||
@ -24,6 +26,10 @@ 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 \-n
|
||||
Open LDMB environment(s) which do not use subdirectories.
|
||||
|
||||
|
@ -37,12 +37,15 @@ int main(int argc,char * argv[])
|
||||
for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) {
|
||||
if (argv[1][1] == 'n' && argv[1][2] == '\0')
|
||||
flags |= MDB_NOSUBDIR;
|
||||
else
|
||||
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 [-n] srcpath [dstpath]\n", progname);
|
||||
fprintf(stderr, "usage: %s [-V] [-n] srcpath [dstpath]\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
75
libraries/liblmdb/mdb_dump.1
Normal file
75
libraries/liblmdb/mdb_dump.1
Normal file
@ -0,0 +1,75 @@
|
||||
.TH MDB_DUMP 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2014 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>
|
276
libraries/liblmdb/mdb_dump.c
Normal file
276
libraries/liblmdb/mdb_dump.c
Normal file
@ -0,0 +1,276 @@
|
||||
/* mdb_dump.c - memory-mapped database dump tool */
|
||||
/*
|
||||
* Copyright 2011-2014 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 "lmdb.h"
|
||||
|
||||
#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 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;
|
||||
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;
|
||||
|
||||
printf("VERSION=3\n");
|
||||
printf("format=%s\n", mode & PRINT ? "print" : "bytevalue");
|
||||
if (name)
|
||||
printf("database=%s\n", name);
|
||||
printf("type=btree\n");
|
||||
|
||||
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 (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);
|
||||
|
||||
envname = argv[optind];
|
||||
rc = mdb_env_create(&env);
|
||||
|
||||
if (alldbs || subname) {
|
||||
mdb_env_set_maxdbs(env, 2);
|
||||
}
|
||||
|
||||
rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 0664);
|
||||
if (rc) {
|
||||
printf("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) {
|
||||
printf("mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
|
||||
rc = mdb_open(txn, subname, 0, &dbi);
|
||||
if (rc) {
|
||||
printf("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) {
|
||||
printf("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);
|
||||
}
|
||||
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;
|
||||
}
|
77
libraries/liblmdb/mdb_load.1
Normal file
77
libraries/liblmdb/mdb_load.1
Normal file
@ -0,0 +1,77 @@
|
||||
.TH MDB_LOAD 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2014 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>
|
396
libraries/liblmdb/mdb_load.c
Normal file
396
libraries/liblmdb/mdb_load.c
Normal file
@ -0,0 +1,396 @@
|
||||
/* mdb_load.c - memory-mapped database load tool */
|
||||
/*
|
||||
* Copyright 2011-2014 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_val kbuf, dbuf;
|
||||
|
||||
#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 const char hexc[] = "0123456789abcdef";
|
||||
|
||||
static void readhdr()
|
||||
{
|
||||
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 %zd: 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 %zd: 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 %zd: unsupported type %s\n",
|
||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("type="));
|
||||
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 %zd: unexpected format\n",
|
||||
prog, lineno);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
*ptr = '\0';
|
||||
fprintf(stderr, "%s: line %zd: unrecognized keyword ignored: %s\n",
|
||||
prog, lineno, (char *)dbuf.mv_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void badend()
|
||||
{
|
||||
fprintf(stderr, "%s: line %zd: 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;
|
||||
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);
|
||||
|
||||
/* 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 %zd: out of memory, line too long\n",
|
||||
prog, lineno);
|
||||
return EOF;
|
||||
}
|
||||
c1 = buf->mv_data;
|
||||
c1 += buf->mv_size;
|
||||
if (fgets((char *)c1, buf->mv_size, stdin) == NULL) {
|
||||
eof = 1;
|
||||
badend();
|
||||
return EOF;
|
||||
}
|
||||
buf->mv_size *= 2;
|
||||
len = strlen((char *)c1);
|
||||
}
|
||||
c1 = c2 = buf->mv_data;
|
||||
len = strlen((char *)c1);
|
||||
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()
|
||||
{
|
||||
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;
|
||||
|
||||
prog = argv[0];
|
||||
|
||||
if (argc < 2) {
|
||||
usage(prog);
|
||||
}
|
||||
|
||||
/* -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(prog);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind != argc - 1)
|
||||
usage(prog);
|
||||
|
||||
envname = argv[optind];
|
||||
rc = mdb_env_create(&env);
|
||||
|
||||
mdb_env_set_maxdbs(env, 2);
|
||||
|
||||
rc = mdb_env_open(env, envname, envflags, 0664);
|
||||
if (rc) {
|
||||
printf("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);
|
||||
dbuf.mv_size = 4096;
|
||||
dbuf.mv_data = malloc(dbuf.mv_size);
|
||||
|
||||
while(!eof) {
|
||||
MDB_val key, data;
|
||||
int batch = 0;
|
||||
flags = 0;
|
||||
|
||||
if (!(mode & NOHDR))
|
||||
readhdr();
|
||||
|
||||
rc = mdb_txn_begin(env, NULL, 0, &txn);
|
||||
if (rc) {
|
||||
printf("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) {
|
||||
printf("mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto txn_abort;
|
||||
}
|
||||
|
||||
rc = mdb_cursor_open(txn, dbi, &mc);
|
||||
if (rc) {
|
||||
printf("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 %zd: txn_commit: %s\n",
|
||||
prog, lineno, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
rc = mdb_txn_begin(env, NULL, 0, &txn);
|
||||
if (rc) {
|
||||
printf("mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto env_close;
|
||||
}
|
||||
rc = mdb_cursor_open(txn, dbi, &mc);
|
||||
if (rc) {
|
||||
printf("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 %zd: 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,5 +1,5 @@
|
||||
.TH MDB_STAT 1 "2012/12/12" "LMDB 0.9.5"
|
||||
.\" Copyright 2012 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.TH MDB_STAT 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2012-2014 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_stat \- LMDB environment status tool
|
||||
@ -7,6 +7,8 @@ mdb_stat \- LMDB environment status tool
|
||||
.B mdb_stat
|
||||
.BR \ envpath
|
||||
[\c
|
||||
.BR \-V ]
|
||||
[\c
|
||||
.BR \-e ]
|
||||
[\c
|
||||
.BR \-f [ f [ f ]]]
|
||||
@ -23,6 +25,9 @@ The
|
||||
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
|
||||
|
@ -37,7 +37,7 @@ static void prstat(MDB_stat *ms)
|
||||
|
||||
static void usage(char *prog)
|
||||
{
|
||||
fprintf(stderr, "usage: %s dbpath [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb]\n", prog);
|
||||
fprintf(stderr, "usage: %s dbpath [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb]\n", prog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -64,10 +64,15 @@ int main(int argc, char *argv[])
|
||||
* -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, "aefnrs:")) != EOF) {
|
||||
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);
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <sys/types.h>
|
||||
#include "midl.h"
|
||||
|
||||
/** @defgroup internal MDB Internals
|
||||
/** @defgroup internal LMDB Internals
|
||||
* @{
|
||||
*/
|
||||
/** @defgroup idls ID List Management
|
||||
|
@ -1,5 +1,5 @@
|
||||
/** @file midl.h
|
||||
* @brief mdb ID List header file.
|
||||
* @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
|
||||
@ -32,7 +32,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup internal MDB Internals
|
||||
/** @defgroup internal LMDB Internals
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* mtest.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -11,7 +11,6 @@
|
||||
* top-level directory of the distribution or, alternatively, at
|
||||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
#define _XOPEN_SOURCE 500 /* srandom(), random() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
@ -36,13 +35,13 @@ int main(int argc,char * argv[])
|
||||
int *values;
|
||||
char sval[32] = "";
|
||||
|
||||
srandom(time(NULL));
|
||||
srand(time(NULL));
|
||||
|
||||
count = (random()%384) + 64;
|
||||
count = (rand()%384) + 64;
|
||||
values = (int *)malloc(count*sizeof(int));
|
||||
|
||||
for(i = 0;i<count;i++) {
|
||||
values[i] = random()%1024;
|
||||
values[i] = rand()%1024;
|
||||
}
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
@ -82,7 +81,7 @@ int main(int argc,char * argv[])
|
||||
|
||||
j=0;
|
||||
key.mv_data = sval;
|
||||
for (i= count - 1; i > -1; i-= (random()%5)) {
|
||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
||||
j++;
|
||||
txn=NULL;
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* mtest2.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -14,7 +14,6 @@
|
||||
|
||||
/* Just like mtest.c, but using a subDB instead of the main DB */
|
||||
|
||||
#define _XOPEN_SOURCE 500 /* srandom(), random() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
@ -38,13 +37,13 @@ int main(int argc,char * argv[])
|
||||
int *values;
|
||||
char sval[32] = "";
|
||||
|
||||
srandom(time(NULL));
|
||||
srand(time(NULL));
|
||||
|
||||
count = (random()%384) + 64;
|
||||
count = (rand()%384) + 64;
|
||||
values = (int *)malloc(count*sizeof(int));
|
||||
|
||||
for(i = 0;i<count;i++) {
|
||||
values[i] = random()%1024;
|
||||
values[i] = rand()%1024;
|
||||
}
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
@ -82,7 +81,7 @@ int main(int argc,char * argv[])
|
||||
|
||||
j=0;
|
||||
key.mv_data = sval;
|
||||
for (i= count - 1; i > -1; i-= (random()%5)) {
|
||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
||||
j++;
|
||||
txn=NULL;
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* mtest3.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -13,7 +13,6 @@
|
||||
*/
|
||||
|
||||
/* Tests for sorted duplicate DBs */
|
||||
#define _XOPEN_SOURCE 500 /* srandom(), random() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -39,15 +38,15 @@ int main(int argc,char * argv[])
|
||||
char sval[32];
|
||||
char kval[sizeof(int)];
|
||||
|
||||
srandom(time(NULL));
|
||||
srand(time(NULL));
|
||||
|
||||
memset(sval, 0, sizeof(sval));
|
||||
|
||||
count = (random()%384) + 64;
|
||||
count = (rand()%384) + 64;
|
||||
values = (int *)malloc(count*sizeof(int));
|
||||
|
||||
for(i = 0;i<count;i++) {
|
||||
values[i] = random()%1024;
|
||||
values[i] = rand()%1024;
|
||||
}
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
@ -87,7 +86,7 @@ int main(int argc,char * argv[])
|
||||
|
||||
j=0;
|
||||
|
||||
for (i= count - 1; i > -1; i-= (random()%5)) {
|
||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
||||
j++;
|
||||
txn=NULL;
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* mtest4.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -13,7 +13,6 @@
|
||||
*/
|
||||
|
||||
/* Tests for sorted duplicate DBs with fixed-size keys */
|
||||
#define _XOPEN_SOURCE 500 /* srandom(), random() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -123,7 +122,7 @@ int main(int argc,char * argv[])
|
||||
mdb_txn_abort(txn);
|
||||
j=0;
|
||||
|
||||
for (i= count - 1; i > -1; i-= (random()%3)) {
|
||||
for (i= count - 1; i > -1; i-= (rand()%3)) {
|
||||
j++;
|
||||
txn=NULL;
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* mtest5.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -13,7 +13,6 @@
|
||||
*/
|
||||
|
||||
/* Tests for sorted duplicate DBs using cursor_put */
|
||||
#define _XOPEN_SOURCE 500 /* srandom(), random() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -39,15 +38,15 @@ int main(int argc,char * argv[])
|
||||
char sval[32];
|
||||
char kval[sizeof(int)];
|
||||
|
||||
srandom(time(NULL));
|
||||
srand(time(NULL));
|
||||
|
||||
memset(sval, 0, sizeof(sval));
|
||||
|
||||
count = (random()%384) + 64;
|
||||
count = (rand()%384) + 64;
|
||||
values = (int *)malloc(count*sizeof(int));
|
||||
|
||||
for(i = 0;i<count;i++) {
|
||||
values[i] = random()%1024;
|
||||
values[i] = rand()%1024;
|
||||
}
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
@ -89,7 +88,7 @@ int main(int argc,char * argv[])
|
||||
|
||||
j=0;
|
||||
|
||||
for (i= count - 1; i > -1; i-= (random()%5)) {
|
||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
||||
j++;
|
||||
txn=NULL;
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* mtest6.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -13,7 +13,6 @@
|
||||
*/
|
||||
|
||||
/* Tests for DB splits and merges */
|
||||
#define _XOPEN_SOURCE 500 /* srandom(), random() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -41,7 +40,7 @@ int main(int argc,char * argv[])
|
||||
long kval;
|
||||
char *sval;
|
||||
|
||||
srandom(time(NULL));
|
||||
srand(time(NULL));
|
||||
|
||||
E(mdb_env_create(&env));
|
||||
E(mdb_env_set_mapsize(env, 10485760));
|
||||
@ -90,7 +89,7 @@ int main(int argc,char * argv[])
|
||||
#if 0
|
||||
j=0;
|
||||
|
||||
for (i= count - 1; i > -1; i-= (random()%5)) {
|
||||
for (i= count - 1; i > -1; i-= (rand()%5)) {
|
||||
j++;
|
||||
txn=NULL;
|
||||
E(mdb_txn_begin(env, NULL, 0, &txn));
|
||||
|
22
libraries/liblmdb/tooltag
Normal file
22
libraries/liblmdb/tooltag
Normal file
@ -0,0 +1,22 @@
|
||||
<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
Block a user