From 06eaf7232e9a920468c0f8d74dcf2fe8b555501c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 14:24:36 +0200 Subject: Adding upstream version 1:10.11.6. Signed-off-by: Daniel Baumann --- storage/maria/ma_backup.c | 278 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 storage/maria/ma_backup.c (limited to 'storage/maria/ma_backup.c') diff --git a/storage/maria/ma_backup.c b/storage/maria/ma_backup.c new file mode 100644 index 00000000..0384dfb4 --- /dev/null +++ b/storage/maria/ma_backup.c @@ -0,0 +1,278 @@ +/* Copyright (C) 2018, 2020 MariaDB Corporation Ab + + 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 02111-1301 USA */ + +/* Code for doing backups of Aria tables */ + +#include "maria_def.h" +#include "ma_blockrec.h" /* PAGE_SUFFIX_SIZE */ +#include "ma_checkpoint.h" +#include + +/** + @brief Get capabilities for an Aria table + + @param kfile key file (.MAI) + @param cap Capabilities are stored here + + @return 0 ok + @return X errno +*/ + +int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap)__attribute__((visibility("default"))) ; +int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap) +{ + MARIA_SHARE share; + int error= 0; + uint head_length= sizeof(share.state.header), base_pos; + uint aligned_bit_blocks; + size_t info_length; + uchar *disc_cache; + DBUG_ENTER("aria_get_capabilities"); + + bzero(cap, sizeof(*cap)); + if (my_pread(kfile,share.state.header.file_version, head_length, 0, + MYF(MY_NABP))) + DBUG_RETURN(HA_ERR_NOT_A_TABLE); + + if (memcmp(share.state.header.file_version, maria_file_magic, 4)) + DBUG_RETURN(HA_ERR_NOT_A_TABLE); + + share.options= mi_uint2korr(share.state.header.options); + + info_length= mi_uint2korr(share.state.header.header_length); + base_pos= mi_uint2korr(share.state.header.base_pos); + + /* + Allocate space for header information and for data that is too + big to keep on stack + */ + if (!(disc_cache= my_malloc(PSI_NOT_INSTRUMENTED, info_length, MYF(MY_WME)))) + DBUG_RETURN(ENOMEM); + + if (my_pread(kfile, disc_cache, info_length, 0L, MYF(MY_NABP))) + { + error= my_errno; + goto err; + } + _ma_base_info_read(disc_cache + base_pos, &share.base); + cap->transactional= share.base.born_transactional; + cap->checksum= MY_TEST(share.options & HA_OPTION_PAGE_CHECKSUM); + cap->online_backup_safe= cap->transactional && cap->checksum; + cap->header_size= share.base.keystart; + cap->keypage_header= ((share.base.born_transactional ? + LSN_STORE_SIZE + TRANSID_SIZE : + 0) + KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE + + KEYPAGE_USED_SIZE); + cap->block_size= share.base.block_size; + cap->data_file_type= share.state.header.data_file_type; + cap->s3_block_size= share.base.s3_block_size; + cap->compression= share.base.compression_algorithm; + cap->encrypted= MY_TEST(share.base.extra_options & + MA_EXTRA_OPTIONS_ENCRYPTED); + + if (share.state.header.data_file_type == BLOCK_RECORD) + { + /* Calulate how man pages the row bitmap covers. From _ma_bitmap_init() */ + aligned_bit_blocks= (cap->block_size - PAGE_SUFFIX_SIZE) / 6; + /* + In each 6 bytes, we have 6*8/3 = 16 pages covered + The +1 is to add the bitmap page, as this doesn't have to be covered + */ + cap->bitmap_pages_covered= aligned_bit_blocks * 16 + 1; + } + + /* Do a check that that we got things right */ + if (share.state.header.data_file_type != BLOCK_RECORD && + cap->online_backup_safe) + error= HA_ERR_NOT_A_TABLE; + +err: + my_free(disc_cache); + DBUG_RETURN(error); +} /* aria_get_capabilities */ + +/**************************************************************************** +** store MARIA_BASE_INFO +****************************************************************************/ + +uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base) +{ + bmove(base->uuid, ptr, MY_UUID_SIZE); ptr+= MY_UUID_SIZE; + base->keystart= mi_sizekorr(ptr); ptr+= 8; + base->max_data_file_length= mi_sizekorr(ptr); ptr+= 8; + base->max_key_file_length= mi_sizekorr(ptr); ptr+= 8; + base->records= (ha_rows) mi_sizekorr(ptr); ptr+= 8; + base->reloc= (ha_rows) mi_sizekorr(ptr); ptr+= 8; + base->mean_row_length= mi_uint4korr(ptr); ptr+= 4; + base->reclength= mi_uint4korr(ptr); ptr+= 4; + base->pack_reclength= mi_uint4korr(ptr); ptr+= 4; + base->min_pack_length= mi_uint4korr(ptr); ptr+= 4; + base->max_pack_length= mi_uint4korr(ptr); ptr+= 4; + base->min_block_length= mi_uint4korr(ptr); ptr+= 4; + base->fields= mi_uint2korr(ptr); ptr+= 2; + base->fixed_not_null_fields= mi_uint2korr(ptr); ptr+= 2; + base->fixed_not_null_fields_length= mi_uint2korr(ptr);ptr+= 2; + base->max_field_lengths= mi_uint2korr(ptr); ptr+= 2; + base->pack_fields= mi_uint2korr(ptr); ptr+= 2; + base->extra_options= mi_uint2korr(ptr); ptr+= 2; + base->null_bytes= mi_uint2korr(ptr); ptr+= 2; + base->original_null_bytes= mi_uint2korr(ptr); ptr+= 2; + base->field_offsets= mi_uint2korr(ptr); ptr+= 2; + base->language= mi_uint2korr(ptr); ptr+= 2; + base->block_size= mi_uint2korr(ptr); ptr+= 2; + + base->rec_reflength= *ptr++; + base->key_reflength= *ptr++; + base->keys= *ptr++; + base->auto_key= *ptr++; + base->born_transactional= *ptr++; + base->compression_algorithm= *ptr++; + base->pack_bytes= mi_uint2korr(ptr); ptr+= 2; + base->blobs= mi_uint2korr(ptr); ptr+= 2; + base->max_key_block_length= mi_uint2korr(ptr); ptr+= 2; + base->max_key_length= mi_uint2korr(ptr); ptr+= 2; + base->extra_alloc_bytes= mi_uint2korr(ptr); ptr+= 2; + base->extra_alloc_procent= *ptr++; + base->s3_block_size= mi_uint3korr(ptr); ptr+= 3; + ptr+= 13; + return ptr; +} + + +/** + @brief Copy an index block with re-read if checksum doesn't match + + @param dfile data file (.MAD) + @param cap aria capabilities from aria_get_capabilities + @param block block number to read (0, 1, 2, 3...) + @param buffer read data to this buffer + @param bytes_read number of bytes actually read (in case of end of file) + + @return 0 ok + @return HA_ERR_END_OF_FILE ; End of file + @return # error number +*/ + +#define MAX_RETRY 10 + +int aria_read_index(File kfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block, + uchar *buffer) +{ + MARIA_SHARE share; + int retry= 0; + DBUG_ENTER("aria_read_index"); + + share.keypage_header= cap->keypage_header; + share.block_size= cap->block_size; + do + { + int error; + size_t length; + if ((length= my_pread(kfile, buffer, cap->block_size, + block * cap->block_size, MYF(0))) != cap->block_size) + { + if (length == 0) + DBUG_RETURN(HA_ERR_END_OF_FILE); + if (length == (size_t) -1) + DBUG_RETURN(my_errno ? my_errno : -1); + /* Assume we got a half read; Do a re-read */ + } + /* If not transactional or key file header, there are no checksums */ + if (!cap->online_backup_safe || + block < cap->header_size/ cap->block_size) + DBUG_RETURN(length == cap->block_size ? 0 : HA_ERR_CRASHED); + + if (length == cap->block_size) + { + length= _ma_get_page_used(&share, buffer); + if (length > cap->block_size - CRC_SIZE) + DBUG_RETURN(HA_ERR_CRASHED); + error= maria_page_crc_check(buffer, block, &share, + MARIA_NO_CRC_NORMAL_PAGE, + (int) length); + if (error != HA_ERR_WRONG_CRC) + DBUG_RETURN(error); + } + my_sleep(100000); /* Sleep 0.1 seconds */ + } while (retry < MAX_RETRY); + DBUG_RETURN(HA_ERR_WRONG_CRC); +} + + +/** + @brief Copy a data block with re-read if checksum doesn't match + + @param dfile data file (.MAD) + @param cap aria capabilities from aria_get_capabilities + @param block block number to read (0, 1, 2, 3...) + @param buffer read data to this buffer + @param bytes_read number of bytes actually read (in case of end of file) + + @return 0 ok + @return HA_ERR_END_OF_FILE ; End of file + @return # error number +*/ + +int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block, + uchar *buffer, size_t *bytes_read) +{ + MARIA_SHARE share; + int retry= 0; + DBUG_ENTER("aria_read_data"); + + share.keypage_header= cap->keypage_header; + share.block_size= cap->block_size; + + if (!cap->online_backup_safe) + { + *bytes_read= my_pread(dfile, buffer, cap->block_size, + block * cap->block_size, MY_WME); + if (*bytes_read == 0) + DBUG_RETURN(HA_ERR_END_OF_FILE); + DBUG_RETURN(*bytes_read > 0 ? 0 : (my_errno ? my_errno : -1)); + } + + *bytes_read= cap->block_size; + do + { + int error; + size_t length; + if ((length= my_pread(dfile, buffer, cap->block_size, + block * cap->block_size, MYF(0))) != cap->block_size) + { + if (length == 0) + DBUG_RETURN(HA_ERR_END_OF_FILE); + if (length == (size_t) -1) + DBUG_RETURN(my_errno ? my_errno : -1); + } + + /* If not transactional or key file header, there are no checksums */ + if (!cap->online_backup_safe) + DBUG_RETURN(length == cap->block_size ? 0 : HA_ERR_CRASHED); + + if (length == cap->block_size) + { + error= maria_page_crc_check(buffer, block, &share, + ((block % cap->bitmap_pages_covered) == 0 ? + MARIA_NO_CRC_BITMAP_PAGE : + MARIA_NO_CRC_NORMAL_PAGE), + share.block_size - CRC_SIZE); + if (error != HA_ERR_WRONG_CRC) + DBUG_RETURN(error); + } + my_sleep(100000); /* Sleep 0.1 seconds */ + } while (retry < MAX_RETRY); + DBUG_RETURN(HA_ERR_WRONG_CRC); +} -- cgit v1.2.3