Commit 3e98addb authored by Howard Chu's avatar Howard Chu
Browse files

Rationalize mdb_env_copy2 API

parent 059b357d
......@@ -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)
......
......@@ -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.
* <ul>
* <li>#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.
* </ul>
* @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.
*
......
......@@ -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
......
......@@ -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",
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment