/* * __wt_backup_file_remove -- * Remove the incremental and meta-data backup files. */ int __wt_backup_file_remove(WT_SESSION_IMPL *session) { WT_DECL_RET; WT_TRET(__wt_remove_if_exists(session, WT_INCREMENTAL_BACKUP)); WT_TRET(__wt_remove_if_exists(session, WT_METADATA_BACKUP)); return (ret); }
/* * __wt_turtle_update -- * Update the turtle file. */ int __wt_turtle_update(WT_SESSION_IMPL *session, const char *key, const char *value) { WT_FSTREAM *fs; WT_DECL_RET; int vmajor, vminor, vpatch; const char *version; fs = NULL; /* * Create the turtle setup file: we currently re-write it from scratch * every time. */ WT_RET(__wt_fopen(session, WT_METADATA_TURTLE_SET, WT_FS_OPEN_CREATE | WT_FS_OPEN_EXCLUSIVE, WT_STREAM_WRITE, &fs)); version = wiredtiger_version(&vmajor, &vminor, &vpatch); WT_ERR(__wt_fprintf(session, fs, "%s\n%s\n%s\n" "major=%d,minor=%d,patch=%d\n%s\n%s\n", WT_METADATA_VERSION_STR, version, WT_METADATA_VERSION, vmajor, vminor, vpatch, key, value)); /* Flush the stream and rename the file into place. */ ret = __wt_sync_and_rename( session, &fs, WT_METADATA_TURTLE_SET, WT_METADATA_TURTLE); /* Close any file handle left open, remove any temporary file. */ err: WT_TRET(__wt_fclose(session, &fs)); WT_TRET(__wt_remove_if_exists(session, WT_METADATA_TURTLE_SET, false)); return (ret); }
/* * __wt_turtle_init -- * Check the turtle file and create if necessary. */ int __wt_turtle_init(WT_SESSION_IMPL *session) { WT_DECL_RET; int exist, exist_incr; char *metaconf; metaconf = NULL; /* * Discard any turtle setup file left-over from previous runs. This * doesn't matter for correctness, it's just cleaning up random files. */ WT_RET(__wt_remove_if_exists(session, WT_METADATA_TURTLE_SET)); /* * We could die after creating the turtle file and before creating the * metadata file, or worse, the metadata file might be in some random * state. Make sure that doesn't happen: if we don't find the turtle * file, first create the metadata file, load any hot backup, and then * create the turtle file. No matter what happens, if metadata file * creation doesn't fully complete, we won't have a turtle file and we * will repeat the process until we succeed. * * Incremental backups can occur only run recovery is run and it becomes * live. So if there is a turtle file and an incremental backup file * that is an error. Otherwise, if there's already a turtle file, * we're done. */ WT_RET(__wt_exist(session, WT_INCREMENTAL_BACKUP, &exist_incr)); WT_RET(__wt_exist(session, WT_METADATA_TURTLE, &exist)); if (exist) { if (exist_incr) WT_RET_MSG(session, EINVAL, "Incremental backup after running recovery " "is not allowed."); return (0); } if (exist_incr) F_SET(S2C(session), WT_CONN_WAS_BACKUP); /* Create the metadata file. */ WT_RET(__metadata_init(session)); /* Load any hot-backup information. */ WT_RET(__metadata_load_hot_backup(session)); /* Create any bulk-loaded file stubs. */ WT_RET(__metadata_load_bulk(session)); /* Create the turtle file. */ WT_RET(__metadata_config(session, &metaconf)); WT_ERR(__wt_turtle_update(session, WT_METAFILE_URI, metaconf)); /* Remove the backup files, we'll never read them again. */ WT_ERR(__wt_backup_file_remove(session)); err: __wt_free(session, metaconf); return (ret); }
/* * __wt_backup_file_remove -- * 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); }
/* * __meta_track_apply -- * Apply the changes in a metadata tracking record. */ static int __meta_track_apply(WT_SESSION_IMPL *session, WT_META_TRACK *trk) { WT_BM *bm; WT_BTREE *btree; WT_DECL_RET; int tret; switch (trk->op) { case WT_ST_EMPTY: /* Unused slot */ break; case WT_ST_CHECKPOINT: /* Checkpoint, see above */ btree = trk->dhandle->handle; bm = btree->bm; WT_WITH_DHANDLE(session, trk->dhandle, WT_TRET(bm->checkpoint_resolve(bm, session))); break; case WT_ST_DROP_COMMIT: if ((tret = __wt_remove_if_exists(session, trk->a)) != 0) { __wt_err(session, tret, "metadata remove dropped file %s", trk->a); WT_TRET(tret); } break; case WT_ST_LOCK: WT_WITH_DHANDLE(session, trk->dhandle, WT_TRET(__wt_session_release_btree(session))); break; case WT_ST_FILEOP: case WT_ST_REMOVE: case WT_ST_SET: break; WT_ILLEGAL_VALUE(session); } __meta_track_clear(session, trk); return (ret); }
/* * __wt_turtle_update -- * Update the turtle file. */ int __wt_turtle_update( WT_SESSION_IMPL *session, const char *key, const char *value) { WT_FH *fh; WT_DECL_ITEM(buf); WT_DECL_RET; int vmajor, vminor, vpatch; const char *version; fh = NULL; /* * Create the turtle setup file: we currently re-write it from scratch * every time. */ WT_RET(__wt_open( session, WT_METADATA_TURTLE_SET, 1, 1, WT_FILE_TYPE_TURTLE, &fh)); version = wiredtiger_version(&vmajor, &vminor, &vpatch); WT_ERR(__wt_scr_alloc(session, 2 * 1024, &buf)); WT_ERR(__wt_buf_fmt(session, buf, "%s\n%s\n%s\n" "major=%d,minor=%d,patch=%d\n%s\n%s\n", WT_METADATA_VERSION_STR, version, WT_METADATA_VERSION, vmajor, vminor, vpatch, key, value)); WT_ERR(__wt_write(session, fh, 0, buf->size, buf->data)); /* Flush the handle and rename the file into place. */ ret = __wt_sync_and_rename_fh( session, &fh, WT_METADATA_TURTLE_SET, WT_METADATA_TURTLE); /* Close any file handle left open, remove any temporary file. */ err: WT_TRET(__wt_close(session, &fh)); WT_TRET(__wt_remove_if_exists(session, WT_METADATA_TURTLE_SET)); __wt_scr_free(session, &buf); return (ret); }
/* * __wt_turtle_init -- * Check the turtle file and create if necessary. */ int __wt_turtle_init(WT_SESSION_IMPL *session) { WT_DECL_RET; bool exist_backup, exist_incr, exist_isrc, exist_turtle, load; char *metaconf; metaconf = NULL; load = false; /* * Discard any turtle setup file left-over from previous runs. This * doesn't matter for correctness, it's just cleaning up random files. */ WT_RET(__wt_remove_if_exists(session, WT_METADATA_TURTLE_SET, false)); /* * We could die after creating the turtle file and before creating the * metadata file, or worse, the metadata file might be in some random * state. Make sure that doesn't happen: if we don't find the turtle * file, first create the metadata file, load any hot backup, and then * create the turtle file. No matter what happens, if metadata file * creation doesn't fully complete, we won't have a turtle file and we * will repeat the process until we succeed. * * Incremental backups can occur only if recovery is run and it becomes * live. So, if there is a turtle file and an incremental backup file, * that is an error. Otherwise, if there's already a turtle file, we're * done. */ WT_RET(__wt_fs_exist(session, WT_INCREMENTAL_BACKUP, &exist_incr)); WT_RET(__wt_fs_exist(session, WT_INCREMENTAL_SRC, &exist_isrc)); WT_RET(__wt_fs_exist(session, WT_METADATA_BACKUP, &exist_backup)); WT_RET(__wt_fs_exist(session, WT_METADATA_TURTLE, &exist_turtle)); if (exist_turtle) { /* * We need to detect the difference between a source database * that may have crashed with an incremental backup file * and a destination database that incorrectly ran recovery. */ if (exist_incr && !exist_isrc) WT_RET_MSG(session, EINVAL, "Incremental backup after running recovery " "is not allowed"); /* * If we have a backup file and metadata and turtle files, * we want to recreate the metadata from the backup. */ if (exist_backup) { WT_RET(__wt_msg(session, "Both %s and %s exist; recreating metadata from " "backup", WT_METADATA_TURTLE, WT_METADATA_BACKUP)); WT_RET( __wt_remove_if_exists(session, WT_METAFILE, false)); WT_RET(__wt_remove_if_exists( session, WT_METADATA_TURTLE, false)); load = true; } } else load = true; if (load) { if (exist_incr) F_SET(S2C(session), WT_CONN_WAS_BACKUP); /* Create the metadata file. */ WT_RET(__metadata_init(session)); /* Load any hot-backup information. */ WT_RET(__metadata_load_hot_backup(session)); /* Create any bulk-loaded file stubs. */ WT_RET(__metadata_load_bulk(session)); /* Create the turtle file. */ WT_RET(__metadata_config(session, &metaconf)); WT_WITH_TURTLE_LOCK(session, ret, ret = __wt_turtle_update( session, WT_METAFILE_URI, metaconf)); WT_ERR(ret); } /* Remove the backup files, we'll never read them again. */ WT_ERR(__wt_backup_file_remove(session)); err: __wt_free(session, metaconf); return (ret); }
ffh = tfh = NULL; buf = NULL; /* * Remove the target file if it exists, then create a temporary file, * copy the original into it and rename it into place. I don't think * its necessary to remove the file, or create a copy and do a rename, * it's likely safe to overwrite the backup file directly. I'm doing * the remove and rename to insulate us from errors in other programs * that might not detect a corrupted backup file; it's cheap insurance * in a path where undetected failure is very bad. */ WT_ERR(__wt_scr_alloc(session, 0, &tmp)); WT_ERR(__wt_buf_fmt(session, tmp, "%s.copy", to)); WT_ERR(__wt_remove_if_exists(session, to, false)); WT_ERR(__wt_remove_if_exists(session, tmp->data, false)); /* Open the from and temporary file handles. */ WT_ERR(__wt_open(session, from, WT_FS_OPEN_FILE_TYPE_REGULAR, 0, &ffh)); WT_ERR(__wt_open(session, tmp->data, WT_FS_OPEN_FILE_TYPE_REGULAR, WT_FS_OPEN_CREATE | WT_FS_OPEN_EXCLUSIVE, &tfh)); /* * Allocate a copy buffer. Don't use a scratch buffer, this thing is * big, and we don't want it hanging around. */ #define WT_BACKUP_COPY_SIZE (128 * 1024) WT_ERR(__wt_malloc(session, WT_BACKUP_COPY_SIZE, &buf)); /* Get the file's size, then copy the bytes. */