summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2013-12-10 11:55:58 -0500
committerKeith Bostic <keith@wiredtiger.com>2013-12-10 11:55:58 -0500
commit1d9f9b163fc74e0cda5621540f7498829f0c047a (patch)
tree9f0e5d3f2e80c84edb04436f0727568f4779e59d
parent72020c57fbd6673ad45d32f6f07572e7cd819aac (diff)
downloadmongo-1d9f9b163fc74e0cda5621540f7498829f0c047a.tar.gz
Don't let reconciliation delete overflow keys out from under readers
instantiating them. #789
-rw-r--r--src/btree/rec_write.c13
-rw-r--r--src/btree/row_key.c28
2 files changed, 38 insertions, 3 deletions
diff --git a/src/btree/rec_write.c b/src/btree/rec_write.c
index 573d5c44f39..6fd89ca9429 100644
--- a/src/btree/rec_write.c
+++ b/src/btree/rec_write.c
@@ -3470,6 +3470,19 @@ __rec_row_leaf(WT_SESSION_IMPL *session,
WT_ERR(__wt_row_leaf_key_work(
session,
page, rip, NULL, 1));
+
+ /*
+ * Acquire the overflow lock to avoid
+ * racing with a thread instantiating
+ * the key. Reader threads hold read
+ * locks on the overflow lock when
+ * checking for key instantiation.
+ */
+ WT_ERR(__wt_writelock(session,
+ S2BT(session)->val_ovfl_lock));
+ WT_ERR(__wt_rwunlock(session,
+ S2BT(session)->val_ovfl_lock));
+
WT_ERR(__wt_ovfl_onpage_add(
session, page,
unpack->data, unpack->size));
diff --git a/src/btree/row_key.c b/src/btree/row_key.c
index 5081e00ab31..66790c0c55e 100644
--- a/src/btree/row_key.c
+++ b/src/btree/row_key.c
@@ -174,7 +174,7 @@ __wt_row_leaf_key_work(WT_SESSION_IMPL *session,
* 1: the test for an on/off page reference.
*/
if (__wt_off_page(page, key)) {
- ikey = key;
+off_page: ikey = key;
/*
* If this is the key we originally wanted, we don't
@@ -233,10 +233,32 @@ __wt_row_leaf_key_work(WT_SESSION_IMPL *session,
/*
* If this is the key we wanted from the start, we don't
* care if it's an overflow key, get a copy and wrap up.
+ *
+ * Avoid racing with reconciliation deleting overflow
+ * keys. Deleted overflow keys must be instantiated
+ * first, acquire the overflow lock and check. Read
+ * the key if we still need to do so, but holding the
+ * overflow lock. Note we not using the version of
+ * the cell-data-ref calls that acquire the overflow
+ * lock and do a look-aside into the tracking cache:
+ * this is an overflow key, not a value, meaning it's
+ * instantiated before being deleted, not copied into
+ * the tracking cache.
*/
if (slot_offset == 0) {
- WT_ERR(__wt_dsk_cell_data_ref(
- session, WT_PAGE_ROW_LEAF, unpack, retb));
+ WT_ERR(__wt_readlock(
+ session, S2BT(session)->val_ovfl_lock));
+ key = WT_ROW_KEY_COPY(rip);
+ if (__wt_off_page(page, key)) {
+ WT_ERR(__wt_rwunlock(session,
+ S2BT(session)->val_ovfl_lock));
+ goto off_page;
+ }
+ ret = __wt_dsk_cell_data_ref(
+ session, WT_PAGE_ROW_LEAF, unpack, retb);
+ WT_TRET(__wt_rwunlock(session,
+ S2BT(session)->val_ovfl_lock));
+ WT_ERR(ret);
break;
}