diff options
Diffstat (limited to 'storage/innobase/include/buf0buf.h')
-rw-r--r-- | storage/innobase/include/buf0buf.h | 304 |
1 files changed, 213 insertions, 91 deletions
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index fd8620eab3b..2284f21e3ab 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -36,6 +36,7 @@ Created 11/5/1995 Heikki Tuuri #ifndef UNIV_HOTBACKUP #include "ut0rbt.h" #include "os0proc.h" +#include "log0log.h" /** @name Modes for buf_page_get_gen */ /* @{ */ @@ -68,14 +69,18 @@ Created 11/5/1995 Heikki Tuuri position of the block. */ /* @} */ -#define MAX_BUFFER_POOLS_BITS 6 /*!< Number of bits to representing +#define MAX_BUFFER_POOLS_BITS 6 /*!< Number of bits to representing a buffer pool ID */ -#define MAX_BUFFER_POOLS (1 << MAX_BUFFER_POOLS_BITS) + +#define MAX_BUFFER_POOLS (1 << MAX_BUFFER_POOLS_BITS) /*!< The maximum number of buffer pools that can be defined */ -#define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent +#define BUF_POOL_WATCH_SIZE (srv_n_purge_threads + 1) + /*!< Maximum number of concurrent buffer pool watches */ +#define MAX_PAGE_HASH_LOCKS 1024 /*!< The maximum number of + page_hash locks */ extern buf_pool_t* buf_pool_ptr; /*!< The buffer pools of the database */ @@ -140,10 +145,12 @@ struct buf_pool_info_struct{ ulint n_pend_reads; /*!< buf_pool->n_pend_reads, pages pending read */ ulint n_pending_flush_lru; /*!< Pages pending flush in LRU */ + ulint n_pending_flush_single_page;/*!< Pages pending to be + flushed as part of single page + flushes issued by various user + threads */ ulint n_pending_flush_list; /*!< Pages pending flush in FLUSH LIST */ - ulint n_pending_flush_single_page;/*!< Pages pending flush in - BUF_FLUSH_SINGLE_PAGE list */ ulint n_pages_made_young; /*!< number of pages made young */ ulint n_pages_not_made_young; /*!< number of pages not made young */ ulint n_pages_read; /*!< buf_pool->n_pages_read */ @@ -270,9 +277,10 @@ Gets the smallest oldest_modification lsn for any page in the pool. Returns zero if all modified pages have been flushed to disk. @return oldest modification in pool, zero if none */ UNIV_INTERN -ib_uint64_t +lsn_t buf_pool_get_oldest_modification(void); /*==================================*/ + /********************************************************************//** Allocates a buf_page_t descriptor. This function must succeed. In case of failure we assert in this function. */ @@ -344,8 +352,7 @@ buf_page_optimistic_get( /*====================*/ ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */ buf_block_t* block, /*!< in: guessed block */ - ib_uint64_t modify_clock,/*!< in: modify clock value if mode is - ..._GUESS_ON_CLOCK */ + ib_uint64_t modify_clock,/*!< in: modify clock value */ const char* file, /*!< in: file name */ ulint line, /*!< in: line where called */ mtr_t* mtr); /*!< in: mini-transaction */ @@ -367,7 +374,7 @@ buf_page_get_known_nowait( /*******************************************************************//** Given a tablespace id and page number tries to get that page. If the page is not in the buffer pool it is not loaded and NULL is returned. -Suitable for using when holding the kernel mutex. */ +Suitable for using when holding the lock_sys_t::mutex. */ UNIV_INTERN const buf_block_t* buf_page_try_get_func( @@ -379,7 +386,7 @@ buf_page_try_get_func( mtr_t* mtr); /*!< in: mini-transaction */ /** Tries to get a page. If the page is not in the buffer pool it is -not loaded. Suitable for using when holding the kernel mutex. +not loaded. Suitable for using when holding the lock_sys_t::mutex. @param space_id in: tablespace id @param page_no in: page number @param mtr in: mini-transaction @@ -492,15 +499,6 @@ buf_page_peek( /*==========*/ ulint space, /*!< in: space id */ ulint offset);/*!< in: page number */ -/********************************************************************//** -Resets the check_index_page_at_flush field of a page if found in the buffer -pool. */ -UNIV_INTERN -void -buf_reset_check_index_page_at_flush( -/*================================*/ - ulint space, /*!< in: space id */ - ulint offset);/*!< in: page number */ #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG /********************************************************************//** Sets file_page_was_freed TRUE if the page is found in the buffer pool. @@ -573,7 +571,7 @@ 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 @@ -625,29 +623,6 @@ buf_block_buf_fix_inc_func( # define buf_block_modify_clock_inc(block) ((void) 0) #endif /* !UNIV_HOTBACKUP */ /********************************************************************//** -Calculates a page checksum which is stored to the page when it is written -to a file. Note that we must be careful to calculate the same value -on 32-bit and 64-bit architectures. -@return checksum */ -UNIV_INTERN -ulint -buf_calc_page_new_checksum( -/*=======================*/ - const byte* page); /*!< in: buffer page */ -/********************************************************************//** -In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only -looked at the first few bytes of the page. This calculates that old -checksum. -NOTE: we must first store the new formula checksum to -FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum -because this takes that field as an input! -@return checksum */ -UNIV_INTERN -ulint -buf_calc_page_old_checksum( -/*=======================*/ - const byte* page); /*!< in: buffer page */ -/********************************************************************//** Checks if a page is corrupt. @return TRUE if corrupted */ UNIV_INTERN @@ -690,6 +665,17 @@ buf_pool_contains_zip( buf_pool_t* buf_pool, /*!< in: buffer pool instance */ const void* data); /*!< in: pointer to compressed page */ #endif /* UNIV_DEBUG */ + +/*********************************************************************** +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 */ + + #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /*********************************************************************//** Validates the buffer pool data structure. @@ -727,7 +713,7 @@ buf_page_print( ulint flags) /*!< in: 0 or BUF_PAGE_PRINT_NO_CRASH or BUF_PAGE_PRINT_NO_FULL */ - __attribute__((nonnull)); + UNIV_COLD __attribute__((nonnull)); /********************************************************************//** Decompress a block. @return TRUE if successful */ @@ -748,12 +734,12 @@ buf_get_latched_pages_number(void); /*==============================*/ #endif /* UNIV_DEBUG */ /*********************************************************************//** -Returns the number of pending buf pool ios. -@return number of pending I/O operations */ +Returns the number of pending buf pool read ios. +@return number of pending read I/O operations */ UNIV_INTERN ulint -buf_get_n_pending_ios(void); -/*=======================*/ +buf_get_n_pending_read_ios(void); +/*============================*/ /*********************************************************************//** Prints info of the buffer i/o. */ UNIV_INTERN @@ -807,8 +793,8 @@ pool. @return number of pending i/o operations */ UNIV_INTERN ulint -buf_pool_check_num_pending_io(void); -/*===============================*/ +buf_pool_check_no_pending_io(void); +/*==============================*/ /*********************************************************************//** Invalidates the file pages in the buffer pool when an archive recovery is completed. All the file pages buffered must be in a replaceable state when @@ -1110,7 +1096,7 @@ buf_block_get_zip_size( Gets the compressed page descriptor corresponding to an uncompressed page if applicable. */ #define buf_block_get_page_zip(block) \ - (UNIV_LIKELY_NULL((block)->page.zip.data) ? &(block)->page.zip : NULL) + ((block)->page.zip.data ? &(block)->page.zip : NULL) #ifndef UNIV_HOTBACKUP /*******************************************************************//** Gets the block to whose frame the pointer is pointing to. @@ -1245,35 +1231,83 @@ 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) */ /******************************************************************//** 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 */ /******************************************************************//** -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 */ +/* There are four different ways we can try to get a bpage or block +from the page hash: +1) Caller already holds the appropriate page hash lock: in the case call +buf_page_hash_get_low() function. +2) Caller wants to hold page hash lock in x-mode +3) Caller wants to hold page hash lock in s-mode +4) Caller doesn't want to hold page hash lock */ +#define buf_page_hash_get_s_locked(b, s, o, l) \ + buf_page_hash_get_locked(b, s, o, l, RW_LOCK_SHARED) +#define buf_page_hash_get_x_locked(b, s, o, l) \ + buf_page_hash_get_locked(b, s, o, l, RW_LOCK_EX) +#define buf_page_hash_get(b, s, o) \ + buf_page_hash_get_locked(b, s, o, NULL, 0) + +#define buf_block_hash_get_s_locked(b, s, o, l) \ + buf_block_hash_get_locked(b, s, o, l, RW_LOCK_SHARED) +#define buf_block_hash_get_x_locked(b, s, o, l) \ + buf_block_hash_get_locked(b, s, o, l, RW_LOCK_EX) +#define buf_block_hash_get(b, s, o) \ + buf_block_hash_get_locked(b, s, o, NULL, 0) + /*********************************************************************//** Gets the current length of the free list of buffer blocks. @return length of the free list */ @@ -1380,7 +1414,16 @@ struct buf_page_struct{ BUF_BLOCK_READY_FOR_USE to BUF_BLOCK_MEMORY need not be protected by buf_page_get_mutex(). - @see enum buf_page_state */ + @see enum buf_page_state. + State changes that are relevant + to page_hash are additionally + protected by the appropriate + page_hash mutex i.e.: if a page + is in page_hash or is being + added to/removed from page_hash + then the corresponding changes + must also be protected by + page_hash mutex. */ #ifndef UNIV_HOTBACKUP unsigned flush_type:2; /*!< if this block is currently being flushed to disk, this tells the @@ -1462,13 +1505,13 @@ struct buf_page_struct{ should hold: in_free_list == (state == BUF_BLOCK_NOT_USED) */ #endif /* UNIV_DEBUG */ - ib_uint64_t newest_modification; + lsn_t newest_modification; /*!< log sequence number of the youngest modification to this block, zero if not modified. Protected by block mutex */ - ib_uint64_t oldest_modification; + lsn_t oldest_modification; /*!< log sequence number of the START of the log entry written of the oldest @@ -1510,8 +1553,10 @@ struct buf_page_struct{ /* @} */ # if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG ibool file_page_was_freed; - /*!< this is set to TRUE when fsp - frees a page in buffer pool */ + /*!< this is set to TRUE when + fsp frees a page in buffer pool; + protected by buf_pool->zip_mutex + or buf_block_struct::mutex. */ # endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ }; @@ -1605,7 +1650,7 @@ struct buf_block_struct{ - we know that buf_block_struct::buf_fix_count == 0. An exception to this is when we init or create a page - in the buffer pool in buf0buf.c. + in the buffer pool in buf0buf.cc. Another exception is that assigning block->index = NULL is allowed whenever holding an x-latch on btr_search_latch. */ @@ -1731,7 +1776,14 @@ struct buf_pool_struct{ hash_table_t* page_hash; /*!< hash table of buf_page_t or buf_block_t file pages, buf_page_in_file() == TRUE, - indexed by (space_id, offset) */ + indexed by (space_id, offset). + page_hash is protected by an + array of mutexes. + Changes in page_hash are protected + by buf_pool->mutex and the relevant + page_hash mutex. Lookups can happen + while holding the buf_pool->mutex or + the relevant page_hash mutex. */ hash_table_t* zip_hash; /*!< hash table of buf_block_t blocks whose frames are allocated to the zip buddy system, @@ -1743,7 +1795,7 @@ struct buf_pool_struct{ time_t last_printout_time; /*!< when buf_print_io was last time called */ - buf_buddy_stat_t buddy_stat[BUF_BUDDY_SIZES + 1]; + buf_buddy_stat_t buddy_stat[BUF_BUDDY_SIZES_MAX + 1]; /*!< Statistics of buddy system, indexed by block size */ buf_pool_stat_t stat; /*!< current statistics */ @@ -1798,10 +1850,16 @@ struct buf_pool_struct{ to read this for heuristic purposes without holding any mutex or latch */ - ulint LRU_flush_ended;/*!< when an LRU flush ends for a page, - this is incremented by one; this is - set to zero when a buffer block is - allocated */ + ibool try_LRU_scan; /*!< Set to FALSE when an LRU + scan for free block fails. This + flag is used to avoid repeated + scans of LRU list when we know + that there is no free block + available in the scan depth for + eviction. Set to TRUE whenever + we flush a batch from the + buffer pool. Protected by the + buf_pool->mutex */ /* @} */ /** @name LRU replacement algorithm fields */ @@ -1822,7 +1880,7 @@ struct buf_pool_struct{ ulint LRU_old_len; /*!< length of the LRU list from the block to which LRU_old points onward, including that block; - see buf0lru.c for the restrictions + see buf0lru.cc for the restrictions on this value; 0 if LRU_old == NULL; NOTE: LRU_old_len must be adjusted whenever LRU_old shrinks or grows! */ @@ -1841,19 +1899,16 @@ struct buf_pool_struct{ UT_LIST_BASE_NODE_T(buf_page_t) zip_clean; /*!< unmodified compressed pages */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES]; + UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES_MAX]; /*!< buddy free lists */ - buf_page_t watch[BUF_POOL_WATCH_SIZE]; + buf_page_t* watch; /*!< Sentinel records for buffer pool watches. Protected by - buf_pool->mutex. */ + buf_pool->mutex. */ -#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE -# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE" -#endif -#if BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE -# error "BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE" +#if BUF_BUDDY_LOW > UNIV_ZIP_SIZE_MIN +# error "BUF_BUDDY_LOW > UNIV_ZIP_SIZE_MIN" #endif /* @} */ }; @@ -1884,6 +1939,47 @@ Use these instead of accessing buf_pool->mutex directly. */ +/** Get appropriate page_hash_lock. */ +# define buf_page_hash_lock_get(b, f) \ + hash_get_lock(b->page_hash, f) + +#ifdef UNIV_SYNC_DEBUG +/** Test if page_hash lock is held in s-mode. */ +# define buf_page_hash_lock_held_s(b, p) \ + rw_lock_own(buf_page_hash_lock_get(b, \ + buf_page_address_fold(p->space, \ + p->offset)), \ + RW_LOCK_SHARED) + +/** Test if page_hash lock is held in x-mode. */ +# define buf_page_hash_lock_held_x(b, p) \ + rw_lock_own(buf_page_hash_lock_get(b, \ + buf_page_address_fold(p->space, \ + p->offset)), \ + RW_LOCK_EX) + +/** Test if page_hash lock is held in x or s-mode. */ +# define buf_page_hash_lock_held_s_or_x(b, p) \ + (buf_page_hash_lock_held_s(b, p) \ + || buf_page_hash_lock_held_x(b, p)) + +# define buf_block_hash_lock_held_s(b, p) \ + buf_page_hash_lock_held_s(b, &(p->page)) + +# define buf_block_hash_lock_held_x(b, p) \ + buf_page_hash_lock_held_x(b, &(p->page)) + +# define buf_block_hash_lock_held_s_or_x(b, p) \ + buf_page_hash_lock_held_s_or_x(b, &(p->page)) +#else /* UNIV_SYNC_DEBUG */ +# define buf_page_hash_lock_held_s(b, p) (TRUE) +# define buf_page_hash_lock_held_x(b, p) (TRUE) +# define buf_page_hash_lock_held_s_or_x(b, p) (TRUE) +# define buf_block_hash_lock_held_s(b, p) (TRUE) +# define buf_block_hash_lock_held_x(b, p) (TRUE) +# define buf_block_hash_lock_held_s_or_x(b, p) (TRUE) +#endif /* UNIV_SYNC_DEBUG */ + #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /** Forbid the release of the buffer pool mutex. */ # define buf_pool_mutex_exit_forbid(b) do { \ @@ -1956,6 +2052,32 @@ FILE_PAGE => NOT_USED NOTE: This transition is allowed if and only if (3) io_fix == 0. */ +#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +/** Functor to validate the LRU list. */ +struct CheckInLRUList { + void operator()(const buf_page_t* elem) const + { + ut_a(elem->in_LRU_list); + } +}; + +/** Functor to validate the LRU list. */ +struct CheckInFreeList { + void operator()(const buf_page_t* elem) const + { + ut_a(elem->in_free_list); + } +}; + +struct CheckUnzipLRUAndLRUList { + void operator()(const buf_block_t* elem) const + { + ut_a(elem->page.in_LRU_list); + ut_a(elem->in_unzip_LRU_list); + } +}; +#endif /* UNIV_DEBUG || defined UNIV_BUF_DEBUG */ + #ifndef UNIV_NONINL #include "buf0buf.ic" #endif |