/* * __wt_turtle_init -- * Check the turtle file and create if necessary. */ int __wt_turtle_init(WT_SESSION_IMPL *session) { WT_DECL_RET; int exist; 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_exist(session, WT_METADATA_TURTLE_SET, &exist)); if (exist) WT_RET(__wt_remove(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. * * If there's already a turtle file, we're done. */ WT_RET(__wt_exist(session, WT_METADATA_TURTLE, &exist)); if (exist) return (0); /* 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 file if it exists, we'll never read it again. */ WT_ERR(__wt_exist(session, WT_METADATA_BACKUP, &exist)); if (exist) WT_ERR(__wt_remove(session, WT_METADATA_BACKUP)); err: __wt_free(session, metaconf); return (ret); }
/* * __backup_file_remove -- * Remove the meta-data backup file. */ static int __backup_file_remove(WT_SESSION_IMPL *session) { WT_DECL_RET; int exist; WT_ERR(__wt_exist(session, WT_INCREMENTAL_BACKUP, &exist)); if (exist) WT_ERR(__wt_remove(session, WT_INCREMENTAL_BACKUP)); WT_ERR(__wt_exist(session, WT_METADATA_BACKUP, &exist)); if (exist) WT_ERR(__wt_remove(session, WT_METADATA_BACKUP)); err: return (ret); }
/* * __lsm_drop_file -- * Helper function to drop part of an LSM tree. */ static int __lsm_drop_file(WT_SESSION_IMPL *session, const char *uri) { WT_DECL_RET; const char *drop_cfg[] = { WT_CONFIG_BASE( session, WT_SESSION_drop), "remove_files=false", NULL }; /* * We need to grab the schema lock to drop the file, so first try to * make sure there is minimal work to freeing space in the cache. Only * bother trying to discard the checkpoint handle: the in-memory handle * should have been closed already. * * This will fail with EBUSY if the file is still in use. */ WT_RET(__lsm_discard_handle(session, uri, WT_CHECKPOINT)); /* * Take the schema lock for the drop operation. Since __wt_schema_drop * results in the hot backup lock being taken when it updates the * metadata (which would be too late to prevent our drop). */ WT_WITH_SCHEMA_LOCK(session, ret = __wt_schema_drop(session, uri, drop_cfg)); if (ret == 0) ret = __wt_remove(session, uri + strlen("file:")); WT_RET(__wt_verbose(session, WT_VERB_LSM, "Dropped %s", uri)); if (ret == EBUSY || ret == ENOENT) WT_RET(__wt_verbose(session, WT_VERB_LSM, "LSM worker drop of %s failed with %d", uri, ret)); return (ret); }
/* * __drop_file -- * Drop a file. */ static int __drop_file(WT_SESSION_IMPL *session, const char *uri, int force) { int exist, ret; const char *filename; ret = 0; filename = uri; if (!WT_PREFIX_SKIP(filename, "file:")) return (EINVAL); /* If open, close the btree handle. */ WT_RET(__wt_session_close_any_open_btree(session, filename)); /* Remove the schema table entry (ignore missing items). */ WT_TRET(__wt_schema_table_remove(session, uri)); if (force && ret == WT_NOTFOUND) ret = 0; /* Remove the underlying physical file. */ exist = 0; WT_TRET(__wt_exist(session, filename, &exist)); if (exist) WT_TRET(__wt_remove(session, filename)); return (ret); }
/* * __wt_remove_if_exists -- * Remove a file if it exists. */ int __wt_remove_if_exists(WT_SESSION_IMPL *session, const char *name) { bool exist; WT_RET(__wt_exist(session, name, &exist)); if (exist) WT_RET(__wt_remove(session, name)); return (0); }
/* * __wt_log_remove -- * Given a log number, remove that log file. */ int __wt_log_remove(WT_SESSION_IMPL *session, uint32_t lognum) { WT_DECL_ITEM(path); WT_DECL_RET; WT_ERR(__wt_scr_alloc(session, 0, &path)); WT_ERR(__wt_log_filename(session, lognum, path)); WT_ERR(__wt_verbose(session, WT_VERB_LOG, "log_remove: remove log %s", (char *)path->data)); WT_ERR(__wt_remove(session, path->data)); err: __wt_scr_free(&path); return (ret); }
/* * __wt_turtle_update -- * Update the turtle file. */ int __wt_turtle_update( WT_SESSION_IMPL *session, const char *key, const char *value) { FILE *fp; WT_DECL_RET; int vmajor, vminor, vpatch; const char *version; char *path; fp = NULL; path = NULL; /* * Create the turtle setup file: we currently re-write it from scratch * every time. */ WT_RET(__wt_filename(session, WT_METADATA_TURTLE_SET, &path)); if ((fp = fopen(path, "w")) == NULL) ret = __wt_errno(); __wt_free(session, path); if (fp == NULL) return (ret); version = wiredtiger_version(&vmajor, &vminor, &vpatch); WT_ERR_TEST((fprintf(fp, "%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) < 0), __wt_errno()); ret = fclose(fp); fp = NULL; WT_ERR_TEST(ret == EOF, __wt_errno()); WT_ERR( __wt_rename(session, WT_METADATA_TURTLE_SET, WT_METADATA_TURTLE)); if (0) { err: WT_TRET(__wt_remove(session, WT_METADATA_TURTLE_SET)); } if (fp != NULL) WT_TRET(fclose(fp) == 0 ? 0 : __wt_errno()); return (ret); }
/* * __wt_metadata_load_backup -- * Load the contents of any hot backup file. */ int __wt_metadata_load_backup(WT_SESSION_IMPL *session) { FILE *fp; WT_DECL_ITEM(key); WT_DECL_ITEM(value); WT_DECL_RET; const char *path; fp = NULL; path = NULL; /* Look for a hot backup file: if we find it, load it. */ WT_RET(__wt_filename(session, WT_METADATA_BACKUP, &path)); if ((fp = fopen(path, "r")) == NULL) { __wt_free(session, path); return (0); } /* Read line pairs and load them into the metadata file. */ WT_ERR(__wt_scr_alloc(session, 512, &key)); WT_ERR(__wt_scr_alloc(session, 512, &value)); for (;;) { WT_ERR(__wt_getline(session, key, fp)); if (key->size == 0) break; WT_ERR(__wt_getline(session, value, fp)); if (value->size == 0) WT_ERR(__wt_illegal_value(session, WT_METADATA_BACKUP)); WT_ERR(__wt_metadata_update(session, key->data, value->data)); } /* Remove the hot backup file, it's only read (successfully) once. */ WT_ERR(__wt_remove(session, WT_METADATA_BACKUP)); err: if (fp != NULL) WT_TRET(fclose(fp) == 0 ? 0 : __wt_errno()); if (path != NULL) __wt_free(session, path); __wt_scr_free(&key); __wt_scr_free(&value); return (ret); }
/* * __drop_file -- * Drop a file. */ static int __drop_file( WT_SESSION_IMPL *session, const char *uri, int force, const char *cfg[]) { WT_DECL_RET; int exist; const char *filename; filename = uri; if (!WT_PREFIX_SKIP(filename, "file:")) return (EINVAL); if (session->btree == NULL && (ret = __wt_session_get_btree(session, uri, NULL, cfg, WT_BTREE_EXCLUSIVE | WT_BTREE_LOCK_ONLY)) != 0) { if (ret == WT_NOTFOUND || ret == ENOENT) ret = 0; return (ret); } /* Close all btree handles associated with this file. */ WT_RET(__wt_conn_btree_close_all(session, uri)); /* Remove the metadata entry (ignore missing items). */ WT_TRET(__wt_metadata_remove(session, uri)); if (force && ret == WT_NOTFOUND) ret = 0; /* Remove the underlying physical file. */ exist = 0; WT_TRET(__wt_exist(session, filename, &exist)); if (exist) { /* * There is no point tracking this operation: there is no going * back from here. */ WT_TRET(__wt_remove(session, filename)); } return (ret); }
/* * __wt_meta_turtle_init -- * Check the turtle file and create if necessary. */ int __wt_meta_turtle_init(WT_SESSION_IMPL *session, int *existp) { WT_DECL_RET; WT_ITEM *buf; int exist; const char *metaconf; const char *cfg[] = API_CONF_DEFAULTS(file, meta, NULL); buf = NULL; metaconf = NULL; *existp = 0; /* Discard any turtle setup file left-over from previous runs. */ WT_RET(__wt_exist(session, WT_METADATA_TURTLE_SET, &exist)); if (exist) WT_RET(__wt_remove(session, WT_METADATA_TURTLE_SET)); /* If there's already a turtle file, we're done. */ WT_RET(__wt_exist(session, WT_METADATA_TURTLE, &exist)); if (exist) { *existp = 1; return (0); } /* Create a turtle file with default values. */ WT_ERR(__wt_scr_alloc(session, 0, &buf)); WT_ERR(__wt_buf_fmt(session, buf, "key_format=S,value_format=S,version=(major=%d,minor=%d)", WT_BTREE_MAJOR_VERSION, WT_BTREE_MINOR_VERSION)); cfg[1] = buf->data; WT_ERR(__wt_config_collapse(session, cfg, &metaconf)); WT_ERR(__wt_meta_turtle_update(session, WT_METADATA_URI, metaconf)); err: __wt_free(session, metaconf); __wt_scr_free(&buf); return (ret); }
/* * __wt_block_manager_create -- * Create a file. */ int __wt_block_manager_create( WT_SESSION_IMPL *session, const char *filename, uint32_t allocsize) { WT_DECL_RET; WT_FH *fh; /* Create the underlying file and open a handle. */ WT_RET(__wt_open(session, filename, 1, 1, WT_FILE_TYPE_DATA, &fh)); /* Write out the file's meta-data. */ ret = __wt_desc_init(session, fh, allocsize); /* Close the file handle. */ WT_TRET(__wt_close(session, fh)); /* Undo any create on error. */ if (ret != 0) WT_TRET(__wt_remove(session, filename)); return (ret); }
/* * __drop_file -- * Drop a file. */ static int __drop_file( WT_SESSION_IMPL *session, const char *uri, int force, const char *cfg[]) { WT_CONFIG_ITEM cval; WT_DECL_RET; int exist, remove_files; const char *filename; WT_RET(__wt_config_gets(session, cfg, "remove_files", &cval)); remove_files = (cval.val != 0); filename = uri; if (!WT_PREFIX_SKIP(filename, "file:")) return (EINVAL); /* Close all btree handles associated with this file. */ WT_WITH_DHANDLE_LOCK(session, ret = __wt_conn_dhandle_close_all(session, uri, force)); WT_RET(ret); /* Remove the metadata entry (ignore missing items). */ WT_TRET(__wt_metadata_remove(session, uri)); if (!remove_files) return (ret); /* Remove the underlying physical file. */ exist = 0; WT_TRET(__wt_exist(session, filename, &exist)); if (exist) { /* * There is no point tracking this operation: there is no going * back from here. */ WT_TRET(__wt_remove(session, filename)); } 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, int unroll) { WT_BM *bm; WT_BTREE *btree; WT_DECL_RET; int tret; /* * Unlock handles and complete checkpoints regardless of whether we are * unrolling. */ if (!unroll && trk->op != WT_ST_CHECKPOINT && trk->op != WT_ST_LOCK) goto free; switch (trk->op) { case WT_ST_EMPTY: /* Unused slot */ break; case WT_ST_CHECKPOINT: /* Checkpoint, see above */ if (!unroll) { btree = trk->dhandle->handle; bm = btree->bm; WT_WITH_DHANDLE(session, trk->dhandle, WT_TRET(bm->checkpoint_resolve(bm, session))); } break; case WT_ST_LOCK: /* Handle lock, see above */ if (unroll && trk->created) F_SET(trk->dhandle, WT_DHANDLE_DISCARD); WT_WITH_DHANDLE(session, trk->dhandle, WT_TRET(__wt_session_release_btree(session))); break; case WT_ST_FILEOP: /* File operation */ /* * For renames, both a and b are set. * For creates, a is NULL. * For removes, b is NULL. */ if (trk->a != NULL && trk->b != NULL && (tret = __wt_rename(session, trk->b + strlen("file:"), trk->a + strlen("file:"))) != 0) { __wt_err(session, tret, "metadata unroll rename %s to %s", trk->b, trk->a); WT_TRET(tret); } else if (trk->a == NULL) { if ((tret = __wt_remove(session, trk->b + strlen("file:"))) != 0) { __wt_err(session, tret, "metadata unroll create %s", trk->b); WT_TRET(tret); } } /* * We can't undo removes yet: that would imply * some kind of temporary rename and remove in * roll forward. */ break; case WT_ST_REMOVE: /* Remove trk.a */ if ((tret = __wt_metadata_remove(session, trk->a)) != 0) { __wt_err(session, tret, "metadata unroll remove: %s", trk->a); WT_TRET(tret); } break; case WT_ST_SET: /* Set trk.a to trk.b */ if ((tret = __wt_metadata_update( session, trk->a, trk->b)) != 0) { __wt_err(session, tret, "metadata unroll update %s to %s", trk->a, trk->b); WT_TRET(tret); } break; WT_ILLEGAL_VALUE(session); } free: trk->op = WT_ST_EMPTY; __wt_free(session, trk->a); __wt_free(session, trk->b); trk->dhandle = NULL; return (ret); }
/* * __meta_track_unroll -- * Undo the changes in a metadata tracking record. */ static int __meta_track_unroll(WT_SESSION_IMPL *session, WT_META_TRACK *trk) { WT_DECL_RET; int tret; switch (trk->op) { case WT_ST_EMPTY: /* Unused slot */ break; case WT_ST_CHECKPOINT: /* Checkpoint, see above */ break; case WT_ST_DROP_COMMIT: break; case WT_ST_LOCK: /* Handle lock, see above */ if (trk->created) F_SET(trk->dhandle, WT_DHANDLE_DISCARD); WT_WITH_DHANDLE(session, trk->dhandle, WT_TRET(__wt_session_release_btree(session))); break; case WT_ST_FILEOP: /* File operation */ /* * For renames, both a and b are set. * For creates, a is NULL. * For removes, b is NULL. */ if (trk->a != NULL && trk->b != NULL && (tret = __wt_rename(session, trk->b + strlen("file:"), trk->a + strlen("file:"))) != 0) { __wt_err(session, tret, "metadata unroll rename %s to %s", trk->b, trk->a); WT_TRET(tret); } else if (trk->a == NULL) { if ((tret = __wt_remove(session, trk->b + strlen("file:"))) != 0) { __wt_err(session, tret, "metadata unroll create %s", trk->b); WT_TRET(tret); } } /* * We can't undo removes yet: that would imply * some kind of temporary rename and remove in * roll forward. */ break; case WT_ST_REMOVE: /* Remove trk.a */ if ((tret = __wt_metadata_remove(session, trk->a)) != 0) { __wt_err(session, tret, "metadata unroll remove: %s", trk->a); WT_TRET(tret); } break; case WT_ST_SET: /* Set trk.a to trk.b */ if ((tret = __wt_metadata_update( session, trk->a, trk->b)) != 0) { __wt_err(session, tret, "metadata unroll update %s to %s", trk->a, trk->b); WT_TRET(tret); } break; WT_ILLEGAL_VALUE(session); } __meta_track_clear(session, trk); return (ret); }
/* * __backup_file_remove -- * Remove the meta-data backup file. */ static int __backup_file_remove(WT_SESSION_IMPL *session) { return (__wt_remove(session, WT_METADATA_BACKUP)); }