buf0buf.ic
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:17k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. The database buffer buf_pool
  3. (c) 1995 Innobase Oy
  4. Created 11/5/1995 Heikki Tuuri
  5. *******************************************************/
  6. #include "buf0flu.h"
  7. #include "buf0lru.h"
  8. #include "buf0rea.h"
  9. #include "mtr0mtr.h"
  10. extern ulint buf_dbg_counter; /* This is used to insert validation
  11. operations in execution in the
  12. debug version */
  13. /************************************************************************
  14. Recommends a move of a block to the start of the LRU list if there is danger
  15. of dropping from the buffer pool. NOTE: does not reserve the buffer pool
  16. mutex. */
  17. UNIV_INLINE
  18. ibool
  19. buf_block_peek_if_too_old(
  20. /*======================*/
  21. /* out: TRUE if should be made younger */
  22. buf_block_t* block) /* in: block to make younger */
  23. {
  24. if (buf_pool->freed_page_clock >= block->freed_page_clock 
  25. + 1 + (buf_pool->curr_size / 1024)) {
  26. return(TRUE);
  27. }
  28. return(FALSE);
  29. }
  30. /*************************************************************************
  31. Gets the current size of buffer buf_pool in bytes. In the case of AWE, the
  32. size of AWE window (= the frames). */
  33. UNIV_INLINE
  34. ulint
  35. buf_pool_get_curr_size(void)
  36. /*========================*/
  37. /* out: size in bytes */
  38. {
  39. return((buf_pool->n_frames) * UNIV_PAGE_SIZE);
  40. }
  41. /*************************************************************************
  42. Gets the maximum size of buffer buf_pool in bytes. In the case of AWE, the
  43. size of AWE window (= the frames). */
  44. UNIV_INLINE
  45. ulint
  46. buf_pool_get_max_size(void)
  47. /*=======================*/
  48. /* out: size in bytes */
  49. {
  50. return((buf_pool->n_frames) * UNIV_PAGE_SIZE);
  51. }
  52. /***********************************************************************
  53. Accessor function for block array. */
  54. UNIV_INLINE
  55. buf_block_t*
  56. buf_pool_get_nth_block(
  57. /*===================*/
  58. /* out: pointer to block */
  59. buf_pool_t* buf_pool,/* in: buf_pool */
  60. ulint i) /* in: index of the block */
  61. {
  62. ut_ad(buf_pool);
  63. ut_ad(i < buf_pool->max_size);
  64. return(i + buf_pool->blocks);
  65. }
  66. /***********************************************************************
  67. Checks if a pointer points to the block array of the buffer pool (blocks, not
  68. the frames). */
  69. UNIV_INLINE
  70. ibool
  71. buf_pool_is_block(
  72. /*==============*/
  73. /* out: TRUE if pointer to block */
  74. void* ptr) /* in: pointer to memory */
  75. {
  76. if ((buf_pool->blocks <= (buf_block_t*)ptr)
  77.     && ((buf_block_t*)ptr < buf_pool->blocks + buf_pool->max_size)) {
  78. return(TRUE);
  79. }
  80. return(FALSE);
  81. }
  82. /************************************************************************
  83. Gets the smallest oldest_modification lsn for any page in the pool. Returns
  84. ut_dulint_zero if all modified pages have been flushed to disk. */
  85. UNIV_INLINE
  86. dulint
  87. buf_pool_get_oldest_modification(void)
  88. /*==================================*/
  89. /* out: oldest modification in pool,
  90. ut_dulint_zero if none */
  91. {
  92. buf_block_t* block;
  93. dulint lsn;
  94. mutex_enter(&(buf_pool->mutex));
  95. block = UT_LIST_GET_LAST(buf_pool->flush_list);
  96. if (block == NULL) {
  97. lsn = ut_dulint_zero;
  98. } else {
  99. lsn = block->oldest_modification;
  100. }
  101. mutex_exit(&(buf_pool->mutex));
  102. return(lsn);
  103. }
  104. /***********************************************************************
  105. Increments the buf_pool clock by one and returns its new value. Remember
  106. that in the 32 bit version the clock wraps around at 4 billion! */
  107. UNIV_INLINE
  108. ulint
  109. buf_pool_clock_tic(void)
  110. /*====================*/
  111. /* out: new clock value */
  112. {
  113. #ifdef UNIV_SYNC_DEBUG
  114. ut_ad(mutex_own(&(buf_pool->mutex)));
  115. #endif /* UNIV_SYNC_DEBUG */
  116. buf_pool->ulint_clock++;
  117. return(buf_pool->ulint_clock);
  118. }
  119. /*************************************************************************
  120. Gets a pointer to the memory frame of a block. */
  121. UNIV_INLINE
  122. buf_frame_t*
  123. buf_block_get_frame(
  124. /*================*/
  125. /* out: pointer to the frame */
  126. buf_block_t* block) /* in: pointer to the control block */
  127. {
  128. ut_ad(block);
  129. ut_ad(block >= buf_pool->blocks);
  130. ut_ad(block < buf_pool->blocks + buf_pool->max_size);
  131. ut_ad(block->state != BUF_BLOCK_NOT_USED); 
  132. ut_ad((block->state != BUF_BLOCK_FILE_PAGE) 
  133.       || (block->buf_fix_count > 0));
  134. return(block->frame);
  135. }
  136. /*************************************************************************
  137. Gets the space id of a block. */
  138. UNIV_INLINE
  139. ulint
  140. buf_block_get_space(
  141. /*================*/
  142. /* out: space id */
  143. buf_block_t* block) /* in: pointer to the control block */
  144. {
  145. ut_ad(block);
  146. ut_ad(block >= buf_pool->blocks);
  147. ut_ad(block < buf_pool->blocks + buf_pool->max_size);
  148. ut_a(block->state == BUF_BLOCK_FILE_PAGE);
  149. ut_ad(block->buf_fix_count > 0);
  150. return(block->space);
  151. }
  152. /*************************************************************************
  153. Gets the page number of a block. */
  154. UNIV_INLINE
  155. ulint
  156. buf_block_get_page_no(
  157. /*==================*/
  158. /* out: page number */
  159. buf_block_t* block) /* in: pointer to the control block */
  160. {
  161. ut_ad(block);
  162. ut_ad(block >= buf_pool->blocks);
  163. ut_ad(block < buf_pool->blocks + buf_pool->max_size);
  164. ut_a(block->state == BUF_BLOCK_FILE_PAGE);
  165. ut_ad(block->buf_fix_count > 0);
  166. return(block->offset);
  167. }
  168. /***********************************************************************
  169. Gets the block to whose frame the pointer is pointing to. */
  170. UNIV_INLINE
  171. buf_block_t*
  172. buf_block_align(
  173. /*============*/
  174. /* out: pointer to block */
  175. byte* ptr) /* in: pointer to a frame */
  176. {
  177. buf_block_t* block;
  178. buf_frame_t* frame_zero;
  179. ut_ad(ptr);
  180. frame_zero = buf_pool->frame_zero;
  181. if ((ulint)ptr < (ulint)frame_zero
  182.     || (ulint)ptr > (ulint)(buf_pool->high_end)) {
  183. ut_print_timestamp(stderr);
  184. fprintf(stderr,
  185. "InnoDB: Error: trying to access a stray pointer %pn"
  186. "InnoDB: buf pool start is at %p, end at %pn"
  187. "InnoDB: Probable reason is database corruption or memoryn"
  188. "InnoDB: corruption. If this happens in an InnoDB database recovery,n"
  189. "InnoDB: you can look from section 6.1 at http://www.innodb.com/ibman.htmln"
  190. "InnoDB: how to force recovery.n",
  191.   ptr, frame_zero,
  192. buf_pool->high_end);
  193. ut_error;
  194. }
  195. block = *(buf_pool->blocks_of_frames + (((ulint)(ptr - frame_zero))
  196. >> UNIV_PAGE_SIZE_SHIFT));
  197. return(block);
  198. }
  199. /***********************************************************************
  200. Gets the frame the pointer is pointing to. */
  201. UNIV_INLINE
  202. buf_frame_t*
  203. buf_frame_align(
  204. /*============*/
  205. /* out: pointer to frame */
  206. byte* ptr) /* in: pointer to a frame */
  207. {
  208. buf_frame_t* frame;
  209. ut_ad(ptr);
  210. frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
  211. if (((ulint)frame < (ulint)(buf_pool->frame_zero))
  212.     || (ulint)frame >= (ulint)(buf_pool->high_end)) {
  213. ut_print_timestamp(stderr);
  214. fprintf(stderr,
  215. "InnoDB: Error: trying to access a stray pointer %pn"
  216. "InnoDB: buf pool start is at %p, end at %pn"
  217. "InnoDB: Probable reason is database corruption or memoryn"
  218. "InnoDB: corruption. If this happens in an InnoDB database recovery,n"
  219. "InnoDB: you can look from section 6.1 at http://www.innodb.com/ibman.htmln"
  220. "InnoDB: how to force recovery.n",
  221.   ptr, buf_pool->frame_zero,
  222. buf_pool->high_end);
  223. ut_error;
  224. }
  225. return(frame);
  226. }
  227. /**************************************************************************
  228. Gets the page number of a pointer pointing within a buffer frame containing
  229. a file page. */
  230. UNIV_INLINE
  231. ulint
  232. buf_frame_get_page_no(
  233. /*==================*/
  234. /* out: page number */
  235. byte* ptr) /* in: pointer to within a buffer frame */
  236. {
  237. return(buf_block_get_page_no(buf_block_align(ptr)));
  238. }
  239. /**************************************************************************
  240. Gets the space id of a pointer pointing within a buffer frame containing a
  241. file page. */
  242. UNIV_INLINE
  243. ulint
  244. buf_frame_get_space_id(
  245. /*===================*/
  246. /* out: space id */
  247. byte* ptr) /* in: pointer to within a buffer frame */
  248. {
  249. return(buf_block_get_space(buf_block_align(ptr)));
  250. }
  251. /**************************************************************************
  252. Gets the space id, page offset, and byte offset within page of a
  253. pointer pointing to a buffer frame containing a file page. */
  254. UNIV_INLINE
  255. void
  256. buf_ptr_get_fsp_addr(
  257. /*=================*/
  258. byte* ptr, /* in: pointer to a buffer frame */
  259. ulint* space, /* out: space id */
  260. fil_addr_t* addr) /* out: page offset and byte offset */
  261. {
  262. buf_block_t* block;
  263. block = buf_block_align(ptr);
  264. *space = buf_block_get_space(block);
  265. addr->page = buf_block_get_page_no(block);
  266. addr->boffset = ptr - buf_frame_align(ptr);
  267. }
  268. /**************************************************************************
  269. Gets the hash value of the page the pointer is pointing to. This can be used
  270. in searches in the lock hash table. */
  271. UNIV_INLINE
  272. ulint
  273. buf_frame_get_lock_hash_val(
  274. /*========================*/
  275. /* out: lock hash value */
  276. byte* ptr) /* in: pointer to within a buffer frame */
  277. {
  278. buf_block_t* block;
  279. block = buf_block_align(ptr);
  280. return(block->lock_hash_val);
  281. }
  282. /**************************************************************************
  283. Gets the mutex number protecting the page record lock hash chain in the lock
  284. table. */
  285. UNIV_INLINE
  286. mutex_t*
  287. buf_frame_get_lock_mutex(
  288. /*=====================*/
  289. /* out: mutex */
  290. byte* ptr) /* in: pointer to within a buffer frame */
  291. {
  292. buf_block_t* block;
  293. block = buf_block_align(ptr);
  294. return(block->lock_mutex);
  295. }
  296. /*************************************************************************
  297. Copies contents of a buffer frame to a given buffer. */
  298. UNIV_INLINE
  299. byte*
  300. buf_frame_copy(
  301. /*===========*/
  302. /* out: buf */
  303. byte* buf, /* in: buffer to copy to */
  304. buf_frame_t* frame) /* in: buffer frame */
  305. {
  306. ut_ad(buf && frame);
  307. ut_memcpy(buf, frame, UNIV_PAGE_SIZE);
  308. return(buf);
  309. }
  310. /************************************************************************
  311. Calculates a folded value of a file page address to use in the page hash
  312. table. */
  313. UNIV_INLINE
  314. ulint
  315. buf_page_address_fold(
  316. /*==================*/
  317. /* out: the folded value */
  318. ulint space, /* in: space id */
  319. ulint offset) /* in: offset of the page within space */
  320. {
  321. return((space << 20) + space + offset);
  322. }
  323. /************************************************************************
  324. This function is used to get info if there is an io operation
  325. going on on a buffer page. */
  326. UNIV_INLINE
  327. ibool
  328. buf_page_io_query(
  329. /*==============*/
  330. /* out: TRUE if io going on */
  331. buf_block_t* block) /* in: buf_pool block, must be bufferfixed */
  332. {
  333. mutex_enter(&(buf_pool->mutex));
  334. ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
  335. ut_ad(block->buf_fix_count > 0);
  336. if (block->io_fix != 0) {
  337. mutex_exit(&(buf_pool->mutex));
  338. return(TRUE);
  339. }
  340. mutex_exit(&(buf_pool->mutex));
  341. return(FALSE);
  342. }
  343. /************************************************************************
  344. Gets the youngest modification log sequence number for a frame. Returns zero
  345. if not a file page or no modification occurred yet. */
  346. UNIV_INLINE
  347. dulint
  348. buf_frame_get_newest_modification(
  349. /*==============================*/
  350. /* out: newest modification to the page */
  351. buf_frame_t* frame) /* in: pointer to a frame */
  352. {
  353. buf_block_t* block;
  354. dulint lsn;
  355. ut_ad(frame);
  356. block = buf_block_align(frame);
  357. mutex_enter(&(buf_pool->mutex));
  358. if (block->state == BUF_BLOCK_FILE_PAGE) {
  359. lsn = block->newest_modification;
  360. } else {
  361. lsn = ut_dulint_zero;
  362. }
  363. mutex_exit(&(buf_pool->mutex));
  364. return(lsn);
  365. }
  366. /************************************************************************
  367. Increments the modify clock of a frame by 1. The caller must (1) own the
  368. buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
  369. on the block. */
  370. UNIV_INLINE
  371. dulint
  372. buf_frame_modify_clock_inc(
  373. /*=======================*/
  374. /* out: new value */
  375. buf_frame_t* frame) /* in: pointer to a frame */
  376. {
  377. buf_block_t* block;
  378. ut_ad(frame);
  379. block = buf_block_align(frame);
  380. #ifdef UNIV_SYNC_DEBUG
  381. ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0))
  382.       || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
  383. #endif /*UNIV_SYNC_DEBUG */
  384. UT_DULINT_INC(block->modify_clock);
  385. return(block->modify_clock);
  386. }
  387. /************************************************************************
  388. Increments the modify clock of a frame by 1. The caller must (1) own the
  389. buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
  390. on the block. */
  391. UNIV_INLINE
  392. dulint
  393. buf_block_modify_clock_inc(
  394. /*=======================*/
  395. /* out: new value */
  396. buf_block_t* block) /* in: block */
  397. {
  398. #ifdef UNIV_SYNC_DEBUG
  399. ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0))
  400.       || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
  401. #endif /* UNIV_SYNC_DEBUG */
  402. UT_DULINT_INC(block->modify_clock);
  403. return(block->modify_clock);
  404. }
  405. /************************************************************************
  406. Returns the value of the modify clock. The caller must have an s-lock 
  407. or x-lock on the block. */
  408. UNIV_INLINE
  409. dulint
  410. buf_frame_get_modify_clock(
  411. /*=======================*/
  412. /* out: value */
  413. buf_frame_t* frame) /* in: pointer to a frame */
  414. {
  415. buf_block_t* block;
  416. ut_ad(frame);
  417. block = buf_block_align(frame);
  418. #ifdef UNIV_SYNC_DEBUG
  419. ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
  420.       || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
  421. #endif /* UNIV_SYNC_DEBUG */
  422. return(block->modify_clock);
  423. }
  424. #ifdef UNIV_SYNC_DEBUG
  425. /***********************************************************************
  426. Increments the bufferfix count. */
  427. UNIV_INLINE
  428. void
  429. buf_block_buf_fix_inc_debug(
  430. /*========================*/
  431. buf_block_t* block, /* in: block to bufferfix */
  432. const char* file __attribute__ ((unused)), /* in: file name */
  433. ulint line __attribute__ ((unused))) /* in: line */
  434. {
  435. #ifdef UNIV_SYNC_DEBUG
  436. ibool ret;
  437. ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
  438. ut_ad(ret == TRUE);
  439. #endif
  440. block->buf_fix_count++;
  441. }
  442. #else /* UNIV_SYNC_DEBUG */
  443. /***********************************************************************
  444. Increments the bufferfix count. */
  445. UNIV_INLINE
  446. void
  447. buf_block_buf_fix_inc(
  448. /*==================*/
  449. buf_block_t* block) /* in: block to bufferfix */
  450. {
  451. block->buf_fix_count++;
  452. }
  453. #endif /* UNIV_SYNC_DEBUG */
  454. /**********************************************************************
  455. Returns the control block of a file page, NULL if not found. */
  456. UNIV_INLINE
  457. buf_block_t*
  458. buf_page_hash_get(
  459. /*==============*/
  460. /* out: block, NULL if not found */
  461. ulint space, /* in: space id */
  462. ulint offset) /* in: offset of the page within space */
  463. {
  464. buf_block_t* block;
  465. ulint fold;
  466. ut_ad(buf_pool);
  467. #ifdef UNIV_SYNC_DEBUG
  468. ut_ad(mutex_own(&(buf_pool->mutex)));
  469. #endif /* UNIV_SYNC_DEBUG */
  470. /* Look for the page in the hash table */
  471. fold = buf_page_address_fold(space, offset);
  472. HASH_SEARCH(hash, buf_pool->page_hash, fold, block,
  473. (block->space == space) && (block->offset == offset));
  474. ut_a(block == NULL || block->state == BUF_BLOCK_FILE_PAGE);
  475. return(block);
  476. }
  477. /************************************************************************
  478. Tries to get the page, but if file io is required, releases all latches
  479. in mtr down to the given savepoint. If io is required, this function
  480. retrieves the page to buffer buf_pool, but does not bufferfix it or latch
  481. it. */
  482. UNIV_INLINE
  483. buf_frame_t*
  484. buf_page_get_release_on_io(
  485. /*=======================*/
  486. /* out: pointer to the frame, or NULL
  487. if not in buffer buf_pool */
  488. ulint space, /* in: space id */
  489. ulint offset, /* in: offset of the page within space
  490. in units of a page */
  491. buf_frame_t* guess, /* in: guessed frame or NULL */
  492. ulint rw_latch, /* in: RW_X_LATCH, RW_S_LATCH,
  493. or RW_NO_LATCH */
  494. ulint savepoint, /* in: mtr savepoint */
  495. mtr_t* mtr) /* in: mtr */
  496. {
  497. buf_frame_t* frame;
  498. frame = buf_page_get_gen(space, offset, rw_latch, guess,
  499. BUF_GET_IF_IN_POOL,
  500. __FILE__, __LINE__,
  501. mtr);
  502. if (frame != NULL) {
  503. return(frame);
  504. }
  505. /* The page was not in the buffer buf_pool: release the latches
  506. down to the savepoint */
  507. mtr_rollback_to_savepoint(mtr, savepoint);
  508. buf_page_get(space, offset, RW_S_LATCH, mtr);
  509. /* When we get here, the page is in buffer, but we release
  510. the latches again down to the savepoint, before returning */
  511. mtr_rollback_to_savepoint(mtr, savepoint);
  512. return(NULL);
  513. }
  514. /************************************************************************
  515. Decrements the bufferfix count of a buffer control block and releases
  516. a latch, if specified. */
  517. UNIV_INLINE
  518. void
  519. buf_page_release(
  520. /*=============*/
  521. buf_block_t* block, /* in: buffer block */
  522. ulint rw_latch, /* in: RW_S_LATCH, RW_X_LATCH,
  523. RW_NO_LATCH */
  524. mtr_t* mtr) /* in: mtr */
  525. {
  526. ulint buf_fix_count;
  527. ut_ad(block);
  528. mutex_enter_fast(&(buf_pool->mutex));
  529. ut_a(block->state == BUF_BLOCK_FILE_PAGE);
  530. ut_a(block->buf_fix_count > 0);
  531. if (rw_latch == RW_X_LATCH && mtr->modifications) {
  532. buf_flush_note_modification(block, mtr);
  533. }
  534. #ifdef UNIV_SYNC_DEBUG
  535. rw_lock_s_unlock(&(block->debug_latch));
  536. #endif
  537. buf_fix_count = block->buf_fix_count;
  538. block->buf_fix_count = buf_fix_count - 1;
  539. mutex_exit(&(buf_pool->mutex));
  540. if (rw_latch == RW_S_LATCH) {
  541. rw_lock_s_unlock(&(block->lock));
  542. } else if (rw_latch == RW_X_LATCH) {
  543. rw_lock_x_unlock(&(block->lock));
  544. }
  545. }
  546. #ifdef UNIV_SYNC_DEBUG
  547. /*************************************************************************
  548. Adds latch level info for the rw-lock protecting the buffer frame. This
  549. should be called in the debug version after a successful latching of a
  550. page if we know the latching order level of the acquired latch. If
  551. UNIV_SYNC_DEBUG is not defined, compiles to an empty function. */
  552. UNIV_INLINE
  553. void
  554. buf_page_dbg_add_level(
  555. /*===================*/
  556. buf_frame_t* frame __attribute__((unused)), /* in: buffer page
  557.                                 where we have acquired latch */
  558. ulint level __attribute__((unused))) /* in: latching order
  559.                                 level */
  560. {
  561. sync_thread_add_level(&(buf_block_align(frame)->lock), level);
  562. }
  563. #endif /* UNIV_SYNC_DEBUG */