summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2012-06-01 23:50:52 +1000
committerMichael Cahill <michael.cahill@wiredtiger.com>2012-06-01 23:50:52 +1000
commit51ec453e72f9742786d405b026a720813df10e6b (patch)
tree5e31f75579733065e981bbe16d7b02c163532a7c
parent7ad7248c3e85b47275ea9169841c7c850321a2fd (diff)
downloadmongo-51ec453e72f9742786d405b026a720813df10e6b.tar.gz
Fix locking for create operations: hold the handle lock until all cleanup is done.
-rw-r--r--src/conn/conn_btree.c6
-rw-r--r--src/meta/meta_track.c23
-rw-r--r--src/schema/schema_create.c10
3 files changed, 24 insertions, 15 deletions
diff --git a/src/conn/conn_btree.c b/src/conn/conn_btree.c
index 5a8381fcebe..e5251289201 100644
--- a/src/conn/conn_btree.c
+++ b/src/conn/conn_btree.c
@@ -243,14 +243,18 @@ __wt_conn_btree_get(WT_SESSION_IMPL *session,
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
const char *treeconf;
+ int locked;
conn = S2C(session);
WT_STAT_INCR(conn->stats, file_open);
+ locked = 1;
if ((btree = session->btree) != NULL) {
if (!F_ISSET(btree, WT_BTREE_EXCLUSIVE))
__wt_conn_btree_open_lock(session, flags);
+ else
+ locked = 0;
} else {
WT_RET(__conn_btree_get(session, name, snapshot, flags));
btree = session->btree;
@@ -267,7 +271,7 @@ __wt_conn_btree_get(WT_SESSION_IMPL *session,
ret = __wt_conn_btree_open(session, treeconf, cfg, flags);
}
-err: if (ret != 0) {
+err: if (ret != 0 && locked) {
F_CLR(btree, WT_BTREE_EXCLUSIVE);
__wt_rwunlock(session, btree->rwlock);
}
diff --git a/src/meta/meta_track.c b/src/meta/meta_track.c
index a8918d25d7a..0956bc863bd 100644
--- a/src/meta/meta_track.c
+++ b/src/meta/meta_track.c
@@ -103,6 +103,8 @@ __meta_track_apply(WT_SESSION_IMPL *session, WT_META_TRACK *trk, int unroll)
case WT_ST_LOCK: /* Handle lock, see above */
saved_btree = session->btree;
session->btree = trk->btree;
+ if (session->created_btree == trk->btree)
+ session->created_btree = NULL;
WT_TRET(__wt_session_release_btree(session));
session->btree = saved_btree;
break;
@@ -120,14 +122,19 @@ __meta_track_apply(WT_SESSION_IMPL *session, WT_META_TRACK *trk, int unroll)
"metadata unroll rename %s to %s",
trk->b, trk->a);
WT_TRET(tret);
- } else if (trk->a == NULL && ((tret =
- __wt_conn_btree_close_all(session, trk->b)) != 0 ||
- (tret = __wt_remove(session,
- trk->b + strlen("file:"))) != 0)) {
- __wt_err(session, tret,
- "metadata unroll create %s",
- trk->b);
- WT_TRET(tret);
+ } else if (trk->a == NULL) {
+ saved_btree = session->btree;
+ if ((session->btree = session->created_btree) != NULL)
+ WT_TRET(
+ __wt_conn_btree_sync_and_close(session));
+ session->btree = saved_btree;
+ if ((tret = __wt_remove(session,
+ trk->b + strlen("file:"))) != 0) {
+ __wt_err(session, tret,
+ "metadata unroll create %s",
+ trk->b);
+ WT_TRET(tret);
+ }
}
/*
* We can't undo removes yet: that would imply
diff --git a/src/schema/schema_create.c b/src/schema/schema_create.c
index 4e51469e4ac..093fcb19326 100644
--- a/src/schema/schema_create.c
+++ b/src/schema/schema_create.c
@@ -31,8 +31,10 @@ __create_file(WT_SESSION_IMPL *session,
WT_RET(__wt_session_get_btree(
session, uri, cfg, WT_BTREE_EXCLUSIVE | WT_BTREE_LOCK_ONLY));
- if (WT_META_TRACKING(session))
+ if (WT_META_TRACKING(session)) {
WT_RET(__wt_meta_track_handle_lock(session));
+ session->created_btree = session->btree;
+ }
/* Check if the file already exists. */
if (!is_metadata && (ret =
@@ -178,12 +180,9 @@ __create_colgroup(WT_SESSION_IMPL *session,
goto err;
}
WT_ERR(__create_file(session, fileuri, exclusive, fileconf));
-
- session->created_btree = session->btree;
WT_ERR(__wt_schema_open_colgroups(session, table));
-err: session->created_btree = NULL;
- __wt_free(session, cgconf);
+err: __wt_free(session, cgconf);
__wt_free(session, fileconf);
__wt_free(session, oldconf);
__wt_buf_free(session, &fmt);
@@ -393,7 +392,6 @@ __wt_schema_create(
else if ((ret = __wt_schema_get_source(session, name, &dsrc)) == 0)
ret = dsrc->create(dsrc, &session->iface, name, config);
- WT_ASSERT(session, session->created_btree == NULL);
session->btree = NULL;
WT_TRET(__wt_meta_track_off(session, ret != 0));