summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/test/format/salvage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/test/format/salvage.c')
-rw-r--r--src/third_party/wiredtiger/test/format/salvage.c156
1 files changed, 79 insertions, 77 deletions
diff --git a/src/third_party/wiredtiger/test/format/salvage.c b/src/third_party/wiredtiger/test/format/salvage.c
index a383c121862..26589e18a3f 100644
--- a/src/third_party/wiredtiger/test/format/salvage.c
+++ b/src/third_party/wiredtiger/test/format/salvage.c
@@ -29,124 +29,126 @@
#include "format.h"
/*
+ * uri_path --
+ * Return the path to an object file, and optionally, the object name.
+ */
+static void
+uri_path(TABLE *table, char **object_namep, char *buf, size_t len)
+{
+ char *p;
+
+ /*
+ * It's a little tricky: if the data source is a file, we're looking for the table URI, if the
+ * data source is a table, we're looking for the table URI with a trailing ".wt".
+ */
+ p = strchr(table->uri, ':');
+ testutil_assert(p != NULL);
+ ++p;
+
+ testutil_check(__wt_snprintf(buf, len, "%s/%s", g.home, p));
+ if (object_namep != NULL)
+ *object_namep = strrchr(buf, '/') + 1;
+ if (!access(buf, F_OK))
+ return;
+ testutil_check(__wt_snprintf(buf, len, "%s/%s.wt", g.home, p));
+ if (object_namep != NULL)
+ *object_namep = strrchr(buf, '/') + 1;
+ if (!access(buf, F_OK))
+ return;
+ testutil_die(0, "%s: unable to find file for salvage", table->uri);
+}
+
+/*
* corrupt --
* Corrupt the file in a random way.
*/
-static int
-corrupt(void)
+static void
+corrupt(TABLE *table)
{
struct stat sb;
FILE *fp;
wt_off_t offset;
size_t len, nw;
- int fd, ret;
- char copycmd[2 * 1024], path[1024];
+ int fd;
+ char buf[MAX_FORMAT_PATH * 2], *object_name, path[MAX_FORMAT_PATH];
const char *smash;
- /*
- * If it's a single Btree file (not LSM), open the file, and corrupt roughly 2% of the file at a
- * random spot, including the beginning of the file and overlapping the end.
- *
- * It's a little tricky: if the data source is a file, we're looking for "wt", if the data
- * source is a table, we're looking for "wt.wt".
- */
- testutil_check(__wt_snprintf(path, sizeof(path), "%s/%s", g.home, WT_NAME));
- if ((fd = open(path, O_RDWR)) != -1) {
- testutil_check(__wt_snprintf(copycmd, sizeof(copycmd),
- "cp %s/%s %s/SALVAGE.copy/%s.corrupted", g.home, WT_NAME, g.home, WT_NAME));
- goto found;
- }
- testutil_check(__wt_snprintf(path, sizeof(path), "%s/%s.wt", g.home, WT_NAME));
- if ((fd = open(path, O_RDWR)) != -1) {
- testutil_check(__wt_snprintf(copycmd, sizeof(copycmd),
- "cp %s/%s.wt %s/SALVAGE.copy/%s.wt.corrupted", g.home, WT_NAME, g.home, WT_NAME));
- goto found;
- }
- return (0);
+ uri_path(table, &object_name, path, sizeof(path));
-found:
- if (fstat(fd, &sb) == -1)
- testutil_die(errno, "salvage-corrupt: fstat");
+ fd = open(path, O_RDWR);
+ testutil_assert(fd != -1);
- offset = mmrand(NULL, 0, (u_int)sb.st_size);
- len = (size_t)(20 + (sb.st_size / 100) * 2);
- testutil_check(__wt_snprintf(path, sizeof(path), "%s/SALVAGE.corrupt", g.home));
- if ((fp = fopen(path, "w")) == NULL)
- testutil_die(errno, "salvage-corrupt: open: %s", path);
+ /*
+ * Corrupt a chunk of the file at a random spot, including the first bytes of the file and
+ * possibly overlapping the end. The length of the corruption is roughly 2% of the file, not
+ * exceeding a megabyte (so we aren't just corrupting the whole file).
+ */
+ testutil_check(fstat(fd, &sb));
+ offset = mmrand(NULL, 0, (u_int)sb.st_size - 1024);
+ len = (size_t)(sb.st_size * 2) / 100;
+ len += 4 * 1024;
+ len = WT_MIN(len, WT_MEGABYTE);
+
+ /* Log the corruption offset and length. */
+ testutil_check(__wt_snprintf(buf, sizeof(buf), "%s/SALVAGE.corrupt", g.home));
+ testutil_assert((fp = fopen(buf, "w")) != NULL);
(void)fprintf(fp, "salvage-corrupt: offset %" PRIuMAX ", length %" WT_SIZET_FMT "\n",
(uintmax_t)offset, len);
fclose_and_clear(&fp);
- if (lseek(fd, offset, SEEK_SET) == -1)
- testutil_die(errno, "salvage-corrupt: lseek");
-
+ testutil_assert(lseek(fd, offset, SEEK_SET) != -1);
smash = "!!! memory corrupted by format to test salvage ";
for (; len > 0; len -= nw) {
nw = (size_t)(len > strlen(smash) ? strlen(smash) : len);
- if (write(fd, smash, nw) == -1)
- testutil_die(errno, "salvage-corrupt: write");
+ testutil_assert(write(fd, smash, nw) != -1);
}
- if (close(fd) == -1)
- testutil_die(errno, "salvage-corrupt: close");
+ testutil_check(close(fd));
- /*
- * Save a copy of the corrupted file so we can replay the salvage step as necessary.
- */
- if ((ret = system(copycmd)) != 0)
- testutil_die(ret, "salvage corrupt copy step failed");
-
- return (1);
+ /* Save a copy of the corrupted file so we can replay the salvage step as necessary. */
+ testutil_check(__wt_snprintf(
+ buf, sizeof(buf), "cp %s %s/SALVAGE.copy/%s.corrupted", path, g.home, object_name));
+ testutil_check(system(buf));
}
-/*
- * Salvage command, save the interesting files so we can replay the salvage command as necessary.
- *
- * Redirect the "cd" command to /dev/null so chatty cd implementations don't add the new working
- * directory to our output.
- */
-#define SALVAGE_COPY_CMD \
- "cd %s > /dev/null && " \
- "rm -rf SALVAGE.copy && mkdir SALVAGE.copy && " \
- "cp WiredTiger* wt* SALVAGE.copy/"
+/* Salvage command, save the interesting files so we can replay the salvage command as necessary. */
+#define SALVAGE_COPY_CMD \
+ "rm -rf %s/SALVAGE.copy && mkdir %s/SALVAGE.copy && cp %s/WiredTiger* %s %s/SALVAGE.copy/"
/*
* wts_salvage --
* Salvage testing.
*/
void
-wts_salvage(void)
+wts_salvage(TABLE *table, void *arg)
{
WT_CONNECTION *conn;
- WT_DECL_RET;
WT_SESSION *session;
- size_t len;
- char *cmd;
+ char buf[MAX_FORMAT_PATH * 5], path[MAX_FORMAT_PATH];
- if (g.c_salvage == 0)
- return;
+ (void)arg; /* unused argument */
- track("salvage", 0ULL, NULL);
+ if (GV(OPS_SALVAGE) == 0 || DATASOURCE(table, "lsm"))
+ return;
/* Save a copy of the interesting files so we can replay the salvage step as necessary. */
- len = strlen(g.home) + strlen(SALVAGE_COPY_CMD) + 1;
- cmd = dmalloc(len);
- testutil_check(__wt_snprintf(cmd, len, SALVAGE_COPY_CMD, g.home));
- if ((ret = system(cmd)) != 0)
- testutil_die(ret, "salvage copy (\"%s\"), failed", cmd);
- free(cmd);
+ uri_path(table, NULL, path, sizeof(path));
+ testutil_check(
+ __wt_snprintf(buf, sizeof(buf), SALVAGE_COPY_CMD, g.home, g.home, g.home, path, g.home));
+ testutil_check(system(buf));
/* Salvage, then verify. */
wts_open(g.home, &conn, &session, true);
- testutil_check(session->salvage(session, g.uri, "force=true"));
- wts_verify(conn, "post-salvage verify");
+ session->app_private = table->track_prefix;
+ testutil_check(session->salvage(session, table->uri, "force=true"));
+ wts_verify(table, conn);
wts_close(&conn, &session);
/* Corrupt the file randomly, salvage, then verify. */
- if (corrupt()) {
- wts_open(g.home, &conn, &session, false);
- testutil_check(session->salvage(session, g.uri, "force=true"));
- wts_verify(conn, "post-corrupt-salvage verify");
- wts_close(&conn, &session);
- }
+ corrupt(table);
+ wts_open(g.home, &conn, &session, false);
+ testutil_check(session->salvage(session, table->uri, "force=true"));
+ wts_verify(table, conn);
+
+ wts_close(&conn, &session);
}