diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-11-28 01:02:46 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-11-28 01:02:46 +0200 |
commit | babb000a36f7a003cc0338cc7f8f01d0beaa5032 (patch) | |
tree | 1064292241b0af40ec8fd56000191df7ffcd5da1 | |
parent | 4b88d5ee516fc7d2e51f55409623c63a1bde25f3 (diff) | |
parent | 4a92165ff04d6c0557eb99cc21ff88998337e376 (diff) | |
download | mariadb-git-babb000a36f7a003cc0338cc7f8f01d0beaa5032.tar.gz |
Merge 10.2 into 10.3
-rw-r--r-- | extra/mariabackup/fil_cur.cc | 9 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 64 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 370 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0space.cc | 13 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0sysspace.cc | 17 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 4 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 43 | ||||
-rw-r--r-- | storage/innobase/include/mem0mem.h | 100 | ||||
-rw-r--r-- | storage/innobase/include/srv0srv.h | 2 | ||||
-rw-r--r-- | storage/innobase/srv/srv0mon.cc | 2 | ||||
-rw-r--r-- | storage/innobase/srv/srv0srv.cc | 2 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 132 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.cc | 8 |
13 files changed, 264 insertions, 502 deletions
diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index ea4cce92dda..d37c8e2f752 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -109,7 +109,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)) { @@ -159,8 +158,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, @@ -178,7 +180,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/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 9ceb2800e73..59426b51127 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -3094,11 +3094,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 */ space->open(); @@ -3775,22 +3772,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); @@ -3802,14 +3794,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); } /*********************************************************************** @@ -4069,13 +4060,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; @@ -4088,36 +4072,8 @@ fail: "innodb_redo_log", SRV_LOG_SPACE_FIRST_ID, 0, FIL_TYPE_LOG, NULL); - 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 3b9e69e8a4b..9247313b392 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -166,9 +166,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 */ const fil_addr_t fil_addr_null = {FIL_NULL, 0}; @@ -437,36 +434,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.is_initialised()); - if (space == NULL) { - return(NULL); - } - node = reinterpret_cast<fil_node_t*>(ut_zalloc_nokey(sizeof(*node))); - node->handle = OS_FILE_CLOSED; + node->handle = handle; node->name = mem_strdup(name); @@ -483,55 +469,115 @@ 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; - node = fil_node_create_low( - name, size, space, is_raw, atomic_write, max_pages); + 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; + } - return(node == NULL ? NULL : node->name); + byte* buf2 = static_cast<byte*>(ut_malloc_nokey(2 * psize)); + + /* Align the memory for file i/o if we might have O_DIRECT set */ + byte* page = static_cast<byte*>(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. @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; @@ -559,9 +605,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 */ @@ -577,156 +626,52 @@ 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<byte*>(ut_malloc_nokey(2 * psize)); - - /* Align the memory for file i/o if we might have O_DIRECT - set */ - byte* page = static_cast<byte*>(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); - } - - 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; + return false; } - } - - /* 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()); fil_system.n_open++; - fil_n_file_opened++; if (fil_space_belongs_in_lru(space)) { @@ -761,7 +706,6 @@ void fil_node_t::close() ut_ad(!is_open()); ut_a(fil_system.n_open > 0); fil_system.n_open--; - fil_n_file_opened--; if (fil_space_belongs_in_lru(space)) { ut_a(UT_LIST_GET_LEN(fil_system.LRU) > 0); @@ -1396,7 +1340,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( @@ -1472,7 +1416,7 @@ fil_space_create( if (space->purpose == FIL_TYPE_TEMPORARY) { /* 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 @@ -3225,17 +3169,17 @@ err_exit: free(crypt_data); *err = DB_ERROR; } else { - fil_node_t* node = fil_node_create_low(path, size, space, - false, true); + fil_node_t* file = space->add(path, OS_FILE_CLOSED, size, + false, true); mtr_t mtr; mtr.start(); fil_op_write_log( - MLOG_FILE_CREATE2, space_id, 0, node->name, + MLOG_FILE_CREATE2, space_id, 0, file->name, NULL, space->flags & ~FSP_FLAGS_MEM_MASK, &mtr); - fil_name_write(space, 0, node, &mtr); + 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; @@ -3603,17 +3547,17 @@ skip_validate: fil_space_t* space = fil_space_create( tablename.m_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) { - goto 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 (validate && purpose != FIL_TYPE_IMPORT && !srv_read_only_mode) { df_remote.close(); @@ -3962,9 +3906,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 b411d315927..aec2a3914b8 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -907,12 +907,18 @@ SysTablespace::open_or_create( space = fil_system.temp_space = fil_space_create( name(), SRV_TMP_SPACE_ID, flags(), FIL_TYPE_TEMPORARY, NULL); + if (!space) { + return DB_ERROR; + } } else { ut_ad(!fil_system.sys_space); ut_ad(space_id() == TRX_SYS_SPACE); space = fil_system.sys_space = fil_space_create( name(), TRX_SYS_SPACE, flags(), FIL_TYPE_TABLESPACE, NULL); + if (!space) { + return DB_ERROR; + } } ut_a(fil_validate()); @@ -923,15 +929,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/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 1e9084905dc..9725375ebbb 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12360,7 +12360,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; @@ -12592,7 +12592,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) { diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 4d5952a8123..3cae36d3eeb 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -189,6 +189,19 @@ struct fil_space_t { && 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); + /** Try to reserve free extents. @param[in] n_free_now current number of free extents @param[in] n_to_reserve number of extents to reserve @@ -324,6 +337,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); + /** Close the file handle. */ void close(); }; @@ -528,9 +546,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. @@ -645,26 +660,6 @@ fil_space_get_latch( ulint id, ulint* flags); -/** 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 @@ -673,7 +668,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/include/mem0mem.h b/storage/innobase/include/mem0mem.h index 2cdb307ea96..f299fc84b5e 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -418,104 +418,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<typename T> -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 <typename U> - mem_heap_allocator (const mem_heap_allocator<U>& 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) - { - return(reinterpret_cast<pointer>( - mem_heap_alloc(m_heap, n * sizeof(T)))); - } - pointer allocate(size_type n, const_pointer) { return allocate(n); } - - void deallocate(pointer, size_type) {} - - 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<void*>(p)) T(t); - } - - void destroy(pointer p) - { - (reinterpret_cast<T*>(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<long>::other */ - template <typename U> - struct rebind - { - typedef mem_heap_allocator<U> other; - }; - -private: - mem_heap_t* m_heap; - template <typename U> friend class mem_heap_allocator; -}; - -template <class T> -bool operator== (const mem_heap_allocator<T>& left, - const mem_heap_allocator<T>& right) -{ - return(left.heap == right.heap); -} - -template <class T> -bool operator!= (const mem_heap_allocator<T>& left, - const mem_heap_allocator<T>& right) -{ - return(left.heap != right.heap); -} - #endif diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 9e68979f8c1..ba5dd5852b7 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -993,7 +993,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 84e88c96742..85d9f0522aa 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 f26328127f9..f3cab013437 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1580,7 +1580,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; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 5156db25166..a2c9828bfee 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -464,23 +464,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_sys.log.create(srv_n_log_files); @@ -628,83 +621,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<unsigned>(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 >> srv_page_size_shift; + 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 @@ -930,12 +908,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]; @@ -960,9 +937,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; } @@ -1863,10 +1839,8 @@ dberr_t srv_start(bool create_new_db) 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_sys.log.create(srv_n_log_files_found); diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 9ee9ba0f0f2..07654be12ee 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -779,9 +779,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); @@ -832,8 +830,8 @@ trx_assign_rseg_low() ut_ad(rseg->is_persistent()); if (rseg->space != fil_system.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 |