int main(int argc, char *argv[]) { FILE *fp; WT_CONNECTION *conn; WT_CURSOR *cursor; WT_SESSION *session; WT_RAND_STATE rnd; uint64_t key; uint32_t absent, count, timeout; int ch, status, ret; pid_t pid; char *working_dir; if ((progname = strrchr(argv[0], DIR_DELIM)) == NULL) progname = argv[0]; else ++progname; working_dir = NULL; timeout = 10; while ((ch = __wt_getopt(progname, argc, argv, "h:t:")) != EOF) switch (ch) { case 'h': working_dir = __wt_optarg; break; case 't': timeout = (uint32_t)atoi(__wt_optarg); break; default: usage(); } argc -= __wt_optind; argv += __wt_optind; if (argc != 0) usage(); testutil_work_dir_from_path(home, 512, working_dir); testutil_make_work_dir(home); /* * Fork a child to insert as many items. We will then randomly * kill the child, run recovery and make sure all items we wrote * exist after recovery runs. */ if ((pid = fork()) < 0) testutil_die(errno, "fork"); if (pid == 0) { /* child */ fill_db(); return (EXIT_SUCCESS); } /* parent */ __wt_random_init(&rnd); /* Sleep for the configured amount of time before killing the child. */ printf("Parent: sleep %" PRIu32 " seconds, then kill child\n", timeout); sleep(timeout); /* * !!! It should be plenty long enough to make sure more than one * log file exists. If wanted, that check would be added here. */ printf("Kill child\n"); if (kill(pid, SIGKILL) != 0) testutil_die(errno, "kill"); waitpid(pid, &status, 0); /* * !!! If we wanted to take a copy of the directory before recovery, * this is the place to do it. */ chdir(home); printf("Open database, run recovery and verify content\n"); if ((ret = wiredtiger_open(NULL, NULL, ENV_CONFIG_REC, &conn)) != 0) testutil_die(ret, "wiredtiger_open"); if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) testutil_die(ret, "WT_CONNECTION:open_session"); if ((ret = session->open_cursor(session, uri, NULL, NULL, &cursor)) != 0) testutil_die(ret, "WT_SESSION.open_cursor: %s", uri); if ((fp = fopen(RECORDS_FILE, "r")) == NULL) testutil_die(errno, "fopen"); /* * For every key in the saved file, verify that the key exists * in the table after recovery. Since we did write-no-sync, we * expect every key to have been recovered. */ for (absent = count = 0;; ++count) { ret = fscanf(fp, "%" SCNu64 "\n", &key); if (ret != EOF && ret != 1) testutil_die(errno, "fscanf"); if (ret == EOF) break; cursor->set_key(cursor, key); if ((ret = cursor->search(cursor)) != 0) { if (ret != WT_NOTFOUND) testutil_die(ret, "search"); printf("no record with key %" PRIu64 "\n", key); ++absent; } } fclose(fp); if ((ret = conn->close(conn, NULL)) != 0) testutil_die(ret, "WT_CONNECTION:close"); if (absent) { printf("%u record(s) absent from %u\n", absent, count); return (EXIT_FAILURE); } printf("%u records verified\n", count); return (EXIT_SUCCESS); }
int main(int argc, char *argv[]) { FILE *fp; WT_CONNECTION *conn; WT_CURSOR *cursor; WT_SESSION *session; pid_t pid; uint64_t new_offset, offset; uint32_t count, max_key; int ch, ret, status; const char *working_dir; (void)testutil_set_progname(argv); working_dir = "WT_TEST.truncated-log"; while ((ch = __wt_getopt(progname, argc, argv, "h:")) != EOF) switch (ch) { case 'h': working_dir = __wt_optarg; break; default: usage(); } argc -= __wt_optind; if (argc != 0) usage(); testutil_work_dir_from_path(home, sizeof(home), working_dir); testutil_make_work_dir(home); /* * Fork a child to do its work. Wait for it to exit. */ if ((pid = fork()) < 0) testutil_die(errno, "fork"); if (pid == 0) { /* child */ fill_db(); return (EXIT_SUCCESS); } /* parent */ /* Wait for child to kill itself. */ if (waitpid(pid, &status, 0) == -1) testutil_die(errno, "waitpid"); /* * !!! If we wanted to take a copy of the directory before recovery, * this is the place to do it. */ if (chdir(home) != 0) testutil_die(errno, "chdir: %s", home); printf("Open database, run recovery and verify content\n"); if ((fp = fopen(RECORDS_FILE, "r")) == NULL) testutil_die(errno, "fopen"); ret = fscanf(fp, "%" SCNu64 " %" SCNu32 "\n", &offset, &max_key); if (ret != 2) testutil_die(errno, "fscanf"); if (fclose(fp) != 0) testutil_die(errno, "fclose"); /* * The offset is the beginning of the last record. Truncate to * the middle of that last record (i.e. ahead of that offset). */ if (offset > UINT64_MAX - V_SIZE) testutil_die(ERANGE, "offset"); new_offset = offset + V_SIZE; printf("Parent: Log file 1: Key %" PRIu32 " at %" PRIu64 "\n", max_key, offset); printf("Parent: Truncate mid-record to %" PRIu64 "\n", new_offset); if (truncate(LOG_FILE_1, (wt_off_t)new_offset) != 0) testutil_die(errno, "truncate"); testutil_check(wiredtiger_open(NULL, NULL, ENV_CONFIG_REC, &conn)); testutil_check(conn->open_session(conn, NULL, NULL, &session)); testutil_check(session->open_cursor(session, uri, NULL, NULL, &cursor)); /* * For every key in the saved file, verify that the key exists * in the table after recovery. Since we did write-no-sync, we * expect every key to have been recovered. */ count = 0; while (cursor->next(cursor) == 0) ++count; /* * The max key in the saved file is the key we truncated, but the * key space starts at 0 and we're counting the records here, so we * expect the max key number of records. Add one for the system * record for the previous LSN that the cursor will see too. */ if (count > (max_key + 1)) { printf("expected %" PRIu32 " records found %" PRIu32 "\n", max_key, count); return (EXIT_FAILURE); } printf("%" PRIu32 " records verified\n", count); /* * Write a log record and then walk the log to make sure we can * read that log record that is beyond the truncated record. */ write_and_read_new(session); testutil_check(conn->close(conn, NULL)); return (EXIT_SUCCESS); }
int main(int argc, char *argv[]) { FILE *fp; WT_CONNECTION *conn; WT_CURSOR *cursor; WT_SESSION *session; uint64_t new_offset, offset; uint32_t count, max_key; int ch, status, ret; pid_t pid; const char *working_dir; if ((progname = strrchr(argv[0], DIR_DELIM)) == NULL) progname = argv[0]; else ++progname; working_dir = "WT_TEST.truncated-log"; while ((ch = __wt_getopt(progname, argc, argv, "h:")) != EOF) switch (ch) { case 'h': working_dir = __wt_optarg; break; default: usage(); } argc -= __wt_optind; argv += __wt_optind; if (argc != 0) usage(); testutil_work_dir_from_path(home, 512, working_dir); testutil_make_work_dir(home); /* * Fork a child to insert as many items. We will then randomly * kill the child, run recovery and make sure all items we wrote * exist after recovery runs. */ if ((pid = fork()) < 0) testutil_die(errno, "fork"); if (pid == 0) { /* child */ fill_db(); return (EXIT_SUCCESS); } /* parent */ /* Wait for child to kill itself. */ if (waitpid(pid, &status, 0) == -1) testutil_die(errno, "waitpid"); /* * !!! If we wanted to take a copy of the directory before recovery, * this is the place to do it. */ if (chdir(home) != 0) testutil_die(errno, "chdir: %s", home); printf("Open database, run recovery and verify content\n"); if ((fp = fopen(RECORDS_FILE, "r")) == NULL) testutil_die(errno, "fopen"); ret = fscanf(fp, "%" SCNu64 " %" SCNu32 "\n", &offset, &max_key); if (ret != 2) testutil_die(errno, "fscanf"); if (fclose(fp) != 0) testutil_die(errno, "fclose"); /* * The offset is the beginning of the last record. Truncate to * the middle of that last record (i.e. ahead of that offset). */ if (offset > UINT64_MAX - V_SIZE) testutil_die(ERANGE, "offset"); new_offset = offset + V_SIZE; printf("Parent: Truncate to %" PRIu64 "\n", new_offset); if ((ret = truncate(LOG_FILE_1, (wt_off_t)new_offset)) != 0) testutil_die(errno, "truncate"); if ((ret = wiredtiger_open(NULL, NULL, ENV_CONFIG_REC, &conn)) != 0) testutil_die(ret, "wiredtiger_open"); if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) testutil_die(ret, "WT_CONNECTION:open_session"); if ((ret = session->open_cursor(session, uri, NULL, NULL, &cursor)) != 0) testutil_die(ret, "WT_SESSION.open_cursor: %s", uri); /* * For every key in the saved file, verify that the key exists * in the table after recovery. Since we did write-no-sync, we * expect every key to have been recovered. */ count = 0; while ((ret = cursor->next(cursor)) == 0) ++count; if ((ret = conn->close(conn, NULL)) != 0) testutil_die(ret, "WT_CONNECTION:close"); if (count > max_key) { printf("expected %" PRIu32 " records found %" PRIu32 "\n", max_key, count); return (EXIT_FAILURE); } printf("%" PRIu32 " records verified\n", count); return (EXIT_SUCCESS); }
int main(int argc, char **argv) { int fdfifo, fdfifowrite; char *x; unsigned long id; VERSIONINFO; x = env_get("WORKDIR"); if (!x) strerr_die2x(111, FATAL, "$WORKDIR not set"); if (chdir(x) == -1) strerr_die4sys(111, FATAL, "unable to chdir to ", x, ": "); x = env_get("GID"); if (!x) strerr_die2x(111, FATAL, "$GID not set"); scan_ulong(x,&id); if (prot_gid((int) id) == -1) strerr_die2sys(111, FATAL, "unable to setgid: "); x = env_get("UID"); if (!x) strerr_die2x(111, FATAL, "$UID not set"); scan_ulong(x,&id); /* undocumented feature */ if(id == 0) if(!env_get("IWANTTORUNASROOTANDKNOWWHATIDO")) strerr_die2x(111, FATAL, "unable to run under uid 0: please change $UID"); if (prot_uid((int) id) == -1) strerr_die2sys(111, FATAL, "unable to setuid: "); buffer_putsflush(buffer_2, ARGV0 "starting\n"); if(fifo_make(FIFONAME, 0620) == -1) strerr_warn4(ARGV0, "unable to create fifo ", FIFONAME, " ", &strerr_sys); fdfifo = open_read(FIFONAME); if(fdfifo == -1) strerr_die4sys(111, FATAL, "unable to open for read ", FIFONAME, " "); coe(fdfifo); ndelay_on(fdfifo); /* DJB says: shouldn't be necessary */ /* we need this to keep the fifo from beeing closed */ fdfifowrite = open_write(FIFONAME); if (fdfifowrite == -1) strerr_die4sys(111, FATAL, "unable to open for write ", FIFONAME, " "); coe(fdfifowrite); /* init a buffer for nonblocking reading */ buffer_init(&wr, waitread, fdfifo, waitreadspace, sizeof waitreadspace); t = dAVLAllocTree(); /* read snapshot of dnsdatatree */ fill_db(); /* SIGALRM can be used to check if dumping the database is needed */ sig_catch(sig_alarm, sigalrm); /* SIGHUP can be used to force dumping the database */ sig_catch(sig_hangup, sighup); /* check if out child is done */ sig_catch(sig_child, sigchld); // XXX SIGINT, SIGTERM, /* do our normal workloop */ doit(); /* we shouldn't get here */ return 1; }