summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/src/schema/schema_alter.c
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2018-04-06 16:06:32 +1000
committerLuke Chen <luke.chen@mongodb.com>2018-04-06 16:23:17 +1000
commitb180ec4ad34b40b499cb4c7a2f01508ed639b44b (patch)
tree87c8fe8e92a19bb0beb69c1c2696e2b3d98aca07 /src/third_party/wiredtiger/src/schema/schema_alter.c
parentf728898d2be6b231175c9d64b39d0f072f5d8d18 (diff)
downloadmongo-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.c197
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);
}