]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#8662 Add -a append option to mdb_load
authorHoward Chu <hyc@openldap.org>
Wed, 20 Sep 2017 17:38:47 +0000 (18:38 +0100)
committerHoward Chu <hyc@openldap.org>
Thu, 28 Jan 2021 18:26:41 +0000 (18:26 +0000)
To allow reloading of custom-sorted DBs from mdb_dump

libraries/liblmdb/mdb.c
libraries/liblmdb/mdb_load.1
libraries/liblmdb/mdb_load.c

index e446bf854cf733b247d162cdd9d1077386b18e90..621cbcfa8ff5cb65dae643b97828e9e7ec2b76bc 100644 (file)
@@ -6597,7 +6597,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
 
        dkey.mv_size = 0;
 
-       if (flags == MDB_CURRENT) {
+       if (flags & MDB_CURRENT) {
                if (!(mc->mc_flags & C_INITIALIZED))
                        return EINVAL;
                rc = MDB_SUCCESS;
@@ -6992,7 +6992,7 @@ put_sub:
                        xdata.mv_size = 0;
                        xdata.mv_data = "";
                        leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
-                       if (flags & MDB_CURRENT) {
+                       if (flags == MDB_CURRENT) {
                                xflags = MDB_CURRENT|MDB_NOSPILL;
                        } else {
                                mdb_xcursor_init1(mc, leaf);
index 05e71c3a7639ce3a1cc523ed3b3519ced882d8c6..78439a14da66734a8c671df53440a940ba06c3a2 100644 (file)
@@ -37,6 +37,13 @@ option below.
 .BR \-V
 Write the library version number to the standard output, and exit.
 .TP
+.BR \-a
+Append all records in the order they appear in the input. The input is assumed to already be
+in correctly sorted order and no sorting or checking for redundant values will be performed.
+This option must be used to reload data that was produced by running
+.B mdb_dump
+on a database that uses custom compare functions.
+.TP
 .BR \-f \ file
 Read from the specified file instead of from the standard input.
 .TP
index 85a18a70be82fc6d424bf880213536096288dd2e..d2a3cec0870b61deb58e0d2d34b0b5905cde0b7d 100644 (file)
@@ -37,6 +37,7 @@ static int Eof;
 static MDB_envinfo info;
 
 static MDB_val kbuf, dbuf;
+static MDB_val k0buf;
 
 #ifdef _WIN32
 #define Z      "I"
@@ -278,10 +279,15 @@ badend:
 
 static void usage(void)
 {
-       fprintf(stderr, "usage: %s [-V] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog);
+       fprintf(stderr, "usage: %s [-V] [-a] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog);
        exit(EXIT_FAILURE);
 }
 
+static int greater(const MDB_val *a, const MDB_val *b)
+{
+       return 1;
+}
+
 int main(int argc, char *argv[])
 {
        int i, rc;
@@ -290,8 +296,9 @@ int main(int argc, char *argv[])
        MDB_cursor *mc;
        MDB_dbi dbi;
        char *envname;
-       int envflags = 0, putflags = 0;
-       int dohdr = 0;
+       int envflags = MDB_NOSYNC, putflags = 0;
+       int dohdr = 0, append = 0;
+       MDB_val prevk;
 
        prog = argv[0];
 
@@ -299,19 +306,23 @@ int main(int argc, char *argv[])
                usage();
        }
 
-       /* -f: load file instead of stdin
+       /* -a: append records in input order
+        * -f: load file instead of stdin
         * -n: use NOSUBDIR flag on env_open
         * -s: load into named subDB
         * -N: use NOOVERWRITE on puts
         * -T: read plaintext
         * -V: print version and exit
         */
-       while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) {
+       while ((i = getopt(argc, argv, "af:ns:NTV")) != EOF) {
                switch(i) {
                case 'V':
                        printf("%s\n", MDB_VERSION_STRING);
                        exit(0);
                        break;
+               case 'a':
+                       append = 1;
+                       break;
                case 'f':
                        if (freopen(optarg, "r", stdin) == NULL) {
                                fprintf(stderr, "%s: %s: reopen: %s\n",
@@ -370,11 +381,16 @@ int main(int argc, char *argv[])
        }
 
        kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2;
-       kbuf.mv_data = malloc(kbuf.mv_size);
+       kbuf.mv_data = malloc(kbuf.mv_size * 2);
+       k0buf.mv_size = kbuf.mv_size;
+       k0buf.mv_data = (char *)kbuf.mv_data + kbuf.mv_size;
+       prevk.mv_data = k0buf.mv_data;
 
        while(!Eof) {
                MDB_val key, data;
                int batch = 0;
+               flags = 0;
+               int appflag;
 
                if (!dohdr) {
                        dohdr = 1;
@@ -392,6 +408,12 @@ int main(int argc, char *argv[])
                        fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
                        goto txn_abort;
                }
+               prevk.mv_size = 0;
+               if (append) {
+                       mdb_set_compare(txn, dbi, greater);
+                       if (flags & MDB_DUPSORT)
+                               mdb_set_dupsort(txn, dbi, greater);
+               }
 
                rc = mdb_cursor_open(txn, dbi, &mc);
                if (rc) {
@@ -410,7 +432,20 @@ int main(int argc, char *argv[])
                                goto txn_abort;
                        }
 
-                       rc = mdb_cursor_put(mc, &key, &data, putflags);
+                       if (append) {
+                               appflag = MDB_APPEND;
+                               if (flags & MDB_DUPSORT) {
+                                       if (prevk.mv_size == key.mv_size && !memcmp(prevk.mv_data, key.mv_data, key.mv_size))
+                                               appflag = MDB_CURRENT|MDB_APPENDDUP;
+                                       else {
+                                               memcpy(prevk.mv_data, key.mv_data, key.mv_size);
+                                               prevk.mv_size = key.mv_size;
+                                       }
+                               }
+                       } else {
+                               appflag = 0;
+                       }
+                       rc = mdb_cursor_put(mc, &key, &data, putflags|appflag);
                        if (rc == MDB_KEYEXIST && putflags)
                                continue;
                        if (rc) {
@@ -435,6 +470,10 @@ int main(int argc, char *argv[])
                                        fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
                                        goto txn_abort;
                                }
+                               if (appflag & MDB_APPENDDUP) {
+                                       MDB_val k, d;
+                                       mdb_cursor_get(mc, &k, &d, MDB_LAST);
+                               }
                                batch = 0;
                        }
                }