00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include <config.h>
00027 #include "buf0lru.h"
00028
00029 #ifdef UNIV_NONINL
00030 #include "buf0lru.ic"
00031 #endif
00032
00033 #include "ut0byte.h"
00034 #include "ut0lst.h"
00035 #include "ut0rnd.h"
00036 #include "sync0sync.h"
00037 #include "sync0rw.h"
00038 #include "hash0hash.h"
00039 #include "os0sync.h"
00040 #include "fil0fil.h"
00041 #include "btr0btr.h"
00042 #include "buf0buddy.h"
00043 #include "buf0buf.h"
00044 #include "buf0flu.h"
00045 #include "buf0rea.h"
00046 #include "btr0sea.h"
00047 #include "ibuf0ibuf.h"
00048 #include "os0file.h"
00049 #include "page0zip.h"
00050 #include "log0recv.h"
00051 #include "srv0srv.h"
00052
00060 #define BUF_LRU_OLD_TOLERANCE 20
00061
00065 #define BUF_LRU_NON_OLD_MIN_LEN 5
00066 #if BUF_LRU_NON_OLD_MIN_LEN >= BUF_LRU_OLD_MIN_LEN
00067 # error "BUF_LRU_NON_OLD_MIN_LEN >= BUF_LRU_OLD_MIN_LEN"
00068 #endif
00069
00073 #define BUF_LRU_DROP_SEARCH_HASH_SIZE 1024
00074
00077 static ibool buf_lru_switched_on_innodb_mon = FALSE;
00078
00079
00088
00089
00093 #define BUF_LRU_STAT_N_INTERVAL 50
00094
00097 #define BUF_LRU_IO_TO_UNZIP_FACTOR 50
00098
00101 static buf_LRU_stat_t buf_LRU_stat_arr[BUF_LRU_STAT_N_INTERVAL];
00102
00104 static ulint buf_LRU_stat_arr_ind;
00105
00108 UNIV_INTERN buf_LRU_stat_t buf_LRU_stat_cur;
00109
00112 UNIV_INTERN buf_LRU_stat_t buf_LRU_stat_sum;
00113
00114
00115
00119 UNIV_INTERN uint buf_LRU_old_threshold_ms;
00120
00121
00122
00132 static
00133 enum buf_page_state
00134 buf_LRU_block_remove_hashed_page(
00135
00136 buf_page_t* bpage,
00139 ibool zip);
00141
00143 static
00144 void
00145 buf_LRU_block_free_hashed_page(
00146
00147 buf_block_t* block);
00150
00154 UNIV_INLINE
00155 ibool
00156 buf_LRU_evict_from_unzip_LRU(
00157
00158 buf_pool_t* buf_pool)
00159 {
00160 ulint io_avg;
00161 ulint unzip_avg;
00162
00163 ut_ad(buf_pool_mutex_own(buf_pool));
00164
00165
00166 if (UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0) {
00167 return(FALSE);
00168 }
00169
00170
00171
00172
00173 if (UT_LIST_GET_LEN(buf_pool->unzip_LRU)
00174 <= UT_LIST_GET_LEN(buf_pool->LRU) / 10) {
00175 return(FALSE);
00176 }
00177
00178
00179
00180 if (buf_pool->freed_page_clock == 0) {
00181 return(TRUE);
00182 }
00183
00184
00185
00186 io_avg = buf_LRU_stat_sum.io / BUF_LRU_STAT_N_INTERVAL
00187 + buf_LRU_stat_cur.io;
00188 unzip_avg = buf_LRU_stat_sum.unzip / BUF_LRU_STAT_N_INTERVAL
00189 + buf_LRU_stat_cur.unzip;
00190
00191
00192
00193
00194
00195 return(unzip_avg <= io_avg * BUF_LRU_IO_TO_UNZIP_FACTOR);
00196 }
00197
00198
00201 static
00202 void
00203 buf_LRU_drop_page_hash_batch(
00204
00205 ulint space_id,
00206 ulint zip_size,
00208 const ulint* arr,
00209 ulint count)
00210 {
00211 ulint i;
00212
00213 ut_ad(arr != NULL);
00214 ut_ad(count <= BUF_LRU_DROP_SEARCH_HASH_SIZE);
00215
00216 for (i = 0; i < count; ++i) {
00217 btr_search_drop_page_hash_when_freed(space_id, zip_size,
00218 arr[i]);
00219 }
00220 }
00221
00222
00227 static
00228 void
00229 buf_LRU_drop_page_hash_for_tablespace(
00230
00231 buf_pool_t* buf_pool,
00232 ulint id)
00233 {
00234 buf_page_t* bpage;
00235 ulint* page_arr;
00236 ulint num_entries;
00237 ulint zip_size;
00238
00239 zip_size = fil_space_get_zip_size(id);
00240
00241 if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
00242
00243 ut_ad(0);
00244 return;
00245 }
00246
00247 page_arr = static_cast<unsigned long *>(ut_malloc(
00248 sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE));
00249
00250 buf_pool_mutex_enter(buf_pool);
00251
00252 scan_again:
00253 num_entries = 0;
00254 bpage = UT_LIST_GET_LAST(buf_pool->LRU);
00255
00256 while (bpage != NULL) {
00257 mutex_t* block_mutex = buf_page_get_mutex(bpage);
00258 buf_page_t* prev_bpage;
00259
00260 mutex_enter(block_mutex);
00261 prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
00262
00263 ut_a(buf_page_in_file(bpage));
00264
00265 if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE
00266 || bpage->space != id
00267 || bpage->buf_fix_count > 0
00268 || bpage->io_fix != BUF_IO_NONE) {
00269
00270
00271 mutex_exit(block_mutex);
00272 goto next_page;
00273 }
00274
00275 if (((buf_block_t*) bpage)->is_hashed) {
00276
00277
00278
00279
00280 page_arr[num_entries] = bpage->offset;
00281 mutex_exit(block_mutex);
00282 ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
00283 ++num_entries;
00284
00285 if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
00286 goto next_page;
00287 }
00288
00289
00290
00291 buf_pool_mutex_exit(buf_pool);
00292
00293 buf_LRU_drop_page_hash_batch(
00294 id, zip_size, page_arr, num_entries);
00295
00296 num_entries = 0;
00297
00298 buf_pool_mutex_enter(buf_pool);
00299 } else {
00300 mutex_exit(block_mutex);
00301 }
00302
00303 next_page:
00304
00305
00306
00307
00308
00309
00310
00311
00312 bpage = prev_bpage;
00313
00314
00315
00316
00317 if (bpage && !buf_page_in_file(bpage)) {
00318 ut_a(num_entries == 0);
00319 goto scan_again;
00320 }
00321 }
00322
00323 buf_pool_mutex_exit(buf_pool);
00324
00325
00326 buf_LRU_drop_page_hash_batch(id, zip_size, page_arr, num_entries);
00327 ut_free(page_arr);
00328 }
00329
00330
00334 static
00335 void
00336 buf_LRU_invalidate_tablespace_buf_pool_instance(
00337
00338 buf_pool_t* buf_pool,
00339 ulint id)
00340 {
00341 buf_page_t* bpage;
00342 ibool all_freed;
00343
00344 scan_again:
00345 buf_pool_mutex_enter(buf_pool);
00346
00347 all_freed = TRUE;
00348
00349 bpage = UT_LIST_GET_LAST(buf_pool->LRU);
00350
00351 while (bpage != NULL) {
00352 buf_page_t* prev_bpage;
00353 ibool prev_bpage_buf_fix = FALSE;
00354
00355 ut_a(buf_page_in_file(bpage));
00356
00357 prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
00358
00359
00360
00361
00362
00363 if (buf_page_get_space(bpage) != id) {
00364
00365
00366 } else if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
00367
00368
00369
00370
00371 all_freed = FALSE;
00372 } else {
00373 mutex_t* block_mutex = buf_page_get_mutex(bpage);
00374 mutex_enter(block_mutex);
00375
00376 if (bpage->buf_fix_count > 0) {
00377
00378
00379
00380
00381
00382
00383 all_freed = FALSE;
00384
00385 goto next_page;
00386 }
00387
00388 #ifdef UNIV_DEBUG
00389 if (buf_debug_prints) {
00390 fprintf(stderr,
00391 "Dropping space %lu page %lu\n",
00392 (ulong) buf_page_get_space(bpage),
00393 (ulong) buf_page_get_page_no(bpage));
00394 }
00395 #endif
00396 if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
00397
00398
00399
00400 if (UNIV_LIKELY(prev_bpage != NULL)) {
00401 switch (buf_page_get_state(
00402 prev_bpage)) {
00403 case BUF_BLOCK_FILE_PAGE:
00404
00405
00406
00407
00408 break;
00409 case BUF_BLOCK_ZIP_PAGE:
00410 case BUF_BLOCK_ZIP_DIRTY:
00411
00412
00413
00414
00415
00416
00417
00418
00419 ut_ad(&buf_pool->zip_mutex
00420 == block_mutex);
00421 ut_ad(mutex_own(block_mutex));
00422 prev_bpage_buf_fix = TRUE;
00423 prev_bpage->buf_fix_count++;
00424 break;
00425 default:
00426 ut_error;
00427 }
00428 }
00429 } else if (((buf_block_t*) bpage)->is_hashed) {
00430 ulint page_no;
00431 ulint zip_size;
00432
00433 buf_pool_mutex_exit(buf_pool);
00434
00435 zip_size = buf_page_get_zip_size(bpage);
00436 page_no = buf_page_get_page_no(bpage);
00437
00438 mutex_exit(block_mutex);
00439
00440
00441
00442
00443 btr_search_drop_page_hash_when_freed(
00444 id, zip_size, page_no);
00445 goto scan_again;
00446 }
00447
00448 if (bpage->oldest_modification != 0) {
00449
00450 buf_flush_remove(bpage);
00451 }
00452
00453
00454
00455 if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
00456 != BUF_BLOCK_ZIP_FREE) {
00457 buf_LRU_block_free_hashed_page((buf_block_t*)
00458 bpage);
00459 } else {
00460
00461
00462
00463 ut_ad(block_mutex == &buf_pool->zip_mutex);
00464 ut_ad(!mutex_own(block_mutex));
00465
00466 if (prev_bpage_buf_fix) {
00467
00468
00469
00470
00471
00472
00473
00474 mutex_enter(block_mutex);
00475 ut_ad(prev_bpage->buf_fix_count > 0);
00476 prev_bpage->buf_fix_count--;
00477 mutex_exit(block_mutex);
00478 }
00479
00480 goto next_page_no_mutex;
00481 }
00482 next_page:
00483 mutex_exit(block_mutex);
00484 }
00485
00486 next_page_no_mutex:
00487 bpage = prev_bpage;
00488 }
00489
00490 buf_pool_mutex_exit(buf_pool);
00491
00492 if (!all_freed) {
00493 os_thread_sleep(20000);
00494
00495 goto scan_again;
00496 }
00497 }
00498
00499
00502 UNIV_INTERN
00503 void
00504 buf_LRU_invalidate_tablespace(
00505
00506 ulint id)
00507 {
00508 ulint i;
00509
00510
00511
00512
00513
00514
00515
00516 for (i = 0; i < srv_buf_pool_instances; i++) {
00517 buf_pool_t* buf_pool;
00518
00519 buf_pool = buf_pool_from_array(i);
00520 buf_LRU_drop_page_hash_for_tablespace(buf_pool, id);
00521 buf_LRU_invalidate_tablespace_buf_pool_instance(buf_pool, id);
00522 }
00523 }
00524
00525
00527 UNIV_INTERN
00528 void
00529 buf_LRU_insert_zip_clean(
00530
00531 buf_page_t* bpage)
00532 {
00533 buf_page_t* b;
00534 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
00535
00536 ut_ad(buf_pool_mutex_own(buf_pool));
00537 ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
00538
00539
00540
00541 b = bpage;
00542 do {
00543 b = UT_LIST_GET_NEXT(LRU, b);
00544 } while (b && buf_page_get_state(b) != BUF_BLOCK_ZIP_PAGE);
00545
00546
00547 if (b) {
00548 b = UT_LIST_GET_PREV(list, b);
00549 }
00550
00551 if (b) {
00552 UT_LIST_INSERT_AFTER(list, buf_pool->zip_clean, b, bpage);
00553 } else {
00554 UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, bpage);
00555 }
00556 }
00557
00558
00562 UNIV_INLINE
00563 ibool
00564 buf_LRU_free_from_unzip_LRU_list(
00565
00566 buf_pool_t* buf_pool,
00567 ulint n_iterations)
00574 {
00575 buf_block_t* block;
00576 ulint distance;
00577
00578 ut_ad(buf_pool_mutex_own(buf_pool));
00579
00580
00581
00582
00583
00584
00585
00586
00587 if (UNIV_UNLIKELY(n_iterations >= 5)
00588 || !buf_LRU_evict_from_unzip_LRU(buf_pool)) {
00589
00590 return(FALSE);
00591 }
00592
00593 distance = 100 + (n_iterations
00594 * UT_LIST_GET_LEN(buf_pool->unzip_LRU)) / 5;
00595
00596 for (block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
00597 UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0);
00598 block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) {
00599
00600 enum buf_lru_free_block_status freed;
00601
00602 ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
00603 ut_ad(block->in_unzip_LRU_list);
00604 ut_ad(block->page.in_LRU_list);
00605
00606 mutex_enter(&block->mutex);
00607 freed = buf_LRU_free_block(&block->page, FALSE, NULL);
00608 mutex_exit(&block->mutex);
00609
00610 switch (freed) {
00611 case BUF_LRU_FREED:
00612 return(TRUE);
00613
00614 case BUF_LRU_CANNOT_RELOCATE:
00615
00616
00617 return(FALSE);
00618
00619 case BUF_LRU_NOT_FREED:
00620
00621
00622 continue;
00623 }
00624
00625
00626
00627 ut_error;
00628 }
00629
00630 return(FALSE);
00631 }
00632
00633
00636 UNIV_INLINE
00637 ibool
00638 buf_LRU_free_from_common_LRU_list(
00639
00640 buf_pool_t* buf_pool,
00641 ulint n_iterations)
00648 {
00649 buf_page_t* bpage;
00650 ulint distance;
00651
00652 ut_ad(buf_pool_mutex_own(buf_pool));
00653
00654 distance = 100 + (n_iterations * buf_pool->curr_size) / 10;
00655
00656 for (bpage = UT_LIST_GET_LAST(buf_pool->LRU);
00657 UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0);
00658 bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
00659
00660 enum buf_lru_free_block_status freed;
00661 unsigned accessed;
00662 mutex_t* block_mutex
00663 = buf_page_get_mutex(bpage);
00664
00665 ut_ad(buf_page_in_file(bpage));
00666 ut_ad(bpage->in_LRU_list);
00667
00668 mutex_enter(block_mutex);
00669 accessed = buf_page_is_accessed(bpage);
00670 freed = buf_LRU_free_block(bpage, TRUE, NULL);
00671 mutex_exit(block_mutex);
00672
00673 switch (freed) {
00674 case BUF_LRU_FREED:
00675
00676
00677
00678 if (!accessed) {
00679 ++buf_pool->stat.n_ra_pages_evicted;
00680 }
00681 return(TRUE);
00682
00683 case BUF_LRU_NOT_FREED:
00684
00685
00686 continue;
00687
00688 case BUF_LRU_CANNOT_RELOCATE:
00689
00690
00691 break;
00692 }
00693
00694
00695
00696 ut_error;
00697 }
00698
00699 return(FALSE);
00700 }
00701
00702
00705 UNIV_INTERN
00706 ibool
00707 buf_LRU_search_and_free_block(
00708
00709 buf_pool_t* buf_pool,
00711 ulint n_iterations)
00720 {
00721 ibool freed = FALSE;
00722
00723 buf_pool_mutex_enter(buf_pool);
00724
00725 freed = buf_LRU_free_from_unzip_LRU_list(buf_pool, n_iterations);
00726
00727 if (!freed) {
00728 freed = buf_LRU_free_from_common_LRU_list(
00729 buf_pool, n_iterations);
00730 }
00731
00732 if (!freed) {
00733 buf_pool->LRU_flush_ended = 0;
00734 } else if (buf_pool->LRU_flush_ended > 0) {
00735 buf_pool->LRU_flush_ended--;
00736 }
00737
00738 buf_pool_mutex_exit(buf_pool);
00739
00740 return(freed);
00741 }
00742
00743
00751 UNIV_INTERN
00752 void
00753 buf_LRU_try_free_flushed_blocks(
00754
00755 buf_pool_t* buf_pool)
00756 {
00757
00758 if (buf_pool == NULL) {
00759 ulint i;
00760
00761 for (i = 0; i < srv_buf_pool_instances; i++) {
00762 buf_pool = buf_pool_from_array(i);
00763 buf_LRU_try_free_flushed_blocks(buf_pool);
00764 }
00765 } else {
00766 buf_pool_mutex_enter(buf_pool);
00767
00768 while (buf_pool->LRU_flush_ended > 0) {
00769
00770 buf_pool_mutex_exit(buf_pool);
00771
00772 buf_LRU_search_and_free_block(buf_pool, 1);
00773
00774 buf_pool_mutex_enter(buf_pool);
00775 }
00776
00777 buf_pool_mutex_exit(buf_pool);
00778 }
00779 }
00780
00781
00786 UNIV_INTERN
00787 ibool
00788 buf_LRU_buf_pool_running_out(void)
00789
00790 {
00791 ulint i;
00792 ibool ret = FALSE;
00793
00794 for (i = 0; i < srv_buf_pool_instances && !ret; i++) {
00795 buf_pool_t* buf_pool;
00796
00797 buf_pool = buf_pool_from_array(i);
00798
00799 buf_pool_mutex_enter(buf_pool);
00800
00801 if (!recv_recovery_on
00802 && UT_LIST_GET_LEN(buf_pool->free)
00803 + UT_LIST_GET_LEN(buf_pool->LRU)
00804 < buf_pool->curr_size / 4) {
00805
00806 ret = TRUE;
00807 }
00808
00809 buf_pool_mutex_exit(buf_pool);
00810 }
00811
00812 return(ret);
00813 }
00814
00815
00819 UNIV_INTERN
00820 buf_block_t*
00821 buf_LRU_get_free_only(
00822
00823 buf_pool_t* buf_pool)
00824 {
00825 buf_block_t* block;
00826
00827 ut_ad(buf_pool_mutex_own(buf_pool));
00828
00829 block = (buf_block_t*) UT_LIST_GET_FIRST(buf_pool->free);
00830
00831 if (block) {
00832
00833 ut_ad(block->page.in_free_list);
00834 ut_d(block->page.in_free_list = FALSE);
00835 ut_ad(!block->page.in_flush_list);
00836 ut_ad(!block->page.in_LRU_list);
00837 ut_a(!buf_page_in_file(&block->page));
00838 UT_LIST_REMOVE(list, buf_pool->free, (&block->page));
00839
00840 mutex_enter(&block->mutex);
00841
00842 buf_block_set_state(block, BUF_BLOCK_READY_FOR_USE);
00843 UNIV_MEM_ALLOC(block->frame, UNIV_PAGE_SIZE);
00844
00845 ut_ad(buf_pool_from_block(block) == buf_pool);
00846
00847 mutex_exit(&block->mutex);
00848 }
00849
00850 return(block);
00851 }
00852
00853
00858 UNIV_INTERN
00859 buf_block_t*
00860 buf_LRU_get_free_block(
00861
00862 buf_pool_t* buf_pool,
00863 ulint zip_size)
00865 {
00866 buf_block_t* block = NULL;
00867 ibool freed;
00868 ulint n_iterations = 1;
00869 ibool mon_value_was = FALSE;
00870 ibool started_monitor = FALSE;
00871 loop:
00872 buf_pool_mutex_enter(buf_pool);
00873
00874 if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
00875 + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->curr_size / 20) {
00876 ut_print_timestamp(stderr);
00877
00878 fprintf(stderr,
00879 " InnoDB: ERROR: over 95 percent of the buffer pool"
00880 " is occupied by\n"
00881 "InnoDB: lock heaps or the adaptive hash index!"
00882 " Check that your\n"
00883 "InnoDB: transactions do not set too many row locks.\n"
00884 "InnoDB: Your buffer pool size is %lu MB."
00885 " Maybe you should make\n"
00886 "InnoDB: the buffer pool bigger?\n"
00887 "InnoDB: We intentionally generate a seg fault"
00888 " to print a stack trace\n"
00889 "InnoDB: on Linux!\n",
00890 (ulong) (buf_pool->curr_size
00891 / (1024 * 1024 / UNIV_PAGE_SIZE)));
00892
00893 ut_error;
00894
00895 } else if (!recv_recovery_on
00896 && (UT_LIST_GET_LEN(buf_pool->free)
00897 + UT_LIST_GET_LEN(buf_pool->LRU))
00898 < buf_pool->curr_size / 3) {
00899
00900 if (!buf_lru_switched_on_innodb_mon) {
00901
00902
00903
00904
00905
00906 ut_print_timestamp(stderr);
00907 fprintf(stderr,
00908 " InnoDB: WARNING: over 67 percent of"
00909 " the buffer pool is occupied by\n"
00910 "InnoDB: lock heaps or the adaptive"
00911 " hash index! Check that your\n"
00912 "InnoDB: transactions do not set too many"
00913 " row locks.\n"
00914 "InnoDB: Your buffer pool size is %lu MB."
00915 " Maybe you should make\n"
00916 "InnoDB: the buffer pool bigger?\n"
00917 "InnoDB: Starting the InnoDB Monitor to print"
00918 " diagnostics, including\n"
00919 "InnoDB: lock heap and hash index sizes.\n",
00920 (ulong) (buf_pool->curr_size
00921 / (1024 * 1024 / UNIV_PAGE_SIZE)));
00922
00923 buf_lru_switched_on_innodb_mon = TRUE;
00924 srv_print_innodb_monitor = TRUE;
00925 os_event_set(srv_lock_timeout_thread_event);
00926 }
00927 } else if (buf_lru_switched_on_innodb_mon) {
00928
00929
00930
00931
00932
00933
00934 buf_lru_switched_on_innodb_mon = FALSE;
00935 srv_print_innodb_monitor = FALSE;
00936 }
00937
00938
00939 block = buf_LRU_get_free_only(buf_pool);
00940 if (block) {
00941
00942 ut_ad(buf_pool_from_block(block) == buf_pool);
00943
00944 #ifdef UNIV_DEBUG
00945 block->page.zip.m_start =
00946 #endif
00947 block->page.zip.m_end =
00948 block->page.zip.m_nonempty =
00949 block->page.zip.n_blobs = 0;
00950
00951 if (UNIV_UNLIKELY(zip_size)) {
00952 ibool lru;
00953 page_zip_set_size(&block->page.zip, zip_size);
00954
00955 block->page.zip.data = static_cast<unsigned char *>(buf_buddy_alloc(
00956 buf_pool, zip_size, &lru));
00957
00958 UNIV_MEM_DESC(block->page.zip.data, zip_size, block);
00959 } else {
00960 page_zip_set_size(&block->page.zip, 0);
00961 block->page.zip.data = NULL;
00962 }
00963
00964 buf_pool_mutex_exit(buf_pool);
00965
00966 if (started_monitor) {
00967 srv_print_innodb_monitor = mon_value_was;
00968 }
00969
00970 return(block);
00971 }
00972
00973
00974
00975
00976 buf_pool_mutex_exit(buf_pool);
00977
00978 freed = buf_LRU_search_and_free_block(buf_pool, n_iterations);
00979
00980 if (freed > 0) {
00981 goto loop;
00982 }
00983
00984 if (n_iterations > 30) {
00985 ut_print_timestamp(stderr);
00986 fprintf(stderr,
00987 " InnoDB: Warning: difficult to find free blocks in\n"
00988 "InnoDB: the buffer pool (%lu search iterations)!"
00989 " Consider\n"
00990 "InnoDB: increasing the buffer pool size.\n"
00991 "InnoDB: It is also possible that"
00992 " in your Unix version\n"
00993 "InnoDB: fsync is very slow, or"
00994 " completely frozen inside\n"
00995 "InnoDB: the OS kernel. Then upgrading to"
00996 " a newer version\n"
00997 "InnoDB: of your operating system may help."
00998 " Look at the\n"
00999 "InnoDB: number of fsyncs in diagnostic info below.\n"
01000 "InnoDB: Pending flushes (fsync) log: %lu;"
01001 " buffer pool: %lu\n"
01002 "InnoDB: %lu OS file reads, %lu OS file writes,"
01003 " %lu OS fsyncs\n"
01004 "InnoDB: Starting InnoDB Monitor to print further\n"
01005 "InnoDB: diagnostics to the standard output.\n",
01006 (ulong) n_iterations,
01007 (ulong) fil_n_pending_log_flushes,
01008 (ulong) fil_n_pending_tablespace_flushes,
01009 (ulong) os_n_file_reads, (ulong) os_n_file_writes,
01010 (ulong) os_n_fsyncs);
01011
01012 mon_value_was = srv_print_innodb_monitor;
01013 started_monitor = TRUE;
01014 srv_print_innodb_monitor = TRUE;
01015 os_event_set(srv_lock_timeout_thread_event);
01016 }
01017
01018
01019
01020 buf_flush_free_margin(buf_pool);
01021 ++srv_buf_pool_wait_free;
01022
01023 os_aio_simulated_wake_handler_threads();
01024
01025 buf_pool_mutex_enter(buf_pool);
01026
01027 if (buf_pool->LRU_flush_ended > 0) {
01028
01029
01030
01031
01032 buf_pool_mutex_exit(buf_pool);
01033
01034 buf_LRU_try_free_flushed_blocks(buf_pool);
01035 } else {
01036 buf_pool_mutex_exit(buf_pool);
01037 }
01038
01039 if (n_iterations > 10) {
01040
01041 os_thread_sleep(500000);
01042 }
01043
01044 n_iterations++;
01045
01046 goto loop;
01047 }
01048
01049
01052 UNIV_INLINE
01053 void
01054 buf_LRU_old_adjust_len(
01055
01056 buf_pool_t* buf_pool)
01057 {
01058 ulint old_len;
01059 ulint new_len;
01060
01061 ut_a(buf_pool->LRU_old);
01062 ut_ad(buf_pool_mutex_own(buf_pool));
01063 ut_ad(buf_pool->LRU_old_ratio >= BUF_LRU_OLD_RATIO_MIN);
01064 ut_ad(buf_pool->LRU_old_ratio <= BUF_LRU_OLD_RATIO_MAX);
01065 #if BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)
01066 # error "BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)"
01067 #endif
01068 #ifdef UNIV_LRU_DEBUG
01069
01070
01071 ut_a(buf_pool->LRU_old->old);
01072 ut_a(!UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)
01073 || !UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)->old);
01074 ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)
01075 || UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old);
01076 #endif
01077
01078 old_len = buf_pool->LRU_old_len;
01079 new_len = ut_min(UT_LIST_GET_LEN(buf_pool->LRU)
01080 * buf_pool->LRU_old_ratio / BUF_LRU_OLD_RATIO_DIV,
01081 UT_LIST_GET_LEN(buf_pool->LRU)
01082 - (BUF_LRU_OLD_TOLERANCE
01083 + BUF_LRU_NON_OLD_MIN_LEN));
01084
01085 for (;;) {
01086 buf_page_t* LRU_old = buf_pool->LRU_old;
01087
01088 ut_a(LRU_old);
01089 ut_ad(LRU_old->in_LRU_list);
01090 #ifdef UNIV_LRU_DEBUG
01091 ut_a(LRU_old->old);
01092 #endif
01093
01094
01095
01096 if (old_len + BUF_LRU_OLD_TOLERANCE < new_len) {
01097
01098 buf_pool->LRU_old = LRU_old = UT_LIST_GET_PREV(
01099 LRU, LRU_old);
01100 #ifdef UNIV_LRU_DEBUG
01101 ut_a(!LRU_old->old);
01102 #endif
01103 old_len = ++buf_pool->LRU_old_len;
01104 buf_page_set_old(LRU_old, TRUE);
01105
01106 } else if (old_len > new_len + BUF_LRU_OLD_TOLERANCE) {
01107
01108 buf_pool->LRU_old = UT_LIST_GET_NEXT(LRU, LRU_old);
01109 old_len = --buf_pool->LRU_old_len;
01110 buf_page_set_old(LRU_old, FALSE);
01111 } else {
01112 return;
01113 }
01114 }
01115 }
01116
01117
01120 static
01121 void
01122 buf_LRU_old_init(
01123
01124 buf_pool_t* buf_pool)
01125 {
01126 buf_page_t* bpage;
01127
01128 ut_ad(buf_pool_mutex_own(buf_pool));
01129 ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);
01130
01131
01132
01133
01134
01135 for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); bpage != NULL;
01136 bpage = UT_LIST_GET_PREV(LRU, bpage)) {
01137 ut_ad(bpage->in_LRU_list);
01138 ut_ad(buf_page_in_file(bpage));
01139
01140
01141 bpage->old = TRUE;
01142 }
01143
01144 buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU);
01145 buf_pool->LRU_old_len = UT_LIST_GET_LEN(buf_pool->LRU);
01146
01147 buf_LRU_old_adjust_len(buf_pool);
01148 }
01149
01150
01152 static
01153 void
01154 buf_unzip_LRU_remove_block_if_needed(
01155
01156 buf_page_t* bpage)
01157 {
01158 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
01159
01160 ut_ad(buf_pool);
01161 ut_ad(bpage);
01162 ut_ad(buf_page_in_file(bpage));
01163 ut_ad(buf_pool_mutex_own(buf_pool));
01164
01165 if (buf_page_belongs_to_unzip_LRU(bpage)) {
01166 buf_block_t* block = (buf_block_t*) bpage;
01167
01168 ut_ad(block->in_unzip_LRU_list);
01169 ut_d(block->in_unzip_LRU_list = FALSE);
01170
01171 UT_LIST_REMOVE(unzip_LRU, buf_pool->unzip_LRU, block);
01172 }
01173 }
01174
01175
01177 UNIV_INLINE
01178 void
01179 buf_LRU_remove_block(
01180
01181 buf_page_t* bpage)
01182 {
01183 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
01184
01185 ut_ad(buf_pool);
01186 ut_ad(bpage);
01187 ut_ad(buf_pool_mutex_own(buf_pool));
01188
01189 ut_a(buf_page_in_file(bpage));
01190
01191 ut_ad(bpage->in_LRU_list);
01192
01193
01194
01195
01196 if (UNIV_UNLIKELY(bpage == buf_pool->LRU_old)) {
01197
01198
01199
01200
01201
01202
01203 buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
01204
01205 ut_a(prev_bpage);
01206 #ifdef UNIV_LRU_DEBUG
01207 ut_a(!prev_bpage->old);
01208 #endif
01209 buf_pool->LRU_old = prev_bpage;
01210 buf_page_set_old(prev_bpage, TRUE);
01211
01212 buf_pool->LRU_old_len++;
01213 }
01214
01215
01216 UT_LIST_REMOVE(LRU, buf_pool->LRU, bpage);
01217 ut_d(bpage->in_LRU_list = FALSE);
01218
01219 buf_unzip_LRU_remove_block_if_needed(bpage);
01220
01221
01222
01223 if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) {
01224
01225 for (bpage = UT_LIST_GET_FIRST(buf_pool->LRU); bpage != NULL;
01226 bpage = UT_LIST_GET_NEXT(LRU, bpage)) {
01227
01228
01229 bpage->old = FALSE;
01230 }
01231
01232 buf_pool->LRU_old = NULL;
01233 buf_pool->LRU_old_len = 0;
01234
01235 return;
01236 }
01237
01238 ut_ad(buf_pool->LRU_old);
01239
01240
01241 if (buf_page_is_old(bpage)) {
01242
01243 buf_pool->LRU_old_len--;
01244 }
01245
01246
01247 buf_LRU_old_adjust_len(buf_pool);
01248 }
01249
01250
01252 UNIV_INTERN
01253 void
01254 buf_unzip_LRU_add_block(
01255
01256 buf_block_t* block,
01257 ibool old)
01259 {
01260 buf_pool_t* buf_pool = buf_pool_from_block(block);
01261
01262 ut_ad(buf_pool);
01263 ut_ad(block);
01264 ut_ad(buf_pool_mutex_own(buf_pool));
01265
01266 ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
01267
01268 ut_ad(!block->in_unzip_LRU_list);
01269 ut_d(block->in_unzip_LRU_list = TRUE);
01270
01271 if (old) {
01272 UT_LIST_ADD_LAST(unzip_LRU, buf_pool->unzip_LRU, block);
01273 } else {
01274 UT_LIST_ADD_FIRST(unzip_LRU, buf_pool->unzip_LRU, block);
01275 }
01276 }
01277
01278
01280 UNIV_INLINE
01281 void
01282 buf_LRU_add_block_to_end_low(
01283
01284 buf_page_t* bpage)
01285 {
01286 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
01287
01288 ut_ad(buf_pool);
01289 ut_ad(bpage);
01290 ut_ad(buf_pool_mutex_own(buf_pool));
01291
01292 ut_a(buf_page_in_file(bpage));
01293
01294 ut_ad(!bpage->in_LRU_list);
01295 UT_LIST_ADD_LAST(LRU, buf_pool->LRU, bpage);
01296 ut_d(bpage->in_LRU_list = TRUE);
01297
01298 if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
01299
01300 ut_ad(buf_pool->LRU_old);
01301
01302
01303
01304 buf_page_set_old(bpage, TRUE);
01305 buf_pool->LRU_old_len++;
01306 buf_LRU_old_adjust_len(buf_pool);
01307
01308 } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
01309
01310
01311
01312
01313 buf_LRU_old_init(buf_pool);
01314 } else {
01315 buf_page_set_old(bpage, buf_pool->LRU_old != NULL);
01316 }
01317
01318
01319
01320 if (buf_page_belongs_to_unzip_LRU(bpage)) {
01321 buf_unzip_LRU_add_block((buf_block_t*) bpage, TRUE);
01322 }
01323 }
01324
01325
01327 UNIV_INLINE
01328 void
01329 buf_LRU_add_block_low(
01330
01331 buf_page_t* bpage,
01332 ibool old)
01336 {
01337 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
01338
01339 ut_ad(buf_pool);
01340 ut_ad(bpage);
01341 ut_ad(buf_pool_mutex_own(buf_pool));
01342
01343 ut_a(buf_page_in_file(bpage));
01344 ut_ad(!bpage->in_LRU_list);
01345
01346 if (!old || (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN)) {
01347
01348 UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, bpage);
01349
01350 bpage->freed_page_clock = buf_pool->freed_page_clock;
01351 } else {
01352 #ifdef UNIV_LRU_DEBUG
01353
01354
01355 ut_a(buf_pool->LRU_old->old);
01356 ut_a(!UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)
01357 || !UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)->old);
01358 ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)
01359 || UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old);
01360 #endif
01361 UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU, buf_pool->LRU_old,
01362 bpage);
01363 buf_pool->LRU_old_len++;
01364 }
01365
01366 ut_d(bpage->in_LRU_list = TRUE);
01367
01368 if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
01369
01370 ut_ad(buf_pool->LRU_old);
01371
01372
01373
01374 buf_page_set_old(bpage, old);
01375 buf_LRU_old_adjust_len(buf_pool);
01376
01377 } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
01378
01379
01380
01381
01382 buf_LRU_old_init(buf_pool);
01383 } else {
01384 buf_page_set_old(bpage, buf_pool->LRU_old != NULL);
01385 }
01386
01387
01388
01389 if (buf_page_belongs_to_unzip_LRU(bpage)) {
01390 buf_unzip_LRU_add_block((buf_block_t*) bpage, old);
01391 }
01392 }
01393
01394
01396 UNIV_INTERN
01397 void
01398 buf_LRU_add_block(
01399
01400 buf_page_t* bpage,
01401 ibool old)
01406 {
01407 buf_LRU_add_block_low(bpage, old);
01408 }
01409
01410
01412 UNIV_INTERN
01413 void
01414 buf_LRU_make_block_young(
01415
01416 buf_page_t* bpage)
01417 {
01418 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
01419
01420 ut_ad(buf_pool_mutex_own(buf_pool));
01421
01422 if (bpage->old) {
01423 buf_pool->stat.n_pages_made_young++;
01424 }
01425
01426 buf_LRU_remove_block(bpage);
01427 buf_LRU_add_block_low(bpage, FALSE);
01428 }
01429
01430
01432 UNIV_INTERN
01433 void
01434 buf_LRU_make_block_old(
01435
01436 buf_page_t* bpage)
01437 {
01438 buf_LRU_remove_block(bpage);
01439 buf_LRU_add_block_to_end_low(bpage);
01440 }
01441
01442
01455 UNIV_INTERN
01456 enum buf_lru_free_block_status
01457 buf_LRU_free_block(
01458
01459 buf_page_t* bpage,
01460 ibool zip,
01462 ibool* buf_pool_mutex_released)
01466 {
01467 buf_page_t* b = NULL;
01468 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
01469 mutex_t* block_mutex = buf_page_get_mutex(bpage);
01470
01471 ut_ad(buf_pool_mutex_own(buf_pool));
01472 ut_ad(mutex_own(block_mutex));
01473 ut_ad(buf_page_in_file(bpage));
01474 ut_ad(bpage->in_LRU_list);
01475 ut_ad(!bpage->in_flush_list == !bpage->oldest_modification);
01476 #if UNIV_WORD_SIZE == 4
01477
01478
01479
01480 UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
01481 #endif
01482
01483 if (!buf_page_can_relocate(bpage)) {
01484
01485
01486 return(BUF_LRU_NOT_FREED);
01487 }
01488
01489 #ifdef UNIV_IBUF_COUNT_DEBUG
01490 ut_a(ibuf_count_get(bpage->space, bpage->offset) == 0);
01491 #endif
01492
01493 if (zip || !bpage->zip.data) {
01494
01495
01496
01497 if (bpage->oldest_modification) {
01498 return(BUF_LRU_NOT_FREED);
01499 }
01500 } else if (bpage->oldest_modification) {
01501
01502
01503 if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
01504 ut_ad(buf_page_get_state(bpage)
01505 == BUF_BLOCK_ZIP_DIRTY);
01506 return(BUF_LRU_NOT_FREED);
01507 }
01508
01509 goto alloc;
01510 } else if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) {
01511
01512
01513
01514 alloc:
01515 buf_pool_mutex_exit_forbid(buf_pool);
01516 b = static_cast<buf_page_t *>(buf_buddy_alloc(buf_pool, sizeof *b, NULL));
01517 buf_pool_mutex_exit_allow(buf_pool);
01518
01519 if (UNIV_UNLIKELY(!b)) {
01520 return(BUF_LRU_CANNOT_RELOCATE);
01521 }
01522
01523 memcpy(b, bpage, sizeof *b);
01524 }
01525
01526 #ifdef UNIV_DEBUG
01527 if (buf_debug_prints) {
01528 fprintf(stderr, "Putting space %lu page %lu to free list\n",
01529 (ulong) buf_page_get_space(bpage),
01530 (ulong) buf_page_get_page_no(bpage));
01531 }
01532 #endif
01533
01534 if (buf_LRU_block_remove_hashed_page(bpage, zip)
01535 != BUF_BLOCK_ZIP_FREE) {
01536 ut_a(bpage->buf_fix_count == 0);
01537
01538 if (b) {
01539 buf_page_t* hash_b;
01540 buf_page_t* prev_b = UT_LIST_GET_PREV(LRU, b);
01541
01542 const ulint fold = buf_page_address_fold(
01543 bpage->space, bpage->offset);
01544
01545 hash_b = buf_page_hash_get_low(
01546 buf_pool, bpage->space, bpage->offset, fold);
01547
01548 ut_a(!hash_b);
01549
01550 b->state = b->oldest_modification
01551 ? BUF_BLOCK_ZIP_DIRTY
01552 : BUF_BLOCK_ZIP_PAGE;
01553 UNIV_MEM_DESC(b->zip.data,
01554 page_zip_get_size(&b->zip), b);
01555
01556
01557
01558
01559
01560
01561 ut_ad(!bpage->in_page_hash);
01562 ut_ad(!bpage->in_LRU_list);
01563
01564
01565 ut_ad(!((buf_block_t*) bpage)->in_unzip_LRU_list);
01566
01567
01568
01569 ut_ad(!b->in_zip_hash);
01570 ut_ad(b->in_page_hash);
01571 ut_ad(b->in_LRU_list);
01572
01573 HASH_INSERT(buf_page_t, hash,
01574 buf_pool->page_hash, fold, b);
01575
01576
01577 if (UNIV_LIKELY(prev_b != NULL)) {
01578 ulint lru_len;
01579
01580 ut_ad(prev_b->in_LRU_list);
01581 ut_ad(buf_page_in_file(prev_b));
01582 #if UNIV_WORD_SIZE == 4
01583
01584
01585
01586
01587 UNIV_MEM_ASSERT_RW(prev_b, sizeof *prev_b);
01588 #endif
01589 UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU,
01590 prev_b, b);
01591
01592 if (buf_page_is_old(b)) {
01593 buf_pool->LRU_old_len++;
01594 if (UNIV_UNLIKELY
01595 (buf_pool->LRU_old
01596 == UT_LIST_GET_NEXT(LRU, b))) {
01597
01598 buf_pool->LRU_old = b;
01599 }
01600 }
01601
01602 lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
01603
01604 if (lru_len > BUF_LRU_OLD_MIN_LEN) {
01605 ut_ad(buf_pool->LRU_old);
01606
01607
01608 buf_LRU_old_adjust_len(buf_pool);
01609 } else if (lru_len == BUF_LRU_OLD_MIN_LEN) {
01610
01611
01612
01613 buf_LRU_old_init(buf_pool);
01614 }
01615 #ifdef UNIV_LRU_DEBUG
01616
01617
01618 buf_page_set_old(b, buf_page_is_old(b));
01619 #endif
01620 } else {
01621 ut_d(b->in_LRU_list = FALSE);
01622 buf_LRU_add_block_low(b, buf_page_is_old(b));
01623 }
01624
01625 if (b->state == BUF_BLOCK_ZIP_PAGE) {
01626 buf_LRU_insert_zip_clean(b);
01627 } else {
01628
01629 buf_flush_relocate_on_flush_list(bpage, b);
01630 }
01631
01632 bpage->zip.data = NULL;
01633 page_zip_set_size(&bpage->zip, 0);
01634
01635
01636
01637
01638 b->buf_fix_count++;
01639 b->io_fix = BUF_IO_READ;
01640 }
01641
01642 if (buf_pool_mutex_released) {
01643 *buf_pool_mutex_released = TRUE;
01644 }
01645
01646 buf_pool_mutex_exit(buf_pool);
01647 mutex_exit(block_mutex);
01648
01649
01650
01651
01652
01653
01654
01655 UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
01656 UNIV_PAGE_SIZE);
01657 btr_search_drop_page_hash_index((buf_block_t*) bpage);
01658 UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
01659 UNIV_PAGE_SIZE);
01660
01661 if (b) {
01662
01663
01664
01665
01666
01667
01668
01669 mach_write_to_4(
01670 b->zip.data + FIL_PAGE_SPACE_OR_CHKSUM,
01671 UNIV_LIKELY(srv_use_checksums)
01672 ? page_zip_calc_checksum(
01673 b->zip.data,
01674 page_zip_get_size(&b->zip))
01675 : BUF_NO_CHECKSUM_MAGIC);
01676 }
01677
01678 buf_pool_mutex_enter(buf_pool);
01679 mutex_enter(block_mutex);
01680
01681 if (b) {
01682 mutex_enter(&buf_pool->zip_mutex);
01683 b->buf_fix_count--;
01684 buf_page_set_io_fix(b, BUF_IO_NONE);
01685 mutex_exit(&buf_pool->zip_mutex);
01686 }
01687
01688 buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
01689 } else {
01690
01691
01692
01693 ut_ad(block_mutex == &buf_pool->zip_mutex);
01694 mutex_enter(block_mutex);
01695 }
01696
01697 return(BUF_LRU_FREED);
01698 }
01699
01700
01702 UNIV_INTERN
01703 void
01704 buf_LRU_block_free_non_file_page(
01705
01706 buf_block_t* block)
01707 {
01708 void* data;
01709 buf_pool_t* buf_pool = buf_pool_from_block(block);
01710
01711 ut_ad(block);
01712 ut_ad(buf_pool_mutex_own(buf_pool));
01713 ut_ad(mutex_own(&block->mutex));
01714
01715 switch (buf_block_get_state(block)) {
01716 case BUF_BLOCK_MEMORY:
01717 case BUF_BLOCK_READY_FOR_USE:
01718 break;
01719 default:
01720 ut_error;
01721 }
01722
01723 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
01724 ut_a(block->n_pointers == 0);
01725 #endif
01726 ut_ad(!block->page.in_free_list);
01727 ut_ad(!block->page.in_flush_list);
01728 ut_ad(!block->page.in_LRU_list);
01729
01730 buf_block_set_state(block, BUF_BLOCK_NOT_USED);
01731
01732 UNIV_MEM_ALLOC(block->frame, UNIV_PAGE_SIZE);
01733 #ifdef UNIV_DEBUG
01734
01735 memset(block->frame, '\0', UNIV_PAGE_SIZE);
01736 #else
01737
01738 memset(block->frame + FIL_PAGE_OFFSET, 0xfe, 4);
01739 memset(block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xfe, 4);
01740 #endif
01741 data = block->page.zip.data;
01742
01743 if (data) {
01744 block->page.zip.data = NULL;
01745 mutex_exit(&block->mutex);
01746 buf_pool_mutex_exit_forbid(buf_pool);
01747
01748 buf_buddy_free(
01749 buf_pool, data, page_zip_get_size(&block->page.zip));
01750
01751 buf_pool_mutex_exit_allow(buf_pool);
01752 mutex_enter(&block->mutex);
01753 page_zip_set_size(&block->page.zip, 0);
01754 }
01755
01756 UT_LIST_ADD_FIRST(list, buf_pool->free, (&block->page));
01757 ut_d(block->page.in_free_list = TRUE);
01758
01759 UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE);
01760 }
01761
01762
01772 static
01773 enum buf_page_state
01774 buf_LRU_block_remove_hashed_page(
01775
01776 buf_page_t* bpage,
01779 ibool zip)
01781 {
01782 ulint fold;
01783 const buf_page_t* hashed_bpage;
01784 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
01785
01786 ut_ad(bpage);
01787 ut_ad(buf_pool_mutex_own(buf_pool));
01788 ut_ad(mutex_own(buf_page_get_mutex(bpage)));
01789
01790 ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
01791 ut_a(bpage->buf_fix_count == 0);
01792
01793 #if UNIV_WORD_SIZE == 4
01794
01795
01796
01797 UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
01798 #endif
01799
01800 buf_LRU_remove_block(bpage);
01801
01802 buf_pool->freed_page_clock += 1;
01803
01804 switch (buf_page_get_state(bpage)) {
01805 case BUF_BLOCK_FILE_PAGE:
01806 UNIV_MEM_ASSERT_W(bpage, sizeof(buf_block_t));
01807 UNIV_MEM_ASSERT_W(((buf_block_t*) bpage)->frame,
01808 UNIV_PAGE_SIZE);
01809 buf_block_modify_clock_inc((buf_block_t*) bpage);
01810 if (bpage->zip.data) {
01811 const page_t* page = ((buf_block_t*) bpage)->frame;
01812 const ulint zip_size
01813 = page_zip_get_size(&bpage->zip);
01814
01815 ut_a(!zip || bpage->oldest_modification == 0);
01816
01817 switch (UNIV_EXPECT(fil_page_get_type(page),
01818 FIL_PAGE_INDEX)) {
01819 case FIL_PAGE_TYPE_ALLOCATED:
01820 case FIL_PAGE_INODE:
01821 case FIL_PAGE_IBUF_BITMAP:
01822 case FIL_PAGE_TYPE_FSP_HDR:
01823 case FIL_PAGE_TYPE_XDES:
01824
01825 if (!zip) {
01826
01827
01828
01829
01830 memcpy(bpage->zip.data, page,
01831 zip_size);
01832 }
01833 break;
01834 case FIL_PAGE_TYPE_ZBLOB:
01835 case FIL_PAGE_TYPE_ZBLOB2:
01836 break;
01837 case FIL_PAGE_INDEX:
01838 #ifdef UNIV_ZIP_DEBUG
01839 ut_a(page_zip_validate(&bpage->zip, page));
01840 #endif
01841 break;
01842 default:
01843 ut_print_timestamp(stderr);
01844 fputs(" InnoDB: ERROR: The compressed page"
01845 " to be evicted seems corrupt:", stderr);
01846 ut_print_buf(stderr, page, zip_size);
01847 fputs("\nInnoDB: Possibly older version"
01848 " of the page:", stderr);
01849 ut_print_buf(stderr, bpage->zip.data,
01850 zip_size);
01851 putc('\n', stderr);
01852 ut_error;
01853 }
01854
01855 break;
01856 }
01857
01858 case BUF_BLOCK_ZIP_PAGE:
01859 ut_a(bpage->oldest_modification == 0);
01860 UNIV_MEM_ASSERT_W(bpage->zip.data,
01861 page_zip_get_size(&bpage->zip));
01862 break;
01863 case BUF_BLOCK_ZIP_FREE:
01864 case BUF_BLOCK_ZIP_DIRTY:
01865 case BUF_BLOCK_NOT_USED:
01866 case BUF_BLOCK_READY_FOR_USE:
01867 case BUF_BLOCK_MEMORY:
01868 case BUF_BLOCK_REMOVE_HASH:
01869 ut_error;
01870 break;
01871 }
01872
01873 fold = buf_page_address_fold(bpage->space, bpage->offset);
01874 hashed_bpage = buf_page_hash_get_low(
01875 buf_pool, bpage->space, bpage->offset, fold);
01876
01877 if (UNIV_UNLIKELY(bpage != hashed_bpage)) {
01878 fprintf(stderr,
01879 "InnoDB: Error: page %lu %lu not found"
01880 " in the hash table\n",
01881 (ulong) bpage->space,
01882 (ulong) bpage->offset);
01883 if (hashed_bpage) {
01884 fprintf(stderr,
01885 "InnoDB: In hash table we find block"
01886 " %p of %lu %lu which is not %p\n",
01887 (const void*) hashed_bpage,
01888 (ulong) hashed_bpage->space,
01889 (ulong) hashed_bpage->offset,
01890 (const void*) bpage);
01891 }
01892
01893 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
01894 mutex_exit(buf_page_get_mutex(bpage));
01895 buf_pool_mutex_exit(buf_pool);
01896 buf_print();
01897 buf_LRU_print();
01898 buf_validate();
01899 buf_LRU_validate();
01900 #endif
01901 ut_error;
01902 }
01903
01904 ut_ad(!bpage->in_zip_hash);
01905 ut_ad(bpage->in_page_hash);
01906 ut_d(bpage->in_page_hash = FALSE);
01907 HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
01908 switch (buf_page_get_state(bpage)) {
01909 case BUF_BLOCK_ZIP_PAGE:
01910 ut_ad(!bpage->in_free_list);
01911 ut_ad(!bpage->in_flush_list);
01912 ut_ad(!bpage->in_LRU_list);
01913 ut_a(bpage->zip.data);
01914 ut_a(buf_page_get_zip_size(bpage));
01915
01916 UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
01917
01918 mutex_exit(&buf_pool->zip_mutex);
01919 buf_pool_mutex_exit_forbid(buf_pool);
01920
01921 buf_buddy_free(
01922 buf_pool, bpage->zip.data,
01923 page_zip_get_size(&bpage->zip));
01924
01925 buf_buddy_free(buf_pool, bpage, sizeof(*bpage));
01926 buf_pool_mutex_exit_allow(buf_pool);
01927
01928 UNIV_MEM_UNDESC(bpage);
01929 return(BUF_BLOCK_ZIP_FREE);
01930
01931 case BUF_BLOCK_FILE_PAGE:
01932 memset(((buf_block_t*) bpage)->frame
01933 + FIL_PAGE_OFFSET, 0xff, 4);
01934 memset(((buf_block_t*) bpage)->frame
01935 + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xff, 4);
01936 UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
01937 UNIV_PAGE_SIZE);
01938 buf_page_set_state(bpage, BUF_BLOCK_REMOVE_HASH);
01939
01940 if (zip && bpage->zip.data) {
01941
01942 void* data = bpage->zip.data;
01943 bpage->zip.data = NULL;
01944
01945 ut_ad(!bpage->in_free_list);
01946 ut_ad(!bpage->in_flush_list);
01947 ut_ad(!bpage->in_LRU_list);
01948 mutex_exit(&((buf_block_t*) bpage)->mutex);
01949 buf_pool_mutex_exit_forbid(buf_pool);
01950
01951 buf_buddy_free(
01952 buf_pool, data,
01953 page_zip_get_size(&bpage->zip));
01954
01955 buf_pool_mutex_exit_allow(buf_pool);
01956 mutex_enter(&((buf_block_t*) bpage)->mutex);
01957 page_zip_set_size(&bpage->zip, 0);
01958 }
01959
01960 return(BUF_BLOCK_REMOVE_HASH);
01961
01962 case BUF_BLOCK_ZIP_FREE:
01963 case BUF_BLOCK_ZIP_DIRTY:
01964 case BUF_BLOCK_NOT_USED:
01965 case BUF_BLOCK_READY_FOR_USE:
01966 case BUF_BLOCK_MEMORY:
01967 case BUF_BLOCK_REMOVE_HASH:
01968 break;
01969 }
01970
01971 ut_error;
01972 return(BUF_BLOCK_ZIP_FREE);
01973 }
01974
01975
01977 static
01978 void
01979 buf_LRU_block_free_hashed_page(
01980
01981 buf_block_t* block)
01983 {
01984 #ifdef UNIV_DEBUG
01985 buf_pool_t* buf_pool = buf_pool_from_block(block);
01986 ut_ad(buf_pool_mutex_own(buf_pool));
01987 #endif
01988 ut_ad(mutex_own(&block->mutex));
01989
01990 buf_block_set_state(block, BUF_BLOCK_MEMORY);
01991
01992 buf_LRU_block_free_non_file_page(block);
01993 }
01994
01995
01998 static
01999 uint
02000 buf_LRU_old_ratio_update_instance(
02001
02002 buf_pool_t* buf_pool,
02003 uint old_pct,
02005 ibool adjust)
02008 {
02009 uint ratio;
02010
02011 ratio = old_pct * BUF_LRU_OLD_RATIO_DIV / 100;
02012 if (ratio < BUF_LRU_OLD_RATIO_MIN) {
02013 ratio = BUF_LRU_OLD_RATIO_MIN;
02014 } else if (ratio > BUF_LRU_OLD_RATIO_MAX) {
02015 ratio = BUF_LRU_OLD_RATIO_MAX;
02016 }
02017
02018 if (adjust) {
02019 buf_pool_mutex_enter(buf_pool);
02020
02021 if (ratio != buf_pool->LRU_old_ratio) {
02022 buf_pool->LRU_old_ratio = ratio;
02023
02024 if (UT_LIST_GET_LEN(buf_pool->LRU)
02025 >= BUF_LRU_OLD_MIN_LEN) {
02026
02027 buf_LRU_old_adjust_len(buf_pool);
02028 }
02029 }
02030
02031 buf_pool_mutex_exit(buf_pool);
02032 } else {
02033 buf_pool->LRU_old_ratio = ratio;
02034 }
02035
02036
02037 return((uint) (ratio * 100 / (double) BUF_LRU_OLD_RATIO_DIV + 0.5));
02038 }
02039
02040
02043 UNIV_INTERN
02044 ulint
02045 buf_LRU_old_ratio_update(
02046
02047 uint old_pct,
02049 ibool adjust)
02052 {
02053 ulint i;
02054 ulint new_ratio = 0;
02055
02056 for (i = 0; i < srv_buf_pool_instances; i++) {
02057 buf_pool_t* buf_pool;
02058
02059 buf_pool = buf_pool_from_array(i);
02060
02061 new_ratio = buf_LRU_old_ratio_update_instance(
02062 buf_pool, old_pct, adjust);
02063 }
02064
02065 return(new_ratio);
02066 }
02067
02068
02071 UNIV_INTERN
02072 void
02073 buf_LRU_stat_update(void)
02074
02075 {
02076 ulint i;
02077 buf_LRU_stat_t* item;
02078 buf_pool_t* buf_pool;
02079 ibool evict_started = FALSE;
02080
02081
02082 for (i = 0; i < srv_buf_pool_instances; i++) {
02083
02084 buf_pool = buf_pool_from_array(i);
02085
02086 if (buf_pool->freed_page_clock != 0) {
02087 evict_started = TRUE;
02088 break;
02089 }
02090 }
02091
02092 if (!evict_started) {
02093 goto func_exit;
02094 }
02095
02096
02097 item = &buf_LRU_stat_arr[buf_LRU_stat_arr_ind];
02098 buf_LRU_stat_arr_ind++;
02099 buf_LRU_stat_arr_ind %= BUF_LRU_STAT_N_INTERVAL;
02100
02101
02102 buf_LRU_stat_sum.io += buf_LRU_stat_cur.io - item->io;
02103 buf_LRU_stat_sum.unzip += buf_LRU_stat_cur.unzip - item->unzip;
02104
02105
02106 memcpy(item, &buf_LRU_stat_cur, sizeof *item);
02107
02108 func_exit:
02109
02110 memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
02111 }
02112
02113 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
02114
02116 static
02117 void
02118 buf_LRU_validate_instance(
02119
02120 buf_pool_t* buf_pool)
02121 {
02122 buf_page_t* bpage;
02123 buf_block_t* block;
02124 ulint old_len;
02125 ulint new_len;
02126
02127 ut_ad(buf_pool);
02128 buf_pool_mutex_enter(buf_pool);
02129
02130 if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
02131
02132 ut_a(buf_pool->LRU_old);
02133 old_len = buf_pool->LRU_old_len;
02134 new_len = ut_min(UT_LIST_GET_LEN(buf_pool->LRU)
02135 * buf_pool->LRU_old_ratio
02136 / BUF_LRU_OLD_RATIO_DIV,
02137 UT_LIST_GET_LEN(buf_pool->LRU)
02138 - (BUF_LRU_OLD_TOLERANCE
02139 + BUF_LRU_NON_OLD_MIN_LEN));
02140 ut_a(old_len >= new_len - BUF_LRU_OLD_TOLERANCE);
02141 ut_a(old_len <= new_len + BUF_LRU_OLD_TOLERANCE);
02142 }
02143
02144 UT_LIST_VALIDATE(LRU, buf_page_t, buf_pool->LRU,
02145 ut_ad(ut_list_node_313->in_LRU_list));
02146
02147 bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
02148
02149 old_len = 0;
02150
02151 while (bpage != NULL) {
02152
02153 switch (buf_page_get_state(bpage)) {
02154 case BUF_BLOCK_ZIP_FREE:
02155 case BUF_BLOCK_NOT_USED:
02156 case BUF_BLOCK_READY_FOR_USE:
02157 case BUF_BLOCK_MEMORY:
02158 case BUF_BLOCK_REMOVE_HASH:
02159 ut_error;
02160 break;
02161 case BUF_BLOCK_FILE_PAGE:
02162 ut_ad(((buf_block_t*) bpage)->in_unzip_LRU_list
02163 == buf_page_belongs_to_unzip_LRU(bpage));
02164 case BUF_BLOCK_ZIP_PAGE:
02165 case BUF_BLOCK_ZIP_DIRTY:
02166 break;
02167 }
02168
02169 if (buf_page_is_old(bpage)) {
02170 const buf_page_t* prev
02171 = UT_LIST_GET_PREV(LRU, bpage);
02172 const buf_page_t* next
02173 = UT_LIST_GET_NEXT(LRU, bpage);
02174
02175 if (!old_len++) {
02176 ut_a(buf_pool->LRU_old == bpage);
02177 } else {
02178 ut_a(!prev || buf_page_is_old(prev));
02179 }
02180
02181 ut_a(!next || buf_page_is_old(next));
02182 }
02183
02184 bpage = UT_LIST_GET_NEXT(LRU, bpage);
02185 }
02186
02187 ut_a(buf_pool->LRU_old_len == old_len);
02188
02189 UT_LIST_VALIDATE(list, buf_page_t, buf_pool->free,
02190 ut_ad(ut_list_node_313->in_free_list));
02191
02192 for (bpage = UT_LIST_GET_FIRST(buf_pool->free);
02193 bpage != NULL;
02194 bpage = UT_LIST_GET_NEXT(list, bpage)) {
02195
02196 ut_a(buf_page_get_state(bpage) == BUF_BLOCK_NOT_USED);
02197 }
02198
02199 UT_LIST_VALIDATE(unzip_LRU, buf_block_t, buf_pool->unzip_LRU,
02200 ut_ad(ut_list_node_313->in_unzip_LRU_list
02201 && ut_list_node_313->page.in_LRU_list));
02202
02203 for (block = UT_LIST_GET_FIRST(buf_pool->unzip_LRU);
02204 block;
02205 block = UT_LIST_GET_NEXT(unzip_LRU, block)) {
02206
02207 ut_ad(block->in_unzip_LRU_list);
02208 ut_ad(block->page.in_LRU_list);
02209 ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
02210 }
02211
02212 buf_pool_mutex_exit(buf_pool);
02213 }
02214
02215
02218 UNIV_INTERN
02219 ibool
02220 buf_LRU_validate(void)
02221
02222 {
02223 ulint i;
02224
02225 for (i = 0; i < srv_buf_pool_instances; i++) {
02226 buf_pool_t* buf_pool;
02227
02228 buf_pool = buf_pool_from_array(i);
02229 buf_LRU_validate_instance(buf_pool);
02230 }
02231
02232 return(TRUE);
02233 }
02234 #endif
02235
02236 #if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
02237
02239 UNIV_INTERN
02240 void
02241 buf_LRU_print_instance(
02242
02243 buf_pool_t* buf_pool)
02244 {
02245 const buf_page_t* bpage;
02246
02247 ut_ad(buf_pool);
02248 buf_pool_mutex_enter(buf_pool);
02249
02250 bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
02251
02252 while (bpage != NULL) {
02253
02254 mutex_enter(buf_page_get_mutex(bpage));
02255 fprintf(stderr, "BLOCK space %lu page %lu ",
02256 (ulong) buf_page_get_space(bpage),
02257 (ulong) buf_page_get_page_no(bpage));
02258
02259 if (buf_page_is_old(bpage)) {
02260 fputs("old ", stderr);
02261 }
02262
02263 if (bpage->buf_fix_count) {
02264 fprintf(stderr, "buffix count %lu ",
02265 (ulong) bpage->buf_fix_count);
02266 }
02267
02268 if (buf_page_get_io_fix(bpage)) {
02269 fprintf(stderr, "io_fix %lu ",
02270 (ulong) buf_page_get_io_fix(bpage));
02271 }
02272
02273 if (bpage->oldest_modification) {
02274 fputs("modif. ", stderr);
02275 }
02276
02277 switch (buf_page_get_state(bpage)) {
02278 const byte* frame;
02279 case BUF_BLOCK_FILE_PAGE:
02280 frame = buf_block_get_frame((buf_block_t*) bpage);
02281 fprintf(stderr, "\ntype %lu"
02282 " index id %llu\n",
02283 (ulong) fil_page_get_type(frame),
02284 (ullint) btr_page_get_index_id(frame));
02285 break;
02286 case BUF_BLOCK_ZIP_PAGE:
02287 frame = bpage->zip.data;
02288 fprintf(stderr, "\ntype %lu size %lu"
02289 " index id %llu\n",
02290 (ulong) fil_page_get_type(frame),
02291 (ulong) buf_page_get_zip_size(bpage),
02292 (ullint) btr_page_get_index_id(frame));
02293 break;
02294
02295 default:
02296 fprintf(stderr, "\n!state %lu!\n",
02297 (ulong) buf_page_get_state(bpage));
02298 break;
02299 }
02300
02301 mutex_exit(buf_page_get_mutex(bpage));
02302 bpage = UT_LIST_GET_NEXT(LRU, bpage);
02303 }
02304
02305 buf_pool_mutex_exit(buf_pool);
02306 }
02307
02308
02310 UNIV_INTERN
02311 void
02312 buf_LRU_print(void)
02313
02314 {
02315 ulint i;
02316 buf_pool_t* buf_pool;
02317
02318 for (i = 0; i < srv_buf_pool_instances; i++) {
02319 buf_pool = buf_pool_from_array(i);
02320 buf_LRU_print_instance(buf_pool);
02321 }
02322 }
02323 #endif