summaryrefslogtreecommitdiff
path: root/src/evict/evict_page.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/evict/evict_page.c')
-rw-r--r--src/evict/evict_page.c87
1 files changed, 43 insertions, 44 deletions
diff --git a/src/evict/evict_page.c b/src/evict/evict_page.c
index b15e1c1f26c..5b17a78a4dd 100644
--- a/src/evict/evict_page.c
+++ b/src/evict/evict_page.c
@@ -37,7 +37,7 @@ __evict_exclusive(WT_SESSION_IMPL *session, WT_REF *ref)
* Check for a hazard pointer indicating another thread is using the
* page, meaning the page cannot be evicted.
*/
- if (__wt_page_hazard_check(session, ref->page) == NULL)
+ if (__wt_hazard_check(session, ref) == NULL)
return (0);
WT_STAT_DATA_INCR(session, cache_eviction_hazard);
@@ -66,7 +66,7 @@ __wt_page_release_evict(WT_SESSION_IMPL *session, WT_REF *ref)
* between.
*/
locked = __wt_atomic_casv32(&ref->state, WT_REF_MEM, WT_REF_LOCKED);
- if ((ret = __wt_hazard_clear(session, page)) != 0 || !locked) {
+ if ((ret = __wt_hazard_clear(session, ref)) != 0 || !locked) {
if (locked)
ref->state = WT_REF_MEM;
return (ret == 0 ? EBUSY : ret);
@@ -163,19 +163,8 @@ __wt_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool closing)
*/
WT_ERR(__evict_page_clean_update(
session, ref, tree_dead || closing));
- else {
- /*
- * The page is not being completely evicted: instead it is
- * being split or replaced. In that case, don't increment the
- * count of pages evicted, which we use to decide whether
- * eviction is making progress. Repeatedly rewriting the same
- * page isn't progress.
- */
- F_SET(session, WT_SESSION_IN_SPLIT);
- ret = __evict_page_dirty_update(session, ref, closing);
- F_CLR(session, WT_SESSION_IN_SPLIT);
- WT_ERR(ret);
- }
+ else
+ WT_ERR(__evict_page_dirty_update(session, ref, closing));
if (clean_page) {
WT_STAT_CONN_INCR(session, cache_eviction_clean);
@@ -407,7 +396,7 @@ __evict_review(
WT_DECL_RET;
WT_PAGE *page;
uint32_t flags;
- bool modified;
+ bool lookaside_retry, modified;
flags = WT_EVICTING;
*flagsp = flags;
@@ -506,27 +495,29 @@ __evict_review(
* If we have an exclusive lock (we're discarding the tree), assert
* there are no updates we cannot read.
*
- * Don't set any other flags for internal pages: they don't have update
- * lists to be saved and restored, nor can we re-create them in memory.
+ * Don't set any other flags for internal pages: there are no update
+ * lists to be saved and restored, changes can't be written into the
+ * lookaside table, nor can we re-create internal pages in memory.
*
* For leaf pages:
*
- * If an in-memory configuration or the page is being forcibly evicted,
- * set the update-restore flag, so reconciliation will write blocks it
+ * In-memory pages are a known configuration.
+ *
+ * Set the update/restore flag, so reconciliation will write blocks it
* can write and create a list of skipped updates for blocks it cannot
- * write, along with disk images. This is how eviction of active, huge
+ * write, along with disk images. This is how eviction of active, huge
* pages works: we take a big page and reconcile it into blocks, some of
* which we write and discard, the rest of which we re-create as smaller
* in-memory pages, (restoring the updates that stopped us from writing
- * the block), and inserting the whole mess into the page's parent.
+ * the block), and inserting the whole mess into the page's parent. Set
+ * the flag in all cases because the incremental cost of update/restore
+ * in reconciliation is minimal, eviction shouldn't have picked a page
+ * where update/restore is necessary, absent some cache pressure. It's
+ * possible updates occurred after we selected this page for eviction,
+ * but it's unlikely and we don't try and manage that risk.
*
- * Otherwise, if eviction is getting pressed, configure reconciliation
- * to write not-yet-globally-visible updates to the lookaside table,
- * allowing the eviction of pages we'd otherwise have to retain in cache
- * to support older readers.
- *
- * Finally, if we don't need to do eviction at the moment, create disk
- * images of split pages in order to re-instantiate them.
+ * Additionally, if we aren't trying to free space in the cache, scrub
+ * the page and keep it in memory.
*/
cache = S2C(session)->cache;
if (closing)
@@ -535,25 +526,33 @@ __evict_review(
if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY))
LF_SET(WT_EVICT_IN_MEMORY |
WT_EVICT_SCRUB | WT_EVICT_UPDATE_RESTORE);
- else if (__wt_cache_stuck(session))
- LF_SET(WT_EVICT_LOOKASIDE);
- else if (!__wt_txn_visible_all(
- session, page->modify->update_txn) ||
- page->read_gen == WT_READGEN_OLDEST ||
- page->memory_footprint >= S2BT(session)->splitmempage)
+ else {
LF_SET(WT_EVICT_UPDATE_RESTORE);
- /*
- * If we aren't trying to free space in the cache, scrub the
- * page and keep it around.
- */
- if (!LF_ISSET(WT_EVICT_LOOKASIDE) &&
- F_ISSET(cache, WT_CACHE_EVICT_SCRUB))
- LF_SET(WT_EVICT_SCRUB);
+ if (F_ISSET(cache, WT_CACHE_EVICT_SCRUB))
+ LF_SET(WT_EVICT_SCRUB);
+ }
}
- *flagsp = flags;
- WT_RET(__wt_reconcile(session, ref, NULL, flags));
+ /* Reconcile the page. */
+ ret = __wt_reconcile(session, ref, NULL, flags, &lookaside_retry);
+
+ /*
+ * If reconciliation fails, eviction is stuck and reconciliation reports
+ * it might succeed if we use the lookaside table (the page didn't have
+ * uncommitted updates, it was not-yet-globally visible updates causing
+ * the problem), configure reconciliation to write those updates to the
+ * lookaside table, allowing the eviction of pages we'd otherwise have
+ * to retain in cache to support older readers.
+ */
+ if (ret == EBUSY && __wt_cache_stuck(session) && lookaside_retry) {
+ LF_CLR(WT_EVICT_SCRUB | WT_EVICT_UPDATE_RESTORE);
+ LF_SET(WT_EVICT_LOOKASIDE);
+ ret = __wt_reconcile(session, ref, NULL, flags, NULL);
+ }
+
+ *flagsp = flags;
+ WT_RET(ret);
/*
* Success: assert the page is clean or reconciliation was configured