diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
commit | 3f619478f796eddbba6e39502fe941b285dd97b1 (patch) | |
tree | e2c7b5777f728320e5b5542b6213fd3591ba51e2 /storage/innobase/include/page0zip.h | |
parent | Initial commit. (diff) | |
download | mariadb-upstream.tar.xz mariadb-upstream.zip |
Adding upstream version 1:10.11.6.upstream/1%10.11.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | storage/innobase/include/page0zip.h | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h new file mode 100644 index 00000000..43329906 --- /dev/null +++ b/storage/innobase/include/page0zip.h @@ -0,0 +1,383 @@ +/***************************************************************************** + +Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, 2022, MariaDB Corporation. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +/**************************************************//** +@file include/page0zip.h +Compressed page interface + +Created June 2005 by Marko Makela +*******************************************************/ + +#ifndef page0zip_h +#define page0zip_h + +#include "buf0types.h" + +#ifndef UNIV_INNOCHECKSUM +#include "mtr0types.h" +#include "page0types.h" +#include "dict0types.h" +#include "srv0srv.h" +#include "trx0types.h" +#include "mem0mem.h" + +/* Compression level to be used by zlib. Settable by user. */ +extern uint page_zip_level; + +/* Default compression level. */ +#define DEFAULT_COMPRESSION_LEVEL 6 +/** Start offset of the area that will be compressed */ +#define PAGE_ZIP_START PAGE_NEW_SUPREMUM_END +/** Size of an compressed page directory entry */ +#define PAGE_ZIP_DIR_SLOT_SIZE 2 +/** Predefine the sum of DIR_SLOT, TRX_ID & ROLL_PTR */ +#define PAGE_ZIP_CLUST_LEAF_SLOT_SIZE \ + (PAGE_ZIP_DIR_SLOT_SIZE \ + + DATA_TRX_ID_LEN \ + + DATA_ROLL_PTR_LEN) +/** Mask of record offsets */ +#define PAGE_ZIP_DIR_SLOT_MASK 0x3fffU +/** 'owned' flag */ +#define PAGE_ZIP_DIR_SLOT_OWNED 0x4000U +/** 'deleted' flag */ +#define PAGE_ZIP_DIR_SLOT_DEL 0x8000U + +/**********************************************************************//** +Determine the size of a compressed page in bytes. +@return size in bytes */ +UNIV_INLINE +ulint +page_zip_get_size( +/*==============*/ + const page_zip_des_t* page_zip) /*!< in: compressed page */ + MY_ATTRIBUTE((warn_unused_result)); +/**********************************************************************//** +Set the size of a compressed page in bytes. */ +UNIV_INLINE +void +page_zip_set_size( +/*==============*/ + page_zip_des_t* page_zip, /*!< in/out: compressed page */ + ulint size); /*!< in: size in bytes */ + +/** Determine if a record is so big that it needs to be stored externally. +@param[in] rec_size length of the record in bytes +@param[in] comp nonzero=compact format +@param[in] n_fields number of fields in the record; ignored if +tablespace is not compressed +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@return false if the entire record can be stored locally on the page */ +inline bool page_zip_rec_needs_ext(ulint rec_size, ulint comp, ulint n_fields, + ulint zip_size) + MY_ATTRIBUTE((warn_unused_result)); + +/**********************************************************************//** +Determine the guaranteed free space on an empty page. +@return minimum payload size on the page */ +ulint +page_zip_empty_size( +/*================*/ + ulint n_fields, /*!< in: number of columns in the index */ + ulint zip_size) /*!< in: compressed page size in bytes */ + MY_ATTRIBUTE((const)); + +/** Check whether a tuple is too big for compressed table +@param[in] index dict index object +@param[in] entry entry for the index +@return true if it's too big, otherwise false */ +bool +page_zip_is_too_big( + const dict_index_t* index, + const dtuple_t* entry); + +/**********************************************************************//** +Initialize a compressed page descriptor. */ +#define page_zip_des_init(page_zip) (page_zip)->clear() + +/**********************************************************************//** +Configure the zlib allocator to use the given memory heap. */ +void +page_zip_set_alloc( +/*===============*/ + void* stream, /*!< in/out: zlib stream */ + mem_heap_t* heap); /*!< in: memory heap to use */ + +/** Attempt to compress a ROW_FORMAT=COMPRESSED page. +@retval true on success +@retval false on failure; block->page.zip will be left intact. */ +bool +page_zip_compress( + buf_block_t* block, /*!< in/out: buffer block */ + dict_index_t* index, /*!< in: index of the B-tree node */ + ulint level, /*!< in: commpression level */ + mtr_t* mtr) /*!< in/out: mini-transaction */ + MY_ATTRIBUTE((nonnull)); + +/**********************************************************************//** +Write the index information for the compressed page. +@return used size of buf */ +ulint +page_zip_fields_encode( +/*===================*/ + ulint n, /*!< in: number of fields + to compress */ + const dict_index_t* index, /*!< in: index comprising + at least n fields */ + ulint trx_id_pos, + /*!< in: position of the trx_id column + in the index, or ULINT_UNDEFINED if + this is a non-leaf page */ + byte* buf); /*!< out: buffer of (n + 1) * 2 bytes */ + +/**********************************************************************//** +Decompress a page. This function should tolerate errors on the compressed +page. Instead of letting assertions fail, it will return FALSE if an +inconsistency is detected. +@return TRUE on success, FALSE on failure */ +ibool +page_zip_decompress( +/*================*/ + page_zip_des_t* page_zip,/*!< in: data, ssize; + out: m_start, m_end, m_nonempty, n_blobs */ + page_t* page, /*!< out: uncompressed page, may be trashed */ + ibool all) /*!< in: TRUE=decompress the whole page; + FALSE=verify but do not copy some + page header fields that should not change + after page creation */ + MY_ATTRIBUTE((nonnull(1,2))); + +#ifdef UNIV_DEBUG +/**********************************************************************//** +Validate a compressed page descriptor. +@return TRUE if ok */ +UNIV_INLINE +ibool +page_zip_simple_validate( +/*=====================*/ + const page_zip_des_t* page_zip); /*!< in: compressed page + descriptor */ +#endif /* UNIV_DEBUG */ + +#ifdef UNIV_ZIP_DEBUG +/**********************************************************************//** +Check that the compressed and decompressed pages match. +@return TRUE if valid, FALSE if not */ +ibool +page_zip_validate_low( +/*==================*/ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + const page_t* page, /*!< in: uncompressed page */ + const dict_index_t* index, /*!< in: index of the page, if known */ + ibool sloppy) /*!< in: FALSE=strict, + TRUE=ignore the MIN_REC_FLAG */ + MY_ATTRIBUTE((nonnull(1,2))); +/**********************************************************************//** +Check that the compressed and decompressed pages match. */ +ibool +page_zip_validate( +/*==============*/ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + const page_t* page, /*!< in: uncompressed page */ + const dict_index_t* index) /*!< in: index of the page, if known */ + MY_ATTRIBUTE((nonnull(1,2))); +#endif /* UNIV_ZIP_DEBUG */ + +/**********************************************************************//** +Determine how big record can be inserted without recompressing the page. +@return a positive number indicating the maximum size of a record +whose insertion is guaranteed to succeed, or zero or negative */ +UNIV_INLINE +lint +page_zip_max_ins_size( +/*==================*/ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + ibool is_clust)/*!< in: TRUE if clustered index */ + MY_ATTRIBUTE((warn_unused_result)); + +/**********************************************************************//** +Determine if enough space is available in the modification log. +@return TRUE if page_zip_write_rec() will succeed */ +UNIV_INLINE +ibool +page_zip_available( +/*===============*/ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + ibool is_clust,/*!< in: TRUE if clustered index */ + ulint length, /*!< in: combined size of the record */ + ulint create) /*!< in: nonzero=add the record to + the heap */ + MY_ATTRIBUTE((warn_unused_result)); + +/** Write an entire record to the ROW_FORMAT=COMPRESSED page. +The data must already have been written to the uncompressed page. +@param[in,out] block ROW_FORMAT=COMPRESSED page +@param[in] rec record in the uncompressed page +@param[in] index the index that the page belongs to +@param[in] offsets rec_get_offsets(rec, index) +@param[in] create nonzero=insert, zero=update +@param[in,out] mtr mini-transaction */ +void page_zip_write_rec(buf_block_t *block, const byte *rec, + const dict_index_t *index, const rec_offs *offsets, + ulint create, mtr_t *mtr) + MY_ATTRIBUTE((nonnull)); + +/**********************************************************************//** +Write a BLOB pointer of a record on the leaf page of a clustered index. +The information must already have been updated on the uncompressed page. */ +void +page_zip_write_blob_ptr( +/*====================*/ + buf_block_t* block, /*!< in/out: ROW_FORMAT=COMPRESSED page */ + const byte* rec, /*!< in/out: record whose data is being + written */ + dict_index_t* index, /*!< in: index of the page */ + const rec_offs* offsets,/*!< in: rec_get_offsets(rec, index) */ + ulint n, /*!< in: column index */ + mtr_t* mtr) /*!< in/out: mini-transaction */ + MY_ATTRIBUTE((nonnull)); + +/**********************************************************************//** +Write the node pointer of a record on a non-leaf compressed page. */ +void +page_zip_write_node_ptr( +/*====================*/ + buf_block_t* block, /*!< in/out: compressed page */ + byte* rec, /*!< in/out: record */ + ulint size, /*!< in: data size of rec */ + ulint ptr, /*!< in: node pointer */ + mtr_t* mtr) /*!< in/out: mini-transaction */ + MY_ATTRIBUTE((nonnull)); + +/** Write the DB_TRX_ID,DB_ROLL_PTR into a clustered index leaf page record. +@param[in,out] block ROW_FORMAT=COMPRESSED page +@param[in,out] rec record +@param[in] offsets rec_get_offsets(rec, index) +@param[in] trx_id_field field number of DB_TRX_ID (number of PK fields) +@param[in] trx_id DB_TRX_ID value (transaction identifier) +@param[in] roll_ptr DB_ROLL_PTR value (undo log pointer) +@param[in,out] mtr mini-transaction */ +void +page_zip_write_trx_id_and_roll_ptr( + buf_block_t* block, + byte* rec, + const rec_offs* offsets, + ulint trx_id_col, + trx_id_t trx_id, + roll_ptr_t roll_ptr, + mtr_t* mtr) + MY_ATTRIBUTE((nonnull)); + +/** Modify the delete-mark flag of a ROW_FORMAT=COMPRESSED record. +@param[in,out] block buffer block +@param[in,out] rec record on a physical index page +@param[in] flag the value of the delete-mark flag +@param[in,out] mtr mini-transaction */ +void page_zip_rec_set_deleted(buf_block_t *block, rec_t *rec, bool flag, + mtr_t *mtr) + MY_ATTRIBUTE((nonnull)); + +/**********************************************************************//** +Insert a record to the dense page directory. */ +void +page_zip_dir_insert( +/*================*/ + page_cur_t* cursor, /*!< in/out: page cursor */ + uint16_t free_rec,/*!< in: record from which rec was + allocated, or 0 */ + byte* rec, /*!< in: record to insert */ + mtr_t* mtr) /*!< in/out: mini-transaction */ + MY_ATTRIBUTE((nonnull(1,3,4))); + +/** Shift the dense page directory and the array of BLOB pointers +when a record is deleted. +@param[in,out] block index page +@param[in,out] rec record being deleted +@param[in] index the index that the page belongs to +@param[in] offsets rec_get_offsets(rec, index) +@param[in] free previous start of the free list +@param[in,out] mtr mini-transaction */ +void page_zip_dir_delete(buf_block_t *block, byte *rec, + const dict_index_t *index, const rec_offs *offsets, + const byte *free, mtr_t *mtr) + MY_ATTRIBUTE((nonnull(1,2,3,4,6))); + +/**********************************************************************//** +Reorganize and compress a page. This is a low-level operation for +compressed pages, to be used when page_zip_compress() fails. +On success, redo log will be written. +The function btr_page_reorganize() should be preferred whenever possible. +IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a +non-clustered index, the caller must update the insert buffer free +bits in the same mini-transaction in such a way that the modification +will be redo-logged. +@return error code +@retval DB_FAIL on overflow; the block_zip will be left intact */ +dberr_t +page_zip_reorganize( + buf_block_t* block, /*!< in/out: page with compressed page; + on the compressed page, in: size; + out: data, n_blobs, + m_start, m_end, m_nonempty */ + dict_index_t* index, /*!< in: index of the B-tree node */ + ulint z_level,/*!< in: compression level */ + mtr_t* mtr, /*!< in: mini-transaction */ + bool restore = false)/*!< whether to restore on failure */ + MY_ATTRIBUTE((nonnull, warn_unused_result)); + +/**********************************************************************//** +Copy the records of a page byte for byte. Do not copy the page header +or trailer, except those B-tree header fields that are directly +related to the storage of records. Also copy PAGE_MAX_TRX_ID. +NOTE: The caller must update the lock table and the adaptive hash index. */ +void +page_zip_copy_recs( + buf_block_t* block, /*!< in/out: buffer block */ + const page_zip_des_t* src_zip, /*!< in: compressed page */ + const page_t* src, /*!< in: page */ + dict_index_t* index, /*!< in: index of the B-tree */ + mtr_t* mtr); /*!< in: mini-transaction */ +#endif /* !UNIV_INNOCHECKSUM */ + +/** Calculate the compressed page checksum. +@param data compressed page +@param size size of compressed page +@param use_adler whether to use Adler32 instead of a XOR of 3 CRC-32C +@return page checksum */ +uint32_t page_zip_calc_checksum(const void *data, size_t size, bool use_adler); + +/** Validate the checksum on a ROW_FORMAT=COMPRESSED page. +@param data ROW_FORMAT=COMPRESSED page +@param size size of the page, in bytes +@return whether the stored checksum matches innodb_checksum_algorithm */ +bool page_zip_verify_checksum(const byte *data, size_t size); + +#ifndef UNIV_INNOCHECKSUM +/**********************************************************************//** +Reset the counters used for filling +INFORMATION_SCHEMA.innodb_cmp_per_index. */ +UNIV_INLINE +void +page_zip_reset_stat_per_index(); +/*===========================*/ + +#include "page0zip.inl" +#endif /* !UNIV_INNOCHECKSUM */ + +#endif /* page0zip_h */ |