@ -129,25 +129,31 @@ static
void
buf_LRU_block_free_hashed_page (
/*===========================*/
buf_block_t * block ) ; /* in: block, must contain a file page and
buf_block_t * block , /* in: block, must contain a file page and
be in a state where it can be freed */
ibool have_page_hash_mutex ) ;
/**********************************************************************
Determines if the unzip_LRU list should be used for evicting a victim
instead of the general LRU list . */
UNIV_INLINE
ibool
buf_LRU_evict_from_unzip_LRU ( void )
buf_LRU_evict_from_unzip_LRU (
ibool have_LRU_mutex )
/*==============================*/
/* out: TRUE if should use unzip_LRU */
{
ulint io_avg ;
ulint unzip_avg ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
if ( ! have_LRU_mutex )
mutex_enter ( & LRU_list_mutex ) ;
/* If the unzip_LRU list is empty, we can only use the LRU. */
if ( UT_LIST_GET_LEN ( buf_pool - > unzip_LRU ) = = 0 ) {
if ( ! have_LRU_mutex )
mutex_exit ( & LRU_list_mutex ) ;
return ( FALSE ) ;
}
@ -156,14 +162,20 @@ buf_LRU_evict_from_unzip_LRU(void)
decompressed pages in the buffer pool . */
if ( UT_LIST_GET_LEN ( buf_pool - > unzip_LRU )
< = UT_LIST_GET_LEN ( buf_pool - > LRU ) / 10 ) {
if ( ! have_LRU_mutex )
mutex_exit ( & LRU_list_mutex ) ;
return ( FALSE ) ;
}
/* If eviction hasn't started yet, we assume by default
that a workload is disk bound . */
if ( buf_pool - > freed_page_clock = = 0 ) {
if ( ! have_LRU_mutex )
mutex_exit ( & LRU_list_mutex ) ;
return ( TRUE ) ;
}
if ( ! have_LRU_mutex )
mutex_exit ( & LRU_list_mutex ) ;
/* Calculate the average over past intervals, and add the values
of the current interval . */
@ -229,7 +241,8 @@ buf_LRU_drop_page_hash_for_tablespace(
page_arr = ut_malloc ( sizeof ( ulint )
* BUF_LRU_DROP_SEARCH_HASH_SIZE ) ;
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & LRU_list_mutex ) ;
scan_again :
num_entries = 0 ;
@ -239,7 +252,13 @@ scan_again:
mutex_t * block_mutex = buf_page_get_mutex ( bpage ) ;
buf_page_t * prev_bpage ;
retry_lock :
mutex_enter ( block_mutex ) ;
if ( block_mutex ! = buf_page_get_mutex ( bpage ) ) {
mutex_exit ( block_mutex ) ;
block_mutex = buf_page_get_mutex ( bpage ) ;
goto retry_lock ;
}
prev_bpage = UT_LIST_GET_PREV ( LRU , bpage ) ;
ut_a ( buf_page_in_file ( bpage ) ) ;
@ -269,12 +288,14 @@ scan_again:
}
/* Array full. We release the buf_pool_mutex to
obey the latching order . */
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
buf_LRU_drop_page_hash_batch ( id , zip_size , page_arr ,
num_entries ) ;
num_entries = 0 ;
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & LRU_list_mutex ) ;
} else {
mutex_exit ( block_mutex ) ;
}
@ -299,7 +320,8 @@ next_page:
}
}
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
/* Drop any remaining batch of search hashed pages. */
buf_LRU_drop_page_hash_batch ( id , zip_size , page_arr , num_entries ) ;
@ -327,7 +349,9 @@ buf_LRU_invalidate_tablespace(
buf_LRU_drop_page_hash_for_tablespace ( id ) ;
scan_again :
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & LRU_list_mutex ) ;
rw_lock_x_lock ( & page_hash_latch ) ;
all_freed = TRUE ;
@ -339,7 +363,13 @@ scan_again:
ut_a ( buf_page_in_file ( bpage ) ) ;
retry_lock :
mutex_enter ( block_mutex ) ;
if ( block_mutex ! = buf_page_get_mutex ( bpage ) ) {
mutex_exit ( block_mutex ) ;
block_mutex = buf_page_get_mutex ( bpage ) ;
goto retry_lock ;
}
prev_bpage = UT_LIST_GET_PREV ( LRU , bpage ) ;
if ( buf_page_get_space ( bpage ) = = id ) {
@ -369,7 +399,9 @@ scan_again:
ulint page_no ;
ulint zip_size ;
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
rw_lock_x_unlock ( & page_hash_latch ) ;
zip_size = buf_page_get_zip_size ( bpage ) ;
page_no = buf_page_get_page_no ( bpage ) ;
@ -393,7 +425,7 @@ scan_again:
if ( buf_LRU_block_remove_hashed_page ( bpage , TRUE )
! = BUF_BLOCK_ZIP_FREE ) {
buf_LRU_block_free_hashed_page ( ( buf_block_t * )
bpage ) ;
bpage , TRUE ) ;
} else {
/* The block_mutex should have been
released by buf_LRU_block_remove_hashed_page ( )
@ -416,7 +448,9 @@ next_page:
bpage = prev_bpage ;
}
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
rw_lock_x_unlock ( & page_hash_latch ) ;
if ( ! all_freed ) {
os_thread_sleep ( 20000 ) ;
@ -439,14 +473,16 @@ buf_LRU_get_recent_limit(void)
ulint len ;
ulint limit ;
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & LRU_list_mutex ) ;
len = UT_LIST_GET_LEN ( buf_pool - > LRU ) ;
if ( len < BUF_LRU_OLD_MIN_LEN ) {
/* The LRU list is too short to do read-ahead */
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
return ( 0 ) ;
}
@ -455,7 +491,8 @@ buf_LRU_get_recent_limit(void)
limit = buf_page_get_LRU_position ( bpage ) - len / BUF_LRU_INITIAL_RATIO ;
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
return ( limit ) ;
}
@ -470,7 +507,9 @@ buf_LRU_insert_zip_clean(
{
buf_page_t * b ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & LRU_list_mutex ) ) ;
ut_ad ( mutex_own ( & flush_list_mutex ) ) ;
ut_ad ( buf_page_get_state ( bpage ) = = BUF_BLOCK_ZIP_PAGE ) ;
/* Find the first successor of bpage in the LRU list
@ -478,17 +517,17 @@ buf_LRU_insert_zip_clean(
b = bpage ;
do {
b = UT_LIST_GET_NEXT ( LRU , b ) ;
} while ( b & & buf_page_get_state ( b ) ! = BUF_BLOCK_ZIP_PAGE ) ;
} while ( b & & ( buf_page_get_state ( b ) ! = BUF_BLOCK_ZIP_PAGE | | ! b - > in_LRU_list ) ) ;
/* Insert bpage before b, i.e., after the predecessor of b. */
if ( b ) {
b = UT_LIST_GET_PREV ( list , b ) ;
b = UT_LIST_GET_PREV ( zip_ list, b ) ;
}
if ( b ) {
UT_LIST_INSERT_AFTER ( list , buf_pool - > zip_clean , b , bpage ) ;
UT_LIST_INSERT_AFTER ( zip_ list, buf_pool - > zip_clean , b , bpage ) ;
} else {
UT_LIST_ADD_FIRST ( list , buf_pool - > zip_clean , bpage ) ;
UT_LIST_ADD_FIRST ( zip_ list, buf_pool - > zip_clean , bpage ) ;
}
}
@ -500,16 +539,17 @@ ibool
buf_LRU_free_from_unzip_LRU_list (
/*=============================*/
/* out: TRUE if freed */
ulint n_iterations ) /* in: how many times this has been called
ulint n_iterations , /* in: how many times this has been called
repeatedly without result : a high value means
that we should search farther ; we will search
n_iterations / 5 of the unzip_LRU list ,
or nothing if n_iterations > = 5 */
ibool have_LRU_mutex )
{
buf_block_t * block ;
ulint distance ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ; /* optimistic */
/* Theoratically it should be much easier to find a victim
from unzip_LRU as we can choose even a dirty block ( as we ' ll
@ -519,7 +559,7 @@ buf_LRU_free_from_unzip_LRU_list(
if we have done five iterations so far . */
if ( UNIV_UNLIKELY ( n_iterations > = 5 )
| | ! buf_LRU_evict_from_unzip_LRU ( ) ) {
| | ! buf_LRU_evict_from_unzip_LRU ( have_LRU_mutex ) ) {
return ( FALSE ) ;
}
@ -527,18 +567,25 @@ buf_LRU_free_from_unzip_LRU_list(
distance = 100 + ( n_iterations
* UT_LIST_GET_LEN ( buf_pool - > unzip_LRU ) ) / 5 ;
restart :
for ( block = UT_LIST_GET_LAST ( buf_pool - > unzip_LRU ) ;
UNIV_LIKELY ( block ! = NULL ) & & UNIV_LIKELY ( distance > 0 ) ;
block = UT_LIST_GET_PREV ( unzip_LRU , block ) , distance - - ) {
enum buf_lru_free_block_status freed ;
mutex_enter ( & block - > mutex ) ;
if ( ! block - > in_unzip_LRU_list | | ! block - > page . in_LRU_list
| | buf_block_get_state ( block ) ! = BUF_BLOCK_FILE_PAGE ) {
mutex_exit ( & block - > mutex ) ;
goto restart ;
}
ut_ad ( buf_block_get_state ( block ) = = BUF_BLOCK_FILE_PAGE ) ;
ut_ad ( block - > in_unzip_LRU_list ) ;
ut_ad ( block - > page . in_LRU_list ) ;
mutex_enter ( & block - > mutex ) ;
freed = buf_LRU_free_block ( & block - > page , FALSE , NULL ) ;
freed = buf_LRU_free_block ( & block - > page , FALSE , NULL , have_LRU_mutex ) ;
mutex_exit ( & block - > mutex ) ;
switch ( freed ) {
@ -571,20 +618,22 @@ ibool
buf_LRU_free_from_common_LRU_list (
/*==============================*/
/* out: TRUE if freed */
ulint n_iterations ) /* in: how many times this has been called
ulint n_iterations , /* in: how many times this has been called
repeatedly without result : a high value means
that we should search farther ; if
n_iterations < 10 , then we search
n_iterations / 10 * buf_pool - > curr_size
pages from the end of the LRU list */
ibool have_LRU_mutex )
{
buf_page_t * bpage ;
ulint distance ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ; /* optimistic */
distance = 100 + ( n_iterations * buf_pool - > curr_size ) / 10 ;
restart :
for ( bpage = UT_LIST_GET_LAST ( buf_pool - > LRU ) ;
UNIV_LIKELY ( bpage ! = NULL ) & & UNIV_LIKELY ( distance > 0 ) ;
bpage = UT_LIST_GET_PREV ( LRU , bpage ) , distance - - ) {
@ -593,11 +642,25 @@ buf_LRU_free_from_common_LRU_list(
mutex_t * block_mutex
= buf_page_get_mutex ( bpage ) ;
retry_lock :
mutex_enter ( block_mutex ) ;
if ( block_mutex ! = buf_page_get_mutex ( bpage ) ) {
mutex_exit ( block_mutex ) ;
block_mutex = buf_page_get_mutex ( bpage ) ;
goto retry_lock ;
}
if ( ! bpage - > in_LRU_list
| | ! buf_page_in_file ( bpage ) ) {
mutex_exit ( block_mutex ) ;
goto restart ;
}
ut_ad ( buf_page_in_file ( bpage ) ) ;
ut_ad ( bpage - > in_LRU_list ) ;
mutex_enter ( block_mutex ) ;
freed = buf_LRU_free_block ( bpage , TRUE , NULL ) ;
freed = buf_LRU_free_block ( bpage , TRUE , NULL , have_LRU_mutex ) ;
mutex_exit ( block_mutex ) ;
switch ( freed ) {
@ -640,22 +703,33 @@ buf_LRU_search_and_free_block(
n_iterations / 5 of the unzip_LRU list . */
{
ibool freed = FALSE ;
ibool have_LRU_mutex = FALSE ;
if ( UT_LIST_GET_LEN ( buf_pool - > unzip_LRU ) )
have_LRU_mutex = TRUE ;
buf_pool_mutex_enter ( ) ;
/* optimistic search... */
/ / buf_pool_mutex_enter ( ) ;
if ( have_LRU_mutex )
mutex_enter ( & LRU_list_mutex ) ;
freed = buf_LRU_free_from_unzip_LRU_list ( n_iterations ) ;
freed = buf_LRU_free_from_unzip_LRU_list ( n_iterations , have_LRU_mutex ) ;
if ( ! freed ) {
freed = buf_LRU_free_from_common_LRU_list ( n_iterations ) ;
freed = buf_LRU_free_from_common_LRU_list ( n_iterations , have_LRU_mutex ) ;
}
mutex_enter ( & buf_pool_mutex ) ;
if ( ! freed ) {
buf_pool - > LRU_flush_ended = 0 ;
} else if ( buf_pool - > LRU_flush_ended > 0 ) {
buf_pool - > LRU_flush_ended - - ;
}
mutex_exit ( & buf_pool_mutex ) ;
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
if ( have_LRU_mutex )
mutex_exit ( & LRU_list_mutex ) ;
return ( freed ) ;
}
@ -673,18 +747,22 @@ void
buf_LRU_try_free_flushed_blocks ( void )
/*=================================*/
{
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & buf_pool_mutex ) ;
while ( buf_pool - > LRU_flush_ended > 0 ) {
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & buf_pool_mutex ) ;
buf_LRU_search_and_free_block ( 1 ) ;
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & buf_pool_mutex ) ;
}
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & buf_pool_mutex ) ;
}
/**********************************************************************
@ -700,7 +778,9 @@ buf_LRU_buf_pool_running_out(void)
{
ibool ret = FALSE ;
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & LRU_list_mutex ) ;
mutex_enter ( & free_list_mutex ) ;
if ( ! recv_recovery_on & & UT_LIST_GET_LEN ( buf_pool - > free )
+ UT_LIST_GET_LEN ( buf_pool - > LRU ) < buf_pool - > curr_size / 4 ) {
@ -708,7 +788,9 @@ buf_LRU_buf_pool_running_out(void)
ret = TRUE ;
}
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
mutex_exit ( & free_list_mutex ) ;
return ( ret ) ;
}
@ -725,9 +807,10 @@ buf_LRU_get_free_only(void)
{
buf_block_t * block ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
block = ( buf_block_t * ) UT_LIST_GET_FIRST ( buf_pool - > free ) ;
mutex_enter ( & free_list_mutex ) ;
block = ( buf_block_t * ) UT_LIST_GET_LAST ( buf_pool - > free ) ;
if ( block ) {
ut_ad ( block - > page . in_free_list ) ;
@ -735,7 +818,9 @@ buf_LRU_get_free_only(void)
ut_ad ( ! block - > page . in_flush_list ) ;
ut_ad ( ! block - > page . in_LRU_list ) ;
ut_a ( ! buf_page_in_file ( & block - > page ) ) ;
UT_LIST_REMOVE ( list , buf_pool - > free , ( & block - > page ) ) ;
UT_LIST_REMOVE ( free , buf_pool - > free , ( & block - > page ) ) ;
mutex_exit ( & free_list_mutex ) ;
mutex_enter ( & block - > mutex ) ;
@ -743,6 +828,8 @@ buf_LRU_get_free_only(void)
UNIV_MEM_ALLOC ( block - > frame , UNIV_PAGE_SIZE ) ;
mutex_exit ( & block - > mutex ) ;
} else {
mutex_exit ( & free_list_mutex ) ;
}
return ( block ) ;
@ -767,7 +854,7 @@ buf_LRU_get_free_block(
ibool mon_value_was = FALSE ;
ibool started_monitor = FALSE ;
loop :
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
if ( ! recv_recovery_on & & UT_LIST_GET_LEN ( buf_pool - > free )
+ UT_LIST_GET_LEN ( buf_pool - > LRU ) < buf_pool - > curr_size / 20 ) {
@ -847,14 +934,16 @@ loop:
if ( UNIV_UNLIKELY ( zip_size ) ) {
ibool lru ;
page_zip_set_size ( & block - > page . zip , zip_size ) ;
block - > page . zip . data = buf_buddy_alloc ( zip_size , & lru ) ;
mutex_enter ( & LRU_list_mutex ) ;
block - > page . zip . data = buf_buddy_alloc ( zip_size , & lru , FALSE ) ;
mutex_exit ( & LRU_list_mutex ) ;
UNIV_MEM_DESC ( block - > page . zip . data , zip_size , block ) ;
} else {
page_zip_set_size ( & block - > page . zip , 0 ) ;
block - > page . zip . data = NULL ;
}
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
if ( started_monitor ) {
srv_print_innodb_monitor = mon_value_was ;
@ -866,7 +955,7 @@ loop:
/* If no block was in the free list, search from the end of the LRU
list and try to free a block there */
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
freed = buf_LRU_search_and_free_block ( n_iterations ) ;
@ -915,18 +1004,21 @@ loop:
os_aio_simulated_wake_handler_threads ( ) ;
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & buf_pool_mutex ) ;
if ( buf_pool - > LRU_flush_ended > 0 ) {
/* We have written pages in an LRU flush. To make the insert
buffer more efficient , we try to move these pages to the free
list . */
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & buf_pool_mutex ) ;
buf_LRU_try_free_flushed_blocks ( ) ;
} else {
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & buf_pool_mutex ) ;
}
if ( n_iterations > 10 ) {
@ -951,7 +1043,8 @@ buf_LRU_old_adjust_len(void)
ulint new_len ;
ut_a ( buf_pool - > LRU_old ) ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & LRU_list_mutex ) ) ;
# if 3 * (BUF_LRU_OLD_MIN_LEN / 8) <= BUF_LRU_OLD_TOLERANCE + 5
# error "3 * (BUF_LRU_OLD_MIN_LEN / 8) <= BUF_LRU_OLD_TOLERANCE + 5"
# endif
@ -1009,7 +1102,8 @@ buf_LRU_old_init(void)
{
buf_page_t * bpage ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & LRU_list_mutex ) ) ;
ut_a ( UT_LIST_GET_LEN ( buf_pool - > LRU ) = = BUF_LRU_OLD_MIN_LEN ) ;
/* We first initialize all blocks in the LRU list as old and then use
@ -1041,13 +1135,14 @@ buf_unzip_LRU_remove_block_if_needed(
ut_ad ( buf_pool ) ;
ut_ad ( bpage ) ;
ut_ad ( buf_page_in_file ( bpage ) ) ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & LRU_list_mutex ) ) ;
if ( buf_page_belongs_to_unzip_LRU ( bpage ) ) {
buf_block_t * block = ( buf_block_t * ) bpage ;
ut_ad ( block - > in_unzip_LRU_list ) ;
ut_d ( block - > in_unzip_LRU_list = FALSE ) ;
block - > in_unzip_LRU_list = FALSE ;
UT_LIST_REMOVE ( unzip_LRU , buf_pool - > unzip_LRU , block ) ;
}
@ -1063,7 +1158,8 @@ buf_LRU_remove_block(
{
ut_ad ( buf_pool ) ;
ut_ad ( bpage ) ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & LRU_list_mutex ) ) ;
ut_a ( buf_page_in_file ( bpage ) ) ;
@ -1126,12 +1222,13 @@ buf_unzip_LRU_add_block(
{
ut_ad ( buf_pool ) ;
ut_ad ( block ) ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & LRU_list_mutex ) ) ;
ut_a ( buf_page_belongs_to_unzip_LRU ( & block - > page ) ) ;
ut_ad ( ! block - > in_unzip_LRU_list ) ;
ut_d ( block - > in_unzip_LRU_list = TRUE ) ;
block - > in_unzip_LRU_list = TRUE ;
if ( old ) {
UT_LIST_ADD_LAST ( unzip_LRU , buf_pool - > unzip_LRU , block ) ;
@ -1152,7 +1249,8 @@ buf_LRU_add_block_to_end_low(
ut_ad ( buf_pool ) ;
ut_ad ( bpage ) ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & LRU_list_mutex ) ) ;
ut_a ( buf_page_in_file ( bpage ) ) ;
@ -1212,7 +1310,8 @@ buf_LRU_add_block_low(
{
ut_ad ( buf_pool ) ;
ut_ad ( bpage ) ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & LRU_list_mutex ) ) ;
ut_a ( buf_page_in_file ( bpage ) ) ;
ut_ad ( ! bpage - > in_LRU_list ) ;
@ -1331,22 +1430,23 @@ buf_LRU_free_block(
buf_page_t * bpage , /* in: block to be freed */
ibool zip , /* in: TRUE if should remove also the
compressed page of an uncompressed page */
ibool * buf_pool_mutex_released )
ibool * buf_pool_mutex_released ,
/* in: pointer to a variable that will
be assigned TRUE if buf_pool_mutex
was temporarily released , or NULL */
ibool have_LRU_mutex )
{
buf_page_t * b = NULL ;
mutex_t * block_mutex = buf_page_get_mutex ( bpage ) ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( block_mutex ) ) ;
ut_ad ( buf_page_in_file ( bpage ) ) ;
ut_ad ( bpage - > in_LRU_list ) ;
/ / ut_ad ( bpage - > in_LRU_list ) ;
ut_ad ( ! bpage - > in_flush_list = = ! bpage - > oldest_modification ) ;
UNIV_MEM_ASSERT_RW ( bpage , sizeof * bpage ) ;
if ( ! buf_page_can_relocate ( bpage ) ) {
if ( ! bpage - > in_LRU_list | | ! block_mutex | | ! b uf_page_can_relocate ( bpage ) ) {
/* Do not free buffer-fixed or I/O-fixed blocks. */
return ( BUF_LRU_NOT_FREED ) ;
@ -1378,15 +1478,15 @@ buf_LRU_free_block(
If it cannot be allocated ( without freeing a block
from the LRU list ) , refuse to free bpage . */
alloc :
buf_pool_mutex_exit_forbid ( ) ;
b = buf_buddy_alloc ( sizeof * b , NULL ) ;
buf_pool_mutex_exit_allow ( ) ;
/ / buf_pool_mutex_exit_forbid ( ) ;
b = buf_buddy_alloc ( sizeof * b , NULL , FALSE ) ;
/ / buf_pool_mutex_exit_allow ( ) ;
if ( UNIV_UNLIKELY ( ! b ) ) {
return ( BUF_LRU_CANNOT_RELOCATE ) ;
}
memcpy ( b , bpage , sizeof * b ) ;
/ / memcpy ( b , bpage , sizeof * b ) ;
}
# ifdef UNIV_DEBUG
@ -1397,6 +1497,39 @@ alloc:
}
# endif /* UNIV_DEBUG */
/* not to break latch order, must re-enter block_mutex */
mutex_exit ( block_mutex ) ;
if ( ! have_LRU_mutex )
mutex_enter ( & LRU_list_mutex ) ; /* optimistic */
rw_lock_x_lock ( & page_hash_latch ) ;
mutex_enter ( block_mutex ) ;
/* recheck states of block */
if ( ! bpage - > in_LRU_list | | block_mutex ! = buf_page_get_mutex ( bpage )
| | ! buf_page_can_relocate ( bpage ) ) {
not_freed :
if ( b ) {
buf_buddy_free ( b , sizeof * b , TRUE ) ;
}
if ( ! have_LRU_mutex )
mutex_exit ( & LRU_list_mutex ) ;
rw_lock_x_unlock ( & page_hash_latch ) ;
return ( BUF_LRU_NOT_FREED ) ;
} else if ( zip | | ! bpage - > zip . data ) {
if ( bpage - > oldest_modification )
goto not_freed ;
} else if ( bpage - > oldest_modification ) {
if ( buf_page_get_state ( bpage ) ! = BUF_BLOCK_FILE_PAGE ) {
ut_ad ( buf_page_get_state ( bpage ) = = BUF_BLOCK_ZIP_DIRTY ) ;
goto not_freed ;
}
}
if ( b ) {
memcpy ( b , bpage , sizeof * b ) ;
}
if ( buf_LRU_block_remove_hashed_page ( bpage , zip )
! = BUF_BLOCK_ZIP_FREE ) {
ut_a ( bpage - > buf_fix_count = = 0 ) ;
@ -1408,6 +1541,10 @@ alloc:
ut_a ( ! buf_page_hash_get ( bpage - > space , bpage - > offset ) ) ;
while ( prev_b & & ! prev_b - > in_LRU_list ) {
prev_b = UT_LIST_GET_PREV ( LRU , prev_b ) ;
}
b - > state = b - > oldest_modification
? BUF_BLOCK_ZIP_DIRTY
: BUF_BLOCK_ZIP_PAGE ;
@ -1482,6 +1619,7 @@ alloc:
buf_LRU_add_block_low ( b , buf_page_is_old ( b ) ) ;
}
mutex_enter ( & flush_list_mutex ) ;
if ( b - > state = = BUF_BLOCK_ZIP_PAGE ) {
buf_LRU_insert_zip_clean ( b ) ;
} else {
@ -1490,22 +1628,23 @@ alloc:
ut_ad ( b - > in_flush_list ) ;
ut_d ( bpage - > in_flush_list = FALSE ) ;
prev = UT_LIST_GET_PREV ( list , b ) ;
UT_LIST_REMOVE ( list , buf_pool - > flush_list , b ) ;
prev = UT_LIST_GET_PREV ( flush_ list, b ) ;
UT_LIST_REMOVE ( flush_ list, buf_pool - > flush_list , b ) ;
if ( prev ) {
ut_ad ( prev - > in_flush_list ) ;
UT_LIST_INSERT_AFTER (
list ,
flush_ list,
buf_pool - > flush_list ,
prev , b ) ;
} else {
UT_LIST_ADD_FIRST (
list ,
flush_ list,
buf_pool - > flush_list ,
b ) ;
}
}
mutex_exit ( & flush_list_mutex ) ;
bpage - > zip . data = NULL ;
page_zip_set_size ( & bpage - > zip , 0 ) ;
@ -1521,7 +1660,9 @@ alloc:
* buf_pool_mutex_released = TRUE ;
}
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
rw_lock_x_unlock ( & page_hash_latch ) ;
mutex_exit ( block_mutex ) ;
/* Remove possible adaptive hash index on the page.
@ -1553,7 +1694,9 @@ alloc:
: BUF_NO_CHECKSUM_MAGIC ) ;
}
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
if ( have_LRU_mutex )
mutex_enter ( & LRU_list_mutex ) ;
mutex_enter ( block_mutex ) ;
if ( b ) {
@ -1563,13 +1706,17 @@ alloc:
mutex_exit ( & buf_pool_zip_mutex ) ;
}
buf_LRU_block_free_hashed_page ( ( buf_block_t * ) bpage ) ;
buf_LRU_block_free_hashed_page ( ( buf_block_t * ) bpage , FALSE ) ;
} else {
/* The block_mutex should have been released by
buf_LRU_block_remove_hashed_page ( ) when it returns
BUF_BLOCK_ZIP_FREE . */
ut_ad ( block_mutex = = & buf_pool_zip_mutex ) ;
mutex_enter ( block_mutex ) ;
if ( ! have_LRU_mutex )
mutex_exit ( & LRU_list_mutex ) ;
rw_lock_x_unlock ( & page_hash_latch ) ;
}
return ( BUF_LRU_FREED ) ;
@ -1581,12 +1728,13 @@ UNIV_INTERN
void
buf_LRU_block_free_non_file_page (
/*=============================*/
buf_block_t * block ) /* in: block, must not contain a file page */
buf_block_t * block , /* in: block, must not contain a file page */
ibool have_page_hash_mutex )
{
void * data ;
ut_ad ( block ) ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & block - > mutex ) ) ;
switch ( buf_block_get_state ( block ) ) {
@ -1620,15 +1768,17 @@ buf_LRU_block_free_non_file_page(
if ( data ) {
block - > page . zip . data = NULL ;
mutex_exit ( & block - > mutex ) ;
buf_pool_mutex_exit_forbid ( ) ;
buf_buddy_free ( data , page_zip_get_size ( & block - > page . zip ) ) ;
buf_pool_mutex_exit_allow ( ) ;
/ / buf_pool_mutex_exit_forbid ( ) ;
buf_buddy_free ( data , page_zip_get_size ( & block - > page . zip ) , have_page_hash_mutex ) ;
/ / buf_pool_mutex_exit_allow ( ) ;
mutex_enter ( & block - > mutex ) ;
page_zip_set_size ( & block - > page . zip , 0 ) ;
}
UT_LIST_ADD_FIRST ( list , buf_pool - > free , ( & block - > page ) ) ;
mutex_enter ( & free_list_mutex ) ;
UT_LIST_ADD_FIRST ( free , buf_pool - > free , ( & block - > page ) ) ;
ut_d ( block - > page . in_free_list = TRUE ) ;
mutex_exit ( & free_list_mutex ) ;
UNIV_MEM_ASSERT_AND_FREE ( block - > frame , UNIV_PAGE_SIZE ) ;
}
@ -1657,7 +1807,11 @@ buf_LRU_block_remove_hashed_page(
{
const buf_page_t * hashed_bpage ;
ut_ad ( bpage ) ;
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & LRU_list_mutex ) ) ;
# ifdef UNIV_SYNC_DEBUG
ut_ad ( rw_lock_own ( & page_hash_latch , RW_LOCK_EX ) ) ;
# endif
ut_ad ( mutex_own ( buf_page_get_mutex ( bpage ) ) ) ;
ut_a ( buf_page_get_io_fix ( bpage ) = = BUF_IO_NONE ) ;
@ -1758,7 +1912,9 @@ buf_LRU_block_remove_hashed_page(
# if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
mutex_exit ( buf_page_get_mutex ( bpage ) ) ;
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
rw_lock_x_unlock ( & page_hash_latch ) ;
buf_print ( ) ;
buf_LRU_print ( ) ;
buf_validate ( ) ;
@ -1781,14 +1937,14 @@ buf_LRU_block_remove_hashed_page(
ut_a ( bpage - > zip . data ) ;
ut_a ( buf_page_get_zip_size ( bpage ) ) ;
UT_LIST_REMOVE ( list , buf_pool - > zip_clean , bpage ) ;
UT_LIST_REMOVE ( zip_ list, buf_pool - > zip_clean , bpage ) ;
mutex_exit ( & buf_pool_zip_mutex ) ;
buf_pool_mutex_exit_forbid ( ) ;
/ / buf_pool_mutex_exit_forbid ( ) ;
buf_buddy_free ( bpage - > zip . data ,
page_zip_get_size ( & bpage - > zip ) ) ;
buf_buddy_free ( bpage , sizeof ( * bpage ) ) ;
buf_pool_mutex_exit_allow ( ) ;
page_zip_get_size ( & bpage - > zip ) , TRUE ) ;
buf_buddy_free ( bpage , sizeof ( * bpage ) , TRUE ) ;
/ / buf_pool_mutex_exit_allow ( ) ;
UNIV_MEM_UNDESC ( bpage ) ;
return ( BUF_BLOCK_ZIP_FREE ) ;
@ -1807,9 +1963,9 @@ buf_LRU_block_remove_hashed_page(
bpage - > zip . data = NULL ;
mutex_exit ( & ( ( buf_block_t * ) bpage ) - > mutex ) ;
buf_pool_mutex_exit_forbid ( ) ;
buf_buddy_free ( data , page_zip_get_size ( & bpage - > zip ) ) ;
buf_pool_mutex_exit_allow ( ) ;
/ / buf_pool_mutex_exit_forbid ( ) ;
buf_buddy_free ( data , page_zip_get_size ( & bpage - > zip ) , TRUE ) ;
/ / buf_pool_mutex_exit_allow ( ) ;
mutex_enter ( & ( ( buf_block_t * ) bpage ) - > mutex ) ;
page_zip_set_size ( & bpage - > zip , 0 ) ;
}
@ -1835,15 +1991,16 @@ static
void
buf_LRU_block_free_hashed_page (
/*===========================*/
buf_block_t * block ) /* in: block, must contain a file page and
buf_block_t * block , /* in: block, must contain a file page and
be in a state where it can be freed */
ibool have_page_hash_mutex )
{
ut_ad ( buf_pool_mutex_own ( ) ) ;
/ / ut_ad ( buf_pool_mutex_own ( ) ) ;
ut_ad ( mutex_own ( & block - > mutex ) ) ;
buf_block_set_state ( block , BUF_BLOCK_MEMORY ) ;
buf_LRU_block_free_non_file_page ( block ) ;
buf_LRU_block_free_non_file_page ( block , have_page_hash_mutex ) ;
}
/************************************************************************
@ -1861,7 +2018,8 @@ buf_LRU_stat_update(void)
goto func_exit ;
}
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & buf_pool_mutex ) ;
/* Update the index. */
item = & buf_LRU_stat_arr [ buf_LRU_stat_arr_ind ] ;
@ -1875,7 +2033,8 @@ buf_LRU_stat_update(void)
/* Put current entry in the array. */
memcpy ( item , & buf_LRU_stat_cur , sizeof * item ) ;
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & buf_pool_mutex ) ;
func_exit :
/* Clear the current entry. */
@ -1897,7 +2056,8 @@ buf_LRU_validate(void)
ulint LRU_pos ;
ut_ad ( buf_pool ) ;
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & LRU_list_mutex ) ;
if ( UT_LIST_GET_LEN ( buf_pool - > LRU ) > = BUF_LRU_OLD_MIN_LEN ) {
@ -1956,15 +2116,21 @@ buf_LRU_validate(void)
ut_a ( buf_pool - > LRU_old_len = = old_len ) ;
}
UT_LIST_VALIDATE ( list , buf_page_t , buf_pool - > free ) ;
mutex_exit ( & LRU_list_mutex ) ;
mutex_enter ( & free_list_mutex ) ;
UT_LIST_VALIDATE ( free , buf_page_t , buf_pool - > free ) ;
for ( bpage = UT_LIST_GET_FIRST ( buf_pool - > free ) ;
bpage ! = NULL ;
bpage = UT_LIST_GET_NEXT ( list , bpage ) ) {
bpage = UT_LIST_GET_NEXT ( free , bpage ) ) {
ut_a ( buf_page_get_state ( bpage ) = = BUF_BLOCK_NOT_USED ) ;
}
mutex_exit ( & free_list_mutex ) ;
mutex_enter ( & LRU_list_mutex ) ;
UT_LIST_VALIDATE ( unzip_LRU , buf_block_t , buf_pool - > unzip_LRU ) ;
for ( block = UT_LIST_GET_FIRST ( buf_pool - > unzip_LRU ) ;
@ -1976,7 +2142,8 @@ buf_LRU_validate(void)
ut_a ( buf_page_belongs_to_unzip_LRU ( & block - > page ) ) ;
}
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
return ( TRUE ) ;
}
# endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
@ -1992,7 +2159,8 @@ buf_LRU_print(void)
const buf_page_t * bpage ;
ut_ad ( buf_pool ) ;
buf_pool_mutex_enter ( ) ;
/ / buf_pool_mutex_enter ( ) ;
mutex_enter ( & LRU_list_mutex ) ;
fprintf ( stderr , " Pool ulint clock %lu \n " ,
( ulong ) buf_pool - > ulint_clock ) ;
@ -2055,6 +2223,7 @@ buf_LRU_print(void)
bpage = UT_LIST_GET_NEXT ( LRU , bpage ) ;
}
buf_pool_mutex_exit ( ) ;
/ / buf_pool_mutex_exit ( ) ;
mutex_exit ( & LRU_list_mutex ) ;
}
# endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */