diff options
Diffstat (limited to 'src/third_party/wiredtiger/src/include/btree.i')
-rw-r--r-- | src/third_party/wiredtiger/src/include/btree.i | 158 |
1 files changed, 96 insertions, 62 deletions
diff --git a/src/third_party/wiredtiger/src/include/btree.i b/src/third_party/wiredtiger/src/include/btree.i index 3234ad1ed41..1ca6426eef6 100644 --- a/src/third_party/wiredtiger/src/include/btree.i +++ b/src/third_party/wiredtiger/src/include/btree.i @@ -61,18 +61,29 @@ __wt_btree_block_free( static inline uint64_t __wt_btree_bytes_inuse(WT_SESSION_IMPL *session) { + WT_BTREE *btree; WT_CACHE *cache; - uint64_t bytes_inuse; + btree = S2BT(session); cache = S2C(session)->cache; - /* Adjust the cache size to take allocation overhead into account. */ - bytes_inuse = S2BT(session)->bytes_inmem; - if (cache->overhead_pct != 0) - bytes_inuse += - (bytes_inuse * (uint64_t)cache->overhead_pct) / 100; + return (__wt_cache_bytes_plus_overhead(cache, btree->bytes_inmem)); +} + +/* + * __wt_btree_dirty_leaf_inuse -- + * Return the number of bytes in use by dirty leaf pages. + */ +static inline uint64_t +__wt_btree_dirty_leaf_inuse(WT_SESSION_IMPL *session) +{ + WT_BTREE *btree; + WT_CACHE *cache; + + btree = S2BT(session); + cache = S2C(session)->cache; - return (bytes_inuse); + return (__wt_cache_bytes_plus_overhead(cache, btree->bytes_dirty_leaf)); } /* @@ -82,18 +93,24 @@ __wt_btree_bytes_inuse(WT_SESSION_IMPL *session) static inline void __wt_cache_page_inmem_incr(WT_SESSION_IMPL *session, WT_PAGE *page, size_t size) { + WT_BTREE *btree; WT_CACHE *cache; WT_ASSERT(session, size < WT_EXABYTE); - + btree = S2BT(session); cache = S2C(session)->cache; - (void)__wt_atomic_add64(&S2BT(session)->bytes_inmem, size); + + (void)__wt_atomic_add64(&btree->bytes_inmem, size); (void)__wt_atomic_add64(&cache->bytes_inmem, size); (void)__wt_atomic_addsize(&page->memory_footprint, size); if (__wt_page_is_modified(page)) { (void)__wt_atomic_addsize(&page->modify->bytes_dirty, size); - (void)__wt_atomic_add64(WT_PAGE_IS_INTERNAL(page) ? - &cache->bytes_dirty_intl : &cache->bytes_dirty_leaf, size); + if (WT_PAGE_IS_INTERNAL(page)) + (void)__wt_atomic_add64(&cache->bytes_dirty_intl, size); + else { + (void)__wt_atomic_add64(&cache->bytes_dirty_leaf, size); + (void)__wt_atomic_add64(&btree->bytes_dirty_leaf, size); + } } /* Track internal size in cache. */ if (WT_PAGE_IS_INTERNAL(page)) @@ -157,6 +174,22 @@ __wt_cache_decr_check_uint64( } /* + * __wt_cache_decr_zero_uint64 -- + * Decrement a uint64_t cache value and zero it on underflow. + */ +static inline void +__wt_cache_decr_zero_uint64( + WT_SESSION_IMPL *session, uint64_t *vp, size_t v, const char *fld) +{ + if (__wt_atomic_sub64(vp, v) < WT_EXABYTE) + return; + + __wt_errx( + session, "%s went negative: decrementing %" WT_SIZET_FMT, fld, v); + *vp = 0; +} + +/* * __wt_cache_page_byte_dirty_decr -- * Decrement the page's dirty byte count, guarding from underflow. */ @@ -164,17 +197,14 @@ static inline void __wt_cache_page_byte_dirty_decr( WT_SESSION_IMPL *session, WT_PAGE *page, size_t size) { + WT_BTREE *btree; WT_CACHE *cache; - const char *destname; - uint64_t *dest; size_t decr, orig; int i; + btree = S2BT(session); cache = S2C(session)->cache; - dest = WT_PAGE_IS_INTERNAL(page) ? - &cache->bytes_dirty_intl : &cache->bytes_dirty_leaf; - destname = WT_PAGE_IS_INTERNAL(page) ? - "WT_CACHE.bytes_dirty_intl" : "WT_CACHE.bytes_dirty_leaf"; + decr = 0; /* [-Wconditional-uninitialized] */ /* * We don't have exclusive access and there are ways of decrementing the @@ -201,11 +231,21 @@ __wt_cache_page_byte_dirty_decr( orig = page->modify->bytes_dirty; decr = WT_MIN(size, orig); if (__wt_atomic_cassize( - &page->modify->bytes_dirty, orig, orig - decr)) { - __wt_cache_decr_check_uint64( - session, dest, decr, destname); + &page->modify->bytes_dirty, orig, orig - decr)) break; - } + } + + if (i == 5) + return; + + if (WT_PAGE_IS_INTERNAL(page)) + __wt_cache_decr_check_uint64(session, &cache->bytes_dirty_intl, + decr, "WT_CACHE.bytes_dirty_intl"); + else { + __wt_cache_decr_check_uint64(session, &btree->bytes_dirty_leaf, + decr, "WT_BTREE.bytes_dirty_leaf"); + __wt_cache_decr_check_uint64(session, &cache->bytes_dirty_leaf, + decr, "WT_CACHE.bytes_dirty_leaf"); } } @@ -244,20 +284,26 @@ __wt_cache_page_inmem_decr(WT_SESSION_IMPL *session, WT_PAGE *page, size_t size) static inline void __wt_cache_dirty_incr(WT_SESSION_IMPL *session, WT_PAGE *page) { + WT_BTREE *btree; WT_CACHE *cache; size_t size; + btree = S2BT(session); cache = S2C(session)->cache; - (void)__wt_atomic_add64(WT_PAGE_IS_INTERNAL(page) ? - &cache->pages_dirty_intl : &cache->pages_dirty_leaf, 1); /* * Take care to read the memory_footprint once in case we are racing * with updates. */ size = page->memory_footprint; - (void)__wt_atomic_add64(WT_PAGE_IS_INTERNAL(page) ? - &cache->bytes_dirty_intl : &cache->bytes_dirty_leaf, size); + if (WT_PAGE_IS_INTERNAL(page)) { + (void)__wt_atomic_add64(&cache->bytes_dirty_intl, size); + (void)__wt_atomic_add64(&cache->pages_dirty_intl, 1); + } else { + (void)__wt_atomic_add64(&btree->bytes_dirty_leaf, size); + (void)__wt_atomic_add64(&cache->bytes_dirty_leaf, size); + (void)__wt_atomic_add64(&cache->pages_dirty_leaf, 1); + } (void)__wt_atomic_addsize(&page->modify->bytes_dirty, size); } @@ -271,19 +317,15 @@ __wt_cache_dirty_decr(WT_SESSION_IMPL *session, WT_PAGE *page) { WT_CACHE *cache; WT_PAGE_MODIFY *modify; - uint64_t *pages_dirty; cache = S2C(session)->cache; - pages_dirty = WT_PAGE_IS_INTERNAL(page) ? - &cache->pages_dirty_intl : &cache->pages_dirty_leaf; - if (*pages_dirty < 1) { - __wt_errx(session, - "cache eviction dirty-page decrement failed: dirty page" - "count went negative"); - *pages_dirty = 0; - } else - (void)__wt_atomic_sub64(pages_dirty, 1); + if (WT_PAGE_IS_INTERNAL(page)) + __wt_cache_decr_zero_uint64(session, + &cache->pages_dirty_intl, 1, "dirty internal page count"); + else + __wt_cache_decr_zero_uint64(session, + &cache->pages_dirty_leaf, 1, "dirty leaf page count"); modify = page->modify; if (modify != NULL && modify->bytes_dirty != 0) @@ -326,16 +368,12 @@ __wt_cache_page_image_incr(WT_SESSION_IMPL *session, uint32_t size) static inline void __wt_cache_page_evict(WT_SESSION_IMPL *session, WT_PAGE *page) { + WT_BTREE *btree; WT_CACHE *cache; WT_PAGE_MODIFY *modify; - uint64_t *dest; - const char *destname; + btree = S2BT(session); cache = S2C(session)->cache; - dest = WT_PAGE_IS_INTERNAL(page) ? - &cache->bytes_dirty_intl : &cache->bytes_dirty_leaf; - destname = WT_PAGE_IS_INTERNAL(page) ? - "WT_CACHE.bytes_dirty_intl" : "WT_CACHE.bytes_dirty_leaf"; modify = page->modify; /* Update the bytes in-memory to reflect the eviction. */ @@ -352,14 +390,18 @@ __wt_cache_page_evict(WT_SESSION_IMPL *session, WT_PAGE *page) /* Update the cache's dirty-byte count. */ if (modify != NULL && modify->bytes_dirty != 0) { - if ((size_t)*dest < modify->bytes_dirty) { - __wt_errx(session, - "%s decrement failed: " - "dirty byte count went negative", destname); - *dest = 0; - } else - __wt_cache_decr_check_uint64(session, dest, - modify->bytes_dirty, destname); + if (WT_PAGE_IS_INTERNAL(page)) + __wt_cache_decr_zero_uint64(session, + &cache->bytes_dirty_intl, + modify->bytes_dirty, "WT_CACHE.bytes_dirty_intl"); + else { + __wt_cache_decr_zero_uint64(session, + &cache->bytes_dirty_leaf, + modify->bytes_dirty, "WT_CACHE.bytes_dirty_leaf"); + __wt_cache_decr_zero_uint64(session, + &btree->bytes_dirty_leaf, + modify->bytes_dirty, "WT_BTREE.bytes_dirty_leaf"); + } } /* Update pages and bytes evicted. */ @@ -1190,7 +1232,7 @@ __wt_page_can_evict( * previous version might be referenced by an internal page already * been written in the checkpoint, leaving the checkpoint inconsistent. */ - if (btree->checkpointing != WT_CKPT_OFF && modified) { + if (modified && btree->checkpointing != WT_CKPT_OFF) { WT_STAT_FAST_CONN_INCR(session, cache_eviction_checkpoint); WT_STAT_FAST_DATA_INCR(session, cache_eviction_checkpoint); return (false); @@ -1217,20 +1259,12 @@ __wt_page_can_evict( F_ISSET_ATOMIC(page, WT_PAGE_SPLIT_BLOCK)) return (false); - /* If the cache is stuck, try anything else. */ - if (F_ISSET(S2C(session)->cache, WT_CACHE_STUCK)) - return (true); - /* - * If the oldest transaction hasn't changed since the last time - * this page was written, it's unlikely we can make progress. - * Similarly, if the most recent update on the page is not yet - * globally visible, eviction will fail. These heuristics - * attempt to avoid repeated attempts to evict the same page. + * If the page is clean but has modifications that + * appear too new to evict, skip it. */ - if (modified && - (mod->last_oldest_id == __wt_txn_oldest_id(session) || - !__wt_txn_visible_all(session, mod->update_txn))) + if (!modified && mod != NULL && + !__wt_txn_visible_all(session, mod->rec_max_txn)) return (false); return (true); |