summaryrefslogtreecommitdiffstats
path: root/extra/mariabackup/changed_page_bitmap.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 13:22:53 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 13:22:53 +0000
commit347c164c35eddab388009470e6848cb361ac93f8 (patch)
tree2c0c44eac690f510bb0a35b2a13b36d606b77b6b /extra/mariabackup/changed_page_bitmap.cc
parentReleasing progress-linux version 1:10.11.7-4~progress7.99u1. (diff)
downloadmariadb-347c164c35eddab388009470e6848cb361ac93f8.tar.xz
mariadb-347c164c35eddab388009470e6848cb361ac93f8.zip
Merging upstream version 1:10.11.8.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'extra/mariabackup/changed_page_bitmap.cc')
-rw-r--r--extra/mariabackup/changed_page_bitmap.cc1040
1 files changed, 0 insertions, 1040 deletions
diff --git a/extra/mariabackup/changed_page_bitmap.cc b/extra/mariabackup/changed_page_bitmap.cc
deleted file mode 100644
index 39a07a25..00000000
--- a/extra/mariabackup/changed_page_bitmap.cc
+++ /dev/null
@@ -1,1040 +0,0 @@
-/******************************************************
-XtraBackup: hot backup tool for InnoDB
-(c) 2009-2012 Percona Inc.
-Originally Created 3/3/2009 Yasufumi Kinoshita
-Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
-Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
-
-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
-
-*******************************************************/
-
-/* Changed page bitmap implementation */
-
-#include "changed_page_bitmap.h"
-
-#include "common.h"
-#include "xtrabackup.h"
-#include "srv0srv.h"
-
-/* TODO: copy-pasted shared definitions from the XtraDB bitmap write code.
-Remove these on the first opportunity, i.e. single-binary XtraBackup. */
-
-/* log0online.h */
-
-/** Single bitmap file information */
-struct log_online_bitmap_file_t {
- char name[FN_REFLEN]; /*!< Name with full path */
- pfs_os_file_t file; /*!< Handle to opened file */
- ib_uint64_t size; /*!< Size of the file */
- ib_uint64_t offset; /*!< Offset of the next read,
- or count of already-read bytes
- */
-};
-
-/** A set of bitmap files containing some LSN range */
-struct log_online_bitmap_file_range_t {
- size_t count; /*!< Number of files */
- /*!< Dynamically-allocated array of info about individual files */
- struct files_t {
- char name[FN_REFLEN];/*!< Name of a file */
- lsn_t start_lsn; /*!< Starting LSN of data in this
- file */
- ulong seq_num; /*!< Sequence number of this file */
- } *files;
-};
-
-/* log0online.c */
-
-/** File name stem for bitmap files. */
-static const char* bmp_file_name_stem = "ib_modified_log_";
-
-/** The bitmap file block size in bytes. All writes will be multiples of this.
- */
-enum {
- MODIFIED_PAGE_BLOCK_SIZE = 4096
-};
-
-/** Offsets in a file bitmap block */
-enum {
- MODIFIED_PAGE_IS_LAST_BLOCK = 0,/* 1 if last block in the current
- write, 0 otherwise. */
- MODIFIED_PAGE_START_LSN = 4, /* The starting tracked LSN of this and
- other blocks in the same write */
- MODIFIED_PAGE_END_LSN = 12, /* The ending tracked LSN of this and
- other blocks in the same write */
- MODIFIED_PAGE_SPACE_ID = 20, /* The space ID of tracked pages in
- this block */
- MODIFIED_PAGE_1ST_PAGE_ID = 24, /* The page ID of the first tracked
- page in this block */
- MODIFIED_PAGE_BLOCK_UNUSED_1 = 28,/* Unused in order to align the start
- of bitmap at 8 byte boundary */
- MODIFIED_PAGE_BLOCK_BITMAP = 32,/* Start of the bitmap itself */
- MODIFIED_PAGE_BLOCK_UNUSED_2 = MODIFIED_PAGE_BLOCK_SIZE - 8,
- /* Unused in order to align the end of
- bitmap at 8 byte boundary */
- MODIFIED_PAGE_BLOCK_CHECKSUM = MODIFIED_PAGE_BLOCK_SIZE - 4
- /* The checksum of the current block */
-};
-
-/** Length of the bitmap data in a block */
-enum { MODIFIED_PAGE_BLOCK_BITMAP_LEN
- = MODIFIED_PAGE_BLOCK_UNUSED_2 - MODIFIED_PAGE_BLOCK_BITMAP };
-
-/** Length of the bitmap data in a block in page ids */
-enum { MODIFIED_PAGE_BLOCK_ID_COUNT = MODIFIED_PAGE_BLOCK_BITMAP_LEN * 8 };
-
-typedef ib_uint64_t bitmap_word_t;
-
-/****************************************************************//**
-Calculate a bitmap block checksum. Algorithm borrowed from
-log_block_calc_checksum.
-@return checksum */
-UNIV_INLINE
-ulint
-log_online_calc_checksum(
-/*=====================*/
- const byte* block); /*!<in: bitmap block */
-
-/****************************************************************//**
-Provide a comparisson function for the RB-tree tree (space,
-block_start_page) pairs. Actual implementation does not matter as
-long as the ordering is full.
-@return -1 if p1 < p2, 0 if p1 == p2, 1 if p1 > p2
-*/
-static
-int
-log_online_compare_bmp_keys(
-/*========================*/
- const void* p1, /*!<in: 1st key to compare */
- const void* p2) /*!<in: 2nd key to compare */
-{
- const byte *k1 = (const byte *)p1;
- const byte *k2 = (const byte *)p2;
-
- ulint k1_space = mach_read_from_4(k1 + MODIFIED_PAGE_SPACE_ID);
- ulint k2_space = mach_read_from_4(k2 + MODIFIED_PAGE_SPACE_ID);
- if (k1_space == k2_space) {
-
- ulint k1_start_page
- = mach_read_from_4(k1 + MODIFIED_PAGE_1ST_PAGE_ID);
- ulint k2_start_page
- = mach_read_from_4(k2 + MODIFIED_PAGE_1ST_PAGE_ID);
- return k1_start_page < k2_start_page
- ? -1 : k1_start_page > k2_start_page ? 1 : 0;
- }
- return k1_space < k2_space ? -1 : 1;
-}
-
-/****************************************************************//**
-Calculate a bitmap block checksum. Algorithm borrowed from
-log_block_calc_checksum.
-@return checksum */
-UNIV_INLINE
-ulint
-log_online_calc_checksum(
-/*=====================*/
- const byte* block) /*!<in: bitmap block */
-{
- ulint sum;
- ulint sh;
- ulint i;
-
- sum = 1;
- sh = 0;
-
- for (i = 0; i < MODIFIED_PAGE_BLOCK_CHECKSUM; i++) {
-
- ulint b = block[i];
- sum &= 0x7FFFFFFFUL;
- sum += b;
- sum += b << sh;
- sh++;
- if (sh > 24) {
-
- sh = 0;
- }
- }
-
- return sum;
-}
-
-/****************************************************************//**
-Read one bitmap data page and check it for corruption.
-
-@return TRUE if page read OK, FALSE if I/O error */
-static
-ibool
-log_online_read_bitmap_page(
-/*========================*/
- log_online_bitmap_file_t *bitmap_file, /*!<in/out: bitmap
- file */
- byte *page, /*!<out: read page. Must be at
- least MODIFIED_PAGE_BLOCK_SIZE
- bytes long */
- ibool *checksum_ok) /*!<out: TRUE if page
- checksum OK */
-{
- ulint checksum;
- ulint actual_checksum;
-
- ut_a(bitmap_file->size >= MODIFIED_PAGE_BLOCK_SIZE);
- ut_a(bitmap_file->offset
- <= bitmap_file->size - MODIFIED_PAGE_BLOCK_SIZE);
- ut_a(bitmap_file->offset % MODIFIED_PAGE_BLOCK_SIZE == 0);
- if (DB_SUCCESS !=
- os_file_read(IORequestRead, bitmap_file->file, page,
- bitmap_file->offset, MODIFIED_PAGE_BLOCK_SIZE,
- nullptr)) {
- /* The following call prints an error message */
- os_file_get_last_error(TRUE);
- msg("InnoDB: Warning: failed reading changed page bitmap "
- "file \'%s\'", bitmap_file->name);
- return FALSE;
- }
-
- bitmap_file->offset += MODIFIED_PAGE_BLOCK_SIZE;
- ut_ad(bitmap_file->offset <= bitmap_file->size);
-
- checksum = mach_read_from_4(page + MODIFIED_PAGE_BLOCK_CHECKSUM);
- actual_checksum = log_online_calc_checksum(page);
- *checksum_ok = (checksum == actual_checksum);
-
- return TRUE;
-}
-
-/*********************************************************************//**
-Check the name of a given file if it's a changed page bitmap file and
-return file sequence and start LSN name components if it is. If is not,
-the values of output parameters are undefined.
-
-@return TRUE if a given file is a changed page bitmap file. */
-static
-ibool
-log_online_is_bitmap_file(
-/*======================*/
- const os_file_stat_t* file_info, /*!<in: file to
- check */
- ulong* bitmap_file_seq_num, /*!<out: bitmap file
- sequence number */
- lsn_t* bitmap_file_start_lsn) /*!<out: bitmap file
- start LSN */
-{
- char stem[FN_REFLEN];
-
- ut_ad (strlen(file_info->name) < OS_FILE_MAX_PATH);
-
- return ((file_info->type == OS_FILE_TYPE_FILE
- || file_info->type == OS_FILE_TYPE_LINK)
- && (sscanf(file_info->name, "%[a-z_]%lu_" LSN_PF ".xdb", stem,
- bitmap_file_seq_num, bitmap_file_start_lsn) == 3)
- && (!strcmp(stem, bmp_file_name_stem)));
-}
-
-/*********************************************************************//**
-List the bitmap files in srv_data_home and setup their range that contains the
-specified LSN interval. This range, if non-empty, will start with a file that
-has the greatest LSN equal to or less than the start LSN and will include all
-the files up to the one with the greatest LSN less than the end LSN. Caller
-must free bitmap_files->files when done if bitmap_files set to non-NULL and
-this function returned TRUE. Field bitmap_files->count might be set to a
-larger value than the actual count of the files, and space for the unused array
-slots will be allocated but cleared to zeroes.
-
-@return TRUE if succeeded
-*/
-static
-ibool
-log_online_setup_bitmap_file_range(
-/*===============================*/
- log_online_bitmap_file_range_t *bitmap_files, /*!<in/out: bitmap file
- range */
- lsn_t range_start, /*!<in: start LSN */
- lsn_t range_end) /*!<in: end LSN */
-{
- os_file_dir_t bitmap_dir;
- os_file_stat_t bitmap_dir_file_info;
- ulong first_file_seq_num = ULONG_MAX;
- ulong last_file_seq_num = 0;
- lsn_t first_file_start_lsn = LSN_MAX;
-
- xb_ad(range_end >= range_start);
-
- bitmap_files->count = 0;
- bitmap_files->files = NULL;
-
- /* 1st pass: size the info array */
-
- bitmap_dir = os_file_opendir(srv_data_home);
- if (UNIV_UNLIKELY(bitmap_dir == IF_WIN(INVALID_HANDLE_VALUE, NULL))) {
- msg("InnoDB: Error: failed to open bitmap directory \'%s\'",
- srv_data_home);
- return FALSE;
- }
-
- while (!os_file_readdir_next_file(srv_data_home, bitmap_dir,
- &bitmap_dir_file_info)) {
-
- ulong file_seq_num;
- lsn_t file_start_lsn;
-
- if (!log_online_is_bitmap_file(&bitmap_dir_file_info,
- &file_seq_num,
- &file_start_lsn)
- || file_start_lsn >= range_end) {
-
- continue;
- }
-
- if (file_seq_num > last_file_seq_num) {
-
- last_file_seq_num = file_seq_num;
- }
-
- if (file_start_lsn >= range_start
- || file_start_lsn == first_file_start_lsn
- || first_file_start_lsn > range_start) {
-
- /* A file that falls into the range */
-
- if (file_start_lsn < first_file_start_lsn) {
-
- first_file_start_lsn = file_start_lsn;
- }
- if (file_seq_num < first_file_seq_num) {
-
- first_file_seq_num = file_seq_num;
- }
- } else if (file_start_lsn > first_file_start_lsn) {
-
- /* A file that has LSN closer to the range start
- but smaller than it, replacing another such file */
- first_file_start_lsn = file_start_lsn;
- first_file_seq_num = file_seq_num;
- }
- }
-
- if (UNIV_UNLIKELY(os_file_closedir_failed(bitmap_dir))) {
- os_file_get_last_error(TRUE);
- msg("InnoDB: Error: cannot close \'%s\'",srv_data_home);
- return FALSE;
- }
-
- if (first_file_seq_num == ULONG_MAX && last_file_seq_num == 0) {
-
- bitmap_files->count = 0;
- return TRUE;
- }
-
- bitmap_files->count = last_file_seq_num - first_file_seq_num + 1;
-
- /* 2nd pass: get the file names in the file_seq_num order */
-
- bitmap_dir = os_file_opendir(srv_data_home);
- if (UNIV_UNLIKELY(bitmap_dir == IF_WIN(INVALID_HANDLE_VALUE, NULL))) {
- msg("InnoDB: Error: failed to open bitmap directory \'%s\'",
- srv_data_home);
- return FALSE;
- }
-
- bitmap_files->files =
- static_cast<log_online_bitmap_file_range_t::files_t *>
- (malloc(bitmap_files->count * sizeof(bitmap_files->files[0])));
- memset(bitmap_files->files, 0,
- bitmap_files->count * sizeof(bitmap_files->files[0]));
-
- while (!os_file_readdir_next_file(srv_data_home, bitmap_dir,
- &bitmap_dir_file_info)) {
-
- ulong file_seq_num;
- lsn_t file_start_lsn;
- size_t array_pos;
-
- if (!log_online_is_bitmap_file(&bitmap_dir_file_info,
- &file_seq_num,
- &file_start_lsn)
- || file_start_lsn >= range_end
- || file_start_lsn < first_file_start_lsn) {
-
- continue;
- }
-
- array_pos = file_seq_num - first_file_seq_num;
- if (UNIV_UNLIKELY(array_pos >= bitmap_files->count)) {
-
- msg("InnoDB: Error: inconsistent bitmap file "
- "directory");
- os_file_closedir(bitmap_dir);
- free(bitmap_files->files);
- return FALSE;
- }
-
- if (file_seq_num > bitmap_files->files[array_pos].seq_num) {
-
- bitmap_files->files[array_pos].seq_num = file_seq_num;
- strncpy(bitmap_files->files[array_pos].name,
- bitmap_dir_file_info.name, FN_REFLEN - 1);
- bitmap_files->files[array_pos].name[FN_REFLEN - 1]
- = '\0';
- bitmap_files->files[array_pos].start_lsn
- = file_start_lsn;
- }
- }
-
- if (UNIV_UNLIKELY(os_file_closedir_failed(bitmap_dir))) {
- os_file_get_last_error(TRUE);
- msg("InnoDB: Error: cannot close \'%s\'", srv_data_home);
- free(bitmap_files->files);
- return FALSE;
- }
-
-#ifdef UNIV_DEBUG
- ut_ad(bitmap_files->files[0].seq_num == first_file_seq_num);
-
- for (size_t i = 1; i < bitmap_files->count; i++) {
- if (!bitmap_files->files[i].seq_num) {
-
- break;
- }
- ut_ad(bitmap_files->files[i].seq_num
- > bitmap_files->files[i - 1].seq_num);
- ut_ad(bitmap_files->files[i].start_lsn
- >= bitmap_files->files[i - 1].start_lsn);
- }
-#endif
-
- return TRUE;
-}
-
-/****************************************************************//**
-Open a bitmap file for reading.
-
-@return whether opened successfully */
-static
-bool
-log_online_open_bitmap_file_read_only(
-/*==================================*/
- const char* name, /*!<in: bitmap file
- name without directory,
- which is assumed to be
- srv_data_home */
- log_online_bitmap_file_t* bitmap_file) /*!<out: opened bitmap
- file */
-{
- bool success = false;
-
- xb_ad(name[0] != '\0');
-
- snprintf(bitmap_file->name, FN_REFLEN, "%s%s", srv_data_home, name);
- bitmap_file->file = os_file_create_simple_no_error_handling(
- 0, bitmap_file->name,
- OS_FILE_OPEN, OS_FILE_READ_ONLY, true, &success);
- if (UNIV_UNLIKELY(!success)) {
-
- /* Here and below assume that bitmap file names do not
- contain apostrophes, thus no need for ut_print_filename(). */
- msg("InnoDB: Warning: error opening the changed page "
- "bitmap \'%s\'", bitmap_file->name);
- return success;
- }
-
- bitmap_file->size = os_file_get_size(bitmap_file->file);
- bitmap_file->offset = 0;
-
-#ifdef __linux__
- posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_SEQUENTIAL);
- posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_NOREUSE);
-#endif
-
- return success;
-}
-
-/****************************************************************//**
-Diagnose one or both of the following situations if we read close to
-the end of bitmap file:
-1) Warn if the remainder of the file is less than one page.
-2) Error if we cannot read any more full pages but the last read page
-did not have the last-in-run flag set.
-
-@return FALSE for the error */
-static
-ibool
-log_online_diagnose_bitmap_eof(
-/*===========================*/
- const log_online_bitmap_file_t* bitmap_file, /*!< in: bitmap file */
- ibool last_page_in_run)/*!< in: "last page in
- run" flag value in the
- last read page */
-{
- /* Check if we are too close to EOF to read a full page */
- if ((bitmap_file->size < MODIFIED_PAGE_BLOCK_SIZE)
- || (bitmap_file->offset
- > bitmap_file->size - MODIFIED_PAGE_BLOCK_SIZE)) {
-
- if (UNIV_UNLIKELY(bitmap_file->offset != bitmap_file->size)) {
-
- /* If we are not at EOF and we have less than one page
- to read, it's junk. This error is not fatal in
- itself. */
-
- msg("InnoDB: Warning: junk at the end of changed "
- "page bitmap file \'%s\'.", bitmap_file->name);
- }
-
- if (UNIV_UNLIKELY(!last_page_in_run)) {
-
- /* We are at EOF but the last read page did not finish
- a run */
- /* It's a "Warning" here because it's not a fatal error
- for the whole server */
- msg("InnoDB: Warning: changed page bitmap "
- "file \'%s\' does not contain a complete run "
- "at the end.", bitmap_file->name);
- return FALSE;
- }
- }
- return TRUE;
-}
-
-/* End of copy-pasted definitions */
-
-/** Iterator structure over changed page bitmap */
-struct xb_page_bitmap_range_struct {
- const xb_page_bitmap *bitmap; /* Bitmap with data */
- ulint space_id; /* Space id for this
- iterator */
- ulint bit_i; /* Bit index of the iterator
- position in the current page */
- const ib_rbt_node_t *bitmap_node; /* Current bitmap tree node */
- const byte *bitmap_page; /* Current bitmap page */
- ulint current_page_id;/* Current page id */
-};
-
-/****************************************************************//**
-Print a diagnostic message on missing bitmap data for an LSN range. */
-static
-void
-xb_msg_missing_lsn_data(
-/*====================*/
- lsn_t missing_interval_start, /*!<in: interval start */
- lsn_t missing_interval_end) /*!<in: interval end */
-{
- msg("mariabackup: warning: changed page data missing for LSNs between "
- LSN_PF " and " LSN_PF, missing_interval_start,
- missing_interval_end);
-}
-
-/****************************************************************//**
-Scan a bitmap file until data for a desired LSN or EOF is found and check that
-the page before the starting one is not corrupted to ensure that the found page
-indeed contains the very start of the desired LSN data. The caller must check
-the page LSN values to determine if the bitmap file was scanned until the data
-was found or until EOF. Page must be at least MODIFIED_PAGE_BLOCK_SIZE big.
-
-@return TRUE if the scan successful without corruption detected
-*/
-static
-ibool
-xb_find_lsn_in_bitmap_file(
-/*=======================*/
- log_online_bitmap_file_t *bitmap_file, /*!<in/out: bitmap
- file */
- byte *page, /*!<in/out: last read
- bitmap page */
- lsn_t *page_end_lsn, /*!<out: end LSN of the
- last read page */
- lsn_t lsn) /*!<in: LSN to find */
-{
- ibool last_page_ok = TRUE;
- ibool next_to_last_page_ok = TRUE;
-
- xb_ad (bitmap_file->size >= MODIFIED_PAGE_BLOCK_SIZE);
-
- *page_end_lsn = 0;
-
- while ((*page_end_lsn <= lsn)
- && (bitmap_file->offset
- <= bitmap_file->size - MODIFIED_PAGE_BLOCK_SIZE)) {
-
- next_to_last_page_ok = last_page_ok;
- if (!log_online_read_bitmap_page(bitmap_file, page,
- &last_page_ok)) {
-
- return FALSE;
- }
-
- *page_end_lsn = mach_read_from_8(page + MODIFIED_PAGE_END_LSN);
- }
-
- /* We check two pages here because the last read page already contains
- the required LSN data. If the next to the last one page is corrupted,
- then we have no way of telling if that page contained the required LSN
- range data too */
- return last_page_ok && next_to_last_page_ok;
-}
-
-/****************************************************************//**
-Read the disk bitmap and build the changed page bitmap tree for the
-LSN interval incremental_lsn to log_sys.next_checkpoint_lsn.
-
-@return the built bitmap tree or NULL if unable to read the full interval for
-any reason. */
-xb_page_bitmap*
-xb_page_bitmap_init(void)
-/*=====================*/
-{
- log_online_bitmap_file_t bitmap_file;
- lsn_t bmp_start_lsn = incremental_lsn;
- const lsn_t bmp_end_lsn{log_sys.next_checkpoint_lsn};
- byte page[MODIFIED_PAGE_BLOCK_SIZE];
- lsn_t current_page_end_lsn;
- xb_page_bitmap *result;
- ibool last_page_in_run= FALSE;
- log_online_bitmap_file_range_t bitmap_files;
- size_t bmp_i;
- ibool last_page_ok = TRUE;
-
- if (UNIV_UNLIKELY(bmp_start_lsn > bmp_end_lsn)) {
-
- msg("mariabackup: incremental backup LSN " LSN_PF
- " is larger than than the last checkpoint LSN " LSN_PF
- , bmp_start_lsn, bmp_end_lsn);
- return NULL;
- }
-
- if (!log_online_setup_bitmap_file_range(&bitmap_files, bmp_start_lsn,
- bmp_end_lsn)) {
-
- return NULL;
- }
-
- /* Only accept no bitmap files returned if start LSN == end LSN */
- if (bitmap_files.count == 0 && bmp_end_lsn != bmp_start_lsn) {
-
- return NULL;
- }
-
- result = rbt_create(MODIFIED_PAGE_BLOCK_SIZE,
- log_online_compare_bmp_keys);
-
- if (bmp_start_lsn == bmp_end_lsn) {
-
- /* Empty range - empty bitmap */
- return result;
- }
-
- bmp_i = 0;
-
- if (UNIV_UNLIKELY(bitmap_files.files[bmp_i].start_lsn
- > bmp_start_lsn)) {
-
- /* The 1st file does not have the starting LSN data */
- xb_msg_missing_lsn_data(bmp_start_lsn,
- bitmap_files.files[bmp_i].start_lsn);
- rbt_free(result);
- free(bitmap_files.files);
- return NULL;
- }
-
- /* Skip any zero-sized files at the start */
- while ((bmp_i < bitmap_files.count - 1)
- && (bitmap_files.files[bmp_i].start_lsn
- == bitmap_files.files[bmp_i + 1].start_lsn)) {
-
- bmp_i++;
- }
-
- /* Is the 1st bitmap file missing? */
- if (UNIV_UNLIKELY(bitmap_files.files[bmp_i].name[0] == '\0')) {
-
- /* TODO: this is not the exact missing range */
- xb_msg_missing_lsn_data(bmp_start_lsn, bmp_end_lsn);
- rbt_free(result);
- free(bitmap_files.files);
- return NULL;
- }
-
- /* Open the 1st bitmap file */
- if (UNIV_UNLIKELY(!log_online_open_bitmap_file_read_only(
- bitmap_files.files[bmp_i].name,
- &bitmap_file))) {
-
- rbt_free(result);
- free(bitmap_files.files);
- return NULL;
- }
-
- /* If the 1st file is truncated, no data. Not merged with the case
- below because zero-length file indicates not a corruption but missing
- subsequent files instead. */
- if (UNIV_UNLIKELY(bitmap_file.size < MODIFIED_PAGE_BLOCK_SIZE)) {
-
- xb_msg_missing_lsn_data(bmp_start_lsn, bmp_end_lsn);
- rbt_free(result);
- free(bitmap_files.files);
- os_file_close(bitmap_file.file);
- return NULL;
- }
-
- /* Find the start of the required LSN range in the file */
- if (UNIV_UNLIKELY(!xb_find_lsn_in_bitmap_file(&bitmap_file, page,
- &current_page_end_lsn,
- bmp_start_lsn))) {
-
- msg("mariabackup: Warning: changed page bitmap file "
- "\'%s\' corrupted", bitmap_file.name);
- rbt_free(result);
- free(bitmap_files.files);
- os_file_close(bitmap_file.file);
- return NULL;
- }
-
- last_page_in_run
- = mach_read_from_4(page + MODIFIED_PAGE_IS_LAST_BLOCK);
-
- if (UNIV_UNLIKELY(!log_online_diagnose_bitmap_eof(&bitmap_file,
- last_page_in_run))) {
-
- rbt_free(result);
- free(bitmap_files.files);
- os_file_close(bitmap_file.file);
- return NULL;
- }
-
- if (UNIV_UNLIKELY(current_page_end_lsn < bmp_start_lsn)) {
-
- xb_msg_missing_lsn_data(current_page_end_lsn, bmp_start_lsn);
- rbt_free(result);
- free(bitmap_files.files);
- os_file_close(bitmap_file.file);
- return NULL;
- }
-
- /* 1st bitmap page found, add it to the tree. */
- rbt_insert(result, page, page);
-
- /* Read next pages/files until all required data is read */
- while (last_page_ok
- && (current_page_end_lsn < bmp_end_lsn
- || (current_page_end_lsn == bmp_end_lsn
- && !last_page_in_run))) {
-
- ib_rbt_bound_t tree_search_pos;
-
- /* If EOF, advance the file skipping over any empty files */
- while (bitmap_file.size < MODIFIED_PAGE_BLOCK_SIZE
- || (bitmap_file.offset
- > bitmap_file.size - MODIFIED_PAGE_BLOCK_SIZE)) {
-
- os_file_close(bitmap_file.file);
-
- if (UNIV_UNLIKELY(
- !log_online_diagnose_bitmap_eof(
- &bitmap_file, last_page_in_run))) {
-
- rbt_free(result);
- free(bitmap_files.files);
- return NULL;
- }
-
- bmp_i++;
-
- if (UNIV_UNLIKELY(bmp_i == bitmap_files.count
- || (bitmap_files.files[bmp_i].seq_num
- == 0))) {
-
- xb_msg_missing_lsn_data(current_page_end_lsn,
- bmp_end_lsn);
- rbt_free(result);
- free(bitmap_files.files);
- return NULL;
- }
-
- /* Is the next file missing? */
- if (UNIV_UNLIKELY(bitmap_files.files[bmp_i].name[0]
- == '\0')) {
-
- /* TODO: this is not the exact missing range */
- xb_msg_missing_lsn_data(bitmap_files.files
- [bmp_i - 1].start_lsn,
- bmp_end_lsn);
- rbt_free(result);
- free(bitmap_files.files);
- return NULL;
- }
-
- if (UNIV_UNLIKELY(
- !log_online_open_bitmap_file_read_only(
- bitmap_files.files[bmp_i].name,
- &bitmap_file))) {
-
- rbt_free(result);
- free(bitmap_files.files);
- return NULL;
- }
- }
-
- if (UNIV_UNLIKELY(
- !log_online_read_bitmap_page(&bitmap_file, page,
- &last_page_ok))) {
-
- rbt_free(result);
- free(bitmap_files.files);
- os_file_close(bitmap_file.file);
- return NULL;
- }
-
- if (UNIV_UNLIKELY(!last_page_ok)) {
-
- msg("mariabackup: warning: changed page bitmap file "
- "\'%s\' corrupted.", bitmap_file.name);
- rbt_free(result);
- free(bitmap_files.files);
- os_file_close(bitmap_file.file);
- return NULL;
- }
-
- /* Merge the current page with an existing page or insert a new
- page into the tree */
-
- if (!rbt_search(result, &tree_search_pos, page)) {
-
- /* Merge the bitmap pages */
- byte *existing_page
- = rbt_value(byte, tree_search_pos.last);
- bitmap_word_t *bmp_word_1 = (bitmap_word_t *)
- (existing_page + MODIFIED_PAGE_BLOCK_BITMAP);
- bitmap_word_t *bmp_end = (bitmap_word_t *)
- (existing_page + MODIFIED_PAGE_BLOCK_UNUSED_2);
- bitmap_word_t *bmp_word_2 = (bitmap_word_t *)
- (page + MODIFIED_PAGE_BLOCK_BITMAP);
- while (bmp_word_1 < bmp_end) {
-
- *bmp_word_1++ |= *bmp_word_2++;
- }
- xb_a (bmp_word_1 == bmp_end);
- } else {
-
- /* Add a new page */
- rbt_add_node(result, &tree_search_pos, page);
- }
-
- current_page_end_lsn
- = mach_read_from_8(page + MODIFIED_PAGE_END_LSN);
- last_page_in_run
- = mach_read_from_4(page + MODIFIED_PAGE_IS_LAST_BLOCK);
- }
-
- xb_a (current_page_end_lsn >= bmp_end_lsn);
-
- free(bitmap_files.files);
- os_file_close(bitmap_file.file);
-
- return result;
-}
-
-/****************************************************************//**
-Free the bitmap tree. */
-void
-xb_page_bitmap_deinit(
-/*==================*/
- xb_page_bitmap* bitmap) /*!<in/out: bitmap tree */
-{
- if (bitmap) {
-
- rbt_free(bitmap);
- }
-}
-
-/****************************************************************//**
-Advance to the next bitmap page or setup the first bitmap page for the
-given bitmap range. Assumes that bitmap_range->bitmap_page has been
-already found/bumped by rbt_search()/rbt_next().
-
-@return FALSE if no more bitmap data for the range space ID */
-static
-ibool
-xb_page_bitmap_setup_next_page(
-/*===========================*/
- xb_page_bitmap_range* bitmap_range) /*!<in/out: the bitmap range */
-{
- ulint new_space_id;
- ulint new_1st_page_id;
-
- if (bitmap_range->bitmap_node == NULL) {
-
- bitmap_range->current_page_id = ULINT_UNDEFINED;
- return FALSE;
- }
-
- bitmap_range->bitmap_page = rbt_value(byte, bitmap_range->bitmap_node);
-
- new_space_id = mach_read_from_4(bitmap_range->bitmap_page
- + MODIFIED_PAGE_SPACE_ID);
- if (new_space_id != bitmap_range->space_id) {
-
- /* No more data for the current page id. */
- xb_a(new_space_id > bitmap_range->space_id);
- bitmap_range->current_page_id = ULINT_UNDEFINED;
- return FALSE;
- }
-
- new_1st_page_id = mach_read_from_4(bitmap_range->bitmap_page +
- MODIFIED_PAGE_1ST_PAGE_ID);
- xb_a (new_1st_page_id >= bitmap_range->current_page_id
- || bitmap_range->current_page_id == ULINT_UNDEFINED);
-
- bitmap_range->current_page_id = new_1st_page_id;
- bitmap_range->bit_i = 0;
-
- return TRUE;
-}
-
-/** Find the node with the smallest key that greater than equal to search key.
-@param[in] tree red-black tree
-@param[in] key search key
-@return node with the smallest greater-than-or-equal key
-@retval NULL if none was found */
-static
-const ib_rbt_node_t*
-rbt_lower_bound(const ib_rbt_t* tree, const void* key)
-{
- ut_ad(!tree->cmp_arg);
- const ib_rbt_node_t* ge = NULL;
-
- for (const ib_rbt_node_t *node = tree->root->left;
- node != tree->nil; ) {
- int result = tree->compare(node->value, key);
-
- if (result < 0) {
- node = node->right;
- } else {
- ge = node;
- if (result == 0) {
- break;
- }
-
- node = node->left;
- }
- }
-
- return(ge);
-}
-
-/****************************************************************//**
-Set up a new bitmap range iterator over a given space id changed
-pages in a given bitmap.
-
-@return bitmap range iterator */
-xb_page_bitmap_range*
-xb_page_bitmap_range_init(
-/*======================*/
- xb_page_bitmap* bitmap, /*!< in: bitmap to iterate over */
- ulint space_id) /*!< in: space id */
-{
- byte search_page[MODIFIED_PAGE_BLOCK_SIZE];
- xb_page_bitmap_range *result
- = static_cast<xb_page_bitmap_range *>(malloc(sizeof(*result)));
-
- memset(result, 0, sizeof(*result));
- result->bitmap = bitmap;
- result->space_id = space_id;
- result->current_page_id = ULINT_UNDEFINED;
-
- /* Search for the 1st page for the given space id */
- /* This also sets MODIFIED_PAGE_1ST_PAGE_ID to 0, which is what we
- want. */
- memset(search_page, 0, MODIFIED_PAGE_BLOCK_SIZE);
- mach_write_to_4(search_page + MODIFIED_PAGE_SPACE_ID, space_id);
-
- result->bitmap_node = rbt_lower_bound(result->bitmap, search_page);
-
- xb_page_bitmap_setup_next_page(result);
-
- return result;
-}
-
-/****************************************************************//**
-Get the value of the bitmap->range->bit_i bitmap bit
-
-@return the current bit value */
-static inline
-ibool
-is_bit_set(
-/*=======*/
- const xb_page_bitmap_range* bitmap_range) /*!< in: bitmap
- range */
-{
- return ((*(((bitmap_word_t *)(bitmap_range->bitmap_page
- + MODIFIED_PAGE_BLOCK_BITMAP))
- + (bitmap_range->bit_i >> 6)))
- & (1ULL << (bitmap_range->bit_i & 0x3F))) ? TRUE : FALSE;
-}
-
-/****************************************************************//**
-Get the next page id that has its bit set or cleared, i.e. equal to
-bit_value.
-
-@return page id */
-ulint
-xb_page_bitmap_range_get_next_bit(
-/*==============================*/
- xb_page_bitmap_range* bitmap_range, /*!< in/out: bitmap range */
- ibool bit_value) /*!< in: bit value */
-{
- if (UNIV_UNLIKELY(bitmap_range->current_page_id
- == ULINT_UNDEFINED)) {
-
- return ULINT_UNDEFINED;
- }
-
- do {
- while (bitmap_range->bit_i < MODIFIED_PAGE_BLOCK_ID_COUNT) {
-
- while (is_bit_set(bitmap_range) != bit_value
- && (bitmap_range->bit_i
- < MODIFIED_PAGE_BLOCK_ID_COUNT)) {
-
- bitmap_range->current_page_id++;
- bitmap_range->bit_i++;
- }
-
- if (bitmap_range->bit_i
- < MODIFIED_PAGE_BLOCK_ID_COUNT) {
-
- ulint result = bitmap_range->current_page_id;
- bitmap_range->current_page_id++;
- bitmap_range->bit_i++;
- return result;
- }
- }
-
- bitmap_range->bitmap_node
- = rbt_next(bitmap_range->bitmap,
- bitmap_range->bitmap_node);
-
- } while (xb_page_bitmap_setup_next_page(bitmap_range));
-
- return ULINT_UNDEFINED;
-}
-
-/****************************************************************//**
-Free the bitmap range iterator. */
-void
-xb_page_bitmap_range_deinit(
-/*========================*/
- xb_page_bitmap_range* bitmap_range) /*! in/out: bitmap range */
-{
- free(bitmap_range);
-}