diff options
author | Luke Chen <luke.chen@mongodb.com> | 2018-04-06 16:06:32 +1000 |
---|---|---|
committer | Luke Chen <luke.chen@mongodb.com> | 2018-04-06 16:23:17 +1000 |
commit | b180ec4ad34b40b499cb4c7a2f01508ed639b44b (patch) | |
tree | 87c8fe8e92a19bb0beb69c1c2696e2b3d98aca07 /src/third_party/wiredtiger/src/schema/schema_alter.c | |
parent | f728898d2be6b231175c9d64b39d0f072f5d8d18 (diff) | |
download | mongo-b180ec4ad34b40b499cb4c7a2f01508ed639b44b.tar.gz |
Import wiredtiger: ea986ede145b8c2e3da8f8d11ef25813770c0b39 from branch mongodb-3.8
ref: 875e91581c..ea986ede14
for: 3.7.4
WT-3724 Log an error if flushing with F_FULLSYNC fails
WT-3849 Add timestamp validation to WT_SESSION::prepare_transaction
WT-3870 Bi-weekly WT codebase lint
WT-3922 Allow truncate operations to be prepared
WT-3931 cursor.prev split race
WT-3971 Make cursor duplication use cursor caching
WT-3973 Allow alter to modify app_metadata
WT-3981 Make snapshot consistent with read_timestamp
WT-3984 Fix race conditions around prepare state transitions
WT-3996 Test truncate with timestamps and lookaside
WT-3997 The cursor walk code can spin without sleeping on restart/split.
WT-4002 Allow duplicates in api_data.py
WT-4005 AddressSanitizer in __wt_timestamp_iszero().
WT-4007 eviction instantiates pages from dead trees.
WT-4008 Add ARM NEON support for row search operations
WT-4011 Checkpoint should not read truncated pages
WT-4022 Avoid WT_RESTART error return during eviction walk
WT-4025 Allow debug dumping of internal pages
Diffstat (limited to 'src/third_party/wiredtiger/src/schema/schema_alter.c')
-rw-r--r-- | src/third_party/wiredtiger/src/schema/schema_alter.c | 197 |
1 files changed, 179 insertions, 18 deletions
diff --git a/src/third_party/wiredtiger/src/schema/schema_alter.c b/src/third_party/wiredtiger/src/schema/schema_alter.c index a957969e6cc..2ebfcfc5d9d 100644 --- a/src/third_party/wiredtiger/src/schema/schema_alter.c +++ b/src/third_party/wiredtiger/src/schema/schema_alter.c @@ -7,41 +7,33 @@ */ #include "wt_internal.h" +static int __schema_alter(WT_SESSION_IMPL *, const char *, const char *[]); /* - * __wt_alter -- - * Alter a file. + * __alter_apply -- + * Alter an object */ -int -__wt_alter(WT_SESSION_IMPL *session, const char *newcfg[]) +static int +__alter_apply(WT_SESSION_IMPL *session, + const char *uri, const char *newcfg[], const char *base_config) { WT_DECL_RET; - const char *cfg[4], *filename, *uri; + const char *cfg[4]; char *config, *newconfig; - uri = session->dhandle->name; - WT_RET(__wt_meta_track_on(session)); - - /* - * We know that we have exclusive access to the file. So it will be - * closed after we're done with it and the next open will see the - * updated metadata. - */ - filename = uri; newconfig = NULL; - if (!WT_PREFIX_SKIP(filename, "file:")) - return (__wt_unexpected_object_type(session, uri, "file:")); /* Find the URI */ WT_RET(__wt_metadata_search(session, uri, &config)); WT_ASSERT(session, newcfg[0] != NULL); + /* * Start with the base configuration because collapse is like * a projection and if we are reading older metadata, it may not * have all the components. */ - cfg[0] = WT_CONFIG_BASE(session, file_meta); + cfg[0] = base_config; cfg[1] = config; cfg[2] = newcfg[0]; cfg[3] = NULL; @@ -63,7 +55,176 @@ err: __wt_free(session, config); if (ret == WT_NOTFOUND) ret = ENOENT; - WT_TRET(__wt_meta_track_off(session, true, ret != 0)); + return (ret); +} + +/* + * __alter_file -- + * Alter a file. + */ +static int +__alter_file(WT_SESSION_IMPL *session, const char *newcfg[]) +{ + const char *uri; + + /* + * We know that we have exclusive access to the file. So it will be + * closed after we're done with it and the next open will see the + * updated metadata. + */ + uri = session->dhandle->name; + if (!WT_PREFIX_MATCH(uri, "file:")) + return (__wt_unexpected_object_type(session, uri, "file:")); + + return (__alter_apply(session, + uri, newcfg, WT_CONFIG_BASE(session, file_meta))); +} + +/* + * __alter_tree -- + * Alter an index or colgroup reference. + */ +static int +__alter_tree(WT_SESSION_IMPL *session, const char *name, const char *newcfg[]) +{ + WT_CONFIG_ITEM cval; + WT_DECL_ITEM(data_source); + WT_DECL_RET; + char *value; + bool is_colgroup; + + value = NULL; + + is_colgroup = WT_PREFIX_MATCH(name, "colgroup:"); + if (!is_colgroup && !WT_PREFIX_MATCH(name, "index:")) + return (__wt_unexpected_object_type( + session, name, "'colgroup:' or 'index:'")); + + /* Read the schema value. */ + WT_ERR(__wt_metadata_search(session, name, &value)); + + /* Get the data source URI. */ + 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); + WT_ERR(__wt_scr_alloc(session, 0, &data_source)); + WT_ERR(__wt_buf_fmt(session, + data_source, "%.*s", (int)cval.len, cval.str)); + + /* Alter the data source */ + WT_ERR(__schema_alter(session, data_source->data, newcfg)); + + /* Alter the index or colgroup */ + if (is_colgroup) + WT_ERR(__alter_apply(session, + name, newcfg, WT_CONFIG_BASE(session, colgroup_meta))); + else + WT_ERR(__alter_apply(session, + name, newcfg, WT_CONFIG_BASE(session, index_meta))); + +err: __wt_scr_free(session, &data_source); + __wt_free(session, value); + return (ret); +} + +/* + * __alter_table -- + * Alter a table. + */ +static int +__alter_table(WT_SESSION_IMPL *session, const char *uri, const char *newcfg[]) +{ + WT_COLGROUP *colgroup; + WT_DECL_RET; + WT_INDEX *idx; + WT_TABLE *table; + u_int i; + const char *name; + + colgroup = NULL; + table = NULL; + name = uri; + WT_PREFIX_SKIP_REQUIRED(session, name, "table:"); + + /* + * Open the table so we can alter its column groups and indexes, keeping + * the table locked exclusive across the alter. + */ + WT_RET(__wt_schema_get_table_uri(session, uri, true, + WT_DHANDLE_EXCLUSIVE, &table)); + /* Meta tracking needs to be used because alter needs to be atomic. */ + WT_ASSERT(session, WT_META_TRACKING(session)); + WT_WITH_DHANDLE(session, &table->iface, + ret = __wt_meta_track_handle_lock(session, false)); + WT_RET(ret); + + /* Alter the column groups. */ + for (i = 0; i < WT_COLGROUPS(table); i++) { + if ((colgroup = table->cgroups[i]) == NULL) + continue; + WT_RET(__alter_tree(session, colgroup->name, newcfg)); + } + + /* Alter the indices. */ + WT_RET(__wt_schema_open_indices(session, table)); + for (i = 0; i < table->nindices; i++) { + if ((idx = table->indices[i]) == NULL) + continue; + WT_RET(__alter_tree(session, idx->name, newcfg)); + } + + /* Alter the table */ + WT_RET(__alter_apply(session, + uri, newcfg, WT_CONFIG_BASE(session, table_meta))); + + return (ret); +} + +/* + * __schema_alter -- + * Alter an object. + */ +static int +__schema_alter(WT_SESSION_IMPL *session, const char *uri, const char *newcfg[]) +{ + uint32_t flags; + + /* + * The alter flag is used so LSM can apply some special logic, the + * exclusive flag avoids conflicts with other operations and the lock + * only flag is required because we don't need to have a handle to + * update the metadata and opening the handle causes problems when + * meta tracking is enabled. + */ + flags = WT_BTREE_ALTER | WT_DHANDLE_EXCLUSIVE | WT_DHANDLE_LOCK_ONLY; + if (WT_PREFIX_MATCH(uri, "file:")) + return (__wt_exclusive_handle_operation( + session, uri, __alter_file, newcfg, flags)); + if (WT_PREFIX_MATCH(uri, "colgroup:") || + WT_PREFIX_MATCH(uri, "index:")) + return (__alter_tree(session, uri, newcfg)); + if (WT_PREFIX_MATCH(uri, "lsm:")) + return (__wt_lsm_tree_worker(session, uri, __alter_file, + NULL, newcfg, flags)); + if (WT_PREFIX_MATCH(uri, "table:")) + return (__alter_table(session, uri, newcfg)); + + return (__wt_bad_object_type(session, uri)); +} + +/* + * __wt_schema_alter -- + * Alter an object. + */ +int +__wt_schema_alter(WT_SESSION_IMPL *session, + const char *uri, const char *newcfg[]) +{ + WT_DECL_RET; + + WT_RET(__wt_meta_track_on(session)); + ret = __schema_alter(session, uri, newcfg); + WT_TRET(__wt_meta_track_off(session, true, ret != 0)); return (ret); } |