From 861038f2e8e68574ef3d9e2e250ac71fdd7a4c53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 26 Nov 2018 17:30:39 +0200 Subject: MDEV-17816: Follow-up fix When dropping a partially created table due to failure, use SQLCOM_TRUNCATE instead of SQLCOM_DROP_DB, so that no foreign key constraints will be touched. If any constraints were added as part of the creation, they would be reverted as part of the transaction rollback. We need an explicit call to row_drop_table_for_mysql(), because InnoDB does not do proper undo logging for CREATE TABLE, but would only drop the table at the end of the rollback. This would not work if the transaction combines both RENAME and CREATE, like TRUNCATE now does. --- storage/innobase/handler/ha_innodb.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 2a73afafcb4..00672bf91bd 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12613,7 +12613,7 @@ int create_table_info_t::create_table(bool create_fk) the failed creation. */ m_trx->error_state = DB_SUCCESS; row_drop_table_for_mysql(m_table_name, m_trx, - SQLCOM_DROP_DB); + SQLCOM_TRUNCATE); trx_rollback_to_savepoint(m_trx, NULL); m_trx->error_state = DB_SUCCESS; @@ -12861,7 +12861,7 @@ ha_innobase::create( that could have been renamed before the failed creation. */ trx->error_state = DB_SUCCESS; row_drop_table_for_mysql(info.table_name(), trx, - SQLCOM_DROP_DB, true); + SQLCOM_TRUNCATE, true); trx_rollback_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); if (own_trx) { -- cgit v1.2.1 From b9824074a66b4cb6125820448b27937be23b0f8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 27 Nov 2018 14:02:24 +0200 Subject: MDEV-17851 Assertion failure srv_undo_tablespaces > 1 trx_assign_rseg_low(): Skip dedicated undo tablespaces if innodb_undo_tablespaces=0 has been set after the database was created. --- storage/innobase/trx/trx0trx.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index b56cb9609ab..93fc1bb0ed2 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1002,9 +1002,7 @@ trx_lists_init_at_db_start() evenly distributed between 0 and innodb_undo_logs-1 @return persistent rollback segment @retval NULL if innodb_read_only */ -static -trx_rseg_t* -trx_assign_rseg_low() +static trx_rseg_t* trx_assign_rseg_low() { if (srv_read_only_mode) { ut_ad(srv_undo_logs == ULONG_UNDEFINED); @@ -1055,8 +1053,8 @@ trx_assign_rseg_low() ut_ad(rseg->is_persistent()); if (rseg->space != TRX_SYS_SPACE) { - ut_ad(srv_undo_tablespaces > 1); - if (rseg->skip_allocation) { + if (rseg->skip_allocation + || !srv_undo_tablespaces) { continue; } } else if (trx_rseg_t* next -- cgit v1.2.1 From eb6364619ff807645230479bf7d2eb87d1a4edb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 27 Nov 2018 14:28:07 +0200 Subject: Remove the redundant variable fil_n_file_opened --- extra/mariabackup/fil_cur.cc | 2 -- storage/innobase/fil/fil0fil.cc | 5 ----- storage/innobase/include/fil0fil.h | 3 --- storage/innobase/include/srv0srv.h | 2 +- storage/innobase/srv/srv0mon.cc | 2 +- storage/innobase/srv/srv0srv.cc | 2 +- 6 files changed, 3 insertions(+), 13 deletions(-) diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index f5b3db1e184..7b7cfb3c948 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -110,7 +110,6 @@ xb_fil_node_close_file( ut_a(fil_system->n_open > 0); fil_system->n_open--; - fil_n_file_opened--; if (node->space->purpose == FIL_TYPE_TABLESPACE && fil_is_user_tablespace_id(node->space->id)) { @@ -179,7 +178,6 @@ xb_fil_cur_open( mutex_enter(&fil_system->mutex); fil_system->n_open++; - fil_n_file_opened++; if (node->space->purpose == FIL_TYPE_TABLESPACE && fil_is_user_tablespace_id(node->space->id)) { diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 6c5ae70a2cc..6368d4b4751 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -138,9 +138,6 @@ ulint fil_n_pending_log_flushes = 0; /** Number of pending tablespace flushes */ ulint fil_n_pending_tablespace_flushes = 0; -/** Number of files currently open */ -ulint fil_n_file_opened = 0; - /** The null file address */ fil_addr_t fil_addr_null = {FIL_NULL, 0}; @@ -758,7 +755,6 @@ retry: ut_a(node->is_open()); fil_system->n_open++; - fil_n_file_opened++; if (fil_space_belongs_in_lru(space)) { @@ -797,7 +793,6 @@ fil_node_close_file( ut_ad(!node->is_open()); ut_a(fil_system->n_open > 0); fil_system->n_open--; - fil_n_file_opened--; if (fil_space_belongs_in_lru(node->space)) { diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 34bf216fd97..d1bd2dc14d4 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -443,9 +443,6 @@ extern ulint fil_n_pending_log_flushes; /** Number of pending tablespace flushes */ extern ulint fil_n_pending_tablespace_flushes; -/** Number of files currently open */ -extern ulint fil_n_file_opened; - #ifndef UNIV_INNOCHECKSUM /** Look up a tablespace. diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 4117a3f0dd3..7ad5d2f2183 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -1020,7 +1020,7 @@ struct export_var_t{ ulint innodb_system_rows_inserted; /*!< srv_n_system_rows_inserted */ ulint innodb_system_rows_updated; /*!< srv_n_system_rows_updated */ ulint innodb_system_rows_deleted; /*!< srv_n_system_rows_deleted*/ - ulint innodb_num_open_files; /*!< fil_n_file_opened */ + ulint innodb_num_open_files; /*!< fil_system_t::n_open */ ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */ ulint innodb_available_undo_logs; /*!< srv_available_undo_logs */ diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index f6c388f2dcf..de1c0d27efe 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -1960,7 +1960,7 @@ srv_mon_process_existing_counter( break; case MONITOR_OVLD_N_FILE_OPENED: - value = fil_n_file_opened; + value = fil_system->n_open; break; case MONITOR_OVLD_IBUF_MERGE_INSERT: diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 08d201511da..5572521662b 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1626,7 +1626,7 @@ srv_export_innodb_status(void) export_vars.innodb_system_rows_deleted = srv_stats.n_system_rows_deleted; - export_vars.innodb_num_open_files = fil_n_file_opened; + export_vars.innodb_num_open_files = fil_system->n_open; export_vars.innodb_truncated_status_writes = srv_truncated_status_writes; -- cgit v1.2.1 From e82e216e374739d7cab022a86b48498aa9c33ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 27 Nov 2018 14:49:20 +0200 Subject: MDEV-17849 Undo tablespace truncation recovery fails to shrink file fil_space_t::add(): Replaces fil_node_create(), fil_node_create_low(). Let the caller pass fil_node_t::handle, to avoid having to close and re-open files. fil_node_t::read_page0(): Refactored from fil_node_open_file(). Read the first page of a data file. fil_node_open_file(): Open the file only once. srv_undo_tablespace_open(): Set the file handle for the opened undo tablespace. This should ensure that ut_ad(file->is_open()) no longer fails in recv_add_trim(). xtrabackup_backup_func(): Remove some dead code. xb_fil_cur_open(): Open files only if needed. Undo tablespaces should already have been opened. --- extra/mariabackup/fil_cur.cc | 7 +- extra/mariabackup/xtrabackup.cc | 64 +----- storage/innobase/fil/fil0fil.cc | 372 +++++++++++++++-------------------- storage/innobase/fsp/fsp0space.cc | 13 +- storage/innobase/fsp/fsp0sysspace.cc | 14 +- storage/innobase/include/fil0fil.h | 40 ++-- storage/innobase/srv/srv0start.cc | 132 +++++-------- 7 files changed, 254 insertions(+), 388 deletions(-) diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index 7b7cfb3c948..219ec8845d4 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -159,8 +159,11 @@ xb_fil_cur_open( /* In the backup mode we should already have a tablespace handle created by fil_ibd_load() unless it is a system tablespace. Otherwise we open the file here. */ - if (cursor->is_system() || srv_operation == SRV_OPERATION_RESTORE_DELTA - || xb_close_files) { + if (!node->is_open()) { + ut_ad(cursor->is_system() + || srv_operation == SRV_OPERATION_RESTORE_DELTA + || xb_close_files); + node->handle = os_file_create_simple_no_error_handling( 0, node->name, OS_FILE_OPEN, diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index e627826b8c4..0f29da9e78e 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -3101,11 +3101,8 @@ xb_load_single_table_tablespace( ut_a(space != NULL); - if (!fil_node_create(file->filepath(), ulint(n_pages), space, - false, false)) { - ut_error; - } - + space->add(file->filepath(), OS_FILE_CLOSED, ulint(n_pages), + false, false); /* by opening the tablespace we forcing node and space objects in the cache to be populated with fields from space header */ fil_space_open(space->name); @@ -3781,22 +3778,17 @@ xb_filters_free() } /*********************************************************************//** -Creates or opens the log files and closes them. -@return DB_SUCCESS or error code */ +Create log file metadata. */ static -ulint +void open_or_create_log_file( /*====================*/ fil_space_t* space, - ibool* log_file_created, /*!< out: TRUE if new log file - created */ ulint i) /*!< in: log file number in group */ { char name[10000]; ulint dirnamelen; - *log_file_created = FALSE; - os_normalize_path(srv_log_group_home_dir); dirnamelen = strlen(srv_log_group_home_dir); @@ -3808,14 +3800,13 @@ open_or_create_log_file( name[dirnamelen++] = OS_PATH_SEPARATOR; } - sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i); + sprintf(name + dirnamelen, "%s%zu", "ib_logfile", i); ut_a(fil_validate()); - ut_a(fil_node_create(name, ulint(srv_log_file_size >> srv_page_size_shift), - space, false, false)); - - return(DB_SUCCESS); + space->add(name, OS_FILE_CLOSED, + ulint(srv_log_file_size >> srv_page_size_shift), + false, false); } /*********************************************************************//** @@ -4124,13 +4115,6 @@ fail: xb_filters_init(); - { - ibool log_file_created; - ibool log_created = FALSE; - ibool log_opened = FALSE; - ulint err; - ulint i; - xb_fil_io_init(); srv_n_file_io_threads = srv_n_read_io_threads; @@ -4145,36 +4129,8 @@ fail: lock_sys_create(srv_lock_table_size); - for (i = 0; i < srv_n_log_files; i++) { - err = open_or_create_log_file(space, &log_file_created, i); - if (err != DB_SUCCESS) { - goto fail; - } - - if (log_file_created) { - log_created = TRUE; - } else { - log_opened = TRUE; - } - if ((log_opened && log_created)) { - msg( - "mariabackup: Error: all log files must be created at the same time.\n" - "mariabackup: All log files must be created also in database creation.\n" - "mariabackup: If you want bigger or smaller log files, shut down the\n" - "mariabackup: database and make sure there were no errors in shutdown.\n" - "mariabackup: Then delete the existing log files. Edit the .cnf file\n" - "mariabackup: and start the database again.\n"); - - goto fail; - } - } - - /* log_file_created must not be TRUE, if online */ - if (log_file_created) { - msg("mariabackup: Something wrong with source files...\n"); - goto fail; - } - + for (ulint i = 0; i < srv_n_log_files; i++) { + open_or_create_log_file(space, i); } /* create extra LSN dir if it does not exist. */ diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 6368d4b4751..7744c9079f2 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -465,36 +465,25 @@ fil_space_is_flushed( /** Append a file to the chain of files of a space. @param[in] name file name of a file that is not open -@param[in] size file size in entire database blocks -@param[in,out] space tablespace from fil_space_create() -@param[in] is_raw whether this is a raw device or partition -@param[in] atomic_write true if the file could use atomic write +@param[in] handle file handle, or OS_FILE_CLOSED +@param[in] size file size in entire database pages +@param[in] is_raw whether this is a raw device +@param[in] atomic_write true if atomic write could be enabled @param[in] max_pages maximum number of pages in file, -ULINT_MAX means the file size is unlimited. -@return pointer to the file name -@retval NULL if error */ -static -fil_node_t* -fil_node_create_low( - const char* name, - ulint size, - fil_space_t* space, - bool is_raw, - bool atomic_write, - ulint max_pages = ULINT_MAX) +or ULINT_MAX for unlimited +@return file object */ +fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle, + ulint size, bool is_raw, bool atomic_write, + ulint max_pages) { fil_node_t* node; ut_ad(name != NULL); ut_ad(fil_system != NULL); - if (space == NULL) { - return(NULL); - } - node = reinterpret_cast(ut_zalloc_nokey(sizeof(*node))); - node->handle = OS_FILE_CLOSED; + node->handle = handle; node->name = mem_strdup(name); @@ -511,56 +500,116 @@ fil_node_create_low( node->init_size = size; node->max_size = max_pages; - mutex_enter(&fil_system->mutex); - - space->size += size; - - node->space = space; + node->space = this; node->atomic_write = atomic_write; - UT_LIST_ADD_LAST(space->chain, node); + mutex_enter(&fil_system->mutex); + this->size += size; + UT_LIST_ADD_LAST(chain, node); + if (node->is_open()) { + fil_system->n_open++; + } mutex_exit(&fil_system->mutex); - return(node); + return node; } -/** Appends a new file to the chain of files of a space. File must be closed. -@param[in] name file name (file must be closed) -@param[in] size file size in database blocks, rounded downwards to - an integer -@param[in,out] space space where to append -@param[in] is_raw true if a raw device or a raw disk partition -@param[in] atomic_write true if the file could use atomic write -@param[in] max_pages maximum number of pages in file, -ULINT_MAX means the file size is unlimited. -@return pointer to the file name -@retval NULL if error */ -char* -fil_node_create( - const char* name, - ulint size, - fil_space_t* space, - bool is_raw, - bool atomic_write, - ulint max_pages) +/** Read the first page of a data file. +@param[in] first whether this is the very first read +@return whether the page was found valid */ +bool fil_node_t::read_page0(bool first) { - fil_node_t* node; + ut_ad(mutex_own(&fil_system->mutex)); + ut_a(space->purpose != FIL_TYPE_LOG); + const page_size_t page_size(space->flags); + const ulint psize = page_size.physical(); + + os_offset_t size_bytes = os_file_get_size(handle); + ut_a(size_bytes != (os_offset_t) -1); + const ulint min_size = FIL_IBD_FILE_INITIAL_SIZE * psize; + + if (size_bytes < min_size) { + ib::error() << "The size of the file " << name + << " is only " << size_bytes + << " bytes, should be at least " << min_size; + return false; + } - node = fil_node_create_low( - name, size, space, is_raw, atomic_write, max_pages); + byte* buf2 = static_cast(ut_malloc_nokey(2 * psize)); - return(node == NULL ? NULL : node->name); + /* Align the memory for file i/o if we might have O_DIRECT set */ + byte* page = static_cast(ut_align(buf2, psize)); + IORequest request(IORequest::READ); + if (!os_file_read(request, handle, page, 0, psize)) { + ib::error() << "Unable to read first page of file " << name; + ut_free(buf2); + return false; + } + srv_stats.page0_read.add(1); + const ulint space_id = fsp_header_get_space_id(page); + ulint flags = fsp_header_get_flags(page); + const ulint size = fsp_header_get_field(page, FSP_SIZE); + const ulint free_limit = fsp_header_get_field(page, FSP_FREE_LIMIT); + const ulint free_len = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE + + page); + /* Try to read crypt_data from page 0 if it is not yet read. */ + if (!space->crypt_data) { + space->crypt_data = fil_space_read_crypt_data(page_size, page); + } + ut_free(buf2); + + if (!fsp_flags_is_valid(flags, space->id)) { + ulint cflags = fsp_flags_convert_from_101(flags); + if (cflags == ULINT_UNDEFINED + || (cflags ^ space->flags) & ~FSP_FLAGS_MEM_MASK) { + ib::error() + << "Expected tablespace flags " + << ib::hex(space->flags) + << " but found " << ib::hex(flags) + << " in the file " << name; + return false; + } + + flags = cflags; + } + + if (UNIV_UNLIKELY(space_id != space->id)) { + ib::error() << "Expected tablespace id " << space->id + << " but found " << space_id + << " in the file " << name; + return false; + } + + ut_ad(space->free_limit == 0 || space->free_limit == free_limit); + ut_ad(space->free_len == 0 || space->free_len == free_len); + space->size_in_header = size; + space->free_limit = free_limit; + space->free_len = free_len; + + if (first) { + /* Truncate the size to a multiple of extent size. */ + ulint mask = psize * FSP_EXTENT_SIZE - 1; + + if (size_bytes <= mask) { + /* .ibd files start smaller than an + extent size. Do not truncate valid data. */ + } else { + size_bytes &= ~os_offset_t(mask); + } + + this->size = ulint(size_bytes / psize); + space->size += this->size; + } + + return true; } /** Open a file node of a tablespace. The caller must own the fil_system mutex. @param[in,out] node File node @return false if the file can't be opened, otherwise true */ -static -bool -fil_node_open_file( - fil_node_t* node) +static bool fil_node_open_file(fil_node_t* node) { bool success; bool read_only_mode; @@ -588,9 +637,12 @@ fil_node_open_file( from a file opened for async I/O! */ retry: - node->handle = os_file_create_simple_no_error_handling( - innodb_data_file_key, node->name, OS_FILE_OPEN, - OS_FILE_READ_ONLY, read_only_mode, &success); + node->handle = os_file_create( + innodb_data_file_key, node->name, + node->is_raw_disk + ? OS_FILE_OPEN_RAW | OS_FILE_ON_ERROR_NO_EXIT + : OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT, + OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); if (!success) { /* The following call prints an error message */ @@ -606,150 +658,47 @@ retry: return(false); } - os_offset_t size_bytes = os_file_get_size(node->handle); - ut_a(size_bytes != (os_offset_t) -1); - - ut_a(space->purpose != FIL_TYPE_LOG); - const page_size_t page_size(space->flags); - const ulint psize = page_size.physical(); - const ulint min_size = FIL_IBD_FILE_INITIAL_SIZE - * psize; - - if (size_bytes < min_size) { - ib::error() << "The size of the file " << node->name - << " is only " << size_bytes - << " bytes, should be at least " << min_size; + if (!node->read_page0(first_time_open)) { os_file_close(node->handle); node->handle = OS_FILE_CLOSED; - return(false); - } - - /* Read the first page of the tablespace */ - - byte* buf2 = static_cast(ut_malloc_nokey(2 * psize)); - - /* Align the memory for file i/o if we might have O_DIRECT - set */ - byte* page = static_cast(ut_align(buf2, psize)); - - IORequest request(IORequest::READ); - - success = os_file_read( - request, - node->handle, page, 0, psize); - srv_stats.page0_read.add(1); - - const ulint space_id - = fsp_header_get_space_id(page); - ulint flags = fsp_header_get_flags(page); - const ulint size = fsp_header_get_field( - page, FSP_SIZE); - const ulint free_limit = fsp_header_get_field( - page, FSP_FREE_LIMIT); - const ulint free_len = flst_get_len( - FSP_HEADER_OFFSET + FSP_FREE + page); - - /* Try to read crypt_data from page 0 if it is not yet - read. */ - if (!space->crypt_data) { - space->crypt_data = fil_space_read_crypt_data( - page_size_t(space->flags), page); - } - - ut_free(buf2); - os_file_close(node->handle); - node->handle = OS_FILE_CLOSED; - - if (!fsp_flags_is_valid(flags, space->id)) { - ulint cflags = fsp_flags_convert_from_101(flags); - if (cflags == ULINT_UNDEFINED - || (cflags ^ space->flags) & ~FSP_FLAGS_MEM_MASK) { - ib::error() - << "Expected tablespace flags " - << ib::hex(space->flags) - << " but found " << ib::hex(flags) - << " in the file " << node->name; - return(false); - } - - flags = cflags; - } - - if (UNIV_UNLIKELY(space_id != space->id)) { - ib::error() - << "Expected tablespace id " << space->id - << " but found " << space_id - << " in the file" << node->name; - return(false); + return false; } - - ut_ad(space->free_limit == 0 - || space->free_limit == free_limit); - ut_ad(space->free_len == 0 - || space->free_len == free_len); - space->size_in_header = size; - space->free_limit = free_limit; - space->free_len = free_len; - - if (first_time_open) { - /* Truncate the size to a multiple of extent size. */ - ulint mask = psize * FSP_EXTENT_SIZE - 1; - - if (size_bytes <= mask) { - /* .ibd files start smaller than an - extent size. Do not truncate valid data. */ - } else { - size_bytes &= ~os_offset_t(mask); - } - - node->size = ulint(size_bytes / psize); - space->size += node->size; - } - } - - /* printf("Opening file %s\n", node->name); */ - - /* Open the file for reading and writing, in Windows normally in the - unbuffered async I/O mode, though global variables may make - os_file_create() to fall back to the normal file I/O mode. */ - - if (space->purpose == FIL_TYPE_LOG) { + } else if (space->purpose == FIL_TYPE_LOG) { node->handle = os_file_create( innodb_log_file_key, node->name, OS_FILE_OPEN, OS_FILE_AIO, OS_LOG_FILE, read_only_mode, &success); - } else if (node->is_raw_disk) { - node->handle = os_file_create( - innodb_data_file_key, node->name, OS_FILE_OPEN_RAW, - OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); } else { node->handle = os_file_create( - innodb_data_file_key, node->name, OS_FILE_OPEN, + innodb_data_file_key, node->name, + node->is_raw_disk + ? OS_FILE_OPEN_RAW | OS_FILE_ON_ERROR_NO_EXIT + : OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT, OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); + } - if (first_time_open) { - /* - For the temporary tablespace and during the - non-redo-logged adjustments in - IMPORT TABLESPACE, we do not care about - the atomicity of writes. - - Atomic writes is supported if the file can be used - with atomic_writes (not log file), O_DIRECT is - used (tested in ha_innodb.cc) and the file is - device and file system that supports atomic writes - for the given block size - */ - space->atomic_write_supported - = space->purpose == FIL_TYPE_TEMPORARY - || space->purpose == FIL_TYPE_IMPORT - || (node->atomic_write - && srv_use_atomic_writes - && my_test_if_atomic_write( - node->handle, - int(page_size_t(space->flags) - .physical()))); - } - } + if (space->purpose != FIL_TYPE_LOG) { + /* + For the temporary tablespace and during the + non-redo-logged adjustments in + IMPORT TABLESPACE, we do not care about + the atomicity of writes. + + Atomic writes is supported if the file can be used + with atomic_writes (not log file), O_DIRECT is + used (tested in ha_innodb.cc) and the file is + device and file system that supports atomic writes + for the given block size + */ + space->atomic_write_supported + = space->purpose == FIL_TYPE_TEMPORARY + || space->purpose == FIL_TYPE_IMPORT + || (node->atomic_write + && srv_use_atomic_writes + && my_test_if_atomic_write( + node->handle, + int(page_size_t(space->flags) + .physical()))); + } ut_a(success); ut_a(node->is_open()); @@ -1430,7 +1379,7 @@ Error messages are issued to the server log. @param[in] purpose tablespace purpose @param[in,out] crypt_data encryption information @param[in] mode encryption mode -@return pointer to created tablespace, to be filled in with fil_node_create() +@return pointer to created tablespace, to be filled in with fil_space_t::add() @retval NULL on failure (such as when the same tablespace exists) */ fil_space_t* fil_space_create( @@ -1519,7 +1468,7 @@ fil_space_create( if (space->purpose == FIL_TYPE_TEMPORARY) { ut_d(space->latch.set_temp_fsp()); /* SysTablespace::open_or_create() would pass - size!=0 to fil_node_create(), so first_time_open + size!=0 to fil_space_t::add(), so first_time_open would not hold in fil_node_open_file(), and we must assign this manually. We do not care about the durability or atomicity of writes to the @@ -3819,22 +3768,16 @@ fil_ibd_create( space = fil_space_create(name, space_id, flags, FIL_TYPE_TABLESPACE, crypt_data, mode); - - fil_node_t* node = NULL; - - if (space) { - node = fil_node_create_low(path, size, space, false, true); - } - - if (!space || !node) { + if (!space) { if (crypt_data) { free(crypt_data); } err = DB_ERROR; } else { - mtr_t mtr; - const fil_node_t* file = UT_LIST_GET_FIRST(space->chain); + mtr_t mtr; + fil_node_t* file = space->add(path, OS_FILE_CLOSED, size, + false, true); mtr.start(); fil_op_write_log( @@ -3843,7 +3786,7 @@ fil_ibd_create( fil_name_write(space, 0, file, &mtr); mtr.commit(); - node->block_size = block_size; + file->block_size = block_size; space->punch_hole = punch_hole; err = DB_SUCCESS; @@ -4072,6 +4015,7 @@ fil_ibd_open( || df_remote.is_open() != df_remote.is_valid()) { return(DB_CORRUPTION); } +error: return(DB_ERROR); } @@ -4180,17 +4124,17 @@ skip_validate: fil_space_t* space = fil_space_create( space_name, id, flags, purpose, crypt_data); + if (!space) { + goto error; + } /* We do not measure the size of the file, that is why we pass the 0 below */ - if (fil_node_create_low( - df_remote.is_open() ? df_remote.filepath() : - df_dict.is_open() ? df_dict.filepath() : - df_default.filepath(), 0, space, false, - true) == NULL) { - err = DB_ERROR; - } + space->add( + df_remote.is_open() ? df_remote.filepath() : + df_dict.is_open() ? df_dict.filepath() : + df_default.filepath(), OS_FILE_CLOSED, 0, false, true); if (err == DB_SUCCESS && validate && purpose != FIL_TYPE_IMPORT && !srv_read_only_mode) { @@ -4539,9 +4483,7 @@ fil_ibd_load( the rounding formula for extents and pages is somewhat complex; we let fil_node_open() do that task. */ - if (!fil_node_create_low(file.filepath(), 0, space, false, false)) { - ut_error; - } + space->add(file.filepath(), OS_FILE_CLOSED, 0, false, false); return(FIL_LOAD_OK); } diff --git a/storage/innobase/fsp/fsp0space.cc b/storage/innobase/fsp/fsp0space.cc index df234f7274e..88b34be4952 100644 --- a/storage/innobase/fsp/fsp0space.cc +++ b/storage/innobase/fsp/fsp0space.cc @@ -123,18 +123,15 @@ Tablespace::open_or_create(bool is_temp) is_temp ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE, NULL); + if (!space) { + return DB_ERROR; + } } ut_a(fil_validate()); - /* Create the tablespace node entry for this data file. */ - if (!fil_node_create( - it->m_filepath, it->m_size, space, false, - TRUE)) { - - err = DB_ERROR; - break; - } + space->add(it->m_filepath, OS_FILE_CLOSED, it->m_size, + false, true); } return(err); diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index baf864bc1c3..b856bf3da74 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -918,6 +918,9 @@ SysTablespace::open_or_create( name(), space_id(), flags(), is_temp ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE, NULL); + if (!space) { + return DB_ERROR; + } } ut_a(fil_validate()); @@ -928,15 +931,8 @@ SysTablespace::open_or_create( : m_last_file_size_max) : it->m_size); - /* Add the datafile to the fil_system cache. */ - if (!fil_node_create( - it->m_filepath, it->m_size, - space, it->m_type != SRV_NOT_RAW, - TRUE, max_size)) { - - err = DB_ERROR; - break; - } + space->add(it->m_filepath, OS_FILE_CLOSED, it->m_size, + it->m_type != SRV_NOT_RAW, true, max_size); } return(err); diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index d1bd2dc14d4..6406ff8448c 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -195,6 +195,19 @@ struct fil_space_t { return !atomic_write_supported && srv_use_doublewrite_buf && buf_dblwr; } + + /** Append a file to the chain of files of a space. + @param[in] name file name of a file that is not open + @param[in] handle file handle, or OS_FILE_CLOSED + @param[in] size file size in entire database pages + @param[in] is_raw whether this is a raw device + @param[in] atomic_write true if atomic write could be enabled + @param[in] max_pages maximum number of pages in file, + or ULINT_MAX for unlimited + @return file object */ + fil_node_t* add(const char* name, pfs_os_file_t handle, + ulint size, bool is_raw, bool atomic_write, + ulint max_pages = ULINT_MAX); }; /** Value of fil_space_t::magic_n */ @@ -252,6 +265,11 @@ struct fil_node_t { { return(handle != OS_FILE_CLOSED); } + + /** Read the first page of a data file. + @param[in] first whether this is the very first read + @return whether the page was found valid */ + bool read_page0(bool first); }; /** Value of fil_node_t::magic_n */ @@ -547,26 +565,6 @@ void fil_space_set_imported( ulint id); -/** Append a file to the chain of files of a space. -@param[in] name file name of a file that is not open -@param[in] size file size in entire database blocks -@param[in,out] space tablespace from fil_space_create() -@param[in] is_raw whether this is a raw device or partition -@param[in] atomic_write true if atomic write could be enabled -@param[in] max_pages maximum number of pages in file, -ULINT_MAX means the file size is unlimited. -@return pointer to the file name -@retval NULL if error */ -char* -fil_node_create( - const char* name, - ulint size, - fil_space_t* space, - bool is_raw, - bool atomic_write, - ulint max_pages = ULINT_MAX) - MY_ATTRIBUTE((warn_unused_result)); - /** Create a space memory object and put it to the fil_system hash table. Error messages are issued to the server log. @param[in] name tablespace name @@ -575,7 +573,7 @@ Error messages are issued to the server log. @param[in] purpose tablespace purpose @param[in,out] crypt_data encryption information @param[in] mode encryption mode -@return pointer to created tablespace, to be filled in with fil_node_create() +@return pointer to created tablespace, to be filled in with fil_space_t::add() @retval NULL on failure (such as when the same tablespace exists) */ fil_space_t* fil_space_create( diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 8719d26d5f3..ae890750841 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -470,23 +470,16 @@ create_log_files( const ulint size = ulint(srv_log_file_size >> srv_page_size_shift); - logfile0 = fil_node_create( - logfilename, size, log_space, false, false); + logfile0 = log_space->add(logfilename, OS_FILE_CLOSED, size, + false, false)->name; ut_a(logfile0); for (unsigned i = 1; i < srv_n_log_files; i++) { sprintf(logfilename + dirnamelen, "ib_logfile%u", i); - if (!fil_node_create(logfilename, size, - log_space, false, false)) { - - ib::error() - << "Cannot create file node for log file " - << logfilename; - - return(DB_ERROR); - } + log_space->add(logfilename, OS_FILE_CLOSED, size, + false, false); } log_init(srv_n_log_files); @@ -634,83 +627,68 @@ srv_undo_tablespace_create( return(err); } -/*********************************************************************//** -Open an undo tablespace. -@return DB_SUCCESS or error code */ -static -dberr_t -srv_undo_tablespace_open( -/*=====================*/ - const char* name, /*!< in: tablespace file name */ - ulint space_id) /*!< in: tablespace id */ + +/** Open an undo tablespace. +@param[in] name tablespace file name +@param[in] space_id tablespace ID +@param[in] create_new_db whether undo tablespaces are being created +@return whether the tablespace was opened */ +static bool srv_undo_tablespace_open(const char* name, ulint space_id, + bool create_new_db) { pfs_os_file_t fh; - bool ret; - dberr_t err = DB_ERROR; + bool success; char undo_name[sizeof "innodb_undo000"]; snprintf(undo_name, sizeof(undo_name), "innodb_undo%03u", static_cast(space_id)); - if (!srv_file_check_mode(name)) { - ib::error() << "UNDO tablespaces must be " << - (srv_read_only_mode ? "writable" : "readable") << "!"; - - return(DB_ERROR); - } - fh = os_file_create( - innodb_data_file_key, name, - OS_FILE_OPEN_RETRY - | OS_FILE_ON_ERROR_NO_EXIT - | OS_FILE_ON_ERROR_SILENT, - OS_FILE_NORMAL, - OS_DATA_FILE, - srv_read_only_mode, - &ret); - - /* If the file open was successful then load the tablespace. */ - - if (ret) { - os_offset_t size; - fil_space_t* space; - - size = os_file_get_size(fh); - ut_a(size != (os_offset_t) -1); + innodb_data_file_key, name, OS_FILE_OPEN + | OS_FILE_ON_ERROR_NO_EXIT | OS_FILE_ON_ERROR_SILENT, + OS_FILE_AIO, OS_DATA_FILE, srv_read_only_mode, &success); + if (!success) { + return false; + } - ret = os_file_close(fh); - ut_a(ret); + os_offset_t size = os_file_get_size(fh); + ut_a(size != os_offset_t(-1)); - /* Load the tablespace into InnoDB's internal - data structures. */ + /* Load the tablespace into InnoDB's internal data structures. */ - /* We set the biggest space id to the undo tablespace - because InnoDB hasn't opened any other tablespace apart - from the system tablespace. */ + /* We set the biggest space id to the undo tablespace + because InnoDB hasn't opened any other tablespace apart + from the system tablespace. */ - fil_set_max_space_id_if_bigger(space_id); + fil_set_max_space_id_if_bigger(space_id); - space = fil_space_create( - undo_name, space_id, FSP_FLAGS_PAGE_SSIZE(), - FIL_TYPE_TABLESPACE, NULL); + fil_space_t* space = fil_space_create( + undo_name, space_id, FSP_FLAGS_PAGE_SSIZE(), + FIL_TYPE_TABLESPACE, NULL); - ut_a(fil_validate()); - ut_a(space); + ut_a(fil_validate()); + ut_a(space); - os_offset_t n_pages = size / UNIV_PAGE_SIZE; + fil_node_t* file = space->add(name, fh, 0, false, true); - /* On 32-bit platforms, ulint is 32 bits and os_offset_t - is 64 bits. It is OK to cast the n_pages to ulint because - the unit has been scaled to pages and page number is always - 32 bits. */ - if (fil_node_create( - name, (ulint) n_pages, space, false, TRUE)) { + mutex_enter(&fil_system->mutex); - err = DB_SUCCESS; + if (create_new_db) { + space->size = file->size = ulint(size >> srv_page_size_shift); + space->size_in_header = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES; + } else { + success = file->read_page0(true); + if (!success) { + os_file_close(file->handle); + file->handle = OS_FILE_CLOSED; + ut_a(fil_system->n_open > 0); + fil_system->n_open--; } } - return(err); + mutex_exit(&fil_system->mutex); + + return success; } /** Check if undo tablespaces and redo log files exist before creating a @@ -936,12 +914,11 @@ srv_undo_tablespaces_init(bool create_new_db) ut_a(undo_tablespace_ids[i] != 0); ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED); - err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]); - - if (err != DB_SUCCESS) { + if (!srv_undo_tablespace_open(name, undo_tablespace_ids[i], + create_new_db)) { ib::error() << "Unable to open undo tablespace '" << name << "'."; - return(err); + return DB_ERROR; } prev_space_id = undo_tablespace_ids[i]; @@ -966,9 +943,8 @@ srv_undo_tablespaces_init(bool create_new_db) name, sizeof(name), "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i); - err = srv_undo_tablespace_open(name, i); - - if (err != DB_SUCCESS) { + if (!srv_undo_tablespace_open(name, i, create_new_db)) { + err = DB_ERROR; break; } @@ -2078,10 +2054,8 @@ innobase_start_or_create_for_mysql() for (unsigned j = 0; j < srv_n_log_files_found; j++) { sprintf(logfilename + dirnamelen, "ib_logfile%u", j); - if (!fil_node_create(logfilename, size, - log_space, false, false)) { - return(srv_init_abort(DB_ERROR)); - } + log_space->add(logfilename, OS_FILE_CLOSED, size, + false, false); } log_init(srv_n_log_files_found); -- cgit v1.2.1 From 4a92165ff04d6c0557eb99cc21ff88998337e376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 28 Nov 2018 00:52:30 +0200 Subject: Remove unused mem_heap_allocator The code became unused in commit 10590dd39cc1e742bbf395c3285201a6a31c5284. --- storage/innobase/include/mem0mem.h | 99 -------------------------------------- 1 file changed, 99 deletions(-) diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index e44f3f730af..e1cd24a26c6 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -412,103 +412,4 @@ struct mem_block_info_t { UNIV_MEM_ALIGNMENT) #include "mem0mem.ic" - -/** A C++ wrapper class to the mem_heap_t routines, so that it can be used -as an STL allocator */ -template -class mem_heap_allocator -{ -public: - typedef T value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - - mem_heap_allocator(mem_heap_t* heap) : m_heap(heap) { } - - mem_heap_allocator(const mem_heap_allocator& other) - : - m_heap(other.m_heap) - { - // Do nothing - } - - template - mem_heap_allocator (const mem_heap_allocator& other) - : - m_heap(other.m_heap) - { - // Do nothing - } - - ~mem_heap_allocator() { m_heap = 0; } - - size_type max_size() const - { - return(ULONG_MAX / sizeof(T)); - } - - /** This function returns a pointer to the first element of a newly - allocated array large enough to contain n objects of type T; only the - memory is allocated, and the objects are not constructed. Moreover, - an optional pointer argument (that points to an object already - allocated by mem_heap_allocator) can be used as a hint to the - implementation about where the new memory should be allocated in - order to improve locality. */ - pointer allocate(size_type n, const_pointer hint = 0) - { - return(reinterpret_cast( - mem_heap_alloc(m_heap, n * sizeof(T)))); - } - - void deallocate(pointer p, size_type n) { } - - pointer address (reference r) const { return(&r); } - - const_pointer address (const_reference r) const { return(&r); } - - void construct(pointer p, const_reference t) - { - new (reinterpret_cast(p)) T(t); - } - - void destroy(pointer p) - { - (reinterpret_cast(p))->~T(); - } - - /** Allocators are required to supply the below template class member - which enables the possibility of obtaining a related allocator, - parametrized in terms of a different type. For example, given an - allocator type IntAllocator for objects of type int, a related - allocator type for objects of type long could be obtained using - IntAllocator::rebind::other */ - template - struct rebind - { - typedef mem_heap_allocator other; - }; - -private: - mem_heap_t* m_heap; - template friend class mem_heap_allocator; -}; - -template -bool operator== (const mem_heap_allocator& left, - const mem_heap_allocator& right) -{ - return(left.heap == right.heap); -} - -template -bool operator!= (const mem_heap_allocator& left, - const mem_heap_allocator& right) -{ - return(left.heap != right.heap); -} - #endif -- cgit v1.2.1