buf0buf.ic
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:16k
源码类别:

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