diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index fb57a72..983860f 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -7472,7 +7472,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; @@ -7865,7 +7865,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); diff --git a/libraries/liblmdb/mdb_load.1 b/libraries/liblmdb/mdb_load.1 index 998acc1..a2f8373 100644 --- a/libraries/liblmdb/mdb_load.1 +++ b/libraries/liblmdb/mdb_load.1 @@ -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 diff --git a/libraries/liblmdb/mdb_load.c b/libraries/liblmdb/mdb_load.c index 74d87b9..73788a3 100644 --- a/libraries/liblmdb/mdb_load.c +++ b/libraries/liblmdb/mdb_load.c @@ -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) @@ -275,10 +276,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; @@ -287,8 +293,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]; @@ -296,19 +303,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", @@ -367,11 +378,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 +405,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) { @@ -407,7 +429,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 +467,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; } }