/* * __truncate_table -- * WT_SESSION::truncate for a table. */ static int __truncate_table(WT_SESSION_IMPL *session, const char *uri, const char *cfg[]) { WT_DECL_RET; WT_TABLE *table; u_int i; WT_RET(__wt_schema_get_table( session, uri, strlen(uri), false, 0, &table)); WT_STAT_DATA_INCR(session, cursor_truncate); /* Truncate the column groups. */ for (i = 0; i < WT_COLGROUPS(table); i++) WT_ERR(__wt_schema_truncate( session, table->cgroups[i]->source, cfg)); /* Truncate the indices. */ WT_ERR(__wt_schema_open_indices(session, table)); for (i = 0; i < table->nindices; i++) WT_ERR(__wt_schema_truncate( session, table->indices[i]->source, cfg)); err: WT_TRET(__wt_schema_release_table(session, table)); return (ret); }
/*修改表名*/ static int __rename_table(WT_SESSION_IMPL *session, const char *uri, const char *newuri, const char *cfg[]) { WT_DECL_RET; WT_TABLE *table; u_int i; const char *oldname; 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_ERR(__wt_schema_remove_table(session, table)); table = NULL; /* Rename the table. */ WT_ERR(__metadata_rename(session, uri, newuri)); }
/* * __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); }
/* * __truncate_table -- * WT_SESSION::truncate for a table. */ static int __truncate_table(WT_SESSION_IMPL *session, const char *name) { WT_BTREE *btree; WT_DECL_ITEM(namebuf); WT_DECL_RET; WT_TABLE *table; int i; WT_RET(__wt_schema_get_table(session, name, strlen(name), 0, &table)); WT_RET(__wt_scr_alloc(session, 0, &namebuf)); /* Truncate the column groups. */ for (i = 0; i < WT_COLGROUPS(table); i++) { /* * Get an exclusive lock on the handle: it will be released by * __wt_conn_btree_close_all. */ WT_ERR(__wt_session_get_btree(session, table->cgroups[i]->source, NULL, NULL, WT_BTREE_EXCLUSIVE)); btree = session->btree; WT_ERR(__wt_buf_set( session, namebuf, btree->name, strlen(btree->name) + 1)); WT_ERR(__truncate_file(session, namebuf->data)); } /* Truncate the indices. */ WT_ERR(__wt_schema_open_indices(session, table)); for (i = 0; i < table->nindices; i++) { /* * Get an exclusive lock on the handle: it will be released by * __wt_conn_btree_close_all. */ WT_ERR(__wt_session_get_btree(session, table->indices[i]->source, NULL, NULL, WT_BTREE_EXCLUSIVE)); btree = session->btree; WT_ERR(__wt_buf_set( session, namebuf, btree->name, strlen(btree->name) + 1)); WT_ERR(__truncate_file(session, namebuf->data)); } table->idx_complete = 0; /* Reopen the column groups. */ ret = __wt_schema_open_colgroups(session, table); err: __wt_scr_free(&namebuf); 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); }
/* * __wt_schema_worker -- * Get Btree handles for the object and cycle through calls to an * underlying worker function with each handle. */ int __wt_schema_worker(WT_SESSION_IMPL *session, const char *uri, int (*file_func)(WT_SESSION_IMPL *, const char *[]), int (*name_func)(WT_SESSION_IMPL *, const char *, bool *), const char *cfg[], uint32_t open_flags) { WT_COLGROUP *colgroup; WT_DATA_SOURCE *dsrc; WT_DECL_RET; WT_INDEX *idx; WT_SESSION *wt_session; WT_TABLE *table; u_int i; bool skip; table = NULL; skip = false; if (name_func != NULL) WT_ERR(name_func(session, uri, &skip)); /* If the callback said to skip this object, we're done. */ if (skip) return (0); /* Get the btree handle(s) and call the underlying function. */ if (WT_PREFIX_MATCH(uri, "file:")) { if (file_func != NULL) WT_ERR(__wt_exclusive_handle_operation(session, uri, file_func, cfg, open_flags)); } else if (WT_PREFIX_MATCH(uri, "colgroup:")) { WT_ERR(__wt_schema_get_colgroup( session, uri, false, NULL, &colgroup)); WT_ERR(__wt_schema_worker(session, colgroup->source, file_func, name_func, cfg, open_flags)); } else if (WT_PREFIX_MATCH(uri, "index:")) { idx = NULL; WT_ERR(__wt_schema_get_index(session, uri, false, false, &idx)); WT_ERR(__wt_schema_worker(session, idx->source, file_func, name_func, cfg, open_flags)); } else if (WT_PREFIX_MATCH(uri, "lsm:")) { WT_ERR(__wt_lsm_tree_worker(session, uri, file_func, name_func, cfg, open_flags)); } else if (WT_PREFIX_MATCH(uri, "table:")) { /* * Note: we would like to use open_flags here (e.g., to lock * the table exclusive during schema-changing operations), but * that is currently problematic because we get the table again * in order to discover column groups and indexes. */ WT_ERR(__wt_schema_get_table_uri( session, uri, false, 0, &table)); /* * We could make a recursive call for each colgroup or index * URI, but since we have already opened the table, we can take * a short cut and skip straight to the sources. If we have a * name function, it needs to know about the intermediate URIs. */ for (i = 0; i < WT_COLGROUPS(table); i++) { colgroup = table->cgroups[i]; skip = false; if (name_func != NULL) WT_ERR(name_func( session, colgroup->name, &skip)); if (!skip) WT_ERR(__wt_schema_worker( session, colgroup->source, file_func, name_func, cfg, open_flags)); } WT_ERR(__wt_schema_open_indices(session, table)); for (i = 0; i < table->nindices; i++) { idx = table->indices[i]; skip = false; if (name_func != NULL) WT_ERR(name_func(session, idx->name, &skip)); if (!skip) WT_ERR(__wt_schema_worker(session, idx->source, file_func, name_func, cfg, open_flags)); } } else if ((dsrc = __wt_schema_get_source(session, uri)) != NULL) { wt_session = (WT_SESSION *)session; if (file_func == __wt_salvage && dsrc->salvage != NULL) WT_ERR(dsrc->salvage( dsrc, wt_session, uri, (WT_CONFIG_ARG *)cfg)); else if (file_func == __wt_verify && dsrc->verify != NULL) WT_ERR(dsrc->verify( dsrc, wt_session, uri, (WT_CONFIG_ARG *)cfg)); else if (file_func == __wt_checkpoint) ; else if (file_func == __wt_checkpoint_get_handles) ; else if (file_func == __wt_checkpoint_sync) ; else WT_ERR(__wt_object_unsupported(session, uri)); } else WT_ERR(__wt_bad_object_type(session, uri)); err: if (table != NULL) WT_TRET(__wt_schema_release_table(session, table)); 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); }
/* * __wt_schema_worker -- * Get Btree handles for the object and cycle through calls to an * underlying worker function with each handle. */ int __wt_schema_worker(WT_SESSION_IMPL *session, const char *uri, int (*file_func)(WT_SESSION_IMPL *, const char *[]), int (*name_func)(WT_SESSION_IMPL *, const char *), const char *cfg[], uint32_t open_flags) { WT_COLGROUP *colgroup; WT_DATA_SOURCE *dsrc; WT_DECL_RET; WT_INDEX *idx; WT_SESSION *wt_session; WT_TABLE *table; const char *tablename; u_int i; table = NULL; tablename = uri; if (name_func != NULL) WT_ERR(name_func(session, uri)); /* Get the btree handle(s) and call the underlying function. */ if (WT_PREFIX_MATCH(uri, "file:")) { if (file_func != NULL) { WT_ERR(__wt_session_get_btree_ckpt( session, uri, cfg, open_flags)); ret = file_func(session, cfg); WT_TRET(__wt_session_release_btree(session)); } } else if (WT_PREFIX_MATCH(uri, "colgroup:")) { WT_ERR(__wt_schema_get_colgroup(session, uri, NULL, &colgroup)); WT_ERR(__wt_schema_worker(session, colgroup->source, file_func, name_func, cfg, open_flags)); } else if (WT_PREFIX_SKIP(tablename, "index:")) { idx = NULL; WT_ERR(__wt_schema_get_index(session, uri, NULL, &idx)); WT_ERR(__wt_schema_worker(session, idx->source, file_func, name_func, cfg, open_flags)); } else if (WT_PREFIX_MATCH(uri, "lsm:")) { WT_ERR(__wt_lsm_tree_worker( session, uri, file_func, name_func, cfg, open_flags)); } else if (WT_PREFIX_SKIP(tablename, "table:")) { WT_ERR(__wt_schema_get_table(session, tablename, strlen(tablename), 0, &table)); WT_ASSERT(session, session->dhandle == NULL); /* * We could make a recursive call for each colgroup or index * URI, but since we have already opened the table, we can take * a short cut and skip straight to the sources. If we have a * name function, it needs to know about the intermediate URIs. */ for (i = 0; i < WT_COLGROUPS(table); i++) { colgroup = table->cgroups[i]; if (name_func != NULL) WT_ERR(name_func(session, colgroup->name)); WT_ERR(__wt_schema_worker(session, colgroup->source, file_func, name_func, cfg, open_flags)); } WT_ERR(__wt_schema_open_indices(session, table)); for (i = 0; i < table->nindices; i++) { idx = table->indices[i]; if (name_func != NULL) WT_ERR(name_func(session, idx->name)); WT_ERR(__wt_schema_worker(session, idx->source, file_func, name_func, cfg, open_flags)); } } else if ((dsrc = __wt_schema_get_source(session, uri)) != NULL) { wt_session = (WT_SESSION *)session; if (file_func == __wt_compact && dsrc->compact != NULL) WT_ERR(dsrc->compact( dsrc, wt_session, uri, (WT_CONFIG_ARG *)cfg)); else if (file_func == __wt_salvage && dsrc->salvage != NULL) WT_ERR(dsrc->salvage( dsrc, wt_session, uri, (WT_CONFIG_ARG *)cfg)); else if (file_func == __wt_verify && dsrc->verify != NULL) WT_ERR(dsrc->verify( dsrc, wt_session, uri, (WT_CONFIG_ARG *)cfg)); else WT_ERR(__wt_object_unsupported(session, uri)); } else WT_ERR(__wt_bad_object_type(session, uri)); err: if (table != NULL) __wt_schema_release_table(session, table); return (ret); }