00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "buf0rea.h"
00027
00028 #include "fil0fil.h"
00029 #include "mtr0mtr.h"
00030
00031 #include "buf0buf.h"
00032 #include "buf0flu.h"
00033 #include "buf0lru.h"
00034 #include "ibuf0ibuf.h"
00035 #include "log0recv.h"
00036 #include "trx0sys.h"
00037 #include "os0file.h"
00038 #include "srv0start.h"
00039 #include "srv0srv.h"
00040
00042 #define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA
00043
00047 #define BUF_READ_AHEAD_PEND_LIMIT 2
00048
00049
00059 UNIV_INTERN
00060 ulint
00061 buf_read_page_low(
00062
00063 ulint* err,
00066 ibool sync,
00067 ulint mode,
00070 ulint space,
00071 ulint zip_size,
00072 ibool unzip,
00073 ib_int64_t tablespace_version,
00078 ulint offset)
00079 {
00080 buf_page_t* bpage;
00081 ulint wake_later;
00082
00083 *err = DB_SUCCESS;
00084
00085 wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
00086 mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER;
00087
00088 if (trx_doublewrite && space == TRX_SYS_SPACE
00089 && ( (offset >= trx_doublewrite->block1
00090 && offset < trx_doublewrite->block1
00091 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
00092 || (offset >= trx_doublewrite->block2
00093 && offset < trx_doublewrite->block2
00094 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) {
00095 ut_print_timestamp(stderr);
00096 fprintf(stderr,
00097 " InnoDB: Warning: trying to read"
00098 " doublewrite buffer page %lu\n",
00099 (ulong) offset);
00100
00101 return(0);
00102 }
00103
00104 if (ibuf_bitmap_page(zip_size, offset)
00105 || trx_sys_hdr_page(space, offset)) {
00106
00107
00108
00109
00110
00111
00112
00113 sync = TRUE;
00114 }
00115
00116
00117
00118
00119
00120 bpage = buf_page_init_for_read(err, mode, space, zip_size, unzip,
00121 tablespace_version, offset);
00122 if (bpage == NULL) {
00123
00124 return(0);
00125 }
00126
00127 #ifdef UNIV_DEBUG
00128 if (buf_debug_prints) {
00129 fprintf(stderr,
00130 "Posting read request for page %lu, sync %lu\n",
00131 (ulong) offset,
00132 (ulong) sync);
00133 }
00134 #endif
00135
00136 ut_ad(buf_page_in_file(bpage));
00137
00138 if (zip_size) {
00139 *err = fil_io(OS_FILE_READ | wake_later,
00140 sync, space, zip_size, offset, 0, zip_size,
00141 bpage->zip.data, bpage);
00142 } else {
00143 ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
00144
00145 *err = fil_io(OS_FILE_READ | wake_later,
00146 sync, space, 0, offset, 0, UNIV_PAGE_SIZE,
00147 ((buf_block_t*) bpage)->frame, bpage);
00148 }
00149 ut_a(*err == DB_SUCCESS);
00150
00151 if (sync) {
00152
00153
00154 buf_page_io_complete(bpage);
00155 }
00156
00157 return(1);
00158 }
00159
00160
00166 UNIV_INTERN
00167 ibool
00168 buf_read_page(
00169
00170 ulint space,
00171 ulint zip_size,
00172 ulint offset)
00173 {
00174 buf_pool_t* buf_pool = buf_pool_get(space, offset);
00175 ib_int64_t tablespace_version;
00176 ulint count;
00177 ulint err;
00178
00179 tablespace_version = fil_space_get_version(space);
00180
00181
00182
00183
00184 count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
00185 zip_size, FALSE,
00186 tablespace_version, offset);
00187 srv_buf_pool_reads += count;
00188 if (err == DB_TABLESPACE_DELETED) {
00189 ut_print_timestamp(stderr);
00190 fprintf(stderr,
00191 " InnoDB: Error: trying to access"
00192 " tablespace %lu page no. %lu,\n"
00193 "InnoDB: but the tablespace does not exist"
00194 " or is just being dropped.\n",
00195 (ulong) space, (ulong) offset);
00196 }
00197
00198
00199 buf_flush_free_margin(buf_pool);
00200
00201
00202 buf_LRU_stat_inc_io();
00203
00204 return(count);
00205 }
00206
00207
00231 UNIV_INTERN
00232 ulint
00233 buf_read_ahead_linear(
00234
00235 ulint space,
00236 ulint zip_size,
00237 ulint offset)
00239 {
00240 buf_pool_t* buf_pool = buf_pool_get(space, offset);
00241 ib_int64_t tablespace_version;
00242 buf_page_t* bpage;
00243 buf_frame_t* frame;
00244 buf_page_t* pred_bpage = NULL;
00245 ulint pred_offset;
00246 ulint succ_offset;
00247 ulint count;
00248 int asc_or_desc;
00249 ulint new_offset;
00250 ulint fail_count;
00251 ulint ibuf_mode;
00252 ulint low, high;
00253 ulint err;
00254 ulint i;
00255 const ulint buf_read_ahead_linear_area
00256 = BUF_READ_AHEAD_LINEAR_AREA(buf_pool);
00257 ulint threshold;
00258
00259 if ((srv_read_ahead & 2) == false) {
00260 return(0);
00261 }
00262
00263 if (UNIV_UNLIKELY(srv_startup_is_before_trx_rollback_phase)) {
00264
00265 return(0);
00266 }
00267
00268 low = (offset / buf_read_ahead_linear_area)
00269 * buf_read_ahead_linear_area;
00270 high = (offset / buf_read_ahead_linear_area + 1)
00271 * buf_read_ahead_linear_area;
00272
00273 if ((offset != low) && (offset != high - 1)) {
00274
00275
00276 return(0);
00277 }
00278
00279 if (ibuf_bitmap_page(zip_size, offset)
00280 || trx_sys_hdr_page(space, offset)) {
00281
00282
00283
00284
00285
00286 return(0);
00287 }
00288
00289
00290
00291
00292
00293 tablespace_version = fil_space_get_version(space);
00294
00295 buf_pool_mutex_enter(buf_pool);
00296
00297 if (high > fil_space_get_size(space)) {
00298 buf_pool_mutex_exit(buf_pool);
00299
00300
00301 return(0);
00302 }
00303
00304 if (buf_pool->n_pend_reads
00305 > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
00306 buf_pool_mutex_exit(buf_pool);
00307
00308 return(0);
00309 }
00310
00311
00312
00313
00314
00315 asc_or_desc = 1;
00316
00317 if (offset == low) {
00318 asc_or_desc = -1;
00319 }
00320
00321
00322
00323 threshold = ut_min((64 - srv_read_ahead_threshold),
00324 BUF_READ_AHEAD_AREA(buf_pool));
00325
00326 fail_count = 0;
00327
00328 for (i = low; i < high; i++) {
00329 bpage = buf_page_hash_get(buf_pool, space, i);
00330
00331 if (bpage == NULL || !buf_page_is_accessed(bpage)) {
00332
00333 fail_count++;
00334
00335 } else if (pred_bpage) {
00336
00337
00338
00339
00340
00341
00342
00343
00344 int res = ut_ulint_cmp(
00345 buf_page_is_accessed(bpage),
00346 buf_page_is_accessed(pred_bpage));
00347
00348 if (res != 0 && res != asc_or_desc) {
00349 fail_count++;
00350 }
00351 }
00352
00353 if (fail_count > threshold) {
00354
00355 buf_pool_mutex_exit(buf_pool);
00356 return(0);
00357 }
00358
00359 if (bpage && buf_page_is_accessed(bpage)) {
00360 pred_bpage = bpage;
00361 }
00362 }
00363
00364
00365
00366
00367 bpage = buf_page_hash_get(buf_pool, space, offset);
00368
00369 if (bpage == NULL) {
00370 buf_pool_mutex_exit(buf_pool);
00371
00372 return(0);
00373 }
00374
00375 switch (buf_page_get_state(bpage)) {
00376 case BUF_BLOCK_ZIP_PAGE:
00377 frame = bpage->zip.data;
00378 break;
00379 case BUF_BLOCK_FILE_PAGE:
00380 frame = ((buf_block_t*) bpage)->frame;
00381 break;
00382 default:
00383 ut_error;
00384 break;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393 pred_offset = fil_page_get_prev(frame);
00394 succ_offset = fil_page_get_next(frame);
00395
00396 buf_pool_mutex_exit(buf_pool);
00397
00398 if ((offset == low) && (succ_offset == offset + 1)) {
00399
00400
00401 new_offset = pred_offset;
00402
00403 } else if ((offset == high - 1) && (pred_offset == offset - 1)) {
00404
00405
00406 new_offset = succ_offset;
00407 } else {
00408
00409
00410 return(0);
00411 }
00412
00413 low = (new_offset / buf_read_ahead_linear_area)
00414 * buf_read_ahead_linear_area;
00415 high = (new_offset / buf_read_ahead_linear_area + 1)
00416 * buf_read_ahead_linear_area;
00417
00418 if ((new_offset != low) && (new_offset != high - 1)) {
00419
00420
00421 return(0);
00422 }
00423
00424 if (high > fil_space_get_size(space)) {
00425
00426
00427 return(0);
00428 }
00429
00430
00431
00432 if (ibuf_inside()) {
00433 ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
00434 } else {
00435 ibuf_mode = BUF_READ_ANY_PAGE;
00436 }
00437
00438 count = 0;
00439
00440
00441
00442
00443
00444 os_aio_simulated_put_read_threads_to_sleep();
00445
00446 for (i = low; i < high; i++) {
00447
00448
00449
00450 if (!ibuf_bitmap_page(zip_size, i)) {
00451 count += buf_read_page_low(
00452 &err, FALSE,
00453 ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
00454 space, zip_size, FALSE, tablespace_version, i);
00455 if (err == DB_TABLESPACE_DELETED) {
00456 ut_print_timestamp(stderr);
00457 fprintf(stderr,
00458 " InnoDB: Warning: in"
00459 " linear readahead trying to access\n"
00460 "InnoDB: tablespace %lu page %lu,\n"
00461 "InnoDB: but the tablespace does not"
00462 " exist or is just being dropped.\n",
00463 (ulong) space, (ulong) i);
00464 }
00465 }
00466 }
00467
00468
00469
00470
00471
00472 os_aio_simulated_wake_handler_threads();
00473
00474
00475 buf_flush_free_margin(buf_pool);
00476
00477 #ifdef UNIV_DEBUG
00478 if (buf_debug_prints && (count > 0)) {
00479 fprintf(stderr,
00480 "LINEAR read-ahead space %lu offset %lu pages %lu\n",
00481 (ulong) space, (ulong) offset, (ulong) count);
00482 }
00483 #endif
00484
00485
00486
00487 buf_LRU_stat_inc_io();
00488
00489 buf_pool->stat.n_ra_pages_read += count;
00490 return(count);
00491 }
00492
00493
00497 UNIV_INTERN
00498 void
00499 buf_read_ibuf_merge_pages(
00500
00501 ibool sync,
00506 const ulint* space_ids,
00507 const ib_int64_t* space_versions,
00514 const ulint* page_nos,
00518 ulint n_stored)
00520 {
00521 ulint i;
00522
00523 ut_ad(!ibuf_inside());
00524 #ifdef UNIV_IBUF_DEBUG
00525 ut_a(n_stored < UNIV_PAGE_SIZE);
00526 #endif
00527
00528 for (i = 0; i < n_stored; i++) {
00529 ulint err;
00530 buf_pool_t* buf_pool;
00531 ulint zip_size = fil_space_get_zip_size(space_ids[i]);
00532
00533 buf_pool = buf_pool_get(space_ids[i], space_versions[i]);
00534
00535 while (buf_pool->n_pend_reads
00536 > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
00537 os_thread_sleep(500000);
00538 }
00539
00540 if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
00541
00542 goto tablespace_deleted;
00543 }
00544
00545 buf_read_page_low(&err, sync && (i + 1 == n_stored),
00546 BUF_READ_ANY_PAGE, space_ids[i],
00547 zip_size, TRUE, space_versions[i],
00548 page_nos[i]);
00549
00550 if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) {
00551 tablespace_deleted:
00552
00553
00554
00555 ibuf_merge_or_delete_for_page(NULL, space_ids[i],
00556 page_nos[i],
00557 zip_size, FALSE);
00558 }
00559 }
00560
00561 os_aio_simulated_wake_handler_threads();
00562
00563
00564 buf_flush_free_margins();
00565
00566 #ifdef UNIV_DEBUG
00567 if (buf_debug_prints) {
00568 fprintf(stderr,
00569 "Ibuf merge read-ahead space %lu pages %lu\n",
00570 (ulong) space_ids[0], (ulong) n_stored);
00571 }
00572 #endif
00573 }
00574
00575
00577 UNIV_INTERN
00578 void
00579 buf_read_recv_pages(
00580
00581 ibool sync,
00586 ulint space,
00587 ulint zip_size,
00589 const ulint* page_nos,
00593 ulint n_stored)
00595 {
00596 ib_int64_t tablespace_version;
00597 ulint count;
00598 ulint err;
00599 ulint i;
00600
00601 zip_size = fil_space_get_zip_size(space);
00602
00603 if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
00604
00605
00606
00607 return;
00608 }
00609
00610 tablespace_version = fil_space_get_version(space);
00611
00612 for (i = 0; i < n_stored; i++) {
00613 buf_pool_t* buf_pool;
00614
00615 count = 0;
00616
00617 os_aio_print_debug = FALSE;
00618 buf_pool = buf_pool_get(space, page_nos[i]);
00619 while (buf_pool->n_pend_reads >= recv_n_pool_free_frames / 2) {
00620
00621 os_aio_simulated_wake_handler_threads();
00622 os_thread_sleep(10000);
00623
00624 count++;
00625
00626 if (count > 1000) {
00627 fprintf(stderr,
00628 "InnoDB: Error: InnoDB has waited for"
00629 " 10 seconds for pending\n"
00630 "InnoDB: reads to the buffer pool to"
00631 " be finished.\n"
00632 "InnoDB: Number of pending reads %lu,"
00633 " pending pread calls %lu\n",
00634 (ulong) buf_pool->n_pend_reads,
00635 (ulong)os_file_n_pending_preads);
00636
00637 os_aio_print_debug = TRUE;
00638 }
00639 }
00640
00641 os_aio_print_debug = FALSE;
00642
00643 if ((i + 1 == n_stored) && sync) {
00644 buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
00645 zip_size, TRUE, tablespace_version,
00646 page_nos[i]);
00647 } else {
00648 buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
00649 | OS_AIO_SIMULATED_WAKE_LATER,
00650 space, zip_size, TRUE,
00651 tablespace_version, page_nos[i]);
00652 }
00653 }
00654
00655 os_aio_simulated_wake_handler_threads();
00656
00657
00658 buf_flush_free_margins();
00659
00660 #ifdef UNIV_DEBUG
00661 if (buf_debug_prints) {
00662 fprintf(stderr,
00663 "Recovery applies read-ahead pages %lu\n",
00664 (ulong) n_stored);
00665 }
00666 #endif
00667 }