Rationalize mdb_env_copy2 API

incre
Howard Chu 11 years ago
parent 059b357d1a
commit 3e98addbe2
  1. 2
      libraries/liblmdb/Makefile
  2. 33
      libraries/liblmdb/lmdb.h
  3. 50
      libraries/liblmdb/mdb.c
  4. 15
      libraries/liblmdb/mdb_copy.c

@ -17,7 +17,7 @@
# read mdb.c before changing any of them. # read mdb.c before changing any of them.
# #
CC = gcc CC = gcc
W = -W -Wall -Wno-unused-parameter -Wbad-function-cast W = -W -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized
THREADS = -pthread THREADS = -pthread
OPT = -O2 -g OPT = -O2 -g
CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS) CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS)

@ -333,6 +333,15 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel
#define MDB_MULTIPLE 0x80000 #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. /** @brief Cursor Get operations.
* *
* This is the set of all operations for retrieving data * 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); 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. * This function may be used to make a backup of an existing environment.
* No lockfile is created, since it gets recreated at need. Unlike * No lockfile is created, since it gets recreated at need.
* #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.
* @note This call can trigger significant file size growth if run in * @note This call can trigger significant file size growth if run in
* parallel with write transactions, because it employs a read-only * parallel with write transactions, because it employs a read-only
* transaction. See long-lived transactions under @ref caveats_sec. * 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 * @param[in] path The directory in which the copy will reside. This
* directory must already exist and be writable but must otherwise be * directory must already exist and be writable but must otherwise be
* empty. * 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. * @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, /** @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. * This function may be used to make a backup of an existing environment.
* No lockfile is created, since it gets recreated at need. See * 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. * must have already been opened successfully.
* @param[in] fd The filedescriptor to write the copy to. It must * @param[in] fd The filedescriptor to write the copy to. It must
* have already been opened for Write access. * 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. * @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. /** @brief Return statistics about the LMDB environment.
* *

@ -8036,6 +8036,7 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
#define MDB_WBUF (1024*1024) #define MDB_WBUF (1024*1024)
#endif #endif
/** State needed for a compacting copy. */
typedef struct mdb_copy { typedef struct mdb_copy {
pthread_mutex_t mc_mutex; pthread_mutex_t mc_mutex;
pthread_cond_t mc_cond; pthread_cond_t mc_cond;
@ -8050,8 +8051,10 @@ typedef struct mdb_copy {
int mc_status; int mc_status;
volatile int mc_new; volatile int mc_new;
int mc_toggle; int mc_toggle;
} mdb_copy; } mdb_copy;
/** Dedicated writer thread for compacting copy. */
static THREAD_RET static THREAD_RET
mdb_env_copythr(void *arg) mdb_env_copythr(void *arg)
{ {
@ -8116,6 +8119,7 @@ again:
#undef DO_WRITE #undef DO_WRITE
} }
/** Tell the writer thread there's a buffer ready to write */
static int static int
mdb_env_cthr_toggle(mdb_copy *my, int st) mdb_env_cthr_toggle(mdb_copy *my, int st)
{ {
@ -8134,6 +8138,7 @@ mdb_env_cthr_toggle(mdb_copy *my, int st)
return 0; return 0;
} }
/** Depth-first tree traversal for compacting copy. */
static int static int
mdb_env_cwalk(mdb_copy *my, pgno_t *pg, int flags) mdb_env_cwalk(mdb_copy *my, pgno_t *pg, int flags)
{ {
@ -8255,6 +8260,9 @@ again:
mc.mc_snum++; mc.mc_snum++;
mc.mc_ki[mc.mc_top] = 0; mc.mc_ki[mc.mc_top] = 0;
if (IS_BRANCH(mp)) { 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); mdb_page_copy(mc.mc_pg[mc.mc_top], mp, my->mc_env->me_psize);
goto again; goto again;
} else } else
@ -8288,8 +8296,9 @@ done:
return rc; return rc;
} }
int /** Copy environment with compaction. */
mdb_env_copyfd2(MDB_env *env, HANDLE fd) static int
mdb_env_copyfd1(MDB_env *env, HANDLE fd)
{ {
MDB_meta *mm; MDB_meta *mm;
MDB_page *mp; MDB_page *mp;
@ -8408,8 +8417,9 @@ leave:
return rc; return rc;
} }
int /** Copy environment as-is. */
mdb_env_copyfd(MDB_env *env, HANDLE fd) static int
mdb_env_copyfd0(MDB_env *env, HANDLE fd)
{ {
MDB_txn *txn = NULL; MDB_txn *txn = NULL;
int rc; int rc;
@ -8512,8 +8522,23 @@ leave:
return rc; return rc;
} }
static int int
mdb_env_copy0(MDB_env *env, const char *path, int flag) 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; int rc, len;
char *lpath; char *lpath;
@ -8558,10 +8583,7 @@ mdb_env_copy0(MDB_env *env, const char *path, int flag)
} }
#endif #endif
if (flag) rc = mdb_env_copyfd2(env, newfd, flags);
rc = mdb_env_copyfd2(env, newfd);
else
rc = mdb_env_copyfd(env, newfd);
leave: leave:
if (!(env->me_flags & MDB_NOSUBDIR)) if (!(env->me_flags & MDB_NOSUBDIR))
@ -8576,13 +8598,7 @@ leave:
int int
mdb_env_copy(MDB_env *env, const char *path) mdb_env_copy(MDB_env *env, const char *path)
{ {
return mdb_env_copy0(env, path, 0); return mdb_env_copy2(env, path, 0);
}
int
mdb_env_copy2(MDB_env *env, const char *path)
{
return mdb_env_copy0(env, path, 1);
} }
int int

@ -33,13 +33,13 @@ int main(int argc,char * argv[])
MDB_env *env; MDB_env *env;
const char *progname = argv[0], *act; const char *progname = argv[0], *act;
unsigned flags = MDB_RDONLY; unsigned flags = MDB_RDONLY;
int compact = 0; unsigned cpflags = 0;
for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) { for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) {
if (argv[1][1] == 'n' && argv[1][2] == '\0') if (argv[1][1] == 'n' && argv[1][2] == '\0')
flags |= MDB_NOSUBDIR; flags |= MDB_NOSUBDIR;
else if (argv[1][1] == 'c' && argv[1][2] == '\0') 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') { else if (argv[1][1] == 'V' && argv[1][2] == '\0') {
printf("%s\n", MDB_VERSION_STRING); printf("%s\n", MDB_VERSION_STRING);
exit(0); exit(0);
@ -68,17 +68,10 @@ int main(int argc,char * argv[])
} }
if (rc == MDB_SUCCESS) { if (rc == MDB_SUCCESS) {
act = "copying"; act = "copying";
if (compact) {
if (argc == 2) if (argc == 2)
rc = mdb_env_copyfd2(env, MDB_STDOUT); rc = mdb_env_copyfd2(env, MDB_STDOUT, cpflags);
else else
rc = mdb_env_copy2(env, argv[2]); rc = mdb_env_copy2(env, argv[2], cpflags);
} else {
if (argc == 2)
rc = mdb_env_copyfd(env, MDB_STDOUT);
else
rc = mdb_env_copy(env, argv[2]);
}
} }
if (rc) if (rc)
fprintf(stderr, "%s: %s failed, error %d (%s)\n", fprintf(stderr, "%s: %s failed, error %d (%s)\n",

Loading…
Cancel
Save