예제 #1
0
파일: schema_rename.c 프로젝트: GYGit/mongo
/*
 * __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);
}
예제 #2
0
/*
 * __create_colgroup --
 *	Create a column group.
 */
static int
__create_colgroup(WT_SESSION_IMPL *session,
    const char *name, int exclusive, const char *config)
{
	WT_CONFIG_ITEM cval;
	WT_DECL_RET;
	WT_ITEM confbuf, fmt, namebuf;
	WT_TABLE *table;
	size_t tlen;
	const char **cfgp, *cfg[4] =
	    { WT_CONFIG_BASE(session, colgroup_meta), config, NULL, NULL };
	const char *sourcecfg[] = { config, NULL, NULL };
	const char *cgname, *source, *sourceconf, *tablename;
	char *cgconf, *oldconf;

	sourceconf = NULL;
	cgconf = oldconf = NULL;
	WT_CLEAR(fmt);
	WT_CLEAR(confbuf);
	WT_CLEAR(namebuf);

	tablename = name;
	if (!WT_PREFIX_SKIP(tablename, "colgroup:"))
		return (EINVAL);
	cgname = strchr(tablename, ':');
	if (cgname != NULL) {
		tlen = (size_t)(cgname - tablename);
		++cgname;
	} else
		tlen = strlen(tablename);

	if ((ret =
	    __wt_schema_get_table(session, tablename, tlen, 1, &table)) != 0)
		WT_RET_MSG(session, (ret == WT_NOTFOUND) ? ENOENT : ret,
		    "Can't create '%s' for non-existent table '%.*s'",
		    name, (int)tlen, tablename);

	/* Make sure the column group is referenced from the table. */
	if (cgname != NULL && (ret =
	    __wt_config_subgets(session, &table->cgconf, cgname, &cval)) != 0)
		WT_ERR_MSG(session, EINVAL,
		    "Column group '%s' not found in table '%.*s'",
		    cgname, (int)tlen, tablename);

	/* Find the first NULL entry in the cfg stack. */
	for (cfgp = &cfg[1]; *cfgp; cfgp++)
		;

	/* Add the source to the colgroup config before collapsing. */
	if (__wt_config_getones(
	    session, config, "source", &cval) == 0 && cval.len != 0) {
		WT_ERR(__wt_buf_fmt(
		    session, &namebuf, "%.*s", (int)cval.len, cval.str));
		source = namebuf.data;
	} else {
		WT_ERR(__wt_schema_colgroup_source(
		    session, table, cgname, config, &namebuf));
		source = namebuf.data;
		WT_ERR(__wt_buf_fmt(
		    session, &confbuf, "source=\"%s\"", source));
		*cfgp++ = confbuf.data;
	}

	/* Calculate the key/value formats: these go into the source config. */
	WT_ERR(__wt_buf_fmt(session, &fmt, "key_format=%s", table->key_format));
	if (cgname == NULL)
		WT_ERR(__wt_buf_catfmt
		    (session, &fmt, ",value_format=%s", table->value_format));
	else {
		if (__wt_config_getones(session, config, "columns", &cval) != 0)
			WT_ERR_MSG(session, EINVAL,
			    "No 'columns' configuration for '%s'", name);
		WT_ERR(__wt_buf_catfmt(session, &fmt, ",value_format="));
		WT_ERR(__wt_struct_reformat(session,
		    table, cval.str, cval.len, NULL, 1, &fmt));
	}
	sourcecfg[1] = fmt.data;
	WT_ERR(__wt_config_merge(session, sourcecfg, NULL, &sourceconf));

	WT_ERR(__wt_schema_create(session, source, sourceconf));

	WT_ERR(__wt_config_collapse(session, cfg, &cgconf));
	if ((ret = __wt_metadata_insert(session, name, cgconf)) != 0) {
		/*
		 * If the entry already exists in the metadata, we're done.
		 * This is an error for exclusive creates but okay otherwise.
		 */
		if (ret == WT_DUPLICATE_KEY)
			ret = exclusive ? EEXIST : 0;
		goto err;
	}

	WT_ERR(__wt_schema_open_colgroups(session, table));

err:	__wt_free(session, cgconf);
	__wt_free(session, sourceconf);
	__wt_free(session, oldconf);
	__wt_buf_free(session, &confbuf);
	__wt_buf_free(session, &fmt);
	__wt_buf_free(session, &namebuf);

	__wt_schema_release_table(session, table);
	return (ret);
}