summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2016-03-17 16:32:03 +1100
committerMichael Cahill <michael.cahill@mongodb.com>2016-03-17 16:32:03 +1100
commit3d91b967d46e4d4d51b5a2ebf9fb1d3fad50053d (patch)
treefa8a44617e1528b4dfec3d8f7acaad118330fb79 /src
parent83bb8a3c49507d5b4d89d6b467b654338a98f564 (diff)
parentb15c7d5d682305e3b4088e19b4171c45556598d6 (diff)
downloadmongo-3d91b967d46e4d4d51b5a2ebf9fb1d3fad50053d.tar.gz
Merge pull request #2587 from wiredtiger/wt-2457-lsm-exclusive
WT-2457 Wait for LSM work units to drain when getting exclusive access.
Diffstat (limited to 'src')
-rw-r--r--src/include/lsm.h2
-rw-r--r--src/lsm/lsm_cursor.c2
-rw-r--r--src/lsm/lsm_tree.c53
-rw-r--r--src/lsm/lsm_worker.c2
4 files changed, 27 insertions, 32 deletions
diff --git a/src/include/lsm.h b/src/include/lsm.h
index 5a3a63a03eb..eacb4d52d3e 100644
--- a/src/include/lsm.h
+++ b/src/include/lsm.h
@@ -179,7 +179,7 @@ struct __wt_lsm_tree {
int collator_owned;
uint32_t refcnt; /* Number of users of the tree */
- uint8_t exclusive; /* Tree is locked exclusively */
+ WT_SESSION_IMPL *excl_session; /* Session has exclusive lock */
#define LSM_TREE_MAX_QUEUE 100
uint32_t queue_ref;
diff --git a/src/lsm/lsm_cursor.c b/src/lsm/lsm_cursor.c
index 0197b6481f4..e023b2b407e 100644
--- a/src/lsm/lsm_cursor.c
+++ b/src/lsm/lsm_cursor.c
@@ -1556,7 +1556,7 @@ __wt_clsm_open(WT_SESSION_IMPL *session,
WT_ERR(ret);
/* Make sure we have exclusive access if and only if we want it */
- WT_ASSERT(session, !bulk || lsm_tree->exclusive);
+ WT_ASSERT(session, !bulk || lsm_tree->excl_session != NULL);
WT_ERR(__wt_calloc_one(session, &clsm));
diff --git a/src/lsm/lsm_tree.c b/src/lsm/lsm_tree.c
index 70ac912f333..e79d52c18e9 100644
--- a/src/lsm/lsm_tree.c
+++ b/src/lsm/lsm_tree.c
@@ -114,11 +114,14 @@ __lsm_tree_close(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
if (i % WT_THOUSAND == 0) {
WT_WITHOUT_LOCKS(session, ret =
__wt_lsm_manager_clear_tree(session, lsm_tree));
- WT_RET(ret);
+ WT_ERR(ret);
}
__wt_yield();
}
return (0);
+
+err: F_SET(lsm_tree, WT_LSM_TREE_ACTIVE);
+ return (ret);
}
/*
@@ -363,27 +366,25 @@ __lsm_tree_find(WT_SESSION_IMPL *session,
/* See if the tree is already open. */
TAILQ_FOREACH(lsm_tree, &S2C(session)->lsmqh, q)
if (strcmp(uri, lsm_tree->name) == 0) {
- /*
- * Short circuit if the handle is already held
- * exclusively or exclusive access is requested and
- * there are references held.
- */
- if ((exclusive && lsm_tree->refcnt > 0) ||
- lsm_tree->exclusive)
- return (EBUSY);
-
if (exclusive) {
/*
* Make sure we win the race to switch on the
* exclusive flag.
*/
- if (!__wt_atomic_cas8(
- &lsm_tree->exclusive, 0, 1))
+ if (!__wt_atomic_cas_ptr(
+ &lsm_tree->excl_session, NULL, session))
return (EBUSY);
- /* Make sure there are no readers */
- if (!__wt_atomic_cas32(
+
+ /*
+ * Drain the work queue before checking for
+ * open cursors - otherwise we can generate
+ * spurious busy returns.
+ */
+ if (__lsm_tree_close(session, lsm_tree) != 0 ||
+ !__wt_atomic_cas32(
&lsm_tree->refcnt, 0, 1)) {
- lsm_tree->exclusive = 0;
+ F_SET(lsm_tree, WT_LSM_TREE_ACTIVE);
+ lsm_tree->excl_session = NULL;
return (EBUSY);
}
} else {
@@ -393,7 +394,7 @@ __lsm_tree_find(WT_SESSION_IMPL *session,
* We got a reference, check if an exclusive
* lock beat us to it.
*/
- if (lsm_tree->exclusive) {
+ if (lsm_tree->excl_session != NULL) {
WT_ASSERT(session,
lsm_tree->refcnt > 0);
(void)__wt_atomic_sub32(
@@ -489,7 +490,7 @@ __lsm_tree_open(WT_SESSION_IMPL *session,
* with getting handles exclusive.
*/
lsm_tree->refcnt = 1;
- lsm_tree->exclusive = exclusive ? 1 : 0;
+ lsm_tree->excl_session = exclusive ? session : NULL;
lsm_tree->queue_ref = 0;
/* Set a flush timestamp as a baseline. */
@@ -524,7 +525,7 @@ __wt_lsm_tree_get(WT_SESSION_IMPL *session,
ret = __lsm_tree_open(session, uri, exclusive, treep);
WT_ASSERT(session, ret != 0 ||
- (exclusive ? 1 : 0) == (*treep)->exclusive);
+ (*treep)->excl_session == (exclusive ? session : NULL));
return (ret);
}
@@ -536,8 +537,11 @@ void
__wt_lsm_tree_release(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
{
WT_ASSERT(session, lsm_tree->refcnt > 0);
- if (lsm_tree->exclusive)
- lsm_tree->exclusive = 0;
+ if (lsm_tree->excl_session == session) {
+ /* We cleared the active flag when getting exclusive access. */
+ F_SET(lsm_tree, WT_LSM_TREE_ACTIVE);
+ lsm_tree->excl_session = NULL;
+ }
(void)__wt_atomic_sub32(&lsm_tree->refcnt, 1);
}
@@ -851,9 +855,6 @@ __wt_lsm_tree_drop(
ret = __wt_lsm_tree_get(session, name, true, &lsm_tree));
WT_RET(ret);
- /* Shut down the LSM worker. */
- WT_ERR(__lsm_tree_close(session, lsm_tree));
-
/* Prevent any new opens. */
WT_ERR(__wt_lsm_tree_writelock(session, lsm_tree));
locked = true;
@@ -913,9 +914,6 @@ __wt_lsm_tree_rename(WT_SESSION_IMPL *session,
ret = __wt_lsm_tree_get(session, olduri, true, &lsm_tree));
WT_RET(ret);
- /* Shut down the LSM worker. */
- WT_ERR(__lsm_tree_close(session, lsm_tree));
-
/* Prevent any new opens. */
WT_ERR(__wt_lsm_tree_writelock(session, lsm_tree));
locked = true;
@@ -988,9 +986,6 @@ __wt_lsm_tree_truncate(
ret = __wt_lsm_tree_get(session, name, true, &lsm_tree));
WT_RET(ret);
- /* Shut down the LSM worker. */
- WT_ERR(__lsm_tree_close(session, lsm_tree));
-
/* Prevent any new opens. */
WT_ERR(__wt_lsm_tree_writelock(session, lsm_tree));
locked = true;
diff --git a/src/lsm/lsm_worker.c b/src/lsm/lsm_worker.c
index b8a85e4a5e5..0874da8db13 100644
--- a/src/lsm/lsm_worker.c
+++ b/src/lsm/lsm_worker.c
@@ -139,7 +139,7 @@ __lsm_worker(void *arg)
if (ret == WT_NOTFOUND) {
F_CLR(entry->lsm_tree, WT_LSM_TREE_COMPACTING);
ret = 0;
- } else if (ret == EBUSY)
+ } else if (ret == EBUSY || ret == EINTR)
ret = 0;
/* Paranoia: clear session state. */