]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
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>
Sat, 10 Oct 2020 12:10:34 +0000 (13:10 +0100)
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 cecd1da6dfbf056b9f15bfb1d506f5d327069636..f3aa3c07adb4c838e33f720916dc1aba388e6217 100644 (file)
@@ -7932,7 +7932,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;
@@ -8321,7 +8321,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 e25ff5a2b75775ed1a787c9b1741a37e43a67336..f897208846dc284ce177adb927baef27ac13037f 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 7888144a7e5098bc6a89b30196cf94d12bbf6160..3865e5a29071c1a51e40bfefe1a34299afe73043 100644 (file)
@@ -37,6 +37,7 @@ static int Eof;
 static MDB_envinfo info;
 
 static MDB_val kbuf, dbuf;
+static MDB_val k0buf;
 
 #define Yu     MDB_PRIy(u)
 
@@ -274,10 +275,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;
@@ -286,8 +292,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];
 
@@ -295,19 +302,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",
@@ -366,12 +377,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;
@@ -389,6 +404,12 @@ int main(int argc, char *argv[])
                        fprintf(stderr, "mdb_dbi_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) {
@@ -407,7 +428,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) {
@@ -432,6 +466,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;
                        }
                }