diff options
author | Keith Bostic <keith@wiredtiger.com> | 2013-12-10 11:55:58 -0500 |
---|---|---|
committer | Keith Bostic <keith@wiredtiger.com> | 2013-12-10 11:55:58 -0500 |
commit | 1d9f9b163fc74e0cda5621540f7498829f0c047a (patch) | |
tree | 9f0e5d3f2e80c84edb04436f0727568f4779e59d | |
parent | 72020c57fbd6673ad45d32f6f07572e7cd819aac (diff) | |
download | mongo-1d9f9b163fc74e0cda5621540f7498829f0c047a.tar.gz |
Don't let reconciliation delete overflow keys out from under readers
instantiating them. #789
-rw-r--r-- | src/btree/rec_write.c | 13 | ||||
-rw-r--r-- | src/btree/row_key.c | 28 |
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; } |