diff options
author | Michael Cahill <michael.cahill@wiredtiger.com> | 2012-06-01 23:50:52 +1000 |
---|---|---|
committer | Michael Cahill <michael.cahill@wiredtiger.com> | 2012-06-01 23:50:52 +1000 |
commit | 51ec453e72f9742786d405b026a720813df10e6b (patch) | |
tree | 5e31f75579733065e981bbe16d7b02c163532a7c | |
parent | 7ad7248c3e85b47275ea9169841c7c850321a2fd (diff) | |
download | mongo-51ec453e72f9742786d405b026a720813df10e6b.tar.gz |
Fix locking for create operations: hold the handle lock until all cleanup is done.
-rw-r--r-- | src/conn/conn_btree.c | 6 | ||||
-rw-r--r-- | src/meta/meta_track.c | 23 | ||||
-rw-r--r-- | src/schema/schema_create.c | 10 |
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)); |