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.

471 lines
17 KiB

  1. /*****************************************************************************
  2. Copyright (c) 2005, 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/page0zip.h
  15. Compressed page interface
  16. Created June 2005 by Marko Makela
  17. *******************************************************/
  18. #ifndef page0zip_h
  19. #define page0zip_h
  20. #ifdef UNIV_MATERIALIZE
  21. # undef UNIV_INLINE
  22. # define UNIV_INLINE
  23. #endif
  24. #include "mtr0types.h"
  25. #include "page0types.h"
  26. #include "buf0types.h"
  27. #include "dict0types.h"
  28. #include "trx0types.h"
  29. #include "mem0mem.h"
  30. /**********************************************************************//**
  31. Determine the size of a compressed page in bytes.
  32. @return size in bytes */
  33. UNIV_INLINE
  34. ulint
  35. page_zip_get_size(
  36. /*==============*/
  37. const page_zip_des_t* page_zip) /*!< in: compressed page */
  38. __attribute__((nonnull, pure));
  39. /**********************************************************************//**
  40. Set the size of a compressed page in bytes. */
  41. UNIV_INLINE
  42. void
  43. page_zip_set_size(
  44. /*==============*/
  45. page_zip_des_t* page_zip, /*!< in/out: compressed page */
  46. ulint size); /*!< in: size in bytes */
  47. #ifndef UNIV_HOTBACKUP
  48. /**********************************************************************//**
  49. Determine if a record is so big that it needs to be stored externally.
  50. @return FALSE if the entire record can be stored locally on the page */
  51. UNIV_INLINE
  52. ibool
  53. page_zip_rec_needs_ext(
  54. /*===================*/
  55. ulint rec_size, /*!< in: length of the record in bytes */
  56. ulint comp, /*!< in: nonzero=compact format */
  57. ulint n_fields, /*!< in: number of fields in the record;
  58. ignored if zip_size == 0 */
  59. ulint zip_size) /*!< in: compressed page size in bytes, or 0 */
  60. __attribute__((const));
  61. /**********************************************************************//**
  62. Determine the guaranteed free space on an empty page.
  63. @return minimum payload size on the page */
  64. UNIV_INTERN
  65. ulint
  66. page_zip_empty_size(
  67. /*================*/
  68. ulint n_fields, /*!< in: number of columns in the index */
  69. ulint zip_size) /*!< in: compressed page size in bytes */
  70. __attribute__((const));
  71. #endif /* !UNIV_HOTBACKUP */
  72. /**********************************************************************//**
  73. Initialize a compressed page descriptor. */
  74. UNIV_INLINE
  75. void
  76. page_zip_des_init(
  77. /*==============*/
  78. page_zip_des_t* page_zip); /*!< in/out: compressed page
  79. descriptor */
  80. /**********************************************************************//**
  81. Configure the zlib allocator to use the given memory heap. */
  82. UNIV_INTERN
  83. void
  84. page_zip_set_alloc(
  85. /*===============*/
  86. void* stream, /*!< in/out: zlib stream */
  87. mem_heap_t* heap); /*!< in: memory heap to use */
  88. /**********************************************************************//**
  89. Compress a page.
  90. @return TRUE on success, FALSE on failure; page_zip will be left
  91. intact on failure. */
  92. UNIV_INTERN
  93. ibool
  94. page_zip_compress(
  95. /*==============*/
  96. page_zip_des_t* page_zip,/*!< in: size; out: data, n_blobs,
  97. m_start, m_end, m_nonempty */
  98. const page_t* page, /*!< in: uncompressed page */
  99. dict_index_t* index, /*!< in: index of the B-tree node */
  100. mtr_t* mtr) /*!< in: mini-transaction, or NULL */
  101. __attribute__((nonnull(1,2,3)));
  102. /**********************************************************************//**
  103. Decompress a page. This function should tolerate errors on the compressed
  104. page. Instead of letting assertions fail, it will return FALSE if an
  105. inconsistency is detected.
  106. @return TRUE on success, FALSE on failure */
  107. UNIV_INTERN
  108. ibool
  109. page_zip_decompress(
  110. /*================*/
  111. page_zip_des_t* page_zip,/*!< in: data, ssize;
  112. out: m_start, m_end, m_nonempty, n_blobs */
  113. page_t* page) /*!< out: uncompressed page, may be trashed */
  114. __attribute__((nonnull));
  115. #ifdef UNIV_DEBUG
  116. /**********************************************************************//**
  117. Validate a compressed page descriptor.
  118. @return TRUE if ok */
  119. UNIV_INLINE
  120. ibool
  121. page_zip_simple_validate(
  122. /*=====================*/
  123. const page_zip_des_t* page_zip); /*!< in: compressed page
  124. descriptor */
  125. #endif /* UNIV_DEBUG */
  126. #ifdef UNIV_ZIP_DEBUG
  127. /**********************************************************************//**
  128. Check that the compressed and decompressed pages match.
  129. @return TRUE if valid, FALSE if not */
  130. UNIV_INTERN
  131. ibool
  132. page_zip_validate_low(
  133. /*==================*/
  134. const page_zip_des_t* page_zip,/*!< in: compressed page */
  135. const page_t* page, /*!< in: uncompressed page */
  136. ibool sloppy) /*!< in: FALSE=strict,
  137. TRUE=ignore the MIN_REC_FLAG */
  138. __attribute__((nonnull));
  139. /**********************************************************************//**
  140. Check that the compressed and decompressed pages match. */
  141. UNIV_INTERN
  142. ibool
  143. page_zip_validate(
  144. /*==============*/
  145. const page_zip_des_t* page_zip,/*!< in: compressed page */
  146. const page_t* page) /*!< in: uncompressed page */
  147. __attribute__((nonnull));
  148. #endif /* UNIV_ZIP_DEBUG */
  149. /**********************************************************************//**
  150. Determine how big record can be inserted without recompressing the page.
  151. @return a positive number indicating the maximum size of a record
  152. whose insertion is guaranteed to succeed, or zero or negative */
  153. UNIV_INLINE
  154. lint
  155. page_zip_max_ins_size(
  156. /*==================*/
  157. const page_zip_des_t* page_zip,/*!< in: compressed page */
  158. ibool is_clust)/*!< in: TRUE if clustered index */
  159. __attribute__((nonnull, pure));
  160. /**********************************************************************//**
  161. Determine if enough space is available in the modification log.
  162. @return TRUE if page_zip_write_rec() will succeed */
  163. UNIV_INLINE
  164. ibool
  165. page_zip_available(
  166. /*===============*/
  167. const page_zip_des_t* page_zip,/*!< in: compressed page */
  168. ibool is_clust,/*!< in: TRUE if clustered index */
  169. ulint length, /*!< in: combined size of the record */
  170. ulint create) /*!< in: nonzero=add the record to
  171. the heap */
  172. __attribute__((nonnull, pure));
  173. /**********************************************************************//**
  174. Write data to the uncompressed header portion of a page. The data must
  175. already have been written to the uncompressed page. */
  176. UNIV_INLINE
  177. void
  178. page_zip_write_header(
  179. /*==================*/
  180. page_zip_des_t* page_zip,/*!< in/out: compressed page */
  181. const byte* str, /*!< in: address on the uncompressed page */
  182. ulint length, /*!< in: length of the data */
  183. mtr_t* mtr) /*!< in: mini-transaction, or NULL */
  184. __attribute__((nonnull(1,2)));
  185. /**********************************************************************//**
  186. Write an entire record on the compressed page. The data must already
  187. have been written to the uncompressed page. */
  188. UNIV_INTERN
  189. void
  190. page_zip_write_rec(
  191. /*===============*/
  192. page_zip_des_t* page_zip,/*!< in/out: compressed page */
  193. const byte* rec, /*!< in: record being written */
  194. dict_index_t* index, /*!< in: the index the record belongs to */
  195. const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
  196. ulint create) /*!< in: nonzero=insert, zero=update */
  197. __attribute__((nonnull));
  198. /***********************************************************//**
  199. Parses a log record of writing a BLOB pointer of a record.
  200. @return end of log record or NULL */
  201. UNIV_INTERN
  202. byte*
  203. page_zip_parse_write_blob_ptr(
  204. /*==========================*/
  205. byte* ptr, /*!< in: redo log buffer */
  206. byte* end_ptr,/*!< in: redo log buffer end */
  207. page_t* page, /*!< in/out: uncompressed page */
  208. page_zip_des_t* page_zip);/*!< in/out: compressed page */
  209. /**********************************************************************//**
  210. Write a BLOB pointer of a record on the leaf page of a clustered index.
  211. The information must already have been updated on the uncompressed page. */
  212. UNIV_INTERN
  213. void
  214. page_zip_write_blob_ptr(
  215. /*====================*/
  216. page_zip_des_t* page_zip,/*!< in/out: compressed page */
  217. const byte* rec, /*!< in/out: record whose data is being
  218. written */
  219. dict_index_t* index, /*!< in: index of the page */
  220. const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
  221. ulint n, /*!< in: column index */
  222. mtr_t* mtr) /*!< in: mini-transaction handle,
  223. or NULL if no logging is needed */
  224. __attribute__((nonnull(1,2,3,4)));
  225. /***********************************************************//**
  226. Parses a log record of writing the node pointer of a record.
  227. @return end of log record or NULL */
  228. UNIV_INTERN
  229. byte*
  230. page_zip_parse_write_node_ptr(
  231. /*==========================*/
  232. byte* ptr, /*!< in: redo log buffer */
  233. byte* end_ptr,/*!< in: redo log buffer end */
  234. page_t* page, /*!< in/out: uncompressed page */
  235. page_zip_des_t* page_zip);/*!< in/out: compressed page */
  236. /**********************************************************************//**
  237. Write the node pointer of a record on a non-leaf compressed page. */
  238. UNIV_INTERN
  239. void
  240. page_zip_write_node_ptr(
  241. /*====================*/
  242. page_zip_des_t* page_zip,/*!< in/out: compressed page */
  243. byte* rec, /*!< in/out: record */
  244. ulint size, /*!< in: data size of rec */
  245. ulint ptr, /*!< in: node pointer */
  246. mtr_t* mtr) /*!< in: mini-transaction, or NULL */
  247. __attribute__((nonnull(1,2)));
  248. /**********************************************************************//**
  249. Write the trx_id and roll_ptr of a record on a B-tree leaf node page. */
  250. UNIV_INTERN
  251. void
  252. page_zip_write_trx_id_and_roll_ptr(
  253. /*===============================*/
  254. page_zip_des_t* page_zip,/*!< in/out: compressed page */
  255. byte* rec, /*!< in/out: record */
  256. const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
  257. ulint trx_id_col,/*!< in: column number of TRX_ID in rec */
  258. trx_id_t trx_id, /*!< in: transaction identifier */
  259. roll_ptr_t roll_ptr)/*!< in: roll_ptr */
  260. __attribute__((nonnull));
  261. /**********************************************************************//**
  262. Write the "deleted" flag of a record on a compressed page. The flag must
  263. already have been written on the uncompressed page. */
  264. UNIV_INTERN
  265. void
  266. page_zip_rec_set_deleted(
  267. /*=====================*/
  268. page_zip_des_t* page_zip,/*!< in/out: compressed page */
  269. const byte* rec, /*!< in: record on the uncompressed page */
  270. ulint flag) /*!< in: the deleted flag (nonzero=TRUE) */
  271. __attribute__((nonnull));
  272. /**********************************************************************//**
  273. Write the "owned" flag of a record on a compressed page. The n_owned field
  274. must already have been written on the uncompressed page. */
  275. UNIV_INTERN
  276. void
  277. page_zip_rec_set_owned(
  278. /*===================*/
  279. page_zip_des_t* page_zip,/*!< in/out: compressed page */
  280. const byte* rec, /*!< in: record on the uncompressed page */
  281. ulint flag) /*!< in: the owned flag (nonzero=TRUE) */
  282. __attribute__((nonnull));
  283. /**********************************************************************//**
  284. Insert a record to the dense page directory. */
  285. UNIV_INTERN
  286. void
  287. page_zip_dir_insert(
  288. /*================*/
  289. page_zip_des_t* page_zip,/*!< in/out: compressed page */
  290. const byte* prev_rec,/*!< in: record after which to insert */
  291. const byte* free_rec,/*!< in: record from which rec was
  292. allocated, or NULL */
  293. byte* rec); /*!< in: record to insert */
  294. /**********************************************************************//**
  295. Shift the dense page directory and the array of BLOB pointers
  296. when a record is deleted. */
  297. UNIV_INTERN
  298. void
  299. page_zip_dir_delete(
  300. /*================*/
  301. page_zip_des_t* page_zip,/*!< in/out: compressed page */
  302. byte* rec, /*!< in: deleted record */
  303. dict_index_t* index, /*!< in: index of rec */
  304. const ulint* offsets,/*!< in: rec_get_offsets(rec) */
  305. const byte* free) /*!< in: previous start of the free list */
  306. __attribute__((nonnull(1,2,3,4)));
  307. /**********************************************************************//**
  308. Add a slot to the dense page directory. */
  309. UNIV_INTERN
  310. void
  311. page_zip_dir_add_slot(
  312. /*==================*/
  313. page_zip_des_t* page_zip, /*!< in/out: compressed page */
  314. ulint is_clustered) /*!< in: nonzero for clustered index,
  315. zero for others */
  316. __attribute__((nonnull));
  317. /***********************************************************//**
  318. Parses a log record of writing to the header of a page.
  319. @return end of log record or NULL */
  320. UNIV_INTERN
  321. byte*
  322. page_zip_parse_write_header(
  323. /*========================*/
  324. byte* ptr, /*!< in: redo log buffer */
  325. byte* end_ptr,/*!< in: redo log buffer end */
  326. page_t* page, /*!< in/out: uncompressed page */
  327. page_zip_des_t* page_zip);/*!< in/out: compressed page */
  328. /**********************************************************************//**
  329. Write data to the uncompressed header portion of a page. The data must
  330. already have been written to the uncompressed page.
  331. However, the data portion of the uncompressed page may differ from
  332. the compressed page when a record is being inserted in
  333. page_cur_insert_rec_low(). */
  334. UNIV_INLINE
  335. void
  336. page_zip_write_header(
  337. /*==================*/
  338. page_zip_des_t* page_zip,/*!< in/out: compressed page */
  339. const byte* str, /*!< in: address on the uncompressed page */
  340. ulint length, /*!< in: length of the data */
  341. mtr_t* mtr) /*!< in: mini-transaction, or NULL */
  342. __attribute__((nonnull(1,2)));
  343. /**********************************************************************//**
  344. Reorganize and compress a page. This is a low-level operation for
  345. compressed pages, to be used when page_zip_compress() fails.
  346. On success, a redo log entry MLOG_ZIP_PAGE_COMPRESS will be written.
  347. The function btr_page_reorganize() should be preferred whenever possible.
  348. IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a
  349. non-clustered index, the caller must update the insert buffer free
  350. bits in the same mini-transaction in such a way that the modification
  351. will be redo-logged.
  352. @return TRUE on success, FALSE on failure; page and page_zip will be
  353. left intact on failure. */
  354. UNIV_INTERN
  355. ibool
  356. page_zip_reorganize(
  357. /*================*/
  358. buf_block_t* block, /*!< in/out: page with compressed page;
  359. on the compressed page, in: size;
  360. out: data, n_blobs,
  361. m_start, m_end, m_nonempty */
  362. dict_index_t* index, /*!< in: index of the B-tree node */
  363. mtr_t* mtr) /*!< in: mini-transaction */
  364. __attribute__((nonnull));
  365. #ifndef UNIV_HOTBACKUP
  366. /**********************************************************************//**
  367. Copy the records of a page byte for byte. Do not copy the page header
  368. or trailer, except those B-tree header fields that are directly
  369. related to the storage of records. Also copy PAGE_MAX_TRX_ID.
  370. NOTE: The caller must update the lock table and the adaptive hash index. */
  371. UNIV_INTERN
  372. void
  373. page_zip_copy_recs(
  374. /*===============*/
  375. page_zip_des_t* page_zip, /*!< out: copy of src_zip
  376. (n_blobs, m_start, m_end,
  377. m_nonempty, data[0..size-1]) */
  378. page_t* page, /*!< out: copy of src */
  379. const page_zip_des_t* src_zip, /*!< in: compressed page */
  380. const page_t* src, /*!< in: page */
  381. dict_index_t* index, /*!< in: index of the B-tree */
  382. mtr_t* mtr) /*!< in: mini-transaction */
  383. __attribute__((nonnull(1,2,3,4)));
  384. #endif /* !UNIV_HOTBACKUP */
  385. /**********************************************************************//**
  386. Parses a log record of compressing an index page.
  387. @return end of log record or NULL */
  388. UNIV_INTERN
  389. byte*
  390. page_zip_parse_compress(
  391. /*====================*/
  392. byte* ptr, /*!< in: buffer */
  393. byte* end_ptr,/*!< in: buffer end */
  394. page_t* page, /*!< out: uncompressed page */
  395. page_zip_des_t* page_zip)/*!< out: compressed page */
  396. __attribute__((nonnull(1,2)));
  397. /**********************************************************************//**
  398. Calculate the compressed page checksum.
  399. @return page checksum */
  400. UNIV_INTERN
  401. ulint
  402. page_zip_calc_checksum(
  403. /*===================*/
  404. const void* data, /*!< in: compressed page */
  405. ulint size) /*!< in: size of compressed page */
  406. __attribute__((nonnull));
  407. #ifndef UNIV_HOTBACKUP
  408. /** Check if a pointer to an uncompressed page matches a compressed page.
  409. @param ptr pointer to an uncompressed page frame
  410. @param page_zip compressed page descriptor
  411. @return TRUE if ptr and page_zip refer to the same block */
  412. # define PAGE_ZIP_MATCH(ptr, page_zip) \
  413. (buf_frame_get_page_zip(ptr) == (page_zip))
  414. #else /* !UNIV_HOTBACKUP */
  415. /** Check if a pointer to an uncompressed page matches a compressed page.
  416. @param ptr pointer to an uncompressed page frame
  417. @param page_zip compressed page descriptor
  418. @return TRUE if ptr and page_zip refer to the same block */
  419. # define PAGE_ZIP_MATCH(ptr, page_zip) \
  420. (page_align(ptr) + UNIV_PAGE_SIZE == (page_zip)->data)
  421. #endif /* !UNIV_HOTBACKUP */
  422. #ifdef UNIV_MATERIALIZE
  423. # undef UNIV_INLINE
  424. # define UNIV_INLINE UNIV_INLINE_ORIGINAL
  425. #endif
  426. #ifndef UNIV_NONINL
  427. # include "page0zip.ic"
  428. #endif
  429. #endif /* page0zip_h */