diff options
Diffstat (limited to 'storage/innobase/include/buf0buf.ic')
-rw-r--r-- | storage/innobase/include/buf0buf.ic | 242 |
1 files changed, 193 insertions, 49 deletions
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index 917ee5dda84..88c29ab5603 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -35,6 +35,16 @@ Created 11/5/1995 Heikki Tuuri #include "buf0lru.h" #include "buf0rea.h" +#ifndef UNIV_HOTBACKUP +/** A chunk of buffers. The buffer pool is allocated in chunks. */ +struct buf_chunk_struct{ + ulint mem_size; /*!< allocated size of the chunk */ + ulint size; /*!< size of frames[] and blocks[] */ + void* mem; /*!< pointer to the memory area which + was allocated for the frames */ + buf_block_t* blocks; /*!< array of buffer control blocks */ +}; + /*********************************************************************//** Gets the current size of buffer buf_pool in bytes. @return size in bytes */ @@ -160,7 +170,7 @@ buf_page_peek_if_too_old( { buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - if (UNIV_UNLIKELY(buf_pool->freed_page_clock == 0)) { + if (buf_pool->freed_page_clock == 0) { /* If eviction has not started yet, do not update the statistics or move blocks in the LRU list. This is either the warm-up phase or an in-memory workload. */ @@ -180,6 +190,7 @@ buf_page_peek_if_too_old( return(!buf_page_peek_if_young(bpage)); } } +#endif /* !UNIV_HOTBACKUP */ /*********************************************************************//** Gets the state of a block. @@ -361,11 +372,11 @@ buf_page_get_flush_type( #ifdef UNIV_DEBUG switch (flush_type) { case BUF_FLUSH_LRU: - case BUF_FLUSH_SINGLE_PAGE: case BUF_FLUSH_LIST: + case BUF_FLUSH_SINGLE_PAGE: return(flush_type); case BUF_FLUSH_N_TYPES: - break; + ut_error; } ut_error; #endif /* UNIV_DEBUG */ @@ -628,7 +639,7 @@ buf_page_get_block( /*===============*/ buf_page_t* bpage) /*!< in: control block, or NULL */ { - if (UNIV_LIKELY(bpage != NULL)) { + if (bpage != NULL) { ut_ad(buf_page_in_file(bpage)); if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { @@ -719,6 +730,23 @@ buf_page_get_page_no( return(bpage->offset); } +/*********************************************************************** +FIXME_FTS Gets the frame the pointer is pointing to. */ +UNIV_INLINE +buf_frame_t* +buf_frame_align( +/*============*/ + /* out: pointer to frame */ + byte* ptr) /* in: pointer to a frame */ +{ + buf_frame_t* frame; + + ut_ad(ptr); + + frame = (buf_frame_t*) ut_align_down(ptr, UNIV_PAGE_SIZE); + + return(frame); +} /*********************************************************************//** Gets the page number of a block. @@ -744,7 +772,8 @@ buf_page_get_zip_size( /*==================*/ const buf_page_t* bpage) /*!< in: pointer to the control block */ { - return(bpage->zip.ssize ? 512 << bpage->zip.ssize : 0); + return(bpage->zip.ssize + ? (UNIV_ZIP_SIZE_MIN >> 1) << bpage->zip.ssize : 0); } /*********************************************************************//** @@ -756,7 +785,8 @@ buf_block_get_zip_size( /*===================*/ const buf_block_t* block) /*!< in: pointer to the control block */ { - return(block->page.zip.ssize ? 512 << block->page.zip.ssize : 0); + return(block->page.zip.ssize + ? (UNIV_ZIP_SIZE_MIN >> 1) << block->page.zip.ssize : 0); } #ifndef UNIV_HOTBACKUP @@ -852,7 +882,7 @@ buf_block_free( /*===========*/ buf_block_t* block) /*!< in, own: block to be freed */ { - buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*)block); + buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*) block); buf_pool_mutex_enter(buf_pool); @@ -905,13 +935,13 @@ Gets the youngest modification log sequence number for a frame. Returns zero if not file page or no modification occurred yet. @return newest modification to page */ UNIV_INLINE -ib_uint64_t +lsn_t buf_page_get_newest_modification( /*=============================*/ const buf_page_t* bpage) /*!< in: block containing the page frame */ { - ib_uint64_t lsn; + lsn_t lsn; mutex_t* block_mutex = buf_page_get_mutex(bpage); mutex_enter(block_mutex); @@ -938,7 +968,7 @@ buf_block_modify_clock_inc( buf_block_t* block) /*!< in: block */ { #ifdef UNIV_SYNC_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*)block); + buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*) block); ut_ad((buf_pool_mutex_own(buf_pool) && (block->page.buf_fix_count == 0)) @@ -1047,18 +1077,24 @@ UNIV_INLINE buf_page_t* buf_page_hash_get_low( /*==================*/ - buf_pool_t* buf_pool, /*!< buffer pool instance */ - ulint space, /*!< in: space id */ - ulint offset, /*!< in: offset of the page - within space */ - ulint fold) /*!< in: buf_page_address_fold( - space, offset) */ + buf_pool_t* buf_pool,/*!< buffer pool instance */ + ulint space, /*!< in: space id */ + ulint offset, /*!< in: offset of the page within space */ + ulint fold) /*!< in: buf_page_address_fold(space, offset) */ { buf_page_t* bpage; - ut_ad(buf_pool); - ut_ad(buf_pool_mutex_own(buf_pool)); - ut_ad(fold == buf_page_address_fold(space, offset)); +#ifdef UNIV_SYNC_DEBUG + ulint hash_fold; + rw_lock_t* hash_lock; + + hash_fold = buf_page_address_fold(space, offset); + ut_ad(hash_fold == fold); + + hash_lock = hash_get_lock(buf_pool->page_hash, fold); + ut_ad(rw_lock_own(hash_lock, RW_LOCK_EX) + || rw_lock_own(hash_lock, RW_LOCK_SHARED)); +#endif /* UNIV_SYNC_DEBUG */ /* Look for the page in the hash table */ @@ -1083,46 +1119,145 @@ buf_page_hash_get_low( /******************************************************************//** Returns the control block of a file page, NULL if not found. -@return block, NULL if not found or not a real control block */ +If the block is found and lock is not NULL then the appropriate +page_hash lock is acquired in the specified lock mode. Otherwise, +mode value is ignored. It is up to the caller to release the +lock. If the block is found and the lock is NULL then the page_hash +lock is released by this function. +@return block, NULL if not found */ UNIV_INLINE buf_page_t* -buf_page_hash_get( -/*==============*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ +buf_page_hash_get_locked( +/*=====================*/ + /*!< out: pointer to the bpage, + or NULL; if NULL, hash_lock + is also NULL. */ + buf_pool_t* buf_pool, /*!< buffer pool instance */ ulint space, /*!< in: space id */ - ulint offset) /*!< in: offset of the page - within space */ + ulint offset, /*!< in: page number */ + rw_lock_t** lock, /*!< in/out: lock of the page + hash acquired if bpage is + found. NULL otherwise. If NULL + is passed then the hash_lock + is released by this function */ + ulint lock_mode) /*!< in: RW_LOCK_EX or + RW_LOCK_SHARED. Ignored if + lock == NULL */ { - buf_page_t* bpage; - ulint fold = buf_page_address_fold(space, offset); + buf_page_t* bpage = NULL; + ulint fold; + rw_lock_t* hash_lock; + ulint mode = RW_LOCK_SHARED; + + if (lock != NULL) { + *lock = NULL; + ut_ad(lock_mode == RW_LOCK_EX + || lock_mode == RW_LOCK_SHARED); + mode = lock_mode; + } + + fold = buf_page_address_fold(space, offset); + hash_lock = hash_get_lock(buf_pool->page_hash, fold); + +#ifdef UNIV_SYNC_DEBUG + ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX) + && !rw_lock_own(hash_lock, RW_LOCK_SHARED)); +#endif /* UNIV_SYNC_DEBUG */ + + if (mode == RW_LOCK_SHARED) { + rw_lock_s_lock(hash_lock); + } else { + rw_lock_x_lock(hash_lock); + } - bpage = buf_page_hash_get_low(buf_pool, space, offset, fold); + bpage = buf_page_hash_get_low(buf_pool, space, offset, fold); - if (bpage && buf_pool_watch_is_sentinel(buf_pool, bpage)) { + if (!bpage || buf_pool_watch_is_sentinel(buf_pool, bpage)) { bpage = NULL; + goto unlock_and_exit; } + ut_ad(buf_page_in_file(bpage)); + ut_ad(offset == bpage->offset); + ut_ad(space == bpage->space); + + if (lock == NULL) { + /* The caller wants us to release the page_hash lock */ + goto unlock_and_exit; + } else { + /* To be released by the caller */ + *lock = hash_lock; + goto exit; + } + +unlock_and_exit: + if (mode == RW_LOCK_SHARED) { + rw_lock_s_unlock(hash_lock); + } else { + rw_lock_x_unlock(hash_lock); + } +exit: return(bpage); } /******************************************************************//** -Returns the control block of a file page, NULL if not found -or an uncompressed page frame does not exist. +Returns the control block of a file page, NULL if not found. +If the block is found and lock is not NULL then the appropriate +page_hash lock is acquired in the specified lock mode. Otherwise, +mode value is ignored. It is up to the caller to release the +lock. If the block is found and the lock is NULL then the page_hash +lock is released by this function. @return block, NULL if not found */ UNIV_INLINE buf_block_t* -buf_block_hash_get( -/*===============*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ +buf_block_hash_get_locked( +/*=====================*/ + /*!< out: pointer to the bpage, + or NULL; if NULL, hash_lock + is also NULL. */ + buf_pool_t* buf_pool, /*!< buffer pool instance */ ulint space, /*!< in: space id */ - ulint offset) /*!< in: offset of the page - within space */ + ulint offset, /*!< in: page number */ + rw_lock_t** lock, /*!< in/out: lock of the page + hash acquired if bpage is + found. NULL otherwise. If NULL + is passed then the hash_lock + is released by this function */ + ulint lock_mode) /*!< in: RW_LOCK_EX or + RW_LOCK_SHARED. Ignored if + lock == NULL */ { - buf_block_t* block; + buf_page_t* bpage = buf_page_hash_get_locked(buf_pool, + space, + offset, + lock, + lock_mode); + buf_block_t* block = buf_page_get_block(bpage); + + if (block) { + ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); +#ifdef UNIV_SYNC_DEBUG + ut_ad(!lock || rw_lock_own(*lock, lock_mode)); +#endif /* UNIV_SYNC_DEBUG */ + return(block); + } else if (bpage) { + /* It is not a block. Just a bpage */ + ut_ad(buf_page_in_file(bpage)); - block = buf_page_get_block(buf_page_hash_get(buf_pool, space, offset)); + if (lock) { + if (lock_mode == RW_LOCK_SHARED) { + rw_lock_s_unlock(*lock); + } else { + rw_lock_x_unlock(*lock); + } + } + *lock = NULL; + return(NULL); + } - return(block); + ut_ad(!bpage); + ut_ad(lock == NULL ||*lock == NULL); + return(NULL); } /********************************************************************//** @@ -1139,16 +1274,9 @@ buf_page_peek( ulint space, /*!< in: space id */ ulint offset) /*!< in: page number */ { - const buf_page_t* bpage; buf_pool_t* buf_pool = buf_pool_get(space, offset); - buf_pool_mutex_enter(buf_pool); - - bpage = buf_page_hash_get(buf_pool, space, offset); - - buf_pool_mutex_exit(buf_pool); - - return(bpage != NULL); + return(buf_page_hash_get(buf_pool, space, offset) != NULL); } /********************************************************************//** @@ -1189,7 +1317,6 @@ buf_page_release_zip( break; } - ut_error; } @@ -1274,4 +1401,21 @@ buf_pool_mutex_exit_all(void) buf_pool_mutex_exit(buf_pool); } } +/*********************************************************************//** +Get the nth chunk's buffer block in the specified buffer pool. +@return the nth chunk's buffer block. */ +UNIV_INLINE +buf_block_t* +buf_get_nth_chunk_block( +/*====================*/ + const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ + ulint n, /*!< in: nth chunk in the buffer pool */ + ulint* chunk_size) /*!< in: chunk size */ +{ + const buf_chunk_t* chunk; + + chunk = buf_pool->chunks + n; + *chunk_size = chunk->size; + return(chunk->blocks); +} #endif /* !UNIV_HOTBACKUP */ |