summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2012-03-11 14:32:29 +1100
committerMichael Cahill <michael.cahill@wiredtiger.com>2012-03-11 14:32:29 +1100
commit3515cdc3f4452fd89e58095f90e7934312ef930b (patch)
treed48222fa2b66e7cd23adbaaa167178f0ded7854c
parenta5f3b8e7d3cbdb91b252f31a9a0a9daf7fa3f0b1 (diff)
downloadmongo-3515cdc3f4452fd89e58095f90e7934312ef930b.tar.gz
Always have an exclusive lock on btree handles before calling __wt_conn_btree_close, apart from the conn->close case which is inherently single-threaded.
-rw-r--r--src/conn/conn_btree.c16
-rw-r--r--src/include/extern.h5
-rw-r--r--src/session/session_api.c2
-rw-r--r--src/session/session_btree.c6
4 files changed, 15 insertions, 14 deletions
diff --git a/src/conn/conn_btree.c b/src/conn/conn_btree.c
index fb72d226139..556905644b7 100644
--- a/src/conn/conn_btree.c
+++ b/src/conn/conn_btree.c
@@ -117,11 +117,10 @@ conf: session->btree = btree;
ret = __wt_btree_open(session, cfg, flags);
if (ret == 0)
F_SET(btree, WT_BTREE_OPEN);
- __wt_rwunlock(session, btree->rwlock);
- if (ret == 0)
- return (0);
+ else
+ (void)__wt_conn_btree_close(session, 1);
- (void)__wt_conn_btree_close(session);
+ __wt_rwunlock(session, btree->rwlock);
return (ret);
}
@@ -130,7 +129,7 @@ conf: session->btree = btree;
* Discard a reference to an open btree file handle.
*/
int
-__wt_conn_btree_close(WT_SESSION_IMPL *session)
+__wt_conn_btree_close(WT_SESSION_IMPL *session, int locked)
{
WT_BTREE *btree;
WT_CONNECTION_IMPL *conn;
@@ -157,14 +156,15 @@ __wt_conn_btree_close(WT_SESSION_IMPL *session)
*/
__wt_spin_lock(session, &conn->spinlock);
inuse = --btree->refcnt > 0;
- if (!inuse)
+ if (!inuse && !locked)
__wt_writelock(session, btree->rwlock);
__wt_spin_unlock(session, &conn->spinlock);
if (!inuse) {
ret = __wt_btree_close(session);
F_CLR(btree, WT_BTREE_OPEN);
- __wt_rwunlock(session, btree->rwlock);
+ if (!locked)
+ __wt_rwunlock(session, btree->rwlock);
}
return (ret);
@@ -238,7 +238,7 @@ restart:
* schema file entry, for good.
*/
while ((btree_session = TAILQ_FIRST(&session->btrees)) != NULL)
- WT_TRET(__wt_session_remove_btree(session, btree_session));
+ WT_TRET(__wt_session_remove_btree(session, btree_session, 0));
/* Close the schema file handle. */
while ((btree = TAILQ_FIRST(&conn->btqh)) != NULL) {
diff --git a/src/include/extern.h b/src/include/extern.h
index 0c59514af21..3ed526cb11c 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -438,7 +438,7 @@ extern int __wt_conn_btree_open(WT_SESSION_IMPL *session,
const char *config,
const char *cfg[],
uint32_t flags);
-extern int __wt_conn_btree_close(WT_SESSION_IMPL *session);
+extern int __wt_conn_btree_close(WT_SESSION_IMPL *session, int locked);
extern int __wt_conn_btree_remove(WT_CONNECTION_IMPL *conn);
extern int __wt_conn_btree_reopen( WT_SESSION_IMPL *session,
const char *cfg[],
@@ -758,7 +758,8 @@ extern int __wt_session_get_btree(WT_SESSION_IMPL *session,
const char *cfg[],
uint32_t flags);
extern int __wt_session_remove_btree( WT_SESSION_IMPL *session,
- WT_BTREE_SESSION *btree_session);
+ WT_BTREE_SESSION *btree_session,
+ int locked);
extern int __wt_session_close_any_open_btree(WT_SESSION_IMPL *session,
const char *name);
extern void __wt_eventv(WT_SESSION_IMPL *session,
diff --git a/src/session/session_api.c b/src/session/session_api.c
index 73568bfdb7e..e57aa124add 100644
--- a/src/session/session_api.c
+++ b/src/session/session_api.c
@@ -38,7 +38,7 @@ __session_close(WT_SESSION *wt_session, const char *config)
WT_TRET(cursor->close(cursor));
while ((btree_session = TAILQ_FIRST(&session->btrees)) != NULL)
- WT_TRET(__wt_session_remove_btree(session, btree_session));
+ WT_TRET(__wt_session_remove_btree(session, btree_session, 0));
WT_TRET(__wt_schema_close_tables(session));
diff --git a/src/session/session_btree.c b/src/session/session_btree.c
index a3dad604379..5bc6f4cffe9 100644
--- a/src/session/session_btree.c
+++ b/src/session/session_btree.c
@@ -175,13 +175,13 @@ __wt_session_get_btree(WT_SESSION_IMPL *session,
*/
int
__wt_session_remove_btree(
- WT_SESSION_IMPL *session, WT_BTREE_SESSION *btree_session)
+ WT_SESSION_IMPL *session, WT_BTREE_SESSION *btree_session, int locked)
{
TAILQ_REMOVE(&session->btrees, btree_session, q);
session->btree = btree_session->btree;
__wt_free(session, btree_session);
- return (__wt_conn_btree_close(session));
+ return (__wt_conn_btree_close(session, locked));
}
/*
@@ -205,7 +205,7 @@ __wt_session_close_any_open_btree(WT_SESSION_IMPL *session, const char *name)
*/
WT_ASSERT(session, btree_session->btree->refcnt == 1);
__wt_schema_detach_tree(session, btree_session->btree);
- ret = __wt_session_remove_btree(session, btree_session);
+ ret = __wt_session_remove_btree(session, btree_session, 1);
__wt_rwunlock(session, session->btree->rwlock);
} else if (ret == WT_NOTFOUND)
ret = 0;