]> git.sur5r.net Git - openldap/commitdiff
Add mdb_env_copyfd()
authorHoward Chu <hyc@symas.com>
Thu, 30 May 2013 20:06:12 +0000 (13:06 -0700)
committerHoward Chu <hyc@symas.com>
Thu, 30 May 2013 20:06:12 +0000 (13:06 -0700)
Allow writing backup to an already opened file handle, for piping
to tar/gzip/ssh/whatever.

libraries/liblmdb/lmdb.h
libraries/liblmdb/mdb.c
libraries/liblmdb/mdb_copy.1
libraries/liblmdb/mdb_copy.c

index 53dab204614631953f47954398d70f44ea8a8642..9776366c7c8ca0584a09036fc1fddd4a4f8b14eb 100644 (file)
@@ -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()
index bc25bb39f07c00ce4d813c9b78bc034dfe73e4aa..eeb0540894ff51f1086e1b2775cd63c031f41244 100644 (file)
@@ -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);
 
index 2b3d421e78c93430e34f1204ece7c4d43f698111..b759f6878617f004da99f73d849a3d81789af141 100644 (file)
@@ -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
index bd0b85911083c5aa9a1e7dc9926552ae868646c3..a2ac4cc7c114ffdf453518843d25c2484c08a07f 100644 (file)
@@ -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));
        }