/*************************************************************************************************
* The test cases of the C language binding
* Copyright (C) 2009-2012 FAL Labs
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include
#define RECBUFSIZ 64 /* buffer size for a record */
#define RECBUFSIZL 1024 /* buffer size for a long record */
#if !defined(TRUE)
#define TRUE 1 /* boolean true */
#endif
#if !defined(FALSE)
#define FALSE 0 /* boolean false */
#endif
typedef struct { /* arguments of visitor */
int64_t rnum;
int32_t rnd;
int64_t cnt;
char rbuf[RECBUFSIZ];
} VISARG;
/* global variables */
const char* g_progname; /* program name */
/* function prototypes */
int main(int argc, char** argv);
static void usage(void);
static int64_t myrand(int64_t range);
static void oprintf(const char* format, ...);
static void oputchar(char c);
static void eprintf(const char* format, ...);
static void dberrprint(KCDB* db, int32_t line, const char* func);
static void idxerrprint(KCIDX* idx, int32_t line, const char* func);
static void dbmetaprint(KCDB* db, int32_t verbose);
static void idxmetaprint(KCIDX* idx, int32_t verbose);
const char* visitfull(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp, void* opq);
static int32_t runorder(int argc, char** argv);
static int32_t runindex(int argc, char** argv);
static int32_t runmap(int argc, char** argv);
static int32_t runlist(int argc, char** argv);
static int32_t procorder(const char* path, int64_t rnum, int32_t rnd, int32_t etc,
int32_t tran, int32_t oflags);
static int32_t procindex(const char* path, int64_t rnum, int32_t rnd, int32_t etc,
int32_t oflags);
static int32_t procmap(int64_t rnum, int32_t rnd, int32_t etc, int64_t bnum);
static int32_t proclist(int64_t rnum, int32_t rnd, int32_t etc);
/* main routine */
int main(int argc, char **argv) {
int32_t i, rv;
g_progname = argv[0];
srand(time(NULL));
if (argc < 2) usage();
rv = 0;
if (!strcmp(argv[1], "order")) {
rv = runorder(argc, argv);
} else if (!strcmp(argv[1], "index")) {
rv = runindex(argc, argv);
} else if (!strcmp(argv[1], "map")) {
rv = runmap(argc, argv);
} else if (!strcmp(argv[1], "list")) {
rv = runlist(argc, argv);
} else {
usage();
}
if (rv != 0) {
oprintf("FAILED:");
for (i = 0; i < argc; i++) {
oprintf(" %s", argv[i]);
}
oprintf("\n\n");
}
return rv;
}
/* print the usage and exit */
static void usage() {
eprintf("%s: test cases of the C binding of Kyoto Cabinet\n", g_progname);
eprintf("\n");
eprintf("usage:\n");
eprintf(" %s order [-rnd] [-etc] [-tran] [-oat|-oas|-onl|-otl|-onr] path rnum\n",
g_progname);
eprintf(" %s index [-rnd] [-etc] [-oat|-oas|-onl|-otl|-onr] path rnum\n", g_progname);
eprintf(" %s map [-rnd] [-etc] [-bnum num] rnum\n", g_progname);
eprintf(" %s list [-rnd] [-etc] rnum\n", g_progname);
eprintf("\n");
exit(1);
}
/* get a random number */
static int64_t myrand(int64_t range) {
uint64_t base, mask;
if (range < 2) return 0;
base = range * (rand() / (RAND_MAX + 1.0));
mask = (uint64_t)rand() << 30;
mask += (uint64_t)rand() >> 2;
return (base ^ mask) % range;
}
/* print formatted error string and flush the buffer */
static void oprintf(const char* format, ...) {
va_list ap;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
fflush(stdout);
}
/* print a character and flush the buffer */
static void oputchar(char c) {
putchar(c);
fflush(stdout);
}
/* print formatted error string and flush the buffer */
static void eprintf(const char* format, ...) {
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fflush(stderr);
}
/* print error message of database */
static void dberrprint(KCDB* db, int32_t line, const char* func) {
char* path;
const char* emsg;
int32_t ecode;
path = kcdbpath(db);
ecode = kcdbecode(db);
emsg = kcdbemsg(db);
oprintf("%s: %d: %s: %s: %d: %s: %s\n",
g_progname, line, func, path ? path : "-", ecode, kcecodename(ecode), emsg);
kcfree(path);
}
/* print error message of database */
static void idxerrprint(KCIDX* idx, int32_t line, const char* func) {
dberrprint(kcidxrevealinnerdb(idx), line, func);
}
/* print members of database */
static void dbmetaprint(KCDB* db, int32_t verbose) {
char* status, *rp;
if (verbose) {
status = kcdbstatus(db);
if (status) {
rp = status;
while (*rp != '\0') {
if (*rp == '\t') {
printf(": ");
} else {
putchar(*rp);
}
rp++;
}
kcfree(status);
}
} else {
oprintf("count: %ld\n", (long)kcdbcount(db));
oprintf("size: %ld\n", (long)kcdbsize(db));
}
}
/* print members of database */
static void idxmetaprint(KCIDX* idx, int32_t verbose) {
dbmetaprint(kcidxrevealinnerdb(idx), verbose);
}
/* visit a full record */
const char* visitfull(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp, void* opq) {
VISARG* arg;
const char* rv;
arg = opq;
arg->cnt++;
rv = KCVISNOP;
switch (arg->rnd ? myrand(7) : arg->cnt % 7) {
case 0: {
rv = arg->rbuf;
*sp = arg->rnd ? (size_t)myrand(sizeof(arg->rbuf)) :
sizeof(arg->rbuf) / (arg->cnt % 5 + 1);
break;
}
case 1: {
rv = KCVISREMOVE;
break;
}
}
if (arg->rnum > 250 && arg->cnt % (arg->rnum / 250) == 0) {
oputchar('.');
if (arg->cnt == arg->rnum || arg->cnt % (arg->rnum / 10) == 0)
oprintf(" (%08ld)\n", (long)arg->cnt);
}
return rv;
}
/* parse arguments of order command */
static int32_t runorder(int argc, char** argv) {
int32_t argbrk = FALSE;
const char* path, *rstr;
int32_t rnd, etc, tran, mode, oflags, i;
int64_t rnum;
path = NULL;
rstr = NULL;
rnd = FALSE;
etc = FALSE;
mode = 0;
tran = FALSE;
oflags = 0;
for (i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!strcmp(argv[i], "--")) {
argbrk = TRUE;
} else if (!strcmp(argv[i], "-rnd")) {
rnd = TRUE;
} else if (!strcmp(argv[i], "-etc")) {
etc = TRUE;
} else if (!strcmp(argv[i], "-tran")) {
tran = TRUE;
} else if (!strcmp(argv[i], "-oat")) {
oflags |= KCOAUTOTRAN;
} else if (!strcmp(argv[i], "-oas")) {
oflags |= KCOAUTOSYNC;
} else if (!strcmp(argv[i], "-onl")) {
oflags |= KCONOLOCK;
} else if (!strcmp(argv[i], "-otl")) {
oflags |= KCOTRYLOCK;
} else if (!strcmp(argv[i], "-onr")) {
oflags |= KCONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = TRUE;
path = argv[i];
} else if (!rstr) {
rstr = argv[i];
} else {
usage();
}
}
if (!path || !rstr) usage();
rnum = kcatoix(rstr);
if (rnum < 1) usage();
return procorder(path, rnum, rnd, etc, tran, oflags);
}
/* parse arguments of index command */
static int32_t runindex(int argc, char** argv) {
int32_t argbrk = FALSE;
const char* path, *rstr;
int32_t rnd, etc, mode, oflags, i;
int64_t rnum;
path = NULL;
rstr = NULL;
rnd = FALSE;
etc = FALSE;
mode = 0;
oflags = 0;
for (i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!strcmp(argv[i], "--")) {
argbrk = TRUE;
} else if (!strcmp(argv[i], "-rnd")) {
rnd = TRUE;
} else if (!strcmp(argv[i], "-etc")) {
etc = TRUE;
} else if (!strcmp(argv[i], "-oat")) {
oflags |= KCOAUTOTRAN;
} else if (!strcmp(argv[i], "-oas")) {
oflags |= KCOAUTOSYNC;
} else if (!strcmp(argv[i], "-onl")) {
oflags |= KCONOLOCK;
} else if (!strcmp(argv[i], "-otl")) {
oflags |= KCOTRYLOCK;
} else if (!strcmp(argv[i], "-onr")) {
oflags |= KCONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = TRUE;
path = argv[i];
} else if (!rstr) {
rstr = argv[i];
} else {
usage();
}
}
if (!path || !rstr) usage();
rnum = kcatoix(rstr);
if (rnum < 1) usage();
return procindex(path, rnum, rnd, etc, oflags);
}
/* parse arguments of map command */
static int32_t runmap(int argc, char** argv) {
int32_t argbrk = FALSE;
const char* rstr;
int32_t rnd, etc, i;
int64_t rnum, bnum;
rstr = NULL;
rnd = FALSE;
etc = FALSE;
bnum = -1;
for (i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!strcmp(argv[i], "--")) {
argbrk = TRUE;
} else if (!strcmp(argv[i], "-rnd")) {
rnd = TRUE;
} else if (!strcmp(argv[i], "-etc")) {
etc = TRUE;
} else if (!strcmp(argv[i], "-bnum")) {
if (++i >= argc) usage();
bnum = kcatoix(argv[i]);
} else {
usage();
}
} else if (!rstr) {
argbrk = TRUE;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
rnum = kcatoix(rstr);
if (rnum < 1) usage();
return procmap(rnum, rnd, etc, bnum);
}
/* parse arguments of list command */
static int32_t runlist(int argc, char** argv) {
int32_t argbrk = FALSE;
const char* rstr;
int32_t rnd, etc, i;
int64_t rnum;
rstr = NULL;
rnd = FALSE;
etc = FALSE;
for (i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!strcmp(argv[i], "--")) {
argbrk = TRUE;
} else if (!strcmp(argv[i], "-rnd")) {
rnd = TRUE;
} else if (!strcmp(argv[i], "-etc")) {
etc = TRUE;
} else {
usage();
}
} else if (!rstr) {
argbrk = TRUE;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
rnum = kcatoix(rstr);
if (rnum < 1) usage();
return proclist(rnum, rnd, etc);
}
/* perform order command */
static int32_t procorder(const char* path, int64_t rnum, int32_t rnd, int32_t etc,
int32_t tran, int32_t oflags) {
KCDB* db;
KCCUR* cur, *paracur;
int32_t err;
char kbuf[RECBUFSIZ], *vbuf, wbuf[RECBUFSIZ], *corepath, *copypath, *snappath;
size_t ksiz, vsiz, psiz;
int32_t wsiz;
int64_t i, cnt;
double stime, etime;
VISARG visarg;
oprintf("\n path=%s rnum=%ld rnd=%d etc=%d tran=%d oflags=%d\n\n",
path, (long)rnum, rnd, etc, tran, oflags);
err = FALSE;
db = kcdbnew();
oprintf("opening the database:\n");
stime = kctime();
if (!kcdbopen(db, path, KCOWRITER | KCOCREATE | KCOTRUNCATE | oflags)) {
dberrprint(db, __LINE__, "kcdbopen");
err = TRUE;
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
oprintf("setting records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
if (tran && !kcdbbegintran(db, FALSE)) {
dberrprint(db, __LINE__, "kcdbbegintran");
err = TRUE;
}
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
if (!kcdbset(db, kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db, __LINE__, "kcdbset");
err = TRUE;
}
if (tran && !kcdbendtran(db, TRUE)) {
dberrprint(db, __LINE__, "kcdbendtran");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
if (etc) {
oprintf("adding records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
if (tran && !kcdbbegintran(db, FALSE)) {
dberrprint(db, __LINE__, "kcdbbegintran");
err = TRUE;
}
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
if (!kcdbadd(db, kbuf, ksiz, kbuf, ksiz) && kcdbecode(db) != KCEDUPREC) {
dberrprint(db, __LINE__, "kcdbadd");
err = TRUE;
}
if (tran && !kcdbendtran(db, TRUE)) {
dberrprint(db, __LINE__, "kcdbendtran");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("appending records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
if (tran && !kcdbbegintran(db, FALSE)) {
dberrprint(db, __LINE__, "kcdbbegintran");
err = TRUE;
}
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
if (!kcdbappend(db, kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db, __LINE__, "kcdbadd");
err = TRUE;
}
if (tran && !kcdbendtran(db, TRUE)) {
dberrprint(db, __LINE__, "kcdbendtran");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
}
oprintf("getting records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
if (tran && !kcdbbegintran(db, FALSE)) {
dberrprint(db, __LINE__, "kcdbbegintran");
err = TRUE;
}
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
vbuf = kcdbget(db, kbuf, ksiz, &vsiz);
if (vbuf) {
if (vsiz < ksiz || memcmp(vbuf, kbuf, ksiz)) {
dberrprint(db, __LINE__, "kcdbget");
err = TRUE;
}
kcfree(vbuf);
} else if (!rnd || kcdbecode(db) != KCENOREC) {
dberrprint(db, __LINE__, "kcdbget");
err = TRUE;
}
if (tran && !kcdbendtran(db, TRUE)) {
dberrprint(db, __LINE__, "kcdbendtran");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
if (etc) {
oprintf("getting records with a buffer:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
if (tran && !kcdbbegintran(db, FALSE)) {
dberrprint(db, __LINE__, "kcdbbegintran");
err = TRUE;
}
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
wsiz = kcdbgetbuf(db, kbuf, ksiz, wbuf, sizeof(wbuf));
if (wsiz >= 0) {
if (wsiz < (int32_t)ksiz || memcmp(wbuf, kbuf, ksiz)) {
dberrprint(db, __LINE__, "kcdbgetbuf");
err = TRUE;
}
} else if (!rnd || kcdbecode(db) != KCENOREC) {
dberrprint(db, __LINE__, "kcdbgetbuf");
err = TRUE;
}
if (tran && !kcdbendtran(db, TRUE)) {
dberrprint(db, __LINE__, "kcdbendtran");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("traversing the database by the inner iterator:\n");
stime = kctime();
cnt = kcdbcount(db);
visarg.rnum = rnum;
visarg.rnd = rnd;
visarg.cnt = 0;
memset(visarg.rbuf, '+', sizeof(visarg.rbuf));
if (tran && !kcdbbegintran(db, FALSE)) {
dberrprint(db, __LINE__, "kcdbbegintran");
err = TRUE;
}
if (!kcdbiterate(db, visitfull, &visarg, TRUE)) {
dberrprint(db, __LINE__, "kcdbiterate");
err = TRUE;
}
if (rnd) oprintf(" (end)\n");
if (tran && !kcdbendtran(db, TRUE)) {
dberrprint(db, __LINE__, "kcdbendtran");
err = TRUE;
}
if (visarg.cnt != cnt) {
dberrprint(db, __LINE__, "kcdbiterate");
err = TRUE;
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("traversing the database by the outer cursor:\n");
stime = kctime();
cnt = kcdbcount(db);
visarg.rnum = rnum;
visarg.rnd = rnd;
visarg.cnt = 0;
if (tran && !kcdbbegintran(db, FALSE)) {
dberrprint(db, __LINE__, "kcdbbegintran");
err = TRUE;
}
cur = kcdbcursor(db);
if (!kccurjump(cur) && kccurecode(cur) != KCENOREC) {
dberrprint(db, __LINE__, "kccurjump");
err = TRUE;
}
paracur = kcdbcursor(db);
while (!err && kccuraccept(cur, &visitfull, &visarg, TRUE, !rnd)) {
if (rnd) {
ksiz = sprintf(kbuf, "%08ld", (long)myrand(rnum));
switch (myrand(3)) {
case 0: {
if (!kcdbremove(db, kbuf, ksiz) && kcdbecode(db) != KCENOREC) {
dberrprint(db, __LINE__, "kcdbremove");
err = TRUE;
}
break;
}
case 1: {
if (!kccurjumpkey(paracur, kbuf, ksiz) && kccurecode(paracur) != KCENOREC) {
dberrprint(db, __LINE__, "kccurjump");
err = TRUE;
}
break;
}
default: {
if (!kccurstep(cur) && kccurecode(cur) != KCENOREC) {
dberrprint(db, __LINE__, "kccurstep");
err = TRUE;
}
break;
}
}
}
}
oprintf(" (end)\n");
kccurdel(paracur);
kccurdel(cur);
if (tran && !kcdbendtran(db, TRUE)) {
dberrprint(db, __LINE__, "kcdbendtran");
err = TRUE;
}
if (!rnd && visarg.cnt != cnt) {
dberrprint(db, __LINE__, "kccuraccept");
err = TRUE;
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("synchronizing the database:\n");
stime = kctime();
if (!kcdbsync(db, FALSE, NULL, NULL)) {
dberrprint(db, __LINE__, "kcdbsync");
err = TRUE;
}
if (!kcdboccupy(db, FALSE, NULL, NULL)) {
dberrprint(db, __LINE__, "kcdboccupy");
err = TRUE;
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
corepath = kcdbpath(db);
psiz = strlen(corepath);
if (strstr(corepath, ".kch") || strstr(corepath, ".kct")) {
copypath = kcmalloc(psiz + 256);
sprintf(copypath, "%s.tmp", corepath);
snappath = kcmalloc(psiz + 256);
sprintf(snappath, "%s.kcss", corepath);
} else {
copypath = kcmalloc(256);
sprintf(copypath, "kclangctest.tmp");
snappath = kcmalloc(256);
sprintf(snappath, "kclangctest.kcss");
}
oprintf("copying the database file:\n");
stime = kctime();
if (!kcdbcopy(db, copypath)) {
dberrprint(db, __LINE__, "kcdbcopy");
err = TRUE;
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
remove(copypath);
oprintf("dumping records into snapshot:\n");
stime = kctime();
if (!kcdbdumpsnap(db, snappath)) {
dberrprint(db, __LINE__, "kcdbdumpsnap");
err = TRUE;
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
oprintf("loading records into snapshot:\n");
stime = kctime();
cnt = kcdbcount(db);
if (rnd && myrand(2) == 0 && !kcdbclear(db)) {
dberrprint(db, __LINE__, "kcdbclear");
err = TRUE;
}
if (!kcdbloadsnap(db, snappath) || kcdbcount(db) != cnt) {
dberrprint(db, __LINE__, "kcdbloadsnap");
err = TRUE;
}
etime = kctime();
dbmetaprint(db, FALSE);
oprintf("time: %.3f\n", etime - stime);
remove(snappath);
kcfree(copypath);
kcfree(snappath);
kcfree(corepath);
}
oprintf("removing records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
if (tran && !kcdbbegintran(db, FALSE)) {
dberrprint(db, __LINE__, "kcdbbegintran");
err = TRUE;
}
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
if (!kcdbremove(db, kbuf, ksiz) &&
((!rnd && !etc) || kcdbecode(db) != KCENOREC)) {
dberrprint(db, __LINE__, "kcdbremove");
err = TRUE;
}
if (tran && !kcdbendtran(db, TRUE)) {
dberrprint(db, __LINE__, "kcdbendtran");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
dbmetaprint(db, TRUE);
oprintf("time: %.3f\n", etime - stime);
oprintf("closing the database:\n");
stime = kctime();
if (!kcdbclose(db)) {
dberrprint(db, __LINE__, "kcdbclose");
err = TRUE;
}
etime = kctime();
oprintf("time: %.3f\n", etime - stime);
kcdbdel(db);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
/* perform index command */
static int32_t procindex(const char* path, int64_t rnum, int32_t rnd, int32_t etc,
int32_t oflags) {
KCIDX* idx;
int32_t err;
char kbuf[RECBUFSIZ], *vbuf;
size_t ksiz, vsiz;
int64_t i;
double stime, etime;
oprintf("\n path=%s rnum=%ld rnd=%d etc=%d oflags=%d\n\n",
path, (long)rnum, rnd, etc, oflags);
err = FALSE;
idx = kcidxnew();
oprintf("opening the database:\n");
stime = kctime();
if (!kcidxopen(idx, path, KCOWRITER | KCOCREATE | KCOTRUNCATE | oflags)) {
idxerrprint(idx, __LINE__, "kcidxopen");
err = TRUE;
}
etime = kctime();
idxmetaprint(idx, FALSE);
oprintf("time: %.3f\n", etime - stime);
oprintf("setting records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
if (!kcidxset(idx, kbuf, ksiz, kbuf, ksiz)) {
idxerrprint(idx, __LINE__, "kcidxset");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
idxmetaprint(idx, FALSE);
oprintf("time: %.3f\n", etime - stime);
if (etc) {
oprintf("adding records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
if (!kcidxadd(idx, kbuf, ksiz, kbuf, ksiz) && kcidxecode(idx) != KCEDUPREC) {
idxerrprint(idx, __LINE__, "kcidxadd");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
idxmetaprint(idx, FALSE);
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("appending records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
if (!kcidxappend(idx, kbuf, ksiz, kbuf, ksiz)) {
idxerrprint(idx, __LINE__, "kcidxadd");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
idxmetaprint(idx, FALSE);
oprintf("time: %.3f\n", etime - stime);
}
oprintf("getting records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
vbuf = kcidxget(idx, kbuf, ksiz, &vsiz);
if (vbuf) {
if (vsiz < ksiz || memcmp(vbuf, kbuf, ksiz)) {
idxerrprint(idx, __LINE__, "kcidxget");
err = TRUE;
}
kcfree(vbuf);
} else if (!rnd || kcidxecode(idx) != KCENOREC) {
idxerrprint(idx, __LINE__, "kcidxget");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
idxmetaprint(idx, FALSE);
oprintf("time: %.3f\n", etime - stime);
if (etc) {
oprintf("synchronizing the database:\n");
stime = kctime();
if (!kcidxsync(idx, FALSE, NULL, NULL)) {
idxerrprint(idx, __LINE__, "kcidxsync");
err = TRUE;
}
etime = kctime();
idxmetaprint(idx, FALSE);
oprintf("time: %.3f\n", etime - stime);
}
oprintf("removing records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
if (!kcidxremove(idx, kbuf, ksiz) &&
((!rnd && !etc) || kcidxecode(idx) != KCENOREC)) {
idxerrprint(idx, __LINE__, "kcidxremove");
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
idxmetaprint(idx, TRUE);
oprintf("time: %.3f\n", etime - stime);
oprintf("closing the database:\n");
stime = kctime();
if (!kcidxclose(idx)) {
idxerrprint(idx, __LINE__, "kcidxclose");
err = TRUE;
}
etime = kctime();
oprintf("time: %.3f\n", etime - stime);
kcidxdel(idx);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
/* perform map command */
static int32_t procmap(int64_t rnum, int32_t rnd, int32_t etc, int64_t bnum) {
KCMAP* map;
KCMAPITER* iter;
KCMAPSORT* sort;
int32_t err;
char kbuf[RECBUFSIZ];
const char* vbuf, *ikbuf;
size_t ksiz, vsiz;
int64_t i, cnt;
double stime, etime;
oprintf("\n rnum=%ld rnd=%d etc=%d bnum=%ld\n\n",
(long)rnum, rnd, etc, (long)bnum);
err = FALSE;
if (bnum < 0) bnum = 0;
map = kcmapnew(bnum);
oprintf("setting records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
kcmapset(map, kbuf, ksiz, kbuf, ksiz);
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
oprintf("count: %ld\n", (long)kcmapcount(map));
oprintf("time: %.3f\n", etime - stime);
if (etc) {
oprintf("adding records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
kcmapadd(map, kbuf, ksiz, kbuf, ksiz);
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
oprintf("count: %ld\n", (long)kcmapcount(map));
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("appending records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
kcmapappend(map, kbuf, ksiz, kbuf, ksiz);
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
oprintf("count: %ld\n", (long)kcmapcount(map));
oprintf("time: %.3f\n", etime - stime);
}
oprintf("getting records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
vbuf = kcmapget(map, kbuf, ksiz, &vsiz);
if (vbuf) {
if (vsiz < ksiz || memcmp(vbuf, kbuf, ksiz)) {
eprintf("%s: kcmapget failed\n", g_progname);
err = TRUE;
}
} else if (!rnd) {
eprintf("%s: kcmapget failed\n", g_progname);
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
oprintf("count: %ld\n", (long)kcmapcount(map));
oprintf("time: %.3f\n", etime - stime);
if (etc) {
oprintf("traversing records:\n");
stime = kctime();
cnt = 0;
iter = kcmapiterator(map);
while (!err && (ikbuf = kcmapiterget(iter, &ksiz, &vbuf, &vsiz)) != NULL) {
if (rnd) {
ksiz = sprintf(kbuf, "%08ld", (long)myrand(rnum));
switch (myrand(3)) {
case 0: {
kcmapremove(map, kbuf, ksiz);
break;
}
case 1: {
kcmapappend(map, kbuf, ksiz, kbuf, ksiz);
break;
}
}
}
if (!kcmapitergetkey(iter, &ksiz)) {
eprintf("%s: kcmapitergetkey failed\n", g_progname);
err = TRUE;
}
if (!kcmapitergetvalue(iter, &vsiz)) {
eprintf("%s: kcmapitergetvalue failed\n", g_progname);
err = TRUE;
}
cnt++;
if (rnum > 250 && cnt % (rnum / 250) == 0) {
oputchar('.');
if (cnt == rnum || cnt % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)cnt);
}
kcmapiterstep(iter);
}
if (rnd) oprintf(" (end)\n");
kcmapiterdel(iter);
if (!rnd && cnt != (int64_t)kcmapcount(map)) {
eprintf("%s: kcmapcount failed\n", g_progname);
err = TRUE;
}
etime = kctime();
oprintf("count: %ld\n", (long)kcmapcount(map));
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("sorting records:\n");
stime = kctime();
cnt = 0;
sort = kcmapsorter(map);
while (!err && (ikbuf = kcmapsortget(sort, &ksiz, &vbuf, &vsiz)) != NULL) {
if (!kcmapsortgetkey(sort, &ksiz)) {
eprintf("%s: kcmapsortgetkey failed\n", g_progname);
err = TRUE;
}
if (!kcmapsortgetvalue(sort, &vsiz)) {
eprintf("%s: kcmapsortgetvalue failed\n", g_progname);
err = TRUE;
}
cnt++;
if (rnum > 250 && cnt % (rnum / 250) == 0) {
oputchar('.');
if (cnt == rnum || cnt % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)cnt);
}
kcmapsortstep(sort);
}
if (rnd) oprintf(" (end)\n");
kcmapsortdel(sort);
if (!rnd && cnt != (int64_t)kcmapcount(map)) {
eprintf("%s: kcmapcount failed\n", g_progname);
err = TRUE;
}
etime = kctime();
oprintf("count: %ld\n", (long)kcmapcount(map));
oprintf("time: %.3f\n", etime - stime);
}
oprintf("removing records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
ksiz = sprintf(kbuf, "%08ld", (long)(rnd ? myrand(rnum) + 1 : i));
if (!kcmapremove(map, kbuf, ksiz) && !rnd) {
eprintf("%s: kcmapremove failed\n", g_progname);
err = TRUE;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
oprintf("count: %ld\n", (long)kcmapcount(map));
oprintf("time: %.3f\n", etime - stime);
kcmapdel(map);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
/* perform list command */
static int32_t proclist(int64_t rnum, int32_t rnd, int32_t etc) {
KCLIST* list;
int32_t err;
char buf[RECBUFSIZ];
size_t size;
int64_t i, cnt;
double stime, etime;
oprintf("\n rnum=%ld rnd=%d etc=%d\n\n",
(long)rnum, rnd, etc);
err = FALSE;
list = kclistnew();
oprintf("setting records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
size = sprintf(buf, "%08ld", (long)i);
if (rnd && myrand(2) == 0) {
kclistunshift(list, buf, size);
} else {
kclistpush(list, buf, size);
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
oprintf("count: %ld\n", (long)kclistcount(list));
oprintf("time: %.3f\n", etime - stime);
oprintf("getting records:\n");
stime = kctime();
cnt = kclistcount(list);
for (i = 1; !err && i <= rnum; i++) {
kclistget(list, rnd ? myrand(cnt) : i - 1, &size);
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
oprintf("count: %ld\n", (long)kclistcount(list));
oprintf("time: %.3f\n", etime - stime);
oprintf("removing records:\n");
stime = kctime();
for (i = 1; !err && i <= rnum; i++) {
if (rnd && myrand(2) == 0) {
kclistshift(list);
} else {
kclistpop(list);
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
oprintf("count: %ld\n", (long)kclistcount(list));
oprintf("time: %.3f\n", etime - stime);
if (etc) {
oprintf("wicked testing:\n");
stime = kctime();
memset(buf, '*', sizeof(buf));
for (i = 1; !err && i <= rnum; i++) {
size = rnd ? (size_t)myrand(sizeof(buf)) : sizeof(buf);
cnt = kclistcount(list);
switch (rnd ? myrand(10) : i % 10) {
case 0: {
kclistpop(list);
break;
}
case 1: {
kclistunshift(list, buf, size);
break;
}
case 2: {
kclistshift(list);
break;
}
case 3: {
kclistinsert(list, buf, size, rnd && cnt > 0 ? myrand(cnt) : cnt / 2);
break;
}
case 4: {
if (cnt > 0) kclistremove(list, rnd ? myrand(cnt) : cnt / 2);
break;
}
case 5: {
if (cnt > 0) kclistget(list, rnd ? myrand(cnt) : cnt / 2, &size);
break;
}
case 6: {
if (rnd ? myrand(100) == 0 : i % 127 == 0) kclistclear(list);
break;
}
default: {
kclistpush(list, buf, size);
break;
}
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08ld)\n", (long)i);
}
}
etime = kctime();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %ld\n", (long)kclistcount(list));
}
kclistdel(list);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
/* END OF FILE */