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
02115 #define LRU_DUMP_FILE "ib_lru_dump"
02116
02117 UNIV_INTERN
02118 bool
02119 buf_LRU_file_dump(void)
02120
02121 {
02122 os_file_t dump_file = -1;
02123 ibool success;
02124 byte* buffer_base = NULL;
02125 byte* buffer = NULL;
02126 buf_page_t* bpage;
02127 ulint buffers;
02128 ulint offset;
02129 bool ret = false;
02130 ulint i;
02131
02132 for (i = 0; i < srv_n_data_files; i++) {
02133 if (strstr(srv_data_file_names[i], LRU_DUMP_FILE) != NULL) {
02134 fprintf(stderr,
02135 " InnoDB: The name '%s' seems to be used for"
02136 " innodb_data_file_path. For safety, dumping of the LRU list"
02137 " is not being done.\n", LRU_DUMP_FILE);
02138 goto end;
02139 }
02140 }
02141
02142 buffer_base = static_cast<byte *>(ut_malloc(2 * UNIV_PAGE_SIZE));
02143 buffer = static_cast<byte *>(ut_align(buffer_base, UNIV_PAGE_SIZE));
02144 if (buffer == NULL) {
02145 fprintf(stderr,
02146 " InnoDB: cannot allocate buffer.\n");
02147 goto end;
02148 }
02149
02150 dump_file = os_file_create(innodb_file_temp_key, LRU_DUMP_FILE, OS_FILE_OVERWRITE,
02151 OS_FILE_NORMAL, OS_DATA_FILE, &success);
02152 if (success == FALSE) {
02153 os_file_get_last_error(TRUE);
02154 fprintf(stderr,
02155 " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
02156 goto end;
02157 }
02158
02159 buffers = offset = 0;
02160
02161 for (i = 0; i < srv_buf_pool_instances; i++) {
02162 buf_pool_t* buf_pool;
02163
02164 buf_pool = buf_pool_from_array(i);
02165
02166 buf_pool_mutex_enter(buf_pool);
02167 bpage = UT_LIST_GET_LAST(buf_pool->LRU);
02168
02169 while (bpage != NULL) {
02170 if (offset == 0) {
02171 memset(buffer, 0, UNIV_PAGE_SIZE);
02172 }
02173
02174 mach_write_to_4(buffer + offset * 4, bpage->space);
02175 offset++;
02176 mach_write_to_4(buffer + offset * 4, bpage->offset);
02177 offset++;
02178
02179 if (offset == UNIV_PAGE_SIZE/4) {
02180 success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
02181 (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
02182 (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
02183 UNIV_PAGE_SIZE);
02184 if (success == FALSE) {
02185 buf_pool_mutex_exit(buf_pool);
02186 fprintf(stderr,
02187 " InnoDB: cannot write page %lu of %s\n",
02188 buffers, LRU_DUMP_FILE);
02189 goto end;
02190 }
02191 buffers++;
02192 offset = 0;
02193 }
02194
02195 bpage = UT_LIST_GET_PREV(LRU, bpage);
02196 }
02197 buf_pool_mutex_exit(buf_pool);
02198 }
02199
02200 if (offset == 0) {
02201 memset(buffer, 0, UNIV_PAGE_SIZE);
02202 }
02203
02204 mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
02205 offset++;
02206 mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
02207 offset++;
02208
02209 success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
02210 (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
02211 (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
02212 UNIV_PAGE_SIZE);
02213 if (success == FALSE) {
02214 goto end;
02215 }
02216
02217 ret = true;
02218 end:
02219 if (dump_file != -1)
02220 os_file_close(dump_file);
02221 if (buffer_base)
02222 ut_free(buffer_base);
02223
02224 return(ret);
02225 }
02226
02227 typedef struct {
02228 ib_uint32_t space_id;
02229 ib_uint32_t page_no;
02230 } dump_record_t;
02231
02232 static int dump_record_cmp(const void *a, const void *b)
02233 {
02234 const dump_record_t *rec1 = (dump_record_t *) a;
02235 const dump_record_t *rec2 = (dump_record_t *) b;
02236
02237 if (rec1->space_id < rec2->space_id)
02238 return -1;
02239 if (rec1->space_id > rec2->space_id)
02240 return 1;
02241 if (rec1->page_no < rec2->page_no)
02242 return -1;
02243 return rec1->page_no > rec2->page_no;
02244 }
02245
02246
02248 UNIV_INTERN
02249 bool
02250 buf_LRU_file_restore(void)
02251
02252 {
02253 os_file_t dump_file = -1;
02254 ibool success;
02255 byte* buffer_base = NULL;
02256 byte* buffer = NULL;
02257 ulint buffers;
02258 ulint offset;
02259 ulint reads = 0;
02260 ulint req = 0;
02261 bool terminated = false;
02262 bool ret = false;
02263 dump_record_t* records = NULL;
02264 ulint size;
02265 ulint size_high;
02266 ulint length;
02267
02268 dump_file = os_file_create_simple_no_error_handling(innodb_file_temp_key,
02269 LRU_DUMP_FILE, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
02270 if (success == FALSE || !os_file_get_size(dump_file, &size, &size_high)) {
02271 os_file_get_last_error(TRUE);
02272 fprintf(stderr,
02273 " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
02274 goto end;
02275 }
02276 if (size == 0 || size_high > 0 || size % 8) {
02277 fprintf(stderr, " InnoDB: broken LRU dump file\n");
02278 goto end;
02279 }
02280 buffer_base = static_cast<byte *>(ut_malloc(2 * UNIV_PAGE_SIZE));
02281 buffer = static_cast<byte *>(ut_align(buffer_base, UNIV_PAGE_SIZE));
02282 records = static_cast<dump_record_t *>(ut_malloc(size));
02283 if (buffer == NULL || records == NULL) {
02284 fprintf(stderr,
02285 " InnoDB: cannot allocate buffer.\n");
02286 goto end;
02287 }
02288
02289 buffers = 0;
02290 length = 0;
02291 while (!terminated) {
02292 success = os_file_read(dump_file, buffer,
02293 (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
02294 (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
02295 UNIV_PAGE_SIZE);
02296 if (success == FALSE) {
02297 fprintf(stderr,
02298 " InnoDB: either could not read page %lu of %s,"
02299 " or terminated unexpectedly.\n",
02300 buffers, LRU_DUMP_FILE);
02301 goto end;
02302 }
02303
02304 for (offset = 0; offset < UNIV_PAGE_SIZE/4; offset += 2) {
02305 ulint space_id;
02306 ulint page_no;
02307
02308 space_id = mach_read_from_4(buffer + offset * 4);
02309 page_no = mach_read_from_4(buffer + (offset + 1) * 4);
02310 if (space_id == 0xFFFFFFFFUL
02311 || page_no == 0xFFFFFFFFUL) {
02312 terminated = true;
02313 break;
02314 }
02315
02316 records[length].space_id = space_id;
02317 records[length].page_no = page_no;
02318 length++;
02319 if (length * 8 >= size) {
02320 fprintf(stderr,
02321 " InnoDB: could not find the "
02322 "end-of-file marker after reading "
02323 "the expected %lu bytes from the "
02324 "LRU dump file.\n"
02325 " InnoDB: this could be caused by a "
02326 "broken or incomplete file.\n"
02327 " InnoDB: trying to process what has "
02328 "been read so far.\n",
02329 size);
02330 terminated = true;
02331 break;
02332 }
02333 }
02334 buffers++;
02335 }
02336
02337 qsort(records, length, sizeof(dump_record_t), dump_record_cmp);
02338
02339 for (offset = 0; offset < length; offset++) {
02340 ulint space_id;
02341 ulint page_no;
02342 ulint zip_size;
02343 ulint err;
02344 int64_t tablespace_version;
02345
02346 space_id = records[offset].space_id;
02347 page_no = records[offset].page_no;
02348
02349 if (offset % 16 == 15) {
02350 os_aio_simulated_wake_handler_threads();
02351 buf_flush_free_margins();
02352 }
02353
02354 zip_size = fil_space_get_zip_size(space_id);
02355 if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
02356 continue;
02357 }
02358
02359 if (fil_is_exist(space_id, page_no)) {
02360
02361 tablespace_version = fil_space_get_version(space_id);
02362
02363 req++;
02364 reads += buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
02365 | OS_AIO_SIMULATED_WAKE_LATER,
02366 space_id, zip_size, TRUE,
02367 tablespace_version, page_no);
02368 buf_LRU_stat_inc_io();
02369 }
02370 }
02371
02372 os_aio_simulated_wake_handler_threads();
02373 buf_flush_free_margins();
02374
02375 ut_print_timestamp(stderr);
02376 fprintf(stderr,
02377 " InnoDB: reading pages based on the dumped LRU list was done."
02378 " (requested: %lu, read: %lu)\n", req, reads);
02379 ret = true;
02380 end:
02381 if (dump_file != -1)
02382 os_file_close(dump_file);
02383 if (buffer_base)
02384 ut_free(buffer_base);
02385 if (records)
02386 ut_free(records);
02387
02388 return(ret);
02389 }
02390
02391 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
02392
02394 static
02395 void
02396 buf_LRU_validate_instance(
02397
02398 buf_pool_t* buf_pool)
02399 {
02400 buf_page_t* bpage;
02401 buf_block_t* block;
02402 ulint old_len;
02403 ulint new_len;
02404
02405 ut_ad(buf_pool);
02406 buf_pool_mutex_enter(buf_pool);
02407
02408 if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
02409
02410 ut_a(buf_pool->LRU_old);
02411 old_len = buf_pool->LRU_old_len;
02412 new_len = ut_min(UT_LIST_GET_LEN(buf_pool->LRU)
02413 * buf_pool->LRU_old_ratio
02414 / BUF_LRU_OLD_RATIO_DIV,
02415 UT_LIST_GET_LEN(buf_pool->LRU)
02416 - (BUF_LRU_OLD_TOLERANCE
02417 + BUF_LRU_NON_OLD_MIN_LEN));
02418 ut_a(old_len >= new_len - BUF_LRU_OLD_TOLERANCE);
02419 ut_a(old_len <= new_len + BUF_LRU_OLD_TOLERANCE);
02420 }
02421
02422 UT_LIST_VALIDATE(LRU, buf_page_t, buf_pool->LRU,
02423 ut_ad(ut_list_node_313->in_LRU_list));
02424
02425 bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
02426
02427 old_len = 0;
02428
02429 while (bpage != NULL) {
02430
02431 switch (buf_page_get_state(bpage)) {
02432 case BUF_BLOCK_ZIP_FREE:
02433 case BUF_BLOCK_NOT_USED:
02434 case BUF_BLOCK_READY_FOR_USE:
02435 case BUF_BLOCK_MEMORY:
02436 case BUF_BLOCK_REMOVE_HASH:
02437 ut_error;
02438 break;
02439 case BUF_BLOCK_FILE_PAGE:
02440 ut_ad(((buf_block_t*) bpage)->in_unzip_LRU_list
02441 == buf_page_belongs_to_unzip_LRU(bpage));
02442 case BUF_BLOCK_ZIP_PAGE:
02443 case BUF_BLOCK_ZIP_DIRTY:
02444 break;
02445 }
02446
02447 if (buf_page_is_old(bpage)) {
02448 const buf_page_t* prev
02449 = UT_LIST_GET_PREV(LRU, bpage);
02450 const buf_page_t* next
02451 = UT_LIST_GET_NEXT(LRU, bpage);
02452
02453 if (!old_len++) {
02454 ut_a(buf_pool->LRU_old == bpage);
02455 } else {
02456 ut_a(!prev || buf_page_is_old(prev));
02457 }
02458
02459 ut_a(!next || buf_page_is_old(next));
02460 }
02461
02462 bpage = UT_LIST_GET_NEXT(LRU, bpage);
02463 }
02464
02465 ut_a(buf_pool->LRU_old_len == old_len);
02466
02467 UT_LIST_VALIDATE(list, buf_page_t, buf_pool->free,
02468 ut_ad(ut_list_node_313->in_free_list));
02469
02470 for (bpage = UT_LIST_GET_FIRST(buf_pool->free);
02471 bpage != NULL;
02472 bpage = UT_LIST_GET_NEXT(list, bpage)) {
02473
02474 ut_a(buf_page_get_state(bpage) == BUF_BLOCK_NOT_USED);
02475 }
02476
02477 UT_LIST_VALIDATE(unzip_LRU, buf_block_t, buf_pool->unzip_LRU,
02478 ut_ad(ut_list_node_313->in_unzip_LRU_list
02479 && ut_list_node_313->page.in_LRU_list));
02480
02481 for (block = UT_LIST_GET_FIRST(buf_pool->unzip_LRU);
02482 block;
02483 block = UT_LIST_GET_NEXT(unzip_LRU, block)) {
02484
02485 ut_ad(block->in_unzip_LRU_list);
02486 ut_ad(block->page.in_LRU_list);
02487 ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
02488 }
02489
02490 buf_pool_mutex_exit(buf_pool);
02491 }
02492
02493
02496 UNIV_INTERN
02497 ibool
02498 buf_LRU_validate(void)
02499
02500 {
02501 ulint i;
02502
02503 for (i = 0; i < srv_buf_pool_instances; i++) {
02504 buf_pool_t* buf_pool;
02505
02506 buf_pool = buf_pool_from_array(i);
02507 buf_LRU_validate_instance(buf_pool);
02508 }
02509
02510 return(TRUE);
02511 }
02512 #endif
02513
02514 #if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
02515
02517 UNIV_INTERN
02518 void
02519 buf_LRU_print_instance(
02520
02521 buf_pool_t* buf_pool)
02522 {
02523 const buf_page_t* bpage;
02524
02525 ut_ad(buf_pool);
02526 buf_pool_mutex_enter(buf_pool);
02527
02528 bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
02529
02530 while (bpage != NULL) {
02531
02532 mutex_enter(buf_page_get_mutex(bpage));
02533 fprintf(stderr, "BLOCK space %lu page %lu ",
02534 (ulong) buf_page_get_space(bpage),
02535 (ulong) buf_page_get_page_no(bpage));
02536
02537 if (buf_page_is_old(bpage)) {
02538 fputs("old ", stderr);
02539 }
02540
02541 if (bpage->buf_fix_count) {
02542 fprintf(stderr, "buffix count %lu ",
02543 (ulong) bpage->buf_fix_count);
02544 }
02545
02546 if (buf_page_get_io_fix(bpage)) {
02547 fprintf(stderr, "io_fix %lu ",
02548 (ulong) buf_page_get_io_fix(bpage));
02549 }
02550
02551 if (bpage->oldest_modification) {
02552 fputs("modif. ", stderr);
02553 }
02554
02555 switch (buf_page_get_state(bpage)) {
02556 const byte* frame;
02557 case BUF_BLOCK_FILE_PAGE:
02558 frame = buf_block_get_frame((buf_block_t*) bpage);
02559 fprintf(stderr, "\ntype %lu"
02560 " index id %llu\n",
02561 (ulong) fil_page_get_type(frame),
02562 (ullint) btr_page_get_index_id(frame));
02563 break;
02564 case BUF_BLOCK_ZIP_PAGE:
02565 frame = bpage->zip.data;
02566 fprintf(stderr, "\ntype %lu size %lu"
02567 " index id %llu\n",
02568 (ulong) fil_page_get_type(frame),
02569 (ulong) buf_page_get_zip_size(bpage),
02570 (ullint) btr_page_get_index_id(frame));
02571 break;
02572
02573 default:
02574 fprintf(stderr, "\n!state %lu!\n",
02575 (ulong) buf_page_get_state(bpage));
02576 break;
02577 }
02578
02579 mutex_exit(buf_page_get_mutex(bpage));
02580 bpage = UT_LIST_GET_NEXT(LRU, bpage);
02581 }
02582
02583 buf_pool_mutex_exit(buf_pool);
02584 }
02585
02586
02588 UNIV_INTERN
02589 void
02590 buf_LRU_print(void)
02591
02592 {
02593 ulint i;
02594 buf_pool_t* buf_pool;
02595
02596 for (i = 0; i < srv_buf_pool_instances; i++) {
02597 buf_pool = buf_pool_from_array(i);
02598 buf_LRU_print_instance(buf_pool);
02599 }
02600 }
02601 #endif