summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2016-03-17 16:32:40 +1100
committerMichael Cahill <michael.cahill@mongodb.com>2016-03-17 16:32:40 +1100
commitfd9840f0e9d4b132675d1ea318c930dafb989c68 (patch)
tree1f996768797f6ab91dad982b15674077c8fe5acd
parent0b8745ea5e5fedd4b173914add7746b99f66aec2 (diff)
parent3d91b967d46e4d4d51b5a2ebf9fb1d3fad50053d (diff)
downloadmongo-fd9840f0e9d4b132675d1ea318c930dafb989c68.tar.gz
Merge branch 'develop' into wt-2426-checkpoint-locking
-rw-r--r--dist/s_string.ok1
-rw-r--r--src/config/config.c9
-rw-r--r--src/include/gcc.h1
-rw-r--r--src/include/lint.h1
-rw-r--r--src/include/lsm.h2
-rw-r--r--src/include/msvc.h1
-rw-r--r--src/lsm/lsm_cursor.c2
-rw-r--r--src/lsm/lsm_tree.c53
-rw-r--r--src/lsm/lsm_worker.c2
-rw-r--r--test/suite/test_lsm03.py60
10 files changed, 94 insertions, 38 deletions
diff --git a/dist/s_string.ok b/dist/s_string.ok
index 43eb7861b23..6762521ca76 100644
--- a/dist/s_string.ok
+++ b/dist/s_string.ok
@@ -878,6 +878,7 @@ ps
psp
pthread
ptr
+ptrdiff
pushms
putK
putV
diff --git a/src/config/config.c b/src/config/config.c
index 9d14353f730..96ef7a4e62a 100644
--- a/src/config/config.c
+++ b/src/config/config.c
@@ -15,13 +15,10 @@
static int
__config_err(WT_CONFIG *conf, const char *msg, int err)
{
- ptrdiff_t d;
-
- d = conf->cur - conf->orig;
-
WT_RET_MSG(conf->session, err,
- "Error parsing '%.*s' at offset %td: %s",
- (int)(conf->end - conf->orig), conf->orig, d, msg);
+ "Error parsing '%.*s' at offset %" WT_PTRDIFFT_FMT ": %s",
+ (int)(conf->end - conf->orig), conf->orig,
+ conf->cur - conf->orig, msg);
}
/*
diff --git a/src/include/gcc.h b/src/include/gcc.h
index 6ccc0de3c03..ce6afdd6e9c 100644
--- a/src/include/gcc.h
+++ b/src/include/gcc.h
@@ -6,6 +6,7 @@
* See the file LICENSE for redistribution information.
*/
+#define WT_PTRDIFFT_FMT "td" /* ptrdiff_t format string */
#define WT_SIZET_FMT "zu" /* size_t format string */
/* Add GCC-specific attributes to types and function declarations. */
diff --git a/src/include/lint.h b/src/include/lint.h
index f8b17022968..1b64186cbab 100644
--- a/src/include/lint.h
+++ b/src/include/lint.h
@@ -6,6 +6,7 @@
* See the file LICENSE for redistribution information.
*/
+#define WT_PTRDIFFT_FMT "td" /* ptrdiff_t format string */
#define WT_SIZET_FMT "zu" /* size_t format string */
#define WT_COMPILER_TYPE_ALIGN(x)
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/include/msvc.h b/src/include/msvc.h
index 99260a44875..d5be5bd8c60 100644
--- a/src/include/msvc.h
+++ b/src/include/msvc.h
@@ -13,6 +13,7 @@
#define inline __inline
+#define WT_PTRDIFFT_FMT "Id" /* ptrdiff_t format string */
#define WT_SIZET_FMT "Iu" /* size_t format string */
/*
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. */
diff --git a/test/suite/test_lsm03.py b/test/suite/test_lsm03.py
new file mode 100644
index 00000000000..448d864c646
--- /dev/null
+++ b/test/suite/test_lsm03.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2016 MongoDB, Inc.
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+import wiredtiger, wtscenario, wttest
+from helper import simple_populate
+
+# test_lsm03.py
+# Check to make sure that LSM schema operations don't get EBUSY when
+# there are no user operations active.
+class test_lsm03(wttest.WiredTigerTestCase):
+ name = 'test_lsm03'
+
+ # Use small pages so we generate some internal layout
+ # Setup LSM so multiple chunks are present
+ config = 'key_format=S,allocation_size=512,internal_page_max=512' + \
+ ',leaf_page_max=1k,lsm=(chunk_size=512k,merge_min=10)'
+
+ # Populate an object then drop it.
+ def test_lsm_drop_active(self):
+ uri = 'lsm:' + self.name
+ simple_populate(self, uri, self.config, 10000)
+
+ # Force to disk
+ self.reopen_conn()
+
+ # An open cursors should cause failure.
+ cursor = self.session.open_cursor(uri, None, None)
+ self.assertRaises(wiredtiger.WiredTigerError,
+ lambda: self.session.drop(uri, None))
+ cursor.close()
+
+ # Add enough records that a merge should be running
+ simple_populate(self, uri, self.config, 50000)
+ # The drop should succeed even when LSM work units are active
+ self.session.drop(uri)