/*- * Copyright (c) 2008-2012 WiredTiger, Inc. * All rights reserved. * * See the file LICENSE for redistribution information. */ #include "wt_internal.h" int __wt_create_file(WT_SESSION_IMPL *session, const char *name, const char *fileuri, const char *config) { WT_ITEM *key, *val; const char *cfg[] = API_CONF_DEFAULTS(session, create, config); const char *filecfg[] = API_CONF_DEFAULTS(file, meta, config); const char *filename, *treeconf; int is_schema, vmajor, vminor, vpatch, ret; key = val = NULL; treeconf = NULL; ret = 0; filename = fileuri; if (!WT_PREFIX_SKIP(filename, "file:")) WT_RET_MSG( session, EINVAL, "Expecting a 'file:' URI: %s", fileuri); /* * Opening the schema table is a special case, use the config * string we were passed to open the file. */ is_schema = (strcmp(filename, WT_SCHEMA_FILENAME) == 0); /* If the file exists, don't try to recreate it. */ if ((ret = __wt_session_get_btree(session, name, fileuri, is_schema ? config : NULL, NULL, WT_BTREE_NO_LOCK)) != WT_NOTFOUND) return (ret); WT_RET(__wt_btree_create(session, filename)); WT_ERR(__wt_schema_table_track_fileop(session, NULL, filename)); /* Insert WiredTiger version numbers into the schema file. */ WT_ERR(__wt_scr_alloc(session, 0, &val)); if (is_schema) { WT_ERR(__wt_schema_table_insert( session, WT_SCHEMA_VERSION_STR, wiredtiger_version(&vmajor, &vminor, &vpatch))); WT_ERR(__wt_buf_fmt(session, val, "major=%d,minor=%d,patch=%d", vmajor, vminor, vpatch)); WT_ERR(__wt_schema_table_insert( session, WT_SCHEMA_VERSION, val->data)); } /* * Insert Btree version numbers into the schema file (including for * the schema file itself, although the schema file version numbers * can never be trusted, we have to get them from the turtle file). */ WT_ERR(__wt_scr_alloc(session, 0, &key)); WT_ERR(__wt_buf_fmt(session, key, "version:%s", filename)); WT_ERR(__wt_buf_fmt(session, val, "major=%d,minor=%d", WT_BTREE_MAJOR_VERSION, WT_BTREE_MINOR_VERSION)); WT_ERR(__wt_schema_table_insert(session, key->data, val->data)); if (is_schema) WT_ERR(__wt_strdup(session, config, &treeconf)); else WT_ERR(__wt_config_collapse(session, filecfg, &treeconf)); WT_ERR(__wt_schema_table_insert(session, fileuri, treeconf)); /* Allocate a WT_BTREE handle, and open the underlying file. */ WT_ERR(__wt_btree_open(session, name, filename, treeconf, cfg, 0)); treeconf = NULL; WT_ERR(__wt_session_add_btree(session, NULL)); /* If something goes wrong, throw away anything we created. */ err: __wt_scr_free(&key); __wt_scr_free(&val); __wt_free(session, treeconf); return (ret); } static int __create_colgroup( WT_SESSION_IMPL *session, const char *name, const char *config) { WT_CONFIG_ITEM cval; WT_ITEM fmt, namebuf, uribuf; WT_TABLE *table; const char *cfg[] = { __wt_confdfl_colgroup_meta, config, NULL, NULL }; const char *filecfg[] = { config, NULL, NULL }; const char **cfgp; const char *cgconf, *cgname, *fileconf, *filename, *fileuri, *tablename; size_t tlen; int ret; cgconf = fileconf = NULL; WT_CLEAR(fmt); WT_CLEAR(namebuf); WT_CLEAR(uribuf); 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, &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_RET_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 filename to the colgroup config before collapsing. */ if (__wt_config_getones(session, config, "filename", &cval) == 0) { WT_ERR(__wt_buf_fmt( session, &namebuf, "%.*s", (int)cval.len, cval.str)); filename = namebuf.data; } else { if (cgname == NULL) WT_ERR(__wt_buf_fmt(session, &namebuf, "filename=%.*s.wt", (int)tlen, tablename)); else WT_ERR(__wt_buf_fmt(session, &namebuf, "filename=%.*s_%s.wt", (int)tlen, tablename, cgname)); *cfgp++ = filename = namebuf.data; (void)WT_PREFIX_SKIP(filename, "filename="); } WT_ERR(__wt_config_collapse(session, cfg, &cgconf)); /* Calculate the key/value formats -- these go into the file 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)); } filecfg[1] = fmt.data; WT_ERR(__wt_config_concat(session, filecfg, &fileconf)); WT_ERR(__wt_buf_fmt(session, &uribuf, "file:%s", filename)); fileuri = uribuf.data; WT_ERR(__wt_schema_table_insert(session, name, cgconf)); WT_ERR(__wt_create_file(session, name, fileuri, fileconf)); WT_ERR(__wt_schema_open_colgroups(session, table)); err: __wt_free(session, cgconf); __wt_free(session, fileconf); __wt_buf_free(session, &fmt); __wt_buf_free(session, &namebuf); __wt_buf_free(session, &uribuf); return (ret); } static int __create_index(WT_SESSION_IMPL *session, const char *name, const char *config) { WT_CONFIG pkcols; WT_CONFIG_ITEM ckey, cval, icols; WT_ITEM extra_cols, fmt, namebuf, uribuf; WT_TABLE *table; const char *cfg[] = { __wt_confdfl_index_meta, config, NULL, NULL }; const char *filecfg[] = { config, NULL, NULL }; const char *fileconf, *filename, *fileuri, *idxconf, *idxname; const char *tablename; size_t tlen; int i, ret; idxconf = fileconf = NULL; WT_CLEAR(fmt); WT_CLEAR(extra_cols); WT_CLEAR(namebuf); WT_CLEAR(uribuf); tablename = name; if (!WT_PREFIX_SKIP(tablename, "index:")) return (EINVAL); idxname = strchr(tablename, ':'); if (idxname == NULL) WT_RET_MSG(session, EINVAL, "Invalid index name, " "should be