00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00033 #include "buf0buf.h"
00034
00035 #ifdef UNIV_NONINL
00036 #include "buf0buf.ic"
00037 #endif
00038
00039 #include "mem0mem.h"
00040 #include "btr0btr.h"
00041 #include "fil0fil.h"
00042 #ifndef UNIV_HOTBACKUP
00043 #include "buf0buddy.h"
00044 #include "lock0lock.h"
00045 #include "btr0sea.h"
00046 #include "ibuf0ibuf.h"
00047 #include "trx0undo.h"
00048 #include "log0log.h"
00049 #endif
00050 #include "srv0srv.h"
00051 #include "dict0dict.h"
00052 #include "log0recv.h"
00053 #include "page0zip.h"
00054
00055 #include <drizzled/errmsg_print.h>
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 #ifndef UNIV_HOTBACKUP
00246
00247 static const int WAIT_FOR_READ = 5000;
00249 static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
00250
00252 UNIV_INTERN buf_pool_t* buf_pool_ptr;
00253
00254 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
00255 static ulint buf_dbg_counter = 0;
00258 #endif
00259 #ifdef UNIV_DEBUG
00260
00262 UNIV_INTERN ibool buf_debug_prints = FALSE;
00263 #endif
00264
00265 #ifdef UNIV_PFS_RWLOCK
00266
00267
00268 UNIV_INTERN mysql_pfs_key_t buf_block_lock_key;
00269 # ifdef UNIV_SYNC_DEBUG
00270 UNIV_INTERN mysql_pfs_key_t buf_block_debug_latch_key;
00271 # endif
00272 #endif
00273
00274 #ifdef UNIV_PFS_MUTEX
00275 UNIV_INTERN mysql_pfs_key_t buffer_block_mutex_key;
00276 UNIV_INTERN mysql_pfs_key_t buf_pool_mutex_key;
00277 UNIV_INTERN mysql_pfs_key_t buf_pool_zip_mutex_key;
00278 UNIV_INTERN mysql_pfs_key_t flush_list_mutex_key;
00279 #endif
00280
00281 #if defined UNIV_PFS_MUTEX || defined UNIV_PFS_RWLOCK
00282 # ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
00283
00284
00285
00286
00287
00288 # define PFS_GROUP_BUFFER_SYNC
00289
00290
00291
00292
00293
00294 # define PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER ULINT_MAX
00295
00296 # endif
00297 #endif
00298
00300 struct buf_chunk_struct{
00301 ulint mem_size;
00302 ulint size;
00303 void* mem;
00305 buf_block_t* blocks;
00306 };
00307 #endif
00308
00309
00313 UNIV_INTERN
00314 ib_uint64_t
00315 buf_pool_get_oldest_modification(void)
00316
00317 {
00318 ulint i;
00319 buf_page_t* bpage;
00320 ib_uint64_t lsn = 0;
00321 ib_uint64_t oldest_lsn = 0;
00322
00323
00324
00325 if (srv_buf_pool_instances > 1)
00326 log_flush_order_mutex_enter();
00327
00328 for (i = 0; i < srv_buf_pool_instances; i++) {
00329 buf_pool_t* buf_pool;
00330
00331 buf_pool = buf_pool_from_array(i);
00332
00333 buf_flush_list_mutex_enter(buf_pool);
00334
00335 bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
00336
00337 if (bpage != NULL) {
00338 ut_ad(bpage->in_flush_list);
00339 lsn = bpage->oldest_modification;
00340 }
00341
00342 buf_flush_list_mutex_exit(buf_pool);
00343
00344 if (!oldest_lsn || oldest_lsn > lsn) {
00345 oldest_lsn = lsn;
00346 }
00347 }
00348
00349 log_flush_order_mutex_exit();
00350
00351
00352
00353
00354 return(oldest_lsn);
00355 }
00356
00357
00359 UNIV_INTERN
00360 void
00361 buf_get_total_list_len(
00362
00363 ulint* LRU_len,
00364 ulint* free_len,
00365 ulint* flush_list_len)
00366 {
00367 ulint i;
00368
00369 *LRU_len = 0;
00370 *free_len = 0;
00371 *flush_list_len = 0;
00372
00373 for (i = 0; i < srv_buf_pool_instances; i++) {
00374 buf_pool_t* buf_pool;
00375
00376 buf_pool = buf_pool_from_array(i);
00377 *LRU_len += UT_LIST_GET_LEN(buf_pool->LRU);
00378 *free_len += UT_LIST_GET_LEN(buf_pool->free);
00379 *flush_list_len += UT_LIST_GET_LEN(buf_pool->flush_list);
00380 }
00381 }
00382
00383
00385 UNIV_INTERN
00386 void
00387 buf_get_total_stat(
00388
00389 buf_pool_stat_t* tot_stat)
00390 {
00391 ulint i;
00392
00393 memset(tot_stat, 0, sizeof(*tot_stat));
00394
00395 for (i = 0; i < srv_buf_pool_instances; i++) {
00396 buf_pool_stat_t*buf_stat;
00397 buf_pool_t* buf_pool;
00398
00399 buf_pool = buf_pool_from_array(i);
00400
00401 buf_stat = &buf_pool->stat;
00402 tot_stat->n_page_gets += buf_stat->n_page_gets;
00403 tot_stat->n_pages_read += buf_stat->n_pages_read;
00404 tot_stat->n_pages_written += buf_stat->n_pages_written;
00405 tot_stat->n_pages_created += buf_stat->n_pages_created;
00406 tot_stat->n_ra_pages_read += buf_stat->n_ra_pages_read;
00407 tot_stat->n_ra_pages_evicted += buf_stat->n_ra_pages_evicted;
00408 tot_stat->n_pages_made_young += buf_stat->n_pages_made_young;
00409
00410 tot_stat->n_pages_not_made_young +=
00411 buf_stat->n_pages_not_made_young;
00412 }
00413 }
00414
00415
00418 UNIV_INTERN
00419 buf_block_t*
00420 buf_block_alloc(
00421
00422 buf_pool_t* buf_pool,
00423 ulint zip_size)
00425 {
00426 buf_block_t* block;
00427 ulint index;
00428 static ulint buf_pool_index;
00429
00430 if (buf_pool == NULL) {
00431
00432
00433 index = buf_pool_index++ % srv_buf_pool_instances;
00434 buf_pool = buf_pool_from_array(index);
00435 }
00436
00437 block = buf_LRU_get_free_block(buf_pool, zip_size);
00438
00439 buf_block_set_state(block, BUF_BLOCK_MEMORY);
00440
00441 return(block);
00442 }
00443
00444
00449 UNIV_INTERN
00450 ulint
00451 buf_calc_page_new_checksum(
00452
00453 const byte* page)
00454 {
00455 ulint checksum;
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
00466 FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
00467 + ut_fold_binary(page + FIL_PAGE_DATA,
00468 UNIV_PAGE_SIZE - FIL_PAGE_DATA
00469 - FIL_PAGE_END_LSN_OLD_CHKSUM);
00470 checksum = checksum & 0xFFFFFFFFUL;
00471
00472 return(checksum);
00473 }
00474
00475
00483 UNIV_INTERN
00484 ulint
00485 buf_calc_page_old_checksum(
00486
00487 const byte* page)
00488 {
00489 ulint checksum;
00490
00491 checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
00492
00493 checksum = checksum & 0xFFFFFFFFUL;
00494
00495 return(checksum);
00496 }
00497
00498
00501 UNIV_INTERN
00502 ibool
00503 buf_page_is_corrupted(
00504
00505 const byte* read_buf,
00506 ulint zip_size)
00508 {
00509 ulint checksum_field;
00510 ulint old_checksum_field;
00511
00512 if (UNIV_LIKELY(!zip_size)
00513 && memcmp(read_buf + FIL_PAGE_LSN + 4,
00514 read_buf + UNIV_PAGE_SIZE
00515 - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) {
00516
00517
00518
00519
00520 return(TRUE);
00521 }
00522
00523 #ifndef UNIV_HOTBACKUP
00524 if (recv_lsn_checks_on) {
00525 ib_uint64_t current_lsn;
00526
00527 if (log_peek_lsn(¤t_lsn)
00528 && UNIV_UNLIKELY
00529 (current_lsn
00530 < mach_read_from_8(read_buf + FIL_PAGE_LSN))) {
00531 ut_print_timestamp(stderr);
00532
00533 drizzled::errmsg_printf(drizzled::error::INFO,
00534 "InnoDB: Error: page %lu log sequence number %"PRIu64". "
00535 "InnoDB: is in the future! Current system log sequence number %"PRIu64". "
00536 "Your database may be corrupt or you may have copied the InnoDB tablespace but not the InnoDB log files. See "
00537 " " REFMAN "forcing-recovery.html for more information. ",
00538 (ulong) mach_read_from_4(read_buf
00539 + FIL_PAGE_OFFSET),
00540 mach_read_from_8(read_buf + FIL_PAGE_LSN),
00541 current_lsn);
00542 }
00543 }
00544 #endif
00545
00546
00547
00548
00549
00550
00551 if (UNIV_LIKELY(srv_use_checksums)) {
00552 checksum_field = mach_read_from_4(read_buf
00553 + FIL_PAGE_SPACE_OR_CHKSUM);
00554
00555 if (UNIV_UNLIKELY(zip_size)) {
00556 return(checksum_field != BUF_NO_CHECKSUM_MAGIC
00557 && checksum_field
00558 != page_zip_calc_checksum(read_buf, zip_size));
00559 }
00560
00561 old_checksum_field = mach_read_from_4(
00562 read_buf + UNIV_PAGE_SIZE
00563 - FIL_PAGE_END_LSN_OLD_CHKSUM);
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 if (old_checksum_field != mach_read_from_4(read_buf
00574 + FIL_PAGE_LSN)
00575 && old_checksum_field != BUF_NO_CHECKSUM_MAGIC
00576 && old_checksum_field
00577 != buf_calc_page_old_checksum(read_buf)) {
00578
00579 return(TRUE);
00580 }
00581
00582
00583
00584
00585 if (checksum_field != 0
00586 && checksum_field != BUF_NO_CHECKSUM_MAGIC
00587 && checksum_field
00588 != buf_calc_page_new_checksum(read_buf)) {
00589
00590 return(TRUE);
00591 }
00592 }
00593
00594 return(FALSE);
00595 }
00596
00597
00599 UNIV_INTERN
00600 void
00601 buf_page_print(
00602
00603 const byte* read_buf,
00604 ulint zip_size)
00606 {
00607 #ifndef UNIV_HOTBACKUP
00608 dict_index_t* index;
00609 #endif
00610 ulint checksum;
00611 ulint old_checksum;
00612 ulint size = zip_size;
00613
00614 if (!size) {
00615 size = UNIV_PAGE_SIZE;
00616 }
00617
00618 ut_print_timestamp(stderr);
00619 fprintf(stderr, " InnoDB: Page dump in ascii and hex (%lu bytes):\n",
00620 (ulong) size);
00621 ut_print_buf(stderr, read_buf, size);
00622 fputs("\nInnoDB: End of page dump\n", stderr);
00623
00624 if (zip_size) {
00625
00626
00627 switch (fil_page_get_type(read_buf)) {
00628 case FIL_PAGE_TYPE_ZBLOB:
00629 case FIL_PAGE_TYPE_ZBLOB2:
00630 checksum = srv_use_checksums
00631 ? page_zip_calc_checksum(read_buf, zip_size)
00632 : BUF_NO_CHECKSUM_MAGIC;
00633 ut_print_timestamp(stderr);
00634 fprintf(stderr,
00635 " InnoDB: Compressed BLOB page"
00636 " checksum %lu, stored %lu\n"
00637 "InnoDB: Page lsn %lu %lu\n"
00638 "InnoDB: Page number (if stored"
00639 " to page already) %lu,\n"
00640 "InnoDB: space id (if stored"
00641 " to page already) %lu\n",
00642 (ulong) checksum,
00643 (ulong) mach_read_from_4(
00644 read_buf + FIL_PAGE_SPACE_OR_CHKSUM),
00645 (ulong) mach_read_from_4(
00646 read_buf + FIL_PAGE_LSN),
00647 (ulong) mach_read_from_4(
00648 read_buf + (FIL_PAGE_LSN + 4)),
00649 (ulong) mach_read_from_4(
00650 read_buf + FIL_PAGE_OFFSET),
00651 (ulong) mach_read_from_4(
00652 read_buf
00653 + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
00654 return;
00655 default:
00656 ut_print_timestamp(stderr);
00657 fprintf(stderr,
00658 " InnoDB: unknown page type %lu,"
00659 " assuming FIL_PAGE_INDEX\n",
00660 fil_page_get_type(read_buf));
00661
00662 case FIL_PAGE_INDEX:
00663 checksum = srv_use_checksums
00664 ? page_zip_calc_checksum(read_buf, zip_size)
00665 : BUF_NO_CHECKSUM_MAGIC;
00666
00667 ut_print_timestamp(stderr);
00668 fprintf(stderr,
00669 " InnoDB: Compressed page checksum %lu,"
00670 " stored %lu\n"
00671 "InnoDB: Page lsn %lu %lu\n"
00672 "InnoDB: Page number (if stored"
00673 " to page already) %lu,\n"
00674 "InnoDB: space id (if stored"
00675 " to page already) %lu\n",
00676 (ulong) checksum,
00677 (ulong) mach_read_from_4(
00678 read_buf + FIL_PAGE_SPACE_OR_CHKSUM),
00679 (ulong) mach_read_from_4(
00680 read_buf + FIL_PAGE_LSN),
00681 (ulong) mach_read_from_4(
00682 read_buf + (FIL_PAGE_LSN + 4)),
00683 (ulong) mach_read_from_4(
00684 read_buf + FIL_PAGE_OFFSET),
00685 (ulong) mach_read_from_4(
00686 read_buf
00687 + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
00688 return;
00689 case FIL_PAGE_TYPE_XDES:
00690
00691 break;
00692 }
00693 }
00694
00695 checksum = srv_use_checksums
00696 ? buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
00697 old_checksum = srv_use_checksums
00698 ? buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
00699
00700 ut_print_timestamp(stderr);
00701 fprintf(stderr,
00702 " InnoDB: Page checksum %lu, prior-to-4.0.14-form"
00703 " checksum %lu\n"
00704 "InnoDB: stored checksum %lu, prior-to-4.0.14-form"
00705 " stored checksum %lu\n"
00706 "InnoDB: Page lsn %lu %lu, low 4 bytes of lsn"
00707 " at page end %lu\n"
00708 "InnoDB: Page number (if stored to page already) %lu,\n"
00709 "InnoDB: space id (if created with >= MySQL-4.1.1"
00710 " and stored already) %lu\n",
00711 (ulong) checksum, (ulong) old_checksum,
00712 (ulong) mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM),
00713 (ulong) mach_read_from_4(read_buf + UNIV_PAGE_SIZE
00714 - FIL_PAGE_END_LSN_OLD_CHKSUM),
00715 (ulong) mach_read_from_4(read_buf + FIL_PAGE_LSN),
00716 (ulong) mach_read_from_4(read_buf + FIL_PAGE_LSN + 4),
00717 (ulong) mach_read_from_4(read_buf + UNIV_PAGE_SIZE
00718 - FIL_PAGE_END_LSN_OLD_CHKSUM + 4),
00719 (ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
00720 (ulong) mach_read_from_4(read_buf
00721 + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
00722
00723 #ifndef UNIV_HOTBACKUP
00724 if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE)
00725 == TRX_UNDO_INSERT) {
00726 fprintf(stderr,
00727 "InnoDB: Page may be an insert undo log page\n");
00728 } else if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR
00729 + TRX_UNDO_PAGE_TYPE)
00730 == TRX_UNDO_UPDATE) {
00731 fprintf(stderr,
00732 "InnoDB: Page may be an update undo log page\n");
00733 }
00734 #endif
00735
00736 switch (fil_page_get_type(read_buf)) {
00737 index_id_t index_id;
00738 case FIL_PAGE_INDEX:
00739 index_id = btr_page_get_index_id(read_buf);
00740 fprintf(stderr,
00741 "InnoDB: Page may be an index page where"
00742 " index id is %llu\n",
00743 (ullint) index_id);
00744 #ifndef UNIV_HOTBACKUP
00745 index = dict_index_find_on_id_low(index_id);
00746 if (index) {
00747 fputs("InnoDB: (", stderr);
00748 dict_index_name_print(stderr, NULL, index);
00749 fputs(")\n", stderr);
00750 }
00751 #endif
00752 break;
00753 case FIL_PAGE_INODE:
00754 fputs("InnoDB: Page may be an 'inode' page\n", stderr);
00755 break;
00756 case FIL_PAGE_IBUF_FREE_LIST:
00757 fputs("InnoDB: Page may be an insert buffer free list page\n",
00758 stderr);
00759 break;
00760 case FIL_PAGE_TYPE_ALLOCATED:
00761 fputs("InnoDB: Page may be a freshly allocated page\n",
00762 stderr);
00763 break;
00764 case FIL_PAGE_IBUF_BITMAP:
00765 fputs("InnoDB: Page may be an insert buffer bitmap page\n",
00766 stderr);
00767 break;
00768 case FIL_PAGE_TYPE_SYS:
00769 fputs("InnoDB: Page may be a system page\n",
00770 stderr);
00771 break;
00772 case FIL_PAGE_TYPE_TRX_SYS:
00773 fputs("InnoDB: Page may be a transaction system page\n",
00774 stderr);
00775 break;
00776 case FIL_PAGE_TYPE_FSP_HDR:
00777 fputs("InnoDB: Page may be a file space header page\n",
00778 stderr);
00779 break;
00780 case FIL_PAGE_TYPE_XDES:
00781 fputs("InnoDB: Page may be an extent descriptor page\n",
00782 stderr);
00783 break;
00784 case FIL_PAGE_TYPE_BLOB:
00785 fputs("InnoDB: Page may be a BLOB page\n",
00786 stderr);
00787 break;
00788 case FIL_PAGE_TYPE_ZBLOB:
00789 case FIL_PAGE_TYPE_ZBLOB2:
00790 fputs("InnoDB: Page may be a compressed BLOB page\n",
00791 stderr);
00792 break;
00793 }
00794 }
00795
00796 #ifndef UNIV_HOTBACKUP
00797
00798 # ifdef PFS_GROUP_BUFFER_SYNC
00799
00805 static
00806 void
00807 pfs_register_buffer_block(
00808
00809 buf_chunk_t* chunk)
00810 {
00811 ulint i;
00812 ulint num_to_register;
00813 buf_block_t* block;
00814
00815 block = chunk->blocks;
00816
00817 num_to_register = ut_min(chunk->size,
00818 PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER);
00819
00820 for (i = 0; i < num_to_register; i++) {
00821 mutex_t* mutex;
00822 rw_lock_t* rwlock;
00823
00824 # ifdef UNIV_PFS_MUTEX
00825 mutex = &block->mutex;
00826 ut_a(!mutex->pfs_psi);
00827 mutex->pfs_psi = (PSI_server)
00828 ? PSI_server->init_mutex(buffer_block_mutex_key, mutex)
00829 : NULL;
00830 # endif
00831
00832 # ifdef UNIV_PFS_RWLOCK
00833 rwlock = &block->lock;
00834 ut_a(!rwlock->pfs_psi);
00835 rwlock->pfs_psi = (PSI_server)
00836 ? PSI_server->init_rwlock(buf_block_lock_key, rwlock)
00837 : NULL;
00838 # endif
00839 block++;
00840 }
00841 }
00842 # endif
00843
00844
00846 static
00847 void
00848 buf_block_init(
00849
00850 buf_pool_t* buf_pool,
00851 buf_block_t* block,
00852 byte* frame)
00853 {
00854 UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE, block);
00855
00856 block->frame = frame;
00857
00858 block->page.buf_pool_index = buf_pool_index(buf_pool);
00859 block->page.state = BUF_BLOCK_NOT_USED;
00860 block->page.buf_fix_count = 0;
00861 block->page.io_fix = BUF_IO_NONE;
00862
00863 block->modify_clock = 0;
00864
00865 #ifdef UNIV_DEBUG_FILE_ACCESSES
00866 block->page.file_page_was_freed = FALSE;
00867 #endif
00868
00869 block->check_index_page_at_flush = FALSE;
00870 block->index = NULL;
00871
00872 block->is_hashed = FALSE;
00873
00874 #ifdef UNIV_DEBUG
00875 block->page.in_page_hash = FALSE;
00876 block->page.in_zip_hash = FALSE;
00877 block->page.in_flush_list = FALSE;
00878 block->page.in_free_list = FALSE;
00879 block->page.in_LRU_list = FALSE;
00880 block->in_unzip_LRU_list = FALSE;
00881 #endif
00882 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00883 block->n_pointers = 0;
00884 #endif
00885 page_zip_des_init(&block->page.zip);
00886
00887 #if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC
00888
00889
00890
00891
00892
00893
00894 mutex_create(PFS_NOT_INSTRUMENTED, &block->mutex, SYNC_BUF_BLOCK);
00895 rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
00896 #else
00897 mutex_create(buffer_block_mutex_key, &block->mutex, SYNC_BUF_BLOCK);
00898 rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
00899 #endif
00900
00901 ut_ad(rw_lock_validate(&(block->lock)));
00902
00903 #ifdef UNIV_SYNC_DEBUG
00904 rw_lock_create(buf_block_debug_latch_key,
00905 &block->debug_latch, SYNC_NO_ORDER_CHECK);
00906 #endif
00907 }
00908
00909
00912 static
00913 buf_chunk_t*
00914 buf_chunk_init(
00915
00916 buf_pool_t* buf_pool,
00917 buf_chunk_t* chunk,
00918 ulint mem_size)
00919 {
00920 buf_block_t* block;
00921 byte* frame;
00922 ulint i;
00923
00924
00925
00926 mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE);
00927
00928 mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block)
00929 + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
00930
00931 chunk->mem_size = mem_size;
00932 chunk->mem = os_mem_alloc_large(&chunk->mem_size);
00933
00934 if (UNIV_UNLIKELY(chunk->mem == NULL)) {
00935
00936 return(NULL);
00937 }
00938
00939
00940
00941 chunk->blocks = static_cast<buf_block_struct *>(chunk->mem);
00942
00943
00944
00945
00946
00947
00948 frame = static_cast<unsigned char *>(ut_align(chunk->mem, UNIV_PAGE_SIZE));
00949 chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
00950 - (frame != chunk->mem);
00951
00952
00953 {
00954 ulint size = chunk->size;
00955
00956 while (frame < (byte*) (chunk->blocks + size)) {
00957 frame += UNIV_PAGE_SIZE;
00958 size--;
00959 }
00960
00961 chunk->size = size;
00962 }
00963
00964
00965
00966
00967
00968 block = chunk->blocks;
00969
00970 for (i = chunk->size; i--; ) {
00971
00972 buf_block_init(buf_pool, block, frame);
00973
00974 #ifdef HAVE_VALGRIND
00975
00976 memset(block->frame, '\0', UNIV_PAGE_SIZE);
00977 #endif
00978
00979 UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
00980
00981 ut_d(block->page.in_free_list = TRUE);
00982 ut_ad(buf_pool_from_block(block) == buf_pool);
00983
00984 block++;
00985 frame += UNIV_PAGE_SIZE;
00986 }
00987
00988 #ifdef PFS_GROUP_BUFFER_SYNC
00989 pfs_register_buffer_block(chunk);
00990 #endif
00991 return(chunk);
00992 }
00993
00994 #ifdef UNIV_DEBUG
00995
00999 static
01000 buf_block_t*
01001 buf_chunk_contains_zip(
01002
01003 buf_chunk_t* chunk,
01004 const void* data)
01005 {
01006 buf_block_t* block;
01007 ulint i;
01008
01009 block = chunk->blocks;
01010
01011 for (i = chunk->size; i--; block++) {
01012 if (block->page.zip.data == data) {
01013
01014 return(block);
01015 }
01016 }
01017
01018 return(NULL);
01019 }
01020
01021
01025 UNIV_INTERN
01026 buf_block_t*
01027 buf_pool_contains_zip(
01028
01029 buf_pool_t* buf_pool,
01030 const void* data)
01031 {
01032 ulint n;
01033 buf_chunk_t* chunk = buf_pool->chunks;
01034
01035 ut_ad(buf_pool);
01036 ut_ad(buf_pool_mutex_own(buf_pool));
01037 for (n = buf_pool->n_chunks; n--; chunk++) {
01038
01039 buf_block_t* block = buf_chunk_contains_zip(chunk, data);
01040
01041 if (block) {
01042 return(block);
01043 }
01044 }
01045
01046 return(NULL);
01047 }
01048 #endif
01049
01050
01053 static
01054 const buf_block_t*
01055 buf_chunk_not_freed(
01056
01057 buf_chunk_t* chunk)
01058 {
01059 buf_block_t* block;
01060 ulint i;
01061
01062 block = chunk->blocks;
01063
01064 for (i = chunk->size; i--; block++) {
01065 ibool ready;
01066
01067 switch (buf_block_get_state(block)) {
01068 case BUF_BLOCK_ZIP_FREE:
01069 case BUF_BLOCK_ZIP_PAGE:
01070 case BUF_BLOCK_ZIP_DIRTY:
01071
01072
01073 ut_error;
01074 break;
01075 case BUF_BLOCK_NOT_USED:
01076 case BUF_BLOCK_READY_FOR_USE:
01077 case BUF_BLOCK_MEMORY:
01078 case BUF_BLOCK_REMOVE_HASH:
01079
01080
01081 break;
01082 case BUF_BLOCK_FILE_PAGE:
01083 mutex_enter(&block->mutex);
01084 ready = buf_flush_ready_for_replace(&block->page);
01085 mutex_exit(&block->mutex);
01086
01087 if (!ready) {
01088
01089 return(block);
01090 }
01091
01092 break;
01093 }
01094 }
01095
01096 return(NULL);
01097 }
01098
01099
01102 static
01103 ibool
01104 buf_chunk_all_free(
01105
01106 const buf_chunk_t* chunk)
01107 {
01108 const buf_block_t* block;
01109 ulint i;
01110
01111 block = chunk->blocks;
01112
01113 for (i = chunk->size; i--; block++) {
01114
01115 if (buf_block_get_state(block) != BUF_BLOCK_NOT_USED) {
01116
01117 return(FALSE);
01118 }
01119 }
01120
01121 return(TRUE);
01122 }
01123
01124
01126 static
01127 void
01128 buf_chunk_free(
01129
01130 buf_pool_t* buf_pool,
01131 buf_chunk_t* chunk)
01132 {
01133 buf_block_t* block;
01134 const buf_block_t* block_end;
01135
01136 ut_ad(buf_pool_mutex_own(buf_pool));
01137
01138 block_end = chunk->blocks + chunk->size;
01139
01140 for (block = chunk->blocks; block < block_end; block++) {
01141 ut_a(buf_block_get_state(block) == BUF_BLOCK_NOT_USED);
01142 ut_a(!block->page.zip.data);
01143
01144 ut_ad(!block->page.in_LRU_list);
01145 ut_ad(!block->in_unzip_LRU_list);
01146 ut_ad(!block->page.in_flush_list);
01147
01148 ut_ad(block->page.in_free_list);
01149 UT_LIST_REMOVE(list, buf_pool->free, (&block->page));
01150
01151
01152 mutex_free(&block->mutex);
01153 rw_lock_free(&block->lock);
01154 #ifdef UNIV_SYNC_DEBUG
01155 rw_lock_free(&block->debug_latch);
01156 #endif
01157 UNIV_MEM_UNDESC(block);
01158 }
01159
01160 os_mem_free_large(chunk->mem, chunk->mem_size);
01161 }
01162
01163
01165 static
01166 void
01167 buf_pool_set_sizes(void)
01168
01169 {
01170 ulint i;
01171 ulint curr_size = 0;
01172
01173 buf_pool_mutex_enter_all();
01174
01175 for (i = 0; i < srv_buf_pool_instances; i++) {
01176 buf_pool_t* buf_pool;
01177
01178 buf_pool = buf_pool_from_array(i);
01179 curr_size += buf_pool->curr_pool_size;
01180 }
01181
01182 srv_buf_pool_curr_size = curr_size;
01183 srv_buf_pool_old_size = srv_buf_pool_size;
01184
01185 buf_pool_mutex_exit_all();
01186 }
01187
01188
01191 static
01192 ulint
01193 buf_pool_init_instance(
01194
01195 buf_pool_t* buf_pool,
01196 ulint buf_pool_size,
01197 ulint instance_no)
01198 {
01199 ulint i;
01200 buf_chunk_t* chunk;
01201
01202
01203
01204 mutex_create(buf_pool_mutex_key,
01205 &buf_pool->mutex, SYNC_BUF_POOL);
01206 mutex_create(buf_pool_zip_mutex_key,
01207 &buf_pool->zip_mutex, SYNC_BUF_BLOCK);
01208
01209 buf_pool_mutex_enter(buf_pool);
01210
01211 if (buf_pool_size > 0) {
01212 buf_pool->n_chunks = 1;
01213 void *chunk_ptr= mem_zalloc((sizeof *chunk));
01214 buf_pool->chunks = chunk = static_cast<buf_chunk_t *>(chunk_ptr);
01215
01216 UT_LIST_INIT(buf_pool->free);
01217
01218 if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
01219 mem_free(chunk);
01220 mem_free(buf_pool);
01221
01222 buf_pool_mutex_exit(buf_pool);
01223
01224 return(DB_ERROR);
01225 }
01226
01227 buf_pool->instance_no = instance_no;
01228 buf_pool->old_pool_size = buf_pool_size;
01229 buf_pool->curr_size = chunk->size;
01230 buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
01231
01232 buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
01233 buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
01234
01235 buf_pool->last_printout_time = ut_time();
01236 }
01237
01238
01239
01240 mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
01241 SYNC_BUF_FLUSH_LIST);
01242
01243 for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
01244 buf_pool->no_flush[i] = os_event_create(NULL);
01245 }
01246
01247
01248
01249
01250
01251
01252 buf_pool_mutex_exit(buf_pool);
01253
01254 return(DB_SUCCESS);
01255 }
01256
01257
01259 static
01260 void
01261 buf_pool_free_instance(
01262
01263 buf_pool_t* buf_pool)
01264
01265 {
01266 buf_chunk_t* chunk;
01267 buf_chunk_t* chunks;
01268
01269 chunks = buf_pool->chunks;
01270 chunk = chunks + buf_pool->n_chunks;
01271
01272 while (--chunk >= chunks) {
01273
01274
01275 os_mem_free_large(chunk->mem, chunk->mem_size);
01276 }
01277
01278 mem_free(buf_pool->chunks);
01279 hash_table_free(buf_pool->page_hash);
01280 hash_table_free(buf_pool->zip_hash);
01281 }
01282
01283
01286 UNIV_INTERN
01287 ulint
01288 buf_pool_init(
01289
01290 ulint total_size,
01291 ulint n_instances)
01292 {
01293 ulint i;
01294 const ulint size = total_size / n_instances;
01295
01296 ut_ad(n_instances > 0);
01297 ut_ad(n_instances <= MAX_BUFFER_POOLS);
01298 ut_ad(n_instances == srv_buf_pool_instances);
01299
01300
01301
01302
01303 void *buf_pool_void_ptr= mem_zalloc(n_instances * sizeof *buf_pool_ptr);
01304 buf_pool_ptr = static_cast<buf_pool_struct *>(buf_pool_void_ptr);
01305
01306 for (i = 0; i < n_instances; i++) {
01307 buf_pool_t* ptr = &buf_pool_ptr[i];
01308
01309 if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
01310
01311
01312 buf_pool_free(i);
01313
01314 return(DB_ERROR);
01315 }
01316 }
01317
01318 buf_pool_set_sizes();
01319 buf_LRU_old_ratio_update(100 * 3/ 8, FALSE);
01320
01321 btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void*) / 64);
01322
01323 return(DB_SUCCESS);
01324 }
01325
01326
01329 UNIV_INTERN
01330 void
01331 buf_pool_free(
01332
01333 ulint n_instances)
01334 {
01335 ulint i;
01336
01337 for (i = 0; i < n_instances; i++) {
01338 buf_pool_free_instance(buf_pool_from_array(i));
01339 }
01340
01341 mem_free(buf_pool_ptr);
01342 buf_pool_ptr = NULL;
01343 }
01344
01345
01347 static
01348 void
01349 buf_pool_drop_hash_index_instance(
01350
01351 buf_pool_t* buf_pool,
01352 ibool* released_search_latch)
01355 {
01356 buf_chunk_t* chunks = buf_pool->chunks;
01357 buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
01358
01359 while (--chunk >= chunks) {
01360 ulint i;
01361 buf_block_t* block = chunk->blocks;
01362
01363 for (i = chunk->size; i--; block++) {
01364
01365
01366
01367
01368 if (!block->is_hashed) {
01369 continue;
01370 }
01371
01372
01373
01374
01375 rw_lock_x_unlock(&btr_search_latch);
01376
01377
01378
01379 *released_search_latch = TRUE;
01380
01381 rw_lock_x_lock(&block->lock);
01382
01383
01384
01385
01386 ut_ad(!btr_search_enabled);
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406 btr_search_drop_page_hash_index(block);
01407
01408 rw_lock_x_unlock(&block->lock);
01409
01410 rw_lock_x_lock(&btr_search_latch);
01411
01412 ut_ad(!btr_search_enabled);
01413 }
01414 }
01415 }
01416
01417
01421 UNIV_INTERN
01422 void
01423 buf_pool_drop_hash_index(void)
01424
01425 {
01426 ibool released_search_latch;
01427
01428 #ifdef UNIV_SYNC_DEBUG
01429 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
01430 #endif
01431 ut_ad(!btr_search_enabled);
01432
01433 do {
01434 ulint i;
01435
01436 released_search_latch = FALSE;
01437
01438 for (i = 0; i < srv_buf_pool_instances; i++) {
01439 buf_pool_t* buf_pool;
01440
01441 buf_pool = buf_pool_from_array(i);
01442
01443 buf_pool_drop_hash_index_instance(
01444 buf_pool, &released_search_latch);
01445 }
01446
01447 } while (released_search_latch);
01448 }
01449
01450
01454 UNIV_INTERN
01455 void
01456 buf_relocate(
01457
01458 buf_page_t* bpage,
01461 buf_page_t* dpage)
01462 {
01463 buf_page_t* b;
01464 ulint fold;
01465 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
01466
01467 ut_ad(buf_pool_mutex_own(buf_pool));
01468 ut_ad(mutex_own(buf_page_get_mutex(bpage)));
01469 ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
01470 ut_a(bpage->buf_fix_count == 0);
01471 ut_ad(bpage->in_LRU_list);
01472 ut_ad(!bpage->in_zip_hash);
01473 ut_ad(bpage->in_page_hash);
01474 ut_ad(bpage == buf_page_hash_get(buf_pool,
01475 bpage->space, bpage->offset));
01476 ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
01477 #ifdef UNIV_DEBUG
01478 switch (buf_page_get_state(bpage)) {
01479 case BUF_BLOCK_ZIP_FREE:
01480 case BUF_BLOCK_NOT_USED:
01481 case BUF_BLOCK_READY_FOR_USE:
01482 case BUF_BLOCK_FILE_PAGE:
01483 case BUF_BLOCK_MEMORY:
01484 case BUF_BLOCK_REMOVE_HASH:
01485 ut_error;
01486 case BUF_BLOCK_ZIP_DIRTY:
01487 case BUF_BLOCK_ZIP_PAGE:
01488 break;
01489 }
01490 #endif
01491
01492 memcpy(dpage, bpage, sizeof *dpage);
01493
01494 ut_d(bpage->in_LRU_list = FALSE);
01495 ut_d(bpage->in_page_hash = FALSE);
01496
01497
01498 b = UT_LIST_GET_PREV(LRU, bpage);
01499 UT_LIST_REMOVE(LRU, buf_pool->LRU, bpage);
01500
01501 if (b) {
01502 UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU, b, dpage);
01503 } else {
01504 UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, dpage);
01505 }
01506
01507 if (UNIV_UNLIKELY(buf_pool->LRU_old == bpage)) {
01508 buf_pool->LRU_old = dpage;
01509 #ifdef UNIV_LRU_DEBUG
01510
01511
01512 ut_a(buf_pool->LRU_old->old);
01513 ut_a(!UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)
01514 || !UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)->old);
01515 ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)
01516 || UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old);
01517 } else {
01518
01519
01520 buf_page_set_old(dpage, buf_page_is_old(dpage));
01521 #endif
01522 }
01523
01524 ut_d(UT_LIST_VALIDATE(LRU, buf_page_t, buf_pool->LRU,
01525 ut_ad(ut_list_node_313->in_LRU_list)));
01526
01527
01528 fold = buf_page_address_fold(bpage->space, bpage->offset);
01529
01530 HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
01531 HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold, dpage);
01532 }
01533
01534
01536 static
01537 void
01538 buf_pool_shrink_instance(
01539
01540 buf_pool_t* buf_pool,
01541 ulint chunk_size)
01542 {
01543 buf_chunk_t* chunks;
01544 buf_chunk_t* chunk;
01545 ulint max_size;
01546 ulint max_free_size;
01547 buf_chunk_t* max_chunk;
01548 buf_chunk_t* max_free_chunk;
01549
01550 ut_ad(!buf_pool_mutex_own(buf_pool));
01551
01552 try_again:
01553 btr_search_disable();
01554 buf_pool_mutex_enter(buf_pool);
01555
01556 shrink_again:
01557 if (buf_pool->n_chunks <= 1) {
01558
01559
01560 goto func_done;
01561 }
01562
01563
01564
01565 chunks = buf_pool->chunks;
01566 chunk = chunks + buf_pool->n_chunks;
01567 max_size = max_free_size = 0;
01568 max_chunk = max_free_chunk = NULL;
01569
01570 while (--chunk >= chunks) {
01571 if (chunk->size <= chunk_size
01572 && chunk->size > max_free_size) {
01573 if (chunk->size > max_size) {
01574 max_size = chunk->size;
01575 max_chunk = chunk;
01576 }
01577
01578 if (buf_chunk_all_free(chunk)) {
01579 max_free_size = chunk->size;
01580 max_free_chunk = chunk;
01581 }
01582 }
01583 }
01584
01585 if (!max_free_size) {
01586
01587 ulint dirty = 0;
01588 ulint nonfree = 0;
01589 buf_block_t* block;
01590 buf_block_t* bend;
01591
01592
01593
01594 if (!max_chunk) {
01595
01596 goto func_exit;
01597 }
01598
01599 block = max_chunk->blocks;
01600 bend = block + max_chunk->size;
01601
01602
01603
01604 for (; block < bend; block++) {
01605 switch (buf_block_get_state(block)) {
01606 case BUF_BLOCK_NOT_USED:
01607 continue;
01608 case BUF_BLOCK_FILE_PAGE:
01609 break;
01610 default:
01611 nonfree++;
01612 continue;
01613 }
01614
01615 mutex_enter(&block->mutex);
01616
01617
01618
01619
01620
01621 if (!buf_flush_ready_for_replace(&block->page)) {
01622
01623 buf_LRU_make_block_old(&block->page);
01624 dirty++;
01625 } else if (buf_LRU_free_block(&block->page, TRUE, NULL)
01626 != BUF_LRU_FREED) {
01627 nonfree++;
01628 }
01629
01630 mutex_exit(&block->mutex);
01631 }
01632
01633 buf_pool_mutex_exit(buf_pool);
01634
01635
01636
01637
01638 if (nonfree) {
01639
01640 os_thread_sleep(100000);
01641 } else if (dirty
01642 && buf_flush_LRU(buf_pool, dirty)
01643 == ULINT_UNDEFINED) {
01644
01645 buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU);
01646 }
01647
01648 goto try_again;
01649 }
01650
01651 max_size = max_free_size;
01652 max_chunk = max_free_chunk;
01653
01654 buf_pool->old_pool_size = buf_pool->curr_pool_size;
01655
01656
01657 chunks = static_cast<buf_chunk_t *>(mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks));
01658 memcpy(chunks, buf_pool->chunks,
01659 (max_chunk - buf_pool->chunks) * sizeof *chunks);
01660 memcpy(chunks + (max_chunk - buf_pool->chunks),
01661 max_chunk + 1,
01662 buf_pool->chunks + buf_pool->n_chunks
01663 - (max_chunk + 1));
01664 ut_a(buf_pool->curr_size > max_chunk->size);
01665 buf_pool->curr_size -= max_chunk->size;
01666 buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
01667 chunk_size -= max_chunk->size;
01668 buf_chunk_free(buf_pool, max_chunk);
01669 mem_free(buf_pool->chunks);
01670 buf_pool->chunks = chunks;
01671 buf_pool->n_chunks--;
01672
01673
01674 if (chunk_size > 1048576 / UNIV_PAGE_SIZE) {
01675
01676 goto shrink_again;
01677 }
01678 goto func_exit;
01679
01680 func_done:
01681 buf_pool->old_pool_size = buf_pool->curr_pool_size;
01682 func_exit:
01683 buf_pool_mutex_exit(buf_pool);
01684 btr_search_enable();
01685 }
01686
01687
01689 static
01690 void
01691 buf_pool_shrink(
01692
01693 ulint chunk_size)
01694 {
01695 ulint i;
01696
01697 for (i = 0; i < srv_buf_pool_instances; i++) {
01698 buf_pool_t* buf_pool;
01699 ulint instance_chunk_size;
01700
01701 instance_chunk_size = chunk_size / srv_buf_pool_instances;
01702 buf_pool = buf_pool_from_array(i);
01703 buf_pool_shrink_instance(buf_pool, instance_chunk_size);
01704 }
01705
01706 buf_pool_set_sizes();
01707 }
01708
01709
01711 static
01712 void
01713 buf_pool_page_hash_rebuild_instance(
01714
01715 buf_pool_t* buf_pool)
01716 {
01717 ulint i;
01718 buf_page_t* b;
01719 buf_chunk_t* chunk;
01720 ulint n_chunks;
01721 hash_table_t* zip_hash;
01722 hash_table_t* page_hash;
01723
01724 buf_pool_mutex_enter(buf_pool);
01725
01726
01727 hash_table_free(buf_pool->page_hash);
01728 buf_pool->page_hash = page_hash = hash_create(2 * buf_pool->curr_size);
01729 zip_hash = hash_create(2 * buf_pool->curr_size);
01730
01731 HASH_MIGRATE(buf_pool->zip_hash, zip_hash, buf_page_t, hash,
01732 BUF_POOL_ZIP_FOLD_BPAGE);
01733
01734 hash_table_free(buf_pool->zip_hash);
01735 buf_pool->zip_hash = zip_hash;
01736
01737
01738
01739 chunk = buf_pool->chunks;
01740 n_chunks = buf_pool->n_chunks;
01741
01742 for (i = 0; i < n_chunks; i++, chunk++) {
01743 ulint j;
01744 buf_block_t* block = chunk->blocks;
01745
01746 for (j = 0; j < chunk->size; j++, block++) {
01747 if (buf_block_get_state(block)
01748 == BUF_BLOCK_FILE_PAGE) {
01749 ut_ad(!block->page.in_zip_hash);
01750 ut_ad(block->page.in_page_hash);
01751
01752 HASH_INSERT(buf_page_t, hash, page_hash,
01753 buf_page_address_fold(
01754 block->page.space,
01755 block->page.offset),
01756 &block->page);
01757 }
01758 }
01759 }
01760
01761
01762
01763
01764
01765 for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
01766 b = UT_LIST_GET_NEXT(list, b)) {
01767 ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
01768 ut_ad(!b->in_flush_list);
01769 ut_ad(b->in_LRU_list);
01770 ut_ad(b->in_page_hash);
01771 ut_ad(!b->in_zip_hash);
01772
01773 HASH_INSERT(buf_page_t, hash, page_hash,
01774 buf_page_address_fold(b->space, b->offset), b);
01775 }
01776
01777 buf_flush_list_mutex_enter(buf_pool);
01778 for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
01779 b = UT_LIST_GET_NEXT(list, b)) {
01780 ut_ad(b->in_flush_list);
01781 ut_ad(b->in_LRU_list);
01782 ut_ad(b->in_page_hash);
01783 ut_ad(!b->in_zip_hash);
01784
01785 switch (buf_page_get_state(b)) {
01786 case BUF_BLOCK_ZIP_DIRTY:
01787 HASH_INSERT(buf_page_t, hash, page_hash,
01788 buf_page_address_fold(b->space,
01789 b->offset), b);
01790 break;
01791 case BUF_BLOCK_FILE_PAGE:
01792
01793 break;
01794 case BUF_BLOCK_ZIP_FREE:
01795 case BUF_BLOCK_ZIP_PAGE:
01796 case BUF_BLOCK_NOT_USED:
01797 case BUF_BLOCK_READY_FOR_USE:
01798 case BUF_BLOCK_MEMORY:
01799 case BUF_BLOCK_REMOVE_HASH:
01800 ut_error;
01801 break;
01802 }
01803 }
01804
01805 buf_flush_list_mutex_exit(buf_pool);
01806 buf_pool_mutex_exit(buf_pool);
01807 }
01808
01809
01810
01811
01812 UNIV_INTERN
01813 ibool
01814 buf_pool_watch_is_sentinel(
01815
01816 buf_pool_t* buf_pool,
01817 const buf_page_t* bpage)
01818 {
01819 ut_ad(buf_page_in_file(bpage));
01820
01821 if (bpage < &buf_pool->watch[0]
01822 || bpage >= &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
01823
01824 ut_ad(buf_page_get_state(bpage) != BUF_BLOCK_ZIP_PAGE
01825 || bpage->zip.data != NULL);
01826
01827 return(FALSE);
01828 }
01829
01830 ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
01831 ut_ad(!bpage->in_zip_hash);
01832 ut_ad(bpage->in_page_hash);
01833 ut_ad(bpage->zip.data == NULL);
01834 ut_ad(bpage->buf_fix_count > 0);
01835 return(TRUE);
01836 }
01837
01838
01842 UNIV_INTERN
01843 buf_page_t*
01844 buf_pool_watch_set(
01845
01846 ulint space,
01847 ulint offset,
01848 ulint fold)
01849 {
01850 buf_page_t* bpage;
01851 ulint i;
01852 buf_pool_t* buf_pool = buf_pool_get(space, offset);
01853
01854 ut_ad(buf_pool_mutex_own(buf_pool));
01855
01856 bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
01857
01858 if (UNIV_LIKELY_NULL(bpage)) {
01859 if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
01860
01861 return(bpage);
01862 }
01863
01864 bpage->buf_fix_count++;
01865 return(NULL);
01866 }
01867
01868 for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
01869 bpage = &buf_pool->watch[i];
01870
01871 ut_ad(bpage->access_time == 0);
01872 ut_ad(bpage->newest_modification == 0);
01873 ut_ad(bpage->oldest_modification == 0);
01874 ut_ad(bpage->zip.data == NULL);
01875 ut_ad(!bpage->in_zip_hash);
01876
01877 switch (bpage->state) {
01878 case BUF_BLOCK_POOL_WATCH:
01879 ut_ad(!bpage->in_page_hash);
01880 ut_ad(bpage->buf_fix_count == 0);
01881
01882
01883
01884
01885
01886
01887 bpage->state = BUF_BLOCK_ZIP_PAGE;
01888 bpage->space = space;
01889 bpage->offset = offset;
01890 bpage->buf_fix_count = 1;
01891
01892 ut_d(bpage->in_page_hash = TRUE);
01893 HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
01894 fold, bpage);
01895 return(NULL);
01896 case BUF_BLOCK_ZIP_PAGE:
01897 ut_ad(bpage->in_page_hash);
01898 ut_ad(bpage->buf_fix_count > 0);
01899 break;
01900 default:
01901 ut_error;
01902 }
01903 }
01904
01905
01906
01907
01908
01909 ut_error;
01910
01911
01912 return(NULL);
01913 }
01914
01915
01917 static
01918 void
01919 buf_pool_page_hash_rebuild(void)
01920
01921 {
01922 ulint i;
01923
01924 for (i = 0; i < srv_buf_pool_instances; i++) {
01925 buf_pool_page_hash_rebuild_instance(buf_pool_from_array(i));
01926 }
01927 }
01928
01929
01931 static
01932 void
01933 buf_pool_increase_instance(
01934
01935 buf_pool_t* buf_pool,
01936 ulint change_size)
01937 {
01938 buf_chunk_t* chunks;
01939 buf_chunk_t* chunk;
01940
01941 buf_pool_mutex_enter(buf_pool);
01942 chunks = static_cast<buf_chunk_t *>(mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks));
01943
01944 memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks * sizeof *chunks);
01945
01946 chunk = &chunks[buf_pool->n_chunks];
01947
01948 if (!buf_chunk_init(buf_pool, chunk, change_size)) {
01949 mem_free(chunks);
01950 } else {
01951 buf_pool->old_pool_size = buf_pool->curr_pool_size;
01952 buf_pool->curr_size += chunk->size;
01953 buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
01954 mem_free(buf_pool->chunks);
01955 buf_pool->chunks = chunks;
01956 buf_pool->n_chunks++;
01957 }
01958
01959 buf_pool_mutex_exit(buf_pool);
01960 }
01961
01962
01964 static
01965 void
01966 buf_pool_increase(
01967
01968 ulint change_size)
01969 {
01970 ulint i;
01971
01972 for (i = 0; i < srv_buf_pool_instances; i++) {
01973 buf_pool_increase_instance(
01974 buf_pool_from_array(i),
01975 change_size / srv_buf_pool_instances);
01976 }
01977
01978 buf_pool_set_sizes();
01979 }
01980
01981
01983 UNIV_INTERN
01984 void
01985 buf_pool_resize(void)
01986
01987 {
01988 ulint change_size;
01989 ulint min_change_size = 1048576 * srv_buf_pool_instances;
01990
01991 buf_pool_mutex_enter_all();
01992
01993 if (srv_buf_pool_old_size == srv_buf_pool_size) {
01994
01995 buf_pool_mutex_exit_all();
01996
01997 return;
01998
01999 } else if (srv_buf_pool_curr_size + min_change_size
02000 > srv_buf_pool_size) {
02001
02002 change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
02003 / UNIV_PAGE_SIZE;
02004
02005 buf_pool_mutex_exit_all();
02006
02007
02008
02009 buf_pool_shrink(change_size);
02010
02011 } else if (srv_buf_pool_curr_size + min_change_size
02012 < srv_buf_pool_size) {
02013
02014
02015
02016 change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
02017
02018 buf_pool_mutex_exit_all();
02019
02020 buf_pool_increase(change_size);
02021 } else {
02022 srv_buf_pool_size = srv_buf_pool_old_size;
02023
02024 buf_pool_mutex_exit_all();
02025
02026 return;
02027 }
02028
02029 buf_pool_page_hash_rebuild();
02030 }
02031
02032
02037 static
02038 void
02039 buf_pool_watch_remove(
02040
02041 buf_pool_t* buf_pool,
02042 ulint fold,
02044 buf_page_t* watch)
02045 {
02046 ut_ad(buf_pool_mutex_own(buf_pool));
02047
02048 HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
02049 ut_d(watch->in_page_hash = FALSE);
02050 watch->buf_fix_count = 0;
02051 watch->state = BUF_BLOCK_POOL_WATCH;
02052 }
02053
02054
02057 UNIV_INTERN
02058 void
02059 buf_pool_watch_unset(
02060
02061 ulint space,
02062 ulint offset)
02063 {
02064 buf_page_t* bpage;
02065 buf_pool_t* buf_pool = buf_pool_get(space, offset);
02066 ulint fold = buf_page_address_fold(space, offset);
02067
02068 buf_pool_mutex_enter(buf_pool);
02069 bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
02070
02071
02072 ut_a(bpage);
02073
02074 if (UNIV_UNLIKELY(!buf_pool_watch_is_sentinel(buf_pool, bpage))) {
02075 mutex_t* mutex = buf_page_get_mutex(bpage);
02076
02077 mutex_enter(mutex);
02078 ut_a(bpage->buf_fix_count > 0);
02079 bpage->buf_fix_count--;
02080 mutex_exit(mutex);
02081 } else {
02082 ut_a(bpage->buf_fix_count > 0);
02083
02084 if (UNIV_LIKELY(!--bpage->buf_fix_count)) {
02085 buf_pool_watch_remove(buf_pool, fold, bpage);
02086 }
02087 }
02088
02089 buf_pool_mutex_exit(buf_pool);
02090 }
02091
02092
02097 UNIV_INTERN
02098 ibool
02099 buf_pool_watch_occurred(
02100
02101 ulint space,
02102 ulint offset)
02103 {
02104 ibool ret;
02105 buf_page_t* bpage;
02106 buf_pool_t* buf_pool = buf_pool_get(space, offset);
02107 ulint fold = buf_page_address_fold(space, offset);
02108
02109 buf_pool_mutex_enter(buf_pool);
02110
02111 bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
02112
02113
02114 ut_a(bpage);
02115 ret = !buf_pool_watch_is_sentinel(buf_pool, bpage);
02116 buf_pool_mutex_exit(buf_pool);
02117
02118 return(ret);
02119 }
02120
02121
02125 UNIV_INTERN
02126 void
02127 buf_page_make_young(
02128
02129 buf_page_t* bpage)
02130 {
02131 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
02132
02133 buf_pool_mutex_enter(buf_pool);
02134
02135 ut_a(buf_page_in_file(bpage));
02136
02137 buf_LRU_make_block_young(bpage);
02138
02139 buf_pool_mutex_exit(buf_pool);
02140 }
02141
02142
02147 static
02148 void
02149 buf_page_set_accessed_make_young(
02150
02151 buf_page_t* bpage,
02153 unsigned access_time)
02156 {
02157 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
02158
02159 ut_ad(!buf_pool_mutex_own(buf_pool));
02160 ut_a(buf_page_in_file(bpage));
02161
02162 if (buf_page_peek_if_too_old(bpage)) {
02163 buf_pool_mutex_enter(buf_pool);
02164 buf_LRU_make_block_young(bpage);
02165 buf_pool_mutex_exit(buf_pool);
02166 } else if (!access_time) {
02167 ulint time_ms = ut_time_ms();
02168 buf_pool_mutex_enter(buf_pool);
02169 buf_page_set_accessed(bpage, time_ms);
02170 buf_pool_mutex_exit(buf_pool);
02171 }
02172 }
02173
02174
02177 UNIV_INTERN
02178 void
02179 buf_reset_check_index_page_at_flush(
02180
02181 ulint space,
02182 ulint offset)
02183 {
02184 buf_block_t* block;
02185 buf_pool_t* buf_pool = buf_pool_get(space, offset);
02186
02187 buf_pool_mutex_enter(buf_pool);
02188
02189 block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
02190
02191 if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
02192 ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
02193 block->check_index_page_at_flush = FALSE;
02194 }
02195
02196 buf_pool_mutex_exit(buf_pool);
02197 }
02198
02199
02204 UNIV_INTERN
02205 ibool
02206 buf_page_peek_if_search_hashed(
02207
02208 ulint space,
02209 ulint offset)
02210 {
02211 buf_block_t* block;
02212 ibool is_hashed;
02213 buf_pool_t* buf_pool = buf_pool_get(space, offset);
02214
02215 buf_pool_mutex_enter(buf_pool);
02216
02217 block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
02218
02219 if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
02220 is_hashed = FALSE;
02221 } else {
02222 ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
02223 is_hashed = block->is_hashed;
02224 }
02225
02226 buf_pool_mutex_exit(buf_pool);
02227
02228 return(is_hashed);
02229 }
02230
02231 #ifdef UNIV_DEBUG_FILE_ACCESSES
02232
02238 UNIV_INTERN
02239 buf_page_t*
02240 buf_page_set_file_page_was_freed(
02241
02242 ulint space,
02243 ulint offset)
02244 {
02245 buf_page_t* bpage;
02246 buf_pool_t* buf_pool = buf_pool_get(space, offset);
02247
02248 buf_pool_mutex_enter(buf_pool);
02249
02250 bpage = buf_page_hash_get(buf_pool, space, offset);
02251
02252 if (bpage) {
02253 ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
02254 bpage->file_page_was_freed = TRUE;
02255 }
02256
02257 buf_pool_mutex_exit(buf_pool);
02258
02259 return(bpage);
02260 }
02261
02262
02268 UNIV_INTERN
02269 buf_page_t*
02270 buf_page_reset_file_page_was_freed(
02271
02272 ulint space,
02273 ulint offset)
02274 {
02275 buf_page_t* bpage;
02276 buf_pool_t* buf_pool = buf_pool_get(space, offset);
02277
02278 buf_pool_mutex_enter(buf_pool);
02279
02280 bpage = buf_page_hash_get(buf_pool, space, offset);
02281
02282 if (bpage) {
02283 ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
02284 bpage->file_page_was_freed = FALSE;
02285 }
02286
02287 buf_pool_mutex_exit(buf_pool);
02288
02289 return(bpage);
02290 }
02291 #endif
02292
02293
02302 UNIV_INTERN
02303 buf_page_t*
02304 buf_page_get_zip(
02305
02306 ulint space,
02307 ulint zip_size,
02308 ulint offset)
02309 {
02310 buf_page_t* bpage;
02311 mutex_t* block_mutex;
02312 ibool must_read;
02313 unsigned access_time;
02314 buf_pool_t* buf_pool = buf_pool_get(space, offset);
02315
02316 #ifndef UNIV_LOG_DEBUG
02317 ut_ad(!ibuf_inside());
02318 #endif
02319 buf_pool->stat.n_page_gets++;
02320
02321 for (;;) {
02322 buf_pool_mutex_enter(buf_pool);
02323 lookup:
02324 bpage = buf_page_hash_get(buf_pool, space, offset);
02325 if (bpage) {
02326 ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
02327 break;
02328 }
02329
02330
02331
02332 buf_pool_mutex_exit(buf_pool);
02333
02334 buf_read_page(space, zip_size, offset);
02335
02336 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
02337 ut_a(++buf_dbg_counter % 37 || buf_validate());
02338 #endif
02339 }
02340
02341 if (UNIV_UNLIKELY(!bpage->zip.data)) {
02342
02343 err_exit:
02344 buf_pool_mutex_exit(buf_pool);
02345 return(NULL);
02346 }
02347
02348 ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
02349
02350 switch (buf_page_get_state(bpage)) {
02351 case BUF_BLOCK_NOT_USED:
02352 case BUF_BLOCK_READY_FOR_USE:
02353 case BUF_BLOCK_MEMORY:
02354 case BUF_BLOCK_REMOVE_HASH:
02355 case BUF_BLOCK_ZIP_FREE:
02356 break;
02357 case BUF_BLOCK_ZIP_PAGE:
02358 case BUF_BLOCK_ZIP_DIRTY:
02359 block_mutex = &buf_pool->zip_mutex;
02360 mutex_enter(block_mutex);
02361 bpage->buf_fix_count++;
02362 goto got_block;
02363 case BUF_BLOCK_FILE_PAGE:
02364 block_mutex = &((buf_block_t*) bpage)->mutex;
02365 mutex_enter(block_mutex);
02366
02367
02368 if (buf_LRU_free_block(bpage, FALSE, NULL)
02369 == BUF_LRU_FREED) {
02370
02371 mutex_exit(block_mutex);
02372 goto lookup;
02373 }
02374
02375 buf_block_buf_fix_inc((buf_block_t*) bpage,
02376 __FILE__, __LINE__);
02377 goto got_block;
02378 }
02379
02380 ut_error;
02381 goto err_exit;
02382
02383 got_block:
02384 must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
02385 access_time = buf_page_is_accessed(bpage);
02386
02387 buf_pool_mutex_exit(buf_pool);
02388
02389 mutex_exit(block_mutex);
02390
02391 buf_page_set_accessed_make_young(bpage, access_time);
02392
02393 #ifdef UNIV_DEBUG_FILE_ACCESSES
02394 ut_a(!bpage->file_page_was_freed);
02395 #endif
02396
02397 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
02398 ut_a(++buf_dbg_counter % 5771 || buf_validate());
02399 ut_a(bpage->buf_fix_count > 0);
02400 ut_a(buf_page_in_file(bpage));
02401 #endif
02402
02403 if (must_read) {
02404
02405
02406
02407 for (;;) {
02408 enum buf_io_fix io_fix;
02409
02410 mutex_enter(block_mutex);
02411 io_fix = buf_page_get_io_fix(bpage);
02412 mutex_exit(block_mutex);
02413
02414 if (io_fix == BUF_IO_READ) {
02415
02416 os_thread_sleep(WAIT_FOR_READ);
02417 } else {
02418 break;
02419 }
02420 }
02421 }
02422
02423 #ifdef UNIV_IBUF_COUNT_DEBUG
02424 ut_a(ibuf_count_get(buf_page_get_space(bpage),
02425 buf_page_get_page_no(bpage)) == 0);
02426 #endif
02427 return(bpage);
02428 }
02429
02430
02432 UNIV_INLINE
02433 void
02434 buf_block_init_low(
02435
02436 buf_block_t* block)
02437 {
02438 block->check_index_page_at_flush = FALSE;
02439 block->index = NULL;
02440
02441 block->n_hash_helps = 0;
02442 block->is_hashed = FALSE;
02443 block->n_fields = 1;
02444 block->n_bytes = 0;
02445 block->left_side = TRUE;
02446 }
02447 #endif
02448
02449
02452 UNIV_INTERN
02453 ibool
02454 buf_zip_decompress(
02455
02456 buf_block_t* block,
02457 ibool check)
02458 {
02459 const byte* frame = block->page.zip.data;
02460 ulint stamp_checksum = mach_read_from_4(
02461 frame + FIL_PAGE_SPACE_OR_CHKSUM);
02462
02463 ut_ad(buf_block_get_zip_size(block));
02464 ut_a(buf_block_get_space(block) != 0);
02465
02466 if (UNIV_LIKELY(check && stamp_checksum != BUF_NO_CHECKSUM_MAGIC)) {
02467 ulint calc_checksum = page_zip_calc_checksum(
02468 frame, page_zip_get_size(&block->page.zip));
02469
02470 if (UNIV_UNLIKELY(stamp_checksum != calc_checksum)) {
02471 ut_print_timestamp(stderr);
02472 fprintf(stderr,
02473 " InnoDB: compressed page checksum mismatch"
02474 " (space %u page %u): %lu != %lu\n",
02475 block->page.space, block->page.offset,
02476 stamp_checksum, calc_checksum);
02477 return(FALSE);
02478 }
02479 }
02480
02481 switch (fil_page_get_type(frame)) {
02482 case FIL_PAGE_INDEX:
02483 if (page_zip_decompress(&block->page.zip,
02484 block->frame, TRUE)) {
02485 return(TRUE);
02486 }
02487
02488 fprintf(stderr,
02489 "InnoDB: unable to decompress space %lu page %lu\n",
02490 (ulong) block->page.space,
02491 (ulong) block->page.offset);
02492 return(FALSE);
02493
02494 case FIL_PAGE_TYPE_ALLOCATED:
02495 case FIL_PAGE_INODE:
02496 case FIL_PAGE_IBUF_BITMAP:
02497 case FIL_PAGE_TYPE_FSP_HDR:
02498 case FIL_PAGE_TYPE_XDES:
02499 case FIL_PAGE_TYPE_ZBLOB:
02500 case FIL_PAGE_TYPE_ZBLOB2:
02501
02502 memcpy(block->frame, frame,
02503 buf_block_get_zip_size(block));
02504 return(TRUE);
02505 }
02506
02507 ut_print_timestamp(stderr);
02508 fprintf(stderr,
02509 " InnoDB: unknown compressed page"
02510 " type %lu\n",
02511 fil_page_get_type(frame));
02512 return(FALSE);
02513 }
02514
02515 #ifndef UNIV_HOTBACKUP
02516
02520 static
02521 buf_block_t*
02522 buf_block_align_instance(
02523
02524 buf_pool_t* buf_pool,
02526 const byte* ptr)
02527 {
02528 buf_chunk_t* chunk;
02529 ulint i;
02530
02531
02532
02533 for (chunk = buf_pool->chunks, i = buf_pool->n_chunks; i--; chunk++) {
02534 lint offs = ptr - chunk->blocks->frame;
02535
02536 if (UNIV_UNLIKELY(offs < 0)) {
02537
02538 continue;
02539 }
02540
02541 offs >>= UNIV_PAGE_SIZE_SHIFT;
02542
02543 if (UNIV_LIKELY((ulint) offs < chunk->size)) {
02544 buf_block_t* block = &chunk->blocks[offs];
02545
02546
02547
02548
02549 ut_ad(block->frame == page_align(ptr));
02550 #ifdef UNIV_DEBUG
02551
02552
02553
02554 mutex_enter(&block->mutex);
02555
02556 switch (buf_block_get_state(block)) {
02557 case BUF_BLOCK_ZIP_FREE:
02558 case BUF_BLOCK_ZIP_PAGE:
02559 case BUF_BLOCK_ZIP_DIRTY:
02560
02561
02562
02563
02564
02565 ut_error;
02566 break;
02567 case BUF_BLOCK_NOT_USED:
02568 case BUF_BLOCK_READY_FOR_USE:
02569 case BUF_BLOCK_MEMORY:
02570
02571
02572
02573
02574 break;
02575 case BUF_BLOCK_REMOVE_HASH:
02576
02577
02578
02579
02580
02581 ut_ad(page_get_space_id(page_align(ptr))
02582 == 0xffffffff);
02583 ut_ad(page_get_page_no(page_align(ptr))
02584 == 0xffffffff);
02585 break;
02586 case BUF_BLOCK_FILE_PAGE:
02587 ut_ad(block->page.space
02588 == page_get_space_id(page_align(ptr)));
02589 ut_ad(block->page.offset
02590 == page_get_page_no(page_align(ptr)));
02591 break;
02592 }
02593
02594 mutex_exit(&block->mutex);
02595 #endif
02596
02597 return(block);
02598 }
02599 }
02600
02601 return(NULL);
02602 }
02603
02604
02607 UNIV_INTERN
02608 buf_block_t*
02609 buf_block_align(
02610
02611 const byte* ptr)
02612 {
02613 ulint i;
02614
02615 for (i = 0; i < srv_buf_pool_instances; i++) {
02616 buf_block_t* block;
02617
02618 block = buf_block_align_instance(
02619 buf_pool_from_array(i), ptr);
02620 if (block) {
02621 return(block);
02622 }
02623 }
02624
02625
02626 ut_error;
02627 return(NULL);
02628 }
02629
02630
02635 static
02636 ibool
02637 buf_pointer_is_block_field_instance(
02638
02639 buf_pool_t* buf_pool,
02640 const void* ptr)
02641 {
02642 const buf_chunk_t* chunk = buf_pool->chunks;
02643 const buf_chunk_t* const echunk = chunk + buf_pool->n_chunks;
02644
02645
02646
02647 while (chunk < echunk) {
02648 if (ptr >= (void *)chunk->blocks
02649 && ptr < (void *)(chunk->blocks + chunk->size)) {
02650
02651 return(TRUE);
02652 }
02653
02654 chunk++;
02655 }
02656
02657 return(FALSE);
02658 }
02659
02660
02664 UNIV_INTERN
02665 ibool
02666 buf_pointer_is_block_field(
02667
02668 const void* ptr)
02669 {
02670 ulint i;
02671
02672 for (i = 0; i < srv_buf_pool_instances; i++) {
02673 ibool found;
02674
02675 found = buf_pointer_is_block_field_instance(
02676 buf_pool_from_array(i), ptr);
02677 if (found) {
02678 return(TRUE);
02679 }
02680 }
02681
02682 return(FALSE);
02683 }
02684
02685
02688 static
02689 ibool
02690 buf_block_is_uncompressed(
02691
02692 buf_pool_t* buf_pool,
02693 const buf_block_t* block)
02695 {
02696 ut_ad(buf_pool_mutex_own(buf_pool));
02697
02698 if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
02699
02700 return(FALSE);
02701 }
02702
02703 return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
02704 }
02705
02706
02709 UNIV_INTERN
02710 buf_block_t*
02711 buf_page_get_gen(
02712
02713 ulint space,
02714 ulint zip_size,
02716 ulint offset,
02717 ulint rw_latch,
02718 buf_block_t* guess,
02719 ulint mode,
02722 const char* file,
02723 ulint line,
02724 mtr_t* mtr)
02725 {
02726 buf_block_t* block;
02727 ulint fold;
02728 unsigned access_time;
02729 ulint fix_type;
02730 ibool must_read;
02731 ulint retries = 0;
02732 buf_pool_t* buf_pool = buf_pool_get(space, offset);
02733
02734 ut_ad(mtr);
02735 ut_ad(mtr->state == MTR_ACTIVE);
02736 ut_ad((rw_latch == RW_S_LATCH)
02737 || (rw_latch == RW_X_LATCH)
02738 || (rw_latch == RW_NO_LATCH));
02739 ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
02740 ut_ad(mode == BUF_GET
02741 || mode == BUF_GET_IF_IN_POOL
02742 || mode == BUF_GET_NO_LATCH
02743 || mode == BUF_GET_IF_IN_POOL_OR_WATCH);
02744 ut_ad(zip_size == fil_space_get_zip_size(space));
02745 ut_ad(ut_is_2pow(zip_size));
02746 #ifndef UNIV_LOG_DEBUG
02747 ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
02748 #endif
02749 buf_pool->stat.n_page_gets++;
02750 fold = buf_page_address_fold(space, offset);
02751 loop:
02752 block = guess;
02753 buf_pool_mutex_enter(buf_pool);
02754
02755 if (block) {
02756
02757
02758
02759
02760
02761
02762
02763
02764 if (!buf_block_is_uncompressed(buf_pool, block)
02765 || offset != block->page.offset
02766 || space != block->page.space
02767 || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
02768
02769 block = guess = NULL;
02770 } else {
02771 ut_ad(!block->page.in_zip_hash);
02772 ut_ad(block->page.in_page_hash);
02773 }
02774 }
02775
02776 if (block == NULL) {
02777 block = (buf_block_t*) buf_page_hash_get_low(
02778 buf_pool, space, offset, fold);
02779 }
02780
02781 loop2:
02782 if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
02783 block = NULL;
02784 }
02785
02786 if (block == NULL) {
02787
02788
02789 if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
02790 block = (buf_block_t*) buf_pool_watch_set(
02791 space, offset, fold);
02792
02793 if (UNIV_LIKELY_NULL(block)) {
02794
02795 goto got_block;
02796 }
02797 }
02798
02799 buf_pool_mutex_exit(buf_pool);
02800
02801 if (mode == BUF_GET_IF_IN_POOL
02802 || mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
02803
02804 return(NULL);
02805 }
02806
02807 if (buf_read_page(space, zip_size, offset)) {
02808 retries = 0;
02809 } else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
02810 ++retries;
02811 } else {
02812 fprintf(stderr, "InnoDB: Error: Unable"
02813 " to read tablespace %lu page no"
02814 " %lu into the buffer pool after"
02815 " %lu attempts\n"
02816 "InnoDB: The most probable cause"
02817 " of this error may be that the"
02818 " table has been corrupted.\n"
02819 "InnoDB: You can try to fix this"
02820 " problem by using"
02821 " innodb_force_recovery.\n"
02822 "InnoDB: Please see reference manual"
02823 " for more details.\n"
02824 "InnoDB: Aborting...\n",
02825 space, offset,
02826 BUF_PAGE_READ_MAX_RETRIES);
02827
02828 ut_error;
02829 }
02830
02831 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
02832 ut_a(++buf_dbg_counter % 37 || buf_validate());
02833 #endif
02834 goto loop;
02835 }
02836
02837 got_block:
02838 ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
02839
02840 must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
02841
02842 if (must_read && mode == BUF_GET_IF_IN_POOL) {
02843
02844
02845
02846
02847 buf_pool_mutex_exit(buf_pool);
02848
02849 return(NULL);
02850 }
02851
02852 switch (buf_block_get_state(block)) {
02853 buf_page_t* bpage;
02854 ibool success;
02855
02856 case BUF_BLOCK_FILE_PAGE:
02857 break;
02858
02859 case BUF_BLOCK_ZIP_PAGE:
02860 case BUF_BLOCK_ZIP_DIRTY:
02861 bpage = &block->page;
02862
02863 mutex_enter(&buf_pool->zip_mutex);
02864
02865 if (bpage->buf_fix_count
02866 || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
02867
02868
02869
02870 mutex_exit(&buf_pool->zip_mutex);
02871 wait_until_unfixed:
02872
02873
02874 buf_pool_mutex_exit(buf_pool);
02875 os_thread_sleep(WAIT_FOR_READ);
02876
02877 goto loop;
02878 }
02879
02880
02881 buf_pool_mutex_exit(buf_pool);
02882 mutex_exit(&buf_pool->zip_mutex);
02883
02884 block = buf_LRU_get_free_block(buf_pool, 0);
02885 ut_a(block);
02886
02887 buf_pool_mutex_enter(buf_pool);
02888 mutex_enter(&block->mutex);
02889
02890 {
02891 buf_page_t* hash_bpage;
02892
02893 hash_bpage = buf_page_hash_get_low(
02894 buf_pool, space, offset, fold);
02895
02896 if (UNIV_UNLIKELY(bpage != hash_bpage)) {
02897
02898
02899
02900
02901 buf_LRU_block_free_non_file_page(block);
02902 mutex_exit(&block->mutex);
02903
02904 block = (buf_block_t*) hash_bpage;
02905 goto loop2;
02906 }
02907 }
02908
02909 if (UNIV_UNLIKELY
02910 (bpage->buf_fix_count
02911 || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
02912
02913
02914
02915
02916
02917
02918 buf_LRU_block_free_non_file_page(block);
02919 mutex_exit(&block->mutex);
02920
02921 goto wait_until_unfixed;
02922 }
02923
02924
02925
02926
02927 mutex_enter(&buf_pool->zip_mutex);
02928
02929 buf_relocate(bpage, &block->page);
02930 buf_block_init_low(block);
02931 block->lock_hash_val = lock_rec_hash(space, offset);
02932
02933 UNIV_MEM_DESC(&block->page.zip.data,
02934 page_zip_get_size(&block->page.zip), block);
02935
02936 if (buf_page_get_state(&block->page)
02937 == BUF_BLOCK_ZIP_PAGE) {
02938 UT_LIST_REMOVE(list, buf_pool->zip_clean,
02939 &block->page);
02940 ut_ad(!block->page.in_flush_list);
02941 } else {
02942
02943 buf_flush_relocate_on_flush_list(bpage,
02944 &block->page);
02945 }
02946
02947
02948
02949
02950 block->page.state = BUF_BLOCK_FILE_PAGE;
02951
02952
02953 buf_unzip_LRU_add_block(block, FALSE);
02954
02955 block->page.buf_fix_count = 1;
02956 buf_block_set_io_fix(block, BUF_IO_READ);
02957 rw_lock_x_lock_func(&block->lock, 0, file, line);
02958
02959 UNIV_MEM_INVALID(bpage, sizeof *bpage);
02960
02961 mutex_exit(&block->mutex);
02962 mutex_exit(&buf_pool->zip_mutex);
02963 buf_pool->n_pend_unzip++;
02964
02965 buf_buddy_free(buf_pool, bpage, sizeof *bpage);
02966
02967 buf_pool_mutex_exit(buf_pool);
02968
02969
02970
02971 success = buf_zip_decompress(block, srv_use_checksums);
02972 ut_a(success);
02973
02974 if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
02975 ibuf_merge_or_delete_for_page(block, space, offset,
02976 zip_size, TRUE);
02977 }
02978
02979
02980 buf_pool_mutex_enter(buf_pool);
02981 mutex_enter(&block->mutex);
02982 block->page.buf_fix_count--;
02983 buf_block_set_io_fix(block, BUF_IO_NONE);
02984 mutex_exit(&block->mutex);
02985 buf_pool->n_pend_unzip--;
02986 rw_lock_x_unlock(&block->lock);
02987
02988 break;
02989
02990 case BUF_BLOCK_ZIP_FREE:
02991 case BUF_BLOCK_NOT_USED:
02992 case BUF_BLOCK_READY_FOR_USE:
02993 case BUF_BLOCK_MEMORY:
02994 case BUF_BLOCK_REMOVE_HASH:
02995 ut_error;
02996 break;
02997 }
02998
02999 ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
03000
03001 mutex_enter(&block->mutex);
03002 #if UNIV_WORD_SIZE == 4
03003
03004
03005
03006 UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
03007 #endif
03008 #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
03009 if ((mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH)
03010 && ibuf_debug) {
03011
03012
03013
03014 if (buf_LRU_free_block(&block->page, TRUE, NULL)
03015 == BUF_LRU_FREED) {
03016 mutex_exit(&block->mutex);
03017 if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
03018
03019
03020
03021 block = (buf_block_t*) buf_pool_watch_set(
03022 space, offset, fold);
03023
03024 if (UNIV_LIKELY_NULL(block)) {
03025
03026
03027
03028
03029 goto got_block;
03030 }
03031 }
03032 buf_pool_mutex_exit(buf_pool);
03033 fprintf(stderr,
03034 "innodb_change_buffering_debug evict %u %u\n",
03035 (unsigned) space, (unsigned) offset);
03036 return(NULL);
03037 } else if (buf_flush_page_try(buf_pool, block)) {
03038 fprintf(stderr,
03039 "innodb_change_buffering_debug flush %u %u\n",
03040 (unsigned) space, (unsigned) offset);
03041 guess = block;
03042 goto loop;
03043 }
03044
03045
03046 }
03047 #endif
03048
03049 buf_block_buf_fix_inc(block, file, line);
03050
03051 mutex_exit(&block->mutex);
03052
03053
03054
03055 access_time = buf_page_is_accessed(&block->page);
03056
03057 buf_pool_mutex_exit(buf_pool);
03058
03059 buf_page_set_accessed_make_young(&block->page, access_time);
03060
03061 #ifdef UNIV_DEBUG_FILE_ACCESSES
03062 ut_a(!block->page.file_page_was_freed);
03063 #endif
03064
03065 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
03066 ut_a(++buf_dbg_counter % 5771 || buf_validate());
03067 ut_a(block->page.buf_fix_count > 0);
03068 ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
03069 #endif
03070
03071 switch (rw_latch) {
03072 case RW_NO_LATCH:
03073 if (must_read) {
03074
03075
03076
03077 for (;;) {
03078 enum buf_io_fix io_fix;
03079
03080 mutex_enter(&block->mutex);
03081 io_fix = buf_block_get_io_fix(block);
03082 mutex_exit(&block->mutex);
03083
03084 if (io_fix == BUF_IO_READ) {
03085
03086 os_thread_sleep(WAIT_FOR_READ);
03087 } else {
03088 break;
03089 }
03090 }
03091 }
03092
03093 fix_type = MTR_MEMO_BUF_FIX;
03094 break;
03095
03096 case RW_S_LATCH:
03097 rw_lock_s_lock_func(&(block->lock), 0, file, line);
03098
03099 fix_type = MTR_MEMO_PAGE_S_FIX;
03100 break;
03101
03102 default:
03103 ut_ad(rw_latch == RW_X_LATCH);
03104 rw_lock_x_lock_func(&(block->lock), 0, file, line);
03105
03106 fix_type = MTR_MEMO_PAGE_X_FIX;
03107 break;
03108 }
03109
03110 mtr_memo_push(mtr, block, fix_type);
03111
03112 if (!access_time) {
03113
03114
03115
03116 buf_read_ahead_linear(space, zip_size, offset);
03117 }
03118
03119 #ifdef UNIV_IBUF_COUNT_DEBUG
03120 ut_a(ibuf_count_get(buf_block_get_space(block),
03121 buf_block_get_page_no(block)) == 0);
03122 #endif
03123 return(block);
03124 }
03125
03126
03130 UNIV_INTERN
03131 ibool
03132 buf_page_optimistic_get(
03133
03134 ulint rw_latch,
03135 buf_block_t* block,
03136 ib_uint64_t modify_clock,
03138 const char* file,
03139 ulint line,
03140 mtr_t* mtr)
03141 {
03142 buf_pool_t* buf_pool;
03143 unsigned access_time;
03144 ibool success;
03145 ulint fix_type;
03146
03147 ut_ad(block);
03148 ut_ad(mtr);
03149 ut_ad(mtr->state == MTR_ACTIVE);
03150 ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
03151
03152 mutex_enter(&block->mutex);
03153
03154 if (UNIV_UNLIKELY(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE)) {
03155
03156 mutex_exit(&block->mutex);
03157
03158 return(FALSE);
03159 }
03160
03161 buf_block_buf_fix_inc(block, file, line);
03162
03163 mutex_exit(&block->mutex);
03164
03165
03166
03167
03168
03169
03170 access_time = buf_page_is_accessed(&block->page);
03171 buf_page_set_accessed_make_young(&block->page, access_time);
03172
03173 ut_ad(!ibuf_inside()
03174 || ibuf_page(buf_block_get_space(block),
03175 buf_block_get_zip_size(block),
03176 buf_block_get_page_no(block), NULL));
03177
03178 if (rw_latch == RW_S_LATCH) {
03179 success = rw_lock_s_lock_nowait(&(block->lock),
03180 file, line);
03181 fix_type = MTR_MEMO_PAGE_S_FIX;
03182 } else {
03183 success = rw_lock_x_lock_func_nowait(&(block->lock),
03184 file, line);
03185 fix_type = MTR_MEMO_PAGE_X_FIX;
03186 }
03187
03188 if (UNIV_UNLIKELY(!success)) {
03189 mutex_enter(&block->mutex);
03190 buf_block_buf_fix_dec(block);
03191 mutex_exit(&block->mutex);
03192
03193 return(FALSE);
03194 }
03195
03196 if (UNIV_UNLIKELY(modify_clock != block->modify_clock)) {
03197 buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
03198
03199 if (rw_latch == RW_S_LATCH) {
03200 rw_lock_s_unlock(&(block->lock));
03201 } else {
03202 rw_lock_x_unlock(&(block->lock));
03203 }
03204
03205 mutex_enter(&block->mutex);
03206 buf_block_buf_fix_dec(block);
03207 mutex_exit(&block->mutex);
03208
03209 return(FALSE);
03210 }
03211
03212 mtr_memo_push(mtr, block, fix_type);
03213
03214 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
03215 ut_a(++buf_dbg_counter % 5771 || buf_validate());
03216 ut_a(block->page.buf_fix_count > 0);
03217 ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
03218 #endif
03219
03220 #ifdef UNIV_DEBUG_FILE_ACCESSES
03221 ut_a(block->page.file_page_was_freed == FALSE);
03222 #endif
03223 if (UNIV_UNLIKELY(!access_time)) {
03224
03225
03226
03227 buf_read_ahead_linear(buf_block_get_space(block),
03228 buf_block_get_zip_size(block),
03229 buf_block_get_page_no(block));
03230 }
03231
03232 #ifdef UNIV_IBUF_COUNT_DEBUG
03233 ut_a(ibuf_count_get(buf_block_get_space(block),
03234 buf_block_get_page_no(block)) == 0);
03235 #endif
03236 buf_pool = buf_pool_from_block(block);
03237 buf_pool->stat.n_page_gets++;
03238
03239 return(TRUE);
03240 }
03241
03242
03247 UNIV_INTERN
03248 ibool
03249 buf_page_get_known_nowait(
03250
03251 ulint rw_latch,
03252 buf_block_t* block,
03253 ulint mode,
03254 const char* file,
03255 ulint line,
03256 mtr_t* mtr)
03257 {
03258 buf_pool_t* buf_pool;
03259 ibool success;
03260 ulint fix_type;
03261
03262 ut_ad(mtr);
03263 ut_ad(mtr->state == MTR_ACTIVE);
03264 ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
03265
03266 mutex_enter(&block->mutex);
03267
03268 if (buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH) {
03269
03270
03271
03272
03273
03274
03275
03276 mutex_exit(&block->mutex);
03277
03278 return(FALSE);
03279 }
03280
03281 ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
03282
03283 buf_block_buf_fix_inc(block, file, line);
03284
03285 mutex_exit(&block->mutex);
03286
03287 buf_pool = buf_pool_from_block(block);
03288
03289 if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
03290 buf_pool_mutex_enter(buf_pool);
03291 buf_LRU_make_block_young(&block->page);
03292 buf_pool_mutex_exit(buf_pool);
03293 } else if (!buf_page_is_accessed(&block->page)) {
03294
03295
03296
03297
03298 ulint time_ms = ut_time_ms();
03299
03300 buf_pool_mutex_enter(buf_pool);
03301 buf_page_set_accessed(&block->page, time_ms);
03302 buf_pool_mutex_exit(buf_pool);
03303 }
03304
03305 ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
03306
03307 if (rw_latch == RW_S_LATCH) {
03308 success = rw_lock_s_lock_nowait(&(block->lock),
03309 file, line);
03310 fix_type = MTR_MEMO_PAGE_S_FIX;
03311 } else {
03312 success = rw_lock_x_lock_func_nowait(&(block->lock),
03313 file, line);
03314 fix_type = MTR_MEMO_PAGE_X_FIX;
03315 }
03316
03317 if (!success) {
03318 mutex_enter(&block->mutex);
03319 buf_block_buf_fix_dec(block);
03320 mutex_exit(&block->mutex);
03321
03322 return(FALSE);
03323 }
03324
03325 mtr_memo_push(mtr, block, fix_type);
03326
03327 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
03328 ut_a(++buf_dbg_counter % 5771 || buf_validate());
03329 ut_a(block->page.buf_fix_count > 0);
03330 ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
03331 #endif
03332 #ifdef UNIV_DEBUG_FILE_ACCESSES
03333 ut_a(block->page.file_page_was_freed == FALSE);
03334 #endif
03335
03336 #ifdef UNIV_IBUF_COUNT_DEBUG
03337 ut_a((mode == BUF_KEEP_OLD)
03338 || (ibuf_count_get(buf_block_get_space(block),
03339 buf_block_get_page_no(block)) == 0));
03340 #endif
03341 buf_pool->stat.n_page_gets++;
03342
03343 return(TRUE);
03344 }
03345
03346
03351 UNIV_INTERN
03352 const buf_block_t*
03353 buf_page_try_get_func(
03354
03355 ulint space_id,
03356 ulint page_no,
03357 const char* file,
03358 ulint line,
03359 mtr_t* mtr)
03360 {
03361 buf_block_t* block;
03362 ibool success;
03363 ulint fix_type;
03364 buf_pool_t* buf_pool = buf_pool_get(space_id, page_no);
03365
03366 ut_ad(mtr);
03367 ut_ad(mtr->state == MTR_ACTIVE);
03368
03369 buf_pool_mutex_enter(buf_pool);
03370 block = buf_block_hash_get(buf_pool, space_id, page_no);
03371
03372 if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
03373 buf_pool_mutex_exit(buf_pool);
03374 return(NULL);
03375 }
03376
03377 ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
03378
03379 mutex_enter(&block->mutex);
03380 buf_pool_mutex_exit(buf_pool);
03381
03382 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
03383 ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
03384 ut_a(buf_block_get_space(block) == space_id);
03385 ut_a(buf_block_get_page_no(block) == page_no);
03386 #endif
03387
03388 buf_block_buf_fix_inc(block, file, line);
03389 mutex_exit(&block->mutex);
03390
03391 fix_type = MTR_MEMO_PAGE_S_FIX;
03392 success = rw_lock_s_lock_nowait(&block->lock, file, line);
03393
03394 if (!success) {
03395
03396
03397
03398
03399 fix_type = MTR_MEMO_PAGE_X_FIX;
03400 success = rw_lock_x_lock_func_nowait(&block->lock,
03401 file, line);
03402 }
03403
03404 if (!success) {
03405 mutex_enter(&block->mutex);
03406 buf_block_buf_fix_dec(block);
03407 mutex_exit(&block->mutex);
03408
03409 return(NULL);
03410 }
03411
03412 mtr_memo_push(mtr, block, fix_type);
03413 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
03414 ut_a(++buf_dbg_counter % 5771 || buf_validate());
03415 ut_a(block->page.buf_fix_count > 0);
03416 ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
03417 #endif
03418 #ifdef UNIV_DEBUG_FILE_ACCESSES
03419 ut_a(block->page.file_page_was_freed == FALSE);
03420 #endif
03421 buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
03422
03423 buf_pool->stat.n_page_gets++;
03424
03425 #ifdef UNIV_IBUF_COUNT_DEBUG
03426 ut_a(ibuf_count_get(buf_block_get_space(block),
03427 buf_block_get_page_no(block)) == 0);
03428 #endif
03429
03430 return(block);
03431 }
03432
03433
03435 UNIV_INLINE
03436 void
03437 buf_page_init_low(
03438
03439 buf_page_t* bpage)
03440 {
03441 bpage->flush_type = BUF_FLUSH_LRU;
03442 bpage->io_fix = BUF_IO_NONE;
03443 bpage->buf_fix_count = 0;
03444 bpage->freed_page_clock = 0;
03445 bpage->access_time = 0;
03446 bpage->newest_modification = 0;
03447 bpage->oldest_modification = 0;
03448 HASH_INVALIDATE(bpage, hash);
03449 #ifdef UNIV_DEBUG_FILE_ACCESSES
03450 bpage->file_page_was_freed = FALSE;
03451 #endif
03452 }
03453
03454
03456 static
03457 void
03458 buf_page_init(
03459
03460 ulint space,
03461 ulint offset,
03463 ulint fold,
03464 buf_block_t* block)
03465 {
03466 buf_page_t* hash_page;
03467 buf_pool_t* buf_pool = buf_pool_get(space, offset);
03468
03469 ut_ad(buf_pool_mutex_own(buf_pool));
03470 ut_ad(mutex_own(&(block->mutex)));
03471 ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
03472
03473
03474 buf_block_set_file_page(block, space, offset);
03475
03476 #ifdef UNIV_DEBUG_VALGRIND
03477 if (!space) {
03478
03479
03480
03481 UNIV_MEM_VALID(block->frame, UNIV_PAGE_SIZE);
03482 }
03483 #endif
03484
03485 buf_block_init_low(block);
03486
03487 block->lock_hash_val = lock_rec_hash(space, offset);
03488
03489 buf_page_init_low(&block->page);
03490
03491
03492
03493 hash_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
03494
03495 if (UNIV_LIKELY(!hash_page)) {
03496 } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
03497
03498 ulint buf_fix_count = hash_page->buf_fix_count;
03499
03500 ut_a(buf_fix_count > 0);
03501 block->page.buf_fix_count += buf_fix_count;
03502 buf_pool_watch_remove(buf_pool, fold, hash_page);
03503 } else {
03504 fprintf(stderr,
03505 "InnoDB: Error: page %lu %lu already found"
03506 " in the hash table: %p, %p\n",
03507 (ulong) space,
03508 (ulong) offset,
03509 (const void*) hash_page, (const void*) block);
03510 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
03511 mutex_exit(&block->mutex);
03512 buf_pool_mutex_exit(buf_pool);
03513 buf_print();
03514 buf_LRU_print();
03515 buf_validate();
03516 buf_LRU_validate();
03517 #endif
03518 ut_error;
03519 }
03520
03521 ut_ad(!block->page.in_zip_hash);
03522 ut_ad(!block->page.in_page_hash);
03523 ut_d(block->page.in_page_hash = TRUE);
03524 HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
03525 fold, &block->page);
03526 }
03527
03528
03538 UNIV_INTERN
03539 buf_page_t*
03540 buf_page_init_for_read(
03541
03542 ulint* err,
03543 ulint mode,
03544 ulint space,
03545 ulint zip_size,
03546 ibool unzip,
03547 ib_int64_t tablespace_version,
03551 ulint offset)
03552 {
03553 buf_block_t* block;
03554 buf_page_t* bpage = NULL;
03555 buf_page_t* watch_page;
03556 mtr_t mtr;
03557 ulint fold;
03558 ibool lru = FALSE;
03559 void* data;
03560 buf_pool_t* buf_pool = buf_pool_get(space, offset);
03561
03562 ut_ad(buf_pool);
03563
03564 *err = DB_SUCCESS;
03565
03566 if (mode == BUF_READ_IBUF_PAGES_ONLY) {
03567
03568
03569 ut_ad(!ibuf_bitmap_page(zip_size, offset));
03570 ut_ad(ibuf_inside());
03571
03572 mtr_start(&mtr);
03573
03574 if (!recv_no_ibuf_operations
03575 && !ibuf_page(space, zip_size, offset, &mtr)) {
03576
03577 mtr_commit(&mtr);
03578
03579 return(NULL);
03580 }
03581 } else {
03582 ut_ad(mode == BUF_READ_ANY_PAGE);
03583 }
03584
03585 if (zip_size && UNIV_LIKELY(!unzip)
03586 && UNIV_LIKELY(!recv_recovery_is_on())) {
03587 block = NULL;
03588 } else {
03589 block = buf_LRU_get_free_block(buf_pool, 0);
03590 ut_ad(block);
03591 ut_ad(buf_pool_from_block(block) == buf_pool);
03592 }
03593
03594 fold = buf_page_address_fold(space, offset);
03595
03596 buf_pool_mutex_enter(buf_pool);
03597
03598 watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
03599 if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
03600
03601 watch_page = NULL;
03602 err_exit:
03603 if (block) {
03604 mutex_enter(&block->mutex);
03605 buf_LRU_block_free_non_file_page(block);
03606 mutex_exit(&block->mutex);
03607 }
03608
03609 bpage = NULL;
03610 goto func_exit;
03611 }
03612
03613 if (fil_tablespace_deleted_or_being_deleted_in_mem(
03614 space, tablespace_version)) {
03615
03616
03617 *err = DB_TABLESPACE_DELETED;
03618
03619 goto err_exit;
03620 }
03621
03622 if (block) {
03623 bpage = &block->page;
03624 mutex_enter(&block->mutex);
03625
03626 ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
03627
03628 buf_page_init(space, offset, fold, block);
03629
03630
03631 buf_LRU_add_block(bpage, TRUE);
03632
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642 rw_lock_x_lock_gen(&block->lock, BUF_IO_READ);
03643 buf_page_set_io_fix(bpage, BUF_IO_READ);
03644
03645 if (UNIV_UNLIKELY(zip_size)) {
03646 page_zip_set_size(&block->page.zip, zip_size);
03647
03648
03649
03650
03651
03652
03653
03654
03655
03656 mutex_exit(&block->mutex);
03657 data = buf_buddy_alloc(buf_pool, zip_size, &lru);
03658 mutex_enter(&block->mutex);
03659 block->page.zip.data = static_cast<unsigned char *>(data);
03660
03661
03662
03663
03664
03665
03666 ut_ad(buf_page_belongs_to_unzip_LRU(&block->page));
03667 buf_unzip_LRU_add_block(block, TRUE);
03668 }
03669
03670 mutex_exit(&block->mutex);
03671 } else {
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681 data = buf_buddy_alloc(buf_pool, zip_size, &lru);
03682 bpage = static_cast<buf_page_struct *>(buf_buddy_alloc(buf_pool, sizeof *bpage, &lru));
03683
03684
03685 bpage->buf_pool_index = buf_pool_index(buf_pool);
03686
03687
03688
03689
03690 if (UNIV_UNLIKELY(lru)) {
03691
03692 watch_page = buf_page_hash_get_low(
03693 buf_pool, space, offset, fold);
03694
03695 if (watch_page
03696 && !buf_pool_watch_is_sentinel(buf_pool,
03697 watch_page)) {
03698
03699
03700 watch_page = NULL;
03701 buf_buddy_free(buf_pool, bpage, sizeof *bpage);
03702 buf_buddy_free(buf_pool, data, zip_size);
03703
03704 bpage = NULL;
03705 goto func_exit;
03706 }
03707 }
03708
03709 page_zip_des_init(&bpage->zip);
03710 page_zip_set_size(&bpage->zip, zip_size);
03711 bpage->zip.data = static_cast<unsigned char *>(data);
03712
03713 mutex_enter(&buf_pool->zip_mutex);
03714 UNIV_MEM_DESC(bpage->zip.data,
03715 page_zip_get_size(&bpage->zip), bpage);
03716
03717 buf_page_init_low(bpage);
03718
03719 bpage->state = BUF_BLOCK_ZIP_PAGE;
03720 bpage->space = space;
03721 bpage->offset = offset;
03722
03723
03724 #ifdef UNIV_DEBUG
03725 bpage->in_page_hash = FALSE;
03726 bpage->in_zip_hash = FALSE;
03727 bpage->in_flush_list = FALSE;
03728 bpage->in_free_list = FALSE;
03729 bpage->in_LRU_list = FALSE;
03730 #endif
03731
03732 ut_d(bpage->in_page_hash = TRUE);
03733
03734 if (UNIV_LIKELY_NULL(watch_page)) {
03735
03736 ulint buf_fix_count = watch_page->buf_fix_count;
03737 ut_a(buf_fix_count > 0);
03738 bpage->buf_fix_count += buf_fix_count;
03739 ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page));
03740 buf_pool_watch_remove(buf_pool, fold, watch_page);
03741 }
03742
03743 HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
03744 bpage);
03745
03746
03747 buf_LRU_add_block(bpage, TRUE);
03748 buf_LRU_insert_zip_clean(bpage);
03749
03750 buf_page_set_io_fix(bpage, BUF_IO_READ);
03751
03752 mutex_exit(&buf_pool->zip_mutex);
03753 }
03754
03755 buf_pool->n_pend_reads++;
03756 func_exit:
03757 buf_pool_mutex_exit(buf_pool);
03758
03759 if (mode == BUF_READ_IBUF_PAGES_ONLY) {
03760
03761 mtr_commit(&mtr);
03762 }
03763
03764 ut_ad(!bpage || buf_page_in_file(bpage));
03765 return(bpage);
03766 }
03767
03768
03774 UNIV_INTERN
03775 buf_block_t*
03776 buf_page_create(
03777
03778 ulint space,
03779 ulint offset,
03781 ulint zip_size,
03782 mtr_t* mtr)
03783 {
03784 buf_frame_t* frame;
03785 buf_block_t* block;
03786 ulint fold;
03787 buf_block_t* free_block = NULL;
03788 ulint time_ms = ut_time_ms();
03789 buf_pool_t* buf_pool = buf_pool_get(space, offset);
03790
03791 ut_ad(mtr);
03792 ut_ad(mtr->state == MTR_ACTIVE);
03793 ut_ad(space || !zip_size);
03794
03795 free_block = buf_LRU_get_free_block(buf_pool, 0);
03796
03797 fold = buf_page_address_fold(space, offset);
03798
03799 buf_pool_mutex_enter(buf_pool);
03800
03801 block = (buf_block_t*) buf_page_hash_get_low(
03802 buf_pool, space, offset, fold);
03803
03804 if (block
03805 && buf_page_in_file(&block->page)
03806 && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
03807 #ifdef UNIV_IBUF_COUNT_DEBUG
03808 ut_a(ibuf_count_get(space, offset) == 0);
03809 #endif
03810 #ifdef UNIV_DEBUG_FILE_ACCESSES
03811 block->page.file_page_was_freed = FALSE;
03812 #endif
03813
03814
03815 buf_pool_mutex_exit(buf_pool);
03816
03817 buf_block_free(free_block);
03818
03819 return(buf_page_get_with_no_latch(space, zip_size,
03820 offset, mtr));
03821 }
03822
03823
03824
03825 #ifdef UNIV_DEBUG
03826 if (buf_debug_prints) {
03827 fprintf(stderr, "Creating space %lu page %lu to buffer\n",
03828 (ulong) space, (ulong) offset);
03829 }
03830 #endif
03831
03832 block = free_block;
03833
03834 mutex_enter(&block->mutex);
03835
03836 buf_page_init(space, offset, fold, block);
03837
03838
03839 buf_LRU_add_block(&block->page, FALSE);
03840
03841 buf_block_buf_fix_inc(block, __FILE__, __LINE__);
03842 buf_pool->stat.n_pages_created++;
03843
03844 if (zip_size) {
03845 void* data;
03846 ibool lru;
03847
03848
03849
03850
03851
03852 buf_page_set_io_fix(&block->page, BUF_IO_READ);
03853 rw_lock_x_lock(&block->lock);
03854
03855 page_zip_set_size(&block->page.zip, zip_size);
03856 mutex_exit(&block->mutex);
03857
03858
03859
03860
03861
03862
03863 data = buf_buddy_alloc(buf_pool, zip_size, &lru);
03864 mutex_enter(&block->mutex);
03865 block->page.zip.data = static_cast<unsigned char *>(data);
03866
03867
03868
03869
03870
03871
03872 ut_ad(buf_page_belongs_to_unzip_LRU(&block->page));
03873 buf_unzip_LRU_add_block(block, FALSE);
03874
03875 buf_page_set_io_fix(&block->page, BUF_IO_NONE);
03876 rw_lock_x_unlock(&block->lock);
03877 }
03878
03879 buf_page_set_accessed(&block->page, time_ms);
03880
03881 buf_pool_mutex_exit(buf_pool);
03882
03883 mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
03884
03885 mutex_exit(&block->mutex);
03886
03887
03888
03889
03890 ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE);
03891
03892
03893 buf_flush_free_margin(buf_pool);
03894
03895 frame = block->frame;
03896
03897 memset(frame + FIL_PAGE_PREV, 0xff, 4);
03898 memset(frame + FIL_PAGE_NEXT, 0xff, 4);
03899 mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED);
03900
03901
03902
03903
03904
03905
03906
03907 memset(frame + FIL_PAGE_FILE_FLUSH_LSN, 0, 8);
03908
03909 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
03910 ut_a(++buf_dbg_counter % 357 || buf_validate());
03911 #endif
03912 #ifdef UNIV_IBUF_COUNT_DEBUG
03913 ut_a(ibuf_count_get(buf_block_get_space(block),
03914 buf_block_get_page_no(block)) == 0);
03915 #endif
03916 return(block);
03917 }
03918
03919
03922 UNIV_INTERN
03923 void
03924 buf_page_io_complete(
03925
03926 buf_page_t* bpage)
03927 {
03928 enum buf_io_fix io_type;
03929 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
03930 const ibool uncompressed = (buf_page_get_state(bpage)
03931 == BUF_BLOCK_FILE_PAGE);
03932
03933 ut_a(buf_page_in_file(bpage));
03934
03935
03936
03937
03938
03939
03940
03941 io_type = buf_page_get_io_fix(bpage);
03942 ut_ad(io_type == BUF_IO_READ || io_type == BUF_IO_WRITE);
03943
03944 if (io_type == BUF_IO_READ) {
03945 ulint read_page_no;
03946 ulint read_space_id;
03947 byte* frame;
03948
03949 if (buf_page_get_zip_size(bpage)) {
03950 frame = bpage->zip.data;
03951 buf_pool->n_pend_unzip++;
03952 if (uncompressed
03953 && !buf_zip_decompress((buf_block_t*) bpage,
03954 FALSE)) {
03955
03956 buf_pool->n_pend_unzip--;
03957 goto corrupt;
03958 }
03959 buf_pool->n_pend_unzip--;
03960 } else {
03961 ut_a(uncompressed);
03962 frame = ((buf_block_t*) bpage)->frame;
03963 }
03964
03965
03966
03967
03968 read_page_no = mach_read_from_4(frame + FIL_PAGE_OFFSET);
03969 read_space_id = mach_read_from_4(
03970 frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
03971
03972 if (bpage->space == TRX_SYS_SPACE
03973 && trx_doublewrite_page_inside(bpage->offset)) {
03974
03975 ut_print_timestamp(stderr);
03976 fprintf(stderr,
03977 " InnoDB: Error: reading page %lu\n"
03978 "InnoDB: which is in the"
03979 " doublewrite buffer!\n",
03980 (ulong) bpage->offset);
03981 } else if (!read_space_id && !read_page_no) {
03982
03983 } else if ((bpage->space
03984 && bpage->space != read_space_id)
03985 || bpage->offset != read_page_no) {
03986
03987
03988
03989
03990
03991 ut_print_timestamp(stderr);
03992 fprintf(stderr,
03993 " InnoDB: Error: space id and page n:o"
03994 " stored in the page\n"
03995 "InnoDB: read in are %lu:%lu,"
03996 " should be %lu:%lu!\n",
03997 (ulong) read_space_id, (ulong) read_page_no,
03998 (ulong) bpage->space,
03999 (ulong) bpage->offset);
04000 }
04001
04002
04003
04004
04005 if (buf_page_is_corrupted(frame,
04006 buf_page_get_zip_size(bpage))) {
04007 corrupt:
04008 fprintf(stderr,
04009 "InnoDB: Database page corruption on disk"
04010 " or a failed\n"
04011 "InnoDB: file read of page %lu.\n"
04012 "InnoDB: You may have to recover"
04013 " from a backup.\n",
04014 (ulong) bpage->offset);
04015 buf_page_print(frame, buf_page_get_zip_size(bpage));
04016 fprintf(stderr,
04017 "InnoDB: Database page corruption on disk"
04018 " or a failed\n"
04019 "InnoDB: file read of page %lu.\n"
04020 "InnoDB: You may have to recover"
04021 " from a backup.\n",
04022 (ulong) bpage->offset);
04023 fputs("InnoDB: It is also possible that"
04024 " your operating\n"
04025 "InnoDB: system has corrupted its"
04026 " own file cache\n"
04027 "InnoDB: and rebooting your computer"
04028 " removes the\n"
04029 "InnoDB: error.\n"
04030 "InnoDB: If the corrupt page is an index page\n"
04031 "InnoDB: you can also try to"
04032 " fix the corruption\n"
04033 "InnoDB: by dumping, dropping,"
04034 " and reimporting\n"
04035 "InnoDB: the corrupt table."
04036 " You can use CHECK\n"
04037 "InnoDB: TABLE to scan your"
04038 " table for corruption.\n"
04039 "InnoDB: See also "
04040 REFMAN "forcing-recovery.html\n"
04041 "InnoDB: about forcing recovery.\n", stderr);
04042
04043 if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
04044 fputs("InnoDB: Ending processing because of"
04045 " a corrupt database page.\n",
04046 stderr);
04047 exit(1);
04048 }
04049 }
04050
04051 if (recv_recovery_is_on()) {
04052
04053 ut_a(uncompressed);
04054 recv_recover_page(TRUE, (buf_block_t*) bpage);
04055 }
04056
04057 if (uncompressed && !recv_no_ibuf_operations && !srv_fake_write) {
04058 ibuf_merge_or_delete_for_page(
04059 (buf_block_t*) bpage, bpage->space,
04060 bpage->offset, buf_page_get_zip_size(bpage),
04061 TRUE);
04062 }
04063 }
04064
04065 buf_pool_mutex_enter(buf_pool);
04066 mutex_enter(buf_page_get_mutex(bpage));
04067
04068 #ifdef UNIV_IBUF_COUNT_DEBUG
04069 if (io_type == BUF_IO_WRITE || uncompressed) {
04070
04071
04072
04073 ut_a(ibuf_count_get(bpage->space, bpage->offset) == 0);
04074 }
04075 #endif
04076
04077
04078
04079
04080
04081 buf_page_set_io_fix(bpage, BUF_IO_NONE);
04082
04083 switch (io_type) {
04084 case BUF_IO_READ:
04085
04086
04087
04088
04089 ut_ad(buf_pool->n_pend_reads > 0);
04090 buf_pool->n_pend_reads--;
04091 buf_pool->stat.n_pages_read++;
04092
04093 if (uncompressed) {
04094 rw_lock_x_unlock_gen(&((buf_block_t*) bpage)->lock,
04095 BUF_IO_READ);
04096 }
04097
04098 break;
04099
04100 case BUF_IO_WRITE:
04101
04102
04103
04104 buf_flush_write_complete(bpage);
04105
04106 if (uncompressed) {
04107 rw_lock_s_unlock_gen(&((buf_block_t*) bpage)->lock,
04108 BUF_IO_WRITE);
04109 }
04110
04111 buf_pool->stat.n_pages_written++;
04112
04113 break;
04114
04115 default:
04116 ut_error;
04117 }
04118
04119 #ifdef UNIV_DEBUG
04120 if (buf_debug_prints) {
04121 fprintf(stderr, "Has %s page space %lu page no %lu\n",
04122 io_type == BUF_IO_READ ? "read" : "written",
04123 (ulong) buf_page_get_space(bpage),
04124 (ulong) buf_page_get_page_no(bpage));
04125 }
04126 #endif
04127
04128 mutex_exit(buf_page_get_mutex(bpage));
04129 buf_pool_mutex_exit(buf_pool);
04130 }
04131
04132
04135 static
04136 ibool
04137 buf_all_freed_instance(
04138
04139 buf_pool_t* buf_pool)
04140 {
04141 ulint i;
04142 buf_chunk_t* chunk;
04143
04144 ut_ad(buf_pool);
04145
04146 buf_pool_mutex_enter(buf_pool);
04147
04148 chunk = buf_pool->chunks;
04149
04150 for (i = buf_pool->n_chunks; i--; chunk++) {
04151
04152 const buf_block_t* block = buf_chunk_not_freed(chunk);
04153
04154 if (UNIV_LIKELY_NULL(block)) {
04155 fprintf(stderr,
04156 "Page %lu %lu still fixed or dirty\n",
04157 (ulong) block->page.space,
04158 (ulong) block->page.offset);
04159 ut_error;
04160 }
04161 }
04162
04163 buf_pool_mutex_exit(buf_pool);
04164
04165 return(TRUE);
04166 }
04167
04168
04170 static
04171 void
04172 buf_pool_invalidate_instance(
04173
04174 buf_pool_t* buf_pool)
04175 {
04176 ibool freed;
04177 int i;
04178
04179 buf_pool_mutex_enter(buf_pool);
04180
04181 for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
04182
04183
04184
04185
04186
04187
04188 ut_ad(buf_pool->init_flush[i] == FALSE);
04189
04190
04191
04192
04193
04194 if (buf_pool->n_flush[i] > 0) {
04195 buf_pool_mutex_exit(buf_pool);
04196 buf_flush_wait_batch_end(buf_pool, static_cast<buf_flush>(i));
04197 buf_pool_mutex_enter(buf_pool);
04198 }
04199 }
04200
04201 buf_pool_mutex_exit(buf_pool);
04202
04203 ut_ad(buf_all_freed_instance(buf_pool));
04204
04205 freed = TRUE;
04206
04207 while (freed) {
04208 freed = buf_LRU_search_and_free_block(buf_pool, 100);
04209 }
04210
04211 buf_pool_mutex_enter(buf_pool);
04212
04213 ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
04214 ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
04215
04216 buf_pool->freed_page_clock = 0;
04217 buf_pool->LRU_old = NULL;
04218 buf_pool->LRU_old_len = 0;
04219 buf_pool->LRU_flush_ended = 0;
04220
04221 memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
04222 buf_refresh_io_stats(buf_pool);
04223
04224 buf_pool_mutex_exit(buf_pool);
04225 }
04226
04227
04231 UNIV_INTERN
04232 void
04233 buf_pool_invalidate(void)
04234
04235 {
04236 ulint i;
04237
04238 for (i = 0; i < srv_buf_pool_instances; i++) {
04239 buf_pool_invalidate_instance(buf_pool_from_array(i));
04240 }
04241 }
04242
04243 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
04244
04247 static
04248 ibool
04249 buf_pool_validate_instance(
04250
04251 buf_pool_t* buf_pool)
04252 {
04253 buf_page_t* b;
04254 buf_chunk_t* chunk;
04255 ulint i;
04256 ulint n_single_flush = 0;
04257 ulint n_lru_flush = 0;
04258 ulint n_list_flush = 0;
04259 ulint n_lru = 0;
04260 ulint n_flush = 0;
04261 ulint n_free = 0;
04262 ulint n_zip = 0;
04263
04264 ut_ad(buf_pool);
04265
04266 buf_pool_mutex_enter(buf_pool);
04267
04268 chunk = buf_pool->chunks;
04269
04270
04271
04272 for (i = buf_pool->n_chunks; i--; chunk++) {
04273
04274 ulint j;
04275 buf_block_t* block = chunk->blocks;
04276
04277 for (j = chunk->size; j--; block++) {
04278
04279 mutex_enter(&block->mutex);
04280
04281 switch (buf_block_get_state(block)) {
04282 case BUF_BLOCK_ZIP_FREE:
04283 case BUF_BLOCK_ZIP_PAGE:
04284 case BUF_BLOCK_ZIP_DIRTY:
04285
04286
04287 ut_error;
04288 break;
04289
04290 case BUF_BLOCK_FILE_PAGE:
04291 ut_a(buf_page_hash_get(buf_pool,
04292 buf_block_get_space(
04293 block),
04294 buf_block_get_page_no(
04295 block))
04296 == &block->page);
04297
04298 #ifdef UNIV_IBUF_COUNT_DEBUG
04299 ut_a(buf_page_get_io_fix(&block->page)
04300 == BUF_IO_READ
04301 || !ibuf_count_get(buf_block_get_space(
04302 block),
04303 buf_block_get_page_no(
04304 block)));
04305 #endif
04306 switch (buf_page_get_io_fix(&block->page)) {
04307 case BUF_IO_NONE:
04308 break;
04309
04310 case BUF_IO_WRITE:
04311 switch (buf_page_get_flush_type(
04312 &block->page)) {
04313 case BUF_FLUSH_LRU:
04314 n_lru_flush++;
04315 ut_a(rw_lock_is_locked(
04316 &block->lock,
04317 RW_LOCK_SHARED));
04318 break;
04319 case BUF_FLUSH_LIST:
04320 n_list_flush++;
04321 break;
04322 case BUF_FLUSH_SINGLE_PAGE:
04323 n_single_flush++;
04324 break;
04325 default:
04326 ut_error;
04327 }
04328
04329 break;
04330
04331 case BUF_IO_READ:
04332
04333 ut_a(rw_lock_is_locked(&block->lock,
04334 RW_LOCK_EX));
04335 break;
04336 }
04337
04338 n_lru++;
04339 break;
04340
04341 case BUF_BLOCK_NOT_USED:
04342 n_free++;
04343 break;
04344
04345 case BUF_BLOCK_READY_FOR_USE:
04346 case BUF_BLOCK_MEMORY:
04347 case BUF_BLOCK_REMOVE_HASH:
04348
04349 break;
04350 }
04351
04352 mutex_exit(&block->mutex);
04353 }
04354 }
04355
04356 mutex_enter(&buf_pool->zip_mutex);
04357
04358
04359
04360 for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
04361 b = UT_LIST_GET_NEXT(list, b)) {
04362 ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
04363 switch (buf_page_get_io_fix(b)) {
04364 case BUF_IO_NONE:
04365
04366 break;
04367 case BUF_IO_READ:
04368
04369
04370
04371
04372 break;
04373 default:
04374 ut_error;
04375 break;
04376 }
04377
04378
04379
04380
04381 ut_a(!b->oldest_modification);
04382 ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
04383
04384 n_lru++;
04385 n_zip++;
04386 }
04387
04388
04389
04390 buf_flush_list_mutex_enter(buf_pool);
04391 for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
04392 b = UT_LIST_GET_NEXT(list, b)) {
04393 ut_ad(b->in_flush_list);
04394 ut_a(b->oldest_modification);
04395 n_flush++;
04396
04397 switch (buf_page_get_state(b)) {
04398 case BUF_BLOCK_ZIP_DIRTY:
04399 n_lru++;
04400 n_zip++;
04401 switch (buf_page_get_io_fix(b)) {
04402 case BUF_IO_NONE:
04403 case BUF_IO_READ:
04404 break;
04405 case BUF_IO_WRITE:
04406 switch (buf_page_get_flush_type(b)) {
04407 case BUF_FLUSH_LRU:
04408 n_lru_flush++;
04409 break;
04410 case BUF_FLUSH_LIST:
04411 n_list_flush++;
04412 break;
04413 case BUF_FLUSH_SINGLE_PAGE:
04414 n_single_flush++;
04415 break;
04416 default:
04417 ut_error;
04418 }
04419 break;
04420 }
04421 break;
04422 case BUF_BLOCK_FILE_PAGE:
04423
04424 break;
04425 case BUF_BLOCK_ZIP_FREE:
04426 case BUF_BLOCK_ZIP_PAGE:
04427 case BUF_BLOCK_NOT_USED:
04428 case BUF_BLOCK_READY_FOR_USE:
04429 case BUF_BLOCK_MEMORY:
04430 case BUF_BLOCK_REMOVE_HASH:
04431 ut_error;
04432 break;
04433 }
04434 ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
04435 }
04436
04437 ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
04438
04439 buf_flush_list_mutex_exit(buf_pool);
04440
04441 mutex_exit(&buf_pool->zip_mutex);
04442
04443 if (n_lru + n_free > buf_pool->curr_size + n_zip) {
04444 fprintf(stderr, "n LRU %lu, n free %lu, pool %lu zip %lu\n",
04445 (ulong) n_lru, (ulong) n_free,
04446 (ulong) buf_pool->curr_size, (ulong) n_zip);
04447 ut_error;
04448 }
04449
04450 ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == n_lru);
04451 if (UT_LIST_GET_LEN(buf_pool->free) != n_free) {
04452 fprintf(stderr, "Free list len %lu, free blocks %lu\n",
04453 (ulong) UT_LIST_GET_LEN(buf_pool->free),
04454 (ulong) n_free);
04455 ut_error;
04456 }
04457
04458 ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
04459 ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
04460 ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
04461
04462 buf_pool_mutex_exit(buf_pool);
04463
04464 ut_a(buf_LRU_validate());
04465 ut_a(buf_flush_validate(buf_pool));
04466
04467 return(TRUE);
04468 }
04469
04470
04473 UNIV_INTERN
04474 ibool
04475 buf_validate(void)
04476
04477 {
04478 ulint i;
04479
04480 for (i = 0; i < srv_buf_pool_instances; i++) {
04481 buf_pool_t* buf_pool;
04482
04483 buf_pool = buf_pool_from_array(i);
04484
04485 buf_pool_validate_instance(buf_pool);
04486 }
04487 return(TRUE);
04488 }
04489
04490 #endif
04491
04492 #if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
04493
04495 static
04496 void
04497 buf_print_instance(
04498
04499 buf_pool_t* buf_pool)
04500 {
04501 index_id_t* index_ids;
04502 ulint* counts;
04503 ulint size;
04504 ulint i;
04505 ulint j;
04506 index_id_t id;
04507 ulint n_found;
04508 buf_chunk_t* chunk;
04509 dict_index_t* index;
04510
04511 ut_ad(buf_pool);
04512
04513 size = buf_pool->curr_size;
04514
04515 index_ids = mem_alloc(size * sizeof *index_ids);
04516 counts = mem_alloc(sizeof(ulint) * size);
04517
04518 buf_pool_mutex_enter(buf_pool);
04519 buf_flush_list_mutex_enter(buf_pool);
04520
04521 fprintf(stderr,
04522 "buf_pool size %lu\n"
04523 "database pages %lu\n"
04524 "free pages %lu\n"
04525 "modified database pages %lu\n"
04526 "n pending decompressions %lu\n"
04527 "n pending reads %lu\n"
04528 "n pending flush LRU %lu list %lu single page %lu\n"
04529 "pages made young %lu, not young %lu\n"
04530 "pages read %lu, created %lu, written %lu\n",
04531 (ulong) size,
04532 (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
04533 (ulong) UT_LIST_GET_LEN(buf_pool->free),
04534 (ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
04535 (ulong) buf_pool->n_pend_unzip,
04536 (ulong) buf_pool->n_pend_reads,
04537 (ulong) buf_pool->n_flush[BUF_FLUSH_LRU],
04538 (ulong) buf_pool->n_flush[BUF_FLUSH_LIST],
04539 (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE],
04540 (ulong) buf_pool->stat.n_pages_made_young,
04541 (ulong) buf_pool->stat.n_pages_not_made_young,
04542 (ulong) buf_pool->stat.n_pages_read,
04543 (ulong) buf_pool->stat.n_pages_created,
04544 (ulong) buf_pool->stat.n_pages_written);
04545
04546 buf_flush_list_mutex_exit(buf_pool);
04547
04548
04549
04550 n_found = 0;
04551
04552 chunk = buf_pool->chunks;
04553
04554 for (i = buf_pool->n_chunks; i--; chunk++) {
04555 buf_block_t* block = chunk->blocks;
04556 ulint n_blocks = chunk->size;
04557
04558 for (; n_blocks--; block++) {
04559 const buf_frame_t* frame = block->frame;
04560
04561 if (fil_page_get_type(frame) == FIL_PAGE_INDEX) {
04562
04563 id = btr_page_get_index_id(frame);
04564
04565
04566 j = 0;
04567
04568 while (j < n_found) {
04569
04570 if (index_ids[j] == id) {
04571 counts[j]++;
04572
04573 break;
04574 }
04575 j++;
04576 }
04577
04578 if (j == n_found) {
04579 n_found++;
04580 index_ids[j] = id;
04581 counts[j] = 1;
04582 }
04583 }
04584 }
04585 }
04586
04587 buf_pool_mutex_exit(buf_pool);
04588
04589 for (i = 0; i < n_found; i++) {
04590 index = dict_index_get_if_in_cache(index_ids[i]);
04591
04592 fprintf(stderr,
04593 "Block count for index %llu in buffer is about %lu",
04594 (ullint) index_ids[i],
04595 (ulong) counts[i]);
04596
04597 if (index) {
04598 putc(' ', stderr);
04599 dict_index_name_print(stderr, NULL, index);
04600 }
04601
04602 putc('\n', stderr);
04603 }
04604
04605 mem_free(index_ids);
04606 mem_free(counts);
04607
04608 ut_a(buf_pool_validate_instance(buf_pool));
04609 }
04610
04611
04613 UNIV_INTERN
04614 void
04615 buf_print(void)
04616
04617 {
04618 ulint i;
04619
04620 for (i = 0; i < srv_buf_pool_instances; i++) {
04621 buf_pool_t* buf_pool;
04622
04623 buf_pool = buf_pool_from_array(i);
04624 buf_print_instance(buf_pool);
04625 }
04626 }
04627 #endif
04628
04629 #ifdef UNIV_DEBUG
04630
04633 UNIV_INTERN
04634 ulint
04635 buf_get_latched_pages_number_instance(
04636
04637 buf_pool_t* buf_pool)
04638 {
04639 buf_page_t* b;
04640 ulint i;
04641 buf_chunk_t* chunk;
04642 ulint fixed_pages_number = 0;
04643
04644 buf_pool_mutex_enter(buf_pool);
04645
04646 chunk = buf_pool->chunks;
04647
04648 for (i = buf_pool->n_chunks; i--; chunk++) {
04649 buf_block_t* block;
04650 ulint j;
04651
04652 block = chunk->blocks;
04653
04654 for (j = chunk->size; j--; block++) {
04655 if (buf_block_get_state(block)
04656 != BUF_BLOCK_FILE_PAGE) {
04657
04658 continue;
04659 }
04660
04661 mutex_enter(&block->mutex);
04662
04663 if (block->page.buf_fix_count != 0
04664 || buf_page_get_io_fix(&block->page)
04665 != BUF_IO_NONE) {
04666 fixed_pages_number++;
04667 }
04668
04669 mutex_exit(&block->mutex);
04670 }
04671 }
04672
04673 mutex_enter(&buf_pool->zip_mutex);
04674
04675
04676
04677 for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
04678 b = UT_LIST_GET_NEXT(list, b)) {
04679 ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
04680 ut_a(buf_page_get_io_fix(b) != BUF_IO_WRITE);
04681
04682 if (b->buf_fix_count != 0
04683 || buf_page_get_io_fix(b) != BUF_IO_NONE) {
04684 fixed_pages_number++;
04685 }
04686 }
04687
04688 buf_flush_list_mutex_enter(buf_pool);
04689 for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
04690 b = UT_LIST_GET_NEXT(list, b)) {
04691 ut_ad(b->in_flush_list);
04692
04693 switch (buf_page_get_state(b)) {
04694 case BUF_BLOCK_ZIP_DIRTY:
04695 if (b->buf_fix_count != 0
04696 || buf_page_get_io_fix(b) != BUF_IO_NONE) {
04697 fixed_pages_number++;
04698 }
04699 break;
04700 case BUF_BLOCK_FILE_PAGE:
04701
04702 break;
04703 case BUF_BLOCK_ZIP_FREE:
04704 case BUF_BLOCK_ZIP_PAGE:
04705 case BUF_BLOCK_NOT_USED:
04706 case BUF_BLOCK_READY_FOR_USE:
04707 case BUF_BLOCK_MEMORY:
04708 case BUF_BLOCK_REMOVE_HASH:
04709 ut_error;
04710 break;
04711 }
04712 }
04713
04714 buf_flush_list_mutex_exit(buf_pool);
04715 mutex_exit(&buf_pool->zip_mutex);
04716 buf_pool_mutex_exit(buf_pool);
04717
04718 return(fixed_pages_number);
04719 }
04720
04721
04724 UNIV_INTERN
04725 ulint
04726 buf_get_latched_pages_number(void)
04727
04728 {
04729 ulint i;
04730 ulint total_latched_pages = 0;
04731
04732 for (i = 0; i < srv_buf_pool_instances; i++) {
04733 buf_pool_t* buf_pool;
04734
04735 buf_pool = buf_pool_from_array(i);
04736
04737 total_latched_pages += buf_get_latched_pages_number_instance(
04738 buf_pool);
04739 }
04740
04741 return(total_latched_pages);
04742 }
04743
04744 #endif
04745
04746
04749 UNIV_INTERN
04750 ulint
04751 buf_get_n_pending_ios(void)
04752
04753 {
04754 ulint i;
04755 ulint pend_ios = 0;
04756
04757 for (i = 0; i < srv_buf_pool_instances; i++) {
04758 buf_pool_t* buf_pool;
04759
04760 buf_pool = buf_pool_from_array(i);
04761
04762 pend_ios +=
04763 buf_pool->n_pend_reads
04764 + buf_pool->n_flush[BUF_FLUSH_LRU]
04765 + buf_pool->n_flush[BUF_FLUSH_LIST]
04766 + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
04767 }
04768
04769 return(pend_ios);
04770 }
04771
04772
04776 UNIV_INTERN
04777 ulint
04778 buf_get_modified_ratio_pct(void)
04779
04780 {
04781 ulint ratio;
04782 ulint lru_len = 0;
04783 ulint free_len = 0;
04784 ulint flush_list_len = 0;
04785
04786 buf_get_total_list_len(&lru_len, &free_len, &flush_list_len);
04787
04788 ratio = (100 * flush_list_len) / (1 + lru_len + free_len);
04789
04790
04791
04792 return(ratio);
04793 }
04794
04795
04797 static
04798 void
04799 buf_print_io_instance(
04800
04801 buf_pool_t* buf_pool,
04802 FILE* file)
04803 {
04804 time_t current_time;
04805 double time_elapsed;
04806 ulint n_gets_diff;
04807
04808 ut_ad(buf_pool);
04809
04810 buf_pool_mutex_enter(buf_pool);
04811 buf_flush_list_mutex_enter(buf_pool);
04812
04813 fprintf(file,
04814 "Buffer pool size %lu\n"
04815 "Free buffers %lu\n"
04816 "Database pages %lu\n"
04817 "Old database pages %lu\n"
04818 "Modified db pages %lu\n"
04819 "Pending reads %lu\n"
04820 "Pending writes: LRU %lu, flush list %lu, single page %lu\n",
04821 (ulong) buf_pool->curr_size,
04822 (ulong) UT_LIST_GET_LEN(buf_pool->free),
04823 (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
04824 (ulong) buf_pool->LRU_old_len,
04825 (ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
04826 (ulong) buf_pool->n_pend_reads,
04827 (ulong) buf_pool->n_flush[BUF_FLUSH_LRU]
04828 + buf_pool->init_flush[BUF_FLUSH_LRU],
04829 (ulong) buf_pool->n_flush[BUF_FLUSH_LIST]
04830 + buf_pool->init_flush[BUF_FLUSH_LIST],
04831 (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
04832
04833 buf_flush_list_mutex_exit(buf_pool);
04834
04835 current_time = time(NULL);
04836 time_elapsed = 0.001 + difftime(current_time,
04837 buf_pool->last_printout_time);
04838
04839 fprintf(file,
04840 "Pages made young %lu, not young %lu\n"
04841 "%.2f youngs/s, %.2f non-youngs/s\n"
04842 "Pages read %lu, created %lu, written %lu\n"
04843 "%.2f reads/s, %.2f creates/s, %.2f writes/s\n",
04844 (ulong) buf_pool->stat.n_pages_made_young,
04845 (ulong) buf_pool->stat.n_pages_not_made_young,
04846 (buf_pool->stat.n_pages_made_young
04847 - buf_pool->old_stat.n_pages_made_young)
04848 / time_elapsed,
04849 (buf_pool->stat.n_pages_not_made_young
04850 - buf_pool->old_stat.n_pages_not_made_young)
04851 / time_elapsed,
04852 (ulong) buf_pool->stat.n_pages_read,
04853 (ulong) buf_pool->stat.n_pages_created,
04854 (ulong) buf_pool->stat.n_pages_written,
04855 (buf_pool->stat.n_pages_read
04856 - buf_pool->old_stat.n_pages_read)
04857 / time_elapsed,
04858 (buf_pool->stat.n_pages_created
04859 - buf_pool->old_stat.n_pages_created)
04860 / time_elapsed,
04861 (buf_pool->stat.n_pages_written
04862 - buf_pool->old_stat.n_pages_written)
04863 / time_elapsed);
04864
04865 n_gets_diff = buf_pool->stat.n_page_gets
04866 - buf_pool->old_stat.n_page_gets;
04867
04868 if (n_gets_diff) {
04869 fprintf(file,
04870 "Buffer pool hit rate %lu / 1000,"
04871 " young-making rate %lu / 1000 not %lu / 1000\n",
04872 (ulong)
04873 (1000 - ((1000 * (buf_pool->stat.n_pages_read
04874 - buf_pool->old_stat.n_pages_read))
04875 / (buf_pool->stat.n_page_gets
04876 - buf_pool->old_stat.n_page_gets))),
04877 (ulong)
04878 (1000 * (buf_pool->stat.n_pages_made_young
04879 - buf_pool->old_stat.n_pages_made_young)
04880 / n_gets_diff),
04881 (ulong)
04882 (1000 * (buf_pool->stat.n_pages_not_made_young
04883 - buf_pool->old_stat.n_pages_not_made_young)
04884 / n_gets_diff));
04885 } else {
04886 fputs("No buffer pool page gets since the last printout\n",
04887 file);
04888 }
04889
04890
04891 fprintf(file, "Pages read ahead %.2f/s,"
04892 " evicted without access %.2f/s\n",
04893 (buf_pool->stat.n_ra_pages_read
04894 - buf_pool->old_stat.n_ra_pages_read)
04895 / time_elapsed,
04896 (buf_pool->stat.n_ra_pages_evicted
04897 - buf_pool->old_stat.n_ra_pages_evicted)
04898 / time_elapsed);
04899
04900
04901
04902 fprintf(file,
04903 "LRU len: %lu, unzip_LRU len: %lu\n"
04904 "I/O sum[%lu]:cur[%lu], unzip sum[%lu]:cur[%lu]\n",
04905 static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->LRU)),
04906 static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->unzip_LRU)),
04907 buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
04908 buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
04909
04910 buf_refresh_io_stats(buf_pool);
04911 buf_pool_mutex_exit(buf_pool);
04912 }
04913
04914
04916 UNIV_INTERN
04917 void
04918 buf_print_io(
04919
04920 FILE* file)
04921 {
04922 ulint i;
04923
04924 for (i = 0; i < srv_buf_pool_instances; i++) {
04925 buf_pool_t* buf_pool;
04926
04927 buf_pool = buf_pool_from_array(i);
04928 buf_print_io_instance(buf_pool, file);
04929 }
04930 }
04931
04932
04934 UNIV_INTERN
04935 void
04936 buf_refresh_io_stats(
04937
04938 buf_pool_t* buf_pool)
04939 {
04940 buf_pool->last_printout_time = ut_time();
04941 buf_pool->old_stat = buf_pool->stat;
04942 }
04943
04944
04946 UNIV_INTERN
04947 void
04948 buf_refresh_io_stats_all(void)
04949
04950 {
04951 ulint i;
04952
04953 for (i = 0; i < srv_buf_pool_instances; i++) {
04954 buf_pool_t* buf_pool;
04955
04956 buf_pool = buf_pool_from_array(i);
04957
04958 buf_refresh_io_stats(buf_pool);
04959 }
04960 }
04961
04962
04965 UNIV_INTERN
04966 ibool
04967 buf_all_freed(void)
04968
04969 {
04970 ulint i;
04971
04972 for (i = 0; i < srv_buf_pool_instances; i++) {
04973 buf_pool_t* buf_pool;
04974
04975 buf_pool = buf_pool_from_array(i);
04976
04977 if (!buf_all_freed_instance(buf_pool)) {
04978 return(FALSE);
04979 }
04980 }
04981
04982 return(TRUE);
04983 }
04984
04985
04989 UNIV_INTERN
04990 ibool
04991 buf_pool_check_no_pending_io(void)
04992
04993 {
04994 ulint i;
04995 ibool ret = TRUE;
04996
04997 buf_pool_mutex_enter_all();
04998
04999 for (i = 0; i < srv_buf_pool_instances && ret; i++) {
05000 const buf_pool_t* buf_pool;
05001
05002 buf_pool = buf_pool_from_array(i);
05003
05004 if (buf_pool->n_pend_reads
05005 + buf_pool->n_flush[BUF_FLUSH_LRU]
05006 + buf_pool->n_flush[BUF_FLUSH_LIST]
05007 + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
05008
05009 ret = FALSE;
05010 }
05011 }
05012
05013 buf_pool_mutex_exit_all();
05014
05015 return(ret);
05016 }
05017
05018 #if 0
05019 Code currently not used
05020
05023 UNIV_INTERN
05024 ulint
05025 buf_get_free_list_len(void)
05026
05027 {
05028 ulint len;
05029
05030 buf_pool_mutex_enter(buf_pool);
05031
05032 len = UT_LIST_GET_LEN(buf_pool->free);
05033
05034 buf_pool_mutex_exit(buf_pool);
05035
05036 return(len);
05037 }
05038 #endif
05039
05040 #else
05041
05043 UNIV_INTERN
05044 void
05045 buf_page_init_for_backup_restore(
05046
05047 ulint space,
05048 ulint offset,
05050 ulint zip_size,
05052 buf_block_t* block)
05053 {
05054 block->page.state = BUF_BLOCK_FILE_PAGE;
05055 block->page.space = space;
05056 block->page.offset = offset;
05057
05058 page_zip_des_init(&block->page.zip);
05059
05060
05061
05062 ut_ad(zip_size <= UNIV_PAGE_SIZE);
05063 ut_ad(ut_is_2pow(zip_size));
05064 page_zip_set_size(&block->page.zip, zip_size);
05065 if (zip_size) {
05066 block->page.zip.data = block->frame + UNIV_PAGE_SIZE;
05067 }
05068 }
05069 #endif