You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1085 lines
28 KiB

20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
branches/zip: Improve the LRU algorithm with a separate unzip_LRU list of blocks that contains uncompressed and compressed frames. This patch was designed by Heikki and Inaam, implemented by Inaam, and refined and reviewed by Marko and Sunny. buf_buddy_n_frames, buf_buddy_min_n_frames, buf_buddy_max_n_frames: Remove. buf_page_belongs_to_unzip_LRU(): New predicate: bpage->zip.data && buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE. buf_pool_t, buf_block_t: Add the linked list unzip_LRU. A block in the regular LRU list is in unzip_LRU iff buf_page_belongs_to_unzip_LRU() holds. buf_LRU_free_block(): Add a third return value to refine the case "cannot free the block". buf_LRU_search_and_free_block(): Update the documentation to reflect the implementation. buf_LRU_stat_t, buf_LRU_stat_cur, buf_LRU_stat_sum, buf_LRU_stat_arr[]: Statistics for the unzip_LRU algorithm. buf_LRU_stat_update(): New function: Update the statistics. Called once per second by srv_error_monitor_thread(). buf_LRU_validate(): Validate the unzip_LRU list as well. buf_LRU_evict_from_unzip_LRU(): New predicate: Use the unzip_LRU before falling back to the regular LRU? buf_LRU_free_from_unzip_LRU_list(), buf_LRU_free_from_common_LRU_list(): Subfunctions of buf_LRU_search_and_free_block(). buf_LRU_search_and_free_block(): Reimplement. Try to evict an uncompressed page from the unzip_LRU list before falling back to evicting an entire block from the common LRU list. buf_unzip_LRU_remove_block_if_needed(): New function. buf_unzip_LRU_add_block(): New function: Add a block to the unzip_LRU list.
18 years ago
branches/zip: Fix most MSVC (Windows) compilation warnings. lock_get_table(), locks_row_eq_lock(), buf_page_get_mutex(): Add return after ut_error. On Windows, ut_error is not declared as "noreturn". Add explicit type casts when assigning ulint to byte to get rid of "possible loss of precision" warnings. struct i_s_table_cache_struct: Declare rows_used, rows_allocd as ulint instead of ullint. 32 bits should be enough. fill_innodb_trx_from_cache(), i_s_zip_fill_low(): Cast 64-bit unsigned integers to longlong when calling Field::store(longlong, bool is_unsigned). Otherwise, the compiler would implicitly convert them to double and invoke Field::store(double) instead. recv_truncate_group(), recv_copy_group(), recv_calc_lsn_on_data_add(): Cast ib_uint64_t expressions to ulint to get rid of "possible loss of precision" warnings. (There should not be any loss of precision in these cases.) log_close(), log_checkpoint_margin(): Declare some variables as ib_uint64_t instead of ulint, so that there won't be any potential loss of precision. mach_write_ull(): Cast the second argument of mach_write_to_4() to ulint. OS_FILE_FROM_FD(): Cast the return value of _get_osfhandle() to HANDLE. row_merge_dict_table_get_index(): Cast the parameter of mem_free() to (void*) in order to get rid of the bogus MSVC warning C4090, which has been reported as MSVC bug 101661: <http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101661> row_mysql_read_blob_ref(): To get rid of a bogus MSVC warning C4090, drop a const qualifier.
18 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
  1. /******************************************************
  2. The database buffer buf_pool
  3. (c) 1995 Innobase Oy
  4. Created 11/5/1995 Heikki Tuuri
  5. *******************************************************/
  6. /***********************************************************************
  7. # Copyright (c) 2008, Google Inc.
  8. # All rights reserved.
  9. #
  10. # Redistribution and use in source and binary forms, with or without
  11. # modification, are permitted provided that the following conditions
  12. # are met:
  13. # * Redistributions of source code must retain the above copyright
  14. # notice, this list of conditions and the following disclaimer.
  15. # * Redistributions in binary form must reproduce the above
  16. # copyright notice, this list of conditions and the following
  17. # disclaimer in the documentation and/or other materials
  18. # provided with the distribution.
  19. # * Neither the name of the Google Inc. nor the names of its
  20. # contributors may be used to endorse or promote products
  21. # derived from this software without specific prior written
  22. # permission.
  23. #
  24. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  27. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  28. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  29. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  30. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  31. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  32. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  33. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  34. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. #
  36. # Note, the BSD license applies to the new code. The old code is GPL.
  37. ***********************************************************************/
  38. #include "buf0flu.h"
  39. #include "buf0lru.h"
  40. #include "buf0rea.h"
  41. #include "mtr0mtr.h"
  42. /************************************************************************
  43. Reads the freed_page_clock of a buffer block. */
  44. UNIV_INLINE
  45. ulint
  46. buf_page_get_freed_page_clock(
  47. /*==========================*/
  48. /* out: freed_page_clock */
  49. const buf_page_t* bpage) /* in: block */
  50. {
  51. /* This is sometimes read without holding buf_pool_mutex. */
  52. return(bpage->freed_page_clock);
  53. }
  54. /************************************************************************
  55. Reads the freed_page_clock of a buffer block. */
  56. UNIV_INLINE
  57. ulint
  58. buf_block_get_freed_page_clock(
  59. /*===========================*/
  60. /* out: freed_page_clock */
  61. const buf_block_t* block) /* in: block */
  62. {
  63. return(buf_page_get_freed_page_clock(&block->page));
  64. }
  65. /************************************************************************
  66. Recommends a move of a block to the start of the LRU list if there is danger
  67. of dropping from the buffer pool. NOTE: does not reserve the buffer pool
  68. mutex. */
  69. UNIV_INLINE
  70. ibool
  71. buf_page_peek_if_too_old(
  72. /*=====================*/
  73. /* out: TRUE if should be made
  74. younger */
  75. const buf_page_t* bpage) /* in: block to make younger */
  76. {
  77. return(buf_pool->freed_page_clock
  78. >= buf_page_get_freed_page_clock(bpage)
  79. + 1 + (buf_pool->curr_size / 4));
  80. }
  81. /*************************************************************************
  82. Gets the current size of buffer buf_pool in bytes. */
  83. UNIV_INLINE
  84. ulint
  85. buf_pool_get_curr_size(void)
  86. /*========================*/
  87. /* out: size in bytes */
  88. {
  89. return(buf_pool->curr_size * UNIV_PAGE_SIZE);
  90. }
  91. /************************************************************************
  92. Gets the smallest oldest_modification lsn for any page in the pool. Returns
  93. zero if all modified pages have been flushed to disk. */
  94. UNIV_INLINE
  95. ib_uint64_t
  96. buf_pool_get_oldest_modification(void)
  97. /*==================================*/
  98. /* out: oldest modification in pool,
  99. zero if none */
  100. {
  101. buf_page_t* bpage;
  102. ib_uint64_t lsn;
  103. buf_pool_mutex_enter();
  104. bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
  105. if (bpage == NULL) {
  106. lsn = 0;
  107. } else {
  108. ut_ad(bpage->in_flush_list);
  109. lsn = bpage->oldest_modification;
  110. }
  111. buf_pool_mutex_exit();
  112. /* The returned answer may be out of date: the flush_list can
  113. change after the mutex has been released. */
  114. return(lsn);
  115. }
  116. /***********************************************************************
  117. Increments the buf_pool clock by one and returns its new value. Remember
  118. that in the 32 bit version the clock wraps around at 4 billion! */
  119. UNIV_INLINE
  120. ulint
  121. buf_pool_clock_tic(void)
  122. /*====================*/
  123. /* out: new clock value */
  124. {
  125. ut_ad(buf_pool_mutex_own());
  126. buf_pool->ulint_clock++;
  127. return(buf_pool->ulint_clock);
  128. }
  129. /*************************************************************************
  130. Gets the state of a block. */
  131. UNIV_INLINE
  132. enum buf_page_state
  133. buf_page_get_state(
  134. /*===============*/
  135. /* out: state */
  136. const buf_page_t* bpage) /* in: pointer to the control block */
  137. {
  138. enum buf_page_state state = (enum buf_page_state) bpage->state;
  139. #ifdef UNIV_DEBUG
  140. switch (state) {
  141. case BUF_BLOCK_ZIP_FREE:
  142. case BUF_BLOCK_ZIP_PAGE:
  143. case BUF_BLOCK_ZIP_DIRTY:
  144. case BUF_BLOCK_NOT_USED:
  145. case BUF_BLOCK_READY_FOR_USE:
  146. case BUF_BLOCK_FILE_PAGE:
  147. case BUF_BLOCK_MEMORY:
  148. case BUF_BLOCK_REMOVE_HASH:
  149. break;
  150. default:
  151. ut_error;
  152. }
  153. #endif /* UNIV_DEBUG */
  154. return(state);
  155. }
  156. /*************************************************************************
  157. Gets the state of a block. */
  158. UNIV_INLINE
  159. enum buf_page_state
  160. buf_block_get_state(
  161. /*================*/
  162. /* out: state */
  163. const buf_block_t* block) /* in: pointer to the control block */
  164. {
  165. return(buf_page_get_state(&block->page));
  166. }
  167. /*************************************************************************
  168. Sets the state of a block. */
  169. UNIV_INLINE
  170. void
  171. buf_page_set_state(
  172. /*===============*/
  173. buf_page_t* bpage, /* in/out: pointer to control block */
  174. enum buf_page_state state) /* in: state */
  175. {
  176. #ifdef UNIV_DEBUG
  177. enum buf_page_state old_state = buf_page_get_state(bpage);
  178. switch (old_state) {
  179. case BUF_BLOCK_ZIP_FREE:
  180. ut_error;
  181. break;
  182. case BUF_BLOCK_ZIP_PAGE:
  183. ut_a(state == BUF_BLOCK_ZIP_DIRTY);
  184. break;
  185. case BUF_BLOCK_ZIP_DIRTY:
  186. ut_a(state == BUF_BLOCK_ZIP_PAGE);
  187. break;
  188. case BUF_BLOCK_NOT_USED:
  189. ut_a(state == BUF_BLOCK_READY_FOR_USE);
  190. break;
  191. case BUF_BLOCK_READY_FOR_USE:
  192. ut_a(state == BUF_BLOCK_MEMORY
  193. || state == BUF_BLOCK_FILE_PAGE
  194. || state == BUF_BLOCK_NOT_USED);
  195. break;
  196. case BUF_BLOCK_MEMORY:
  197. ut_a(state == BUF_BLOCK_NOT_USED);
  198. break;
  199. case BUF_BLOCK_FILE_PAGE:
  200. ut_a(state == BUF_BLOCK_NOT_USED
  201. || state == BUF_BLOCK_REMOVE_HASH);
  202. break;
  203. case BUF_BLOCK_REMOVE_HASH:
  204. ut_a(state == BUF_BLOCK_MEMORY);
  205. break;
  206. }
  207. #endif /* UNIV_DEBUG */
  208. bpage->state = state;
  209. ut_ad(buf_page_get_state(bpage) == state);
  210. }
  211. /*************************************************************************
  212. Sets the state of a block. */
  213. UNIV_INLINE
  214. void
  215. buf_block_set_state(
  216. /*================*/
  217. buf_block_t* block, /* in/out: pointer to control block */
  218. enum buf_page_state state) /* in: state */
  219. {
  220. buf_page_set_state(&block->page, state);
  221. }
  222. /*************************************************************************
  223. Determines if a block is mapped to a tablespace. */
  224. UNIV_INLINE
  225. ibool
  226. buf_page_in_file(
  227. /*=============*/
  228. /* out: TRUE if mapped */
  229. const buf_page_t* bpage) /* in: pointer to control block */
  230. {
  231. switch (buf_page_get_state(bpage)) {
  232. case BUF_BLOCK_ZIP_FREE:
  233. /* This is a free page in buf_pool->zip_free[].
  234. Such pages should only be accessed by the buddy allocator. */
  235. ut_error;
  236. break;
  237. case BUF_BLOCK_ZIP_PAGE:
  238. case BUF_BLOCK_ZIP_DIRTY:
  239. case BUF_BLOCK_FILE_PAGE:
  240. return(TRUE);
  241. case BUF_BLOCK_NOT_USED:
  242. case BUF_BLOCK_READY_FOR_USE:
  243. case BUF_BLOCK_MEMORY:
  244. case BUF_BLOCK_REMOVE_HASH:
  245. break;
  246. }
  247. return(FALSE);
  248. }
  249. /*************************************************************************
  250. Determines if a block should be on unzip_LRU list. */
  251. UNIV_INLINE
  252. ibool
  253. buf_page_belongs_to_unzip_LRU(
  254. /*==========================*/
  255. /* out: TRUE if block belongs
  256. to unzip_LRU */
  257. const buf_page_t* bpage) /* in: pointer to control block */
  258. {
  259. ut_ad(buf_page_in_file(bpage));
  260. return(bpage->zip.data
  261. && buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
  262. }
  263. /*************************************************************************
  264. Determine the approximate LRU list position of a block. */
  265. UNIV_INLINE
  266. ulint
  267. buf_page_get_LRU_position(
  268. /*======================*/
  269. /* out: LRU list position */
  270. const buf_page_t* bpage) /* in: control block */
  271. {
  272. ut_ad(buf_page_in_file(bpage));
  273. ut_ad(buf_pool_mutex_own());
  274. return(bpage->LRU_position);
  275. }
  276. /*************************************************************************
  277. Gets the mutex of a block. */
  278. UNIV_INLINE
  279. mutex_t*
  280. buf_page_get_mutex(
  281. /*===============*/
  282. /* out: pointer to mutex
  283. protecting bpage */
  284. const buf_page_t* bpage) /* in: pointer to control block */
  285. {
  286. switch (buf_page_get_state(bpage)) {
  287. case BUF_BLOCK_ZIP_FREE:
  288. ut_error;
  289. return(NULL);
  290. case BUF_BLOCK_ZIP_PAGE:
  291. case BUF_BLOCK_ZIP_DIRTY:
  292. return(&buf_pool_zip_mutex);
  293. default:
  294. return(&((buf_block_t*) bpage)->mutex);
  295. }
  296. }
  297. /*************************************************************************
  298. Get the flush type of a page. */
  299. UNIV_INLINE
  300. enum buf_flush
  301. buf_page_get_flush_type(
  302. /*====================*/
  303. /* out: flush type */
  304. const buf_page_t* bpage) /* in: buffer page */
  305. {
  306. enum buf_flush flush_type = (enum buf_flush) bpage->flush_type;
  307. #ifdef UNIV_DEBUG
  308. switch (flush_type) {
  309. case BUF_FLUSH_LRU:
  310. case BUF_FLUSH_SINGLE_PAGE:
  311. case BUF_FLUSH_LIST:
  312. return(flush_type);
  313. case BUF_FLUSH_N_TYPES:
  314. break;
  315. }
  316. ut_error;
  317. #endif /* UNIV_DEBUG */
  318. return(flush_type);
  319. }
  320. /*************************************************************************
  321. Set the flush type of a page. */
  322. UNIV_INLINE
  323. void
  324. buf_page_set_flush_type(
  325. /*====================*/
  326. buf_page_t* bpage, /* in: buffer page */
  327. enum buf_flush flush_type) /* in: flush type */
  328. {
  329. bpage->flush_type = flush_type;
  330. ut_ad(buf_page_get_flush_type(bpage) == flush_type);
  331. }
  332. /*************************************************************************
  333. Map a block to a file page. */
  334. UNIV_INLINE
  335. void
  336. buf_block_set_file_page(
  337. /*====================*/
  338. buf_block_t* block, /* in/out: pointer to control block */
  339. ulint space, /* in: tablespace id */
  340. ulint page_no)/* in: page number */
  341. {
  342. buf_block_set_state(block, BUF_BLOCK_FILE_PAGE);
  343. block->page.space = space;
  344. block->page.offset = page_no;
  345. }
  346. /*************************************************************************
  347. Gets the io_fix state of a block. */
  348. UNIV_INLINE
  349. enum buf_io_fix
  350. buf_page_get_io_fix(
  351. /*================*/
  352. /* out: io_fix state */
  353. const buf_page_t* bpage) /* in: pointer to the control block */
  354. {
  355. enum buf_io_fix io_fix = (enum buf_io_fix) bpage->io_fix;
  356. #ifdef UNIV_DEBUG
  357. switch (io_fix) {
  358. case BUF_IO_NONE:
  359. case BUF_IO_READ:
  360. case BUF_IO_WRITE:
  361. return(io_fix);
  362. }
  363. ut_error;
  364. #endif /* UNIV_DEBUG */
  365. return(io_fix);
  366. }
  367. /*************************************************************************
  368. Gets the io_fix state of a block. */
  369. UNIV_INLINE
  370. enum buf_io_fix
  371. buf_block_get_io_fix(
  372. /*================*/
  373. /* out: io_fix state */
  374. const buf_block_t* block) /* in: pointer to the control block */
  375. {
  376. return(buf_page_get_io_fix(&block->page));
  377. }
  378. /*************************************************************************
  379. Sets the io_fix state of a block. */
  380. UNIV_INLINE
  381. void
  382. buf_page_set_io_fix(
  383. /*================*/
  384. buf_page_t* bpage, /* in/out: control block */
  385. enum buf_io_fix io_fix) /* in: io_fix state */
  386. {
  387. ut_ad(buf_pool_mutex_own());
  388. ut_ad(mutex_own(buf_page_get_mutex(bpage)));
  389. bpage->io_fix = io_fix;
  390. ut_ad(buf_page_get_io_fix(bpage) == io_fix);
  391. }
  392. /*************************************************************************
  393. Sets the io_fix state of a block. */
  394. UNIV_INLINE
  395. void
  396. buf_block_set_io_fix(
  397. /*=================*/
  398. buf_block_t* block, /* in/out: control block */
  399. enum buf_io_fix io_fix) /* in: io_fix state */
  400. {
  401. buf_page_set_io_fix(&block->page, io_fix);
  402. }
  403. /************************************************************************
  404. Determine if a buffer block can be relocated in memory. The block
  405. can be dirty, but it must not be I/O-fixed or bufferfixed. */
  406. UNIV_INLINE
  407. ibool
  408. buf_page_can_relocate(
  409. /*==================*/
  410. const buf_page_t* bpage) /* control block being relocated */
  411. {
  412. ut_ad(buf_pool_mutex_own());
  413. ut_ad(mutex_own(buf_page_get_mutex(bpage)));
  414. ut_ad(buf_page_in_file(bpage));
  415. ut_ad(bpage->in_LRU_list);
  416. return(buf_page_get_io_fix(bpage) == BUF_IO_NONE
  417. && bpage->buf_fix_count == 0);
  418. }
  419. /*************************************************************************
  420. Determine if a block has been flagged old. */
  421. UNIV_INLINE
  422. ibool
  423. buf_page_is_old(
  424. /*============*/
  425. /* out: TRUE if old */
  426. const buf_page_t* bpage) /* in: control block */
  427. {
  428. ut_ad(buf_page_in_file(bpage));
  429. ut_ad(buf_pool_mutex_own());
  430. return(bpage->old);
  431. }
  432. /*************************************************************************
  433. Flag a block old. */
  434. UNIV_INLINE
  435. void
  436. buf_page_set_old(
  437. /*=============*/
  438. buf_page_t* bpage, /* in/out: control block */
  439. ibool old) /* in: old */
  440. {
  441. ut_a(buf_page_in_file(bpage));
  442. ut_ad(buf_pool_mutex_own());
  443. ut_ad(bpage->in_LRU_list);
  444. #ifdef UNIV_LRU_DEBUG
  445. if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)
  446. && UT_LIST_GET_PREV(LRU, bpage)->old
  447. == UT_LIST_GET_NEXT(LRU, bpage)->old) {
  448. ut_a(UT_LIST_GET_PREV(LRU, bpage)->old == old);
  449. }
  450. #endif /* UNIV_LRU_DEBUG */
  451. bpage->old = old;
  452. }
  453. /*************************************************************************
  454. Determine if a block has been accessed in the buffer pool. */
  455. UNIV_INLINE
  456. ibool
  457. buf_page_is_accessed(
  458. /*=================*/
  459. /* out: TRUE if accessed */
  460. const buf_page_t* bpage) /* in: control block */
  461. {
  462. ut_ad(buf_page_in_file(bpage));
  463. return(bpage->accessed);
  464. }
  465. /*************************************************************************
  466. Flag a block accessed. */
  467. UNIV_INLINE
  468. void
  469. buf_page_set_accessed(
  470. /*==================*/
  471. buf_page_t* bpage, /* in/out: control block */
  472. ibool accessed) /* in: accessed */
  473. {
  474. ut_a(buf_page_in_file(bpage));
  475. ut_ad(mutex_own(buf_page_get_mutex(bpage)));
  476. bpage->accessed = accessed;
  477. }
  478. /*************************************************************************
  479. Gets the buf_block_t handle of a buffered file block if an uncompressed
  480. page frame exists, or NULL. */
  481. UNIV_INLINE
  482. buf_block_t*
  483. buf_page_get_block(
  484. /*===============*/
  485. /* out: control block, or NULL */
  486. buf_page_t* bpage) /* in: control block, or NULL */
  487. {
  488. if (UNIV_LIKELY(bpage != NULL)) {
  489. ut_ad(buf_page_in_file(bpage));
  490. if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) {
  491. return((buf_block_t*) bpage);
  492. }
  493. }
  494. return(NULL);
  495. }
  496. #ifdef UNIV_DEBUG
  497. /*************************************************************************
  498. Gets a pointer to the memory frame of a block. */
  499. UNIV_INLINE
  500. buf_frame_t*
  501. buf_block_get_frame(
  502. /*================*/
  503. /* out: pointer to the frame */
  504. const buf_block_t* block) /* in: pointer to the control block */
  505. {
  506. ut_ad(block);
  507. switch (buf_block_get_state(block)) {
  508. case BUF_BLOCK_ZIP_FREE:
  509. case BUF_BLOCK_ZIP_PAGE:
  510. case BUF_BLOCK_ZIP_DIRTY:
  511. case BUF_BLOCK_NOT_USED:
  512. ut_error;
  513. break;
  514. case BUF_BLOCK_FILE_PAGE:
  515. ut_a(block->page.buf_fix_count > 0);
  516. /* fall through */
  517. case BUF_BLOCK_READY_FOR_USE:
  518. case BUF_BLOCK_MEMORY:
  519. case BUF_BLOCK_REMOVE_HASH:
  520. goto ok;
  521. }
  522. ut_error;
  523. ok:
  524. return((buf_frame_t*) block->frame);
  525. }
  526. #endif /* UNIV_DEBUG */
  527. /*************************************************************************
  528. Gets the space id of a block. */
  529. UNIV_INLINE
  530. ulint
  531. buf_page_get_space(
  532. /*===============*/
  533. /* out: space id */
  534. const buf_page_t* bpage) /* in: pointer to the control block */
  535. {
  536. ut_ad(bpage);
  537. ut_a(buf_page_in_file(bpage));
  538. return(bpage->space);
  539. }
  540. /*************************************************************************
  541. Gets the space id of a block. */
  542. UNIV_INLINE
  543. ulint
  544. buf_block_get_space(
  545. /*================*/
  546. /* out: space id */
  547. const buf_block_t* block) /* in: pointer to the control block */
  548. {
  549. ut_ad(block);
  550. ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
  551. return(block->page.space);
  552. }
  553. /*************************************************************************
  554. Gets the page number of a block. */
  555. UNIV_INLINE
  556. ulint
  557. buf_page_get_page_no(
  558. /*=================*/
  559. /* out: page number */
  560. const buf_page_t* bpage) /* in: pointer to the control block */
  561. {
  562. ut_ad(bpage);
  563. ut_a(buf_page_in_file(bpage));
  564. return(bpage->offset);
  565. }
  566. /*************************************************************************
  567. Gets the page number of a block. */
  568. UNIV_INLINE
  569. ulint
  570. buf_block_get_page_no(
  571. /*==================*/
  572. /* out: page number */
  573. const buf_block_t* block) /* in: pointer to the control block */
  574. {
  575. ut_ad(block);
  576. ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
  577. return(block->page.offset);
  578. }
  579. /*************************************************************************
  580. Gets the compressed page size of a block. */
  581. UNIV_INLINE
  582. ulint
  583. buf_page_get_zip_size(
  584. /*==================*/
  585. /* out: compressed page size, or 0 */
  586. const buf_page_t* bpage) /* in: pointer to the control block */
  587. {
  588. return(bpage->zip.ssize ? 512 << bpage->zip.ssize : 0);
  589. }
  590. /*************************************************************************
  591. Gets the compressed page size of a block. */
  592. UNIV_INLINE
  593. ulint
  594. buf_block_get_zip_size(
  595. /*===================*/
  596. /* out: compressed page size, or 0 */
  597. const buf_block_t* block) /* in: pointer to the control block */
  598. {
  599. return(block->page.zip.ssize ? 512 << block->page.zip.ssize : 0);
  600. }
  601. #if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
  602. /*************************************************************************
  603. Gets the compressed page descriptor corresponding to an uncompressed page
  604. if applicable. */
  605. UNIV_INLINE
  606. const page_zip_des_t*
  607. buf_frame_get_page_zip(
  608. /*===================*/
  609. /* out: compressed page descriptor, or NULL */
  610. const byte* ptr) /* in: pointer to the page */
  611. {
  612. return(buf_block_get_page_zip(buf_block_align(ptr)));
  613. }
  614. #endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
  615. /**************************************************************************
  616. Gets the space id, page offset, and byte offset within page of a
  617. pointer pointing to a buffer frame containing a file page. */
  618. UNIV_INLINE
  619. void
  620. buf_ptr_get_fsp_addr(
  621. /*=================*/
  622. const void* ptr, /* in: pointer to a buffer frame */
  623. ulint* space, /* out: space id */
  624. fil_addr_t* addr) /* out: page offset and byte offset */
  625. {
  626. const page_t* page = (const page_t*) ut_align_down(ptr,
  627. UNIV_PAGE_SIZE);
  628. *space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
  629. addr->page = mach_read_from_4(page + FIL_PAGE_OFFSET);
  630. addr->boffset = ut_align_offset(ptr, UNIV_PAGE_SIZE);
  631. }
  632. /**************************************************************************
  633. Gets the hash value of the page the pointer is pointing to. This can be used
  634. in searches in the lock hash table. */
  635. UNIV_INLINE
  636. ulint
  637. buf_block_get_lock_hash_val(
  638. /*========================*/
  639. /* out: lock hash value */
  640. const buf_block_t* block) /* in: block */
  641. {
  642. return(block->lock_hash_val);
  643. }
  644. /************************************************************************
  645. Allocates a buffer block. */
  646. UNIV_INLINE
  647. buf_block_t*
  648. buf_block_alloc(
  649. /*============*/
  650. /* out, own: the allocated block,
  651. in state BUF_BLOCK_MEMORY */
  652. ulint zip_size) /* in: compressed page size in bytes,
  653. or 0 if uncompressed tablespace */
  654. {
  655. buf_block_t* block;
  656. block = buf_LRU_get_free_block(zip_size);
  657. buf_block_set_state(block, BUF_BLOCK_MEMORY);
  658. return(block);
  659. }
  660. /************************************************************************
  661. Frees a buffer block which does not contain a file page. */
  662. UNIV_INLINE
  663. void
  664. buf_block_free(
  665. /*===========*/
  666. buf_block_t* block) /* in, own: block to be freed */
  667. {
  668. buf_pool_mutex_enter();
  669. mutex_enter(&block->mutex);
  670. ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
  671. buf_LRU_block_free_non_file_page(block);
  672. mutex_exit(&block->mutex);
  673. buf_pool_mutex_exit();
  674. }
  675. /*************************************************************************
  676. Copies contents of a buffer frame to a given buffer. */
  677. UNIV_INLINE
  678. byte*
  679. buf_frame_copy(
  680. /*===========*/
  681. /* out: buf */
  682. byte* buf, /* in: buffer to copy to */
  683. const buf_frame_t* frame) /* in: buffer frame */
  684. {
  685. ut_ad(buf && frame);
  686. ut_memcpy(buf, frame, UNIV_PAGE_SIZE);
  687. return(buf);
  688. }
  689. /************************************************************************
  690. Calculates a folded value of a file page address to use in the page hash
  691. table. */
  692. UNIV_INLINE
  693. ulint
  694. buf_page_address_fold(
  695. /*==================*/
  696. /* out: the folded value */
  697. ulint space, /* in: space id */
  698. ulint offset) /* in: offset of the page within space */
  699. {
  700. return((space << 20) + space + offset);
  701. }
  702. /************************************************************************
  703. This function is used to get info if there is an io operation
  704. going on on a buffer page. */
  705. UNIV_INLINE
  706. ibool
  707. buf_page_io_query(
  708. /*==============*/
  709. /* out: TRUE if io going on */
  710. buf_page_t* bpage) /* in: buf_pool block, must be bufferfixed */
  711. {
  712. ibool io_fixed;
  713. buf_pool_mutex_enter();
  714. ut_ad(buf_page_in_file(bpage));
  715. ut_ad(bpage->buf_fix_count > 0);
  716. io_fixed = buf_page_get_io_fix(bpage) != BUF_IO_NONE;
  717. buf_pool_mutex_exit();
  718. return(io_fixed);
  719. }
  720. /************************************************************************
  721. Gets the youngest modification log sequence number for a frame.
  722. Returns zero if not file page or no modification occurred yet. */
  723. UNIV_INLINE
  724. ib_uint64_t
  725. buf_page_get_newest_modification(
  726. /*=============================*/
  727. /* out: newest modification to page */
  728. const buf_page_t* bpage) /* in: block containing the
  729. page frame */
  730. {
  731. ib_uint64_t lsn;
  732. mutex_t* block_mutex = buf_page_get_mutex(bpage);
  733. mutex_enter(block_mutex);
  734. if (buf_page_in_file(bpage)) {
  735. lsn = bpage->newest_modification;
  736. } else {
  737. lsn = 0;
  738. }
  739. mutex_exit(block_mutex);
  740. return(lsn);
  741. }
  742. /************************************************************************
  743. Increments the modify clock of a frame by 1. The caller must (1) own the
  744. buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
  745. on the block. */
  746. UNIV_INLINE
  747. void
  748. buf_block_modify_clock_inc(
  749. /*=======================*/
  750. buf_block_t* block) /* in: block */
  751. {
  752. #ifdef UNIV_SYNC_DEBUG
  753. ut_ad((buf_pool_mutex_own()
  754. && (block->page.buf_fix_count == 0))
  755. || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
  756. #endif /* UNIV_SYNC_DEBUG */
  757. block->modify_clock++;
  758. }
  759. /************************************************************************
  760. Returns the value of the modify clock. The caller must have an s-lock
  761. or x-lock on the block. */
  762. UNIV_INLINE
  763. ib_uint64_t
  764. buf_block_get_modify_clock(
  765. /*=======================*/
  766. /* out: value */
  767. buf_block_t* block) /* in: block */
  768. {
  769. #ifdef UNIV_SYNC_DEBUG
  770. ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
  771. || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
  772. #endif /* UNIV_SYNC_DEBUG */
  773. return(block->modify_clock);
  774. }
  775. /***********************************************************************
  776. Increments the bufferfix count. */
  777. UNIV_INLINE
  778. void
  779. buf_block_buf_fix_inc_func(
  780. /*=======================*/
  781. #ifdef UNIV_SYNC_DEBUG
  782. const char* file, /* in: file name */
  783. ulint line, /* in: line */
  784. #endif /* UNIV_SYNC_DEBUG */
  785. buf_block_t* block) /* in: block to bufferfix */
  786. {
  787. #ifdef UNIV_SYNC_DEBUG
  788. ibool ret;
  789. ret = rw_lock_s_lock_nowait(&(block->debug_latch), file, line);
  790. ut_a(ret);
  791. #endif /* UNIV_SYNC_DEBUG */
  792. ut_ad(mutex_own(&block->mutex));
  793. block->page.buf_fix_count++;
  794. }
  795. #ifdef UNIV_SYNC_DEBUG
  796. # define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
  797. #else /* UNIV_SYNC_DEBUG */
  798. # define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
  799. #endif /* UNIV_SYNC_DEBUG */
  800. /***********************************************************************
  801. Decrements the bufferfix count. */
  802. UNIV_INLINE
  803. void
  804. buf_block_buf_fix_dec(
  805. /*==================*/
  806. buf_block_t* block) /* in: block to bufferunfix */
  807. {
  808. ut_ad(mutex_own(&block->mutex));
  809. block->page.buf_fix_count--;
  810. #ifdef UNIV_SYNC_DEBUG
  811. rw_lock_s_unlock(&block->debug_latch);
  812. #endif
  813. }
  814. /**********************************************************************
  815. Returns the control block of a file page, NULL if not found. */
  816. UNIV_INLINE
  817. buf_page_t*
  818. buf_page_hash_get(
  819. /*==============*/
  820. /* out: block, NULL if not found */
  821. ulint space, /* in: space id */
  822. ulint offset) /* in: offset of the page within space */
  823. {
  824. buf_page_t* bpage;
  825. ulint fold;
  826. ut_ad(buf_pool);
  827. ut_ad(buf_pool_mutex_own());
  828. /* Look for the page in the hash table */
  829. fold = buf_page_address_fold(space, offset);
  830. HASH_SEARCH(hash, buf_pool->page_hash, fold, buf_page_t*, bpage,
  831. ut_ad(bpage->in_page_hash && !bpage->in_zip_hash
  832. && buf_page_in_file(bpage)),
  833. bpage->space == space && bpage->offset == offset);
  834. if (bpage) {
  835. ut_a(buf_page_in_file(bpage));
  836. ut_ad(bpage->in_page_hash);
  837. ut_ad(!bpage->in_zip_hash);
  838. UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
  839. }
  840. return(bpage);
  841. }
  842. /**********************************************************************
  843. Returns the control block of a file page, NULL if not found
  844. or an uncompressed page frame does not exist. */
  845. UNIV_INLINE
  846. buf_block_t*
  847. buf_block_hash_get(
  848. /*===============*/
  849. /* out: block, NULL if not found */
  850. ulint space, /* in: space id */
  851. ulint offset) /* in: offset of the page within space */
  852. {
  853. return(buf_page_get_block(buf_page_hash_get(space, offset)));
  854. }
  855. /************************************************************************
  856. Returns TRUE if the page can be found in the buffer pool hash table. NOTE
  857. that it is possible that the page is not yet read from disk, though. */
  858. UNIV_INLINE
  859. ibool
  860. buf_page_peek(
  861. /*==========*/
  862. /* out: TRUE if found from page hash table,
  863. NOTE that the page is not necessarily yet read
  864. from disk! */
  865. ulint space, /* in: space id */
  866. ulint offset) /* in: page number */
  867. {
  868. const buf_page_t* bpage;
  869. buf_pool_mutex_enter();
  870. bpage = buf_page_hash_get(space, offset);
  871. buf_pool_mutex_exit();
  872. return(bpage != NULL);
  873. }
  874. /************************************************************************
  875. Releases a compressed-only page acquired with buf_page_get_zip(). */
  876. UNIV_INLINE
  877. void
  878. buf_page_release_zip(
  879. /*=================*/
  880. buf_page_t* bpage) /* in: buffer block */
  881. {
  882. buf_block_t* block;
  883. ut_ad(bpage);
  884. ut_a(bpage->buf_fix_count > 0);
  885. switch (buf_page_get_state(bpage)) {
  886. case BUF_BLOCK_ZIP_PAGE:
  887. case BUF_BLOCK_ZIP_DIRTY:
  888. mutex_enter(&buf_pool_zip_mutex);
  889. bpage->buf_fix_count--;
  890. mutex_exit(&buf_pool_zip_mutex);
  891. return;
  892. case BUF_BLOCK_FILE_PAGE:
  893. block = (buf_block_t*) bpage;
  894. mutex_enter(&block->mutex);
  895. #ifdef UNIV_SYNC_DEBUG
  896. rw_lock_s_unlock(&block->debug_latch);
  897. #endif
  898. bpage->buf_fix_count--;
  899. mutex_exit(&block->mutex);
  900. return;
  901. case BUF_BLOCK_ZIP_FREE:
  902. case BUF_BLOCK_NOT_USED:
  903. case BUF_BLOCK_READY_FOR_USE:
  904. case BUF_BLOCK_MEMORY:
  905. case BUF_BLOCK_REMOVE_HASH:
  906. break;
  907. }
  908. ut_error;
  909. }
  910. /************************************************************************
  911. Decrements the bufferfix count of a buffer control block and releases
  912. a latch, if specified. */
  913. UNIV_INLINE
  914. void
  915. buf_page_release(
  916. /*=============*/
  917. buf_block_t* block, /* in: buffer block */
  918. ulint rw_latch, /* in: RW_S_LATCH, RW_X_LATCH,
  919. RW_NO_LATCH */
  920. mtr_t* mtr) /* in: mtr */
  921. {
  922. ut_ad(block);
  923. ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
  924. ut_a(block->page.buf_fix_count > 0);
  925. if (rw_latch == RW_X_LATCH && mtr->modifications) {
  926. buf_pool_mutex_enter();
  927. buf_flush_note_modification(block, mtr);
  928. buf_pool_mutex_exit();
  929. }
  930. mutex_enter(&block->mutex);
  931. #ifdef UNIV_SYNC_DEBUG
  932. rw_lock_s_unlock(&(block->debug_latch));
  933. #endif
  934. block->page.buf_fix_count--;
  935. /* Dirty blocks should be in the flush list. */
  936. ut_ad(!block->page.oldest_modification
  937. || block->page.in_flush_list);
  938. mutex_exit(&block->mutex);
  939. if (rw_latch == RW_S_LATCH) {
  940. rw_lock_s_unlock(&(block->lock));
  941. } else if (rw_latch == RW_X_LATCH) {
  942. rw_lock_x_unlock(&(block->lock));
  943. }
  944. }
  945. #ifdef UNIV_SYNC_DEBUG
  946. /*************************************************************************
  947. Adds latch level info for the rw-lock protecting the buffer frame. This
  948. should be called in the debug version after a successful latching of a
  949. page if we know the latching order level of the acquired latch. */
  950. UNIV_INLINE
  951. void
  952. buf_block_dbg_add_level(
  953. /*====================*/
  954. buf_block_t* block, /* in: buffer page
  955. where we have acquired latch */
  956. ulint level) /* in: latching order level */
  957. {
  958. sync_thread_add_level(&block->lock, level);
  959. }
  960. #endif /* UNIV_SYNC_DEBUG */