diff options
Diffstat (limited to 'storage/xtradb/btr/btr0scrub.cc')
-rw-r--r-- | storage/xtradb/btr/btr0scrub.cc | 931 |
1 files changed, 0 insertions, 931 deletions
diff --git a/storage/xtradb/btr/btr0scrub.cc b/storage/xtradb/btr/btr0scrub.cc deleted file mode 100644 index 24c84ed301b..00000000000 --- a/storage/xtradb/btr/btr0scrub.cc +++ /dev/null @@ -1,931 +0,0 @@ -// Copyright (c) 2014, Google Inc. - -/**************************************************//** -@file btr/btr0scrub.cc -Scrubbing of btree pages - -*******************************************************/ - -#include "btr0btr.h" -#include "btr0cur.h" -#include "btr0scrub.h" -#include "ibuf0ibuf.h" -#include "fsp0fsp.h" -#include "dict0dict.h" -#include "mtr0mtr.h" - -/* used when trying to acquire dict-lock */ -UNIV_INTERN bool fil_crypt_is_closing(ulint space); - -/** -* scrub data at delete time (e.g purge thread) -*/ -my_bool srv_immediate_scrub_data_uncompressed = false; - -/** -* background scrub uncompressed data -* -* if srv_immediate_scrub_data_uncompressed is enabled -* this is only needed to handle "old" data -*/ -my_bool srv_background_scrub_data_uncompressed = false; - -/** -* backgrounds scrub compressed data -* -* reorganize compressed page for scrubbing -* (only way to scrub compressed data) -*/ -my_bool srv_background_scrub_data_compressed = false; - -/* check spaces once per hour */ -UNIV_INTERN uint srv_background_scrub_data_check_interval = (60 * 60); - -/* default to scrub spaces that hasn't been scrubbed in a week */ -UNIV_INTERN uint srv_background_scrub_data_interval = (7 * 24 * 60 * 60); - -/** -* statistics for scrubbing by background threads -*/ -static btr_scrub_stat_t scrub_stat; -static ib_mutex_t scrub_stat_mutex; -#ifdef UNIV_PFS_MUTEX -UNIV_INTERN mysql_pfs_key_t scrub_stat_mutex_key; -#endif - -#ifdef UNIV_DEBUG -/** -* srv_scrub_force_testing -* -* - force scrubbing using background threads even for uncompressed tables -* - force pessimistic scrubbing (page split) even if not needed -* (see test_pessimistic_scrub_pct) -*/ -my_bool srv_scrub_force_testing = true; - -/** -* Force pessimistic scrubbing in 50% of the cases (UNIV_DEBUG only) -*/ -static int test_pessimistic_scrub_pct = 50; - -#endif -static uint scrub_compression_level = page_zip_level; - -/**************************************************************//** -Log a scrubbing failure */ -static -void -log_scrub_failure( -/*===============*/ - btr_scrub_t* scrub_data, /*!< in: data to store statistics on */ - buf_block_t* block, /*!< in: block */ - dberr_t err) /*!< in: error */ -{ - const char* reason = "unknown"; - switch(err) { - case DB_UNDERFLOW: - reason = "too few records on page"; - scrub_data->scrub_stat.page_split_failures_underflow++; - break; - case DB_INDEX_CORRUPT: - reason = "unable to find index!"; - scrub_data->scrub_stat.page_split_failures_missing_index++; - break; - case DB_OUT_OF_FILE_SPACE: - reason = "out of filespace"; - scrub_data->scrub_stat.page_split_failures_out_of_filespace++; - break; - default: - ut_ad(0); - reason = "unknown"; - scrub_data->scrub_stat.page_split_failures_unknown++; - } - fprintf(stderr, - "InnoDB: Warning: Failed to scrub page %lu in space %lu : %s\n", - buf_block_get_page_no(block), - buf_block_get_space(block), - reason); -} - -/**************************************************************** -Lock dict mutexes */ -static -bool -btr_scrub_lock_dict_func(ulint space_id, bool lock_to_close_table, - const char * file, uint line) -{ - time_t start = time(0); - time_t last = start; - - /* FIXME: this is not the proper way of doing things. The - dict_sys->mutex should not be held by any thread for longer - than a few microseconds. It must not be held during I/O, - for example. So, what is the purpose for this busy-waiting? - This function should be rewritten as part of MDEV-8139: - Fix scrubbing tests. */ - - while (mutex_enter_nowait_func(&(dict_sys->mutex), file, line)) { - /* if we lock to close a table, we wait forever - * if we don't lock to close a table, we check if space - * is closing, and then instead give up - */ - if (lock_to_close_table) { - } else if (fil_space_t* space = fil_space_acquire(space_id)) { - bool stopping = space->is_stopping(); - fil_space_release(space); - if (stopping) { - return false; - } - } else { - return false; - } - - os_thread_sleep(250000); - - time_t now = time(0); - if (now >= last + 30) { - fprintf(stderr, - "WARNING: %s:%u waited %ld seconds for" - " dict_sys lock, space: %lu" - " lock_to_close_table: %d\n", - file, line, now - start, space_id, - lock_to_close_table); - - last = now; - } - } - - ut_ad(mutex_own(&dict_sys->mutex)); - return true; -} - -#define btr_scrub_lock_dict(space, lock_to_close_table) \ - btr_scrub_lock_dict_func(space, lock_to_close_table, __FILE__, __LINE__) - -/**************************************************************** -Unlock dict mutexes */ -static -void -btr_scrub_unlock_dict() -{ - dict_mutex_exit_for_mysql(); -} - -/**************************************************************** -Release reference to table -*/ -static -void -btr_scrub_table_close( -/*==================*/ - dict_table_t* table) /*!< in: table */ -{ - bool dict_locked = true; - bool try_drop = false; - table->stats_bg_flag &= ~BG_SCRUB_IN_PROGRESS; - dict_table_close(table, dict_locked, try_drop); -} - -/**************************************************************** -Release reference to table -*/ -static -void -btr_scrub_table_close_for_thread( - btr_scrub_t *scrub_data) -{ - if (scrub_data->current_table == NULL) { - return; - } - - if (fil_space_t* space = fil_space_acquire(scrub_data->space)) { - /* If tablespace is not marked as stopping perform - the actual close. */ - if (!space->is_stopping()) { - mutex_enter(&dict_sys->mutex); - /* perform the actual closing */ - btr_scrub_table_close(scrub_data->current_table); - mutex_exit(&dict_sys->mutex); - } - fil_space_release(space); - } - - scrub_data->current_table = NULL; - scrub_data->current_index = NULL; -} - -/**************************************************************//** -Check if scrubbing is turned ON or OFF */ -static -bool -check_scrub_setting( -/*=====================*/ - btr_scrub_t* scrub_data) /*!< in: scrub data */ -{ - if (scrub_data->compressed) - return srv_background_scrub_data_compressed; - else - return srv_background_scrub_data_uncompressed; -} - -#define IBUF_INDEX_ID (DICT_IBUF_ID_MIN + IBUF_SPACE_ID) - -/**************************************************************//** -Check if a page needs scrubbing */ -UNIV_INTERN -int -btr_page_needs_scrubbing( -/*=====================*/ - btr_scrub_t* scrub_data, /*!< in: scrub data */ - buf_block_t* block, /*!< in: block to check, latched */ - btr_scrub_page_allocation_status_t allocated) /*!< in: is block known - to be allocated */ -{ - /** - * Check if scrubbing has been turned OFF. - * - * at start of space, we check if scrubbing is ON or OFF - * here we only check if scrubbing is turned OFF. - * - * Motivation is that it's only valueable to have a full table (space) - * scrubbed. - */ - if (!check_scrub_setting(scrub_data)) { - bool before_value = scrub_data->scrubbing; - scrub_data->scrubbing = false; - - if (before_value == true) { - /* we toggle scrubbing from on to off */ - return BTR_SCRUB_TURNED_OFF; - } - } - - if (scrub_data->scrubbing == false) { - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - - page_t* page = buf_block_get_frame(block); - uint type = fil_page_get_type(page); - - if (allocated == BTR_SCRUB_PAGE_ALLOCATED) { - if (type != FIL_PAGE_INDEX) { - /* this function is called from fil-crypt-threads. - * these threads iterate all pages of all tablespaces - * and don't know about fil_page_type. - * But scrubbing is only needed for index-pages. */ - - /** - * NOTE: scrubbing is also needed for UNDO pages, - * but they are scrubbed at purge-time, since they are - * uncompressed - */ - - /* if encountering page type not needing scrubbing - release reference to table object */ - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - - if (page_has_garbage(page) == false) { - /* no garbage (from deleted/shrunken records) */ - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - - } else if (allocated == BTR_SCRUB_PAGE_FREE || - allocated == BTR_SCRUB_PAGE_ALLOCATION_UNKNOWN) { - - if (! (type == FIL_PAGE_INDEX || - type == FIL_PAGE_TYPE_BLOB || - type == FIL_PAGE_TYPE_ZBLOB || - type == FIL_PAGE_TYPE_ZBLOB2)) { - - /** - * If this is a dropped page, we also need to scrub - * BLOB pages - */ - - /* if encountering page type not needing scrubbing - release reference to table object */ - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - } - - if (btr_page_get_index_id(page) == IBUF_INDEX_ID) { - /* skip ibuf */ - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - - return BTR_SCRUB_PAGE; -} - -/**************************************************************** -Handle a skipped page -*/ -UNIV_INTERN -void -btr_scrub_skip_page( -/*==================*/ - btr_scrub_t* scrub_data, /*!< in: data with scrub state */ - int needs_scrubbing) /*!< in: return code from - btr_page_needs_scrubbing */ -{ - switch(needs_scrubbing) { - case BTR_SCRUB_SKIP_PAGE: - /* nothing todo */ - return; - case BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE: - btr_scrub_table_close_for_thread(scrub_data); - return; - case BTR_SCRUB_TURNED_OFF: - case BTR_SCRUB_SKIP_PAGE_AND_COMPLETE_SPACE: - btr_scrub_complete_space(scrub_data); - return; - } - - /* unknown value. should not happen */ - ut_a(0); -} - -/**************************************************************** -Try to scrub a page using btr_page_reorganize_low -return DB_SUCCESS on success or DB_OVERFLOW on failure */ -static -dberr_t -btr_optimistic_scrub( -/*==================*/ - btr_scrub_t* scrub_data, /*!< in: data with scrub state */ - buf_block_t* block, /*!< in: block to scrub */ - dict_index_t* index, /*!< in: index */ - mtr_t* mtr) /*!< in: mtr */ -{ -#ifdef UNIV_DEBUG - if (srv_scrub_force_testing && - page_get_n_recs(buf_block_get_frame(block)) > 2 && - (rand() % 100) < test_pessimistic_scrub_pct) { - - fprintf(stderr, - "scrub: simulate btr_page_reorganize failed %lu:%lu " - " table: %llu:%s index: %llu:%s get_n_recs(): %lu\n", - buf_block_get_space(block), - buf_block_get_page_no(block), - (ulonglong)scrub_data->current_table->id, - scrub_data->current_table->name, - (ulonglong)scrub_data->current_index->id, - scrub_data->current_index->name, - page_get_n_recs(buf_block_get_frame(block))); - return DB_OVERFLOW; - } -#endif - - page_cur_t cur; - page_cur_set_before_first(block, &cur); - bool recovery = false; - if (!btr_page_reorganize_low(recovery, scrub_compression_level, - &cur, index, mtr)) { - return DB_OVERFLOW; - } - - /* We play safe and reset the free bits */ - if (!dict_index_is_clust(index) && - block != NULL) { - buf_frame_t* frame = buf_block_get_frame(block); - if (frame && - page_is_leaf(frame)) { - - ibuf_reset_free_bits(block); - } - } - - scrub_data->scrub_stat.page_reorganizations++; - - return DB_SUCCESS; -} - -/**************************************************************** -Try to scrub a page by splitting it -return DB_SUCCESS on success -DB_UNDERFLOW if page has too few records -DB_OUT_OF_FILE_SPACE if we can't find space for split */ -static -dberr_t -btr_pessimistic_scrub( -/*==================*/ - btr_scrub_t* scrub_data, /*!< in: data with scrub state */ - buf_block_t* block, /*!< in: block to scrub */ - dict_index_t* index, /*!< in: index */ - mtr_t* mtr) /*!< in: mtr */ -{ - page_t* page = buf_block_get_frame(block); - if (page_get_n_recs(page) < 2) { - /** - * There is no way we can split a page with < 2 records - */ - log_scrub_failure(scrub_data, block, DB_UNDERFLOW); - return DB_UNDERFLOW; - } - - /** - * Splitting page needs new space, allocate it here - * so that splitting won't fail due to this */ - ulint n_extents = 3; - ulint n_reserved = 0; - if (!fsp_reserve_free_extents(&n_reserved, index->space, - n_extents, FSP_NORMAL, mtr)) { - log_scrub_failure(scrub_data, block, - DB_OUT_OF_FILE_SPACE); - return DB_OUT_OF_FILE_SPACE; - } - - /* read block variables */ - ulint space = buf_block_get_space(block); - ulint page_no = buf_block_get_page_no(block); - ulint zip_size = buf_block_get_zip_size(block); - ulint left_page_no = btr_page_get_prev(page, mtr); - ulint right_page_no = btr_page_get_next(page, mtr); - - /** - * When splitting page, we need X-latches on left/right brothers - * see e.g btr_cur_latch_leaves - */ - - if (left_page_no != FIL_NULL) { - /** - * pages needs to be locked left-to-right, release block - * and re-lock. We still have x-lock on index - * so this should be safe - */ - mtr_release_buf_page_at_savepoint(mtr, scrub_data->savepoint, - block); - - buf_block_t* get_block = btr_block_get( - space, zip_size, left_page_no, - RW_X_LATCH, index, mtr); - get_block->check_index_page_at_flush = TRUE; - - /** - * Refetch block and re-initialize page - */ - block = btr_block_get( - space, zip_size, page_no, - RW_X_LATCH, index, mtr); - - page = buf_block_get_frame(block); - - /** - * structure should be unchanged - */ - ut_a(left_page_no == btr_page_get_prev(page, mtr)); - ut_a(right_page_no == btr_page_get_next(page, mtr)); - } - - if (right_page_no != FIL_NULL) { - buf_block_t* get_block = btr_block_get( - space, zip_size, right_page_no, - RW_X_LATCH, index, mtr); - get_block->check_index_page_at_flush = TRUE; - } - - /* arguments to btr_page_split_and_insert */ - mem_heap_t* heap = NULL; - dtuple_t* entry = NULL; - ulint* offsets = NULL; - ulint n_ext = 0; - ulint flags = BTR_MODIFY_TREE; - - /** - * position a cursor on first record on page - */ - rec_t* rec = page_rec_get_next(page_get_infimum_rec(page)); - btr_cur_t cursor; - btr_cur_position(index, rec, block, &cursor); - - /** - * call split page with NULL as argument for entry to insert - */ - if (dict_index_get_page(index) == buf_block_get_page_no(block)) { - /* The page is the root page - * NOTE: ibuf_reset_free_bits is called inside - * btr_root_raise_and_insert */ - rec = btr_root_raise_and_insert( - flags, &cursor, &offsets, &heap, entry, n_ext, mtr); - } else { - /* We play safe and reset the free bits - * NOTE: need to call this prior to btr_page_split_and_insert */ - if (!dict_index_is_clust(index) && - block != NULL) { - buf_frame_t* frame = buf_block_get_frame(block); - if (frame && - page_is_leaf(frame)) { - - ibuf_reset_free_bits(block); - } - } - - rec = btr_page_split_and_insert( - flags, &cursor, &offsets, &heap, entry, n_ext, mtr); - } - - if (heap) { - mem_heap_free(heap); - } - - if (n_reserved > 0) { - fil_space_release_free_extents(index->space, n_reserved); - } - - scrub_data->scrub_stat.page_splits++; - return DB_SUCCESS; -} - -/**************************************************************** -Location index by id for a table -return index or NULL */ -static -dict_index_t* -find_index( -/*========*/ - dict_table_t* table, /*!< in: table */ - index_id_t index_id) /*!< in: index id */ -{ - if (table != NULL) { - dict_index_t* index = dict_table_get_first_index(table); - while (index != NULL) { - if (index->id == index_id) - return index; - index = dict_table_get_next_index(index); - } - } - - return NULL; -} - -/**************************************************************** -Check if table should be scrubbed -*/ -static -bool -btr_scrub_table_needs_scrubbing( -/*============================*/ - dict_table_t* table) /*!< in: table */ -{ - if (table == NULL) - return false; - - if (table->stats_bg_flag & BG_STAT_SHOULD_QUIT) { - return false; - } - - if (table->to_be_dropped) { - return false; - } - - if (!table->is_readable()) { - return false; - } - - return true; -} - -/**************************************************************** -Check if index should be scrubbed -*/ -static -bool -btr_scrub_index_needs_scrubbing( -/*============================*/ - dict_index_t* index) /*!< in: index */ -{ - if (index == NULL) - return false; - - if (dict_index_is_ibuf(index)) { - return false; - } - - if (dict_index_is_online_ddl(index)) { - return false; - } - - return true; -} - -/**************************************************************** -Get table and index and store it on scrub_data -*/ -static -void -btr_scrub_get_table_and_index( -/*=========================*/ - btr_scrub_t* scrub_data, /*!< in/out: scrub data */ - index_id_t index_id) /*!< in: index id */ -{ - /* first check if it's an index to current table */ - scrub_data->current_index = find_index(scrub_data->current_table, - index_id); - - if (scrub_data->current_index != NULL) { - /* yes it was */ - return; - } - - if (!btr_scrub_lock_dict(scrub_data->space, false)) { - btr_scrub_complete_space(scrub_data); - return; - } - - /* close current table (if any) */ - if (scrub_data->current_table != NULL) { - btr_scrub_table_close(scrub_data->current_table); - scrub_data->current_table = NULL; - } - - /* argument to dict_table_open_on_index_id */ - bool dict_locked = true; - - /* open table based on index_id */ - dict_table_t* table = dict_table_open_on_index_id( - index_id, - dict_locked); - - if (table != NULL) { - /* mark table as being scrubbed */ - table->stats_bg_flag |= BG_SCRUB_IN_PROGRESS; - - if (!btr_scrub_table_needs_scrubbing(table)) { - btr_scrub_table_close(table); - btr_scrub_unlock_dict(); - return; - } - } - - btr_scrub_unlock_dict(); - scrub_data->current_table = table; - scrub_data->current_index = find_index(table, index_id); -} - -/**************************************************************** -Handle free page */ -UNIV_INTERN -int -btr_scrub_free_page( -/*====================*/ - btr_scrub_t* scrub_data, /*!< in/out: scrub data */ - buf_block_t* block, /*!< in: block to scrub */ - mtr_t* mtr) /*!< in: mtr */ -{ - // TODO(jonaso): scrub only what is actually needed - - { - /* note: perform both the memset and setting of FIL_PAGE_TYPE - * wo/ logging. so that if we crash before page is flushed - * it will be found by scrubbing thread again - */ - memset(buf_block_get_frame(block) + PAGE_HEADER, 0, - UNIV_PAGE_SIZE - PAGE_HEADER); - - mach_write_to_2(buf_block_get_frame(block) + FIL_PAGE_TYPE, - FIL_PAGE_TYPE_ALLOCATED); - } - - ulint compact = 1; - page_create(block, mtr, compact); - - mtr_commit(mtr); - - /* page doesn't need further processing => SKIP - * and close table/index so that we don't keep references too long */ - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; -} - -/**************************************************************** -Recheck if a page needs scrubbing, and if it does load appropriate -table and index */ -UNIV_INTERN -int -btr_scrub_recheck_page( -/*====================*/ - btr_scrub_t* scrub_data, /*!< inut: scrub data */ - buf_block_t* block, /*!< in: block */ - btr_scrub_page_allocation_status_t allocated, /*!< in: is block - allocated or free */ - mtr_t* mtr) /*!< in: mtr */ -{ - /* recheck if page needs scrubbing (knowing allocation status) */ - int needs_scrubbing = btr_page_needs_scrubbing( - scrub_data, block, allocated); - - if (needs_scrubbing != BTR_SCRUB_PAGE) { - mtr_commit(mtr); - return needs_scrubbing; - } - - if (allocated == BTR_SCRUB_PAGE_FREE) { - /** we don't need to load table/index for free pages - * so scrub directly here */ - /* mtr is committed inside btr_scrub_page_free */ - return btr_scrub_free_page(scrub_data, - block, - mtr); - } - - page_t* page = buf_block_get_frame(block); - index_id_t index_id = btr_page_get_index_id(page); - - if (scrub_data->current_index == NULL || - scrub_data->current_index->id != index_id) { - - /** - * commit mtr (i.e release locks on block) - * and try to get table&index potentially loading it - * from disk - */ - mtr_commit(mtr); - btr_scrub_get_table_and_index(scrub_data, index_id); - } else { - /* we already have correct index - * commit mtr so that we can lock index before fetching page - */ - mtr_commit(mtr); - } - - /* check if table is about to be dropped */ - if (!btr_scrub_table_needs_scrubbing(scrub_data->current_table)) { - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - - /* check if index is scrubbable */ - if (!btr_scrub_index_needs_scrubbing(scrub_data->current_index)) { - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - - mtr_start(mtr); - mtr_x_lock(dict_index_get_lock(scrub_data->current_index), mtr); - /** set savepoint for X-latch of block */ - scrub_data->savepoint = mtr_set_savepoint(mtr); - return BTR_SCRUB_PAGE; -} - -/**************************************************************** -Perform actual scrubbing of page */ -UNIV_INTERN -int -btr_scrub_page( -/*============*/ - btr_scrub_t* scrub_data, /*!< in/out: scrub data */ - buf_block_t* block, /*!< in: block */ - btr_scrub_page_allocation_status_t allocated, /*!< in: is block - allocated or free */ - mtr_t* mtr) /*!< in: mtr */ -{ - /* recheck if page needs scrubbing (knowing allocation status) */ - int needs_scrubbing = BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - - if (block) { - btr_page_needs_scrubbing(scrub_data, block, allocated); - } - - if (!block || needs_scrubbing != BTR_SCRUB_PAGE) { - mtr_commit(mtr); - return needs_scrubbing; - } - - if (allocated == BTR_SCRUB_PAGE_FREE) { - /* mtr is committed inside btr_scrub_page_free */ - return btr_scrub_free_page(scrub_data, - block, - mtr); - } - - /* check that table/index still match now that they are loaded */ - - if (scrub_data->current_table->space != scrub_data->space) { - /* this is truncate table */ - mtr_commit(mtr); - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - - if (scrub_data->current_index->space != scrub_data->space) { - /* this is truncate table */ - mtr_commit(mtr); - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - - if (scrub_data->current_index->page == FIL_NULL) { - /* this is truncate table */ - mtr_commit(mtr); - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - - buf_frame_t* frame = buf_block_get_frame(block); - - if (!frame || btr_page_get_index_id(frame) != - scrub_data->current_index->id) { - /* page has been reallocated to new index */ - mtr_commit(mtr); - return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; - } - - /* check if I can scrub (reorganize) page wo/ overflow */ - if (btr_optimistic_scrub(scrub_data, - block, - scrub_data->current_index, - mtr) != DB_SUCCESS) { - - /** - * Can't reorganize page...need to split it - */ - btr_pessimistic_scrub(scrub_data, - block, - scrub_data->current_index, - mtr); - } - mtr_commit(mtr); - - return BTR_SCRUB_SKIP_PAGE; // no further action needed -} - -/**************************************************************//** -Start iterating a space */ -UNIV_INTERN -bool -btr_scrub_start_space( -/*===================*/ - ulint space, /*!< in: space */ - btr_scrub_t* scrub_data) /*!< in/out: scrub data */ -{ - scrub_data->space = space; - scrub_data->current_table = NULL; - scrub_data->current_index = NULL; - - scrub_data->compressed = fil_space_get_zip_size(space) > 0; - scrub_data->scrubbing = check_scrub_setting(scrub_data); - return scrub_data->scrubbing; -} - -/*********************************************************************** -Update global statistics with thread statistics */ -static -void -btr_scrub_update_total_stat(btr_scrub_t *scrub_data) -{ - mutex_enter(&scrub_stat_mutex); - scrub_stat.page_reorganizations += - scrub_data->scrub_stat.page_reorganizations; - scrub_stat.page_splits += - scrub_data->scrub_stat.page_splits; - scrub_stat.page_split_failures_underflow += - scrub_data->scrub_stat.page_split_failures_underflow; - scrub_stat.page_split_failures_out_of_filespace += - scrub_data->scrub_stat.page_split_failures_out_of_filespace; - scrub_stat.page_split_failures_missing_index += - scrub_data->scrub_stat.page_split_failures_missing_index; - scrub_stat.page_split_failures_unknown += - scrub_data->scrub_stat.page_split_failures_unknown; - mutex_exit(&scrub_stat_mutex); - - // clear stat - memset(&scrub_data->scrub_stat, 0, sizeof(scrub_data->scrub_stat)); -} - -/**************************************************************//** -Complete iterating a space */ -UNIV_INTERN -bool -btr_scrub_complete_space( -/*=====================*/ - btr_scrub_t* scrub_data) /*!< in/out: scrub data */ -{ - btr_scrub_table_close_for_thread(scrub_data); - btr_scrub_update_total_stat(scrub_data); - return scrub_data->scrubbing; -} - -/********************************************************************* -Return scrub statistics */ -void -btr_scrub_total_stat(btr_scrub_stat_t *stat) -{ - mutex_enter(&scrub_stat_mutex); - *stat = scrub_stat; - mutex_exit(&scrub_stat_mutex); -} - -/********************************************************************* -Init global variables */ -UNIV_INTERN -void -btr_scrub_init() -{ - mutex_create(scrub_stat_mutex_key, - &scrub_stat_mutex, SYNC_NO_ORDER_CHECK); - - memset(&scrub_stat, 0, sizeof(scrub_stat)); -} - -/********************************************************************* -Cleanup globals */ -UNIV_INTERN -void -btr_scrub_cleanup() -{ - mutex_free(&scrub_stat_mutex); -} |