diff options
author | Alex Gorrod <alexg@wiredtiger.com> | 2013-01-08 19:37:09 +1100 |
---|---|---|
committer | Alex Gorrod <alexg@wiredtiger.com> | 2013-01-08 19:37:09 +1100 |
commit | a3237122ec0f32cb1082292a052419dc85925afb (patch) | |
tree | 57112e270dc98961b6a55e4bc174d05a6bd31a3b | |
parent | a2188ebb823f491786f6116ddb588eb81ea95184 (diff) | |
download | mongo-a3237122ec0f32cb1082292a052419dc85925afb.tar.gz |
Add a forced eviction mode that uses a new page state, instead
of re-using the locked state and tracking other information in
the eviction server.
-rw-r--r-- | src/btree/bt_debug.c | 3 | ||||
-rw-r--r-- | src/btree/bt_evict.c | 44 | ||||
-rw-r--r-- | src/btree/bt_page.c | 1 | ||||
-rw-r--r-- | src/btree/bt_walk.c | 5 | ||||
-rw-r--r-- | src/btree/rec_evict.c | 4 | ||||
-rw-r--r-- | src/btree/rec_write.c | 1 | ||||
-rw-r--r-- | src/include/btmem.h | 7 |
7 files changed, 39 insertions, 26 deletions
diff --git a/src/btree/bt_debug.c b/src/btree/bt_debug.c index 20a5f74632c..d740a6550a0 100644 --- a/src/btree/bt_debug.c +++ b/src/btree/bt_debug.c @@ -781,6 +781,9 @@ __debug_ref(WT_DBG *ds, WT_REF *ref, WT_PAGE *page) case WT_REF_DELETED: __dmsg(ds, "deleted"); break; + case WT_REF_EVICT_FORCE: + __dmsg(ds, "evict-force %p", ref->page); + break; case WT_REF_EVICT_WALK: __dmsg(ds, "evict-walk %p", ref->page); break; diff --git a/src/btree/bt_evict.c b/src/btree/bt_evict.c index 558ed786055..204f08d7d01 100644 --- a/src/btree/bt_evict.c +++ b/src/btree/bt_evict.c @@ -36,19 +36,22 @@ static int __evict_worker(WT_SESSION_IMPL *); static inline uint64_t __evict_read_gen(const WT_EVICT_ENTRY *entry) { + WT_PAGE *page; uint64_t read_gen; + page = entry->page; + /* Never prioritize empty slots. */ - if (entry->page == NULL) + if (page == NULL) return (UINT64_MAX); /* Always prioritize pages selected by force. */ - if (F_ISSET_ATOMIC(entry->page, WT_PAGE_EVICT_LOCKED)) + if (page->ref->state == WT_REF_EVICT_FORCE) return (0); - read_gen = entry->page->read_gen + entry->btree->evict_priority; - if (entry->page->type == WT_PAGE_ROW_INT || - entry->page->type == WT_PAGE_COL_INT) + read_gen = page->read_gen + entry->btree->evict_priority; + if (page->type == WT_PAGE_ROW_INT || + page->type == WT_PAGE_COL_INT) read_gen += WT_EVICT_INT_SKEW; return (read_gen); @@ -76,8 +79,6 @@ __evict_lru_cmp(const void *a, const void *b) static inline void __evict_list_clr(WT_SESSION_IMPL *session, WT_EVICT_ENTRY *e) { - WT_REF *ref; - if (e->page != NULL) { WT_ASSERT(session, F_ISSET_ATOMIC(e->page, WT_PAGE_EVICT_LRU)); F_CLR_ATOMIC(e->page, WT_PAGE_EVICT_LRU); @@ -86,13 +87,8 @@ __evict_list_clr(WT_SESSION_IMPL *session, WT_EVICT_ENTRY *e) * clear the locked state when removing it from the eviction * queue. */ - if (F_ISSET_ATOMIC(e->page, WT_PAGE_EVICT_LOCKED)) { - ref = e->page->ref; - WT_ASSERT(session, ref->state == WT_REF_LOCKED); - (void)WT_ATOMIC_CAS( - ref->state, WT_REF_LOCKED, WT_REF_MEM); - F_CLR_ATOMIC(e->page, WT_PAGE_EVICT_LOCKED); - } + (void)WT_ATOMIC_CAS(e->page->ref->state, + WT_REF_EVICT_FORCE, WT_REF_MEM); } e->page = NULL; e->btree = WT_DEBUG_POINT; @@ -131,6 +127,7 @@ __wt_evict_list_clr_page(WT_SESSION_IMPL *session, WT_PAGE *page) WT_ASSERT(session, WT_PAGE_IS_ROOT(page) || page->ref->page != page || + page->ref->state == WT_REF_EVICT_FORCE || page->ref->state == WT_REF_EVICT_WALK || page->ref->state == WT_REF_LOCKED); @@ -201,14 +198,12 @@ __wt_evict_forced_page(WT_SESSION_IMPL *session, WT_PAGE *page) * page - which makes it more likely that the next pass of the eviction * server will successfully evict the page. */ - if (!WT_ATOMIC_CAS(page->ref->state, WT_REF_MEM, WT_REF_LOCKED)) + if (!WT_ATOMIC_CAS(page->ref->state, WT_REF_MEM, WT_REF_EVICT_FORCE)) goto err; - /* Tell eviction that we already have the page locked. */ - F_SET_ATOMIC(page, WT_PAGE_EVICT_LOCKED); err: __wt_spin_unlock(session, &cache->evict_lock); /* Only wake the server if the page was added and locked. */ - if (ret == 0 && F_ISSET_ATOMIC(page, WT_PAGE_EVICT_LOCKED)) { + if (ret == 0 && page->ref->state == WT_REF_EVICT_FORCE) { F_SET(S2C(session)->cache, WT_EVICT_FORCE_PASS); __wt_evict_server_wake(session); } @@ -1085,10 +1080,15 @@ __evict_get_page( ref = evict->page->ref; WT_ASSERT(session, evict->page == ref->page); - /* Explicitly requested pages are already locked. */ - if (F_ISSET_ATOMIC(ref->page, WT_PAGE_EVICT_LOCKED)) - F_CLR_ATOMIC(ref->page, WT_PAGE_EVICT_LOCKED); - else if (!WT_ATOMIC_CAS(ref->state, WT_REF_MEM, WT_REF_LOCKED)) + /* + * Switch pages from the evict force state to locked - the + * logic for forced and regular eviction is identical from here + * on, and having reconciliation be able to use a single + * locked state simplifies that code. + */ + if (!WT_ATOMIC_CAS( + ref->state, WT_REF_EVICT_FORCE, WT_REF_LOCKED) && + !WT_ATOMIC_CAS(ref->state, WT_REF_MEM, WT_REF_LOCKED)) continue; /* diff --git a/src/btree/bt_page.c b/src/btree/bt_page.c index 0f63b11b7a2..712417f8889 100644 --- a/src/btree/bt_page.c +++ b/src/btree/bt_page.c @@ -42,6 +42,7 @@ __wt_page_in_func( WT_RET(__wt_cache_full_check(session)); WT_RET(__wt_cache_read(session, parent, ref)); continue; + case WT_REF_EVICT_FORCE: case WT_REF_LOCKED: case WT_REF_READING: /* diff --git a/src/btree/bt_walk.c b/src/btree/bt_walk.c index 1b4a1d7c2fa..7c5b2f2ca79 100644 --- a/src/btree/bt_walk.c +++ b/src/btree/bt_walk.c @@ -284,8 +284,9 @@ retry: if (!WT_ATOMIC_CAS(ref->state, * that the page will be read back in to cache. */ while (LF_ISSET(WT_TREE_WAIT) && - (ref->state == WT_REF_LOCKED || - ref->state == WT_REF_READING)) + (ref->state == WT_REF_EVICT_FORCE || + ref->state == WT_REF_LOCKED || + ref->state == WT_REF_READING)) __wt_yield(); if (ref->state == WT_REF_DELETED || ref->state == WT_REF_DISK) diff --git a/src/btree/rec_evict.c b/src/btree/rec_evict.c index b739e644099..c158a20325c 100644 --- a/src/btree/rec_evict.c +++ b/src/btree/rec_evict.c @@ -273,6 +273,7 @@ __rec_review(WT_SESSION_IMPL *session, session, ref, ref->page, exclusive, 0)); break; case WT_REF_EVICT_WALK: /* Walk point */ + case WT_REF_EVICT_FORCE: /* Forced evict */ case WT_REF_LOCKED: /* Being evicted */ case WT_REF_READING: /* Being read */ return (EBUSY); @@ -462,7 +463,8 @@ __rec_excl_clear(WT_SESSION_IMPL *session) if ((ref = session->excl[i]) == NULL) break; WT_ASSERT(session, - ref->state == WT_REF_LOCKED && ref->page != NULL); + (ref->state == WT_REF_LOCKED || + ref->state == WT_REF_EVICT_FORCE) && ref->page != NULL); ref->state = WT_REF_MEM; } } diff --git a/src/btree/rec_write.c b/src/btree/rec_write.c index 34908d5a79f..61fbf030596 100644 --- a/src/btree/rec_write.c +++ b/src/btree/rec_write.c @@ -323,6 +323,7 @@ __rec_child_modify(WT_SESSION_IMPL *session, WT_HAVE_DIAGNOSTIC_YIELD; return (ret); + case WT_REF_EVICT_FORCE: case WT_REF_LOCKED: /* * If being called by the eviction server, the page was diff --git a/src/include/btmem.h b/src/include/btmem.h index 16572e433be..9fc0225e296 100644 --- a/src/include/btmem.h +++ b/src/include/btmem.h @@ -308,7 +308,6 @@ struct __wt_page { #define WT_PAGE_BUILD_KEYS 0x01 /* Keys have been built in memory */ #define WT_PAGE_EVICT_LRU 0x02 /* Page is on the LRU queue */ -#define WT_PAGE_EVICT_LOCKED 0x04 /* Page was locked when queued */ uint8_t flags_atomic; /* Atomic flags, use F_*_ATOMIC */ }; @@ -338,6 +337,11 @@ struct __wt_page { * row-store leaf pages without reading them if they don't reference overflow * items. * + * WT_REF_EVICT_FORCE: + * An application thread has selected this page for eviction. No other + * hazard references should be granted. If eviction fails, the eviction server + * should set the state back to WT_REF_MEM. + * * WT_REF_EVICT_WALK: * The next page to be walked for LRU eviction. This page is available for * reads but not eviction. @@ -375,6 +379,7 @@ struct __wt_page { enum __wt_page_state { WT_REF_DISK=0, /* Page is on disk */ WT_REF_DELETED, /* Page is on disk, but deleted */ + WT_REF_EVICT_FORCE, /* Page is ready for forced eviction */ WT_REF_EVICT_WALK, /* Next page for LRU eviction */ WT_REF_LOCKED, /* Page being evicted */ WT_REF_MEM, /* Page is in cache and valid */ |