diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index d7860627717..8aeeb7d7e9f 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -730,13 +730,15 @@ datafiles_iter_next(datafiles_iter_t *it) fil_system.space_list.begin() : std::next(it->space); - while (it->space != fil_system.space_list.end() && - (it->space->purpose != FIL_TYPE_TABLESPACE || - UT_LIST_GET_LEN(it->space->chain) == 0)) + while (it->space != fil_system.space_list.end() + && UT_LIST_GET_LEN(it->space->chain) == 0) ++it->space; if (it->space == fil_system.space_list.end()) goto end; + ut_ad(!it->space->is_temporary()); + ut_ad(!it->space->is_being_imported()); + it->node = UT_LIST_GET_FIRST(it->space->chain); end: @@ -907,7 +909,7 @@ err: @param[in] len length of name, in bytes @param[in] new_name new file name (NULL if not rename) @param[in] new_len length of new_name, in bytes (0 if NULL) */ -static void backup_file_op(ulint space_id, int type, +static void backup_file_op(uint32_t space_id, int type, const byte* name, ulint len, const byte* new_name, ulint new_len) { @@ -923,7 +925,8 @@ static void backup_file_op(ulint space_id, int type, std::string space_name = filename_to_spacename(name, len); ddl_tracker.id_to_name[space_id] = space_name; ddl_tracker.delete_defer(space_id, space_name); - msg("DDL tracking : create %zu \"%.*s\"", space_id, int(len), name); + msg("DDL tracking : create %" PRIu32 " \"%.*s\"", + space_id, int(len), name); } break; case FILE_MODIFY: @@ -939,7 +942,7 @@ static void backup_file_op(ulint space_id, int type, ddl_tracker.id_to_name[space_id] = new_space_name; ddl_tracker.rename_defer(space_id, old_space_name, new_space_name); - msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"", + msg("DDL tracking : rename %" PRIu32 " \"%.*s\",\"%.*s\"", space_id, int(len), name, int(new_len), new_name); } break; @@ -947,7 +950,8 @@ static void backup_file_op(ulint space_id, int type, ddl_tracker.drops.insert(space_id); ddl_tracker.delete_defer( space_id, filename_to_spacename(name, len)); - msg("DDL tracking : delete %zu \"%.*s\"", space_id, int(len), name); + msg("DDL tracking : delete %" PRIu32 " \"%.*s\"", + space_id, int(len), name); break; default: ut_ad(0); @@ -966,21 +970,22 @@ static void backup_file_op(ulint space_id, int type, We will abort backup in this case. */ -static void backup_file_op_fail(ulint space_id, int type, +static void backup_file_op_fail(uint32_t space_id, int type, const byte* name, ulint len, const byte* new_name, ulint new_len) { bool fail = false; switch(type) { case FILE_CREATE: - msg("DDL tracking : create %zu \"%.*s\"", space_id, int(len), name); + msg("DDL tracking : create %" PRIu32 " \"%.*s\"", + space_id, int(len), name); fail = !check_if_skip_table( filename_to_spacename(name, len).c_str()); break; case FILE_MODIFY: break; case FILE_RENAME: - msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"", + msg("DDL tracking : rename %" PRIu32 " \"%.*s\",\"%.*s\"", space_id, int(len), name, int(new_len), new_name); fail = !check_if_skip_table( filename_to_spacename(name, len).c_str()) @@ -990,7 +995,8 @@ static void backup_file_op_fail(ulint space_id, int type, case FILE_DELETE: fail = !check_if_skip_table( filename_to_spacename(name, len).c_str()); - msg("DDL tracking : delete %zu \"%.*s\"", space_id, int(len), name); + msg("DDL tracking : delete %" PRIu32 " \"%.*s\"", + space_id, int(len), name); break; default: ut_ad(0); @@ -1011,7 +1017,7 @@ static void backup_undo_trunc(uint32_t space_id) /* Function to store the space id of page0 INIT_PAGE @param space_id space id which has page0 init page */ -static void backup_first_page_op(ulint space_id) +static void backup_first_page_op(uint32_t space_id) { first_page_init_ids.insert(space_id); } @@ -3532,8 +3538,8 @@ static void xb_load_single_table_tablespace(const char *dirname, if (err == DB_SUCCESS && file->space_id() != SRV_TMP_SPACE_ID) { mysql_mutex_lock(&fil_system.mutex); space = fil_space_t::create( - file->space_id(), file->flags(), - FIL_TYPE_TABLESPACE, nullptr/* TODO: crypt_data */, + uint32_t(file->space_id()), file->flags(), false, + nullptr/* TODO: crypt_data */, FIL_ENCRYPTION_DEFAULT, file->handle() != OS_FILE_CLOSED); ut_ad(space); @@ -4998,8 +5004,8 @@ void CorruptedPages::backup_fix_ddl(ds_ctxt *ds_data, ds_ctxt *ds_meta) iter != ddl_tracker.tables_in_backup.end(); iter++) { - const std::string name = iter->second; - ulint id = iter->first; + uint32_t id = iter->first; + const std::string &name = iter->second; if (ddl_tracker.drops.find(id) != ddl_tracker.drops.end()) { dropped_tables.insert(name); @@ -5025,8 +5031,8 @@ void CorruptedPages::backup_fix_ddl(ds_ctxt *ds_data, ds_ctxt *ds_meta) iter != ddl_tracker.id_to_name.end(); iter++) { - ulint id = iter->first; - std::string name = iter->second; + uint32_t id = iter->first; + const std::string &name = iter->second; if (ddl_tracker.tables_in_backup.find(id) != ddl_tracker.tables_in_backup.end()) { /* already processed above */ @@ -5322,8 +5328,8 @@ exit: char tmpname[FN_REFLEN]; - snprintf(tmpname, FN_REFLEN, "%s/xtrabackup_tmp_#" ULINTPF, - dbname, fil_space->id); + snprintf(tmpname, FN_REFLEN, "%s/xtrabackup_tmp_#%" + PRIu32, dbname, fil_space->id); msg("mariabackup: Renaming %s to %s.ibd", fil_space->chain.start->name, tmpname); @@ -5378,8 +5384,8 @@ exit: ut_ad(fil_space_t::physical_size(flags) == info.page_size); mysql_mutex_lock(&fil_system.mutex); - fil_space_t* space = fil_space_t::create(info.space_id, flags, - FIL_TYPE_TABLESPACE, 0, + fil_space_t* space = fil_space_t::create(uint32_t(info.space_id), + flags, false, 0, FIL_ENCRYPTION_DEFAULT, true); mysql_mutex_unlock(&fil_system.mutex); if (space) { diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index ae604f0826c..4cc3cdf38c4 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -3643,8 +3643,7 @@ static dberr_t buf_page_check_corrupt(buf_page_t *bpage, const bool seems_encrypted = !node.space->full_crc32() && key_version && node.space->crypt_data && node.space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED; - ut_ad(node.space->purpose != FIL_TYPE_TEMPORARY || - node.space->full_crc32()); + ut_ad(!node.space->is_temporary() || node.space->full_crc32()); /* If traditional checksums match, we assume that page is not anymore encrypted. */ @@ -3652,7 +3651,7 @@ static dberr_t buf_page_check_corrupt(buf_page_t *bpage, && !buf_is_zeroes(span(dst_frame, node.space->physical_size())) && (key_version || node.space->is_compressed() - || node.space->purpose == FIL_TYPE_TEMPORARY)) { + || node.space->is_temporary())) { if (buf_page_full_crc32_is_corrupted( bpage->id().space(), dst_frame, node.space->is_compressed())) { diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 31036bf978d..0060ee29fd9 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -750,7 +750,8 @@ void buf_dblwr_t::add_to_batch(const IORequest &request, size_t size) ut_ad(request.bpage); ut_ad(request.bpage->in_file()); ut_ad(request.node); - ut_ad(request.node->space->purpose == FIL_TYPE_TABLESPACE); + ut_ad(!request.node->space->is_temporary()); + ut_ad(!request.node->space->is_being_imported()); ut_ad(request.node->space->id == request.bpage->id().space()); ut_ad(request.node->space->referenced()); ut_ad(!srv_read_only_mode); diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index a513f2499f6..024866f4f75 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -639,7 +639,7 @@ static byte *buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s, fil_space_crypt_t *crypt_data= space->crypt_data; bool encrypted, page_compressed; - if (space->purpose == FIL_TYPE_TEMPORARY) + if (space->is_temporary()) { ut_ad(!crypt_data); encrypted= innodb_encrypt_temporary_tables; @@ -685,13 +685,13 @@ static byte *buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s, if (!page_compressed) { not_compressed: - d= space->purpose == FIL_TYPE_TEMPORARY + d= space->is_temporary() ? buf_tmp_page_encrypt(page_no, s, d) : fil_space_encrypt(space, page_no, s, d); } else { - ut_ad(space->purpose != FIL_TYPE_TEMPORARY); + ut_ad(!space->is_temporary()); /* First we compress the page content */ buf_tmp_reserve_compression_buf(*slot); byte *tmp= (*slot)->comp_buf; @@ -768,8 +768,7 @@ bool buf_page_t::flush(fil_space_t *space) mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex); ut_ad(in_file()); ut_ad(in_LRU_list); - ut_ad((space->purpose == FIL_TYPE_TEMPORARY) == - (space == fil_system.temp_space)); + ut_ad((space->is_temporary()) == (space == fil_system.temp_space)); ut_ad(space->referenced()); const auto s= state(); @@ -779,12 +778,12 @@ bool buf_page_t::flush(fil_space_t *space) (FIL_PAGE_LSN + (zip.data ? zip.data : frame))); ut_ad(lsn ? lsn >= oldest_modification() || oldest_modification() == 2 - : space->purpose != FIL_TYPE_TABLESPACE); + : (space->is_temporary() || space->is_being_imported())); if (s < UNFIXED) { ut_a(s >= FREED); - if (UNIV_LIKELY(space->purpose == FIL_TYPE_TABLESPACE)) + if (!space->is_temporary() && !space->is_being_imported()) { freed: if (lsn > log_sys.get_flushed_lsn()) @@ -800,7 +799,8 @@ bool buf_page_t::flush(fil_space_t *space) if (UNIV_UNLIKELY(lsn < space->get_create_lsn())) { - ut_ad(space->purpose == FIL_TYPE_TABLESPACE); + ut_ad(!space->is_temporary()); + ut_ad(!space->is_being_imported()); goto freed; } @@ -884,7 +884,7 @@ bool buf_page_t::flush(fil_space_t *space) if ((s & LRU_MASK) == REINIT || !space->use_doublewrite()) { - if (UNIV_LIKELY(space->purpose == FIL_TYPE_TABLESPACE) && + if (!space->is_temporary() && !space->is_being_imported() && lsn > log_sys.get_flushed_lsn()) log_write_up_to(lsn, true); space->io(IORequest{type, this, slot}, physical_offset(), size, @@ -1735,7 +1735,7 @@ done: if (acquired) space->release(); - if (space->purpose == FIL_TYPE_IMPORT) + if (space->is_being_imported()) os_aio_wait_until_no_pending_writes(true); else buf_dblwr.flush_buffered_writes(); diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index e9efc10f994..917c4d51ee9 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -972,8 +972,10 @@ void dict_check_tablespaces_and_store_max_id(const std::set *spaces) const bool not_dropped{!rec_get_deleted_flag(rec, 0)}; /* Check that the .ibd file exists. */ - if (fil_ibd_open(not_dropped, FIL_TYPE_TABLESPACE, - space_id, dict_tf_to_fsp_flags(flags), + if (fil_ibd_open(space_id, dict_tf_to_fsp_flags(flags), + not_dropped + ? fil_space_t::VALIDATE_NOTHING + : fil_space_t::MAYBE_MISSING, name, filepath)) { } else if (!not_dropped) { } else if (srv_operation == SRV_OPERATION_NORMAL @@ -2291,8 +2293,8 @@ dict_load_tablespace( } table->space = fil_ibd_open( - 2, FIL_TYPE_TABLESPACE, table->space_id, - dict_tf_to_fsp_flags(table->flags), + table->space_id, dict_tf_to_fsp_flags(table->flags), + fil_space_t::VALIDATE_SPACE_ID, {table->name.m_name, strlen(table->name.m_name)}, filepath); if (!table->space) { diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 59189d3e053..9de43abbb17 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -136,9 +136,6 @@ dict_table_t *dict_table_t::create(const span &name, ulint n_cols, ulint n_v_cols, ulint flags, ulint flags2) { - ut_ad(!space || space->purpose == FIL_TYPE_TABLESPACE || - space->purpose == FIL_TYPE_TEMPORARY || - space->purpose == FIL_TYPE_IMPORT); ut_a(dict_tf2_is_valid(flags, flags2)); ut_a(!(flags2 & DICT_TF2_UNUSED_BIT_MASK)); diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index ddfa6440680..842f79569d9 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1067,7 +1067,8 @@ default_encrypt_list only when default encrypt */ static bool fil_crypt_must_remove(const fil_space_t &space) { - ut_ad(space.purpose == FIL_TYPE_TABLESPACE); + ut_ad(!space.is_temporary()); + ut_ad(!space.is_being_imported()); fil_space_crypt_t *crypt_data = space.crypt_data; mysql_mutex_assert_owner(&fil_system.mutex); const ulong encrypt_tables= srv_encrypt_tables; @@ -1103,7 +1104,8 @@ fil_crypt_space_needs_rotation( fil_space_t* space = &*state->space; ut_ad(space->referenced()); - ut_ad(space->purpose == FIL_TYPE_TABLESPACE); + ut_ad(!space->is_temporary()); + ut_ad(!space->is_being_imported()); fil_space_crypt_t *crypt_data = space->crypt_data; @@ -1455,7 +1457,7 @@ space_list_t::iterator fil_space_t::next(space_list_t::iterator space, for (; space != fil_system.space_list.end(); ++space) { - if (space->purpose != FIL_TYPE_TABLESPACE) + if (space->is_temporary() || space->is_being_imported()) continue; const uint32_t n= space->acquire_low(); if (UNIV_LIKELY(!(n & (STOPPING | CLOSING)))) @@ -2137,9 +2139,9 @@ static void fil_crypt_default_encrypt_tables_fill() mysql_mutex_assert_owner(&fil_system.mutex); for (fil_space_t& space : fil_system.space_list) { - if (space.purpose != FIL_TYPE_TABLESPACE - || space.is_in_default_encrypt + if (space.is_in_default_encrypt || UT_LIST_GET_LEN(space.chain) == 0 + || space.is_temporary() || space.is_being_imported() || !space.acquire_if_not_stopped()) { continue; } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index a682fd533e9..1f72c2bbd1f 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -81,17 +81,10 @@ bool fil_space_t::try_to_close(fil_space_t *ignore_space, bool print_info) mysql_mutex_assert_owner(&fil_system.mutex); for (fil_space_t &space : fil_system.space_list) { - if (&space == ignore_space) + if (&space == ignore_space || space.is_being_imported() || + !fil_is_user_tablespace_id(space.id)) continue; - switch (space.purpose) { - case FIL_TYPE_TEMPORARY: - continue; - case FIL_TYPE_IMPORT: - break; - case FIL_TYPE_TABLESPACE: - if (!fil_is_user_tablespace_id(space.id)) - continue; - } + ut_ad(!space.is_temporary()); /* We are using an approximation of LRU replacement policy. In fil_node_open_file_low(), newly opened files are moved to the end @@ -432,7 +425,7 @@ static bool fil_node_open_file(fil_node_t *node, const byte *page, bool no_lsn) srv_operation == SRV_OPERATION_BACKUP || srv_operation == SRV_OPERATION_RESTORE || srv_operation == SRV_OPERATION_RESTORE_DELTA); - ut_ad(node->space->purpose != FIL_TYPE_TEMPORARY); + ut_ad(!node->space->is_temporary()); ut_ad(node->space->referenced()); const auto old_time= fil_system.n_open_exceeded_time; @@ -493,7 +486,7 @@ void fil_node_t::prepare_to_close_or_detach() srv_operation == SRV_OPERATION_RESTORE_DELTA); ut_a(is_open()); ut_a(!being_extended); - ut_a(space->is_ready_to_close() || space->purpose == FIL_TYPE_TEMPORARY || + ut_a(space->is_ready_to_close() || space->is_temporary() || srv_fast_shutdown == 2 || !srv_was_started); ut_a(fil_system.n_open > 0); @@ -650,14 +643,13 @@ fil_space_extend_must_retry( mysql_mutex_lock(&fil_system.mutex); break; default: - ut_ad(space->purpose == FIL_TYPE_TABLESPACE - || space->purpose == FIL_TYPE_IMPORT); - if (space->purpose == FIL_TYPE_TABLESPACE) { + ut_ad(!space->is_temporary()); + if (!space->is_being_imported()) { goto do_flush; } break; case SRV_TMP_SPACE_ID: - ut_ad(space->purpose == FIL_TYPE_TEMPORARY); + ut_ad(space->is_temporary()); srv_tmp_space.set_last_file_size(pages_in_MiB); break; } @@ -671,8 +663,7 @@ ATTRIBUTE_COLD bool fil_space_t::prepare_acquired() ut_ad(referenced()); mysql_mutex_assert_owner(&fil_system.mutex); fil_node_t *node= UT_LIST_GET_LAST(chain); - ut_ad(!id || purpose == FIL_TYPE_TEMPORARY || - node == UT_LIST_GET_FIRST(chain)); + ut_ad(!id || is_temporary() || node == UT_LIST_GET_FIRST(chain)); const bool is_open= node && (node->is_open() || fil_node_open_file(node, nullptr, false)); @@ -734,7 +725,7 @@ ATTRIBUTE_COLD bool fil_space_t::acquire_and_prepare() @return whether the tablespace is at least as big as requested */ bool fil_space_extend(fil_space_t *space, uint32_t size) { - ut_ad(!srv_read_only_mode || space->purpose == FIL_TYPE_TEMPORARY); + ut_ad(!srv_read_only_mode || space->is_temporary()); bool success= false; const bool acquired= space->acquire(); mysql_mutex_lock(&fil_system.mutex); @@ -942,111 +933,87 @@ fil_space_free( return(space != NULL); } -/** Create a tablespace in fil_system. -@param name tablespace name -@param id tablespace identifier -@param flags tablespace flags -@param purpose tablespace purpose -@param crypt_data encryption information -@param mode encryption mode -@param opened true if space files are opened -@return pointer to created tablespace, to be filled in with add() -@retval nullptr on failure (such as when the same tablespace exists) */ -fil_space_t *fil_space_t::create(ulint id, ulint flags, - fil_type_t purpose, - fil_space_crypt_t *crypt_data, - fil_encryption_t mode, - bool opened) +fil_space_t::fil_space_t(uint32_t id, ulint flags, bool being_imported, + fil_space_crypt_t *crypt_data) noexcept : + id(id), crypt_data(crypt_data), being_imported(being_imported), flags(flags) { - fil_space_t* space; + UT_LIST_INIT(chain, &fil_node_t::chain); +#ifndef SUX_LOCK_GENERIC + memset((void*) &latch, 0, sizeof latch); +#endif + latch.SRW_LOCK_INIT(fil_space_latch_key); +} - mysql_mutex_assert_owner(&fil_system.mutex); - ut_ad(fil_system.is_initialised()); - ut_ad(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, id)); - ut_ad(srv_page_size == UNIV_PAGE_SIZE_ORIG || flags != 0); +fil_space_t *fil_space_t::create(uint32_t id, ulint flags, + bool being_imported, + fil_space_crypt_t *crypt_data, + fil_encryption_t mode, + bool opened) noexcept +{ + mysql_mutex_assert_owner(&fil_system.mutex); + ut_ad(fil_system.is_initialised()); + ut_ad(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, id)); + ut_ad(srv_page_size == UNIV_PAGE_SIZE_ORIG || flags != 0); - DBUG_EXECUTE_IF("fil_space_create_failure", return(NULL);); + DBUG_EXECUTE_IF("fil_space_create_failure", return nullptr;); - fil_space_t** after = reinterpret_cast( - &fil_system.spaces.cell_get(id)->node); - for (; *after; after = &(*after)->hash) { - ut_a((*after)->id != id); - } + fil_space_t** after= fil_system.spaces.cell_get(id)->search + (&fil_space_t::hash, [id](const fil_space_t *space) + { return !space || space->id == id; }); + ut_a(!*after); + fil_space_t *space= new (ut_malloc_nokey(sizeof(*space))) + fil_space_t(id, flags, being_imported, crypt_data); + *after= space; - /* FIXME: if calloc() is defined as an inline function that calls - memset() or bzero(), then GCC 6 -flifetime-dse can optimize it away */ - *after = space = new (ut_zalloc_nokey(sizeof(*space))) fil_space_t; + if (crypt_data) + DBUG_PRINT("crypt", ("Tablespace %" PRIu32 " encryption %d key id %" PRIu32 + ":%s %s", + id, crypt_data->encryption, crypt_data->key_id, + fil_crypt_get_mode(crypt_data), + fil_crypt_get_type(crypt_data))); - space->id = id; + if (opened) + fil_system.add_opened_last_to_space_list(space); + else + fil_system.space_list.push_back(*space); - UT_LIST_INIT(space->chain, &fil_node_t::chain); + switch (id) { + case 0: + ut_ad(!fil_system.sys_space); + fil_system.sys_space= space; + break; + case SRV_TMP_SPACE_ID: + ut_ad(!fil_system.temp_space); + fil_system.temp_space= space; + return space; + default: + if (UNIV_LIKELY(id <= fil_system.max_assigned_id)) + break; + if (UNIV_UNLIKELY(srv_operation == SRV_OPERATION_BACKUP)) + break; + if (!fil_system.space_id_reuse_warned) + sql_print_warning("InnoDB: Allocated tablespace ID %" PRIu32 + ", old maximum was %" PRIu32, + id, fil_system.max_assigned_id); + fil_system.max_assigned_id = id; + } - space->purpose = purpose; - space->flags = flags; + if ((mode == FIL_ENCRYPTION_ON || + (mode == FIL_ENCRYPTION_OFF || srv_encrypt_tables)) && + !space->is_being_imported() && fil_crypt_must_default_encrypt()) + { + fil_system.default_encrypt_tables.push_back(*space); + space->is_in_default_encrypt= true; - space->crypt_data = crypt_data; - space->n_pending.store(CLOSING, std::memory_order_relaxed); + if (srv_n_fil_crypt_threads_started) + { + mysql_mutex_unlock(&fil_system.mutex); + fil_crypt_threads_signal(); + mysql_mutex_lock(&fil_system.mutex); + } + } - DBUG_LOG("tablespace", "Created metadata for " << id); - if (crypt_data) { - DBUG_LOG("crypt", - "Tablespace " << id - << " encryption " << crypt_data->encryption - << " key id " << crypt_data->key_id - << ":" << fil_crypt_get_mode(crypt_data) - << " " << fil_crypt_get_type(crypt_data)); - } - - space->latch.SRW_LOCK_INIT(fil_space_latch_key); - - if (opened) - fil_system.add_opened_last_to_space_list(space); - else - fil_system.space_list.push_back(*space); - - switch (id) { - case 0: - ut_ad(!fil_system.sys_space); - fil_system.sys_space = space; - break; - case SRV_TMP_SPACE_ID: - ut_ad(!fil_system.temp_space); - fil_system.temp_space = space; - break; - default: - ut_ad(purpose != FIL_TYPE_TEMPORARY); - if (UNIV_LIKELY(id <= fil_system.max_assigned_id)) { - break; - } - if (UNIV_UNLIKELY(srv_operation == SRV_OPERATION_BACKUP)) { - break; - } - if (!fil_system.space_id_reuse_warned) { - ib::warn() << "Allocated tablespace ID " << id - << ", old maximum was " - << fil_system.max_assigned_id; - } - - fil_system.max_assigned_id = id; - } - - const bool rotate = purpose == FIL_TYPE_TABLESPACE - && (mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF - || srv_encrypt_tables) - && fil_crypt_must_default_encrypt(); - - if (rotate) { - fil_system.default_encrypt_tables.push_back(*space); - space->is_in_default_encrypt = true; - - if (srv_n_fil_crypt_threads_started) { - mysql_mutex_unlock(&fil_system.mutex); - fil_crypt_threads_signal(); - mysql_mutex_lock(&fil_system.mutex); - } - } - - return(space); + return space; } /*******************************************************************//** @@ -1580,6 +1547,7 @@ fil_name_write( fil_space_t *fil_space_t::drop(ulint id, pfs_os_file_t *detached_handle) { ut_a(!is_system_tablespace(id)); + ut_ad(id != SRV_TMP_SPACE_ID); mysql_mutex_lock(&fil_system.mutex); fil_space_t *space= fil_space_get_by_id(id); @@ -1622,7 +1590,7 @@ fil_space_t *fil_space_t::drop(ulint id, pfs_os_file_t *detached_handle) if (space->crypt_data) fil_space_crypt_close_tablespace(space); - if (space->purpose == FIL_TYPE_TABLESPACE) + if (!space->is_being_imported()) { /* Before deleting the file, persistently write a log record. */ mtr_t mtr; @@ -1635,8 +1603,6 @@ fil_space_t *fil_space_t::drop(ulint id, pfs_os_file_t *detached_handle) os_file_delete(innodb_data_file_key, space->chain.start->name); } - else - ut_ad(space->purpose == FIL_TYPE_IMPORT); if (char *cfg_name= fil_make_filepath(space->chain.start->name, fil_space_t::name_type{}, CFG, false)) @@ -1935,7 +1901,7 @@ fil_ibd_create( uint32_t size, fil_encryption_t mode, uint32_t key_id, - dberr_t* err) + dberr_t* err) noexcept { pfs_os_file_t file; bool success; @@ -2055,8 +2021,8 @@ err_exit: log_make_checkpoint();); mysql_mutex_lock(&fil_system.mutex); - if (fil_space_t* space = fil_space_t::create(space_id, flags, - FIL_TYPE_TABLESPACE, + if (fil_space_t* space = fil_space_t::create(uint32_t(space_id), + flags, false, crypt_data, mode, true)) { fil_node_t* node = space->add(path, file, size, false, true); node->find_metadata(IF_WIN(,true)); @@ -2078,51 +2044,17 @@ err_exit: goto err_exit; } -/** Try to open a single-table tablespace and optionally check that the -space id in it is correct. If this does not succeed, print an error message -to the .err log. This function is used to open a tablespace when we start -mysqld after the dictionary has been booted, and also in IMPORT TABLESPACE. - -NOTE that we assume this operation is used either at the database startup -or under the protection of dict_sys.latch, so that two users cannot -race here. This operation does not leave the file associated with the -tablespace open, but closes it after we have looked at the space id in it. - -If the validate boolean is set, we read the first page of the file and -check that the space id in the file is what we expect. We assume that -this function runs much faster if no check is made, since accessing the -file inode probably is much faster (the OS caches them) than accessing -the first page of the file. This boolean may be initially false, but if -a remote tablespace is found it will be changed to true. - -If the fix_dict boolean is set, then it is safe to use an internal SQL -statement to update the dictionary tables if they are incorrect. - -@param[in] validate 0=maybe missing, 1=do not validate, 2=validate -@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_TEMPORARY -@param[in] id tablespace ID -@param[in] flags expected FSP_SPACE_FLAGS -@param[in] name table name -If file-per-table, it is the table name in the databasename/tablename format -@param[in] path_in expected filepath, usually read from dictionary -@param[out] err DB_SUCCESS or error code -@return tablespace -@retval NULL if the tablespace could not be opened */ -fil_space_t* -fil_ibd_open( - unsigned validate, - fil_type_t purpose, - ulint id, - ulint flags, - fil_space_t::name_type name, - const char* path_in, - dberr_t* err) +fil_space_t *fil_ibd_open(ulint id, ulint flags, + fil_space_t::validate validate, + fil_space_t::name_type name, + const char *path_in, dberr_t *err) noexcept { mysql_mutex_lock(&fil_system.mutex); fil_space_t* space = fil_space_get_by_id(id); mysql_mutex_unlock(&fil_system.mutex); if (space) { - if (validate > 1 && !srv_read_only_mode) { + if (validate == fil_space_t::VALIDATE_SPACE_ID + && !srv_read_only_mode) { fsp_flags_try_adjust(space, flags & ~FSP_FLAGS_MEM_MASK); } @@ -2148,8 +2080,8 @@ func_exit: ulint tablespaces_found = 0; ulint valid_tablespaces_found = 0; - df_default.init(flags); - df_remote.init(flags); + df_default.init(uint32_t(flags)); + df_remote.init(uint32_t(flags)); /* Discover the correct file by looking in three possible locations while avoiding unecessary effort. */ @@ -2178,7 +2110,7 @@ func_exit: /* Dict path is not the default path. Always validate remote files. If default is opened, it was moved. */ must_validate = true; - } else if (validate > 1) { + } else if (validate >= fil_space_t::VALIDATE_SPACE_ID) { must_validate = true; } @@ -2195,7 +2127,8 @@ func_exit: the first server startup. The tables ought to be dropped by drop_garbage_tables_after_restore() a little later. */ - const bool strict = validate && !tablespaces_found + const bool strict = (validate != fil_space_t::MAYBE_MISSING) + && !tablespaces_found && operation_not_for_export && !(srv_operation == SRV_OPERATION_NORMAL && srv_start_after_restore @@ -2326,7 +2259,9 @@ skip_validate: : NULL; mysql_mutex_lock(&fil_system.mutex); - space = fil_space_t::create(id, flags, purpose, crypt_data); + space = fil_space_t::create(uint32_t(id), flags, + validate == fil_space_t::VALIDATE_IMPORT, + crypt_data); if (!space) { mysql_mutex_unlock(&fil_system.mutex); goto error; @@ -2344,7 +2279,7 @@ skip_validate: df_remote.close(); df_default.close(); if (space->acquire()) { - if (purpose != FIL_TYPE_IMPORT) { + if (validate < fil_space_t::VALIDATE_IMPORT) { fsp_flags_try_adjust(space, flags & ~FSP_FLAGS_MEM_MASK); } @@ -2632,8 +2567,8 @@ tablespace_check: mysql_mutex_lock(&fil_system.mutex); - space = fil_space_t::create( - space_id, flags, FIL_TYPE_TABLESPACE, crypt_data); + space = fil_space_t::create(uint32_t(space_id), flags, false, + crypt_data); if (space == NULL) { mysql_mutex_unlock(&fil_system.mutex); @@ -2661,16 +2596,14 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags) { ut_ad(!srv_read_only_mode); ut_ad(fil_space_t::is_valid_flags(flags, space->id)); + ut_ad(!space->is_being_imported()); + ut_ad(!space->is_temporary()); if (space->full_crc32() || fil_space_t::full_crc32(flags)) { return; } - if (!space->size && (space->purpose != FIL_TYPE_TABLESPACE - || !space->get_size())) { + if (!space->size || !space->get_size()) { return; } - /* This code is executed during server startup while no - connections are allowed. We do not need to protect against - DROP TABLE by fil_space_acquire(). */ mtr_t mtr; mtr.start(); if (buf_block_t* b = buf_page_get( @@ -2760,7 +2693,7 @@ inline void fil_node_t::complete_write() { mysql_mutex_assert_not_owner(&fil_system.mutex); - if (space->purpose != FIL_TYPE_TEMPORARY && + if (!space->is_temporary() && srv_file_flush_method != SRV_O_DIRECT_NO_FSYNC && space->set_needs_flush()) { @@ -3074,8 +3007,8 @@ fil_space_validate_for_mtr_commit( { mysql_mutex_assert_not_owner(&fil_system.mutex); ut_ad(space != NULL); - ut_ad(space->purpose == FIL_TYPE_TABLESPACE); ut_ad(!is_predefined_tablespace(space->id)); + ut_ad(!space->is_being_imported()); /* We are serving mtr_commit(). While there is an active mini-transaction, we should have !space->is_stopping(). This is @@ -3290,7 +3223,7 @@ fil_space_t::name_type fil_space_t::name() const if (!UT_LIST_GET_FIRST(chain) || srv_is_undo_tablespace(id)) return name_type{}; - ut_ad(purpose != FIL_TYPE_TEMPORARY); + ut_ad(!is_temporary()); ut_ad(UT_LIST_GET_LEN(chain) == 1); const char *path= UT_LIST_GET_FIRST(chain)->name; diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 3f94e8fb569..40bfca1388c 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -352,7 +352,7 @@ xdes_get_descriptor_with_space_hdr( ut_ad(limit == space->free_limit || (space->free_limit == 0 && (init_space - || space->purpose == FIL_TYPE_TEMPORARY + || space->is_temporary() || (srv_startup_is_before_trx_rollback_phase && (space->id == TRX_SYS_SPACE || srv_is_undo_tablespace(space->id)))))); @@ -490,14 +490,15 @@ void fil_space_t::modify_check(const mtr_t& mtr) const case MTR_LOG_NONE: /* These modes are only allowed within a non-bitmap page when there is a higher-level redo log record written. */ - ut_ad(purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_TEMPORARY); + ut_ad(!is_being_imported()); break; case MTR_LOG_NO_REDO: - ut_ad(purpose == FIL_TYPE_TEMPORARY || purpose == FIL_TYPE_IMPORT); + ut_ad(is_temporary() || is_being_imported()); break; default: /* We may only write redo log for a persistent tablespace. */ - ut_ad(purpose == FIL_TYPE_TABLESPACE); + ut_ad(!is_temporary()); + ut_ad(!is_being_imported()); ut_ad(mtr.is_named_space(id)); } } @@ -857,7 +858,7 @@ fsp_fill_free_list( FIL_PAGE_TYPE_XDES); } - if (space->purpose != FIL_TYPE_TEMPORARY) + if (!space->is_temporary()) { buf_block_t *f= buf_LRU_get_free_block(false); buf_block_t *block= diff --git a/storage/innobase/fsp/fsp0space.cc b/storage/innobase/fsp/fsp0space.cc index 8c6344946a4..e72ddfef7ed 100644 --- a/storage/innobase/fsp/fsp0space.cc +++ b/storage/innobase/fsp/fsp0space.cc @@ -132,10 +132,8 @@ Tablespace::open_or_create(bool is_temp) mysql_mutex_lock(&fil_system.mutex); space = fil_space_t::create( - m_space_id, fsp_flags, - is_temp - ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE, - NULL); + uint32_t(m_space_id), fsp_flags, + false, nullptr); if (!space) { mysql_mutex_unlock(&fil_system.mutex); return DB_ERROR; diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index 2a60f60b43d..dbc5987b2e5 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -936,8 +936,7 @@ SysTablespace::open_or_create( } else if (is_temp) { ut_ad(space_id() == SRV_TMP_SPACE_ID); space = fil_space_t::create( - SRV_TMP_SPACE_ID, flags(), - FIL_TYPE_TEMPORARY, NULL); + SRV_TMP_SPACE_ID, flags(), false, nullptr); ut_ad(space == fil_system.temp_space); if (!space) { err = DB_ERROR; @@ -948,8 +947,7 @@ SysTablespace::open_or_create( } else { ut_ad(space_id() == TRX_SYS_SPACE); space = fil_space_t::create( - TRX_SYS_SPACE, it->flags(), - FIL_TYPE_TABLESPACE, NULL); + TRX_SYS_SPACE, it->flags(), false, nullptr); ut_ad(space == fil_system.sys_space); if (!space) { err = DB_ERROR; diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 604ce85e93e..c38ff61b0e4 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -6562,7 +6562,8 @@ static int i_s_sys_tablespaces_fill_table(THD *thd, TABLE_LIST *tables, Item*) for (fil_space_t &space : fil_system.space_list) { - if (space.purpose == FIL_TYPE_TABLESPACE && !space.is_stopping() && + if (!space.is_temporary() && !space.is_being_imported() && + !space.is_stopping() && space.chain.start) { space.reacquire(); @@ -6734,7 +6735,7 @@ i_s_dict_fill_tablespaces_encryption( } else if (srv_is_undo_tablespace(space->id)) { char undo_name[sizeof "innodb_undo000"]; snprintf(undo_name, sizeof(undo_name), - "innodb_undo%03zu",space->id); + "innodb_undo%03" PRIu32, space->id); OK(fields[TABLESPACES_ENCRYPTION_NAME]->store( undo_name, strlen(undo_name), system_charset_info)); @@ -6802,7 +6803,7 @@ i_s_tablespaces_encryption_fill_table( fil_system.freeze_space_list++; for (fil_space_t& space : fil_system.space_list) { - if (space.purpose == FIL_TYPE_TABLESPACE + if (!space.is_temporary() && !space.is_being_imported() && !space.is_stopping()) { space.reacquire(); mysql_mutex_unlock(&fil_system.mutex); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 750df18dc8d..3e8f7888959 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -738,13 +738,15 @@ ibuf_set_free_bits_func( mtr.start(); const page_id_t id(block->page.id()); const fil_space_t *space= mtr.set_named_space_id(id.space()); + /* all callers of ibuf_update_free_bits_if_full() or ibuf_reset_free_bits() + check this */ + ut_ad(!space->is_temporary()); if (buf_block_t *bitmap_page= ibuf_bitmap_get_map_page(id, block->zip_size(), &mtr)) { - if (space->purpose != FIL_TYPE_TABLESPACE) + if (space->is_being_imported()) /* IndexPurge may invoke this */ mtr.set_log_mode(MTR_LOG_NO_REDO); - #ifdef UNIV_IBUF_DEBUG if (max_val != ULINT_UNDEFINED) { @@ -925,8 +927,7 @@ ibuf_page_low( return(false); } - compile_time_assert(IBUF_SPACE_ID == 0); - ut_ad(fil_system.sys_space->purpose == FIL_TYPE_TABLESPACE); + static_assert(IBUF_SPACE_ID == 0, "compatiblity"); #ifdef UNIV_DEBUG if (x_latch) { @@ -4498,7 +4499,7 @@ ibuf_print( dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) { ut_ad(trx->mysql_thd); - ut_ad(space->purpose == FIL_TYPE_IMPORT); + ut_ad(space->is_being_imported()); const unsigned zip_size = space->zip_size(); const unsigned physical_size = space->physical_size(); diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 8e5357912d3..ff627e81eb2 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -100,16 +100,6 @@ class page_id_t; /** Structure containing encryption specification */ struct fil_space_crypt_t; -/** File types */ -enum fil_type_t { - /** temporary tablespace (temporary undo log or tables) */ - FIL_TYPE_TEMPORARY, - /** a tablespace that is being imported (no logging until finished) */ - FIL_TYPE_IMPORT, - /** persistent tablespace (for system, undo log or tables) */ - FIL_TYPE_TABLESPACE, -}; - struct fil_node_t; /** Structure to store first and last value of range */ @@ -344,42 +334,43 @@ struct fil_space_t final { #ifndef UNIV_INNOCHECKSUM friend fil_node_t; + + /** Constructor; see @fil_space_t::create() */ + inline explicit fil_space_t(uint32_t id, ulint flags, bool being_imported, + fil_space_crypt_t *crypt_data) noexcept; + ~fil_space_t() { ut_ad(!latch_owner); latch.destroy(); } - ulint id; /*!< space id */ + /** tablespace identifier */ + uint32_t id; /** fil_system.spaces chain node */ - fil_space_t *hash; - lsn_t max_lsn; - /*!< LSN of the most recent - fil_names_write_if_was_clean(). - Reset to 0 by fil_names_clear(). - Protected by log_sys.mutex. - If and only if this is nonzero, the - tablespace will be in named_spaces. */ - fil_type_t purpose;/*!< purpose */ - UT_LIST_BASE_NODE_T(fil_node_t) chain; - /*!< base node for the file chain */ - uint32_t size; /*!< tablespace file size in pages; - 0 if not known yet */ - uint32_t size_in_header; - /* FSP_SIZE in the tablespace header; - 0 if not known yet */ - uint32_t free_len; - /*!< length of the FSP_FREE list */ - uint32_t free_limit; - /*!< contents of FSP_FREE_LIMIT */ - uint32_t recv_size; - /*!< recovered tablespace size in pages; - 0 if no size change was read from the redo log, - or if the size change was implemented */ - uint32_t n_reserved_extents; - /*!< number of reserved free extents for - ongoing operations like B-tree page split */ + fil_space_t *hash= nullptr; + /** log_sys.get_lsn() of the most recent fil_names_write_if_was_clean(). + Reset to 0 by fil_names_clear(). Protected by log_sys.mutex. + If and only if this is nonzero, the tablespace will be in named_spaces. */ + lsn_t max_lsn= 0; + /** base node for the chain of data files; multiple entries are + only possible for is_temporary() or id==0 */ + UT_LIST_BASE_NODE_T(fil_node_t) chain; + /** tablespace size in pages; 0 if not determined yet */ + uint32_t size= 0; + /** FSP_SIZE in the tablespace header; 0 if not determined yet */ + uint32_t size_in_header= 0; + /** length of the FSP_FREE list */ + uint32_t free_len= 0; + /** contents of FSP_FREE_LIMIT */ + uint32_t free_limit= 0; + /** recovered tablespace size in pages; 0 if no size change was read + from the redo log, or if the size change was applied */ + uint32_t recv_size= 0; + /** number of reserved free extents for ongoing operations like + B-tree page split */ + uint32_t n_reserved_extents= 0; private: #ifdef UNIV_DEBUG fil_space_t *next_in_space_list(); @@ -390,10 +381,10 @@ private: #endif /** the committed size of the tablespace in pages */ - Atomic_relaxed committed_size; + Atomic_relaxed committed_size{0}; /** Number of pending operations on the file. The tablespace cannot be freed while (n_pending & PENDING) != 0. */ - std::atomic n_pending; + std::atomic n_pending{CLOSING}; /** Flag in n_pending that indicates that the tablespace is about to be deleted, and no further operations should be performed */ static constexpr uint32_t STOPPING_READS= 1U << 31; @@ -415,20 +406,23 @@ private: /** latch protecting all page allocation bitmap pages */ IF_DBUG(srw_lock_debug, srw_lock) latch; /** the thread that holds the exclusive latch, or 0 */ - pthread_t latch_owner; + pthread_t latch_owner= 0; public: /** MariaDB encryption data */ - fil_space_crypt_t *crypt_data; + fil_space_crypt_t *crypt_data= nullptr; /** Whether needs_flush(), or this is in fil_system.unflushed_spaces */ - bool is_in_unflushed_spaces; + bool is_in_unflushed_spaces= false; /** Whether this in fil_system.default_encrypt_tables (needs key rotation) */ - bool is_in_default_encrypt; + bool is_in_default_encrypt= false; private: + /** Whether the tablespace is being imported */ + bool being_imported= false; + /** Whether any corrupton of this tablespace has been reported */ - mutable std::atomic_flag is_corrupted; + mutable std::atomic_flag is_corrupted{false}; /** mutex to protect freed_ranges and last_freed_lsn */ std::mutex freed_range_mutex; @@ -437,11 +431,18 @@ private: range_set freed_ranges; /** LSN of freeing last page; protected by freed_range_mutex */ - lsn_t last_freed_lsn; + lsn_t last_freed_lsn= 0; /** LSN of undo tablespace creation or 0; protected by latch */ - lsn_t create_lsn; + lsn_t create_lsn= 0; public: + /** @return whether this is the temporary tablespace */ + bool is_temporary() const noexcept + { return UNIV_UNLIKELY(id == SRV_TMP_SPACE_ID); } + /** @return whether this tablespace is being imported */ + bool is_being_imported() const noexcept + { return UNIV_UNLIKELY(being_imported); } + /** @return whether doublewrite buffering is needed */ inline bool use_doublewrite() const; @@ -511,7 +512,7 @@ public: MY_ATTRIBUTE((nonnull)); /** Note that the tablespace has been imported. - Initially, purpose=FIL_TYPE_IMPORT so that no redo log is + Initially, purpose=IMPORT so that no redo log is written while the space ID is being updated in each page. */ inline void set_imported(); @@ -946,18 +947,18 @@ public: #ifndef UNIV_INNOCHECKSUM MY_ATTRIBUTE((warn_unused_result)) /** Create a tablespace in fil_system. - @param id tablespace identifier - @param flags tablespace flags - @param purpose tablespace purpose - @param crypt_data encryption information - @param mode encryption mode - @param opened true if space files are opened + @param id tablespace identifier + @param flags tablespace flags + @param being_imported whether this is IMPORT TABLESPACE + @param crypt_data encryption information + @param mode encryption mode + @param opened whether the tablespace files are open @return pointer to created tablespace, to be filled in with add() @retval nullptr on failure (such as when the same tablespace exists) */ - static fil_space_t *create(ulint id, ulint flags, - fil_type_t purpose, fil_space_crypt_t *crypt_data, + static fil_space_t *create(uint32_t id, ulint flags, bool being_imported, + fil_space_crypt_t *crypt_data, fil_encryption_t mode= FIL_ENCRYPTION_DEFAULT, - bool opened= false); + bool opened= false) noexcept; MY_ATTRIBUTE((warn_unused_result)) /** Acquire a tablespace reference. @@ -1079,6 +1080,18 @@ public: /** @return the tablespace name (databasename/tablename) */ name_type name() const; + /** How to validate tablespace files that are being opened */ + enum validate { + /** the file may be missing */ + MAYBE_MISSING= 0, + /** do not validate */ + VALIDATE_NOTHING, + /** validate the tablespace ID */ + VALIDATE_SPACE_ID, + /** opening a file for ALTER TABLE...IMPORT TABLESPACE */ + VALIDATE_IMPORT + }; + private: /** @return whether the file is usable for io() */ ATTRIBUTE_COLD bool prepare_acquired(); @@ -1163,8 +1176,8 @@ inline bool fil_space_t::use_doublewrite() const inline void fil_space_t::set_imported() { - ut_ad(purpose == FIL_TYPE_IMPORT); - purpose= FIL_TYPE_TABLESPACE; + ut_ad(being_imported); + being_imported= false; UT_LIST_GET_FIRST(chain)->find_metadata(); } @@ -1478,12 +1491,9 @@ public: ulint n_open; /** last time we noted n_open exceeding the limit; protected by mutex */ time_t n_open_exceeded_time; - ulint max_assigned_id;/*!< maximum space id in the existing - tables, or assigned during the time - mysqld has been up; at an InnoDB - startup we scan the data dictionary - and set here the maximum of the - space id's of the tables there */ + /** maximum space id in the existing tables; on InnoDB startup this is + initialized based on the data dictionary contents */ + ulint max_assigned_id; /** nonzero if fil_node_open_file_low() should avoid moving the tablespace to the end of space_list, for FIFO policy of try_to_close() */ ulint freeze_space_list; @@ -1588,7 +1598,7 @@ template inline void fil_space_t::flush() { mysql_mutex_assert_not_owner(&fil_system.mutex); ut_ad(!have_reference || (pending() & PENDING)); - ut_ad(purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_IMPORT); + ut_ad(!is_temporary()); if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) { ut_ad(!is_in_unflushed_spaces); @@ -1729,7 +1739,7 @@ fil_ibd_create( uint32_t size, fil_encryption_t mode, uint32_t key_id, - dberr_t* err) + dberr_t* err) noexcept MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations. @@ -1738,43 +1748,28 @@ fil_ibd_create( @param[in] flags desired tablespace flags */ void fsp_flags_try_adjust(fil_space_t* space, ulint flags); -/********************************************************************//** +/** Tries to open a single-table tablespace and optionally checks the space id is right in it. If does not succeed, prints an error message to the .err log. This function is used to open a tablespace when we start up mysqld, and also in IMPORT TABLESPACE. -NOTE that we assume this operation is used either at the database startup -or under the protection of dict_sys.latch, so that two users cannot -race here. This operation does not leave the file associated with the -tablespace open, but closes it after we have looked at the space id in it. -If the validate boolean is set, we read the first page of the file and -check that the space id in the file is what we expect. We assume that -this function runs much faster if no check is made, since accessing the -file inode probably is much faster (the OS caches them) than accessing -the first page of the file. This boolean may be initially false, but if -a remote tablespace is found it will be changed to true. +NOTE that we assume this operation is used either at the database +startup or under the protection of MDL, to prevent concurrent access +to the same tablespace. -@param[in] validate 0=maybe missing, 1=do not validate, 2=validate -@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_TEMPORARY -@param[in] id tablespace ID -@param[in] flags expected FSP_SPACE_FLAGS -@param[in] name table name -If file-per-table, it is the table name in the databasename/tablename format -@param[in] path_in expected filepath, usually read from dictionary -@param[out] err DB_SUCCESS or error code +@param id tablespace identifier +@param flags expected FSP_SPACE_FLAGS +@param validate how to validate files +@param name the table name in databasename/tablename format +@param path_in expected filepath, usually read from dictionary +@param err DB_SUCCESS or error code @return tablespace -@retval NULL if the tablespace could not be opened */ -fil_space_t* -fil_ibd_open( - unsigned validate, - fil_type_t purpose, - ulint id, - ulint flags, - fil_space_t::name_type name, - const char* path_in, - dberr_t* err = NULL) - MY_ATTRIBUTE((warn_unused_result)); +@retval nullptr if the tablespace could not be opened */ +fil_space_t *fil_ibd_open(ulint id, ulint flags, + fil_space_t::validate validate, + fil_space_t::name_type name, + const char *path_in, dberr_t *err= nullptr) noexcept; enum fil_load_status { /** The tablespace file(s) were found and valid. */ diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 773bd4c9f86..fb7028126c8 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -93,9 +93,9 @@ void recv_sys_justify_left_parsing_buf(); @param[in] len length of name, in bytes @param[in] new_name new file name (NULL if not rename) @param[in] new_len length of new_name, in bytes (0 if NULL) */ -extern void (*log_file_op)(ulint space_id, int type, - const byte* name, ulint len, - const byte* new_name, ulint new_len); +extern void (*log_file_op)(uint32_t space_id, int type, + const byte* name, size_t len, + const byte* new_name, size_t new_len); /** Report an operation which does undo log tablespace truncation during backup @@ -104,7 +104,7 @@ extern void (*undo_space_trunc)(uint32_t space_id); /** Report an operation which does INIT_PAGE for page0 during backup. @param space_id tablespace identifier */ -extern void (*first_page_init)(ulint space_id); +extern void (*first_page_init)(uint32_t space_id); /** Stored redo log record */ struct log_rec_t diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 2c9c93a42fa..cb408313279 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -598,10 +598,10 @@ struct file_name_t { /** Map of dirty tablespaces during recovery */ typedef std::map< - ulint, + uint32_t, file_name_t, std::less, - ut_allocator > > recv_spaces_t; + ut_allocator > > recv_spaces_t; static recv_spaces_t recv_spaces; @@ -820,8 +820,8 @@ processed: if (crypt_data && !fil_crypt_check(crypt_data, name.c_str())) return nullptr; mysql_mutex_lock(&fil_system.mutex); - fil_space_t *space= fil_space_t::create(it->first, flags, - FIL_TYPE_TABLESPACE, crypt_data); + fil_space_t *space= fil_space_t::create(it->first, flags, false, + crypt_data); ut_ad(space); const char *filename= name.c_str(); if (srv_operation == SRV_OPERATION_RESTORE) @@ -939,13 +939,13 @@ deferred_spaces; @param[in] len length of name, in bytes @param[in] new_name new file name (NULL if not rename) @param[in] new_len length of new_name, in bytes (0 if NULL) */ -void (*log_file_op)(ulint space_id, int type, - const byte* name, ulint len, - const byte* new_name, ulint new_len); +void (*log_file_op)(uint32_t space_id, int type, + const byte* name, size_t len, + const byte* new_name, size_t new_len); void (*undo_space_trunc)(uint32_t space_id); -void (*first_page_init)(ulint space_id); +void (*first_page_init)(uint32_t space_id); /** Information about initializing page contents during redo log processing. FIXME: Rely on recv_sys.pages! */ @@ -4203,7 +4203,7 @@ recv_validate_tablespace(bool rescan, bool& missing_tablespace) for (recv_sys_t::map::iterator p = recv_sys.pages.begin(); p != recv_sys.pages.end();) { ut_ad(!p->second.log.empty()); - const ulint space = p->first.space(); + const uint32_t space = p->first.space(); if (is_predefined_tablespace(space)) { next: p++; @@ -4213,7 +4213,7 @@ next: recv_spaces_t::iterator i = recv_spaces.find(space); ut_ad(i != recv_spaces.end()); - if (deferred_spaces.find(static_cast(space))) { + if (deferred_spaces.find(space)) { /* Skip redo logs belonging to incomplete tablespaces */ goto next; diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index d6306f7b1c1..834bceaa8e2 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -488,8 +488,7 @@ mtr_t::x_lock_space(ulint space_id) } else { space = fil_space_get(space_id); ut_ad(m_log_mode != MTR_LOG_NO_REDO - || space->purpose == FIL_TYPE_TEMPORARY - || space->purpose == FIL_TYPE_IMPORT); + || space->is_temporary() || space->is_being_imported()); } ut_ad(space); @@ -502,9 +501,6 @@ mtr_t::x_lock_space(ulint space_id) @param space tablespace */ void mtr_t::x_lock_space(fil_space_t *space) { - ut_ad(space->purpose == FIL_TYPE_TEMPORARY || - space->purpose == FIL_TYPE_IMPORT || - space->purpose == FIL_TYPE_TABLESPACE); if (!memo_contains(*space)) { memo_push(space, MTR_MEMO_SPACE_X_LOCK); diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index b73fe21216b..25f47cb032d 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -3947,13 +3947,19 @@ void fil_node_t::find_metadata(IF_WIN(,bool create)) noexcept punch_hole= 2; else punch_hole= IF_WIN(, !create ||) os_is_sparse_file_supported(file); - if (space->purpose != FIL_TYPE_TABLESPACE) + /* For temporary tablespace or during IMPORT TABLESPACE, we + disable neighbour flushing and do not care about atomicity. */ + if (space->is_temporary()) { - /* For temporary tablespace or during IMPORT TABLESPACE, we - disable neighbour flushing and do not care about atomicity. */ on_ssd= true; atomic_write= true; - if (space->purpose == FIL_TYPE_TEMPORARY || !space->is_compressed()) + return; + } + if (space->is_being_imported()) + { + on_ssd= true; + atomic_write= true; + if (!space->is_compressed()) return; } #ifdef _WIN32 diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 0be420147c0..a7557044056 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -4841,11 +4841,10 @@ import_error: we will not be writing any redo log for it before we have invoked fil_space_t::set_imported() to declare it a persistent tablespace. */ - ulint fsp_flags = dict_tf_to_fsp_flags(table->flags); - - table->space = fil_ibd_open( - 2, FIL_TYPE_IMPORT, table->space_id, - fsp_flags, name, filepath, &err); + table->space = fil_ibd_open(table->space_id, + dict_tf_to_fsp_flags(table->flags), + fil_space_t::VALIDATE_IMPORT, + name, filepath, &err); ut_ad((table->space == NULL) == (err != DB_SUCCESS)); DBUG_EXECUTE_IF("ib_import_open_tablespace_failure", @@ -4947,8 +4946,6 @@ import_error: } ib::info() << "Phase IV - Flush complete"; - /* Set tablespace purpose as FIL_TYPE_TABLESPACE, - so that rollback can go ahead smoothly */ table->space->set_imported(); err = lock_sys_tables(trx); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 727a9f4d4fc..c3397c88336 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -575,9 +575,9 @@ err_exit: fil_set_max_space_id_if_bigger(space_id); mysql_mutex_lock(&fil_system.mutex); - fil_space_t *space= fil_space_t::create(space_id, fsp_flags, - FIL_TYPE_TABLESPACE, nullptr, - FIL_ENCRYPTION_DEFAULT, true); + fil_space_t *space= fil_space_t::create(uint32_t(space_id), + fsp_flags, false, nullptr, + FIL_ENCRYPTION_DEFAULT, true); ut_ad(space); fil_node_t *file= space->add(name, fh, 0, false, true); diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index 614e34e5a8a..df3755f6c10 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -238,7 +238,8 @@ static trx_rseg_t *trx_rseg_create(ulint space_id) if (fil_space_t *space= mtr.x_lock_space(space_id)) { - ut_ad(space->purpose == FIL_TYPE_TABLESPACE); + ut_ad(!space->is_temporary()); + ut_ad(!space->is_being_imported()); if (buf_block_t *sys_header= trx_sysf_get(&mtr)) { ulint rseg_id= trx_sys_rseg_find_free(sys_header);