summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-11-28 01:02:46 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2018-11-28 01:02:46 +0200
commitbabb000a36f7a003cc0338cc7f8f01d0beaa5032 (patch)
tree1064292241b0af40ec8fd56000191df7ffcd5da1
parent4b88d5ee516fc7d2e51f55409623c63a1bde25f3 (diff)
parent4a92165ff04d6c0557eb99cc21ff88998337e376 (diff)
downloadmariadb-git-babb000a36f7a003cc0338cc7f8f01d0beaa5032.tar.gz
Merge 10.2 into 10.3
-rw-r--r--extra/mariabackup/fil_cur.cc9
-rw-r--r--extra/mariabackup/xtrabackup.cc64
-rw-r--r--storage/innobase/fil/fil0fil.cc370
-rw-r--r--storage/innobase/fsp/fsp0space.cc13
-rw-r--r--storage/innobase/fsp/fsp0sysspace.cc17
-rw-r--r--storage/innobase/handler/ha_innodb.cc4
-rw-r--r--storage/innobase/include/fil0fil.h43
-rw-r--r--storage/innobase/include/mem0mem.h100
-rw-r--r--storage/innobase/include/srv0srv.h2
-rw-r--r--storage/innobase/srv/srv0mon.cc2
-rw-r--r--storage/innobase/srv/srv0srv.cc2
-rw-r--r--storage/innobase/srv/srv0start.cc132
-rw-r--r--storage/innobase/trx/trx0trx.cc8
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