summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsueloverso <sue@mongodb.com>2016-07-21 22:52:06 -0400
committerAlex Gorrod <alexander.gorrod@mongodb.com>2016-07-22 12:52:06 +1000
commita5f696c394815e3d630b77187899670b8087da37 (patch)
tree0ef1005922d18e5e02e72abb371aee6cf8c3a15d
parentc74fcf400168930c3f0f9f39f5ec30a06a01f2df (diff)
downloadmongo-a5f696c394815e3d630b77187899670b8087da37.tar.gz
WT-2239 Make sure LSM cursors read up to date dsk_gen, it was racing with compact. (#2895)
-rw-r--r--src/lsm/lsm_cursor.c6
-rw-r--r--src/lsm/lsm_tree.c14
2 files changed, 19 insertions, 1 deletions
diff --git a/src/lsm/lsm_cursor.c b/src/lsm/lsm_cursor.c
index 0fb917e8f4c..a0e636768f0 100644
--- a/src/lsm/lsm_cursor.c
+++ b/src/lsm/lsm_cursor.c
@@ -205,6 +205,12 @@ __clsm_enter(WT_CURSOR_LSM *clsm, bool reset, bool update)
WT_RET(__wt_txn_id_check(session));
WT_RET(__clsm_enter_update(clsm));
+ /*
+ * Switching the tree will update the generation before
+ * updating the switch transaction. We test the
+ * transaction in clsm_enter_update. Now test the
+ * disk generation to avoid races.
+ */
if (clsm->dsk_gen != clsm->lsm_tree->dsk_gen)
goto open;
diff --git a/src/lsm/lsm_tree.c b/src/lsm/lsm_tree.c
index da106ae2089..2ecfb614eee 100644
--- a/src/lsm/lsm_tree.c
+++ b/src/lsm/lsm_tree.c
@@ -771,6 +771,11 @@ __wt_lsm_tree_switch(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
++lsm_tree->dsk_gen;
lsm_tree->modified = true;
+ /*
+ * Ensure the updated disk generation is visible to all other threads
+ * before updating the transaction ID.
+ */
+ WT_FULL_BARRIER();
/*
* Set the switch transaction in the previous chunk unless this is
@@ -1187,8 +1192,15 @@ __wt_lsm_compact(WT_SESSION_IMPL *session, const char *name, bool *skipp)
*/
if (lsm_tree->nchunks > 0 &&
(chunk = lsm_tree->chunk[lsm_tree->nchunks - 1]) != NULL) {
- if (chunk->switch_txn == WT_TXN_NONE)
+ if (chunk->switch_txn == WT_TXN_NONE) {
+ /*
+ * Make sure any cursors open on the tree see the
+ * new switch generation before updating.
+ */
+ ++lsm_tree->dsk_gen;
+ WT_FULL_BARRIER();
chunk->switch_txn = __wt_txn_id_alloc(session, false);
+ }
/*
* If we have a chunk, we want to look for it to be on-disk.
* So we need to add a reference to keep it available.