#include "univ.i"#include "ut0byte.h"#include "buf0types.h"Include dependency graph for buf0lru.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
Defines | |
| #define | BUF_LRU_OLD_MIN_LEN 80 |
| #define | BUF_LRU_FREE_SEARCH_LEN (5 + 2 * BUF_READ_AHEAD_AREA) |
Functions | |
| void | buf_LRU_try_free_flushed_blocks (void) |
| ibool | buf_LRU_buf_pool_running_out (void) |
| void | buf_LRU_invalidate_tablespace (ulint id) |
| ulint | buf_LRU_get_recent_limit (void) |
| ibool | buf_LRU_search_and_free_block (ulint n_iterations) |
| buf_block_t * | buf_LRU_get_free_block (void) |
| void | buf_LRU_block_free_non_file_page (buf_block_t *block) |
| void | buf_LRU_add_block (buf_block_t *block, ibool old) |
| void | buf_LRU_make_block_young (buf_block_t *block) |
| void | buf_LRU_make_block_old (buf_block_t *block) |
| #define BUF_LRU_FREE_SEARCH_LEN (5 + 2 * BUF_READ_AHEAD_AREA) |
| #define BUF_LRU_OLD_MIN_LEN 80 |
Definition at line 45 of file buf0lru.h.
Referenced by buf_flush_try_neighbors(), buf_LRU_add_block_low(), buf_LRU_add_block_to_end_low(), buf_LRU_get_recent_limit(), buf_LRU_old_adjust_len(), buf_LRU_old_init(), and buf_LRU_remove_block().
| void buf_LRU_add_block | ( | buf_block_t * | block, | |
| ibool | old | |||
| ) |
Definition at line 775 of file buf0lru.c.
References yaSSL::block, and buf_LRU_add_block_low().
Referenced by buf_page_create(), and buf_page_init_for_read().
00777 : control block */ 00778 ibool old) /* in: TRUE if should be put to the old 00779 blocks in the LRU list, else put to the start; 00780 if the LRU list is very short, the block is 00781 added to the start, regardless of this 00782 parameter */ 00783 { 00784 buf_LRU_add_block_low(block, old); 00785 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void buf_LRU_block_free_non_file_page | ( | buf_block_t * | block | ) |
Definition at line 815 of file buf0lru.c.
References yaSSL::block, BUF_BLOCK_MEMORY, BUF_BLOCK_NOT_USED, BUF_BLOCK_READY_FOR_USE, buf_pool, free, memset, buf_pool_struct::mutex, srv_use_awe, TRUE, UNIV_PAGE_SIZE, ut_a, ut_ad, and UT_LIST_ADD_FIRST.
Referenced by buf_block_free(), and buf_LRU_block_free_hashed_page().
00817 : block, must not contain a file page */ 00818 { 00819 #ifdef UNIV_SYNC_DEBUG 00820 ut_ad(mutex_own(&(buf_pool->mutex))); 00821 #endif /* UNIV_SYNC_DEBUG */ 00822 ut_ad(block); 00823 00824 ut_a((block->state == BUF_BLOCK_MEMORY) 00825 || (block->state == BUF_BLOCK_READY_FOR_USE)); 00826 00827 ut_a(block->n_pointers == 0); 00828 ut_a(!block->in_free_list); 00829 00830 block->state = BUF_BLOCK_NOT_USED; 00831 00832 #ifdef UNIV_DEBUG 00833 /* Wipe contents of page to reveal possible stale pointers to it */ 00834 memset(block->frame, '\0', UNIV_PAGE_SIZE); 00835 #endif 00836 UT_LIST_ADD_FIRST(free, buf_pool->free, block); 00837 block->in_free_list = TRUE; 00838 00839 if (srv_use_awe && block->frame) { 00840 /* Add to the list of mapped pages */ 00841 00842 UT_LIST_ADD_FIRST(awe_LRU_free_mapped, 00843 buf_pool->awe_LRU_free_mapped, block); 00844 } 00845 }
Here is the caller graph for this function:

| ibool buf_LRU_buf_pool_running_out | ( | void | ) |
Definition at line 302 of file buf0lru.c.
References buf_pool, FALSE, buf_pool_struct::max_size, buf_pool_struct::mutex, mutex_enter, mutex_exit(), recv_recovery_on, TRUE, and UT_LIST_GET_LEN.
Referenced by row_ins_clust_index_entry_by_modify(), row_ins_index_entry_low(), row_ins_sec_index_entry_by_modify(), row_upd_clust_rec(), and sel_set_rec_lock().
00304 : TRUE if less than 25 % of buffer pool 00305 left */ 00306 { 00307 ibool ret = FALSE; 00308 00309 mutex_enter(&(buf_pool->mutex)); 00310 00311 if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) 00312 + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) { 00313 00314 ret = TRUE; 00315 } 00316 00317 mutex_exit(&(buf_pool->mutex)); 00318 00319 return(ret); 00320 }
Here is the call graph for this function:

