summaryrefslogtreecommitdiff
path: root/src/session/session_dhandle.c
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2014-10-28 08:29:30 -0400
committerKeith Bostic <keith@wiredtiger.com>2014-10-28 08:29:30 -0400
commita6761cff3b41349458e0053448fb3b8ca114e575 (patch)
tree4d7f3f635afd6857b740405e93b6617f63ca6337 /src/session/session_dhandle.c
parent97cb5c8685ffd5805ca2cc0dbebb7ea2679034e2 (diff)
downloadmongo-a6761cff3b41349458e0053448fb3b8ca114e575.tar.gz
Change read/write locks to no longer track if an exclusive lock was
acquired by its caller, instead track in the code if we acquired an exclusive lock and choose the correct unlock call based on that information.
Diffstat (limited to 'src/session/session_dhandle.c')
-rw-r--r--src/session/session_dhandle.c71
1 files changed, 48 insertions, 23 deletions
diff --git a/src/session/session_dhandle.c b/src/session/session_dhandle.c
index a44d2b04568..0c07e5fa259 100644
--- a/src/session/session_dhandle.c
+++ b/src/session/session_dhandle.c
@@ -71,14 +71,14 @@ __session_add_btree(
int
__wt_session_lock_btree(WT_SESSION_IMPL *session, uint32_t flags)
{
+ enum { NOLOCK, READLOCK, WRITELOCK } locked;
WT_BTREE *btree;
WT_DATA_HANDLE *dhandle;
uint32_t special_flags;
- int locked;
btree = S2BT(session);
dhandle = session->dhandle;
- locked = 0;
+ locked = NOLOCK;
/*
* Special operation flags will cause the handle to be reopened.
@@ -103,13 +103,13 @@ __wt_session_lock_btree(WT_SESSION_IMPL *session, uint32_t flags)
if (LF_ISSET(WT_DHANDLE_LOCK_ONLY) || special_flags == 0) {
WT_RET(__wt_try_writelock(session, dhandle->rwlock));
F_SET(dhandle, WT_DHANDLE_EXCLUSIVE);
- locked = 1;
+ locked = WRITELOCK;
}
} else if (F_ISSET(btree, WT_BTREE_SPECIAL_FLAGS))
return (EBUSY);
else {
WT_RET(__wt_readlock(session, dhandle->rwlock));
- locked = 1;
+ locked = READLOCK;
}
/*
@@ -125,9 +125,16 @@ __wt_session_lock_btree(WT_SESSION_IMPL *session, uint32_t flags)
* The handle needs to be opened. If we locked the handle above,
* unlock it before returning.
*/
- if (locked) {
+ switch (locked) {
+ case NOLOCK:
+ break;
+ case READLOCK:
+ WT_RET(__wt_readunlock(session, dhandle->rwlock));
+ break;
+ case WRITELOCK:
F_CLR(dhandle, WT_DHANDLE_EXCLUSIVE);
- WT_RET(__wt_rwunlock(session, dhandle->rwlock));
+ WT_RET(__wt_writeunlock(session, dhandle->rwlock));
+ break;
}
/* Treat an unopened handle just like a non-existent handle. */
@@ -141,6 +148,7 @@ __wt_session_lock_btree(WT_SESSION_IMPL *session, uint32_t flags)
int
__wt_session_release_btree(WT_SESSION_IMPL *session)
{
+ enum { NOLOCK, READLOCK, WRITELOCK } locked;
WT_BTREE *btree;
WT_DATA_HANDLE *dhandle;
WT_DECL_RET;
@@ -148,28 +156,36 @@ __wt_session_release_btree(WT_SESSION_IMPL *session)
btree = S2BT(session);
dhandle = session->dhandle;
- /* Decrement the data-source's in-use counter. */
- WT_ERR(__session_dhandle_decr_use(session));
+ /*
+ * Decrement the data-source's in-use counter. We ignore errors because
+ * they're insignificant and handling them complicates error handling in
+ * this function more than I'm willing to live with.
+ */
+ (void)__session_dhandle_decr_use(session);
+ locked = F_ISSET(dhandle, WT_DHANDLE_EXCLUSIVE) ? WRITELOCK : READLOCK;
if (F_ISSET(dhandle, WT_DHANDLE_DISCARD_CLOSE)) {
/*
- * If configured to discard on last close, trade our lock for an
- * exclusive lock (we may already have an exclusive lock but it
- * is less likely and discard on close is uncommon, so we don't
- * bother figuring it out. If the exchange succeeds, setup for
+ * If configured to discard on last close, trade any read lock
+ * for an exclusive lock. If the exchange succeeds, setup for
* discard. It is expected acquiring an exclusive lock will fail
* sometimes since the handle may still be in use: in that case
- * we've already unlocked, so we're done.
+ * we're done.
*/
- WT_ERR(__wt_rwunlock(session, dhandle->rwlock));
- ret = __wt_try_writelock(session, dhandle->rwlock);
- if (ret != 0) {
- if (ret == EBUSY)
- ret = 0;
- goto err;
+ if (locked == READLOCK) {
+ locked = NOLOCK;
+ WT_ERR(__wt_readunlock(session, dhandle->rwlock));
+ ret = __wt_try_writelock(session, dhandle->rwlock);
+ if (ret != 0) {
+ if (ret == EBUSY)
+ ret = 0;
+ goto err;
+ }
+ locked = WRITELOCK;
+ F_CLR(dhandle, WT_DHANDLE_DISCARD_CLOSE);
+ F_SET(dhandle,
+ WT_DHANDLE_DISCARD | WT_DHANDLE_EXCLUSIVE);
}
- F_CLR(dhandle, WT_DHANDLE_DISCARD_CLOSE);
- F_SET(dhandle, WT_DHANDLE_DISCARD | WT_DHANDLE_EXCLUSIVE);
}
/*
@@ -187,9 +203,18 @@ __wt_session_release_btree(WT_SESSION_IMPL *session)
if (F_ISSET(dhandle, WT_DHANDLE_EXCLUSIVE))
F_CLR(dhandle, WT_DHANDLE_EXCLUSIVE);
- WT_TRET(__wt_rwunlock(session, dhandle->rwlock));
+err: switch (locked) {
+ case NOLOCK:
+ break;
+ case READLOCK:
+ WT_TRET(__wt_readunlock(session, dhandle->rwlock));
+ break;
+ case WRITELOCK:
+ WT_TRET(__wt_writeunlock(session, dhandle->rwlock));
+ break;
+ }
-err: session->dhandle = NULL;
+ session->dhandle = NULL;
return (ret);
}