summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/src/cursor/cur_backup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/src/cursor/cur_backup.c')
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_backup.c934
1 files changed, 447 insertions, 487 deletions
diff --git a/src/third_party/wiredtiger/src/cursor/cur_backup.c b/src/third_party/wiredtiger/src/cursor/cur_backup.c
index ada12f43977..656cb3ac3a1 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_backup.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_backup.c
@@ -9,612 +9,572 @@
#include "wt_internal.h"
static int __backup_all(WT_SESSION_IMPL *);
-static int __backup_list_append(
- WT_SESSION_IMPL *, WT_CURSOR_BACKUP *, const char *);
+static int __backup_list_append(WT_SESSION_IMPL *, WT_CURSOR_BACKUP *, const char *);
static int __backup_list_uri_append(WT_SESSION_IMPL *, const char *, bool *);
-static int __backup_start(
- WT_SESSION_IMPL *, WT_CURSOR_BACKUP *, bool, const char *[]);
+static int __backup_start(WT_SESSION_IMPL *, WT_CURSOR_BACKUP *, bool, const char *[]);
static int __backup_stop(WT_SESSION_IMPL *, WT_CURSOR_BACKUP *);
-static int __backup_uri(
- WT_SESSION_IMPL *, const char *[], bool, bool *, bool *);
+static int __backup_uri(WT_SESSION_IMPL *, const char *[], bool, bool *, bool *);
/*
* __curbackup_next --
- * WT_CURSOR->next method for the backup cursor type.
+ * WT_CURSOR->next method for the backup cursor type.
*/
static int
__curbackup_next(WT_CURSOR *cursor)
{
- WT_CURSOR_BACKUP *cb;
- WT_DECL_RET;
- WT_SESSION_IMPL *session;
+ WT_CURSOR_BACKUP *cb;
+ WT_DECL_RET;
+ WT_SESSION_IMPL *session;
- cb = (WT_CURSOR_BACKUP *)cursor;
- CURSOR_API_CALL(cursor, session, next, NULL);
+ cb = (WT_CURSOR_BACKUP *)cursor;
+ CURSOR_API_CALL(cursor, session, next, NULL);
- if (cb->list == NULL || cb->list[cb->next] == NULL) {
- F_CLR(cursor, WT_CURSTD_KEY_SET);
- WT_ERR(WT_NOTFOUND);
- }
+ if (cb->list == NULL || cb->list[cb->next] == NULL) {
+ F_CLR(cursor, WT_CURSTD_KEY_SET);
+ WT_ERR(WT_NOTFOUND);
+ }
- cb->iface.key.data = cb->list[cb->next];
- cb->iface.key.size = strlen(cb->list[cb->next]) + 1;
- ++cb->next;
+ cb->iface.key.data = cb->list[cb->next];
+ cb->iface.key.size = strlen(cb->list[cb->next]) + 1;
+ ++cb->next;
- F_SET(cursor, WT_CURSTD_KEY_INT);
+ F_SET(cursor, WT_CURSTD_KEY_INT);
-err: API_END_RET(session, ret);
+err:
+ API_END_RET(session, ret);
}
/*
* __curbackup_reset --
- * WT_CURSOR->reset method for the backup cursor type.
+ * WT_CURSOR->reset method for the backup cursor type.
*/
static int
__curbackup_reset(WT_CURSOR *cursor)
{
- WT_CURSOR_BACKUP *cb;
- WT_DECL_RET;
- WT_SESSION_IMPL *session;
+ WT_CURSOR_BACKUP *cb;
+ WT_DECL_RET;
+ WT_SESSION_IMPL *session;
- cb = (WT_CURSOR_BACKUP *)cursor;
- CURSOR_API_CALL_PREPARE_ALLOWED(cursor, session, reset, NULL);
+ cb = (WT_CURSOR_BACKUP *)cursor;
+ CURSOR_API_CALL_PREPARE_ALLOWED(cursor, session, reset, NULL);
- cb->next = 0;
- F_CLR(cursor, WT_CURSTD_KEY_SET | WT_CURSTD_VALUE_SET);
+ cb->next = 0;
+ F_CLR(cursor, WT_CURSTD_KEY_SET | WT_CURSTD_VALUE_SET);
-err: API_END_RET(session, ret);
+err:
+ API_END_RET(session, ret);
}
/*
* __backup_free --
- * Free list resources for a backup cursor.
+ * Free list resources for a backup cursor.
*/
static void
__backup_free(WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb)
{
- int i;
-
- if (cb->list != NULL) {
- for (i = 0; cb->list[i] != NULL; ++i)
- __wt_free(session, cb->list[i]);
- __wt_free(session, cb->list);
- }
+ int i;
+ if (cb->list != NULL) {
+ for (i = 0; cb->list[i] != NULL; ++i)
+ __wt_free(session, cb->list[i]);
+ __wt_free(session, cb->list);
+ }
}
/*
* __curbackup_close --
- * WT_CURSOR->close method for the backup cursor type.
+ * WT_CURSOR->close method for the backup cursor type.
*/
static int
__curbackup_close(WT_CURSOR *cursor)
{
- WT_CURSOR_BACKUP *cb;
- WT_DECL_RET;
- WT_SESSION_IMPL *session;
+ WT_CURSOR_BACKUP *cb;
+ WT_DECL_RET;
+ WT_SESSION_IMPL *session;
- cb = (WT_CURSOR_BACKUP *)cursor;
- CURSOR_API_CALL_PREPARE_ALLOWED(cursor, session, close, NULL);
+ cb = (WT_CURSOR_BACKUP *)cursor;
+ CURSOR_API_CALL_PREPARE_ALLOWED(cursor, session, close, NULL);
err:
- /*
- * When starting a hot backup, we serialize hot backup cursors and set
- * the connection's hot-backup flag. Once that's done, we set the
- * cursor's backup-locker flag, implying the cursor owns all necessary
- * cleanup (including removing temporary files), regardless of error or
- * success. The cursor's backup-locker flag is never cleared (it's just
- * discarded when the cursor is closed), because that cursor will never
- * not be responsible for cleanup.
- */
- if (F_ISSET(cb, WT_CURBACKUP_DUP)) {
- __backup_free(session, cb);
- /* Make sure the original backup cursor is still open. */
- WT_ASSERT(session, F_ISSET(session, WT_SESSION_BACKUP_CURSOR));
- F_CLR(session, WT_SESSION_BACKUP_DUP);
- F_CLR(cb, WT_CURBACKUP_DUP);
- } else if (F_ISSET(cb, WT_CURBACKUP_LOCKER))
- WT_TRET(__backup_stop(session, cb));
-
- __wt_cursor_close(cursor);
- session->bkp_cursor = NULL;
-
- API_END_RET(session, ret);
+ /*
+ * When starting a hot backup, we serialize hot backup cursors and set the connection's
+ * hot-backup flag. Once that's done, we set the cursor's backup-locker flag, implying the
+ * cursor owns all necessary cleanup (including removing temporary files), regardless of error
+ * or success. The cursor's backup-locker flag is never cleared (it's just discarded when the
+ * cursor is closed), because that cursor will never not be responsible for cleanup.
+ */
+ if (F_ISSET(cb, WT_CURBACKUP_DUP)) {
+ __backup_free(session, cb);
+ /* Make sure the original backup cursor is still open. */
+ WT_ASSERT(session, F_ISSET(session, WT_SESSION_BACKUP_CURSOR));
+ F_CLR(session, WT_SESSION_BACKUP_DUP);
+ F_CLR(cb, WT_CURBACKUP_DUP);
+ } else if (F_ISSET(cb, WT_CURBACKUP_LOCKER))
+ WT_TRET(__backup_stop(session, cb));
+
+ __wt_cursor_close(cursor);
+ session->bkp_cursor = NULL;
+
+ API_END_RET(session, ret);
}
/*
* __wt_curbackup_open --
- * WT_SESSION->open_cursor method for the backup cursor type.
+ * WT_SESSION->open_cursor method for the backup cursor type.
*/
int
-__wt_curbackup_open(WT_SESSION_IMPL *session, const char *uri,
- WT_CURSOR *other, const char *cfg[], WT_CURSOR **cursorp)
+__wt_curbackup_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *other, const char *cfg[],
+ WT_CURSOR **cursorp)
{
- WT_CURSOR_STATIC_INIT(iface,
- __wt_cursor_get_key, /* get-key */
- __wt_cursor_get_value_notsup, /* get-value */
- __wt_cursor_set_key_notsup, /* set-key */
- __wt_cursor_set_value_notsup, /* set-value */
- __wt_cursor_compare_notsup, /* compare */
- __wt_cursor_equals_notsup, /* equals */
- __curbackup_next, /* next */
- __wt_cursor_notsup, /* prev */
- __curbackup_reset, /* reset */
- __wt_cursor_notsup, /* search */
- __wt_cursor_search_near_notsup, /* search-near */
- __wt_cursor_notsup, /* insert */
- __wt_cursor_modify_notsup, /* modify */
- __wt_cursor_notsup, /* update */
- __wt_cursor_notsup, /* remove */
- __wt_cursor_notsup, /* reserve */
- __wt_cursor_reconfigure_notsup, /* reconfigure */
- __wt_cursor_notsup, /* cache */
- __wt_cursor_reopen_notsup, /* reopen */
- __curbackup_close); /* close */
- WT_CURSOR *cursor;
- WT_CURSOR_BACKUP *cb;
- WT_DECL_RET;
-
- WT_STATIC_ASSERT(offsetof(WT_CURSOR_BACKUP, iface) == 0);
-
- WT_RET(__wt_calloc_one(session, &cb));
- cursor = (WT_CURSOR *)cb;
- *cursor = iface;
- cursor->session = (WT_SESSION *)session;
- cursor->key_format = "S"; /* Return the file names as the key. */
- cursor->value_format = ""; /* No value. */
-
- session->bkp_cursor = cb;
-
- /*
- * Start the backup and fill in the cursor's list. Acquire the schema
- * lock, we need a consistent view when creating a copy.
- */
- WT_WITH_CHECKPOINT_LOCK(session,
- WT_WITH_SCHEMA_LOCK(session,
- ret = __backup_start(session, cb, other != NULL, cfg)));
- WT_ERR(ret);
-
- WT_ERR(__wt_cursor_init(cursor, uri, NULL, cfg, cursorp));
-
- if (0) {
-err: WT_TRET(__curbackup_close(cursor));
- *cursorp = NULL;
- }
-
- return (ret);
+ WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */
+ __wt_cursor_get_value_notsup, /* get-value */
+ __wt_cursor_set_key_notsup, /* set-key */
+ __wt_cursor_set_value_notsup, /* set-value */
+ __wt_cursor_compare_notsup, /* compare */
+ __wt_cursor_equals_notsup, /* equals */
+ __curbackup_next, /* next */
+ __wt_cursor_notsup, /* prev */
+ __curbackup_reset, /* reset */
+ __wt_cursor_notsup, /* search */
+ __wt_cursor_search_near_notsup, /* search-near */
+ __wt_cursor_notsup, /* insert */
+ __wt_cursor_modify_notsup, /* modify */
+ __wt_cursor_notsup, /* update */
+ __wt_cursor_notsup, /* remove */
+ __wt_cursor_notsup, /* reserve */
+ __wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* cache */
+ __wt_cursor_reopen_notsup, /* reopen */
+ __curbackup_close); /* close */
+ WT_CURSOR *cursor;
+ WT_CURSOR_BACKUP *cb;
+ WT_DECL_RET;
+
+ WT_STATIC_ASSERT(offsetof(WT_CURSOR_BACKUP, iface) == 0);
+
+ WT_RET(__wt_calloc_one(session, &cb));
+ cursor = (WT_CURSOR *)cb;
+ *cursor = iface;
+ cursor->session = (WT_SESSION *)session;
+ cursor->key_format = "S"; /* Return the file names as the key. */
+ cursor->value_format = ""; /* No value. */
+
+ session->bkp_cursor = cb;
+
+ /*
+ * Start the backup and fill in the cursor's list. Acquire the schema lock, we need a consistent
+ * view when creating a copy.
+ */
+ WT_WITH_CHECKPOINT_LOCK(
+ session, WT_WITH_SCHEMA_LOCK(session, ret = __backup_start(session, cb, other != NULL, cfg)));
+ WT_ERR(ret);
+
+ WT_ERR(__wt_cursor_init(cursor, uri, NULL, cfg, cursorp));
+
+ if (0) {
+err:
+ WT_TRET(__curbackup_close(cursor));
+ *cursorp = NULL;
+ }
+
+ return (ret);
}
/*
* __backup_log_append --
- * Append log files needed for backup.
+ * Append log files needed for backup.
*/
static int
__backup_log_append(WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb, bool active)
{
- WT_CONNECTION_IMPL *conn;
- WT_DECL_RET;
- u_int i, logcount;
- char **logfiles;
-
- conn = S2C(session);
- logfiles = NULL;
- logcount = 0;
- ret = 0;
-
- if (conn->log) {
- WT_ERR(__wt_log_get_backup_files(
- session, &logfiles, &logcount, &cb->maxid, active));
- for (i = 0; i < logcount; i++)
- WT_ERR(__backup_list_append(session, cb, logfiles[i]));
- }
-err: WT_TRET(__wt_fs_directory_list_free(session, &logfiles, logcount));
- return (ret);
+ WT_CONNECTION_IMPL *conn;
+ WT_DECL_RET;
+ u_int i, logcount;
+ char **logfiles;
+
+ conn = S2C(session);
+ logfiles = NULL;
+ logcount = 0;
+ ret = 0;
+
+ if (conn->log) {
+ WT_ERR(__wt_log_get_backup_files(session, &logfiles, &logcount, &cb->maxid, active));
+ for (i = 0; i < logcount; i++)
+ WT_ERR(__backup_list_append(session, cb, logfiles[i]));
+ }
+err:
+ WT_TRET(__wt_fs_directory_list_free(session, &logfiles, logcount));
+ return (ret);
}
/*
* __backup_start --
- * Start a backup.
+ * Start a backup.
*/
static int
-__backup_start(WT_SESSION_IMPL *session,
- WT_CURSOR_BACKUP *cb, bool is_dup, const char *cfg[])
+__backup_start(WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb, bool is_dup, const char *cfg[])
{
- WT_CONNECTION_IMPL *conn;
- WT_DECL_RET;
- WT_FSTREAM *srcfs;
- const char *dest;
- bool exist, log_only, target_list;
-
- conn = S2C(session);
- srcfs = NULL;
- dest = NULL;
-
- cb->next = 0;
- cb->list = NULL;
- cb->list_next = 0;
-
- WT_RET(__wt_inmem_unsupported_op(session, "backup cursor"));
-
- /*
- * Single thread hot backups: we're holding the schema lock, so we
- * know we'll serialize with other attempts to start a hot backup.
- */
- if (conn->hot_backup && !is_dup)
- WT_RET_MSG(
- session, EINVAL, "there is already a backup cursor open");
-
- if (F_ISSET(session, WT_SESSION_BACKUP_DUP) && is_dup)
- WT_RET_MSG(session, EINVAL,
- "there is already a duplicate backup cursor open");
-
- if (!is_dup) {
- /*
- * The hot backup copy is done outside of WiredTiger, which
- * means file blocks can't be freed and re-allocated until the
- * backup completes. The checkpoint code checks the backup flag,
- * and if a backup cursor is open checkpoints aren't discarded.
- * We release the lock as soon as we've set the flag, we don't
- * want to block checkpoints, we just want to make sure no
- * checkpoints are deleted. The checkpoint code holds the lock
- * until it's finished the checkpoint, otherwise we could start
- * a hot backup that would race with an already-started
- * checkpoint.
- *
- * We are holding the checkpoint and schema locks so schema
- * operations will not see the backup file list until it is
- * complete and valid.
- */
- WT_WITH_HOTBACKUP_WRITE_LOCK(session,
- WT_CONN_HOTBACKUP_START(conn));
-
- /* We're the lock holder, we own cleanup. */
- F_SET(cb, WT_CURBACKUP_LOCKER);
-
- /*
- * Create a temporary backup file. This must be opened before
- * generating the list of targets in backup_uri. This file will
- * later be renamed to the correct name depending on whether or
- * not we're doing an incremental backup. We need a temp file
- * so that if we fail or crash while filling it, the existence
- * of a partial file doesn't confuse restarting in the source
- * database.
- */
- WT_ERR(__wt_fopen(session, WT_BACKUP_TMP,
- WT_FS_OPEN_CREATE, WT_STREAM_WRITE, &cb->bfs));
- }
-
- /*
- * If targets were specified, add them to the list. Otherwise it is a
- * full backup, add all database objects and log files to the list.
- */
- target_list = false;
- WT_ERR(__backup_uri(session,
- cfg, is_dup, &target_list, &log_only));
- /*
- * For a duplicate cursor, all the work is done in backup_uri. The only
- * usage accepted is "target=("log:")" so error if not log only.
- */
- if (is_dup) {
- if (!log_only)
- WT_ERR_MSG(session, EINVAL,
- "duplicate backup cursor must be for logs only.");
- F_SET(cb, WT_CURBACKUP_DUP);
- F_SET(session, WT_SESSION_BACKUP_DUP);
- goto done;
- }
- if (!target_list) {
- /*
- * It's important to first gather the log files to be copied
- * (which internally starts a new log file), followed by
- * choosing a checkpoint to reference in the WiredTiger.backup
- * file.
- *
- * Applications may have logic that takes a checkpoint, followed
- * by performing a write that should only appear in the new
- * checkpoint. This ordering prevents choosing the prior
- * checkpoint, but including the write in the log files
- * returned.
- *
- * It is also possible, and considered legal, to choose the new
- * checkpoint, but not include the log file that contains the
- * log entry for taking the new checkpoint.
- */
- WT_ERR(__backup_log_append(session, cb, true));
- WT_ERR(__backup_all(session));
- }
-
- /* Add the hot backup and standard WiredTiger files to the list. */
- if (log_only) {
- /*
- * If this is not a duplicate cursor, using the log target is an
- * incremental backup. If this is a duplicate cursor then using
- * the log target on an existing backup cursor means this cursor
- * returns the current list of log files. That list was set up
- * when parsing the URI so we don't have anything to do here.
- *
- * We also open an incremental backup source file so that we can
- * detect a crash with an incremental backup existing in the
- * source directory versus an improper destination.
- */
- dest = WT_INCREMENTAL_BACKUP;
- WT_ERR(__wt_fopen(session, WT_INCREMENTAL_SRC,
- WT_FS_OPEN_CREATE, WT_STREAM_WRITE, &srcfs));
- WT_ERR(__backup_list_append(
- session, cb, WT_INCREMENTAL_BACKUP));
- } else {
- dest = WT_METADATA_BACKUP;
- WT_ERR(__backup_list_append(session, cb, WT_METADATA_BACKUP));
- WT_ERR(__wt_fs_exist(session, WT_BASECONFIG, &exist));
- if (exist)
- WT_ERR(__backup_list_append(
- session, cb, WT_BASECONFIG));
- WT_ERR(__wt_fs_exist(session, WT_USERCONFIG, &exist));
- if (exist)
- WT_ERR(__backup_list_append(
- session, cb, WT_USERCONFIG));
- WT_ERR(__backup_list_append(session, cb, WT_WIREDTIGER));
- }
+ WT_CONNECTION_IMPL *conn;
+ WT_DECL_RET;
+ WT_FSTREAM *srcfs;
+ const char *dest;
+ bool exist, log_only, target_list;
+
+ conn = S2C(session);
+ srcfs = NULL;
+ dest = NULL;
+
+ cb->next = 0;
+ cb->list = NULL;
+ cb->list_next = 0;
+
+ WT_RET(__wt_inmem_unsupported_op(session, "backup cursor"));
+
+ /*
+ * Single thread hot backups: we're holding the schema lock, so we know we'll serialize with
+ * other attempts to start a hot backup.
+ */
+ if (conn->hot_backup && !is_dup)
+ WT_RET_MSG(session, EINVAL, "there is already a backup cursor open");
+
+ if (F_ISSET(session, WT_SESSION_BACKUP_DUP) && is_dup)
+ WT_RET_MSG(session, EINVAL, "there is already a duplicate backup cursor open");
+
+ if (!is_dup) {
+ /*
+ * The hot backup copy is done outside of WiredTiger, which
+ * means file blocks can't be freed and re-allocated until the
+ * backup completes. The checkpoint code checks the backup flag,
+ * and if a backup cursor is open checkpoints aren't discarded.
+ * We release the lock as soon as we've set the flag, we don't
+ * want to block checkpoints, we just want to make sure no
+ * checkpoints are deleted. The checkpoint code holds the lock
+ * until it's finished the checkpoint, otherwise we could start
+ * a hot backup that would race with an already-started
+ * checkpoint.
+ *
+ * We are holding the checkpoint and schema locks so schema
+ * operations will not see the backup file list until it is
+ * complete and valid.
+ */
+ WT_WITH_HOTBACKUP_WRITE_LOCK(session, WT_CONN_HOTBACKUP_START(conn));
+
+ /* We're the lock holder, we own cleanup. */
+ F_SET(cb, WT_CURBACKUP_LOCKER);
+
+ /*
+ * Create a temporary backup file. This must be opened before generating the list of targets
+ * in backup_uri. This file will later be renamed to the correct name depending on whether
+ * or not we're doing an incremental backup. We need a temp file so that if we fail or crash
+ * while filling it, the existence of a partial file doesn't confuse restarting in the
+ * source database.
+ */
+ WT_ERR(__wt_fopen(session, WT_BACKUP_TMP, WT_FS_OPEN_CREATE, WT_STREAM_WRITE, &cb->bfs));
+ }
+
+ /*
+ * If targets were specified, add them to the list. Otherwise it is a full backup, add all
+ * database objects and log files to the list.
+ */
+ target_list = false;
+ WT_ERR(__backup_uri(session, cfg, is_dup, &target_list, &log_only));
+ /*
+ * For a duplicate cursor, all the work is done in backup_uri. The only usage accepted is
+ * "target=("log:")" so error if not log only.
+ */
+ if (is_dup) {
+ if (!log_only)
+ WT_ERR_MSG(session, EINVAL, "duplicate backup cursor must be for logs only");
+ F_SET(cb, WT_CURBACKUP_DUP);
+ F_SET(session, WT_SESSION_BACKUP_DUP);
+ goto done;
+ }
+ if (!target_list) {
+ /*
+ * It's important to first gather the log files to be copied
+ * (which internally starts a new log file), followed by
+ * choosing a checkpoint to reference in the WiredTiger.backup
+ * file.
+ *
+ * Applications may have logic that takes a checkpoint, followed
+ * by performing a write that should only appear in the new
+ * checkpoint. This ordering prevents choosing the prior
+ * checkpoint, but including the write in the log files
+ * returned.
+ *
+ * It is also possible, and considered legal, to choose the new
+ * checkpoint, but not include the log file that contains the
+ * log entry for taking the new checkpoint.
+ */
+ WT_ERR(__backup_log_append(session, cb, true));
+ WT_ERR(__backup_all(session));
+ }
+
+ /* Add the hot backup and standard WiredTiger files to the list. */
+ if (log_only) {
+ /*
+ * If this is not a duplicate cursor, using the log target is an
+ * incremental backup. If this is a duplicate cursor then using
+ * the log target on an existing backup cursor means this cursor
+ * returns the current list of log files. That list was set up
+ * when parsing the URI so we don't have anything to do here.
+ *
+ * We also open an incremental backup source file so that we can
+ * detect a crash with an incremental backup existing in the
+ * source directory versus an improper destination.
+ */
+ dest = WT_INCREMENTAL_BACKUP;
+ WT_ERR(__wt_fopen(session, WT_INCREMENTAL_SRC, WT_FS_OPEN_CREATE, WT_STREAM_WRITE, &srcfs));
+ WT_ERR(__backup_list_append(session, cb, WT_INCREMENTAL_BACKUP));
+ } else {
+ dest = WT_METADATA_BACKUP;
+ WT_ERR(__backup_list_append(session, cb, WT_METADATA_BACKUP));
+ WT_ERR(__wt_fs_exist(session, WT_BASECONFIG, &exist));
+ if (exist)
+ WT_ERR(__backup_list_append(session, cb, WT_BASECONFIG));
+ WT_ERR(__wt_fs_exist(session, WT_USERCONFIG, &exist));
+ if (exist)
+ WT_ERR(__backup_list_append(session, cb, WT_USERCONFIG));
+ WT_ERR(__backup_list_append(session, cb, WT_WIREDTIGER));
+ }
err:
- /* Close the hot backup file. */
- if (srcfs != NULL)
- WT_TRET(__wt_fclose(session, &srcfs));
- /*
- * Sync and rename the temp file into place.
- */
- if (ret == 0)
- ret = __wt_sync_and_rename(session,
- &cb->bfs, WT_BACKUP_TMP, dest);
- if (ret == 0) {
- WT_WITH_HOTBACKUP_WRITE_LOCK(session,
- conn->hot_backup_list = cb->list);
- F_SET(session, WT_SESSION_BACKUP_CURSOR);
- }
- /*
- * If the file hasn't been closed, do it now.
- */
- if (cb->bfs != NULL)
- WT_TRET(__wt_fclose(session, &cb->bfs));
+ /* Close the hot backup file. */
+ if (srcfs != NULL)
+ WT_TRET(__wt_fclose(session, &srcfs));
+ /*
+ * Sync and rename the temp file into place.
+ */
+ if (ret == 0)
+ ret = __wt_sync_and_rename(session, &cb->bfs, WT_BACKUP_TMP, dest);
+ if (ret == 0) {
+ WT_WITH_HOTBACKUP_WRITE_LOCK(session, conn->hot_backup_list = cb->list);
+ F_SET(session, WT_SESSION_BACKUP_CURSOR);
+ }
+ /*
+ * If the file hasn't been closed, do it now.
+ */
+ if (cb->bfs != NULL)
+ WT_TRET(__wt_fclose(session, &cb->bfs));
done:
- return (ret);
+ return (ret);
}
/*
* __backup_stop --
- * Stop a backup.
+ * Stop a backup.
*/
static int
__backup_stop(WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb)
{
- WT_CONNECTION_IMPL *conn;
- WT_DECL_RET;
+ WT_CONNECTION_IMPL *conn;
+ WT_DECL_RET;
- conn = S2C(session);
+ conn = S2C(session);
- /* Release all btree names held by the backup. */
- WT_ASSERT(session, !F_ISSET(cb, WT_CURBACKUP_DUP));
- /* If it's not a dup backup cursor, make sure one isn't open. */
- WT_ASSERT(session, !F_ISSET(session, WT_SESSION_BACKUP_DUP));
- WT_WITH_HOTBACKUP_WRITE_LOCK(session, conn->hot_backup_list = NULL);
- __backup_free(session, cb);
+ /* Release all btree names held by the backup. */
+ WT_ASSERT(session, !F_ISSET(cb, WT_CURBACKUP_DUP));
+ /* If it's not a dup backup cursor, make sure one isn't open. */
+ WT_ASSERT(session, !F_ISSET(session, WT_SESSION_BACKUP_DUP));
+ WT_WITH_HOTBACKUP_WRITE_LOCK(session, conn->hot_backup_list = NULL);
+ __backup_free(session, cb);
- /* Remove any backup specific file. */
- WT_TRET(__wt_backup_file_remove(session));
+ /* Remove any backup specific file. */
+ WT_TRET(__wt_backup_file_remove(session));
- /* Checkpoint deletion and next hot backup can proceed. */
- WT_WITH_HOTBACKUP_WRITE_LOCK(session, conn->hot_backup = false);
- F_CLR(session, WT_SESSION_BACKUP_CURSOR);
+ /* Checkpoint deletion and next hot backup can proceed. */
+ WT_WITH_HOTBACKUP_WRITE_LOCK(session, conn->hot_backup = false);
+ F_CLR(session, WT_SESSION_BACKUP_CURSOR);
- return (ret);
+ return (ret);
}
/*
* __backup_all --
- * Backup all objects in the database.
+ * Backup all objects in the database.
*/
static int
__backup_all(WT_SESSION_IMPL *session)
{
- /* Build a list of the file objects that need to be copied. */
- return (__wt_meta_apply_all(
- session, NULL, __backup_list_uri_append, NULL));
+ /* Build a list of the file objects that need to be copied. */
+ return (__wt_meta_apply_all(session, NULL, __backup_list_uri_append, NULL));
}
/*
* __backup_uri --
- * Backup a list of objects.
+ * Backup a list of objects.
*/
static int
-__backup_uri(WT_SESSION_IMPL *session, const char *cfg[],
- bool is_dup, bool *foundp, bool *log_only)
+__backup_uri(WT_SESSION_IMPL *session, const char *cfg[], bool is_dup, bool *foundp, bool *log_only)
{
- WT_CONFIG targetconf;
- WT_CONFIG_ITEM cval, k, v;
- WT_DECL_ITEM(tmp);
- WT_DECL_RET;
- const char *uri;
- bool target_list;
-
- *foundp = *log_only = false;
-
- /*
- * If we find a non-empty target configuration string, we have a job,
- * otherwise it's not our problem.
- */
- WT_RET(__wt_config_gets(session, cfg, "target", &cval));
- __wt_config_subinit(session, &targetconf, &cval);
- for (target_list = false;
- (ret = __wt_config_next(&targetconf, &k, &v)) == 0;
- target_list = true) {
- /* If it is our first time through, allocate. */
- if (!target_list) {
- *foundp = true;
- WT_ERR(__wt_scr_alloc(session, 512, &tmp));
- }
-
- WT_ERR(__wt_buf_fmt(session, tmp, "%.*s", (int)k.len, k.str));
- uri = tmp->data;
- if (v.len != 0)
- WT_ERR_MSG(session, EINVAL,
- "%s: invalid backup target: URIs may need quoting",
- uri);
-
- /*
- * Handle log targets. We do not need to go through the schema
- * worker, just call the function to append them. Set log_only
- * only if it is our only URI target.
- */
- if (WT_PREFIX_MATCH(uri, "log:")) {
- /*
- * Log archive cannot mix with incremental backup, don't
- * let that happen. If we're a duplicate cursor
- * archiving is already temporarily suspended.
- */
- if (!is_dup && FLD_ISSET(
- S2C(session)->log_flags, WT_CONN_LOG_ARCHIVE))
- WT_ERR_MSG(session, EINVAL,
- "incremental backup not possible when "
- "automatic log archival configured");
- *log_only = !target_list;
- WT_ERR(__backup_log_append(
- session, session->bkp_cursor, false));
- } else {
- *log_only = false;
-
- /*
- * If backing up individual tables, we have to include
- * indexes, which may involve opening those indexes.
- * Acquire the table lock in write mode for that case.
- */
- WT_WITH_TABLE_WRITE_LOCK(session,
- ret = __wt_schema_worker(session,
- uri, NULL, __backup_list_uri_append, cfg, 0));
- WT_ERR(ret);
- }
- }
- WT_ERR_NOTFOUND_OK(ret);
-
-err: __wt_scr_free(session, &tmp);
- return (ret);
+ WT_CONFIG targetconf;
+ WT_CONFIG_ITEM cval, k, v;
+ WT_DECL_ITEM(tmp);
+ WT_DECL_RET;
+ const char *uri;
+ bool target_list;
+
+ *foundp = *log_only = false;
+
+ /*
+ * If we find a non-empty target configuration string, we have a job, otherwise it's not our
+ * problem.
+ */
+ WT_RET(__wt_config_gets(session, cfg, "target", &cval));
+ __wt_config_subinit(session, &targetconf, &cval);
+ for (target_list = false; (ret = __wt_config_next(&targetconf, &k, &v)) == 0;
+ target_list = true) {
+ /* If it is our first time through, allocate. */
+ if (!target_list) {
+ *foundp = true;
+ WT_ERR(__wt_scr_alloc(session, 512, &tmp));
+ }
+
+ WT_ERR(__wt_buf_fmt(session, tmp, "%.*s", (int)k.len, k.str));
+ uri = tmp->data;
+ if (v.len != 0)
+ WT_ERR_MSG(session, EINVAL, "%s: invalid backup target: URIs may need quoting", uri);
+
+ /*
+ * Handle log targets. We do not need to go through the schema worker, just call the
+ * function to append them. Set log_only only if it is our only URI target.
+ */
+ if (WT_PREFIX_MATCH(uri, "log:")) {
+ /*
+ * Log archive cannot mix with incremental backup, don't let that happen. If we're a
+ * duplicate cursor archiving is already temporarily suspended.
+ */
+ if (!is_dup && FLD_ISSET(S2C(session)->log_flags, WT_CONN_LOG_ARCHIVE))
+ WT_ERR_MSG(session, EINVAL,
+ "incremental backup not possible when "
+ "automatic log archival configured");
+ *log_only = !target_list;
+ WT_ERR(__backup_log_append(session, session->bkp_cursor, false));
+ } else {
+ *log_only = false;
+
+ /*
+ * If backing up individual tables, we have to include indexes, which may involve
+ * opening those indexes. Acquire the table lock in write mode for that case.
+ */
+ WT_WITH_TABLE_WRITE_LOCK(session,
+ ret = __wt_schema_worker(session, uri, NULL, __backup_list_uri_append, cfg, 0));
+ WT_ERR(ret);
+ }
+ }
+ WT_ERR_NOTFOUND_OK(ret);
+
+err:
+ __wt_scr_free(session, &tmp);
+ return (ret);
}
/*
* __wt_backup_file_remove --
- * Remove the incremental and meta-data backup files.
+ * Remove the incremental and meta-data backup files.
*/
int
__wt_backup_file_remove(WT_SESSION_IMPL *session)
{
- WT_DECL_RET;
-
- /*
- * Note that order matters for removing the incremental files. We must
- * remove the backup file before removing the source file so that we
- * always know we were a source directory while there's any chance of
- * an incremental backup file existing.
- */
- WT_TRET(__wt_remove_if_exists(session, WT_BACKUP_TMP, true));
- WT_TRET(__wt_remove_if_exists(session, WT_INCREMENTAL_BACKUP, true));
- WT_TRET(__wt_remove_if_exists(session, WT_INCREMENTAL_SRC, true));
- WT_TRET(__wt_remove_if_exists(session, WT_METADATA_BACKUP, true));
- return (ret);
+ WT_DECL_RET;
+
+ /*
+ * Note that order matters for removing the incremental files. We must remove the backup file
+ * before removing the source file so that we always know we were a source directory while
+ * there's any chance of an incremental backup file existing.
+ */
+ WT_TRET(__wt_remove_if_exists(session, WT_BACKUP_TMP, true));
+ WT_TRET(__wt_remove_if_exists(session, WT_INCREMENTAL_BACKUP, true));
+ WT_TRET(__wt_remove_if_exists(session, WT_INCREMENTAL_SRC, true));
+ WT_TRET(__wt_remove_if_exists(session, WT_METADATA_BACKUP, true));
+ return (ret);
}
/*
* __backup_list_uri_append --
- * Append a new file name to the list, allocate space as necessary.
- * Called via the schema_worker function.
+ * Append a new file name to the list, allocate space as necessary. Called via the schema_worker
+ * function.
*/
static int
-__backup_list_uri_append(
- WT_SESSION_IMPL *session, const char *name, bool *skip)
+__backup_list_uri_append(WT_SESSION_IMPL *session, const char *name, bool *skip)
{
- WT_CURSOR_BACKUP *cb;
- WT_DECL_RET;
- char *value;
-
- cb = session->bkp_cursor;
- WT_UNUSED(skip);
-
- /*
- * While reading the metadata file, check there are no data sources
- * that can't support hot backup. This checks for a data source that's
- * non-standard, which can't be backed up, but is also sanity checking:
- * if there's an entry backed by anything other than a file or lsm
- * entry, we're confused.
- */
- if (!WT_PREFIX_MATCH(name, "file:") &&
- !WT_PREFIX_MATCH(name, "colgroup:") &&
- !WT_PREFIX_MATCH(name, "index:") &&
- !WT_PREFIX_MATCH(name, "lsm:") &&
- !WT_PREFIX_MATCH(name, WT_SYSTEM_PREFIX) &&
- !WT_PREFIX_MATCH(name, "table:"))
- WT_RET_MSG(session, ENOTSUP,
- "hot backup is not supported for objects of type %s",
- name);
-
- /* Ignore the lookaside table or system info. */
- if (strcmp(name, WT_LAS_URI) == 0)
- return (0);
-
- /* Add the metadata entry to the backup file. */
- WT_RET(__wt_metadata_search(session, name, &value));
- ret = __wt_fprintf(session, cb->bfs, "%s\n%s\n", name, value);
- __wt_free(session, value);
- WT_RET(ret);
-
- /*
- * We want to retain the system information in the backup metadata
- * file above, but there is no file object to copy so return now.
- */
- if (WT_PREFIX_MATCH(name, WT_SYSTEM_PREFIX))
- return (0);
-
- /* Add file type objects to the list of files to be copied. */
- if (WT_PREFIX_MATCH(name, "file:"))
- WT_RET(__backup_list_append(session, cb, name));
-
- return (0);
+ WT_CURSOR_BACKUP *cb;
+ WT_DECL_RET;
+ char *value;
+
+ cb = session->bkp_cursor;
+ WT_UNUSED(skip);
+
+ /*
+ * While reading the metadata file, check there are no data sources that can't support hot
+ * backup. This checks for a data source that's non-standard, which can't be backed up, but is
+ * also sanity checking: if there's an entry backed by anything other than a file or lsm entry,
+ * we're confused.
+ */
+ if (!WT_PREFIX_MATCH(name, "file:") && !WT_PREFIX_MATCH(name, "colgroup:") &&
+ !WT_PREFIX_MATCH(name, "index:") && !WT_PREFIX_MATCH(name, "lsm:") &&
+ !WT_PREFIX_MATCH(name, WT_SYSTEM_PREFIX) && !WT_PREFIX_MATCH(name, "table:"))
+ WT_RET_MSG(session, ENOTSUP, "hot backup is not supported for objects of type %s", name);
+
+ /* Ignore the lookaside table or system info. */
+ if (strcmp(name, WT_LAS_URI) == 0)
+ return (0);
+
+ /* Add the metadata entry to the backup file. */
+ WT_RET(__wt_metadata_search(session, name, &value));
+ ret = __wt_fprintf(session, cb->bfs, "%s\n%s\n", name, value);
+ __wt_free(session, value);
+ WT_RET(ret);
+
+ /*
+ * We want to retain the system information in the backup metadata file above, but there is no
+ * file object to copy so return now.
+ */
+ if (WT_PREFIX_MATCH(name, WT_SYSTEM_PREFIX))
+ return (0);
+
+ /* Add file type objects to the list of files to be copied. */
+ if (WT_PREFIX_MATCH(name, "file:"))
+ WT_RET(__backup_list_append(session, cb, name));
+
+ return (0);
}
/*
* __backup_list_append --
- * Append a new file name to the list, allocate space as necessary.
+ * Append a new file name to the list, allocate space as necessary.
*/
static int
-__backup_list_append(
- WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb, const char *uri)
+__backup_list_append(WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb, const char *uri)
{
- const char *name;
- char **p;
-
- /* Leave a NULL at the end to mark the end of the list. */
- WT_RET(__wt_realloc_def(session, &cb->list_allocated,
- cb->list_next + 2, &cb->list));
- p = &cb->list[cb->list_next];
- p[0] = p[1] = NULL;
-
- name = uri;
-
- /*
- * If it's a file in the database we need to remove the prefix.
- */
- if (WT_PREFIX_MATCH(uri, "file:"))
- name += strlen("file:");
-
- /*
- * !!!
- * Assumes metadata file entries map one-to-one to physical files.
- * To support a block manager where that's not the case, we'd need
- * to call into the block manager and get a list of physical files
- * that map to this logical "file". I'm not going to worry about
- * that for now, that block manager might not even support physical
- * copying of files by applications.
- */
- WT_RET(__wt_strdup(session, name, p));
-
- ++cb->list_next;
- return (0);
+ char **p;
+ const char *name;
+
+ /* Leave a NULL at the end to mark the end of the list. */
+ WT_RET(__wt_realloc_def(session, &cb->list_allocated, cb->list_next + 2, &cb->list));
+ p = &cb->list[cb->list_next];
+ p[0] = p[1] = NULL;
+
+ name = uri;
+
+ /*
+ * If it's a file in the database we need to remove the prefix.
+ */
+ if (WT_PREFIX_MATCH(uri, "file:"))
+ name += strlen("file:");
+
+ /*
+ * !!!
+ * Assumes metadata file entries map one-to-one to physical files.
+ * To support a block manager where that's not the case, we'd need
+ * to call into the block manager and get a list of physical files
+ * that map to this logical "file". I'm not going to worry about
+ * that for now, that block manager might not even support physical
+ * copying of files by applications.
+ */
+ WT_RET(__wt_strdup(session, name, p));
+
+ ++cb->list_next;
+ return (0);
}