2015-01-07 21:49:50 +08:00
|
|
|
/* mdb_load.c - memory-mapped database load tool */
|
2016-06-09 18:16:28 +08:00
|
|
|
|
2015-01-07 21:49:50 +08:00
|
|
|
/*
|
2016-06-09 18:16:28 +08:00
|
|
|
* Copyright (c) 2015,2016 Leonid Yuriev <leo@yuriev.ru>.
|
|
|
|
* Copyright (c) 2015,2016 Peter-Service R&D LLC.
|
|
|
|
*
|
|
|
|
* This file is part of ReOpenMDBX.
|
|
|
|
*
|
|
|
|
* ReOpenMDBX is free software; you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* ReOpenMDBX is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* ---
|
|
|
|
*
|
|
|
|
* Copyright 2011-2014 Howard Chu, Symas Corp.
|
2015-01-07 21:49:50 +08:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted only as authorized by the OpenLDAP
|
|
|
|
* Public License.
|
|
|
|
*
|
|
|
|
* A copy of this license is available in the file LICENSE in the
|
|
|
|
* top-level directory of the distribution or, alternatively, at
|
|
|
|
* <http://www.OpenLDAP.org/license.html>.
|
|
|
|
*/
|
2016-06-09 18:16:28 +08:00
|
|
|
|
2015-01-07 21:49:50 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <unistd.h>
|
2015-10-13 20:46:59 +08:00
|
|
|
#include "mdbx.h"
|
2015-01-07 21:49:50 +08:00
|
|
|
|
|
|
|
#define PRINT 1
|
|
|
|
#define NOHDR 2
|
|
|
|
static int mode;
|
|
|
|
|
|
|
|
static char *subname = NULL;
|
|
|
|
|
|
|
|
static size_t lineno;
|
|
|
|
static int version;
|
|
|
|
|
2015-09-01 04:47:37 +08:00
|
|
|
static int dbi_flags;
|
2015-01-07 21:49:50 +08:00
|
|
|
|
|
|
|
static char *prog;
|
|
|
|
|
|
|
|
static int Eof;
|
|
|
|
|
|
|
|
static MDB_envinfo info;
|
|
|
|
|
|
|
|
static MDB_val kbuf, dbuf;
|
|
|
|
|
|
|
|
#define STRLENOF(s) (sizeof(s)-1)
|
|
|
|
|
|
|
|
typedef struct flagbit {
|
|
|
|
int bit;
|
|
|
|
char *name;
|
|
|
|
int len;
|
|
|
|
} flagbit;
|
|
|
|
|
|
|
|
#define S(s) s, STRLENOF(s)
|
|
|
|
|
|
|
|
flagbit dbflags[] = {
|
|
|
|
{ MDB_REVERSEKEY, S("reversekey") },
|
|
|
|
{ MDB_DUPSORT, S("dupsort") },
|
|
|
|
{ MDB_INTEGERKEY, S("integerkey") },
|
|
|
|
{ MDB_DUPFIXED, S("dupfixed") },
|
|
|
|
{ MDB_INTEGERDUP, S("integerdup") },
|
|
|
|
{ MDB_REVERSEDUP, S("reversedup") },
|
|
|
|
{ 0, NULL, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static void readhdr(void)
|
|
|
|
{
|
|
|
|
char *ptr;
|
|
|
|
|
2015-09-01 04:47:37 +08:00
|
|
|
dbi_flags = 0;
|
2015-01-07 21:49:50 +08:00
|
|
|
while (fgets(dbuf.mv_data, dbuf.mv_size, stdin) != NULL) {
|
|
|
|
lineno++;
|
2015-09-01 04:19:35 +08:00
|
|
|
if (!strncmp(dbuf.mv_data, "db_pagesize=", STRLENOF("db_pagesize="))
|
|
|
|
|| !strncmp(dbuf.mv_data, "duplicates=", STRLENOF("duplicates="))) {
|
|
|
|
/* LY: silently ignore information fields. */
|
|
|
|
continue;
|
|
|
|
} else if (!strncmp(dbuf.mv_data, "VERSION=", STRLENOF("VERSION="))) {
|
2015-01-07 21:49:50 +08:00
|
|
|
version=atoi((char *)dbuf.mv_data+STRLENOF("VERSION="));
|
|
|
|
if (version > 3) {
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: unsupported VERSION %d\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno, version);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
} else if (!strncmp(dbuf.mv_data, "HEADER=END", STRLENOF("HEADER=END"))) {
|
|
|
|
break;
|
|
|
|
} else if (!strncmp(dbuf.mv_data, "format=", STRLENOF("format="))) {
|
|
|
|
if (!strncmp((char *)dbuf.mv_data+STRLENOF("FORMAT="), "print", STRLENOF("print")))
|
|
|
|
mode |= PRINT;
|
|
|
|
else if (strncmp((char *)dbuf.mv_data+STRLENOF("FORMAT="), "bytevalue", STRLENOF("bytevalue"))) {
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: unsupported FORMAT %s\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno, (char *)dbuf.mv_data+STRLENOF("FORMAT="));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
} else if (!strncmp(dbuf.mv_data, "database=", STRLENOF("database="))) {
|
|
|
|
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
|
|
|
if (ptr) *ptr = '\0';
|
|
|
|
if (subname) free(subname);
|
|
|
|
subname = strdup((char *)dbuf.mv_data+STRLENOF("database="));
|
|
|
|
} else if (!strncmp(dbuf.mv_data, "type=", STRLENOF("type="))) {
|
|
|
|
if (strncmp((char *)dbuf.mv_data+STRLENOF("type="), "btree", STRLENOF("btree"))) {
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: unsupported type %s\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno, (char *)dbuf.mv_data+STRLENOF("type="));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
} else if (!strncmp(dbuf.mv_data, "mapaddr=", STRLENOF("mapaddr="))) {
|
|
|
|
int i;
|
|
|
|
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
|
|
|
if (ptr) *ptr = '\0';
|
|
|
|
i = sscanf((char *)dbuf.mv_data+STRLENOF("mapaddr="), "%p", &info.me_mapaddr);
|
|
|
|
if (i != 1) {
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: invalid mapaddr %s\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapaddr="));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
} else if (!strncmp(dbuf.mv_data, "mapsize=", STRLENOF("mapsize="))) {
|
|
|
|
int i;
|
|
|
|
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
|
|
|
if (ptr) *ptr = '\0';
|
2016-05-30 21:27:59 +08:00
|
|
|
i = sscanf((char *)dbuf.mv_data+STRLENOF("mapsize="), "%zu", &info.me_mapsize);
|
2015-01-07 21:49:50 +08:00
|
|
|
if (i != 1) {
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: invalid mapsize %s\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapsize="));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
} else if (!strncmp(dbuf.mv_data, "maxreaders=", STRLENOF("maxreaders="))) {
|
|
|
|
int i;
|
|
|
|
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
|
|
|
if (ptr) *ptr = '\0';
|
|
|
|
i = sscanf((char *)dbuf.mv_data+STRLENOF("maxreaders="), "%u", &info.me_maxreaders);
|
|
|
|
if (i != 1) {
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: invalid maxreaders %s\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno, (char *)dbuf.mv_data+STRLENOF("maxreaders="));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int i;
|
|
|
|
for (i=0; dbflags[i].bit; i++) {
|
|
|
|
if (!strncmp(dbuf.mv_data, dbflags[i].name, dbflags[i].len) &&
|
|
|
|
((char *)dbuf.mv_data)[dbflags[i].len] == '=') {
|
2015-09-01 04:47:37 +08:00
|
|
|
if (((char *)dbuf.mv_data)[dbflags[i].len+1] == '1')
|
|
|
|
dbi_flags |= dbflags[i].bit;
|
2015-01-07 21:49:50 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!dbflags[i].bit) {
|
|
|
|
ptr = memchr(dbuf.mv_data, '=', dbuf.mv_size);
|
|
|
|
if (!ptr) {
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: unexpected format\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
} else {
|
|
|
|
*ptr = '\0';
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: unrecognized keyword ignored: %s\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno, (char *)dbuf.mv_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void badend(void)
|
|
|
|
{
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: unexpected end of input\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int unhex(unsigned char *c2)
|
|
|
|
{
|
|
|
|
int x, c;
|
|
|
|
x = *c2++ & 0x4f;
|
|
|
|
if (x & 0x40)
|
|
|
|
x -= 55;
|
|
|
|
c = x << 4;
|
|
|
|
x = *c2 & 0x4f;
|
|
|
|
if (x & 0x40)
|
|
|
|
x -= 55;
|
|
|
|
c |= x;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int readline(MDB_val *out, MDB_val *buf)
|
|
|
|
{
|
|
|
|
unsigned char *c1, *c2, *end;
|
2015-02-27 05:36:04 +08:00
|
|
|
size_t len, l2;
|
2015-01-07 21:49:50 +08:00
|
|
|
int c;
|
|
|
|
|
|
|
|
if (!(mode & NOHDR)) {
|
|
|
|
c = fgetc(stdin);
|
|
|
|
if (c == EOF) {
|
|
|
|
Eof = 1;
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
if (c != ' ') {
|
|
|
|
lineno++;
|
|
|
|
if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) {
|
|
|
|
badend:
|
|
|
|
Eof = 1;
|
|
|
|
badend();
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
if (c == 'D' && !strncmp(buf->mv_data, "ATA=END", STRLENOF("ATA=END")))
|
|
|
|
return EOF;
|
|
|
|
goto badend;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) {
|
|
|
|
Eof = 1;
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
lineno++;
|
|
|
|
|
|
|
|
c1 = buf->mv_data;
|
|
|
|
len = strlen((char *)c1);
|
2015-02-27 05:36:04 +08:00
|
|
|
l2 = len;
|
2015-01-07 21:49:50 +08:00
|
|
|
|
|
|
|
/* Is buffer too short? */
|
|
|
|
while (c1[len-1] != '\n') {
|
|
|
|
buf->mv_data = realloc(buf->mv_data, buf->mv_size*2);
|
|
|
|
if (!buf->mv_data) {
|
|
|
|
Eof = 1;
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: out of memory, line too long\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno);
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
c1 = buf->mv_data;
|
2015-02-27 05:36:04 +08:00
|
|
|
c1 += l2;
|
|
|
|
if (fgets((char *)c1, buf->mv_size+1, stdin) == NULL) {
|
2015-01-07 21:49:50 +08:00
|
|
|
Eof = 1;
|
|
|
|
badend();
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
buf->mv_size *= 2;
|
|
|
|
len = strlen((char *)c1);
|
2015-02-27 05:36:04 +08:00
|
|
|
l2 += len;
|
2015-01-07 21:49:50 +08:00
|
|
|
}
|
|
|
|
c1 = c2 = buf->mv_data;
|
2015-02-27 05:36:04 +08:00
|
|
|
len = l2;
|
2015-01-07 21:49:50 +08:00
|
|
|
c1[--len] = '\0';
|
|
|
|
end = c1 + len;
|
|
|
|
|
|
|
|
if (mode & PRINT) {
|
|
|
|
while (c2 < end) {
|
|
|
|
if (*c2 == '\\') {
|
|
|
|
if (c2[1] == '\\') {
|
|
|
|
c1++; c2 += 2;
|
|
|
|
} else {
|
|
|
|
if (c2+3 > end || !isxdigit(c2[1]) || !isxdigit(c2[2])) {
|
|
|
|
Eof = 1;
|
|
|
|
badend();
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
*c1++ = unhex(++c2);
|
|
|
|
c2 += 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
c1++; c2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* odd length not allowed */
|
|
|
|
if (len & 1) {
|
|
|
|
Eof = 1;
|
|
|
|
badend();
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
while (c2 < end) {
|
|
|
|
if (!isxdigit(*c2) || !isxdigit(c2[1])) {
|
|
|
|
Eof = 1;
|
|
|
|
badend();
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
*c1++ = unhex(c2);
|
|
|
|
c2 += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c2 = out->mv_data = buf->mv_data;
|
|
|
|
out->mv_size = c1 - c2;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void usage(void)
|
|
|
|
{
|
2015-10-01 01:11:20 +08:00
|
|
|
fprintf(stderr, "usage: %s [-V] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog);
|
2015-01-07 21:49:50 +08:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int i, rc;
|
|
|
|
MDB_env *env;
|
|
|
|
MDB_txn *txn;
|
|
|
|
MDB_cursor *mc;
|
|
|
|
MDB_dbi dbi;
|
|
|
|
char *envname;
|
|
|
|
int envflags = 0, putflags = 0;
|
|
|
|
|
|
|
|
prog = argv[0];
|
|
|
|
|
|
|
|
if (argc < 2) {
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -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) {
|
|
|
|
switch(i) {
|
|
|
|
case 'V':
|
|
|
|
printf("%s\n", MDB_VERSION_STRING);
|
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
if (freopen(optarg, "r", stdin) == NULL) {
|
|
|
|
fprintf(stderr, "%s: %s: reopen: %s\n",
|
|
|
|
prog, optarg, strerror(errno));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
envflags |= MDB_NOSUBDIR;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
subname = strdup(optarg);
|
|
|
|
break;
|
|
|
|
case 'N':
|
|
|
|
putflags = MDB_NOOVERWRITE|MDB_NODUPDATA;
|
|
|
|
break;
|
|
|
|
case 'T':
|
2015-11-22 09:15:14 +08:00
|
|
|
mode |= NOHDR | PRINT;
|
2015-01-07 21:49:50 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (optind != argc - 1)
|
|
|
|
usage();
|
|
|
|
|
|
|
|
dbuf.mv_size = 4096;
|
|
|
|
dbuf.mv_data = malloc(dbuf.mv_size);
|
|
|
|
|
|
|
|
if (!(mode & NOHDR))
|
|
|
|
readhdr();
|
|
|
|
|
|
|
|
envname = argv[optind];
|
|
|
|
rc = mdb_env_create(&env);
|
|
|
|
if (rc) {
|
|
|
|
fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
mdb_env_set_maxdbs(env, 2);
|
|
|
|
|
|
|
|
if (info.me_maxreaders)
|
|
|
|
mdb_env_set_maxreaders(env, info.me_maxreaders);
|
|
|
|
|
|
|
|
if (info.me_mapsize)
|
|
|
|
mdb_env_set_mapsize(env, info.me_mapsize);
|
|
|
|
|
|
|
|
if (info.me_mapaddr)
|
|
|
|
envflags |= MDB_FIXEDMAP;
|
|
|
|
|
|
|
|
rc = mdb_env_open(env, envname, envflags, 0664);
|
|
|
|
if (rc) {
|
|
|
|
fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
|
|
goto env_close;
|
|
|
|
}
|
|
|
|
|
|
|
|
kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2;
|
|
|
|
kbuf.mv_data = malloc(kbuf.mv_size);
|
|
|
|
|
|
|
|
while(!Eof) {
|
|
|
|
MDB_val key, data;
|
|
|
|
int batch = 0;
|
2015-01-16 03:06:04 +08:00
|
|
|
|
2015-01-07 21:49:50 +08:00
|
|
|
rc = mdb_txn_begin(env, NULL, 0, &txn);
|
|
|
|
if (rc) {
|
|
|
|
fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
|
|
goto env_close;
|
|
|
|
}
|
|
|
|
|
2015-09-01 04:47:37 +08:00
|
|
|
rc = mdb_open(txn, subname, dbi_flags|MDB_CREATE, &dbi);
|
2015-01-07 21:49:50 +08:00
|
|
|
if (rc) {
|
|
|
|
fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
|
|
goto txn_abort;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = mdb_cursor_open(txn, dbi, &mc);
|
|
|
|
if (rc) {
|
|
|
|
fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
|
|
goto txn_abort;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(1) {
|
|
|
|
rc = readline(&key, &kbuf);
|
2015-11-22 08:59:55 +08:00
|
|
|
if (rc) /* rc == EOF */
|
2015-01-07 21:49:50 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
rc = readline(&data, &dbuf);
|
2015-11-22 08:59:55 +08:00
|
|
|
if (rc) {
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: failed to read key value\n", prog, lineno);
|
2015-01-07 21:49:50 +08:00
|
|
|
goto txn_abort;
|
2015-11-22 08:59:55 +08:00
|
|
|
}
|
2015-01-16 03:06:04 +08:00
|
|
|
|
2015-01-07 21:49:50 +08:00
|
|
|
rc = mdb_cursor_put(mc, &key, &data, putflags);
|
|
|
|
if (rc == MDB_KEYEXIST && putflags)
|
|
|
|
continue;
|
2015-11-22 08:59:55 +08:00
|
|
|
if (rc) {
|
|
|
|
fprintf(stderr, "mdb_cursor_put failed, error %d %s\n", rc, mdb_strerror(rc));
|
2015-01-07 21:49:50 +08:00
|
|
|
goto txn_abort;
|
2015-11-22 08:59:55 +08:00
|
|
|
}
|
2015-01-07 21:49:50 +08:00
|
|
|
batch++;
|
|
|
|
if (batch == 100) {
|
|
|
|
rc = mdb_txn_commit(txn);
|
|
|
|
if (rc) {
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: txn_commit: %s\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno, mdb_strerror(rc));
|
|
|
|
goto env_close;
|
|
|
|
}
|
|
|
|
rc = mdb_txn_begin(env, NULL, 0, &txn);
|
|
|
|
if (rc) {
|
|
|
|
fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
|
|
goto env_close;
|
|
|
|
}
|
|
|
|
rc = mdb_cursor_open(txn, dbi, &mc);
|
|
|
|
if (rc) {
|
|
|
|
fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
|
|
|
goto txn_abort;
|
|
|
|
}
|
|
|
|
batch = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rc = mdb_txn_commit(txn);
|
|
|
|
txn = NULL;
|
|
|
|
if (rc) {
|
2016-05-30 21:27:59 +08:00
|
|
|
fprintf(stderr, "%s: line %zd: txn_commit: %s\n",
|
2015-01-07 21:49:50 +08:00
|
|
|
prog, lineno, mdb_strerror(rc));
|
|
|
|
goto env_close;
|
|
|
|
}
|
|
|
|
mdb_dbi_close(env, dbi);
|
2015-09-01 04:47:37 +08:00
|
|
|
if(!(mode & NOHDR))
|
|
|
|
readhdr();
|
2015-01-07 21:49:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
txn_abort:
|
|
|
|
mdb_txn_abort(txn);
|
|
|
|
env_close:
|
|
|
|
mdb_env_close(env);
|
|
|
|
|
|
|
|
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
|
|
}
|