mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 06:44:16 +01:00
Preliminary db_dump.
Ouputs without transactions, does not dump a header. git-svn-id: file:///svn/tokudb@441 c7de825b-a66e-492c-adef-691d508d4ae1
This commit is contained in:
parent
1955c4d541
commit
e215a35f09
6 changed files with 761 additions and 86 deletions
|
@ -7,7 +7,7 @@ BDB_LOAD=/usr/local/Berkeleydb.4.1/bin/db_load
|
|||
UTILS= \
|
||||
tokudb_gen \
|
||||
tokudb_load \
|
||||
# tokudb_dump \
|
||||
tokudb_dump \
|
||||
#End
|
||||
|
||||
.PHONY: all clean test test_gen test_gen_hex test_load
|
||||
|
|
|
@ -18,68 +18,4 @@ typedef uint8_t bool;
|
|||
|
||||
#define IS_POWER_OF_2(num) ((num) > 0 && ((num) & ((num) - 1)) == 0)
|
||||
|
||||
int strtoint32 (DB_ENV* dbenv, char* progname, char* str, int32_t* num, int32_t min, int32_t max, int base);
|
||||
int strtouint32 (DB_ENV* dbenv, char* progname, char* str, uint32_t* num, uint32_t min, uint32_t max, int base);
|
||||
int strtoint64 (DB_ENV* dbenv, char* progname, char* str, int64_t* num, int64_t min, int64_t max, int base);
|
||||
int strtouint64 (DB_ENV* dbenv, char* progname, char* str, uint64_t* num, uint64_t min, uint64_t max, int base);
|
||||
|
||||
/*
|
||||
* Convert a string to an integer of type "type".
|
||||
*
|
||||
*
|
||||
* Sets errno and returns:
|
||||
* EINVAL: str == NULL, num == NULL, or string not of the form [ \t]*[+-]?[0-9]+
|
||||
* ERANGE: value out of range specified. (Range of [min, max])
|
||||
*
|
||||
* *num is unchanged on error.
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
#define DEF_STR_TO(name, type, bigtype, strtofunc, frmt) \
|
||||
int name(DB_ENV* dbenv, char* progname, char* str, type* num, type min, type max, int base) \
|
||||
{ \
|
||||
char* test; \
|
||||
bigtype value; \
|
||||
\
|
||||
assert(str); \
|
||||
assert(num); \
|
||||
assert(min <= max); \
|
||||
assert(dbenv || progname); \
|
||||
assert(base == 0 || (base >= 2 && base <= 36)); \
|
||||
\
|
||||
errno = 0; \
|
||||
while (isspace(*str)) str++; \
|
||||
value = strtofunc(str, &test, base); \
|
||||
if ((*test != '\0' && *test != '\n') || test == str) { \
|
||||
if (dbenv == NULL) fprintf(stderr, "%s: %s: Invalid numeric argument\n", progname, str); \
|
||||
else dbenv->err(dbenv, 0, "%s: Invalid numeric argument", str); \
|
||||
errno = EINVAL; \
|
||||
goto error; \
|
||||
} \
|
||||
if (errno != 0) { \
|
||||
if (dbenv == NULL) fprintf(stderr, "%s: %s: %s\n", progname, str, strerror(errno)); \
|
||||
else dbenv->err(dbenv, errno, "%s", str); \
|
||||
goto error; \
|
||||
} \
|
||||
if (value < min) { \
|
||||
if (dbenv == NULL) fprintf(stderr, "%s: %s: Less than minimum value (%" frmt ")\n", progname, str, min); \
|
||||
else dbenv->err(dbenv, 0, "%s: Less than minimum value (%" frmt ")", str, min); \
|
||||
goto error; \
|
||||
} \
|
||||
if (value > max) { \
|
||||
if (dbenv == NULL) fprintf(stderr, "%s: %s: Greater than maximum value (%" frmt ")\n", progname, str, max); \
|
||||
else dbenv->err(dbenv, 0, "%s: Greater than maximum value (%" frmt ")", str, max); \
|
||||
goto error; \
|
||||
} \
|
||||
*num = value; \
|
||||
return EXIT_SUCCESS; \
|
||||
error: \
|
||||
return errno; \
|
||||
}
|
||||
|
||||
DEF_STR_TO(strtoint32, int32_t, int64_t, strtoll, "d");
|
||||
DEF_STR_TO(strtouint32, uint32_t, uint64_t, strtoull, "u");
|
||||
DEF_STR_TO(strtoint64, int64_t, int64_t, strtoll, "lld");
|
||||
DEF_STR_TO(strtouint64, uint64_t, uint64_t, strtoull, "llu");
|
||||
|
||||
#endif /* #if !defined(TOKUDB_COMMON_H) */
|
||||
|
|
79
utils/tokudb_common_funcs.h
Executable file
79
utils/tokudb_common_funcs.h
Executable file
|
@ -0,0 +1,79 @@
|
|||
#if !defined(TOKUDB_COMMON_FUNCS_H)
|
||||
|
||||
#define TOKUDB_COMMON_FUNCS_H
|
||||
#include "tokudb_common.h"
|
||||
int strtoint32 (DB_ENV* dbenv, char* progname, char* str, int32_t* num, int32_t min, int32_t max, int base);
|
||||
int strtouint32 (DB_ENV* dbenv, char* progname, char* str, uint32_t* num, uint32_t min, uint32_t max, int base);
|
||||
int strtoint64 (DB_ENV* dbenv, char* progname, char* str, int64_t* num, int64_t min, int64_t max, int base);
|
||||
int strtouint64 (DB_ENV* dbenv, char* progname, char* str, uint64_t* num, uint64_t min, uint64_t max, int base);
|
||||
|
||||
/*
|
||||
* Convert a string to an integer of type "type".
|
||||
*
|
||||
*
|
||||
* Sets errno and returns:
|
||||
* EINVAL: str == NULL, num == NULL, or string not of the form [ \t]*[+-]?[0-9]+
|
||||
* ERANGE: value out of range specified. (Range of [min, max])
|
||||
*
|
||||
* *num is unchanged on error.
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
#define DEF_STR_TO(name, type, bigtype, strtofunc, frmt) \
|
||||
int name(DB_ENV* dbenv, char* progname, char* str, type* num, type min, type max, int base) \
|
||||
{ \
|
||||
char* test; \
|
||||
bigtype value; \
|
||||
\
|
||||
assert(str); \
|
||||
assert(num); \
|
||||
assert(min <= max); \
|
||||
assert(dbenv || progname); \
|
||||
assert(base == 0 || (base >= 2 && base <= 36)); \
|
||||
\
|
||||
errno = 0; \
|
||||
while (isspace(*str)) str++; \
|
||||
value = strtofunc(str, &test, base); \
|
||||
if ((*test != '\0' && *test != '\n') || test == str) { \
|
||||
if (dbenv == NULL) fprintf(stderr, "%s: %s: Invalid numeric argument\n", progname, str); \
|
||||
else dbenv->err(dbenv, 0, "%s: Invalid numeric argument", str); \
|
||||
errno = EINVAL; \
|
||||
goto error; \
|
||||
} \
|
||||
if (errno != 0) { \
|
||||
if (dbenv == NULL) fprintf(stderr, "%s: %s: %s\n", progname, str, strerror(errno)); \
|
||||
else dbenv->err(dbenv, errno, "%s", str); \
|
||||
goto error; \
|
||||
} \
|
||||
if (value < min) { \
|
||||
if (dbenv == NULL) fprintf(stderr, "%s: %s: Less than minimum value (%" frmt ")\n", progname, str, min); \
|
||||
else dbenv->err(dbenv, 0, "%s: Less than minimum value (%" frmt ")", str, min); \
|
||||
goto error; \
|
||||
} \
|
||||
if (value > max) { \
|
||||
if (dbenv == NULL) fprintf(stderr, "%s: %s: Greater than maximum value (%" frmt ")\n", progname, str, max); \
|
||||
else dbenv->err(dbenv, 0, "%s: Greater than maximum value (%" frmt ")", str, max); \
|
||||
goto error; \
|
||||
} \
|
||||
*num = value; \
|
||||
return EXIT_SUCCESS; \
|
||||
error: \
|
||||
return errno; \
|
||||
}
|
||||
|
||||
DEF_STR_TO(strtoint32, int32_t, int64_t, strtoll, "d");
|
||||
DEF_STR_TO(strtouint32, uint32_t, uint64_t, strtoull, "u");
|
||||
DEF_STR_TO(strtoint64, int64_t, int64_t, strtoll, "lld");
|
||||
DEF_STR_TO(strtouint64, uint64_t, uint64_t, strtoull, "llu");
|
||||
|
||||
void outputbyte(uint8_t ch)
|
||||
{
|
||||
if (g.plaintext) {
|
||||
if (ch == '\\') printf("\\\\");
|
||||
else if (isprint(ch)) printf("%c", ch);
|
||||
else printf("\\%02x", ch);
|
||||
}
|
||||
else printf("%02x", ch);
|
||||
}
|
||||
|
||||
#endif /* #if !defined(TOKUDB_COMMON_H) */
|
|
@ -1,10 +1,666 @@
|
|||
#include "../include/db.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <db.h>
|
||||
#include "tokudb_common.h"
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
char *fname;
|
||||
assert(argc==2);
|
||||
fname = argv[1];
|
||||
|
||||
typedef struct {
|
||||
char* data[2];
|
||||
} gdbt;
|
||||
|
||||
typedef struct {
|
||||
char* data;
|
||||
} rhdr;
|
||||
|
||||
typedef struct {
|
||||
bool leadingspace;
|
||||
bool plaintext;
|
||||
bool header;
|
||||
bool keys;
|
||||
bool is_private;
|
||||
bool file_error;
|
||||
char* progname;
|
||||
char* homedir;
|
||||
char* database;
|
||||
char* subdatabase;
|
||||
char** config_options;
|
||||
int32_t version;
|
||||
int exitcode;
|
||||
DBTYPE dbtype;
|
||||
DB* db;
|
||||
DB_ENV* dbenv;
|
||||
struct {
|
||||
char* data[2];
|
||||
} dump_dbt;
|
||||
struct {
|
||||
char* data;
|
||||
} dump_header;
|
||||
} dump_globals;
|
||||
|
||||
dump_globals g;
|
||||
#include "tokudb_common_funcs.h"
|
||||
|
||||
int usage ();
|
||||
int longusage ();
|
||||
int dump_database ();
|
||||
int create_init_env();
|
||||
int dump_header ();
|
||||
int dump_footer ();
|
||||
int open_database ();
|
||||
int dump_pairs ();
|
||||
int apply_commandline_options();
|
||||
int close_database ();
|
||||
int hextoint (int ch);
|
||||
int doublechararray(char** pmem, uint64_t* size);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int ch;
|
||||
int retval;
|
||||
struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'H' },
|
||||
{ "plain_text", no_argument, NULL, 'T' },
|
||||
{ "Version", no_argument, NULL, 'V' },
|
||||
{ "config", required_argument, NULL, 'c' },
|
||||
{ "input_file", required_argument, NULL, 'f' },
|
||||
{ "home", required_argument, NULL, 'h' },
|
||||
{ "password", required_argument, NULL, 'p' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
char** next_config_option;
|
||||
|
||||
/* Set up the globals. */
|
||||
memset(&g, 0, sizeof(g));
|
||||
g.leadingspace = true;
|
||||
g.dbtype = DB_UNKNOWN;
|
||||
g.progname = argv[0];
|
||||
g.header = true;
|
||||
|
||||
next_config_option = g.config_options = (char**) calloc(argc, sizeof(char*));
|
||||
if (next_config_option == NULL) {
|
||||
fprintf(stderr, "%s: %s\n", g.progname, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
while ((ch = getopt_long_only(argc, argv, "HTVc:f:h:p:t:", options, NULL)) != EOF) {
|
||||
switch (ch) {
|
||||
case ('H'): {
|
||||
g.exitcode = longusage();
|
||||
goto cleanup;
|
||||
}
|
||||
case ('T'): {
|
||||
g.plaintext = true;
|
||||
g.leadingspace = false;
|
||||
g.header = false;
|
||||
break;
|
||||
}
|
||||
case ('V'): {
|
||||
fprintf(stderr, "%s: -%c option not supported.\n", g.progname, ch);
|
||||
goto error;
|
||||
}
|
||||
case ('c'): {
|
||||
*next_config_option++ = optarg;
|
||||
break;
|
||||
}
|
||||
case ('f'): {
|
||||
if (freopen(optarg, "w", stdout) == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: reopen: %s\n",
|
||||
g.progname, optarg, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ('h'): {
|
||||
g.homedir = optarg;
|
||||
break;
|
||||
}
|
||||
case ('p'): {
|
||||
/* Clear password. */
|
||||
memset(optarg, 0, strlen(optarg));
|
||||
fprintf(stderr, "%s: -%c option not supported.\n", g.progname, ch);
|
||||
goto error;
|
||||
}
|
||||
case ('?'):
|
||||
default: {
|
||||
g.exitcode = usage();
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 1) {
|
||||
g.exitcode = usage();
|
||||
goto cleanup;
|
||||
}
|
||||
//TODO: /* Handle possible interruptions/signals. */
|
||||
|
||||
g.database = argv[0];
|
||||
if (create_init_env() != 0) goto error;
|
||||
//TODO: Figure out how to dump multiple databases at once.
|
||||
if (dump_database() != 0) goto error;
|
||||
if (false) {
|
||||
error:
|
||||
g.exitcode = EXIT_FAILURE;
|
||||
fprintf(stderr, "%s: Quitting out due to errors.\n", g.progname);
|
||||
}
|
||||
cleanup:
|
||||
if (g.dbenv && (retval = g.dbenv->close(g.dbenv, 0)) != 0) {
|
||||
g.exitcode = EXIT_FAILURE;
|
||||
fprintf(stderr, "%s: dbenv->close: %s\n", g.progname, db_strerror(retval));
|
||||
}
|
||||
//TODO: /* Resend any caught signal. */
|
||||
if (g.config_options) free(g.config_options);
|
||||
if (g.subdatabase) free(g.subdatabase);
|
||||
// if (g.read_header.data) free(g.read_header.data);
|
||||
// if (g.get_dbt.data[0]) free(g.get_dbt.data[0]);
|
||||
// if (g.get_dbt.data[1]) free(g.get_dbt.data[1]);
|
||||
|
||||
return g.exitcode;
|
||||
}
|
||||
|
||||
int dump_database()
|
||||
{
|
||||
DB_ENV* dbenv = g.dbenv;
|
||||
int retval;
|
||||
|
||||
/* Create a database handle. */
|
||||
retval = db_create(&g.db, g.dbenv, 0);
|
||||
if (retval != 0) {
|
||||
dbenv->err(dbenv, retval, "db_create");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (apply_commandline_options() != 0) goto error;
|
||||
if (g.file_error) goto cleanup;
|
||||
|
||||
/*
|
||||
//TODO: Uncomment.. implement get_type, and verify the internal type is btree.
|
||||
if (g.dbtype == DB_UNKNOWN) {
|
||||
dbenv->err(dbenv, 0, "no database type specified");
|
||||
goto error;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
TODO: If/when supporting encryption
|
||||
if (g.password && (retval = db->set_flags(db, DB_ENCRYPT))) {
|
||||
dbenv->err(dbenv, ret, "DB->set_flags: DB_ENCRYPT");
|
||||
goto error;
|
||||
}
|
||||
*/
|
||||
//TODO: dump_header()
|
||||
if (open_database() != 0) goto error;
|
||||
if (dump_pairs() != 0) goto error;
|
||||
//TODO: dump_footer()
|
||||
if (g.file_error) goto cleanup;
|
||||
|
||||
if (false) {
|
||||
error:
|
||||
g.exitcode = EXIT_FAILURE;
|
||||
}
|
||||
cleanup:
|
||||
|
||||
if (close_database() != 0) g.exitcode = EXIT_FAILURE;
|
||||
|
||||
return g.exitcode;
|
||||
}
|
||||
|
||||
int usage()
|
||||
{
|
||||
printf("TODO: Implement %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
printf
|
||||
(
|
||||
"usage: %s [-ThHfF] [-d delimiter] [-s delimiter]\n"
|
||||
" -m minsize -M maxsize [-r random seed]\n"
|
||||
" (-n maxnumkeys | -N maxkibibytes) [-o filename]\n",
|
||||
g.progname
|
||||
);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int longusage()
|
||||
{
|
||||
printf("TODO: Implement %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int create_init_env()
|
||||
{
|
||||
int retval;
|
||||
DB_ENV* dbenv;
|
||||
int flags;
|
||||
//TODO: Experiments to determine right cache size for tokudb, or maybe command line argument.
|
||||
int cache = 1 << 20; /* 1 megabyte */
|
||||
|
||||
retval = db_env_create(&dbenv, 0);
|
||||
if (retval) {
|
||||
fprintf(stderr, "%s: db_dbenv_create: %s\n", g.progname, db_strerror(retval));
|
||||
goto error;
|
||||
}
|
||||
///TODO: UNCOMMENT/IMPLEMENT dbenv->set_errfile(dbenv, stderr);
|
||||
dbenv->set_errpfx(dbenv, g.progname);
|
||||
/*
|
||||
TODO: Anything for encryption?
|
||||
*/
|
||||
|
||||
/* Open the dbenvironment. */
|
||||
g.is_private = false;
|
||||
//flags = DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_USE_ENVIRON;
|
||||
flags = DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL; ///TODO: UNCOMMENT/IMPLEMENT | DB_USE_ENVIRON;
|
||||
//TODO: Transactions.. SET_BITS(flags, DB_INIT_TXN);
|
||||
|
||||
/*
|
||||
///TODO: UNCOMMENT/IMPLEMENT Notes: We require DB_PRIVATE
|
||||
if (!dbenv->open(dbenv, g.homedir, flags, 0)) goto success;
|
||||
*/
|
||||
|
||||
/*
|
||||
///TODO: UNCOMMENT/IMPLEMENT
|
||||
retval = dbenv->set_cachesize(dbenv, 0, cache, 1);
|
||||
if (retval) {
|
||||
dbenv->err(dbenv, retval, "DB_ENV->set_cachesize");
|
||||
goto error;
|
||||
}
|
||||
*/
|
||||
g.is_private = true;
|
||||
//TODO: Do we want to support transactions/logging even in single-process mode?
|
||||
//Maybe if the db already exists.
|
||||
//If db does not exist.. makes sense not to log or have transactions
|
||||
REMOVE_BITS(flags, DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN);
|
||||
SET_BITS(flags, DB_CREATE | DB_PRIVATE);
|
||||
|
||||
retval = dbenv->open(dbenv, g.homedir, flags, 0);
|
||||
if (retval) {
|
||||
dbenv->err(dbenv, retval, "DB_ENV->open");
|
||||
goto error;
|
||||
}
|
||||
success:
|
||||
g.dbenv = dbenv;
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
error:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int printabletocstring(char* inputstr, char** poutputstr)
|
||||
{
|
||||
char highch;
|
||||
char lowch;
|
||||
char nextch;
|
||||
char* cstring;
|
||||
DB_ENV* dbenv = g.dbenv;
|
||||
|
||||
|
||||
assert(inputstr);
|
||||
assert(poutputstr);
|
||||
assert(*poutputstr == NULL);
|
||||
|
||||
cstring = (char*)malloc((strlen(inputstr) + 1) * sizeof(char));
|
||||
if (cstring == NULL) {
|
||||
dbenv->err(dbenv, ENOMEM, "");
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (*poutputstr = cstring; *inputstr != '\0'; inputstr++) {
|
||||
if (*inputstr == '\\') {
|
||||
if ((highch = *++inputstr) == '\\') {
|
||||
*cstring++ = '\\';
|
||||
continue;
|
||||
}
|
||||
if (highch == '\0' || (lowch = *++inputstr) == '\0') {
|
||||
dbenv->err(dbenv, 0, "unexpected end of input data or key/data pair");
|
||||
goto error;
|
||||
}
|
||||
if (!isxdigit(highch)) {
|
||||
dbenv->err(dbenv, 0, "Unexpected '%c' (non-hex) input.\n", highch);
|
||||
goto error;
|
||||
}
|
||||
if (!isxdigit(lowch)) {
|
||||
dbenv->err(dbenv, 0, "Unexpected '%c' (non-hex) input.\n", lowch);
|
||||
goto error;
|
||||
}
|
||||
nextch = (hextoint(highch) << 4) | hextoint(lowch);
|
||||
if (nextch == '\0') {
|
||||
/* Database names are c strings, and cannot have extra NULL terminators. */
|
||||
dbenv->err(dbenv, 0, "Unexpected '\\00' in input.\n");
|
||||
goto error;
|
||||
}
|
||||
*cstring++ = nextch;
|
||||
}
|
||||
else *cstring++ = *inputstr;
|
||||
}
|
||||
/* Terminate the string. */
|
||||
*cstring = '\0';
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
error:
|
||||
dbenv->err(dbenv, 0, "Quitting out due to errors.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
///TODO: IMPLEMENT/Replace original line.
|
||||
#define PARSE_NUMBER(match, dbfunction) \
|
||||
if (!strcmp(field, match)) { \
|
||||
if (strtoint32(dbenv, NULL, value, &num, 1, INT32_MAX, 10)) goto error; \
|
||||
/*if ((retval = dbfunction(db, num)) != 0) goto printerror;*/ \
|
||||
continue; \
|
||||
}
|
||||
|
||||
///TODO: IMPLEMENT/Replace original line.
|
||||
#define PARSE_UNSUPPORTEDNUMBER(match, dbfunction) \
|
||||
if (!strcmp(field, match)) { \
|
||||
if (strtoint32(dbenv, NULL, value, &num, 1, INT32_MAX, 10)) goto error; \
|
||||
dbenv->err(dbenv, 0, "%s option not supported.\n", field); \
|
||||
goto error; \
|
||||
}
|
||||
|
||||
#define PARSE_FLAG(match, flag) \
|
||||
if (!strcmp(field, match)) { \
|
||||
if (strtoint32(dbenv, NULL, value, &num, 0, 1, 10)) { \
|
||||
dbenv->err(dbenv, 0, \
|
||||
"%s: boolean name=value pairs require a value of 0 or 1", \
|
||||
field); \
|
||||
goto error; \
|
||||
} \
|
||||
if ((retval = db->set_flags(db, flag)) != 0) { \
|
||||
dbenv->err(dbenv, retval, \
|
||||
"set_flags: %s", \
|
||||
field); \
|
||||
goto error; \
|
||||
} \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define PARSE_UNSUPPORTEDFLAG(match, flag) \
|
||||
if (!strcmp(field, match)) { \
|
||||
if (strtoint32(dbenv, NULL, value, &num, 0, 1, 10)) { \
|
||||
dbenv->err(dbenv, 0, \
|
||||
"%s: boolean name=value pairs require a value of 0 or 1", \
|
||||
field); \
|
||||
goto error; \
|
||||
} \
|
||||
dbenv->err(dbenv, 0, "%s option not supported.\n", field); \
|
||||
goto error; \
|
||||
}
|
||||
|
||||
#define PARSE_CHAR(match, dbfunction) \
|
||||
if (!strcmp(field, match)) { \
|
||||
if (strlen(value) != 1) { \
|
||||
dbenv->err(dbenv, 0, \
|
||||
"%s=%s: Expected 1-byte value", \
|
||||
field, value); \
|
||||
goto error; \
|
||||
} \
|
||||
if ((retval = dbfunction(db, value[0])) != 0) { \
|
||||
goto printerror; \
|
||||
} \
|
||||
continue; \
|
||||
}
|
||||
|
||||
int dump_header()
|
||||
{
|
||||
//TODO: All of this.. have not started.
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apply_commandline_options()
|
||||
{
|
||||
char** next_config_option = g.config_options;
|
||||
unsigned index;
|
||||
char* field;
|
||||
char* value = NULL;
|
||||
bool first;
|
||||
int ch;
|
||||
int32_t num;
|
||||
int retval;
|
||||
DB* db = g.db;
|
||||
DB_ENV* dbenv = g.dbenv;
|
||||
|
||||
assert(g.header);
|
||||
|
||||
for (index = 0; g.config_options[index]; index++) {
|
||||
if (value) {
|
||||
/* Restore the field=value format. */
|
||||
value[-1] = '=';
|
||||
value = NULL;
|
||||
}
|
||||
field = g.config_options[index];
|
||||
|
||||
if ((value = strchr(field, '=')) == NULL) {
|
||||
dbenv->err(dbenv, 0, "command-line configuration uses name=value format");
|
||||
goto error;
|
||||
}
|
||||
value[0] = '\0';
|
||||
value++;
|
||||
|
||||
if (field[0] == '\0' || value[0] == '\0') {
|
||||
dbenv->err(dbenv, 0, "command-line configuration uses name=value format");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!strcmp(field, "database") || !strcmp(field, "subdatabase")) {
|
||||
if (g.subdatabase != NULL) {
|
||||
free(g.subdatabase);
|
||||
g.subdatabase = NULL;
|
||||
}
|
||||
if ((retval = printabletocstring(value, &g.subdatabase))) {
|
||||
dbenv->err(dbenv, retval, "error reading db name");
|
||||
goto error;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(field, "keys")) {
|
||||
int32_t temp;
|
||||
if (strtoint32(dbenv, NULL, value, &temp, 0, 1, 10)) {
|
||||
dbenv->err(dbenv, 0,
|
||||
"%s: boolean name=value pairs require a value of 0 or 1",
|
||||
field);
|
||||
goto error;
|
||||
}
|
||||
g.keys = temp;
|
||||
if (!g.keys) {
|
||||
dbenv->err(dbenv, 0, "keys=0 not supported", field);
|
||||
goto error;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
///TODO: UNCOMMENT/IMPLEMENT
|
||||
PARSE_NUMBER( "bt_minkey", db->set_bt_minkey);
|
||||
PARSE_NUMBER( "db_lorder", db->set_lorder);
|
||||
PARSE_NUMBER( "db_pagesize", db->set_pagesize);
|
||||
PARSE_NUMBER( "re_len", db->set_re_len);
|
||||
PARSE_UNSUPPORTEDNUMBER("extentsize", db->set_q_extentsize);
|
||||
PARSE_UNSUPPORTEDNUMBER("h_ffactor", db->set_h_ffactor);
|
||||
PARSE_UNSUPPORTEDNUMBER("h_nelem", db->set_h_nelem);
|
||||
PARSE_CHAR( "re_pad", db->set_re_pad);
|
||||
PARSE_FLAG( "chksum", DB_CHKSUM_SHA1);
|
||||
PARSE_FLAG( "duplicates", DB_DUP);
|
||||
PARSE_FLAG( "dupsort", DB_DUPSORT);
|
||||
PARSE_FLAG( "recnum", DB_RECNUM);
|
||||
PARSE_UNSUPPORTEDFLAG( "renumber", DB_RENUMBER);
|
||||
*/
|
||||
|
||||
dbenv->err(dbenv, 0, "unknown input-file header configuration keyword \"%s\"", field);
|
||||
goto error;
|
||||
}
|
||||
if (value) {
|
||||
/* Restore the field=value format. */
|
||||
value[-1] = '=';
|
||||
value = NULL;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
if (false) {
|
||||
printerror:
|
||||
dbenv->err(dbenv, retval, "%s=%s", field, value);
|
||||
}
|
||||
error:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int open_database()
|
||||
{
|
||||
DB* db = g.db;
|
||||
DB_ENV* dbenv = g.dbenv;
|
||||
int retval;
|
||||
|
||||
int open_flags = DB_RDONLY;
|
||||
//TODO: Transaction auto commit stuff
|
||||
//if (TXN_ON(dbenv)) SET_BITS(open_flags, DB_AUTO_COMMIT);
|
||||
//TODO: First see if it exists.. THEN create it?
|
||||
retval = db->open(db, NULL, g.database, g.subdatabase, g.dbtype, open_flags, 0666);
|
||||
if (retval != 0) {
|
||||
dbenv->err(dbenv, retval, "DB->open: %s", g.database);
|
||||
goto error;
|
||||
}
|
||||
//TODO: Ensure we have enough cache to store some min number of btree pages.
|
||||
//NOTE: This may require closing db, environment, and creating new ones.
|
||||
|
||||
|
||||
/*
|
||||
///TODO: UNCOMMENT/IMPLEMENT
|
||||
DBTYPE existingtype;
|
||||
retval = db->get_type(db, &existingtype);
|
||||
if (retval != 0) {
|
||||
dbenv->err(dbenv, retval, "DB->get_type: %s", g.database);
|
||||
goto error;
|
||||
}
|
||||
assert(g.dbtype == DB_BTREE);
|
||||
if (existingtype != g.dbtype) {
|
||||
fprintf(stderr, "Existing database is not a dictionary (DB_BTREE).\n");
|
||||
goto error;
|
||||
}
|
||||
*/
|
||||
return EXIT_SUCCESS;
|
||||
error:
|
||||
fprintf(stderr, "Quitting out due to errors.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int hextoint(int ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
return ch - '0';
|
||||
}
|
||||
if (ch >= 'a' && ch <= 'z') {
|
||||
return ch - 'a' + 10;
|
||||
}
|
||||
if (ch >= 'A' && ch <= 'Z') {
|
||||
return ch - 'A' + 10;
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int doublechararray(char** pmem, uint64_t* size)
|
||||
{
|
||||
DB_ENV* dbenv = g.dbenv;
|
||||
|
||||
assert(pmem);
|
||||
assert(size);
|
||||
assert(IS_POWER_OF_2(*size));
|
||||
|
||||
*size <<= 1;
|
||||
if (*size == 0) {
|
||||
/* Overflowed uint64_t. */
|
||||
dbenv->err(dbenv, 0, "doublechararray\n");
|
||||
goto error;
|
||||
}
|
||||
if ((*pmem = (char*)realloc(*pmem, *size)) == NULL) {
|
||||
dbenv->err(dbenv, errno, "");
|
||||
goto error;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
error:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int dump_dbt(DBT* dbt)
|
||||
{
|
||||
char* str;
|
||||
uint32_t index;
|
||||
|
||||
assert(dbt);
|
||||
str = (char*)dbt->data;
|
||||
if (g.leadingspace) printf(" ");
|
||||
if (dbt->size > 0) {
|
||||
assert(dbt->data);
|
||||
for (index = 0; index < dbt->size; index++) {
|
||||
outputbyte(str[index]);
|
||||
if (ferror(stdout)) {
|
||||
perror("stdout");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
if (false) {
|
||||
error:
|
||||
g.exitcode = EXIT_FAILURE;
|
||||
}
|
||||
return g.exitcode;
|
||||
}
|
||||
|
||||
int dump_pairs()
|
||||
{
|
||||
int retval;
|
||||
size_t length;
|
||||
DBT key;
|
||||
DBT data;
|
||||
int spacech;
|
||||
DB* db = g.db;///////////////
|
||||
DB_ENV* dbenv = g.dbenv;
|
||||
DBC* dbc = NULL;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
if ((retval = db->cursor(db, (DB_TXN*)NULL, &dbc, 0)) != 0) {
|
||||
dbenv->err(dbenv, retval, "DB->cursor");
|
||||
goto error;
|
||||
}
|
||||
while ((retval = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0) {
|
||||
if (dump_dbt(&key) != 0) goto error;
|
||||
if (dump_dbt(&data) != 0) goto error;
|
||||
}
|
||||
if (retval != DB_NOTFOUND) {
|
||||
dbenv->err(dbenv, retval, "DBC->c_get");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
if (false) {
|
||||
error:
|
||||
g.exitcode = EXIT_FAILURE;
|
||||
}
|
||||
cleanup:
|
||||
if (dbc && (retval = dbc->c_close(dbc)) != 0) {
|
||||
dbenv->err(dbenv, retval, "DBC->c_close");
|
||||
g.exitcode = EXIT_FAILURE;
|
||||
}
|
||||
success:
|
||||
return g.exitcode;
|
||||
}
|
||||
|
||||
int close_database()
|
||||
{
|
||||
DB* db = g.db;
|
||||
DB_ENV* dbenv = g.dbenv;
|
||||
int retval;
|
||||
|
||||
assert(db);
|
||||
if ((retval = db->close(db, 0)) != 0) {
|
||||
dbenv->err(dbenv, retval, "DB->close");
|
||||
goto error;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
error:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
|
@ -14,14 +14,23 @@ extern int optopt;
|
|||
extern int opterr;
|
||||
extern int optreset;
|
||||
|
||||
typedef struct {
|
||||
bool plaintext;
|
||||
} gen_globals;
|
||||
|
||||
gen_globals g;
|
||||
#include "tokudb_common_funcs.h"
|
||||
|
||||
int usage(void);
|
||||
void generate_keys(void);
|
||||
int get_delimiter(char* str);
|
||||
|
||||
|
||||
|
||||
char dbt_delimiter = '\n';
|
||||
char sort_delimiter[2];
|
||||
char* progname;
|
||||
bool plaintext = false;
|
||||
|
||||
uint32_t lengthmin = 0;
|
||||
bool set_lengthmin = false;
|
||||
uint32_t lengthlimit = 0;
|
||||
|
@ -38,9 +47,13 @@ bool set_seed = false;
|
|||
bool printableonly = false;
|
||||
bool leadingspace = true;
|
||||
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
int ch;
|
||||
|
||||
/* Set up the globals. */
|
||||
memset(&g, 0, sizeof(g));
|
||||
|
||||
progname = argv[0];
|
||||
strcpy(sort_delimiter, "");
|
||||
|
||||
|
@ -67,14 +80,14 @@ int main (int argc, char *argv[]) {
|
|||
break;
|
||||
}
|
||||
case ('T'): {
|
||||
plaintext = true;
|
||||
g.plaintext = true;
|
||||
leadingspace = false;
|
||||
header = false;
|
||||
footer = false;
|
||||
break;
|
||||
}
|
||||
case ('p'): {
|
||||
plaintext = true;
|
||||
g.plaintext = true;
|
||||
leadingspace = true;
|
||||
break;
|
||||
}
|
||||
|
@ -239,7 +252,7 @@ int main (int argc, char *argv[]) {
|
|||
"type=btree\n"
|
||||
"db_pagesize=4096\n"
|
||||
"HEADER=END\n",
|
||||
plaintext ? "print" : "bytevalue");
|
||||
g.plaintext ? "print" : "bytevalue");
|
||||
}
|
||||
if (outputkeys) generate_keys();
|
||||
if (footer) printf("DATA=END\n");
|
||||
|
@ -283,16 +296,6 @@ int32_t random_below(int32_t limit)
|
|||
return random() % limit;
|
||||
}
|
||||
|
||||
void outputbyte(uint8_t ch)
|
||||
{
|
||||
if (plaintext) {
|
||||
if (ch == '\\') printf("\\\\");
|
||||
else if (isprint(ch)) printf("%c", ch);
|
||||
else printf("\\%02x", ch);
|
||||
}
|
||||
else printf("%02x", ch);
|
||||
}
|
||||
|
||||
void outputstring(char* str)
|
||||
{
|
||||
char* p;
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef struct {
|
|||
} load_globals;
|
||||
|
||||
load_globals g;
|
||||
#include "tokudb_common_funcs.h"
|
||||
|
||||
int usage ();
|
||||
int longusage ();
|
||||
|
@ -287,11 +288,11 @@ int create_init_env()
|
|||
/*
|
||||
///TODO: UNCOMMENT/IMPLEMENT
|
||||
retval = dbenv->set_cachesize(dbenv, 0, cache, 1);
|
||||
*/
|
||||
if (retval) {
|
||||
dbenv->err(dbenv, retval, "DB_ENV->set_cachesize");
|
||||
goto error;
|
||||
}
|
||||
*/
|
||||
g.is_private = true;
|
||||
//TODO: Do we want to support transactions/logging even in single-process mode?
|
||||
//Maybe if the db already exists.
|
||||
|
|
Loading…
Add table
Reference in a new issue