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.

327 lines
10 KiB

  1. /*****************************************************************************
  2. Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
  3. This program is free software; you can redistribute it and/or modify it under
  4. the terms of the GNU General Public License as published by the Free Software
  5. Foundation; version 2 of the License.
  6. This program is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along with
  10. this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  11. Place, Suite 330, Boston, MA 02111-1307 USA
  12. *****************************************************************************/
  13. /**************************************************//**
  14. @file include/ibuf0ibuf.ic
  15. Insert buffer
  16. Created 7/19/1997 Heikki Tuuri
  17. *******************************************************/
  18. #include "page0page.h"
  19. #include "page0zip.h"
  20. #ifndef UNIV_HOTBACKUP
  21. #include "buf0lru.h"
  22. /** Counter for ibuf_should_try() */
  23. extern ulint ibuf_flush_count;
  24. /** An index page must contain at least UNIV_PAGE_SIZE /
  25. IBUF_PAGE_SIZE_PER_FREE_SPACE bytes of free space for ibuf to try to
  26. buffer inserts to this page. If there is this much of free space, the
  27. corresponding bits are set in the ibuf bitmap. */
  28. #define IBUF_PAGE_SIZE_PER_FREE_SPACE 32
  29. /** Insert buffer struct */
  30. struct ibuf_struct{
  31. ulint size; /*!< current size of the ibuf index
  32. tree, in pages */
  33. ulint max_size; /*!< recommended maximum size of the
  34. ibuf index tree, in pages */
  35. ulint seg_size; /*!< allocated pages of the file
  36. segment containing ibuf header and
  37. tree */
  38. ibool empty; /*!< after an insert to the ibuf tree
  39. is performed, this is set to FALSE,
  40. and if a contract operation finds
  41. the tree empty, this is set to
  42. TRUE */
  43. ulint free_list_len; /*!< length of the free list */
  44. ulint height; /*!< tree height */
  45. dict_index_t* index; /*!< insert buffer index */
  46. ulint n_inserts; /*!< number of inserts made to
  47. the insert buffer */
  48. ulint n_merges; /*!< number of pages merged */
  49. ulint n_merged_recs; /*!< number of records merged */
  50. };
  51. /************************************************************************//**
  52. Sets the free bit of the page in the ibuf bitmap. This is done in a separate
  53. mini-transaction, hence this operation does not restrict further work to only
  54. ibuf bitmap operations, which would result if the latch to the bitmap page
  55. were kept. */
  56. UNIV_INTERN
  57. void
  58. ibuf_set_free_bits_func(
  59. /*====================*/
  60. buf_block_t* block, /*!< in: index page of a non-clustered index;
  61. free bit is reset if page level is 0 */
  62. #ifdef UNIV_IBUF_DEBUG
  63. ulint max_val,/*!< in: ULINT_UNDEFINED or a maximum
  64. value which the bits must have before
  65. setting; this is for debugging */
  66. #endif /* UNIV_IBUF_DEBUG */
  67. ulint val); /*!< in: value to set: < 4 */
  68. #ifdef UNIV_IBUF_DEBUG
  69. # define ibuf_set_free_bits(b,v,max) ibuf_set_free_bits_func(b,max,v)
  70. #else /* UNIV_IBUF_DEBUG */
  71. # define ibuf_set_free_bits(b,v,max) ibuf_set_free_bits_func(b,v)
  72. #endif /* UNIV_IBUF_DEBUG */
  73. /**********************************************************************//**
  74. A basic partial test if an insert to the insert buffer could be possible and
  75. recommended. */
  76. UNIV_INLINE
  77. ibool
  78. ibuf_should_try(
  79. /*============*/
  80. dict_index_t* index, /*!< in: index where to insert */
  81. ulint ignore_sec_unique) /*!< in: if != 0, we should
  82. ignore UNIQUE constraint on
  83. a secondary index when we
  84. decide */
  85. {
  86. if (ibuf_use != IBUF_USE_NONE
  87. && !dict_index_is_clust(index)
  88. && (ignore_sec_unique || !dict_index_is_unique(index))) {
  89. ibuf_flush_count++;
  90. if (ibuf_flush_count % 4 == 0) {
  91. buf_LRU_try_free_flushed_blocks();
  92. }
  93. return(TRUE);
  94. }
  95. return(FALSE);
  96. }
  97. /***********************************************************************//**
  98. Checks if a page address is an ibuf bitmap page address.
  99. @return TRUE if a bitmap page */
  100. UNIV_INLINE
  101. ibool
  102. ibuf_bitmap_page(
  103. /*=============*/
  104. ulint zip_size,/*!< in: compressed page size in bytes;
  105. 0 for uncompressed pages */
  106. ulint page_no)/*!< in: page number */
  107. {
  108. ut_ad(ut_is_2pow(zip_size));
  109. if (!zip_size) {
  110. return(UNIV_UNLIKELY((page_no & (UNIV_PAGE_SIZE - 1))
  111. == FSP_IBUF_BITMAP_OFFSET));
  112. }
  113. return(UNIV_UNLIKELY((page_no & (zip_size - 1))
  114. == FSP_IBUF_BITMAP_OFFSET));
  115. }
  116. /*********************************************************************//**
  117. Translates the free space on a page to a value in the ibuf bitmap.
  118. @return value for ibuf bitmap bits */
  119. UNIV_INLINE
  120. ulint
  121. ibuf_index_page_calc_free_bits(
  122. /*===========================*/
  123. ulint zip_size, /*!< in: compressed page size in bytes;
  124. 0 for uncompressed pages */
  125. ulint max_ins_size) /*!< in: maximum insert size after reorganize
  126. for the page */
  127. {
  128. ulint n;
  129. ut_ad(ut_is_2pow(zip_size));
  130. ut_ad(!zip_size || zip_size > IBUF_PAGE_SIZE_PER_FREE_SPACE);
  131. ut_ad(zip_size <= UNIV_PAGE_SIZE);
  132. if (zip_size) {
  133. n = max_ins_size
  134. / (zip_size / IBUF_PAGE_SIZE_PER_FREE_SPACE);
  135. } else {
  136. n = max_ins_size
  137. / (UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE);
  138. }
  139. if (n == 3) {
  140. n = 2;
  141. }
  142. if (n > 3) {
  143. n = 3;
  144. }
  145. return(n);
  146. }
  147. /*********************************************************************//**
  148. Translates the ibuf free bits to the free space on a page in bytes.
  149. @return maximum insert size after reorganize for the page */
  150. UNIV_INLINE
  151. ulint
  152. ibuf_index_page_calc_free_from_bits(
  153. /*================================*/
  154. ulint zip_size,/*!< in: compressed page size in bytes;
  155. 0 for uncompressed pages */
  156. ulint bits) /*!< in: value for ibuf bitmap bits */
  157. {
  158. ut_ad(bits < 4);
  159. ut_ad(ut_is_2pow(zip_size));
  160. ut_ad(!zip_size || zip_size > IBUF_PAGE_SIZE_PER_FREE_SPACE);
  161. ut_ad(zip_size <= UNIV_PAGE_SIZE);
  162. if (zip_size) {
  163. if (bits == 3) {
  164. return(4 * zip_size / IBUF_PAGE_SIZE_PER_FREE_SPACE);
  165. }
  166. return(bits * zip_size / IBUF_PAGE_SIZE_PER_FREE_SPACE);
  167. }
  168. if (bits == 3) {
  169. return(4 * UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE);
  170. }
  171. return(bits * (UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE));
  172. }
  173. /*********************************************************************//**
  174. Translates the free space on a compressed page to a value in the ibuf bitmap.
  175. @return value for ibuf bitmap bits */
  176. UNIV_INLINE
  177. ulint
  178. ibuf_index_page_calc_free_zip(
  179. /*==========================*/
  180. ulint zip_size,
  181. /*!< in: compressed page size in bytes */
  182. const buf_block_t* block) /*!< in: buffer block */
  183. {
  184. ulint max_ins_size;
  185. const page_zip_des_t* page_zip;
  186. lint zip_max_ins;
  187. ut_ad(zip_size == buf_block_get_zip_size(block));
  188. ut_ad(zip_size);
  189. max_ins_size = page_get_max_insert_size_after_reorganize(
  190. buf_block_get_frame(block), 1);
  191. page_zip = buf_block_get_page_zip(block);
  192. zip_max_ins = page_zip_max_ins_size(page_zip,
  193. FALSE/* not clustered */);
  194. if (UNIV_UNLIKELY(zip_max_ins < 0)) {
  195. return(0);
  196. } else if (UNIV_LIKELY(max_ins_size > (ulint) zip_max_ins)) {
  197. max_ins_size = (ulint) zip_max_ins;
  198. }
  199. return(ibuf_index_page_calc_free_bits(zip_size, max_ins_size));
  200. }
  201. /*********************************************************************//**
  202. Translates the free space on a page to a value in the ibuf bitmap.
  203. @return value for ibuf bitmap bits */
  204. UNIV_INLINE
  205. ulint
  206. ibuf_index_page_calc_free(
  207. /*======================*/
  208. ulint zip_size,/*!< in: compressed page size in bytes;
  209. 0 for uncompressed pages */
  210. const buf_block_t* block) /*!< in: buffer block */
  211. {
  212. ut_ad(zip_size == buf_block_get_zip_size(block));
  213. if (!zip_size) {
  214. ulint max_ins_size;
  215. max_ins_size = page_get_max_insert_size_after_reorganize(
  216. buf_block_get_frame(block), 1);
  217. return(ibuf_index_page_calc_free_bits(0, max_ins_size));
  218. } else {
  219. return(ibuf_index_page_calc_free_zip(zip_size, block));
  220. }
  221. }
  222. /************************************************************************//**
  223. Updates the free bits of an uncompressed page in the ibuf bitmap if
  224. there is not enough free on the page any more. This is done in a
  225. separate mini-transaction, hence this operation does not restrict
  226. further work to only ibuf bitmap operations, which would result if the
  227. latch to the bitmap page were kept. NOTE: The free bits in the insert
  228. buffer bitmap must never exceed the free space on a page. It is
  229. unsafe to increment the bits in a separately committed
  230. mini-transaction, because in crash recovery, the free bits could
  231. momentarily be set too high. It is only safe to use this function for
  232. decrementing the free bits. Should more free space become available,
  233. we must not update the free bits here, because that would break crash
  234. recovery. */
  235. UNIV_INLINE
  236. void
  237. ibuf_update_free_bits_if_full(
  238. /*==========================*/
  239. buf_block_t* block, /*!< in: index page to which we have added new
  240. records; the free bits are updated if the
  241. index is non-clustered and non-unique and
  242. the page level is 0, and the page becomes
  243. fuller */
  244. ulint max_ins_size,/*!< in: value of maximum insert size with
  245. reorganize before the latest operation
  246. performed to the page */
  247. ulint increase)/*!< in: upper limit for the additional space
  248. used in the latest operation, if known, or
  249. ULINT_UNDEFINED */
  250. {
  251. ulint before;
  252. ulint after;
  253. ut_ad(!buf_block_get_page_zip(block));
  254. before = ibuf_index_page_calc_free_bits(0, max_ins_size);
  255. if (max_ins_size >= increase) {
  256. #if ULINT32_UNDEFINED <= UNIV_PAGE_SIZE
  257. # error "ULINT32_UNDEFINED <= UNIV_PAGE_SIZE"
  258. #endif
  259. after = ibuf_index_page_calc_free_bits(0, max_ins_size
  260. - increase);
  261. #ifdef UNIV_IBUF_DEBUG
  262. ut_a(after <= ibuf_index_page_calc_free(0, block));
  263. #endif
  264. } else {
  265. after = ibuf_index_page_calc_free(0, block);
  266. }
  267. if (after == 0) {
  268. /* We move the page to the front of the buffer pool LRU list:
  269. the purpose of this is to prevent those pages to which we
  270. cannot make inserts using the insert buffer from slipping
  271. out of the buffer pool */
  272. buf_page_make_young(&block->page);
  273. }
  274. if (before > after) {
  275. ibuf_set_free_bits(block, after, before);
  276. }
  277. }
  278. #endif /* !UNIV_HOTBACKUP */