1/***************************************************************************** 2 3Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. 4Copyright (c) 2008, Google Inc. 5 6Portions of this file contain modifications contributed and copyrighted by 7Google, Inc. Those modifications are gratefully acknowledged and are described 8briefly in the InnoDB documentation. The contributions by Google are 9incorporated with their permission, and subject to the conditions contained in 10the file COPYING.Google. 11 12This program is free software; you can redistribute it and/or modify 13it under the terms of the GNU General Public License, version 2.0, 14as published by the Free Software Foundation. 15 16This program is also distributed with certain software (including 17but not limited to OpenSSL) that is licensed under separate terms, 18as designated in a particular file or component or in included license 19documentation. The authors of MySQL hereby grant you an additional 20permission to link the program and your derivative works with the 21separately licensed software that they have included with MySQL. 22 23This program is distributed in the hope that it will be useful, 24but WITHOUT ANY WARRANTY; without even the implied warranty of 25MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26GNU General Public License, version 2.0, for more details. 27 28You should have received a copy of the GNU General Public License along with 29this program; if not, write to the Free Software Foundation, Inc., 3051 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 31 32*****************************************************************************/ 33 34/**************************************************//** 35@file include/buf0buf.ic 36The database buffer buf_pool 37 38Created 11/5/1995 Heikki Tuuri 39*******************************************************/ 40 41#include "mtr0mtr.h" 42#ifndef UNIV_HOTBACKUP 43#include "buf0flu.h" 44#include "buf0lru.h" 45#include "buf0rea.h" 46 47/** A chunk of buffers. The buffer pool is allocated in chunks. */ 48struct buf_chunk_t{ 49 ulint mem_size; /*!< allocated size of the chunk */ 50 ulint size; /*!< size of frames[] and blocks[] */ 51 void* mem; /*!< pointer to the memory area which 52 was allocated for the frames */ 53 buf_block_t* blocks; /*!< array of buffer control blocks */ 54}; 55 56/*********************************************************************//** 57Gets the current size of buffer buf_pool in bytes. 58@return size in bytes */ 59UNIV_INLINE 60ulint 61buf_pool_get_curr_size(void) 62/*========================*/ 63{ 64 return(srv_buf_pool_curr_size); 65} 66 67/********************************************************************//** 68Calculates the index of a buffer pool to the buf_pool[] array. 69@return the position of the buffer pool in buf_pool[] */ 70UNIV_INLINE 71ulint 72buf_pool_index( 73/*===========*/ 74 const buf_pool_t* buf_pool) /*!< in: buffer pool */ 75{ 76 ulint i = buf_pool - buf_pool_ptr; 77 ut_ad(i < MAX_BUFFER_POOLS); 78 ut_ad(i < srv_buf_pool_instances); 79 return(i); 80} 81 82/******************************************************************//** 83Returns the buffer pool instance given a page instance 84@return buf_pool */ 85UNIV_INLINE 86buf_pool_t* 87buf_pool_from_bpage( 88/*================*/ 89 const buf_page_t* bpage) /*!< in: buffer pool page */ 90{ 91 ulint i; 92 i = bpage->buf_pool_index; 93 ut_ad(i < srv_buf_pool_instances); 94 return(&buf_pool_ptr[i]); 95} 96 97/******************************************************************//** 98Returns the buffer pool instance given a block instance 99@return buf_pool */ 100UNIV_INLINE 101buf_pool_t* 102buf_pool_from_block( 103/*================*/ 104 const buf_block_t* block) /*!< in: block */ 105{ 106 return(buf_pool_from_bpage(&block->page)); 107} 108 109/*********************************************************************//** 110Gets the current size of buffer buf_pool in pages. 111@return size in pages*/ 112UNIV_INLINE 113ulint 114buf_pool_get_n_pages(void) 115/*======================*/ 116{ 117 return(buf_pool_get_curr_size() / UNIV_PAGE_SIZE); 118} 119 120/********************************************************************//** 121Reads the freed_page_clock of a buffer block. 122@return freed_page_clock */ 123UNIV_INLINE 124ulint 125buf_page_get_freed_page_clock( 126/*==========================*/ 127 const buf_page_t* bpage) /*!< in: block */ 128{ 129 /* This is sometimes read without holding buf_pool->mutex. */ 130 return(bpage->freed_page_clock); 131} 132 133/********************************************************************//** 134Reads the freed_page_clock of a buffer block. 135@return freed_page_clock */ 136UNIV_INLINE 137ulint 138buf_block_get_freed_page_clock( 139/*===========================*/ 140 const buf_block_t* block) /*!< in: block */ 141{ 142 return(buf_page_get_freed_page_clock(&block->page)); 143} 144 145/********************************************************************//** 146Tells if a block is still close enough to the MRU end of the LRU list 147meaning that it is not in danger of getting evicted and also implying 148that it has been accessed recently. 149Note that this is for heuristics only and does not reserve buffer pool 150mutex. 151@return TRUE if block is close to MRU end of LRU */ 152UNIV_INLINE 153ibool 154buf_page_peek_if_young( 155/*===================*/ 156 const buf_page_t* bpage) /*!< in: block */ 157{ 158 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); 159 160 /* FIXME: bpage->freed_page_clock is 31 bits */ 161 return((buf_pool->freed_page_clock & ((1UL << 31) - 1)) 162 < ((ulint) bpage->freed_page_clock 163 + (buf_pool->curr_size 164 * (BUF_LRU_OLD_RATIO_DIV - buf_pool->LRU_old_ratio) 165 / (BUF_LRU_OLD_RATIO_DIV * 4)))); 166} 167 168/********************************************************************//** 169Recommends a move of a block to the start of the LRU list if there is danger 170of dropping from the buffer pool. NOTE: does not reserve the buffer pool 171mutex. 172@return TRUE if should be made younger */ 173UNIV_INLINE 174ibool 175buf_page_peek_if_too_old( 176/*=====================*/ 177 const buf_page_t* bpage) /*!< in: block to make younger */ 178{ 179 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); 180 181 if (buf_pool->freed_page_clock == 0) { 182 /* If eviction has not started yet, do not update the 183 statistics or move blocks in the LRU list. This is 184 either the warm-up phase or an in-memory workload. */ 185 return(FALSE); 186 } else if (buf_LRU_old_threshold_ms && bpage->old) { 187 unsigned access_time = buf_page_is_accessed(bpage); 188 189 if (access_time > 0 190 && ((ib_uint32_t) (ut_time_ms() - access_time)) 191 >= buf_LRU_old_threshold_ms) { 192 return(TRUE); 193 } 194 195 buf_pool->stat.n_pages_not_made_young++; 196 return(FALSE); 197 } else { 198 return(!buf_page_peek_if_young(bpage)); 199 } 200} 201#endif /* !UNIV_HOTBACKUP */ 202 203/*********************************************************************//** 204Gets the state of a block. 205@return state */ 206UNIV_INLINE 207enum buf_page_state 208buf_page_get_state( 209/*===============*/ 210 const buf_page_t* bpage) /*!< in: pointer to the control block */ 211{ 212 enum buf_page_state state = (enum buf_page_state) bpage->state; 213 214#ifdef UNIV_DEBUG 215 switch (state) { 216 case BUF_BLOCK_POOL_WATCH: 217 case BUF_BLOCK_ZIP_PAGE: 218 case BUF_BLOCK_ZIP_DIRTY: 219 case BUF_BLOCK_NOT_USED: 220 case BUF_BLOCK_READY_FOR_USE: 221 case BUF_BLOCK_FILE_PAGE: 222 case BUF_BLOCK_MEMORY: 223 case BUF_BLOCK_REMOVE_HASH: 224 break; 225 default: 226 ut_error; 227 } 228#endif /* UNIV_DEBUG */ 229 230 return(state); 231} 232/*********************************************************************//** 233Gets the state of a block. 234@return state */ 235UNIV_INLINE 236enum buf_page_state 237buf_block_get_state( 238/*================*/ 239 const buf_block_t* block) /*!< in: pointer to the control block */ 240{ 241 return(buf_page_get_state(&block->page)); 242} 243/*********************************************************************//** 244Sets the state of a block. */ 245UNIV_INLINE 246void 247buf_page_set_state( 248/*===============*/ 249 buf_page_t* bpage, /*!< in/out: pointer to control block */ 250 enum buf_page_state state) /*!< in: state */ 251{ 252#ifdef UNIV_DEBUG 253 enum buf_page_state old_state = buf_page_get_state(bpage); 254 255 switch (old_state) { 256 case BUF_BLOCK_POOL_WATCH: 257 ut_error; 258 break; 259 case BUF_BLOCK_ZIP_PAGE: 260 ut_a(state == BUF_BLOCK_ZIP_DIRTY); 261 break; 262 case BUF_BLOCK_ZIP_DIRTY: 263 ut_a(state == BUF_BLOCK_ZIP_PAGE); 264 break; 265 case BUF_BLOCK_NOT_USED: 266 ut_a(state == BUF_BLOCK_READY_FOR_USE); 267 break; 268 case BUF_BLOCK_READY_FOR_USE: 269 ut_a(state == BUF_BLOCK_MEMORY 270 || state == BUF_BLOCK_FILE_PAGE 271 || state == BUF_BLOCK_NOT_USED); 272 break; 273 case BUF_BLOCK_MEMORY: 274 ut_a(state == BUF_BLOCK_NOT_USED); 275 break; 276 case BUF_BLOCK_FILE_PAGE: 277 ut_a(state == BUF_BLOCK_NOT_USED 278 || state == BUF_BLOCK_REMOVE_HASH); 279 break; 280 case BUF_BLOCK_REMOVE_HASH: 281 ut_a(state == BUF_BLOCK_MEMORY); 282 break; 283 } 284#endif /* UNIV_DEBUG */ 285 bpage->state = state; 286 ut_ad(buf_page_get_state(bpage) == state); 287} 288 289/*********************************************************************//** 290Sets the state of a block. */ 291UNIV_INLINE 292void 293buf_block_set_state( 294/*================*/ 295 buf_block_t* block, /*!< in/out: pointer to control block */ 296 enum buf_page_state state) /*!< in: state */ 297{ 298 buf_page_set_state(&block->page, state); 299} 300 301/*********************************************************************//** 302Determines if a block is mapped to a tablespace. 303@return TRUE if mapped */ 304UNIV_INLINE 305ibool 306buf_page_in_file( 307/*=============*/ 308 const buf_page_t* bpage) /*!< in: pointer to control block */ 309{ 310 switch (buf_page_get_state(bpage)) { 311 case BUF_BLOCK_POOL_WATCH: 312 ut_error; 313 break; 314 case BUF_BLOCK_ZIP_PAGE: 315 case BUF_BLOCK_ZIP_DIRTY: 316 case BUF_BLOCK_FILE_PAGE: 317 return(TRUE); 318 case BUF_BLOCK_NOT_USED: 319 case BUF_BLOCK_READY_FOR_USE: 320 case BUF_BLOCK_MEMORY: 321 case BUF_BLOCK_REMOVE_HASH: 322 break; 323 } 324 325 return(FALSE); 326} 327 328#ifndef UNIV_HOTBACKUP 329/*********************************************************************//** 330Determines if a block should be on unzip_LRU list. 331@return TRUE if block belongs to unzip_LRU */ 332UNIV_INLINE 333ibool 334buf_page_belongs_to_unzip_LRU( 335/*==========================*/ 336 const buf_page_t* bpage) /*!< in: pointer to control block */ 337{ 338 ut_ad(buf_page_in_file(bpage)); 339 340 return(bpage->zip.data 341 && buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); 342} 343 344/*********************************************************************//** 345Gets the mutex of a block. 346@return pointer to mutex protecting bpage */ 347UNIV_INLINE 348ib_mutex_t* 349buf_page_get_mutex( 350/*===============*/ 351 const buf_page_t* bpage) /*!< in: pointer to control block */ 352{ 353 switch (buf_page_get_state(bpage)) { 354 case BUF_BLOCK_POOL_WATCH: 355 ut_error; 356 return(NULL); 357 case BUF_BLOCK_ZIP_PAGE: 358 case BUF_BLOCK_ZIP_DIRTY: { 359 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); 360 361 return(&buf_pool->zip_mutex); 362 } 363 default: 364 return(&((buf_block_t*) bpage)->mutex); 365 } 366} 367 368/*********************************************************************//** 369Get the flush type of a page. 370@return flush type */ 371UNIV_INLINE 372buf_flush_t 373buf_page_get_flush_type( 374/*====================*/ 375 const buf_page_t* bpage) /*!< in: buffer page */ 376{ 377 buf_flush_t flush_type = (buf_flush_t) bpage->flush_type; 378 379#ifdef UNIV_DEBUG 380 switch (flush_type) { 381 case BUF_FLUSH_LRU: 382 case BUF_FLUSH_LIST: 383 case BUF_FLUSH_SINGLE_PAGE: 384 return(flush_type); 385 case BUF_FLUSH_N_TYPES: 386 ut_error; 387 } 388 ut_error; 389#endif /* UNIV_DEBUG */ 390 return(flush_type); 391} 392/*********************************************************************//** 393Set the flush type of a page. */ 394UNIV_INLINE 395void 396buf_page_set_flush_type( 397/*====================*/ 398 buf_page_t* bpage, /*!< in: buffer page */ 399 buf_flush_t flush_type) /*!< in: flush type */ 400{ 401 bpage->flush_type = flush_type; 402 ut_ad(buf_page_get_flush_type(bpage) == flush_type); 403} 404 405/*********************************************************************//** 406Map a block to a file page. */ 407UNIV_INLINE 408void 409buf_block_set_file_page( 410/*====================*/ 411 buf_block_t* block, /*!< in/out: pointer to control block */ 412 ulint space, /*!< in: tablespace id */ 413 ulint page_no)/*!< in: page number */ 414{ 415 buf_block_set_state(block, BUF_BLOCK_FILE_PAGE); 416 block->page.space = static_cast<ib_uint32_t>(space); 417 block->page.offset = static_cast<ib_uint32_t>(page_no); 418} 419 420/*********************************************************************//** 421Gets the io_fix state of a block. 422@return io_fix state */ 423UNIV_INLINE 424enum buf_io_fix 425buf_page_get_io_fix( 426/*================*/ 427 const buf_page_t* bpage) /*!< in: pointer to the control block */ 428{ 429 ut_ad(bpage != NULL); 430 431 enum buf_io_fix io_fix = (enum buf_io_fix) bpage->io_fix; 432#ifdef UNIV_DEBUG 433 switch (io_fix) { 434 case BUF_IO_NONE: 435 case BUF_IO_READ: 436 case BUF_IO_WRITE: 437 case BUF_IO_PIN: 438 return(io_fix); 439 } 440 ut_error; 441#endif /* UNIV_DEBUG */ 442 return(io_fix); 443} 444 445/*********************************************************************//** 446Gets the io_fix state of a block. 447@return io_fix state */ 448UNIV_INLINE 449enum buf_io_fix 450buf_block_get_io_fix( 451/*=================*/ 452 const buf_block_t* block) /*!< in: pointer to the control block */ 453{ 454 return(buf_page_get_io_fix(&block->page)); 455} 456 457/*********************************************************************//** 458Sets the io_fix state of a block. */ 459UNIV_INLINE 460void 461buf_page_set_io_fix( 462/*================*/ 463 buf_page_t* bpage, /*!< in/out: control block */ 464 enum buf_io_fix io_fix) /*!< in: io_fix state */ 465{ 466#ifdef UNIV_DEBUG 467 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); 468 ut_ad(buf_pool_mutex_own(buf_pool)); 469#endif 470 ut_ad(mutex_own(buf_page_get_mutex(bpage))); 471 472 bpage->io_fix = io_fix; 473 ut_ad(buf_page_get_io_fix(bpage) == io_fix); 474} 475 476/*********************************************************************//** 477Sets the io_fix state of a block. */ 478UNIV_INLINE 479void 480buf_block_set_io_fix( 481/*=================*/ 482 buf_block_t* block, /*!< in/out: control block */ 483 enum buf_io_fix io_fix) /*!< in: io_fix state */ 484{ 485 buf_page_set_io_fix(&block->page, io_fix); 486} 487 488/*********************************************************************//** 489Makes a block sticky. A sticky block implies that even after we release 490the buf_pool->mutex and the block->mutex: 491* it cannot be removed from the flush_list 492* the block descriptor cannot be relocated 493* it cannot be removed from the LRU list 494Note that: 495* the block can still change its position in the LRU list 496* the next and previous pointers can change. */ 497UNIV_INLINE 498void 499buf_page_set_sticky( 500/*================*/ 501 buf_page_t* bpage) /*!< in/out: control block */ 502{ 503#ifdef UNIV_DEBUG 504 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); 505 ut_ad(buf_pool_mutex_own(buf_pool)); 506#endif 507 ut_ad(mutex_own(buf_page_get_mutex(bpage))); 508 ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_NONE); 509 510 bpage->io_fix = BUF_IO_PIN; 511} 512 513/*********************************************************************//** 514Removes stickiness of a block. */ 515UNIV_INLINE 516void 517buf_page_unset_sticky( 518/*==================*/ 519 buf_page_t* bpage) /*!< in/out: control block */ 520{ 521#ifdef UNIV_DEBUG 522 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); 523 ut_ad(buf_pool_mutex_own(buf_pool)); 524#endif 525 ut_ad(mutex_own(buf_page_get_mutex(bpage))); 526 ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_PIN); 527 528 bpage->io_fix = BUF_IO_NONE; 529} 530 531/********************************************************************//** 532Determine if a buffer block can be relocated in memory. The block 533can be dirty, but it must not be I/O-fixed or bufferfixed. */ 534UNIV_INLINE 535ibool 536buf_page_can_relocate( 537/*==================*/ 538 const buf_page_t* bpage) /*!< control block being relocated */ 539{ 540#ifdef UNIV_DEBUG 541 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); 542 ut_ad(buf_pool_mutex_own(buf_pool)); 543#endif 544 ut_ad(mutex_own(buf_page_get_mutex(bpage))); 545 ut_ad(buf_page_in_file(bpage)); 546 ut_ad(bpage->in_LRU_list); 547 548 return(buf_page_get_io_fix(bpage) == BUF_IO_NONE 549 && bpage->buf_fix_count == 0); 550} 551 552/*********************************************************************//** 553Determine if a block has been flagged old. 554@return TRUE if old */ 555UNIV_INLINE 556ibool 557buf_page_is_old( 558/*============*/ 559 const buf_page_t* bpage) /*!< in: control block */ 560{ 561#ifdef UNIV_DEBUG 562 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); 563 ut_ad(buf_pool_mutex_own(buf_pool)); 564#endif 565 ut_ad(buf_page_in_file(bpage)); 566 567 return(bpage->old); 568} 569 570/*********************************************************************//** 571Flag a block old. */ 572UNIV_INLINE 573void 574buf_page_set_old( 575/*=============*/ 576 buf_page_t* bpage, /*!< in/out: control block */ 577 ibool old) /*!< in: old */ 578{ 579#ifdef UNIV_DEBUG 580 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); 581#endif /* UNIV_DEBUG */ 582 ut_a(buf_page_in_file(bpage)); 583 ut_ad(buf_pool_mutex_own(buf_pool)); 584 ut_ad(bpage->in_LRU_list); 585 586#ifdef UNIV_LRU_DEBUG 587 ut_a((buf_pool->LRU_old_len == 0) == (buf_pool->LRU_old == NULL)); 588 /* If a block is flagged "old", the LRU_old list must exist. */ 589 ut_a(!old || buf_pool->LRU_old); 590 591 if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)) { 592 const buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); 593 const buf_page_t* next = UT_LIST_GET_NEXT(LRU, bpage); 594 if (prev->old == next->old) { 595 ut_a(prev->old == old); 596 } else { 597 ut_a(!prev->old); 598 ut_a(buf_pool->LRU_old == (old ? bpage : next)); 599 } 600 } 601#endif /* UNIV_LRU_DEBUG */ 602 603 bpage->old = old; 604} 605 606/*********************************************************************//** 607Determine the time of first access of a block in the buffer pool. 608@return ut_time_ms() at the time of first access, 0 if not accessed */ 609UNIV_INLINE 610unsigned 611buf_page_is_accessed( 612/*=================*/ 613 const buf_page_t* bpage) /*!< in: control block */ 614{ 615 ut_ad(buf_page_in_file(bpage)); 616 617 return(bpage->access_time); 618} 619 620/*********************************************************************//** 621Flag a block accessed. */ 622UNIV_INLINE 623void 624buf_page_set_accessed( 625/*==================*/ 626 buf_page_t* bpage) /*!< in/out: control block */ 627{ 628#ifdef UNIV_DEBUG 629 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); 630 ut_ad(!buf_pool_mutex_own(buf_pool)); 631 ut_ad(mutex_own(buf_page_get_mutex(bpage))); 632#endif /* UNIV_DEBUG */ 633 634 ut_a(buf_page_in_file(bpage)); 635 636 if (bpage->access_time == 0) { 637 /* Make this the time of the first access. */ 638 bpage->access_time = static_cast<uint>(ut_time_ms()); 639 } 640} 641 642/*********************************************************************//** 643Gets the buf_block_t handle of a buffered file block if an uncompressed 644page frame exists, or NULL. 645@return control block, or NULL */ 646UNIV_INLINE 647buf_block_t* 648buf_page_get_block( 649/*===============*/ 650 buf_page_t* bpage) /*!< in: control block, or NULL */ 651{ 652 if (bpage != NULL) { 653 ut_ad(buf_page_in_file(bpage)); 654 655 if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { 656 return((buf_block_t*) bpage); 657 } 658 } 659 660 return(NULL); 661} 662#endif /* !UNIV_HOTBACKUP */ 663 664#ifdef UNIV_DEBUG 665/*********************************************************************//** 666Gets a pointer to the memory frame of a block. 667@return pointer to the frame */ 668UNIV_INLINE 669buf_frame_t* 670buf_block_get_frame( 671/*================*/ 672 const buf_block_t* block) /*!< in: pointer to the control block */ 673{ 674 ut_ad(block); 675 676 switch (buf_block_get_state(block)) { 677 case BUF_BLOCK_POOL_WATCH: 678 case BUF_BLOCK_ZIP_PAGE: 679 case BUF_BLOCK_ZIP_DIRTY: 680 case BUF_BLOCK_NOT_USED: 681 ut_error; 682 break; 683 case BUF_BLOCK_FILE_PAGE: 684# ifndef UNIV_HOTBACKUP 685 ut_a(block->page.buf_fix_count > 0); 686# endif /* !UNIV_HOTBACKUP */ 687 /* fall through */ 688 case BUF_BLOCK_READY_FOR_USE: 689 case BUF_BLOCK_MEMORY: 690 case BUF_BLOCK_REMOVE_HASH: 691 goto ok; 692 } 693 ut_error; 694ok: 695 return((buf_frame_t*) block->frame); 696} 697#endif /* UNIV_DEBUG */ 698 699/*********************************************************************//** 700Gets the space id of a block. 701@return space id */ 702UNIV_INLINE 703ulint 704buf_page_get_space( 705/*===============*/ 706 const buf_page_t* bpage) /*!< in: pointer to the control block */ 707{ 708 ut_ad(bpage); 709 ut_a(buf_page_in_file(bpage)); 710 711 return(bpage->space); 712} 713 714/*********************************************************************//** 715Gets the space id of a block. 716@return space id */ 717UNIV_INLINE 718ulint 719buf_block_get_space( 720/*================*/ 721 const buf_block_t* block) /*!< in: pointer to the control block */ 722{ 723 ut_ad(block); 724 ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); 725 726 return(block->page.space); 727} 728 729/*********************************************************************//** 730Gets the page number of a block. 731@return page number */ 732UNIV_INLINE 733ulint 734buf_page_get_page_no( 735/*=================*/ 736 const buf_page_t* bpage) /*!< in: pointer to the control block */ 737{ 738 ut_ad(bpage); 739 ut_a(buf_page_in_file(bpage)); 740 741 return(bpage->offset); 742} 743/*********************************************************************** 744FIXME_FTS Gets the frame the pointer is pointing to. */ 745UNIV_INLINE 746buf_frame_t* 747buf_frame_align( 748/*============*/ 749 /* out: pointer to frame */ 750 byte* ptr) /* in: pointer to a frame */ 751{ 752 buf_frame_t* frame; 753 754 ut_ad(ptr); 755 756 frame = (buf_frame_t*) ut_align_down(ptr, UNIV_PAGE_SIZE); 757 758 return(frame); 759} 760 761/*********************************************************************//** 762Gets the page number of a block. 763@return page number */ 764UNIV_INLINE 765ulint 766buf_block_get_page_no( 767/*==================*/ 768 const buf_block_t* block) /*!< in: pointer to the control block */ 769{ 770 ut_ad(block); 771 ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); 772 773 return(block->page.offset); 774} 775 776/*********************************************************************//** 777Gets the compressed page size of a block. 778@return compressed page size, or 0 */ 779UNIV_INLINE 780ulint 781buf_page_get_zip_size( 782/*==================*/ 783 const buf_page_t* bpage) /*!< in: pointer to the control block */ 784{ 785 return(bpage->zip.ssize 786 ? (UNIV_ZIP_SIZE_MIN >> 1) << bpage->zip.ssize : 0); 787} 788 789/*********************************************************************//** 790Gets the compressed page size of a block. 791@return compressed page size, or 0 */ 792UNIV_INLINE 793ulint 794buf_block_get_zip_size( 795/*===================*/ 796 const buf_block_t* block) /*!< in: pointer to the control block */ 797{ 798 return(block->page.zip.ssize 799 ? (UNIV_ZIP_SIZE_MIN >> 1) << block->page.zip.ssize : 0); 800} 801 802#ifndef UNIV_HOTBACKUP 803#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG 804/*********************************************************************//** 805Gets the compressed page descriptor corresponding to an uncompressed page 806if applicable. 807@return compressed page descriptor, or NULL */ 808UNIV_INLINE 809const page_zip_des_t* 810buf_frame_get_page_zip( 811/*===================*/ 812 const byte* ptr) /*!< in: pointer to the page */ 813{ 814 return(buf_block_get_page_zip(buf_block_align(ptr))); 815} 816#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */ 817#endif /* !UNIV_HOTBACKUP */ 818 819/**********************************************************************//** 820Gets the space id, page offset, and byte offset within page of a 821pointer pointing to a buffer frame containing a file page. */ 822UNIV_INLINE 823void 824buf_ptr_get_fsp_addr( 825/*=================*/ 826 const void* ptr, /*!< in: pointer to a buffer frame */ 827 ulint* space, /*!< out: space id */ 828 fil_addr_t* addr) /*!< out: page offset and byte offset */ 829{ 830 const page_t* page = (const page_t*) ut_align_down(ptr, 831 UNIV_PAGE_SIZE); 832 833 *space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); 834 addr->page = mach_read_from_4(page + FIL_PAGE_OFFSET); 835 addr->boffset = ut_align_offset(ptr, UNIV_PAGE_SIZE); 836} 837 838#ifndef UNIV_HOTBACKUP 839/**********************************************************************//** 840Gets the hash value of the page the pointer is pointing to. This can be used 841in searches in the lock hash table. 842@return lock hash value */ 843UNIV_INLINE 844ulint 845buf_block_get_lock_hash_val( 846/*========================*/ 847 const buf_block_t* block) /*!< in: block */ 848{ 849 ut_ad(block); 850 ut_ad(buf_page_in_file(&block->page)); 851#ifdef UNIV_SYNC_DEBUG 852 ut_ad(rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_EXCLUSIVE) 853 || rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_SHARED)); 854#endif /* UNIV_SYNC_DEBUG */ 855 return(block->lock_hash_val); 856} 857 858/********************************************************************//** 859Allocates a buf_page_t descriptor. This function must succeed. In case 860of failure we assert in this function. 861@return: the allocated descriptor. */ 862UNIV_INLINE 863buf_page_t* 864buf_page_alloc_descriptor(void) 865/*===========================*/ 866{ 867 buf_page_t* bpage; 868 869 bpage = (buf_page_t*) ut_malloc(sizeof *bpage); 870 ut_d(memset(bpage, 0, sizeof *bpage)); 871 UNIV_MEM_ALLOC(bpage, sizeof *bpage); 872 873 return(bpage); 874} 875 876/********************************************************************//** 877Free a buf_page_t descriptor. */ 878UNIV_INLINE 879void 880buf_page_free_descriptor( 881/*=====================*/ 882 buf_page_t* bpage) /*!< in: bpage descriptor to free. */ 883{ 884 ut_free(bpage); 885} 886 887/********************************************************************//** 888Frees a buffer block which does not contain a file page. */ 889UNIV_INLINE 890void 891buf_block_free( 892/*===========*/ 893 buf_block_t* block) /*!< in, own: block to be freed */ 894{ 895 buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*) block); 896 897 buf_pool_mutex_enter(buf_pool); 898 899 mutex_enter(&block->mutex); 900 901 ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE); 902 903 buf_LRU_block_free_non_file_page(block); 904 905 mutex_exit(&block->mutex); 906 907 buf_pool_mutex_exit(buf_pool); 908} 909#endif /* !UNIV_HOTBACKUP */ 910 911/*********************************************************************//** 912Copies contents of a buffer frame to a given buffer. 913@return buf */ 914UNIV_INLINE 915byte* 916buf_frame_copy( 917/*===========*/ 918 byte* buf, /*!< in: buffer to copy to */ 919 const buf_frame_t* frame) /*!< in: buffer frame */ 920{ 921 ut_ad(buf && frame); 922 923 ut_memcpy(buf, frame, UNIV_PAGE_SIZE); 924 925 return(buf); 926} 927 928#ifndef UNIV_HOTBACKUP 929/********************************************************************//** 930Calculates a folded value of a file page address to use in the page hash 931table. 932@return the folded value */ 933UNIV_INLINE 934ulint 935buf_page_address_fold( 936/*==================*/ 937 ulint space, /*!< in: space id */ 938 ulint offset) /*!< in: offset of the page within space */ 939{ 940 return((space << 20) + space + offset); 941} 942 943/********************************************************************//** 944Gets the youngest modification log sequence number for a frame. 945Returns zero if not file page or no modification occurred yet. 946@return newest modification to page */ 947UNIV_INLINE 948lsn_t 949buf_page_get_newest_modification( 950/*=============================*/ 951 const buf_page_t* bpage) /*!< in: block containing the 952 page frame */ 953{ 954 lsn_t lsn; 955 ib_mutex_t* block_mutex = buf_page_get_mutex(bpage); 956 957 mutex_enter(block_mutex); 958 959 if (buf_page_in_file(bpage)) { 960 lsn = bpage->newest_modification; 961 } else { 962 lsn = 0; 963 } 964 965 mutex_exit(block_mutex); 966 967 return(lsn); 968} 969 970/********************************************************************//** 971Increments the modify clock of a frame by 1. The caller must (1) own the 972buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock 973on the block. */ 974UNIV_INLINE 975void 976buf_block_modify_clock_inc( 977/*=======================*/ 978 buf_block_t* block) /*!< in: block */ 979{ 980#ifdef UNIV_SYNC_DEBUG 981 buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*) block); 982 983 ut_ad((buf_pool_mutex_own(buf_pool) 984 && (block->page.buf_fix_count == 0)) 985 || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE)); 986#endif /* UNIV_SYNC_DEBUG */ 987 988 block->modify_clock++; 989} 990 991/********************************************************************//** 992Returns the value of the modify clock. The caller must have an s-lock 993or x-lock on the block. 994@return value */ 995UNIV_INLINE 996ib_uint64_t 997buf_block_get_modify_clock( 998/*=======================*/ 999 buf_block_t* block) /*!< in: block */ 1000{ 1001#ifdef UNIV_SYNC_DEBUG 1002 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) 1003 || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE)); 1004#endif /* UNIV_SYNC_DEBUG */ 1005 1006 return(block->modify_clock); 1007} 1008 1009/*******************************************************************//** 1010Increments the bufferfix count. */ 1011UNIV_INLINE 1012void 1013buf_block_fix( 1014/*===========*/ 1015 buf_block_t* block) /*!< in/out: block to bufferfix */ 1016{ 1017#ifdef PAGE_ATOMIC_REF_COUNT 1018 os_atomic_increment_uint32(&block->page.buf_fix_count, 1); 1019#else 1020 ib_mutex_t* block_mutex = buf_page_get_mutex(&block->page); 1021 1022 mutex_enter(block_mutex); 1023 ++block->page.buf_fix_count; 1024 mutex_exit(block_mutex); 1025#endif /* PAGE_ATOMIC_REF_COUNT */ 1026} 1027 1028/*******************************************************************//** 1029Increments the bufferfix count. */ 1030UNIV_INLINE 1031void 1032buf_block_buf_fix_inc_func( 1033/*=======================*/ 1034#ifdef UNIV_SYNC_DEBUG 1035 const char* file, /*!< in: file name */ 1036 ulint line, /*!< in: line */ 1037#endif /* UNIV_SYNC_DEBUG */ 1038 buf_block_t* block) /*!< in/out: block to bufferfix */ 1039{ 1040#ifdef UNIV_SYNC_DEBUG 1041 ibool ret; 1042 1043 ret = rw_lock_s_lock_nowait(&(block->debug_latch), file, line); 1044 ut_a(ret); 1045#endif /* UNIV_SYNC_DEBUG */ 1046 1047#ifdef PAGE_ATOMIC_REF_COUNT 1048 os_atomic_increment_uint32(&block->page.buf_fix_count, 1); 1049#else 1050 ut_ad(mutex_own(&block->mutex)); 1051 1052 ++block->page.buf_fix_count; 1053#endif /* PAGE_ATOMIC_REF_COUNT */ 1054} 1055 1056/*******************************************************************//** 1057Decrements the bufferfix count. */ 1058UNIV_INLINE 1059void 1060buf_block_unfix( 1061/*============*/ 1062 buf_block_t* block) /*!< in/out: block to bufferunfix */ 1063{ 1064 ut_ad(block->page.buf_fix_count > 0); 1065 1066#ifdef PAGE_ATOMIC_REF_COUNT 1067 os_atomic_decrement_uint32(&block->page.buf_fix_count, 1); 1068#else 1069 ib_mutex_t* block_mutex = buf_page_get_mutex(&block->page); 1070 1071 mutex_enter(block_mutex); 1072 --block->page.buf_fix_count; 1073 mutex_exit(block_mutex); 1074#endif /* PAGE_ATOMIC_REF_COUNT */ 1075} 1076 1077/*******************************************************************//** 1078Decrements the bufferfix count. */ 1079UNIV_INLINE 1080void 1081buf_block_buf_fix_dec( 1082/*==================*/ 1083 buf_block_t* block) /*!< in/out: block to bufferunfix */ 1084{ 1085 ut_ad(block->page.buf_fix_count > 0); 1086 1087#ifdef PAGE_ATOMIC_REF_COUNT 1088 os_atomic_decrement_uint32(&block->page.buf_fix_count, 1); 1089#else 1090 mutex_enter(&block->mutex); 1091 --block->page.buf_fix_count; 1092 mutex_exit(&block->mutex); 1093#endif /* PAGE_ATOMIC_REF_COUNT */ 1094 1095#ifdef UNIV_SYNC_DEBUG 1096 rw_lock_s_unlock(&block->debug_latch); 1097#endif 1098} 1099 1100/******************************************************************//** 1101Returns the buffer pool instance given space and offset of page 1102@return buffer pool */ 1103UNIV_INLINE 1104buf_pool_t* 1105buf_pool_get( 1106/*==========*/ 1107 ulint space, /*!< in: space id */ 1108 ulint offset) /*!< in: offset of the page within space */ 1109{ 1110 ulint fold; 1111 ulint index; 1112 ulint ignored_offset; 1113 1114 ignored_offset = offset >> 6; /* 2log of BUF_READ_AHEAD_AREA (64)*/ 1115 fold = buf_page_address_fold(space, ignored_offset); 1116 index = fold % srv_buf_pool_instances; 1117 return(&buf_pool_ptr[index]); 1118} 1119 1120/******************************************************************//** 1121Returns the buffer pool instance given its array index 1122@return buffer pool */ 1123UNIV_INLINE 1124buf_pool_t* 1125buf_pool_from_array( 1126/*================*/ 1127 ulint index) /*!< in: array index to get 1128 buffer pool instance from */ 1129{ 1130 ut_ad(index < MAX_BUFFER_POOLS); 1131 ut_ad(index < srv_buf_pool_instances); 1132 return(&buf_pool_ptr[index]); 1133} 1134 1135/******************************************************************//** 1136Returns the control block of a file page, NULL if not found. 1137@return block, NULL if not found */ 1138UNIV_INLINE 1139buf_page_t* 1140buf_page_hash_get_low( 1141/*==================*/ 1142 buf_pool_t* buf_pool,/*!< buffer pool instance */ 1143 ulint space, /*!< in: space id */ 1144 ulint offset, /*!< in: offset of the page within space */ 1145 ulint fold) /*!< in: buf_page_address_fold(space, offset) */ 1146{ 1147 buf_page_t* bpage; 1148 1149#ifdef UNIV_SYNC_DEBUG 1150 ulint hash_fold; 1151 rw_lock_t* hash_lock; 1152 1153 hash_fold = buf_page_address_fold(space, offset); 1154 ut_ad(hash_fold == fold); 1155 1156 hash_lock = hash_get_lock(buf_pool->page_hash, fold); 1157 ut_ad(rw_lock_own(hash_lock, RW_LOCK_EX) 1158 || rw_lock_own(hash_lock, RW_LOCK_SHARED)); 1159#endif /* UNIV_SYNC_DEBUG */ 1160 1161 /* Look for the page in the hash table */ 1162 1163 HASH_SEARCH(hash, buf_pool->page_hash, fold, buf_page_t*, bpage, 1164 ut_ad(bpage->in_page_hash && !bpage->in_zip_hash 1165 && buf_page_in_file(bpage)), 1166 bpage->space == space && bpage->offset == offset); 1167 if (bpage) { 1168 ut_a(buf_page_in_file(bpage)); 1169 ut_ad(bpage->in_page_hash); 1170 ut_ad(!bpage->in_zip_hash); 1171 } 1172 1173 return(bpage); 1174} 1175 1176/******************************************************************//** 1177Returns the control block of a file page, NULL if not found. 1178If the block is found and lock is not NULL then the appropriate 1179page_hash lock is acquired in the specified lock mode. Otherwise, 1180mode value is ignored. It is up to the caller to release the 1181lock. If the block is found and the lock is NULL then the page_hash 1182lock is released by this function. 1183@return block, NULL if not found, or watch sentinel (if watch is true) */ 1184UNIV_INLINE 1185buf_page_t* 1186buf_page_hash_get_locked( 1187/*=====================*/ 1188 /*!< out: pointer to the bpage, 1189 or NULL; if NULL, hash_lock 1190 is also NULL. */ 1191 buf_pool_t* buf_pool, /*!< buffer pool instance */ 1192 ulint space, /*!< in: space id */ 1193 ulint offset, /*!< in: page number */ 1194 rw_lock_t** lock, /*!< in/out: lock of the page 1195 hash acquired if bpage is 1196 found. NULL otherwise. If NULL 1197 is passed then the hash_lock 1198 is released by this function */ 1199 ulint lock_mode, /*!< in: RW_LOCK_EX or 1200 RW_LOCK_SHARED. Ignored if 1201 lock == NULL */ 1202 bool watch) /*!< in: if true, return watch 1203 sentinel also. */ 1204{ 1205 buf_page_t* bpage = NULL; 1206 ulint fold; 1207 rw_lock_t* hash_lock; 1208 ulint mode = RW_LOCK_SHARED; 1209 1210 if (lock != NULL) { 1211 *lock = NULL; 1212 ut_ad(lock_mode == RW_LOCK_EX 1213 || lock_mode == RW_LOCK_SHARED); 1214 mode = lock_mode; 1215 } 1216 1217 fold = buf_page_address_fold(space, offset); 1218 hash_lock = hash_get_lock(buf_pool->page_hash, fold); 1219 1220#ifdef UNIV_SYNC_DEBUG 1221 ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX) 1222 && !rw_lock_own(hash_lock, RW_LOCK_SHARED)); 1223#endif /* UNIV_SYNC_DEBUG */ 1224 1225 if (mode == RW_LOCK_SHARED) { 1226 rw_lock_s_lock(hash_lock); 1227 } else { 1228 rw_lock_x_lock(hash_lock); 1229 } 1230 1231 bpage = buf_page_hash_get_low(buf_pool, space, offset, fold); 1232 1233 if (!bpage || buf_pool_watch_is_sentinel(buf_pool, bpage)) { 1234 if (!watch) { 1235 bpage = NULL; 1236 } 1237 goto unlock_and_exit; 1238 } 1239 1240 ut_ad(buf_page_in_file(bpage)); 1241 ut_ad(offset == bpage->offset); 1242 ut_ad(space == bpage->space); 1243 1244 if (lock == NULL) { 1245 /* The caller wants us to release the page_hash lock */ 1246 goto unlock_and_exit; 1247 } else { 1248 /* To be released by the caller */ 1249 *lock = hash_lock; 1250 goto exit; 1251 } 1252 1253unlock_and_exit: 1254 if (mode == RW_LOCK_SHARED) { 1255 rw_lock_s_unlock(hash_lock); 1256 } else { 1257 rw_lock_x_unlock(hash_lock); 1258 } 1259exit: 1260 return(bpage); 1261} 1262 1263/******************************************************************//** 1264Returns the control block of a file page, NULL if not found. 1265If the block is found and lock is not NULL then the appropriate 1266page_hash lock is acquired in the specified lock mode. Otherwise, 1267mode value is ignored. It is up to the caller to release the 1268lock. If the block is found and the lock is NULL then the page_hash 1269lock is released by this function. 1270@return block, NULL if not found */ 1271UNIV_INLINE 1272buf_block_t* 1273buf_block_hash_get_locked( 1274/*=====================*/ 1275 /*!< out: pointer to the bpage, 1276 or NULL; if NULL, hash_lock 1277 is also NULL. */ 1278 buf_pool_t* buf_pool, /*!< buffer pool instance */ 1279 ulint space, /*!< in: space id */ 1280 ulint offset, /*!< in: page number */ 1281 rw_lock_t** lock, /*!< in/out: lock of the page 1282 hash acquired if bpage is 1283 found. NULL otherwise. If NULL 1284 is passed then the hash_lock 1285 is released by this function */ 1286 ulint lock_mode) /*!< in: RW_LOCK_EX or 1287 RW_LOCK_SHARED. Ignored if 1288 lock == NULL */ 1289{ 1290 buf_page_t* bpage = buf_page_hash_get_locked(buf_pool, 1291 space, 1292 offset, 1293 lock, 1294 lock_mode); 1295 buf_block_t* block = buf_page_get_block(bpage); 1296 1297 if (block) { 1298 ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); 1299#ifdef UNIV_SYNC_DEBUG 1300 ut_ad(!lock || rw_lock_own(*lock, lock_mode)); 1301#endif /* UNIV_SYNC_DEBUG */ 1302 return(block); 1303 } else if (bpage) { 1304 /* It is not a block. Just a bpage */ 1305 ut_ad(buf_page_in_file(bpage)); 1306 1307 if (lock) { 1308 if (lock_mode == RW_LOCK_SHARED) { 1309 rw_lock_s_unlock(*lock); 1310 } else { 1311 rw_lock_x_unlock(*lock); 1312 } 1313 } 1314 *lock = NULL; 1315 return(NULL); 1316 } 1317 1318 ut_ad(!bpage); 1319 ut_ad(lock == NULL ||*lock == NULL); 1320 return(NULL); 1321} 1322 1323/********************************************************************//** 1324Returns TRUE if the page can be found in the buffer pool hash table. 1325 1326NOTE that it is possible that the page is not yet read from disk, 1327though. 1328 1329@return TRUE if found in the page hash table */ 1330UNIV_INLINE 1331ibool 1332buf_page_peek( 1333/*==========*/ 1334 ulint space, /*!< in: space id */ 1335 ulint offset) /*!< in: page number */ 1336{ 1337 buf_pool_t* buf_pool = buf_pool_get(space, offset); 1338 1339 return(buf_page_hash_get(buf_pool, space, offset) != NULL); 1340} 1341 1342/********************************************************************//** 1343Releases a compressed-only page acquired with buf_page_get_zip(). */ 1344UNIV_INLINE 1345void 1346buf_page_release_zip( 1347/*=================*/ 1348 buf_page_t* bpage) /*!< in: buffer block */ 1349{ 1350 buf_block_t* block; 1351 1352 block = (buf_block_t*) bpage; 1353 1354 switch (buf_page_get_state(bpage)) { 1355 case BUF_BLOCK_FILE_PAGE: 1356#ifdef UNIV_SYNC_DEBUG 1357 rw_lock_s_unlock(&block->debug_latch); 1358#endif /* UNUV_SYNC_DEBUG */ 1359 /* Fall through */ 1360 case BUF_BLOCK_ZIP_PAGE: 1361 case BUF_BLOCK_ZIP_DIRTY: 1362 buf_block_unfix(block); 1363 return; 1364 1365 case BUF_BLOCK_POOL_WATCH: 1366 case BUF_BLOCK_NOT_USED: 1367 case BUF_BLOCK_READY_FOR_USE: 1368 case BUF_BLOCK_MEMORY: 1369 case BUF_BLOCK_REMOVE_HASH: 1370 break; 1371 } 1372 1373 ut_error; 1374} 1375 1376/********************************************************************//** 1377Decrements the bufferfix count of a buffer control block and releases 1378a latch, if specified. */ 1379UNIV_INLINE 1380void 1381buf_page_release( 1382/*=============*/ 1383 buf_block_t* block, /*!< in: buffer block */ 1384 ulint rw_latch) /*!< in: RW_S_LATCH, RW_X_LATCH, 1385 RW_NO_LATCH */ 1386{ 1387 ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); 1388 1389#ifdef UNIV_SYNC_DEBUG 1390 rw_lock_s_unlock(&(block->debug_latch)); 1391#endif 1392 if (rw_latch == RW_S_LATCH) { 1393 rw_lock_s_unlock(&(block->lock)); 1394 } else if (rw_latch == RW_X_LATCH) { 1395 rw_lock_x_unlock(&(block->lock)); 1396 } 1397 1398 buf_block_unfix(block); 1399} 1400 1401#ifdef UNIV_SYNC_DEBUG 1402/*********************************************************************//** 1403Adds latch level info for the rw-lock protecting the buffer frame. This 1404should be called in the debug version after a successful latching of a 1405page if we know the latching order level of the acquired latch. */ 1406UNIV_INLINE 1407void 1408buf_block_dbg_add_level( 1409/*====================*/ 1410 buf_block_t* block, /*!< in: buffer page 1411 where we have acquired latch */ 1412 ulint level) /*!< in: latching order level */ 1413{ 1414 sync_thread_add_level(&block->lock, level, FALSE); 1415} 1416 1417#endif /* UNIV_SYNC_DEBUG */ 1418/********************************************************************//** 1419Acquire mutex on all buffer pool instances. */ 1420UNIV_INLINE 1421void 1422buf_pool_mutex_enter_all(void) 1423/*==========================*/ 1424{ 1425 ulint i; 1426 1427 for (i = 0; i < srv_buf_pool_instances; i++) { 1428 buf_pool_t* buf_pool; 1429 1430 buf_pool = buf_pool_from_array(i); 1431 buf_pool_mutex_enter(buf_pool); 1432 } 1433} 1434 1435/********************************************************************//** 1436Release mutex on all buffer pool instances. */ 1437UNIV_INLINE 1438void 1439buf_pool_mutex_exit_all(void) 1440/*=========================*/ 1441{ 1442 ulint i; 1443 1444 for (i = 0; i < srv_buf_pool_instances; i++) { 1445 buf_pool_t* buf_pool; 1446 1447 buf_pool = buf_pool_from_array(i); 1448 buf_pool_mutex_exit(buf_pool); 1449 } 1450} 1451/*********************************************************************//** 1452Get the nth chunk's buffer block in the specified buffer pool. 1453@return the nth chunk's buffer block. */ 1454UNIV_INLINE 1455buf_block_t* 1456buf_get_nth_chunk_block( 1457/*====================*/ 1458 const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ 1459 ulint n, /*!< in: nth chunk in the buffer pool */ 1460 ulint* chunk_size) /*!< in: chunk size */ 1461{ 1462 const buf_chunk_t* chunk; 1463 1464 chunk = buf_pool->chunks + n; 1465 *chunk_size = chunk->size; 1466 return(chunk->blocks); 1467} 1468#endif /* !UNIV_HOTBACKUP */ 1469