void hxercise(HXFILE *hp, char const *str, FILE *fp) { int maxrec = hxmaxrec(hp), reclim = maxrec * 2, buflim = reclim; char *recspc = malloc(reclim), *rec = recspc + 5; char *bufspc = malloc(buflim), *buf = bufspc + 7; int i, test[2] = {}; # define OK(...) ++test[_ok(fp, __VA_ARGS__)] memset(recspc, fill, reclim); int len1 = hx_load(hp, rec, 0, str); OK(len1 > 0 && len1 <= maxrec, "hx_load(,,0,) returns: %d in 1..%d for '%s'", len1, maxrec, str); OK(memspan(recspc, fill, reclim), "hx_load(,rec,0,) leaves rec unchanged"); int len2 = hx_load(hp, rec, len1, str); OK(len2 == len1 && memspan(recspc, fill, 5) && memspan(rec+len1, fill, reclim-5-len1), "hx_load(,,%d,): %d", len1, len2); char rec2[len1]; memcpy(rec2, rec, len1); OK(!hx_diff(hp, rec2, rec), "diff of copy"); OK(hx_hash(hp, rec2) == hx_hash(hp, rec), "hash of copy"); memset(recspc, fill, reclim); for (i = 1; i < len1; ++i) { len2 = hx_load(hp, rec, i, str); OK(len2 == len1 && memspan(recspc, fill, 5) && !memcmp(rec, buf, i) && memspan(rec+i, fill, reclim-5-i), "hx_load(,,%d,): %d", i ,len2); } memcpy(buf, rec, len1); for (i = len1; i > 0; --i) { if (hx_test(hp, buf, i)) { buf[i] ^= 0x5A; OK(hx_test(hp, buf, i), "retest %d", i); } } memset(bufspc, fill, buflim); len2 = hx_save(hp, rec2, len1, buf, 0); OK(memspan(bufspc, fill, buflim), "hx_save(,,,,0) leaves target unchanged"); if (len2 > buflim - 5) { buflim *= 2; bufspc = realloc(bufspc, buflim); memset(bufspc, fill, buflim); buf = bufspc + 7; } int len3 = hx_save(hp, rec2, len1, buf, len2 + 1); OK(len3 == len2 && memspan(buf, fill, 7) && memspan(buf, fill, buflim-7-len2) && buf[len3-1] && (int)strlen(buf) == len3-1 && strchr(buf, '\t') && !strchr(buf, '\n'), "hx_save(,,%d,,%d): %d", len1, len2+1, len3); DEBUG2("+%d -%d: '%s'", test[0], test[1], str); free(recspc); free(bufspc); }
static void do_load(HXFILE * hp, FILE * inp) { HXRET hxret = 0; int reclen, recsize = hxmaxrec(hp); int bufsize = 2 * recsize; char rec[recsize], buf[bufsize]; int lineno = 0, more, added = 0; if (verbose == 1) setvbuf(stderr, NULL, _IONBF, 0); while ((more = ! !fgets(buf, bufsize, inp))) { ++lineno; char *cp = buf + strlen(buf); if (cp > buf && cp[-1] == '\n') *--cp = 0; if (cp == buf) continue; reclen = hx_load(hp, rec, recsize, buf); if (reclen <= 0) { fprintf(stderr, "# load: invalid %s: %s\n", reclen == HXERR_BAD_REQUEST ? "request" : "input", buf); continue; } hxret = hxput(hp, rec, reclen); if (verbose > 1) fprintf(stderr, "# load(%s): %s\n", buf, hxerror(hxret)); else if (verbose && lineno % 1000 == 0) putc('.', stderr); if (hxret < 0) break; if (hxret == HXNOTE) ++added; } if (verbose == 1 && lineno > 999) putc('\n', stderr); if (more) fprintf(stderr, "load: error at input line %d (%s)\n", lineno, hxerror(hxret)); if (verbose) fprintf(stderr, "load: in: %d added: %d\n", lineno, added); }
static void del(HXFILE * hp, FILE * fp) { int keysize = hxmaxrec(hp) + 1; char buf[keysize * 2], key[keysize]; while (fgets(buf, keysize * 2, fp)) { int len = strlen(buf); if (buf[len - 1] == '\n') buf[--len] = 0; len = hx_load(hp, key, keysize, buf); if (len <= 0) continue; is_hxret("del", hxdel(hp, key)); } if (fp) fclose(fp); }
int main(int argc, char **argv) { char const *hx = getenv("hx"); if (!hx) hx = "."; int mapmode = HX_MMAP; char inpdflt[strlen(hx) + sizeof "/data.tab"]; char const *inpfile = inpdflt; int memsize = 0; strcat(strcpy(inpdflt, hx), "/data.tab"); if (argc == 1) usage("[-d] inpfile [membits | 0]\n" " -d: use disk io, not mmap\n" " membits: size of RAM for hxbuild (default:20)\n" " membits=0 means use the existing perf_x.hx"); if (!strcmp(argv[1], "-d")) mapmode = 0, ++argv, --argc; switch (argc) { case 3: memsize = atoi(argv[2]); case 2: inpfile = argv[1]; case 1: break; } // Ensure that dirname(argv[0]) is in LD_LIBRARY_PATH: char *dir = strrchr(argv[0], '/'), empty[] = ""; char const *llp = getenv("LD_LIBRARY_PATH"); dir = dir ? (*dir = 0, argv[0]) : empty; if (!llp) llp = ""; char llpath[strlen(dir) + strlen(llp) + 2]; setenv("LD_LIBRARY_PATH", strcat(strcat(strcpy(llpath, dir), ":"), llp), /*OVERRIDE*/1); HXFILE *hp; HXSTAT info; HXRET rc; FILE *fp = strcmp(inpfile, "-") ? fopen(inpfile, "r") : stdin; if (!fp) die(": cannot read %s:", inpfile); setvbuf(fp, NULL, _IOFBF, 65536); if (memsize) { memsize = 1 << memsize; hxcreate("perf_x.hx", 0644, 4096, 0, 0); hp = hxopen("perf_x.hx", HX_UPDATE); rc = hxbuild(hp, fp, memsize, 0.0); if (rc < 0) die("hxbuild(%d): %s", memsize, hxerror(rc)); hxclose(hp); } if (hxdebug) system("echo;echo built; chx info perf_x.hx; chx stat perf_x.hx; chx -vdd check perf_x.hx"); hp = hxopen("perf_x.hx", HX_UPDATE | mapmode); if (!hp) die("cannot open perf_x.hx%s:", mapmode ? " with MMAP" : ""); char buf[4096], rec[4096]; int len; double t0 = tick(); rewind(fp); while (fgets(buf, sizeof(buf), fp)) { buf[strlen(buf) - 1] = 0; hx_load(hp, rec, sizeof rec, buf); hxget(hp, rec, sizeof(rec)); } t0 = tick() - t0; double t1 = tick(); rewind(fp); while (fgets(buf, sizeof(buf), fp)) { buf[strlen(buf) - 1] = 0; buf[0] ^= 0x55; hx_load(hp, rec, sizeof rec, buf); hxget(hp, rec, sizeof(rec)); } t1 = tick() - t1; double t2 = tick(); rewind(fp); while (fgets(buf, sizeof(buf), fp)) { buf[strlen(buf) - 1] = 0; strcat(buf, "hello, world"); len = hx_load(hp, rec, sizeof rec, buf); hxput(hp, rec, len); } t2 = tick() - t2; if (hxdebug) system("echo;echo put+12; chx info perf_x.hx; chx stat perf_x.hx; chx -vdd check perf_x.hx"); double t3 = tick(); rewind(fp); while (fgets(buf, sizeof(buf), fp)) { buf[strlen(buf) - 1] = 0; len = hx_load(hp, rec, sizeof rec, buf); hxput(hp, rec, len); } t3 = tick() - t3; if (hxdebug) system("echo;echo put-0; chx info perf_x.hx; chx stat perf_x.hx; chx -vdd check perf_x.hx"); double t4 = tick(); rewind(fp); while (fgets(buf, sizeof(buf), fp)) { strcpy(buf + strlen(buf) - 1, "---------1---------2---------3---------4---------5---------6---------7---------8---------9---------0\n"); len = hx_load(hp, rec, sizeof rec, buf); hxput(hp, rec, len); } t4 = tick() - t4; if (hxdebug) system("echo;echo put+100; chx info perf_x.hx; chx stat perf_x.hx; chx -vdd check perf_x.hx"); double t5 = tick(); rewind(fp); while (fgets(buf, sizeof(buf), fp)) { buf[strlen(buf) - 1] = 0; hx_load(hp, rec, sizeof rec, buf); hxget(hp, rec, sizeof(rec)); } t5 = tick() - t5; double t6 = tick(); rewind(fp); while (fgets(buf, sizeof(buf), fp)) { buf[strlen(buf) - 1] = 0; buf[0] ^= 0x55; hx_load(hp, rec, sizeof rec, buf); hxget(hp, rec, sizeof(rec)); } t6 = tick() - t6; double t7 = tick(); rewind(fp); while (fgets(buf, sizeof(buf), fp)) { buf[strlen(buf) - 1] = 0; buf[0] ^= 0x55; hx_load(hp, rec, sizeof rec, buf); hxput(hp, rec, sizeof(rec)); } t7 = tick() - t7; hxstat(hp, &info); fprintf(stderr, "nrecs: %g build: %.2fM rec/sec\n(usec:)\n" "\tget-y\t%.2f\n\tget-n\t%.2f\n" "\tput+12\t%.2f\n\tput+0\t%.2f\n\tput+100\t%.2f\n" "\tget-y\t%.2f\n\tget-n\t%.2f\n\tput-xx\t%.2f\n", info.nrecs, info.nrecs/1E6/t0, t0*1E6/info.nrecs, t1*1E6/info.nrecs, t2*1E6/info.nrecs, t3*1E6/info.nrecs, t4*1E6/info.nrecs, t5*1E6/info.nrecs, t6*1E6/info.nrecs, t7*1E6/info.nrecs); return 0; }