summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/test/format/backup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/test/format/backup.c')
-rw-r--r--src/third_party/wiredtiger/test/format/backup.c118
1 files changed, 80 insertions, 38 deletions
diff --git a/src/third_party/wiredtiger/test/format/backup.c b/src/third_party/wiredtiger/test/format/backup.c
index 2b1463bd0e3..69fdf771de9 100644
--- a/src/third_party/wiredtiger/test/format/backup.c
+++ b/src/third_party/wiredtiger/test/format/backup.c
@@ -38,7 +38,7 @@ check_copy(void)
WT_CONNECTION *conn;
WT_SESSION *session;
- wts_open(g.home_backup, 0, &conn);
+ wts_open(g.home_backup, false, &conn);
testutil_checkfmt(
conn->open_session(conn, NULL, NULL, &session),
@@ -53,27 +53,30 @@ check_copy(void)
/*
* copy_file --
- * Copy a single file into the backup directory.
+ * Copy a single file into the backup directories.
*/
static void
-copy_file(const char *name)
+copy_file(WT_SESSION *session, const char *name)
{
size_t len;
- char *cmd;
-
- len = strlen(g.home) + strlen(g.home_backup) + strlen(name) * 2 + 20;
- cmd = dmalloc(len);
- (void)snprintf(cmd, len,
- "cp %s/%s %s/%s", g.home, name, g.home_backup, name);
- testutil_checkfmt(system(cmd), "backup copy: %s", cmd);
- free(cmd);
-
- len = strlen(g.home) + strlen(g.home_backup2) + strlen(name) * 2 + 20;
- cmd = dmalloc(len);
- (void)snprintf(cmd, len,
- "cp %s/%s %s/%s", g.home, name, g.home_backup2, name);
- testutil_checkfmt(system(cmd), "backup copy: %s", cmd);
- free(cmd);
+ char *first, *second;
+
+ len = strlen("BACKUP") + strlen(name) + 10;
+ first = dmalloc(len);
+ (void)snprintf(first, len, "BACKUP/%s", name);
+ testutil_check(__wt_copy_and_sync(session, name, first));
+
+ /*
+ * Save another copy of the original file to make debugging recovery
+ * errors easier.
+ */
+ len = strlen("BACKUP_COPY") + strlen(name) + 10;
+ second = dmalloc(len);
+ (void)snprintf(second, len, "BACKUP_COPY/%s", name);
+ testutil_check(__wt_copy_and_sync(session, first, second));
+
+ free(first);
+ free(second);
}
/*
@@ -85,10 +88,11 @@ backup(void *arg)
{
WT_CONNECTION *conn;
WT_CURSOR *backup_cursor;
+ WT_DECL_RET;
WT_SESSION *session;
- u_int period;
- int ret;
- const char *key;
+ u_int incremental, period;
+ bool full;
+ const char *config, *key;
(void)(arg);
@@ -102,48 +106,86 @@ backup(void *arg)
testutil_check(conn->open_session(conn, NULL, NULL, &session));
/*
- * Perform a backup at somewhere under 10 seconds (so we get at
- * least one done), and then at 45 second intervals.
+ * Perform a full backup at somewhere under 10 seconds (that way there's
+ * at least one), then at larger intervals, optionally do incremental
+ * backups between full backups.
*/
- for (period = mmrand(NULL, 1, 10);; period = 45) {
+ incremental = 0;
+ for (period = mmrand(NULL, 1, 10);; period = mmrand(NULL, 20, 45)) {
/* Sleep for short periods so we don't make the run wait. */
while (period > 0 && !g.workers_finished) {
--period;
sleep(1);
}
- if (g.workers_finished)
- break;
- /* Lock out named checkpoints */
+ /*
+ * We can't drop named checkpoints while there's a backup in
+ * progress, serialize backups with named checkpoints. Wait
+ * for the checkpoint to complete, otherwise backups might be
+ * starved out.
+ */
testutil_check(pthread_rwlock_wrlock(&g.backup_lock));
+ if (g.workers_finished) {
+ testutil_check(pthread_rwlock_unlock(&g.backup_lock));
+ break;
+ }
- /* Re-create the backup directory. */
- testutil_checkfmt(
- system(g.home_backup_init),
- "%s", "backup directory creation failed");
+ if (incremental) {
+ config = "target=(\"log:\")";
+ full = false;
+ } else {
+ /* Re-create the backup directory. */
+ testutil_checkfmt(
+ system(g.home_backup_init),
+ "%s", "backup directory creation failed");
+
+ config = NULL;
+ full = true;
+ }
/*
- * open_cursor can return EBUSY if a metadata operation is
- * currently happening - retry in that case.
+ * open_cursor can return EBUSY if concurrent with a metadata
+ * operation, retry in that case.
*/
- while ((ret = session->open_cursor(session,
- "backup:", NULL, NULL, &backup_cursor)) == EBUSY)
- sleep(1);
+ while ((ret = session->open_cursor(
+ session, "backup:", NULL, config, &backup_cursor)) == EBUSY)
+ __wt_yield();
if (ret != 0)
testutil_die(ret, "session.open_cursor: backup");
while ((ret = backup_cursor->next(backup_cursor)) == 0) {
testutil_check(
backup_cursor->get_key(backup_cursor, &key));
- copy_file(key);
+ copy_file(session, key);
}
+ if (ret != WT_NOTFOUND)
+ testutil_die(ret, "backup-cursor");
+
+ /* After an incremental backup, truncate the log files. */
+ if (incremental)
+ testutil_check(session->truncate(
+ session, "log:", backup_cursor, NULL, NULL));
testutil_check(backup_cursor->close(backup_cursor));
testutil_check(pthread_rwlock_unlock(&g.backup_lock));
- check_copy();
+ /*
+ * If automatic log archival isn't configured, optionally do
+ * incremental backups after each full backup. If we're not
+ * doing any more incrementals, verify the backup (we can't
+ * verify intermediate states, once we perform recovery on the
+ * backup database, we can't do any more incremental backups).
+ */
+ if (full)
+ incremental =
+ g.c_logging_archive ? 1 : mmrand(NULL, 1, 5);
+ if (--incremental == 0)
+ check_copy();
}
+ if (incremental != 0)
+ check_copy();
+
testutil_check(session->close(session, NULL));
return (NULL);