diff --git a/libraries/liblmdb/Makefile b/libraries/liblmdb/Makefile
index 60ab528..25c1095 100644
--- a/libraries/liblmdb/Makefile
+++ b/libraries/liblmdb/Makefile
@@ -17,7 +17,7 @@
# read mdb.c before changing any of them.
#
CC = gcc
-W = -W -Wall -Wno-unused-parameter -Wbad-function-cast
+W = -W -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized
THREADS = -pthread
OPT = -O2 -g
CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS)
diff --git a/libraries/liblmdb/lmdb.h b/libraries/liblmdb/lmdb.h
index b579179..0bc97cd 100644
--- a/libraries/liblmdb/lmdb.h
+++ b/libraries/liblmdb/lmdb.h
@@ -333,6 +333,15 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel
#define MDB_MULTIPLE 0x80000
/* @} */
+/** @defgroup mdb_copy Copy Flags
+ * @{
+ */
+/** Compacting copy: Omit free space from copy, and renumber all
+ * pages sequentially.
+ */
+#define MDB_CP_COMPACT 0x01
+/* @} */
+
/** @brief Cursor Get operations.
*
* This is the set of all operations for retrieving data
@@ -622,14 +631,10 @@ int mdb_env_copy(MDB_env *env, const char *path);
*/
int mdb_env_copyfd(MDB_env *env, mdb_filehandle_t fd);
- /** @brief Copy an LMDB environment to the specified path, with compaction.
+ /** @brief Copy an LMDB environment to the specified path, with options.
*
* This function may be used to make a backup of an existing environment.
- * No lockfile is created, since it gets recreated at need. Unlike
- * #mdb_env_copy(), which copies all pages from the environment, this
- * function trims freed/unused pages from the copy and reorders leaf
- * pages in sequential order. This function may execute more slowly
- * than #mdb_env_copy() and will use more CPU time.
+ * No lockfile is created, since it gets recreated at need.
* @note This call can trigger significant file size growth if run in
* parallel with write transactions, because it employs a read-only
* transaction. See long-lived transactions under @ref caveats_sec.
@@ -638,12 +643,20 @@ int mdb_env_copyfd(MDB_env *env, mdb_filehandle_t fd);
* @param[in] path The directory in which the copy will reside. This
* directory must already exist and be writable but must otherwise be
* empty.
+ * @param[in] flags Special options for this operation. This parameter
+ * must be set to 0 or by bitwise OR'ing together one or more of the
+ * values described here.
+ *
+ * - #MDB_CP_COMPACT - Perform compaction while copying: omit free
+ * pages and sequentially renumber all pages in output. This option
+ * consumes more CPU and runs more slowly than the default.
+ *
* @return A non-zero error value on failure and 0 on success.
*/
-int mdb_env_copy2(MDB_env *env, const char *path);
+int mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags);
/** @brief Copy an LMDB environment to the specified file descriptor,
- * with compaction.
+ * with options.
*
* This function may be used to make a backup of an existing environment.
* No lockfile is created, since it gets recreated at need. See
@@ -655,9 +668,11 @@ int mdb_env_copy2(MDB_env *env, const char *path);
* must have already been opened successfully.
* @param[in] fd The filedescriptor to write the copy to. It must
* have already been opened for Write access.
+ * @param[in] flags Special options for this operation.
+ * See #mdb_env_copy2() for options.
* @return A non-zero error value on failure and 0 on success.
*/
-int mdb_env_copyfd2(MDB_env *env, mdb_filehandle_t fd);
+int mdb_env_copyfd2(MDB_env *env, mdb_filehandle_t fd, unsigned int flags);
/** @brief Return statistics about the LMDB environment.
*
diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c
index 609eb92..5acdba4 100644
--- a/libraries/liblmdb/mdb.c
+++ b/libraries/liblmdb/mdb.c
@@ -8036,6 +8036,7 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
#define MDB_WBUF (1024*1024)
#endif
+ /** State needed for a compacting copy. */
typedef struct mdb_copy {
pthread_mutex_t mc_mutex;
pthread_cond_t mc_cond;
@@ -8050,8 +8051,10 @@ typedef struct mdb_copy {
int mc_status;
volatile int mc_new;
int mc_toggle;
+
} mdb_copy;
+ /** Dedicated writer thread for compacting copy. */
static THREAD_RET
mdb_env_copythr(void *arg)
{
@@ -8116,6 +8119,7 @@ again:
#undef DO_WRITE
}
+ /** Tell the writer thread there's a buffer ready to write */
static int
mdb_env_cthr_toggle(mdb_copy *my, int st)
{
@@ -8134,6 +8138,7 @@ mdb_env_cthr_toggle(mdb_copy *my, int st)
return 0;
}
+ /** Depth-first tree traversal for compacting copy. */
static int
mdb_env_cwalk(mdb_copy *my, pgno_t *pg, int flags)
{
@@ -8255,6 +8260,9 @@ again:
mc.mc_snum++;
mc.mc_ki[mc.mc_top] = 0;
if (IS_BRANCH(mp)) {
+ /* Whenever we advance to a sibling branch page,
+ * we must proceed all the way down to its first leaf.
+ */
mdb_page_copy(mc.mc_pg[mc.mc_top], mp, my->mc_env->me_psize);
goto again;
} else
@@ -8288,8 +8296,9 @@ done:
return rc;
}
-int
-mdb_env_copyfd2(MDB_env *env, HANDLE fd)
+ /** Copy environment with compaction. */
+static int
+mdb_env_copyfd1(MDB_env *env, HANDLE fd)
{
MDB_meta *mm;
MDB_page *mp;
@@ -8408,8 +8417,9 @@ leave:
return rc;
}
-int
-mdb_env_copyfd(MDB_env *env, HANDLE fd)
+ /** Copy environment as-is. */
+static int
+mdb_env_copyfd0(MDB_env *env, HANDLE fd)
{
MDB_txn *txn = NULL;
int rc;
@@ -8512,8 +8522,23 @@ leave:
return rc;
}
-static int
-mdb_env_copy0(MDB_env *env, const char *path, int flag)
+int
+mdb_env_copyfd2(MDB_env *env, HANDLE fd, unsigned int flags)
+{
+ if (flags & MDB_CP_COMPACT)
+ return mdb_env_copyfd1(env, fd);
+ else
+ return mdb_env_copyfd0(env, fd);
+}
+
+int
+mdb_env_copyfd(MDB_env *env, HANDLE fd)
+{
+ return mdb_env_copyfd2(env, fd, 0);
+}
+
+int
+mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags)
{
int rc, len;
char *lpath;
@@ -8558,10 +8583,7 @@ mdb_env_copy0(MDB_env *env, const char *path, int flag)
}
#endif
- if (flag)
- rc = mdb_env_copyfd2(env, newfd);
- else
- rc = mdb_env_copyfd(env, newfd);
+ rc = mdb_env_copyfd2(env, newfd, flags);
leave:
if (!(env->me_flags & MDB_NOSUBDIR))
@@ -8576,13 +8598,7 @@ leave:
int
mdb_env_copy(MDB_env *env, const char *path)
{
- return mdb_env_copy0(env, path, 0);
-}
-
-int
-mdb_env_copy2(MDB_env *env, const char *path)
-{
- return mdb_env_copy0(env, path, 1);
+ return mdb_env_copy2(env, path, 0);
}
int
diff --git a/libraries/liblmdb/mdb_copy.c b/libraries/liblmdb/mdb_copy.c
index 0814519..c54fefe 100644
--- a/libraries/liblmdb/mdb_copy.c
+++ b/libraries/liblmdb/mdb_copy.c
@@ -33,13 +33,13 @@ int main(int argc,char * argv[])
MDB_env *env;
const char *progname = argv[0], *act;
unsigned flags = MDB_RDONLY;
- int compact = 0;
+ unsigned cpflags = 0;
for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) {
if (argv[1][1] == 'n' && argv[1][2] == '\0')
flags |= MDB_NOSUBDIR;
else if (argv[1][1] == 'c' && argv[1][2] == '\0')
- compact = 1;
+ cpflags |= MDB_CP_COMPACT;
else if (argv[1][1] == 'V' && argv[1][2] == '\0') {
printf("%s\n", MDB_VERSION_STRING);
exit(0);
@@ -68,17 +68,10 @@ int main(int argc,char * argv[])
}
if (rc == MDB_SUCCESS) {
act = "copying";
- if (compact) {
- if (argc == 2)
- rc = mdb_env_copyfd2(env, MDB_STDOUT);
- else
- rc = mdb_env_copy2(env, argv[2]);
- } else {
- if (argc == 2)
- rc = mdb_env_copyfd(env, MDB_STDOUT);
- else
- rc = mdb_env_copy(env, argv[2]);
- }
+ if (argc == 2)
+ rc = mdb_env_copyfd2(env, MDB_STDOUT, cpflags);
+ else
+ rc = mdb_env_copy2(env, argv[2], cpflags);
}
if (rc)
fprintf(stderr, "%s: %s failed, error %d (%s)\n",