Here is the caller graph for this function:

| buf_block_t* buf_LRU_get_free_block | ( | void | ) |
Definition at line 328 of file buf0lru.c.
References yaSSL::block, buf_awe_map_page_to_frame(), BUF_BLOCK_FILE_PAGE, BUF_BLOCK_READY_FOR_USE, buf_flush_free_margin(), buf_LRU_search_and_free_block(), buf_lru_switched_on_innodb_mon, buf_LRU_try_free_flushed_blocks(), buf_pool, buf_pool_struct::curr_size, FALSE, fil_n_pending_log_flushes, fil_n_pending_tablespace_flushes, free, buf_pool_struct::LRU_flush_ended, buf_pool_struct::max_size, buf_pool_struct::mutex, mutex_enter, mutex_exit(), NULL, os_aio_simulated_wake_handler_threads(), os_event_set(), os_n_file_reads, os_n_file_writes, os_n_fsyncs, os_thread_sleep(), recv_recovery_on, srv_buf_pool_wait_free, srv_lock_timeout_thread_event, srv_print_innodb_monitor, srv_use_awe, TRUE, UNIV_PAGE_SIZE, ut_a, ut_error, UT_LIST_GET_FIRST, UT_LIST_GET_LEN, UT_LIST_REMOVE, and ut_print_timestamp().
Referenced by buf_block_alloc(), and buf_page_create().
00330 : the free control block; also if AWE is 00331 used, it is guaranteed that the block has its 00332 page mapped to a frame when we return */ 00333 { 00334 buf_block_t* block = NULL; 00335 ibool freed; 00336 ulint n_iterations = 1; 00337 ibool mon_value_was = FALSE; 00338 ibool started_monitor = FALSE; 00339 loop: 00340 mutex_enter(&(buf_pool->mutex)); 00341 00342 if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) 00343 + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) { 00344 ut_print_timestamp(stderr); 00345 00346 fprintf(stderr, 00347 " InnoDB: ERROR: over 95 percent of the buffer pool is occupied by\n" 00348 "InnoDB: lock heaps or the adaptive hash index! Check that your\n" 00349 "InnoDB: transactions do not set too many row locks.\n" 00350 "InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n" 00351 "InnoDB: the buffer pool bigger?\n" 00352 "InnoDB: We intentionally generate a seg fault to print a stack trace\n" 00353 "InnoDB: on Linux!\n", 00354 (ulong)(buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE))); 00355 00356 ut_error; 00357 00358 } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) 00359 + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 3) { 00360 00361 if (!buf_lru_switched_on_innodb_mon) { 00362 00363 /* Over 67 % of the buffer pool is occupied by lock 00364 heaps or the adaptive hash index. This may be a memory 00365 leak! */ 00366 00367 ut_print_timestamp(stderr); 00368 fprintf(stderr, 00369 " InnoDB: WARNING: over 67 percent of the buffer pool is occupied by\n" 00370 "InnoDB: lock heaps or the adaptive hash index! Check that your\n" 00371 "InnoDB: transactions do not set too many row locks.\n" 00372 "InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n" 00373 "InnoDB: the buffer pool bigger?\n" 00374 "InnoDB: Starting the InnoDB Monitor to print diagnostics, including\n" 00375 "InnoDB: lock heap and hash index sizes.\n", 00376 (ulong) (buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE))); 00377 00378 buf_lru_switched_on_innodb_mon = TRUE; 00379 srv_print_innodb_monitor = TRUE; 00380 os_event_set(srv_lock_timeout_thread_event); 00381 } 00382 } else if (buf_lru_switched_on_innodb_mon) { 00383 00384 /* Switch off the InnoDB Monitor; this is a simple way 00385 to stop the monitor if the situation becomes less urgent, 00386 but may also surprise users if the user also switched on the 00387 monitor! */ 00388 00389 buf_lru_switched_on_innodb_mon = FALSE; 00390 srv_print_innodb_monitor = FALSE; 00391 } 00392 00393 /* If there is a block in the free list, take it */ 00394 if (UT_LIST_GET_LEN(buf_pool->free) > 0) { 00395 00396 block = UT_LIST_GET_FIRST(buf_pool->free); 00397 ut_a(block->in_free_list); 00398 UT_LIST_REMOVE(free, buf_pool->free, block); 00399 block->in_free_list = FALSE; 00400 ut_a(block->state != BUF_BLOCK_FILE_PAGE); 00401 ut_a(!block->in_LRU_list); 00402 00403 if (srv_use_awe) { 00404 if (block->frame) { 00405 /* Remove from the list of mapped pages */ 00406 00407 UT_LIST_REMOVE(awe_LRU_free_mapped, 00408 buf_pool->awe_LRU_free_mapped, block); 00409 } else { 00410 /* We map the page to a frame; second param 00411 FALSE below because we do not want it to be 00412 added to the awe_LRU_free_mapped list */ 00413 00414 buf_awe_map_page_to_frame(block, FALSE); 00415 } 00416 } 00417 00418 block->state = BUF_BLOCK_READY_FOR_USE; 00419 00420 mutex_exit(&(buf_pool->mutex)); 00421 00422 if (started_monitor) { 00423 srv_print_innodb_monitor = mon_value_was; 00424 } 00425 00426 return(block); 00427 } 00428 00429 /* If no block was in the free list, search from the end of the LRU 00430 list and try to free a block there */ 00431 00432 mutex_exit(&(buf_pool->mutex)); 00433 00434 freed = buf_LRU_search_and_free_block(n_iterations); 00435 00436 if (freed > 0) { 00437 goto loop; 00438 } 00439 00440 if (n_iterations > 30) { 00441 ut_print_timestamp(stderr); 00442 fprintf(stderr, 00443 "InnoDB: Warning: difficult to find free blocks from\n" 00444 "InnoDB: the buffer pool (%lu search iterations)! Consider\n" 00445 "InnoDB: increasing the buffer pool size.\n" 00446 "InnoDB: It is also possible that in your Unix version\n" 00447 "InnoDB: fsync is very slow, or completely frozen inside\n" 00448 "InnoDB: the OS kernel. Then upgrading to a newer version\n" 00449 "InnoDB: of your operating system may help. Look at the\n" 00450 "InnoDB: number of fsyncs in diagnostic info below.\n" 00451 "InnoDB: Pending flushes (fsync) log: %lu; buffer pool: %lu\n" 00452 "InnoDB: %lu OS file reads, %lu OS file writes, %lu OS fsyncs\n" 00453 "InnoDB: Starting InnoDB Monitor to print further\n" 00454 "InnoDB: diagnostics to the standard output.\n", 00455 (ulong) n_iterations, 00456 (ulong) fil_n_pending_log_flushes, 00457 (ulong) fil_n_pending_tablespace_flushes, 00458 (ulong) os_n_file_reads, (ulong) os_n_file_writes, 00459 (ulong) os_n_fsyncs); 00460 00461 mon_value_was = srv_print_innodb_monitor; 00462 started_monitor = TRUE; 00463 srv_print_innodb_monitor = TRUE; 00464 os_event_set(srv_lock_timeout_thread_event); 00465 } 00466 00467 /* No free block was found: try to flush the LRU list */ 00468 00469 buf_flush_free_margin(); 00470 ++srv_buf_pool_wait_free; 00471 00472 os_aio_simulated_wake_handler_threads(); 00473 00474 mutex_enter(&(buf_pool->mutex)); 00475 00476 if (buf_pool->LRU_flush_ended > 0) { 00477 /* We have written pages in an LRU flush. To make the insert 00478 buffer more efficient, we try to move these pages to the free 00479 list. */ 00480 00481 mutex_exit(&(buf_pool->mutex)); 00482 00483 buf_LRU_try_free_flushed_blocks(); 00484 } else { 00485 mutex_exit(&(buf_pool->mutex)); 00486 } 00487 00488 if (n_iterations > 10) { 00489 00490 os_thread_sleep(500000); 00491 } 00492 00493 n_iterations++; 00494 00495 goto loop; 00496 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint buf_LRU_get_recent_limit | ( | void | ) |
Definition at line 159 of file buf0lru.c.
References yaSSL::block, BUF_LRU_INITIAL_RATIO, BUF_LRU_OLD_MIN_LEN, buf_pool, buf_pool_struct::mutex, mutex_enter, mutex_exit(), UT_LIST_GET_FIRST, and UT_LIST_GET_LEN.
Referenced by buf_read_ahead_random().
00161 : the limit; zero if could not determine it */ 00162 { 00163 buf_block_t* block; 00164 ulint len; 00165 ulint limit; 00166 00167 mutex_enter(&(buf_pool->mutex)); 00168 00169 len = UT_LIST_GET_LEN(buf_pool->LRU); 00170 00171 if (len < BUF_LRU_OLD_MIN_LEN) { 00172 /* The LRU list is too short to do read-ahead */ 00173 00174 mutex_exit(&(buf_pool->mutex)); 00175 00176 return(0); 00177 } 00178 00179 block = UT_LIST_GET_FIRST(buf_pool->LRU); 00180 00181 limit = block->LRU_position - len / BUF_LRU_INITIAL_RATIO; 00182 00183 mutex_exit(&(buf_pool->mutex)); 00184 00185 return(limit); 00186 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void buf_LRU_invalidate_tablespace | ( | ulint | id | ) |
Definition at line 73 of file buf0lru.c.
References yaSSL::block, btr_search_drop_page_hash_when_freed(), BUF_BLOCK_FILE_PAGE, buf_LRU_block_free_hashed_page(), buf_LRU_block_remove_hashed_page(), buf_pool, FALSE, buf_pool_struct::mutex, mutex_enter, mutex_exit(), NULL, os_thread_sleep(), TRUE, ut_a, ut_dulint_cmp(), ut_dulint_zero, UT_LIST_GET_LAST, UT_LIST_GET_PREV, and UT_LIST_REMOVE.
Referenced by fil_delete_tablespace().
00075 : space id */ 00076 { 00077 buf_block_t* block; 00078 ulint page_no; 00079 ibool all_freed; 00080 00081 scan_again: 00082 mutex_enter(&(buf_pool->mutex)); 00083 00084 all_freed = TRUE; 00085 00086 block = UT_LIST_GET_LAST(buf_pool->LRU); 00087 00088 while (block != NULL) { 00089 ut_a(block->state == BUF_BLOCK_FILE_PAGE); 00090 00091 if (block->space == id 00092 && (block->buf_fix_count > 0 || block->io_fix != 0)) { 00093 00094 /* We cannot remove this page during this scan yet; 00095 maybe the system is currently reading it in, or 00096 flushing the modifications to the file */ 00097 00098 all_freed = FALSE; 00099 00100 goto next_page; 00101 } 00102 00103 if (block->space == id) { 00104 #ifdef UNIV_DEBUG 00105 if (buf_debug_prints) { 00106 printf( 00107 "Dropping space %lu page %lu\n", 00108 (ulong) block->space, 00109 (ulong) block->offset); 00110 } 00111 #endif 00112 if (block->is_hashed) { 00113 page_no = block->offset; 00114 00115 mutex_exit(&(buf_pool->mutex)); 00116 00117 /* Note that the following call will acquire 00118 an S-latch on the page */ 00119 00120 btr_search_drop_page_hash_when_freed(id, 00121 page_no); 00122 goto scan_again; 00123 } 00124 00125 if (0 != ut_dulint_cmp(block->oldest_modification, 00126 ut_dulint_zero)) { 00127 00128 /* Remove from the flush list of modified 00129 blocks */ 00130 block->oldest_modification = ut_dulint_zero; 00131 00132 UT_LIST_REMOVE(flush_list, 00133 buf_pool->flush_list, block); 00134 } 00135 00136 /* Remove from the LRU list */ 00137 buf_LRU_block_remove_hashed_page(block); 00138 buf_LRU_block_free_hashed_page(block); 00139 } 00140 next_page: 00141 block = UT_LIST_GET_PREV(LRU, block); 00142 } 00143 00144 mutex_exit(&(buf_pool->mutex)); 00145 00146 if (!all_freed) { 00147 os_thread_sleep(20000); 00148 00149 goto scan_again; 00150 } 00151 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void buf_LRU_make_block_old | ( | buf_block_t * | block | ) |
Definition at line 803 of file buf0lru.c.
References yaSSL::block, buf_LRU_add_block_to_end_low(), and buf_LRU_remove_block().
Referenced by buf_flush_write_complete().
00805 : control block */ 00806 { 00807 buf_LRU_remove_block(block); 00808 buf_LRU_add_block_to_end_low(block); 00809 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void buf_LRU_make_block_young | ( | buf_block_t * | block | ) |
Definition at line 791 of file buf0lru.c.
References yaSSL::block, buf_LRU_add_block_low(), buf_LRU_remove_block(), and FALSE.
Referenced by buf_block_make_young(), and buf_page_make_young().
00793 : control block */ 00794 { 00795 buf_LRU_remove_block(block); 00796 buf_LRU_add_block_low(block, FALSE); 00797 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool buf_LRU_search_and_free_block | ( | ulint | n_iterations | ) |
Definition at line 193 of file buf0lru.c.
References yaSSL::block, btr_search_drop_page_hash_index(), buf_flush_ready_for_replace(), buf_LRU_block_free_hashed_page(), buf_LRU_block_remove_hashed_page(), buf_pool, buf_pool_struct::curr_size, FALSE, buf_pool_struct::LRU_flush_ended, buf_pool_struct::mutex, mutex_enter, mutex_exit(), NULL, TRUE, ut_a, UT_LIST_GET_LAST, and UT_LIST_GET_PREV.
Referenced by buf_LRU_get_free_block(), buf_LRU_try_free_flushed_blocks(), and buf_pool_invalidate().
00195 : TRUE if freed */ 00196 ulint n_iterations) /* in: how many times this has been called 00197 repeatedly without result: a high value means 00198 that we should search farther; if value is 00199 k < 10, then we only search k/10 * [number 00200 of pages in the buffer pool] from the end 00201 of the LRU list */ 00202 { 00203 buf_block_t* block; 00204 ulint distance = 0; 00205 ibool freed; 00206 00207 mutex_enter(&(buf_pool->mutex)); 00208 00209 freed = FALSE; 00210 block = UT_LIST_GET_LAST(buf_pool->LRU); 00211 00212 while (block != NULL) { 00213 ut_a(block->in_LRU_list); 00214 if (buf_flush_ready_for_replace(block)) { 00215 00216 #ifdef UNIV_DEBUG 00217 if (buf_debug_prints) { 00218 fprintf(stderr, 00219 "Putting space %lu page %lu to free list\n", 00220 (ulong) block->space, 00221 (ulong) block->offset); 00222 } 00223 #endif /* UNIV_DEBUG */ 00224 00225 buf_LRU_block_remove_hashed_page(block); 00226 00227 mutex_exit(&(buf_pool->mutex)); 00228 00229 /* Remove possible adaptive hash index built on the 00230 page; in the case of AWE the block may not have a 00231 frame at all */ 00232 00233 if (block->frame) { 00234 btr_search_drop_page_hash_index(block->frame); 00235 } 00236 mutex_enter(&(buf_pool->mutex)); 00237 00238 ut_a(block->buf_fix_count == 0); 00239 00240 buf_LRU_block_free_hashed_page(block); 00241 freed = TRUE; 00242 00243 break; 00244 } 00245 block = UT_LIST_GET_PREV(LRU, block); 00246 distance++; 00247 00248 if (!freed && n_iterations <= 10 00249 && distance > 100 + (n_iterations * buf_pool->curr_size) 00250 / 10) { 00251 buf_pool->LRU_flush_ended = 0; 00252 00253 mutex_exit(&(buf_pool->mutex)); 00254 00255 return(FALSE); 00256 } 00257 } 00258 if (buf_pool->LRU_flush_ended > 0) { 00259 buf_pool->LRU_flush_ended--; 00260 } 00261 if (!freed) { 00262 buf_pool->LRU_flush_ended = 0; 00263 } 00264 mutex_exit(&(buf_pool->mutex)); 00265 00266 return(freed); 00267 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void buf_LRU_try_free_flushed_blocks | ( | void | ) |
Definition at line 279 of file buf0lru.c.
References buf_LRU_search_and_free_block(), buf_pool, buf_pool_struct::LRU_flush_ended, buf_pool_struct::mutex, mutex_enter, and mutex_exit().
Referenced by buf_LRU_get_free_block().
00281 { 00282 mutex_enter(&(buf_pool->mutex)); 00283 00284 while (buf_pool->LRU_flush_ended > 0) { 00285 00286 mutex_exit(&(buf_pool->mutex)); 00287 00288 buf_LRU_search_and_free_block(1); 00289 00290 mutex_enter(&(buf_pool->mutex)); 00291 } 00292 00293 mutex_exit(&(buf_pool->mutex)); 00294 }
Here is the call graph for this function:

Here is the caller graph for this function:

1.4.7

