mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-06 10:46:21 +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;
|
typedef mode_t mdb_mode_t;
|
||||||
#endif
|
#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
|
/** @defgroup mdb MDB API
|
||||||
* @{
|
* @{
|
||||||
* @brief OpenLDAP Lightning Memory-Mapped Database Manager
|
* @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);
|
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.
|
/** @brief Return statistics about the MDB environment.
|
||||||
*
|
*
|
||||||
* @param[in] env An environment handle returned by #mdb_env_create()
|
* @param[in] env An environment handle returned by #mdb_env_create()
|
||||||
|
@ -199,12 +199,6 @@ mdb_sem_wait(sem_t *sem)
|
|||||||
*/
|
*/
|
||||||
#define ErrCode() errno
|
#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.
|
/** A value for an invalid file handle.
|
||||||
* Mainly used to initialize file variables and signify that they are
|
* Mainly used to initialize file variables and signify that they are
|
||||||
* unused.
|
* unused.
|
||||||
@ -3631,60 +3625,20 @@ mdb_env_close0(MDB_env *env, int excl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
mdb_env_copy(MDB_env *env, const char *path)
|
mdb_env_copyfd(MDB_env *env, int fd)
|
||||||
{
|
{
|
||||||
MDB_txn *txn = NULL;
|
MDB_txn *txn = NULL;
|
||||||
int rc, len;
|
int rc;
|
||||||
size_t wsize;
|
size_t wsize;
|
||||||
char *lpath, *ptr;
|
char *ptr;
|
||||||
HANDLE newfd = INVALID_HANDLE_VALUE;
|
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
|
/* Do the lock/unlock of the reader mutex before starting the
|
||||||
* write txn. Otherwise other read txns could block writers.
|
* write txn. Otherwise other read txns could block writers.
|
||||||
*/
|
*/
|
||||||
rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
|
rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
return rc;
|
||||||
|
|
||||||
if (env->me_txns) {
|
if (env->me_txns) {
|
||||||
/* We must start the actual read txn after blocking writers */
|
/* We must start the actual read txn after blocking writers */
|
||||||
@ -3751,6 +3705,59 @@ mdb_env_copy(MDB_env *env, const char *path)
|
|||||||
|
|
||||||
leave:
|
leave:
|
||||||
mdb_txn_abort(txn);
|
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)
|
if (newfd != INVALID_HANDLE_VALUE)
|
||||||
close(newfd);
|
close(newfd);
|
||||||
|
|
||||||
|
@ -5,12 +5,18 @@
|
|||||||
mdb_copy \- LMDB environment copy tool
|
mdb_copy \- LMDB environment copy tool
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B mdb_copy
|
.B mdb_copy
|
||||||
.I srcpath\ dstpath
|
.I srcpath\ [dstpath]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
The
|
The
|
||||||
.B mdb_copy
|
.B mdb_copy
|
||||||
utility copies an LMDB environment. The environment can
|
utility copies an LMDB environment. The environment can
|
||||||
be copied regardless of whether it is currently in use.
|
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
|
.SH DIAGNOSTICS
|
||||||
Exit status is zero if no errors occur.
|
Exit status is zero if no errors occur.
|
||||||
Errors result in a non-zero exit status and
|
Errors result in a non-zero exit status and
|
||||||
|
@ -21,8 +21,8 @@ int main(int argc,char * argv[])
|
|||||||
MDB_env *env;
|
MDB_env *env;
|
||||||
char *envname = argv[1];
|
char *envname = argv[1];
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc<2 || argc>3) {
|
||||||
fprintf(stderr, "usage: %s srcpath dstpath\n", argv[0]);
|
fprintf(stderr, "usage: %s srcpath [dstpath]\n", argv[0]);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,10 @@ int main(int argc,char * argv[])
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
printf("mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
printf("mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||||
} else {
|
} 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)
|
if (rc)
|
||||||
printf("mdb_env_copy failed, error %d %s\n", rc, mdb_strerror(rc));
|
printf("mdb_env_copy failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user