mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
Add mdb_env_copyfd()
Allow writing backup to an already opened file handle, for piping to tar/gzip/ssh/whatever.
This commit is contained in:
parent
4b49291653
commit
c68e5ae9be
@ -144,6 +144,14 @@ typedef int mdb_mode_t;
|
||||
typedef mode_t mdb_mode_t;
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
/** An abstraction for a file handle.
|
||||
* On POSIX systems file handles are small integers. On Windows
|
||||
* they're opaque pointers.
|
||||
*/
|
||||
#define HANDLE int
|
||||
#endif
|
||||
|
||||
/** @defgroup mdb MDB API
|
||||
* @{
|
||||
* @brief OpenLDAP Lightning Memory-Mapped Database Manager
|
||||
@ -533,6 +541,17 @@ 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.
|
||||
*
|
||||
* This function may be used to make a backup of an existing environment.
|
||||
* @param[in] env An environment handle returned by #mdb_env_create(). It
|
||||
* 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.
|
||||
* @return A non-zero error value on failure and 0 on success.
|
||||
*/
|
||||
int mdb_env_copyfd(MDB_env *env, HANDLE fd);
|
||||
|
||||
/** @brief Return statistics about the MDB environment.
|
||||
*
|
||||
* @param[in] env An environment handle returned by #mdb_env_create()
|
||||
|
@ -199,12 +199,6 @@ mdb_sem_wait(sem_t *sem)
|
||||
*/
|
||||
#define ErrCode() errno
|
||||
|
||||
/** An abstraction for a file handle.
|
||||
* On POSIX systems file handles are small integers. On Windows
|
||||
* they're opaque pointers.
|
||||
*/
|
||||
#define HANDLE int
|
||||
|
||||
/** A value for an invalid file handle.
|
||||
* Mainly used to initialize file variables and signify that they are
|
||||
* unused.
|
||||
@ -3631,60 +3625,20 @@ mdb_env_close0(MDB_env *env, int excl)
|
||||
}
|
||||
|
||||
int
|
||||
mdb_env_copy(MDB_env *env, const char *path)
|
||||
mdb_env_copyfd(MDB_env *env, int fd)
|
||||
{
|
||||
MDB_txn *txn = NULL;
|
||||
int rc, len;
|
||||
int rc;
|
||||
size_t wsize;
|
||||
char *lpath, *ptr;
|
||||
char *ptr;
|
||||
HANDLE newfd = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (env->me_flags & MDB_NOSUBDIR) {
|
||||
lpath = (char *)path;
|
||||
} else {
|
||||
len = strlen(path);
|
||||
len += sizeof(DATANAME);
|
||||
lpath = malloc(len);
|
||||
if (!lpath)
|
||||
return ENOMEM;
|
||||
sprintf(lpath, "%s" DATANAME, path);
|
||||
}
|
||||
|
||||
/* The destination path must exist, but the destination file must not.
|
||||
* We don't want the OS to cache the writes, since the source data is
|
||||
* already in the OS cache.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
newfd = CreateFile(lpath, GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||
FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, NULL);
|
||||
#else
|
||||
newfd = open(lpath, O_WRONLY|O_CREAT|O_EXCL
|
||||
#ifdef O_DIRECT
|
||||
|O_DIRECT
|
||||
#endif
|
||||
, 0666);
|
||||
#endif
|
||||
if (!(env->me_flags & MDB_NOSUBDIR))
|
||||
free(lpath);
|
||||
if (newfd == INVALID_HANDLE_VALUE) {
|
||||
rc = ErrCode();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
#ifdef F_NOCACHE /* __APPLE__ */
|
||||
rc = fcntl(newfd, F_NOCACHE, 1);
|
||||
if (rc) {
|
||||
rc = ErrCode();
|
||||
goto leave;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Do the lock/unlock of the reader mutex before starting the
|
||||
* write txn. Otherwise other read txns could block writers.
|
||||
*/
|
||||
rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
|
||||
if (rc)
|
||||
goto leave;
|
||||
return rc;
|
||||
|
||||
if (env->me_txns) {
|
||||
/* We must start the actual read txn after blocking writers */
|
||||
@ -3751,6 +3705,59 @@ mdb_env_copy(MDB_env *env, const char *path)
|
||||
|
||||
leave:
|
||||
mdb_txn_abort(txn);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
mdb_env_copy(MDB_env *env, const char *path)
|
||||
{
|
||||
int rc, len;
|
||||
char *lpath;
|
||||
HANDLE newfd = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (env->me_flags & MDB_NOSUBDIR) {
|
||||
lpath = (char *)path;
|
||||
} else {
|
||||
len = strlen(path);
|
||||
len += sizeof(DATANAME);
|
||||
lpath = malloc(len);
|
||||
if (!lpath)
|
||||
return ENOMEM;
|
||||
sprintf(lpath, "%s" DATANAME, path);
|
||||
}
|
||||
|
||||
/* The destination path must exist, but the destination file must not.
|
||||
* We don't want the OS to cache the writes, since the source data is
|
||||
* already in the OS cache.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
newfd = CreateFile(lpath, GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||
FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, NULL);
|
||||
#else
|
||||
newfd = open(lpath, O_WRONLY|O_CREAT|O_EXCL
|
||||
#ifdef O_DIRECT
|
||||
|O_DIRECT
|
||||
#endif
|
||||
, 0666);
|
||||
#endif
|
||||
if (!(env->me_flags & MDB_NOSUBDIR))
|
||||
free(lpath);
|
||||
if (newfd == INVALID_HANDLE_VALUE) {
|
||||
rc = ErrCode();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
#ifdef F_NOCACHE /* __APPLE__ */
|
||||
rc = fcntl(newfd, F_NOCACHE, 1);
|
||||
if (rc) {
|
||||
rc = ErrCode();
|
||||
goto leave;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = mdb_env_copyfd(env, newfd);
|
||||
|
||||
leave:
|
||||
if (newfd != INVALID_HANDLE_VALUE)
|
||||
close(newfd);
|
||||
|
||||
|
@ -5,12 +5,18 @@
|
||||
mdb_copy \- LMDB environment copy tool
|
||||
.SH SYNOPSIS
|
||||
.B mdb_copy
|
||||
.I srcpath\ dstpath
|
||||
.I srcpath\ [dstpath]
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.B mdb_copy
|
||||
utility copies an LMDB environment. The environment can
|
||||
be copied regardless of whether it is currently in use.
|
||||
|
||||
If
|
||||
.I dstpath
|
||||
is specified it must be the path of an empty directory
|
||||
for storing the backup. Otherwise, the backup will be
|
||||
written to stdout.
|
||||
.SH DIAGNOSTICS
|
||||
Exit status is zero if no errors occur.
|
||||
Errors result in a non-zero exit status and
|
||||
|
@ -21,8 +21,8 @@ int main(int argc,char * argv[])
|
||||
MDB_env *env;
|
||||
char *envname = argv[1];
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "usage: %s srcpath dstpath\n", argv[0]);
|
||||
if (argc<2 || argc>3) {
|
||||
fprintf(stderr, "usage: %s srcpath [dstpath]\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -32,7 +32,10 @@ int main(int argc,char * argv[])
|
||||
if (rc) {
|
||||
printf("mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
} else {
|
||||
rc = mdb_env_copy(env, argv[2]);
|
||||
if (argc == 2)
|
||||
rc = mdb_env_copyfd(env, 1);
|
||||
else
|
||||
rc = mdb_env_copy(env, argv[2]);
|
||||
if (rc)
|
||||
printf("mdb_env_copy failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user