diff options
author | Michael Cahill <michael.cahill@mongodb.com> | 2016-03-17 16:32:03 +1100 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2016-03-17 16:32:03 +1100 |
commit | 3d91b967d46e4d4d51b5a2ebf9fb1d3fad50053d (patch) | |
tree | fa8a44617e1528b4dfec3d8f7acaad118330fb79 /src | |
parent | 83bb8a3c49507d5b4d89d6b467b654338a98f564 (diff) | |
parent | b15c7d5d682305e3b4088e19b4171c45556598d6 (diff) | |
download | mongo-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.h | 2 | ||||
-rw-r--r-- | src/lsm/lsm_cursor.c | 2 | ||||
-rw-r--r-- | src/lsm/lsm_tree.c | 53 | ||||
-rw-r--r-- | src/lsm/lsm_worker.c | 2 |
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. */ |