/* * __curbackup_close -- * 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; cb = (WT_CURSOR_BACKUP *)cursor; CURSOR_API_CALL(cursor, session, close, NULL); /* * 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_LOCKER)) WT_TRET(__backup_stop(session, cb)); WT_TRET(__wt_cursor_close(cursor)); session->bkp_cursor = NULL; err: API_END_RET(session, ret); }
/* * __curbackup_close -- * 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; int tret; cb = (WT_CURSOR_BACKUP *)cursor; CURSOR_API_CALL(cursor, session, close, NULL); WT_TRET(__backup_cleanup_handles(session, cb)); WT_TRET(__wt_cursor_close(cursor)); session->bkp_cursor = NULL; WT_WITH_SCHEMA_LOCK(session, tret = __backup_stop(session)); /* Stop the backup. */ WT_TRET(tret); err: API_END_RET(session, ret); }
/* * __backup_start -- * Start a backup. */ static int __backup_start( WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb, const char *cfg[]) { WT_CONNECTION_IMPL *conn; WT_DECL_RET; int exist, log_only, target_list; conn = S2C(session); cb->next = 0; cb->list = NULL; /* * 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) WT_RET_MSG( session, EINVAL, "there is already a backup cursor open"); /* * 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. */ __wt_spin_lock(session, &conn->hot_backup_lock); conn->hot_backup = 1; __wt_spin_unlock(session, &conn->hot_backup_lock); /* Create the hot backup file. */ WT_ERR(__backup_file_create(session, cb, 0)); /* Add log files if logging is enabled. */ /* * If a list of targets was specified, work our way through them. * Else, generate a list of all database objects. * * Include log files if doing a full backup, and copy them before * copying data files to avoid rolling the metadata forward across * a checkpoint that completes during the backup. */ target_list = 0; WT_ERR(__backup_uri(session, cb, cfg, &target_list, &log_only)); if (!target_list) { WT_ERR(__backup_log_append(session, cb, 1)); WT_ERR(__backup_all(session, cb)); } /* Add the hot backup and standard WiredTiger files to the list. */ if (log_only) { /* * Close any hot backup file. * We're about to open the incremental backup file. */ if (cb->bfp != NULL) { WT_TRET(fclose(cb->bfp) == 0 ? 0 : __wt_errno()); cb->bfp = NULL; } WT_ERR(__backup_file_create(session, cb, log_only)); WT_ERR(__backup_list_append( session, cb, WT_INCREMENTAL_BACKUP)); } else { WT_ERR(__backup_list_append( session, cb, WT_METADATA_BACKUP)); WT_ERR(__wt_exist(session, WT_BASECONFIG, &exist)); if (exist) WT_ERR(__backup_list_append( session, cb, WT_BASECONFIG)); WT_ERR(__wt_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 (cb->bfp != NULL) { WT_TRET(fclose(cb->bfp) == 0 ? 0 : __wt_errno()); cb->bfp = NULL; } if (ret != 0) { WT_TRET(__backup_cleanup_handles(session, cb)); WT_TRET(__backup_stop(session)); } return (ret); }