int main(void) { char input[999]; char const *envhx = getenv("hx"); if (!envhx) die(": $hx not set"); setvbuf(stdout, 0, _IOLBF, 0); plan_tests(1 + 4*4); HXRET rc = hxbuild(0, 0, 1<<20, 0.0); ok(rc == HXERR_BAD_REQUEST, "hxbuild rejects NULL arg: %s", hxerror(rc)); try("/dev/null", 0); try(strcat(strcpy(input, envhx), "/data.tab"), 88172); try(strcat(strcat(strcpy(input, "cat "), envhx), "/data.tab"), 88172); try(strcat(strcat(strcpy(input, "head -2335 "), envhx), "/data.tab"), 2335); return exit_status(); } static void try(char const *inpfile, int nrecs) { FILE *fp = strchr(inpfile, ' ') ? popen(inpfile, "r") : fopen(inpfile, "r"); ok(fp, "input %s", inpfile); if (!fp) die(": unable to open %s:", inpfile); setvbuf(fp, NULL, _IOFBF, 16384); hxcreate("build_t.hx", 0755, 4096, "", 0); HXFILE *hp = hxopen("build_t.hx", HX_UPDATE); double alpha = tick(); HXRET rc = hxbuild(hp, fp, 1<<20, 0.0); //128MB double omega = tick(); if (strchr(inpfile, ' ')) pclose(fp); else fclose(fp); ok(rc == 0, "hxbuild from (%s) in %.3g secs, returns %s", inpfile, omega - alpha, hxerror(rc)); rc = hxfix(hp,0,0,0,0); ok(rc == (HXRET)HX_UPDATE, "hxcheck returns: %s", hxmode(rc)); HXSTAT st; hxstat(hp, &st); ok(st.nrecs == nrecs, "hxbuild loaded %.0f/%d records", st.nrecs, nrecs); hxclose(hp); unlink("build_t.hx"); }
int main(int argc, char **argv) { int count = argc > 1 ? atoi(argv[1]) : 10000; plan_tests(9); ok(sizeof(off_t) == 8, "sizeof(off_t) == %" FSIZE "d", sizeof(off_t)); // TODO: add tests that actually test hx() on large databases int npages = 1 << 20; int pgsize = 8192; int rc = hxcreate("large_t.hx", 0666, pgsize, NULL, 0); ok(rc == HXOKAY, "hxcreate(large_t.hx): %d %s", rc, hxerror(rc)); HXFILE *hp = hxopen("large_t.hx", HX_UPDATE); ok(hp != NULL, "hxopen(large_t.hx): %d %s", errno, errname[errno]); int fd = hxfileno(hp); off_t size = (off_t) pgsize * npages; // 8GB ok(!ftruncate(fd, size), "grow to %" FOFF "d: %d %s", size, errno, errname[errno]); // Manually initialize map pages. // A map page must indicate that it itself (i.e. bit 0 in the map) is // allocated, else it will eventually be allocated and overwritten as // an overflow page. // 32:8(bits/byte)*4(pgrate) pgsize:bytes/page 6:(page header overhead) int pg, last = _hxmap(hp, npages, &pg); // "pg" is just junk here. char map = 1; for (pg = 0; (pg = NEXT_MAP(hp, pg)) <= last;) { lseek(fd, (off_t) pg * pgsize + sizeof(HXPAGE), 0); write(fd, &map, 1); } struct stat sb; ok(!fstat(hxfileno(hp), &sb), "fstat: %d %s", errno, errname[errno]); ok(sb.st_size == size, "size is 0x%" FOFF "x", sb.st_size); // 10000 records is enough to ensure that at least SOME records end up // above the 4GB mark. int i, tally = 0; char rec[11] = { }; for (i = rc = 0; i < count; ++i) { sprintf(rec, "%08d", i); rc = hxput(hp, rec, 10); if (rc != 0) break; rc = hxget(hp, rec, 10); if (rc != 10) { fprintf(stderr, "hxget(%s) failed: %d\n", rec, rc); break; } } ok(i == count, "inserted and retrieved %d/%d records: %s", i, count, hxerror(rc)); while (0 < (rc = hxnext(hp, rec, 11))) ++tally; ok(tally == count, "hxnext retrieved %d/%d records: %s", tally, count, hxerror(rc)); rc = hxfix(hp, 0, 0, 0, 0); ok(rc == (HXRET) HX_UPDATE, "hxcheck: large_t.hx is ready for %s access", hxmode(rc)); hxclose(hp); return exit_status(); }
//--------------|--------------------------------------------- int main(int argc, char **argv) { int ret = 0; int opt; int timed = 0; char cmd[10240]; while (0 < (opt = getopt(argc, argv, "?c:dmp:s:tv-"))) { switch (opt) { case '?': help(); break; case 'c': hxcrash = atoi(optarg); break; case 'd': ++hxdebug; break; case 'm': mmode |= HX_MMAP; break; case 's': mmode |= HX_FSYNC; break; case 't': timed++; break; case 'v': ++verbose; break; } } argc -= optind; argv += optind; setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stderr, NULL, _IOLBF, 0); errno = 0; //setvbuf sets errno !? int size = 0; HXMODE mode; HXFILE *hp = NULL; FILE *fp = NULL; if (!*argv) die("See 'chx help' for usage"); if (*argv[0] == '?' || !strcmp(argv[0], "help")) help(); double tstart = tick(); if (hxdebug) hxtime = tstart; if (!strcmp(argv[0], "build")) { hp = do_hxopen("build", argv[1], HX_UPDATE); fp = do_fopen("build", argv[2], "r"); int memsize = argc > 3 ? atoi(argv[3]) : 1; int inpsize = argc > 4 ? atoi(argv[4]) : 0; memsize <<= 20; is_hxret("build", hxbuild(hp, fp, memsize, inpsize)); } else if (!strcmp(argv[0], "check")) { char *udata = argc > 3 ? argv[3] : NULL; if (argc < 2) die("%s: requires filename [pgsize [udata]]", argv[0]); if (argc > 2 && !sscanf(argv[2], "%d", &size)) die("%s: invalid pgsize", argv[2]); hp = do_hxopen("check", argv[1], HX_CHECK); mode = hxfix(hp, NULL, size, udata, udata ? strlen(udata) : 0); if (verbose || mode != HX_UPDATE) printf("%s %s\n", hxmode(mode), errno ? strerror(errno) : ""); ret = mode != HX_UPDATE; } else if (!strcmp(argv[0], "create")) { if (argc < 3 || !sscanf(argv[2], "%d", &size)) die("create: requires filename, pgsize, type"); char const *type = argv[3] ? argv[3] : ""; is_hxret("create", hxcreate(argv[1], 0644, size, type, strlen(type))); hp = do_hxopen("create", argv[1], HX_RECOVER); } else if (!strcmp(argv[0], "del")) { hp = do_hxopen("del", argv[1], HX_UPDATE); fp = do_fopen("del", argv[2], "r"); del(hp, fp); } else if (!strcmp(argv[0], "dump")) { hp = do_hxopen("dump", argv[1], HX_READ); dump(hp, stdout); } else if (!strcmp(argv[0], "fix") || !strcmp(argv[0], "repair")) { char *udata = argc > 3 ? argv[3] : NULL; if (argc < 2) die("%s: requires filename [pgsize [udata]]", argv[0]); if (argv[2] && !sscanf(argv[2], "%d", &size)) die("%s: invalid pgsize", argv[2]); hp = do_hxopen("repair", argv[1], HX_UPDATE); fp = tmpfile(); mode = hxfix(hp, fp, size, udata, udata ? strlen(udata) : 0); if (verbose || mode != HX_UPDATE) printf("%s %s\n", hxmode(mode), errno ? strerror(errno) : ""); ret = mode != HX_UPDATE; } else if (!strcmp(argv[0], "hdrs")) { hp = do_hxopen("hdrs", argv[1], HX_READ); fp = do_fopen("hdrs", argv[2], "w"); hdrs(hp); } else if (!strcmp(argv[0], "info")) { hp = do_hxopen("info", argv[1], HX_READ); info(hp); } else if (!strcmp(argv[0], "load")) { hp = do_hxopen("load", argv[1], HX_UPDATE); fp = do_fopen("hdrs", argv[2], "r"); do_load(hp, fp); } else if (!strcmp(argv[0], "lock")) { hp = do_hxopen("lock", argv[1], HX_READ); do_lock(hp); } else if (!strcmp(argv[0], "maps")) { hp = do_hxopen("maps", argv[1], HX_READ); is_hxret("maps", maps(hp)); } else if (!strcmp(argv[0], "pack")) { hp = do_hxopen("load", argv[1], HX_UPDATE); is_hxret("pack", hxpack(hp)); } else if (!strcmp(argv[0], "save")) { hp = do_hxopen("save", argv[1], HX_READ); fp = do_fopen("save", argv[2], "w"); do_save(hp, fp); } else if (!strcmp(argv[0], "shape")) { double density; if (argc != 3 || !sscanf(argv[2], "%lf", &density)) die("%s: requires density arg (0 to 1.0)", argv[2]); hp = do_hxopen("shape", argv[1], HX_UPDATE); is_hxret("shape", hxshape(hp, density)); } else if (!strcmp(argv[0], "stat")) { hp = do_hxopen("stat", argv[1], HX_READ); stats(hp); } else if (!strcmp(argv[0], "types")) { // for each dir in LD_LIBRARY_PATH (and "" -> ".") then /lib then /usr/lib, // find all files of the form "<dir>/hx_<rectype>.so" // and build a file of unique rectypes. // Then call hxlib which returns an exact path and a bitmask of DIFF/LOAD/TEST // "type diff-load-test path" // If the path matches, print the entry. types(getenv("LD_LIBRARY_PATH")); types("lib:/usr/lib"); } else { die("%s: unknown command. See 'chx help'", cmd); } if (fp) fclose(fp); if (hp) hxclose(hp); if (timed) fprintf(stderr, "# chx %s: %.3f secs\n", *argv, tick() - tstart); return ret; }