/* * __drop_table -- * WT_SESSION::drop for a table. */ static int __drop_table(WT_SESSION_IMPL *session, const char *uri, const char *cfg[]) { WT_COLGROUP *colgroup; WT_DECL_RET; WT_INDEX *idx; WT_TABLE *table; const char *name; u_int i; name = uri; (void)WT_PREFIX_SKIP(name, "table:"); table = NULL; WT_ERR(__wt_schema_get_table( session, name, strlen(name), true, &table)); /* Drop the column groups. */ for (i = 0; i < WT_COLGROUPS(table); i++) { if ((colgroup = table->cgroups[i]) == NULL) continue; /* * Drop the column group before updating the metadata to avoid * the metadata for the table becoming inconsistent if we can't * get exclusive access. */ WT_ERR(__wt_schema_drop(session, colgroup->source, cfg)); WT_ERR(__wt_metadata_remove(session, colgroup->name)); } /* Drop the indices. */ WT_ERR(__wt_schema_open_indices(session, table)); for (i = 0; i < table->nindices; i++) { if ((idx = table->indices[i]) == NULL) continue; /* * Drop the column group before updating the metadata to avoid * the metadata for the table becoming inconsistent if we can't * get exclusive access. */ WT_ERR(__wt_schema_drop(session, idx->source, cfg)); WT_ERR(__wt_metadata_remove(session, idx->name)); } WT_ERR(__wt_schema_remove_table(session, table)); table = NULL; /* Remove the metadata entry (ignore missing items). */ WT_ERR(__wt_metadata_remove(session, uri)); err: if (table != NULL) __wt_schema_release_table(session, table); return (ret); }
/* * __drop_file -- * Drop a file. */ static int __drop_file( WT_SESSION_IMPL *session, const char *uri, bool force, const char *cfg[]) { WT_CONFIG_ITEM cval; WT_DECL_RET; bool 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_HANDLE_LIST_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); /* * Schedule the remove of the underlying physical file when the drop * completes. */ WT_TRET(__wt_meta_track_drop(session, filename)); return (ret); }
/* * __rename_file -- * WT_SESSION::rename for a file. */ static int __rename_file( WT_SESSION_IMPL *session, const char *uri, const char *newuri) { WT_DECL_RET; bool exist; const char *filename, *newfile; char *newvalue, *oldvalue; newvalue = oldvalue = NULL; filename = uri; newfile = newuri; if (!WT_PREFIX_SKIP(filename, "file:") || !WT_PREFIX_SKIP(newfile, "file:")) return (EINVAL); /* Close any btree handles in the file. */ WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_conn_dhandle_close_all(session, uri, false)); WT_ERR(ret); /* * First, check if the file being renamed exists in the system. Doing * this check first matches the table rename behavior because we return * WT_NOTFOUND when the renamed file doesn't exist (subsequently mapped * to ENOENT by the session layer). */ WT_ERR(__wt_metadata_search(session, uri, &oldvalue)); /* * Check to see if the proposed name is already in use, in either the * metadata or the filesystem. */ switch (ret = __wt_metadata_search(session, newuri, &newvalue)) { case 0: WT_ERR_MSG(session, EEXIST, "%s", newuri); /* NOTREACHED */ case WT_NOTFOUND: break; default: WT_ERR(ret); } WT_ERR(__wt_fs_exist(session, newfile, &exist)); if (exist) WT_ERR_MSG(session, EEXIST, "%s", newfile); /* Replace the old file entries with new file entries. */ WT_ERR(__wt_metadata_remove(session, uri)); WT_ERR(__wt_metadata_insert(session, newuri, oldvalue)); /* Rename the underlying file. */ WT_ERR(__wt_fs_rename(session, filename, newfile, false)); if (WT_META_TRACKING(session)) WT_ERR(__wt_meta_track_fileop(session, uri, newuri)); err: __wt_free(session, newvalue); __wt_free(session, oldvalue); 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; 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, ret = __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 && (ret = __wt_fs_rename(session, trk->b + strlen("file:"), trk->a + strlen("file:"), true)) != 0) __wt_err(session, ret, "metadata unroll rename %s to %s", trk->b, trk->a); if (trk->a == NULL && (ret = __wt_fs_remove(session, trk->b + strlen("file:"), false)) != 0) __wt_err(session, ret, "metadata unroll create %s", trk->b); /* * 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 ((ret = __wt_metadata_remove(session, trk->a)) != 0) __wt_err(session, ret, "metadata unroll remove: %s", trk->a); break; case WT_ST_SET: /* Set trk.a to trk.b */ if ((ret = __wt_metadata_update(session, trk->a, trk->b)) != 0) __wt_err(session, ret, "metadata unroll update %s to %s", trk->a, trk->b); break; } __meta_track_clear(session, trk); return (ret); }
/*修改文件名操作*/ static int __rename_file(WT_SESSION_IMPL* session, const char* uri, const char* newuri) { WT_DECL_RET; int exist; const char *filename, *newfile; char *newvalue, *oldvalue; newvalue = oldvalue = NULL; filename = uri; newfile = newuri; if (!WT_PREFIX_SKIP(filename, "file:") || !WT_PREFIX_SKIP(newfile, "file:")) return (EINVAL); /*关闭这个文件对应的data source handler*/ WT_WITH_DHANDLE_LOCK(session, ret = __wt_conn_dhandle_close_all(session, uri, 0)); WT_ERR(ret); /* * First, check if the file being renamed exists in the system. Doing * this check first matches the table rename behavior because we return * WT_NOTFOUND when the renamed file doesn't exist (subsequently mapped * to ENOENT by the session layer). */ /*先查出旧的文件名uri对应的meta 信息,再用新的文件名uri旧版本的meta信息*/ WT_ERR(__wt_metadata_search(session, uri, &oldvalue)); switch (ret = __wt_metadata_search(session, newuri, &newvalue)) { case 0: WT_ERR_MSG(session, EEXIST, "%s", newuri); /* NOTREACHED */ case WT_NOTFOUND: break; default: WT_ERR(ret); } WT_ERR(__wt_exist(session, newfile, &exist)); if (exist) WT_ERR_MSG(session, EEXIST, "%s", newfile); /* Replace the old file entries with new file entries. */ WT_ERR(__wt_metadata_remove(session, uri)); WT_ERR(__wt_metadata_insert(session, newuri, oldvalue)); WT_ERR(__wt_rename(session, filename, newfile)); if(WT_META_TRACKING(session)) WT_ERR(__wt_meta_track_fileop(session, uri, newuri)); err: __wt_free(session, newvalue); __wt_free(session, oldvalue); return ret; }
/* * __metadata_rename -- * Rename an entry in the metadata table. */ static int __metadata_rename(WT_SESSION_IMPL *session, const char *uri, const char *newuri) { WT_DECL_RET; char *value; WT_RET(__wt_metadata_search(session, uri, &value)); WT_ERR(__wt_metadata_remove(session, uri)); WT_ERR(__wt_metadata_insert(session, newuri, value)); err: __wt_free(session, value); return (ret); }
/* * __rename_file -- * WT_SESSION::rename for a file. */ static int __rename_file( WT_SESSION_IMPL *session, const char *uri, const char *newuri) { WT_DECL_RET; int exist; const char *filename, *newfile, *value; value = NULL; filename = uri; newfile = newuri; if (!WT_PREFIX_SKIP(filename, "file:") || !WT_PREFIX_SKIP(newfile, "file:")) return (EINVAL); /* Close any btree handles in the file. */ WT_RET(__wt_conn_btree_close_all(session, uri)); /* * Check to see if the proposed name is already in use, in either * the metadata or the filesystem. */ switch (ret = __wt_metadata_read(session, newuri, &value)) { case 0: WT_ERR_MSG(session, EEXIST, "%s", newuri); case WT_NOTFOUND: ret = 0; break; default: WT_ERR(ret); } WT_ERR(__wt_exist(session, newfile, &exist)); if (exist) WT_ERR_MSG(session, EEXIST, "%s", newfile); /* Replace the old file entries with new file entries. */ WT_ERR(__wt_metadata_read(session, uri, &value)); WT_ERR(__wt_metadata_remove(session, uri)); WT_ERR(__wt_metadata_insert(session, newuri, value)); /* Rename the underlying file. */ WT_ERR(__wt_rename(session, filename, newfile)); if (WT_META_TRACKING(session)) WT_ERR(__wt_meta_track_fileop(session, uri, newuri)); err: __wt_free(session, value); return (ret); }
/* * __drop_index -- * WT_SESSION::drop for an index. */ static int __drop_index( WT_SESSION_IMPL *session, const char *uri, bool force, const char *cfg[]) { WT_DECL_RET; WT_INDEX *idx; /* If we can get the index, detach it from the table. */ if ((ret = __wt_schema_get_index(session, uri, true, force, &idx)) == 0) WT_TRET(__wt_schema_drop(session, idx->source, cfg)); WT_TRET(__wt_metadata_remove(session, uri)); return (ret); }
/* * __wt_lsm_tree_drop -- * Drop an LSM tree. */ int __wt_lsm_tree_drop( WT_SESSION_IMPL *session, const char *name, const char *cfg[]) { WT_DECL_RET; WT_LSM_CHUNK *chunk; WT_LSM_TREE *lsm_tree; u_int i; int locked; locked = 0; /* Get the LSM tree. */ WT_RET(__wt_lsm_tree_get(session, name, 1, &lsm_tree)); /* Shut down the LSM worker. */ WT_ERR(__lsm_tree_close(session, lsm_tree)); /* Prevent any new opens. */ WT_ERR(__wt_try_writelock(session, lsm_tree->rwlock)); locked = 1; /* Drop the chunks. */ for (i = 0; i < lsm_tree->nchunks; i++) { chunk = lsm_tree->chunk[i]; WT_ERR(__wt_schema_drop(session, chunk->uri, cfg)); if (F_ISSET(chunk, WT_LSM_CHUNK_BLOOM)) WT_ERR( __wt_schema_drop(session, chunk->bloom_uri, cfg)); } /* Drop any chunks on the obsolete list. */ for (i = 0; i < lsm_tree->nold_chunks; i++) { if ((chunk = lsm_tree->old_chunks[i]) == NULL) continue; WT_ERR(__wt_schema_drop(session, chunk->uri, cfg)); if (F_ISSET(chunk, WT_LSM_CHUNK_BLOOM)) WT_ERR( __wt_schema_drop(session, chunk->bloom_uri, cfg)); } ret = __wt_rwunlock(session, lsm_tree->rwlock); locked = 0; if (ret == 0) ret = __wt_metadata_remove(session, name); err: if (locked) WT_TRET(__wt_rwunlock(session, lsm_tree->rwlock)); WT_TRET(__lsm_tree_discard(session, lsm_tree)); return (ret); }
/* * __drop_index -- * WT_SESSION::drop for a colgroup. */ static int __drop_index( WT_SESSION_IMPL *session, const char *uri, bool force, const char *cfg[]) { WT_INDEX *idx; WT_DECL_RET; WT_TABLE *table; /* If we can get the colgroup, detach it from the table. */ if ((ret = __wt_schema_get_index( session, uri, force, &table, &idx)) == 0) { table->idx_complete = false; WT_TRET(__wt_schema_drop(session, idx->source, cfg)); } WT_TRET(__wt_metadata_remove(session, uri)); return (ret); }
/* * __drop_colgroup -- * WT_SESSION::drop for a colgroup. */ static int __drop_colgroup( WT_SESSION_IMPL *session, const char *uri, const char *cfg[]) { WT_COLGROUP *colgroup; WT_DECL_RET; WT_TABLE *table; /* If we can get the colgroup, detach it from the table. */ if ((ret = __wt_schema_get_colgroup( session, uri, &table, &colgroup)) == 0) { table->cg_complete = 0; WT_TRET(__wt_schema_drop(session, colgroup->source, cfg)); } WT_TRET(__wt_metadata_remove(session, uri)); 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); }
/* * __rename_table -- * WT_SESSION::rename for a table. */ static int __rename_table(WT_SESSION_IMPL *session, const char *uri, const char *newuri, const char *cfg[]) { WT_DECL_ITEM(buf); WT_DECL_RET; WT_TABLE *table; u_int i; const char *oldname, *value; oldname = uri; (void)WT_PREFIX_SKIP(oldname, "table:"); WT_RET(__wt_schema_get_table( session, oldname, strlen(oldname), 0, &table)); /* Rename the column groups. */ for (i = 0; i < WT_COLGROUPS(table); i++) WT_ERR(__rename_tree(session, table, newuri, table->cgroups[i]->name, cfg)); /* Rename the indices. */ WT_ERR(__wt_schema_open_indices(session, table)); for (i = 0; i < table->nindices; i++) WT_ERR(__rename_tree(session, table, newuri, table->indices[i]->name, cfg)); __wt_schema_remove_table(session, table); table = NULL; /* Rename the table. */ WT_ERR(__wt_scr_alloc(session, 0, &buf)); WT_ERR(__wt_metadata_read(session, uri, &value)); WT_ERR(__wt_metadata_remove(session, uri)); WT_ERR(__wt_metadata_insert(session, newuri, value)); err: __wt_scr_free(&buf); if (table != NULL) __wt_schema_release_table(session, table); return (ret); }
/* * __drop_colgroup -- * WT_SESSION::drop for a colgroup. */ static int __drop_colgroup( WT_SESSION_IMPL *session, const char *uri, bool force, const char *cfg[]) { WT_COLGROUP *colgroup; WT_DECL_RET; WT_TABLE *table; WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_TABLE_WRITE)); /* If we can get the colgroup, detach it from the table. */ if ((ret = __wt_schema_get_colgroup( session, uri, force, &table, &colgroup)) == 0) { WT_TRET(__wt_schema_drop(session, colgroup->source, cfg)); if (ret == 0) table->cg_complete = false; } WT_TRET(__wt_metadata_remove(session, uri)); 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); }
/* * __curmetadata_remove -- * WT_CURSOR->remove method for the metadata cursor type. */ static int __curmetadata_remove(WT_CURSOR *cursor) { WT_CURSOR *file_cursor; WT_CURSOR_METADATA *mdc; WT_DECL_RET; WT_SESSION_IMPL *session; mdc = (WT_CURSOR_METADATA *)cursor; file_cursor = mdc->file_cursor; CURSOR_API_CALL(cursor, session, remove, ((WT_CURSOR_BTREE *)file_cursor)->btree); WT_MD_CURSOR_NEEDKEY(cursor); /* * Since the key format is 's' the WT_ITEM must contain a NULL * terminated string. */ ret = __wt_metadata_remove(session, cursor->key.data); err: API_END_RET(session, ret); }
/* * __rename_table -- * WT_SESSION::rename for a table. */ static int __rename_table( WT_SESSION_IMPL *session, const char *oldname, const char *newname) { WT_DECL_RET; WT_ITEM *buf; WT_TABLE *table; int i; const char *value; buf = NULL; WT_RET( __wt_schema_get_table(session, oldname, strlen(oldname), &table)); /* Rename the column groups. */ for (i = 0; i < WT_COLGROUPS(table); i++) WT_RET(__rename_tree(session, table->cg_name[i], newname)); /* Rename the indices. */ WT_RET(__wt_schema_open_index(session, table, NULL, 0)); for (i = 0; i < table->nindices; i++) WT_RET(__rename_tree(session, table->idx_name[i], newname)); WT_RET(__wt_schema_remove_table(session, table)); /* Rename the table. */ WT_ERR(__wt_scr_alloc(session, 0, &buf)); WT_ERR(__wt_buf_fmt(session, buf, "table:%s", oldname)); WT_ERR(__wt_metadata_read(session, buf->data, &value)); WT_ERR(__wt_metadata_remove(session, buf->data)); WT_ERR(__wt_buf_fmt(session, buf, "table:%s", newname)); WT_ERR(__wt_metadata_insert(session, buf->data, value)); err: __wt_scr_free(&buf); return (ret); }
/* * __wt_lsm_tree_rename -- * Rename an LSM tree. */ int __wt_lsm_tree_rename(WT_SESSION_IMPL *session, const char *oldname, const char *newname, const char *cfg[]) { WT_DECL_RET; WT_ITEM buf; WT_LSM_CHUNK *chunk; WT_LSM_TREE *lsm_tree; const char *old; u_int i; int locked; old = NULL; WT_CLEAR(buf); locked = 0; /* Get the LSM tree. */ WT_RET(__wt_lsm_tree_get(session, oldname, 1, &lsm_tree)); /* Shut down the LSM worker. */ WT_ERR(__lsm_tree_close(session, lsm_tree)); /* Prevent any new opens. */ WT_ERR(__wt_try_writelock(session, lsm_tree->rwlock)); locked = 1; /* Set the new name. */ WT_ERR(__lsm_tree_set_name(session, lsm_tree, newname)); /* Rename the chunks. */ for (i = 0; i < lsm_tree->nchunks; i++) { chunk = lsm_tree->chunk[i]; old = chunk->uri; chunk->uri = NULL; WT_ERR(__wt_lsm_tree_chunk_name( session, lsm_tree, chunk->id, &buf)); chunk->uri = __wt_buf_steal(session, &buf, NULL); WT_ERR(__wt_schema_rename(session, old, chunk->uri, cfg)); __wt_free(session, old); if (F_ISSET(chunk, WT_LSM_CHUNK_BLOOM)) { old = chunk->bloom_uri; chunk->bloom_uri = NULL; WT_ERR(__wt_lsm_tree_bloom_name( session, lsm_tree, chunk->id, &buf)); chunk->bloom_uri = __wt_buf_steal(session, &buf, NULL); F_SET(chunk, WT_LSM_CHUNK_BLOOM); WT_ERR(__wt_schema_rename( session, old, chunk->uri, cfg)); __wt_free(session, old); } } ret = __wt_rwunlock(session, lsm_tree->rwlock); locked = 0; if (ret == 0) ret = __wt_lsm_meta_write(session, lsm_tree); if (ret == 0) ret = __wt_metadata_remove(session, oldname); err: if (locked) WT_TRET(__wt_rwunlock(session, lsm_tree->rwlock)); if (old != NULL) __wt_free(session, old); /* * Discard this LSM tree structure. The first operation on the renamed * tree will create a new one. */ WT_TRET(__lsm_tree_discard(session, lsm_tree)); return (ret); }
/* * __drop_table -- * WT_SESSION::drop for a table. */ static int __drop_table( WT_SESSION_IMPL *session, const char *uri, const char *cfg[]) { WT_COLGROUP *colgroup; WT_DECL_RET; WT_INDEX *idx; WT_TABLE *table; u_int i; const char *name; bool tracked; WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_TABLE_WRITE)); name = uri; WT_PREFIX_SKIP_REQUIRED(session, name, "table:"); table = NULL; tracked = false; /* * Open the table so we can drop its column groups and indexes. * * Ideally we would keep the table locked exclusive across the drop, * but for now we rely on the global table lock to prevent the table * being reopened while it is being dropped. One issue is that the * WT_WITHOUT_LOCKS macro can drop and reacquire the global table lock, * avoiding deadlocks while waiting for LSM operation to quiesce. * * Temporarily getting the table exclusively serves the purpose * of ensuring that cursors on the table that are already open * must at least be closed before this call proceeds. */ WT_ERR(__wt_schema_get_table_uri(session, uri, true, WT_DHANDLE_EXCLUSIVE, &table)); WT_ERR(__wt_schema_release_table(session, table)); WT_ERR(__wt_schema_get_table_uri(session, uri, true, 0, &table)); /* Drop the column groups. */ for (i = 0; i < WT_COLGROUPS(table); i++) { if ((colgroup = table->cgroups[i]) == NULL) continue; /* * Drop the column group before updating the metadata to avoid * the metadata for the table becoming inconsistent if we can't * get exclusive access. */ WT_ERR(__wt_schema_drop(session, colgroup->source, cfg)); WT_ERR(__wt_metadata_remove(session, colgroup->name)); } /* Drop the indices. */ WT_ERR(__wt_schema_open_indices(session, table)); for (i = 0; i < table->nindices; i++) { if ((idx = table->indices[i]) == NULL) continue; /* * Drop the index before updating the metadata to avoid * the metadata for the table becoming inconsistent if we can't * get exclusive access. */ WT_ERR(__wt_schema_drop(session, idx->source, cfg)); WT_ERR(__wt_metadata_remove(session, idx->name)); } /* Make sure the table data handle is closed. */ WT_TRET(__wt_schema_release_table(session, table)); WT_ERR(__wt_schema_get_table_uri( session, uri, true, WT_DHANDLE_EXCLUSIVE, &table)); F_SET(&table->iface, WT_DHANDLE_DISCARD); if (WT_META_TRACKING(session)) { WT_WITH_DHANDLE(session, &table->iface, ret = __wt_meta_track_handle_lock(session, false)); WT_ERR(ret); tracked = true; } /* Remove the metadata entry (ignore missing items). */ WT_ERR(__wt_metadata_remove(session, uri)); err: if (table != NULL && !tracked) WT_TRET(__wt_schema_release_table(session, table)); return (ret); }
/* * __rename_tree -- * Rename an index or colgroup reference. */ static int __rename_tree(WT_SESSION_IMPL *session, const char *name, const char *newname) { WT_DECL_RET; WT_ITEM *of, *nf, *nk, *nv; const char *newfile, *p, *t, *value; nf = nk = nv = of = NULL; /* Read the old schema value. */ WT_ERR(__wt_metadata_read(session, name, &value)); /* * Create the new file name, new schema key, new schema value. * * Names are of the form "prefix.oldname:suffix", where suffix is * optional; we need prefix and suffix. */ if ((p = strchr(name, ':')) == NULL) WT_ERR_MSG(session, EINVAL, "invalid index or column-group name: %s", name); t = strchr(p + 1, ':'); WT_ERR(__wt_scr_alloc(session, 0, &nf)); WT_ERR(__wt_buf_fmt(session, nf, "file:%s%s%s.wt", newname, t == NULL ? "" : "_", t == NULL ? "" : t + 1)); newfile = (const char *)nf->data + strlen("file:"); WT_ERR(__wt_scr_alloc(session, 0, &nk)); WT_ERR(__wt_buf_fmt(session, nk, "%.*s:%s%s%s", (int)WT_PTRDIFF(p, name), name, newname, t == NULL ? "" : ":", t == NULL ? "" : t + 1)); if ((p = strstr(value, "filename=")) == NULL) WT_ERR_MSG(session, EINVAL, "index or column-group value has no file name: %s", value); p += strlen("filename="); t = strchr(p, ','); /* Take a copy of the old filename. */ WT_ERR(__wt_scr_alloc(session, 0, &of)); WT_ERR(__wt_buf_fmt(session, of, "file:%.*s", (int)((t == NULL) ? strlen(p) : WT_PTRDIFF(t, p)), p)); /* Overwrite it with the new filename. */ WT_ERR(__wt_scr_alloc(session, 0, &nv)); WT_ERR(__wt_buf_fmt(session, nv, "%.*s%s%s", (int)WT_PTRDIFF(p, value), value, newfile, t == NULL ? "" : t)); /* * Remove the old metadata entry. * Insert the new metadata entry. */ WT_ERR(__wt_metadata_remove(session, name)); WT_ERR(__wt_metadata_insert(session, nk->data, nv->data)); /* Rename the file. */ WT_ERR(__rename_file(session, of->data, nf->data)); err: __wt_scr_free(&nf); __wt_scr_free(&nk); __wt_scr_free(&nv); __wt_scr_free(&of); __wt_free(session, value); return (ret); }
/* * __rename_tree -- * Rename an index or colgroup reference. */ static int __rename_tree(WT_SESSION_IMPL *session, WT_TABLE *table, const char *newuri, const char *name, const char *cfg[]) { WT_CONFIG_ITEM cval; WT_DECL_ITEM(nn); WT_DECL_ITEM(ns); WT_DECL_ITEM(nv); WT_DECL_ITEM(os); WT_DECL_RET; bool is_colgroup; const char *newname, *olduri, *suffix; char *value; olduri = table->name; value = NULL; newname = newuri; (void)WT_PREFIX_SKIP(newname, "table:"); /* * Create the new data source URI and update the schema value. * * 'name' has the format (colgroup|index):<tablename>[:<suffix>]; * we need the suffix. */ is_colgroup = WT_PREFIX_MATCH(name, "colgroup:"); if (!is_colgroup && !WT_PREFIX_MATCH(name, "index:")) WT_ERR_MSG(session, EINVAL, "expected a 'colgroup:' or 'index:' source: '%s'", name); suffix = strchr(name, ':'); /* An existing table should have a well formed name. */ WT_ASSERT(session, suffix != NULL); suffix = strchr(suffix + 1, ':'); WT_ERR(__wt_scr_alloc(session, 0, &nn)); WT_ERR(__wt_buf_fmt(session, nn, "%s%s%s", is_colgroup ? "colgroup:" : "index:", newname, (suffix == NULL) ? "" : suffix)); /* Skip the colon, if any. */ if (suffix != NULL) ++suffix; /* Read the old schema value. */ WT_ERR(__wt_metadata_search(session, name, &value)); /* * Calculate the new data source URI. Use the existing table structure * and substitute the new name temporarily. */ WT_ERR(__wt_scr_alloc(session, 0, &ns)); table->name = newuri; if (is_colgroup) WT_ERR(__wt_schema_colgroup_source( session, table, suffix, value, ns)); else WT_ERR(__wt_schema_index_source( session, table, suffix, value, ns)); if ((ret = __wt_config_getones(session, value, "source", &cval)) != 0) WT_ERR_MSG(session, EINVAL, "index or column group has no data source: %s", value); /* Take a copy of the old data source. */ WT_ERR(__wt_scr_alloc(session, 0, &os)); WT_ERR(__wt_buf_fmt(session, os, "%.*s", (int)cval.len, cval.str)); /* Overwrite it with the new data source. */ WT_ERR(__wt_scr_alloc(session, 0, &nv)); WT_ERR(__wt_buf_fmt(session, nv, "%.*s%s%s", (int)WT_PTRDIFF(cval.str, value), value, (const char *)ns->data, cval.str + cval.len)); /* * Do the rename before updating the metadata to avoid leaving the * metadata inconsistent if the rename fails. */ WT_ERR(__wt_schema_rename(session, os->data, ns->data, cfg)); /* * Remove the old metadata entry. * Insert the new metadata entry. */ WT_ERR(__wt_metadata_remove(session, name)); WT_ERR(__wt_metadata_insert(session, nn->data, nv->data)); err: __wt_scr_free(session, &nn); __wt_scr_free(session, &ns); __wt_scr_free(session, &nv); __wt_scr_free(session, &os); __wt_free(session, value); table->name = olduri; 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); }