summaryrefslogtreecommitdiff
path: root/src/support
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2012-08-06 09:51:42 +0000
committerKeith Bostic <keith@wiredtiger.com>2012-08-06 09:53:08 +0000
commit7933a39e61489a918998dfa0b14af8855dc713c7 (patch)
treedc602e964ed8ecf1a67af2c18f1f3c1cf7b07805 /src/support
parentd217b2c6758c37fb06dc08d5b4b127ec572452ae (diff)
downloadmongo-7933a39e61489a918998dfa0b14af8855dc713c7.tar.gz
Michael's fix for a hazard reference race, where page eviction races with the
creation of the hazard reference, we have to check the pointer itself as well as the state of the pointer. Close #284. the creation of the hazard reference and the actua
Diffstat (limited to 'src/support')
-rw-r--r--src/support/hazard.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/src/support/hazard.c b/src/support/hazard.c
index 71060a08f19..c713f9a5ee9 100644
--- a/src/support/hazard.c
+++ b/src/support/hazard.c
@@ -42,11 +42,11 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, int *busyp
* page eviction server.
*
* Add the WT_REF reference to the session's hazard list and flush the
- * write, then see if the state field is still WT_REF_MEM. If it's
- * still WT_REF_MEM, we can use the page because the page eviction
- * server will see our hazard reference before it discards the buffer
- * (the eviction server sets the state to WT_REF_LOCKED, then flushes
- * memory and checks the hazard references).
+ * write, then see if the page's state is still valid. If so, we can
+ * use the page because the page eviction server will see our hazard
+ * reference before it discards the page (the eviction server sets the
+ * state to WT_REF_LOCKED, then flushes memory and checks the hazard
+ * references).
*/
for (hp = session->hazard;
hp < session->hazard + conn->hazard_size; ++hp) {
@@ -62,11 +62,19 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, int *busyp
WT_FULL_BARRIER();
/*
- * Check to see if the page state is still valid (where valid
- * means a state of WT_REF_MEM or WT_REF_EVICT_WALK).
+ * Check if the page state is still valid, where valid means a
+ * state of WT_REF_MEM or WT_REF_EVICT_WALK and the pointer is
+ * unchanged. (The pointer can change, it means the page was
+ * evicted between the time we set our hazard reference and the
+ * publication. It would theoretically be possible for the
+ * page to be evicted and a different page read into the same
+ * memory, so the pointer hasn't changed but the contents have.
+ * That's OK, we found this page in tree's key space, whatever
+ * page we find here is the page page for us to use.)
*/
- if (ref->state == WT_REF_MEM ||
- ref->state == WT_REF_EVICT_WALK) {
+ if (ref->page == hp->page &&
+ (ref->state == WT_REF_MEM ||
+ ref->state == WT_REF_EVICT_WALK)) {
WT_VERBOSE_RET(session, hazard,
"session %p hazard %p: set", session, ref->page);
@@ -88,9 +96,7 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, int *busyp
* go ahead and complete the eviction.
*
* We don't bother publishing this update: the worst case is we
- * prevent the page from being evicted, but that's not going to
- * happen repeatedly, the eviction thread gives up and won't try
- * again until it loops around through the tree.
+ * prevent some random page from being evicted.
*/
hp->page = NULL;
*busyp = 1;