2007-10-11 18:01:43 +00:00
|
|
|
#if !defined(TOKUDB_COMMON_FUNCS_H)
|
|
|
|
#define TOKUDB_COMMON_FUNCS_H
|
2007-11-29 14:29:22 +00:00
|
|
|
|
|
|
|
/* -*- mode: C; c-basic-offset: 4 -*- */
|
|
|
|
#ident "Copyright (c) 2007 Tokutek Inc. All rights reserved."
|
|
|
|
|
2007-10-11 18:01:43 +00:00
|
|
|
#include "tokudb_common.h"
|
2007-10-17 01:24:30 +00:00
|
|
|
|
|
|
|
//DB_ENV->err disabled since it does not use db_strerror
|
2013-04-16 23:57:45 -04:00
|
|
|
#define PRINT_ERROR(retval, ...) \
|
2007-10-17 01:24:30 +00:00
|
|
|
if (0) g.dbenv->err(g.dbenv, retval, __VA_ARGS__); \
|
|
|
|
else { \
|
|
|
|
fprintf(stderr, "%s: %s:", g.progname, db_strerror(retval)); \
|
|
|
|
fprintf(stderr, __VA_ARGS__); \
|
2007-10-17 01:54:47 +00:00
|
|
|
fprintf(stderr, "\n"); \
|
2007-10-17 01:24:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//DB_ENV->err disabled since it does not use db_strerror, errx does not exist.
|
2013-04-16 23:57:45 -04:00
|
|
|
#define PRINT_ERRORX(...) \
|
2007-10-17 01:24:30 +00:00
|
|
|
if (0) g.dbenv->err(g.dbenv, 0, __VA_ARGS__); \
|
|
|
|
else { \
|
|
|
|
fprintf(stderr, "%s: ", g.progname); \
|
|
|
|
fprintf(stderr, __VA_ARGS__); \
|
2007-10-17 01:54:47 +00:00
|
|
|
fprintf(stderr, "\n"); \
|
2007-10-17 01:24:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int strtoint32 (char* str, int32_t* num, int32_t min, int32_t max, int base);
|
2008-07-21 18:00:38 +00:00
|
|
|
int strtouint32 (char* str, u_int32_t* num, u_int32_t min, u_int32_t max, int base);
|
2007-10-17 01:24:30 +00:00
|
|
|
int strtoint64 (char* str, int64_t* num, int64_t min, int64_t max, int base);
|
2008-07-21 18:00:38 +00:00
|
|
|
int strtouint64 (char* str, u_int64_t* num, u_int64_t min, u_int64_t max, int base);
|
2007-10-11 18:01:43 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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) \
|
2007-10-17 01:24:30 +00:00
|
|
|
int name(char* str, type* num, type min, type max, int base) \
|
2007-10-11 18:01:43 +00:00
|
|
|
{ \
|
|
|
|
char* test; \
|
|
|
|
bigtype value; \
|
|
|
|
\
|
|
|
|
assert(str); \
|
|
|
|
assert(num); \
|
|
|
|
assert(min <= max); \
|
2007-10-17 01:24:30 +00:00
|
|
|
assert(g.dbenv || g.progname); \
|
2007-10-11 18:01:43 +00:00
|
|
|
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) { \
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERRORX("%s: Invalid numeric argument\n", str); \
|
2007-10-11 18:01:43 +00:00
|
|
|
errno = EINVAL; \
|
|
|
|
goto error; \
|
|
|
|
} \
|
|
|
|
if (errno != 0) { \
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERROR(errno, "%s\n", str); \
|
2007-10-11 18:01:43 +00:00
|
|
|
} \
|
|
|
|
if (value < min) { \
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERRORX("%s: Less than minimum value (%" frmt ")\n", str, min); \
|
2007-10-11 18:01:43 +00:00
|
|
|
goto error; \
|
|
|
|
} \
|
|
|
|
if (value > max) { \
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERRORX("%s: Greater than maximum value (%" frmt ")\n", str, max); \
|
2007-10-11 18:01:43 +00:00
|
|
|
goto error; \
|
|
|
|
} \
|
|
|
|
*num = value; \
|
|
|
|
return EXIT_SUCCESS; \
|
|
|
|
error: \
|
|
|
|
return errno; \
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
DEF_STR_TO(strtoint32, int32_t, int64_t, strtoll, PRId32)
|
|
|
|
DEF_STR_TO(strtouint32, u_int32_t, u_int64_t, strtoull, PRIu32)
|
|
|
|
DEF_STR_TO(strtoint64, int64_t, int64_t, strtoll, PRId64)
|
|
|
|
DEF_STR_TO(strtouint64, u_int64_t, u_int64_t, strtoull, PRIu64)
|
2007-10-11 18:01:43 +00:00
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
static inline void
|
|
|
|
outputbyte(u_int8_t ch)
|
2007-10-11 18:01:43 +00:00
|
|
|
{
|
|
|
|
if (g.plaintext) {
|
|
|
|
if (ch == '\\') printf("\\\\");
|
|
|
|
else if (isprint(ch)) printf("%c", ch);
|
|
|
|
else printf("\\%02x", ch);
|
|
|
|
}
|
|
|
|
else printf("%02x", ch);
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
static inline void
|
|
|
|
outputstring(char* str)
|
2007-10-17 01:24:30 +00:00
|
|
|
{
|
|
|
|
char* p;
|
|
|
|
|
|
|
|
for (p = str; *p != '\0'; p++) {
|
2008-07-21 18:00:38 +00:00
|
|
|
outputbyte((u_int8_t)*p);
|
2007-10-17 01:24:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
static inline void
|
|
|
|
outputplaintextstring(char* str)
|
2007-10-17 01:24:30 +00:00
|
|
|
{
|
|
|
|
bool old_plaintext = g.plaintext;
|
|
|
|
g.plaintext = true;
|
|
|
|
outputstring(str);
|
|
|
|
g.plaintext = old_plaintext;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
static inline int
|
|
|
|
hextoint(int ch)
|
2007-10-17 01:24:30 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
static inline int
|
|
|
|
printabletocstring(char* inputstr, char** poutputstr)
|
2007-10-17 01:24:30 +00:00
|
|
|
{
|
|
|
|
char highch;
|
|
|
|
char lowch;
|
|
|
|
char nextch;
|
|
|
|
char* cstring;
|
|
|
|
|
|
|
|
assert(inputstr);
|
|
|
|
assert(poutputstr);
|
|
|
|
assert(*poutputstr == NULL);
|
|
|
|
|
2013-04-16 23:57:46 -04:00
|
|
|
cstring = (char*)toku_malloc((strlen(inputstr) + 1) * sizeof(char));
|
2007-10-17 01:24:30 +00:00
|
|
|
if (cstring == NULL) {
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERROR(errno, "printabletocstring");
|
2007-10-17 01:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (*poutputstr = cstring; *inputstr != '\0'; inputstr++) {
|
|
|
|
if (*inputstr == '\\') {
|
|
|
|
if ((highch = *++inputstr) == '\\') {
|
|
|
|
*cstring++ = '\\';
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (highch == '\0' || (lowch = *++inputstr) == '\0') {
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERROR(0, "unexpected end of input data or key/data pair");
|
2007-10-17 01:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (!isxdigit(highch)) {
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERROR(0, "Unexpected '%c' (non-hex) input.\n", highch);
|
2007-10-17 01:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (!isxdigit(lowch)) {
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERROR(0, "Unexpected '%c' (non-hex) input.\n", lowch);
|
2007-10-17 01:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2013-04-16 23:57:45 -04:00
|
|
|
nextch = (char)((hextoint(highch) << 4) | hextoint(lowch));
|
2007-10-17 01:24:30 +00:00
|
|
|
if (nextch == '\0') {
|
|
|
|
/* Database names are c strings, and cannot have extra NULL terminators. */
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERROR(0, "Unexpected '\\00' in input.\n");
|
2007-10-17 01:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
*cstring++ = nextch;
|
|
|
|
}
|
|
|
|
else *cstring++ = *inputstr;
|
|
|
|
}
|
|
|
|
/* Terminate the string. */
|
|
|
|
*cstring = '\0';
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
|
|
|
|
error:
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERROR(0, "Quitting out due to errors.\n");
|
2007-10-17 01:24:30 +00:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
static inline int
|
|
|
|
verify_library_version()
|
2007-10-17 01:24:30 +00:00
|
|
|
{
|
|
|
|
int major;
|
|
|
|
int minor;
|
|
|
|
|
|
|
|
db_version(&major, &minor, NULL);
|
|
|
|
if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR) {
|
2013-04-16 23:57:45 -04:00
|
|
|
PRINT_ERRORX("version %d.%d doesn't match library version %d.%d\n",
|
2007-10-17 01:24:30 +00:00
|
|
|
DB_VERSION_MAJOR, DB_VERSION_MINOR, major, minor);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-12-10 20:51:27 +00:00
|
|
|
static int last_caught = 0;
|
|
|
|
|
2013-04-16 23:57:46 -04:00
|
|
|
static void catch_signal(int which_signal) {
|
|
|
|
last_caught = which_signal;
|
2007-12-10 20:51:27 +00:00
|
|
|
if (last_caught == 0) last_caught = SIGINT;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
static inline void
|
|
|
|
init_catch_signals(void) {
|
2007-12-10 20:51:27 +00:00
|
|
|
signal(SIGINT, catch_signal);
|
|
|
|
signal(SIGTERM, catch_signal);
|
2013-04-16 23:57:45 -04:00
|
|
|
#ifdef SIGHUP
|
|
|
|
signal(SIGHUP, catch_signal);
|
|
|
|
#endif
|
|
|
|
#ifdef SIGPIPE
|
|
|
|
signal(SIGPIPE, catch_signal);
|
|
|
|
#endif
|
2007-12-10 20:51:27 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
static inline int
|
|
|
|
caught_any_signals(void) {
|
2007-12-10 20:51:27 +00:00
|
|
|
return last_caught != 0;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
static inline void
|
|
|
|
resend_signals(void) {
|
2007-12-10 20:51:27 +00:00
|
|
|
if (last_caught) {
|
|
|
|
signal(last_caught, SIG_DFL);
|
|
|
|
raise(last_caught);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:45 -04:00
|
|
|
#include <memory.h>
|
|
|
|
#if IS_TDB && (defined(_WIN32) || defined(_WIN64))
|
|
|
|
#include <ydb.h>
|
|
|
|
#endif
|
|
|
|
static int test_main (int argc, char *argv[]);
|
|
|
|
int
|
|
|
|
main(int argc, char *argv[]) {
|
|
|
|
int r;
|
|
|
|
#if IS_TDB && (defined(_WIN32) || defined(_WIN64))
|
|
|
|
//toku_ydb_init();
|
|
|
|
#endif
|
|
|
|
#if !IS_TDB && DB_VERSION_MINOR==4 && DB_VERSION_MINOR == 7
|
|
|
|
r = db_env_set_func_malloc(toku_malloc); assert(r==0);
|
|
|
|
r = db_env_set_func_free(toku_free); assert(r==0);
|
|
|
|
r = db_env_set_func_realloc(toku_realloc); assert(r==0);
|
|
|
|
#endif
|
|
|
|
r = test_main(argc, argv);
|
|
|
|
#if IS_TDB && (defined(_WIN32) || defined(_WIN64))
|
|
|
|
//toku_ydb_destroy();
|
|
|
|
#endif
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2007-10-11 18:01:43 +00:00
|
|
|
#endif /* #if !defined(TOKUDB_COMMON_H) */
|