Commit babb000a authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.2 into 10.3

parents 4b88d5ee 4a92165f
...@@ -109,7 +109,6 @@ xb_fil_node_close_file( ...@@ -109,7 +109,6 @@ xb_fil_node_close_file(
ut_a(fil_system.n_open > 0); ut_a(fil_system.n_open > 0);
fil_system.n_open--; fil_system.n_open--;
fil_n_file_opened--;
if (node->space->purpose == FIL_TYPE_TABLESPACE && if (node->space->purpose == FIL_TYPE_TABLESPACE &&
fil_is_user_tablespace_id(node->space->id)) { fil_is_user_tablespace_id(node->space->id)) {
...@@ -159,8 +158,11 @@ xb_fil_cur_open( ...@@ -159,8 +158,11 @@ xb_fil_cur_open(
/* In the backup mode we should already have a tablespace handle created /* In the backup mode we should already have a tablespace handle created
by fil_ibd_load() unless it is a system by fil_ibd_load() unless it is a system
tablespace. Otherwise we open the file here. */ tablespace. Otherwise we open the file here. */
if (cursor->is_system() || srv_operation == SRV_OPERATION_RESTORE_DELTA if (!node->is_open()) {
|| xb_close_files) { ut_ad(cursor->is_system()
|| srv_operation == SRV_OPERATION_RESTORE_DELTA
|| xb_close_files);
node->handle = os_file_create_simple_no_error_handling( node->handle = os_file_create_simple_no_error_handling(
0, node->name, 0, node->name,
OS_FILE_OPEN, OS_FILE_OPEN,
...@@ -178,7 +180,6 @@ xb_fil_cur_open( ...@@ -178,7 +180,6 @@ xb_fil_cur_open(
mutex_enter(&fil_system.mutex); mutex_enter(&fil_system.mutex);
fil_system.n_open++; fil_system.n_open++;
fil_n_file_opened++;
if (node->space->purpose == FIL_TYPE_TABLESPACE && if (node->space->purpose == FIL_TYPE_TABLESPACE &&
fil_is_user_tablespace_id(node->space->id)) { fil_is_user_tablespace_id(node->space->id)) {
......
...@@ -3094,11 +3094,8 @@ xb_load_single_table_tablespace( ...@@ -3094,11 +3094,8 @@ xb_load_single_table_tablespace(
ut_a(space != NULL); ut_a(space != NULL);
if (!fil_node_create(file->filepath(), ulint(n_pages), space, space->add(file->filepath(), OS_FILE_CLOSED, ulint(n_pages),
false, false)) { false, false);
ut_error;
}
/* by opening the tablespace we forcing node and space objects /* by opening the tablespace we forcing node and space objects
in the cache to be populated with fields from space header */ in the cache to be populated with fields from space header */
space->open(); space->open();
...@@ -3775,22 +3772,17 @@ xb_filters_free() ...@@ -3775,22 +3772,17 @@ xb_filters_free()
} }
/*********************************************************************//** /*********************************************************************//**
Creates or opens the log files and closes them. Create log file metadata. */
@return DB_SUCCESS or error code */
static static
ulint void
open_or_create_log_file( open_or_create_log_file(
/*====================*/ /*====================*/
fil_space_t* space, fil_space_t* space,
ibool* log_file_created, /*!< out: TRUE if new log file
created */
ulint i) /*!< in: log file number in group */ ulint i) /*!< in: log file number in group */
{ {
char name[10000]; char name[10000];
ulint dirnamelen; ulint dirnamelen;
*log_file_created = FALSE;
os_normalize_path(srv_log_group_home_dir); os_normalize_path(srv_log_group_home_dir);
dirnamelen = strlen(srv_log_group_home_dir); dirnamelen = strlen(srv_log_group_home_dir);
...@@ -3802,14 +3794,13 @@ open_or_create_log_file( ...@@ -3802,14 +3794,13 @@ open_or_create_log_file(
name[dirnamelen++] = OS_PATH_SEPARATOR; 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_validate());
ut_a(fil_node_create(name, ulint(srv_log_file_size >> srv_page_size_shift), space->add(name, OS_FILE_CLOSED,
space, false, false)); ulint(srv_log_file_size >> srv_page_size_shift),
false, false);
return(DB_SUCCESS);
} }
/*********************************************************************** /***********************************************************************
...@@ -4069,13 +4060,6 @@ xtrabackup_backup_func() ...@@ -4069,13 +4060,6 @@ xtrabackup_backup_func()
xb_filters_init(); xb_filters_init();
{
ibool log_file_created;
ibool log_created = FALSE;
ibool log_opened = FALSE;
ulint err;
ulint i;
xb_fil_io_init(); xb_fil_io_init();
srv_n_file_io_threads = srv_n_read_io_threads; srv_n_file_io_threads = srv_n_read_io_threads;
...@@ -4088,36 +4072,8 @@ xtrabackup_backup_func() ...@@ -4088,36 +4072,8 @@ xtrabackup_backup_func()
"innodb_redo_log", SRV_LOG_SPACE_FIRST_ID, 0, "innodb_redo_log", SRV_LOG_SPACE_FIRST_ID, 0,
FIL_TYPE_LOG, NULL); FIL_TYPE_LOG, NULL);
for (i = 0; i < srv_n_log_files; i++) { for (ulint i = 0; i < srv_n_log_files; i++) {
err = open_or_create_log_file(space, &log_file_created, i); open_or_create_log_file(space, 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;
}
} }
/* create extra LSN dir if it does not exist. */ /* create extra LSN dir if it does not exist. */
......
...@@ -166,9 +166,6 @@ ulint fil_n_pending_log_flushes = 0; ...@@ -166,9 +166,6 @@ ulint fil_n_pending_log_flushes = 0;
/** Number of pending tablespace flushes */ /** Number of pending tablespace flushes */
ulint fil_n_pending_tablespace_flushes = 0; ulint fil_n_pending_tablespace_flushes = 0;
/** Number of files currently open */
ulint fil_n_file_opened = 0;
/** The null file address */ /** The null file address */
const fil_addr_t fil_addr_null = {FIL_NULL, 0}; const fil_addr_t fil_addr_null = {FIL_NULL, 0};
...@@ -437,36 +434,25 @@ fil_space_is_flushed( ...@@ -437,36 +434,25 @@ fil_space_is_flushed(
/** Append a file to the chain of files of a space. /** 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] name file name of a file that is not open
@param[in] size file size in entire database blocks @param[in] handle file handle, or OS_FILE_CLOSED
@param[in,out] space tablespace from fil_space_create() @param[in] size file size in entire database pages
@param[in] is_raw whether this is a raw device or partition @param[in] is_raw whether this is a raw device
@param[in] atomic_write true if the file could use atomic write @param[in] atomic_write true if atomic write could be enabled
@param[in] max_pages maximum number of pages in file, @param[in] max_pages maximum number of pages in file,
ULINT_MAX means the file size is unlimited. or ULINT_MAX for unlimited
@return pointer to the file name @return file object */
@retval NULL if error */ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle,
static ulint size, bool is_raw, bool atomic_write,
fil_node_t* ulint max_pages)
fil_node_create_low(
const char* name,
ulint size,
fil_space_t* space,
bool is_raw,
bool atomic_write,
ulint max_pages = ULINT_MAX)
{ {
fil_node_t* node; fil_node_t* node;
ut_ad(name != NULL); ut_ad(name != NULL);
ut_ad(fil_system.is_initialised()); ut_ad(fil_system.is_initialised());
if (space == NULL) {
return(NULL);
}
node = reinterpret_cast<fil_node_t*>(ut_zalloc_nokey(sizeof(*node))); node = reinterpret_cast<fil_node_t*>(ut_zalloc_nokey(sizeof(*node)));
node->handle = OS_FILE_CLOSED; node->handle = handle;
node->name = mem_strdup(name); node->name = mem_strdup(name);
...@@ -483,55 +469,115 @@ fil_node_create_low( ...@@ -483,55 +469,115 @@ fil_node_create_low(
node->init_size = size; node->init_size = size;
node->max_size = max_pages; node->max_size = max_pages;
mutex_enter(&fil_system.mutex); node->space = this;
space->size += size;
node->space = space;
node->atomic_write = atomic_write; 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); 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. /** Read the first page of a data file.
@param[in] name file name (file must be closed) @param[in] first whether this is the very first read
@param[in] size file size in database blocks, rounded downwards to @return whether the page was found valid */
an integer bool fil_node_t::read_page0(bool first)
@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)
{ {
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( if (size_bytes < min_size) {
name, size, space, is_raw, atomic_write, max_pages); 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. /** Open a file node of a tablespace.
@param[in,out] node File node @param[in,out] node File node
@return false if the file can't be opened, otherwise true */ @return false if the file can't be opened, otherwise true */
static static bool fil_node_open_file(fil_node_t* node)
bool
fil_node_open_file(
fil_node_t* node)
{ {
bool success; bool success;
bool read_only_mode; bool read_only_mode;
...@@ -559,9 +605,12 @@ fil_node_open_file( ...@@ -559,9 +605,12 @@ fil_node_open_file(
from a file opened for async I/O! */ from a file opened for async I/O! */
retry: retry:
node->handle = os_file_create_simple_no_error_handling( node->handle = os_file_create(
innodb_data_file_key, node->name, OS_FILE_OPEN, innodb_data_file_key, node->name,
OS_FILE_READ_ONLY, read_only_mode, &success); 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) { if (!success) {
/* The following call prints an error message */ /* The following call prints an error message */
...@@ -577,156 +626,52 @@ fil_node_open_file( ...@@ -577,156 +626,52 @@ fil_node_open_file(
return(false); return(false);
} }
os_offset_t size_bytes = os_file_get_size(node->handle); if (!node->read_page0(first_time_open)) {
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;
os_file_close(node->handle); os_file_close(node->handle);
node->handle = OS_FILE_CLOSED; node->handle = OS_FILE_CLOSED;
return(false); 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;
} }
} } else if (space->purpose == FIL_TYPE_LOG) {
/* 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) {
node->handle = os_file_create( node->handle = os_file_create(
innodb_log_file_key, node->name, OS_FILE_OPEN, innodb_log_file_key, node->name, OS_FILE_OPEN,
OS_FILE_AIO, OS_LOG_FILE, read_only_mode, &success); 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 { } else {
node->handle = os_file_create( 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); OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success);
}
if (first_time_open) { if (space->purpose != FIL_TYPE_LOG) {
/* /*
For the temporary tablespace and during the For the temporary tablespace and during the
non-redo-logged adjustments in non-redo-logged adjustments in
IMPORT TABLESPACE, we do not care about IMPORT TABLESPACE, we do not care about
the atomicity of writes. the atomicity of writes.
Atomic writes is supported if the file can be used Atomic writes is supported if the file can be used
with atomic_writes (not log file), O_DIRECT is with atomic_writes (not log file), O_DIRECT is
used (tested in ha_innodb.cc) and the file is used (tested in ha_innodb.cc) and the file is
device and file system that supports atomic writes device and file system that supports atomic writes
for the given block size for the given block size
*/ */
space->atomic_write_supported space->atomic_write_supported
= space->purpose == FIL_TYPE_TEMPORARY = space->purpose == FIL_TYPE_TEMPORARY
|| space->purpose == FIL_TYPE_IMPORT || space->purpose == FIL_TYPE_IMPORT
|| (node->atomic_write || (node->atomic_write
&& srv_use_atomic_writes && srv_use_atomic_writes
&& my_test_if_atomic_write( && my_test_if_atomic_write(
node->handle, node->handle,
int(page_size_t(space->flags) int(page_size_t(space->flags)
.physical()))); .physical())));
} }
}
ut_a(success); ut_a(success);
ut_a(node->is_open()); ut_a(node->is_open());
fil_system.n_open++; fil_system.n_open++;
fil_n_file_opened++;
if (fil_space_belongs_in_lru(space)) { if (fil_space_belongs_in_lru(space)) {
...@@ -761,7 +706,6 @@ void fil_node_t::close() ...@@ -761,7 +706,6 @@ void fil_node_t::close()
ut_ad(!is_open()); ut_ad(!is_open());
ut_a(fil_system.n_open > 0); ut_a(fil_system.n_open > 0);
fil_system.n_open--; fil_system.n_open--;
fil_n_file_opened--;
if (fil_space_belongs_in_lru(space)) { if (fil_space_belongs_in_lru(space)) {
ut_a(UT_LIST_GET_LEN(fil_system.LRU) > 0); ut_a(UT_LIST_GET_LEN(fil_system.LRU) > 0);
...@@ -1396,7 +1340,7 @@ Error messages are issued to the server log. ...@@ -1396,7 +1340,7 @@ Error messages are issued to the server log.
@param[in] purpose tablespace purpose @param[in] purpose tablespace purpose
@param[in,out] crypt_data encryption information @param[in,out] crypt_data encryption information
@param[in] mode encryption mode @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) */ @retval NULL on failure (such as when the same tablespace exists) */
fil_space_t* fil_space_t*
fil_space_create( fil_space_create(
...@@ -1472,7 +1416,7 @@ fil_space_create( ...@@ -1472,7 +1416,7 @@ fil_space_create(
if (space->purpose == FIL_TYPE_TEMPORARY) { if (space->purpose == FIL_TYPE_TEMPORARY) {
/* SysTablespace::open_or_create() would pass /* 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 would not hold in fil_node_open_file(), and we
must assign this manually. We do not care about must assign this manually. We do not care about
the durability or atomicity of writes to the the durability or atomicity of writes to the
...@@ -3225,17 +3169,17 @@ fil_ibd_create( ...@@ -3225,17 +3169,17 @@ fil_ibd_create(
free(crypt_data); free(crypt_data);
*err = DB_ERROR; *err = DB_ERROR;
} else { } else {
fil_node_t* node = fil_node_create_low(path, size, space, fil_node_t* file = space->add(path, OS_FILE_CLOSED, size,
false, true); false, true);
mtr_t mtr; mtr_t mtr;
mtr.start(); mtr.start();
fil_op_write_log( 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); NULL, space->flags & ~FSP_FLAGS_MEM_MASK, &mtr);
fil_name_write(space, 0, node, &mtr); fil_name_write(space, 0, file, &mtr);
mtr.commit(); mtr.commit();
node->block_size = block_size; file->block_size = block_size;
space->punch_hole = punch_hole; space->punch_hole = punch_hole;
*err = DB_SUCCESS; *err = DB_SUCCESS;
...@@ -3603,17 +3547,17 @@ fil_ibd_open( ...@@ -3603,17 +3547,17 @@ fil_ibd_open(
fil_space_t* space = fil_space_create( fil_space_t* space = fil_space_create(
tablename.m_name, id, flags, purpose, crypt_data); 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 do not measure the size of the file, that is why
we pass the 0 below */ we pass the 0 below */
if (fil_node_create_low( space->add(
df_remote.is_open() ? df_remote.filepath() : df_remote.is_open() ? df_remote.filepath() :
df_dict.is_open() ? df_dict.filepath() : df_dict.is_open() ? df_dict.filepath() :
df_default.filepath(), 0, space, false, df_default.filepath(), OS_FILE_CLOSED, 0, false, true);
true) == NULL) {
goto error;
}
if (validate && purpose != FIL_TYPE_IMPORT && !srv_read_only_mode) { if (validate && purpose != FIL_TYPE_IMPORT && !srv_read_only_mode) {
df_remote.close(); df_remote.close();
...@@ -3962,9 +3906,7 @@ fil_ibd_load( ...@@ -3962,9 +3906,7 @@ fil_ibd_load(
the rounding formula for extents and pages is somewhat complex; we the rounding formula for extents and pages is somewhat complex; we
let fil_node_open() do that task. */ let fil_node_open() do that task. */
if (!fil_node_create_low(file.filepath(), 0, space, false, false)) { space->add(file.filepath(), OS_FILE_CLOSED, 0, false, false);
ut_error;
}
return(FIL_LOAD_OK); return(FIL_LOAD_OK);
} }
......
...@@ -123,18 +123,15 @@ Tablespace::open_or_create(bool is_temp) ...@@ -123,18 +123,15 @@ Tablespace::open_or_create(bool is_temp)
is_temp is_temp
? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE, ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE,
NULL); NULL);
if (!space) {
return DB_ERROR;
}
} }
ut_a(fil_validate()); ut_a(fil_validate());
/* Create the tablespace node entry for this data file. */ space->add(it->m_filepath, OS_FILE_CLOSED, it->m_size,
if (!fil_node_create( false, true);
it->m_filepath, it->m_size, space, false,
TRUE)) {
err = DB_ERROR;
break;
}
} }
return(err); return(err);
......
...@@ -907,12 +907,18 @@ SysTablespace::open_or_create( ...@@ -907,12 +907,18 @@ SysTablespace::open_or_create(
space = fil_system.temp_space = fil_space_create( space = fil_system.temp_space = fil_space_create(
name(), SRV_TMP_SPACE_ID, flags(), name(), SRV_TMP_SPACE_ID, flags(),
FIL_TYPE_TEMPORARY, NULL); FIL_TYPE_TEMPORARY, NULL);
if (!space) {
return DB_ERROR;
}
} else { } else {
ut_ad(!fil_system.sys_space); ut_ad(!fil_system.sys_space);
ut_ad(space_id() == TRX_SYS_SPACE); ut_ad(space_id() == TRX_SYS_SPACE);
space = fil_system.sys_space = fil_space_create( space = fil_system.sys_space = fil_space_create(
name(), TRX_SYS_SPACE, flags(), name(), TRX_SYS_SPACE, flags(),
FIL_TYPE_TABLESPACE, NULL); FIL_TYPE_TABLESPACE, NULL);
if (!space) {
return DB_ERROR;
}
} }
ut_a(fil_validate()); ut_a(fil_validate());
...@@ -923,15 +929,8 @@ SysTablespace::open_or_create( ...@@ -923,15 +929,8 @@ SysTablespace::open_or_create(
: m_last_file_size_max) : m_last_file_size_max)
: it->m_size); : it->m_size);
/* Add the datafile to the fil_system cache. */ space->add(it->m_filepath, OS_FILE_CLOSED, it->m_size,
if (!fil_node_create( it->m_type != SRV_NOT_RAW, true, max_size);
it->m_filepath, it->m_size,
space, it->m_type != SRV_NOT_RAW,
TRUE, max_size)) {
err = DB_ERROR;
break;
}
} }
return(err); return(err);
......
...@@ -12360,7 +12360,7 @@ int create_table_info_t::create_table(bool create_fk) ...@@ -12360,7 +12360,7 @@ int create_table_info_t::create_table(bool create_fk)
the failed creation. */ the failed creation. */
m_trx->error_state = DB_SUCCESS; m_trx->error_state = DB_SUCCESS;
row_drop_table_for_mysql(m_table_name, m_trx, row_drop_table_for_mysql(m_table_name, m_trx,
SQLCOM_DROP_DB); SQLCOM_TRUNCATE);
trx_rollback_to_savepoint(m_trx, NULL); trx_rollback_to_savepoint(m_trx, NULL);
m_trx->error_state = DB_SUCCESS; m_trx->error_state = DB_SUCCESS;
...@@ -12592,7 +12592,7 @@ ha_innobase::create( ...@@ -12592,7 +12592,7 @@ ha_innobase::create(
that could have been renamed before the failed creation. */ that could have been renamed before the failed creation. */
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
row_drop_table_for_mysql(info.table_name(), trx, row_drop_table_for_mysql(info.table_name(), trx,
SQLCOM_DROP_DB, true); SQLCOM_TRUNCATE, true);
trx_rollback_for_mysql(trx); trx_rollback_for_mysql(trx);
row_mysql_unlock_data_dictionary(trx); row_mysql_unlock_data_dictionary(trx);
if (own_trx) { if (own_trx) {
......
...@@ -189,6 +189,19 @@ struct fil_space_t { ...@@ -189,6 +189,19 @@ struct fil_space_t {
&& srv_use_doublewrite_buf && buf_dblwr; && 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. /** Try to reserve free extents.
@param[in] n_free_now current number of free extents @param[in] n_free_now current number of free extents
@param[in] n_to_reserve number of extents to reserve @param[in] n_to_reserve number of extents to reserve
...@@ -324,6 +337,11 @@ struct fil_node_t { ...@@ -324,6 +337,11 @@ struct fil_node_t {
return(handle != OS_FILE_CLOSED); 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. */ /** Close the file handle. */
void close(); void close();
}; };
...@@ -528,9 +546,6 @@ extern ulint fil_n_pending_log_flushes; ...@@ -528,9 +546,6 @@ extern ulint fil_n_pending_log_flushes;
/** Number of pending tablespace flushes */ /** Number of pending tablespace flushes */
extern ulint fil_n_pending_tablespace_flushes; extern ulint fil_n_pending_tablespace_flushes;
/** Number of files currently open */
extern ulint fil_n_file_opened;
#ifndef UNIV_INNOCHECKSUM #ifndef UNIV_INNOCHECKSUM
/** Look up a tablespace. /** Look up a tablespace.
...@@ -645,26 +660,6 @@ fil_space_get_latch( ...@@ -645,26 +660,6 @@ fil_space_get_latch(
ulint id, ulint id,
ulint* flags); 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. /** Create a space memory object and put it to the fil_system hash table.
Error messages are issued to the server log. Error messages are issued to the server log.
@param[in] name tablespace name @param[in] name tablespace name
...@@ -673,7 +668,7 @@ Error messages are issued to the server log. ...@@ -673,7 +668,7 @@ Error messages are issued to the server log.
@param[in] purpose tablespace purpose @param[in] purpose tablespace purpose
@param[in,out] crypt_data encryption information @param[in,out] crypt_data encryption information
@param[in] mode encryption mode @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) */ @retval NULL on failure (such as when the same tablespace exists) */
fil_space_t* fil_space_t*
fil_space_create( fil_space_create(
......
...@@ -418,104 +418,4 @@ struct mem_block_info_t { ...@@ -418,104 +418,4 @@ struct mem_block_info_t {
UNIV_MEM_ALIGNMENT) UNIV_MEM_ALIGNMENT)
#include "mem0mem.ic" #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 #endif
...@@ -993,7 +993,7 @@ struct export_var_t{ ...@@ -993,7 +993,7 @@ struct export_var_t{
ulint innodb_system_rows_inserted; /*!< srv_n_system_rows_inserted */ ulint innodb_system_rows_inserted; /*!< srv_n_system_rows_inserted */
ulint innodb_system_rows_updated; /*!< srv_n_system_rows_updated */ ulint innodb_system_rows_updated; /*!< srv_n_system_rows_updated */
ulint innodb_system_rows_deleted; /*!< srv_n_system_rows_deleted*/ 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_truncated_status_writes; /*!< srv_truncated_status_writes */
ulint innodb_available_undo_logs; /*!< srv_available_undo_logs ulint innodb_available_undo_logs; /*!< srv_available_undo_logs
*/ */
......
...@@ -1960,7 +1960,7 @@ srv_mon_process_existing_counter( ...@@ -1960,7 +1960,7 @@ srv_mon_process_existing_counter(
break; break;
case MONITOR_OVLD_N_FILE_OPENED: case MONITOR_OVLD_N_FILE_OPENED:
value = fil_n_file_opened; value = fil_system.n_open;
break; break;
case MONITOR_OVLD_IBUF_MERGE_INSERT: case MONITOR_OVLD_IBUF_MERGE_INSERT:
......
...@@ -1580,7 +1580,7 @@ srv_export_innodb_status(void) ...@@ -1580,7 +1580,7 @@ srv_export_innodb_status(void)
export_vars.innodb_system_rows_deleted = export_vars.innodb_system_rows_deleted =
srv_stats.n_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 = export_vars.innodb_truncated_status_writes =
srv_truncated_status_writes; srv_truncated_status_writes;
......
...@@ -464,23 +464,16 @@ create_log_files( ...@@ -464,23 +464,16 @@ create_log_files(
const ulint size = ulint(srv_log_file_size >> srv_page_size_shift); const ulint size = ulint(srv_log_file_size >> srv_page_size_shift);
logfile0 = fil_node_create( logfile0 = log_space->add(logfilename, OS_FILE_CLOSED, size,
logfilename, size, log_space, false, false); false, false)->name;
ut_a(logfile0); ut_a(logfile0);
for (unsigned i = 1; i < srv_n_log_files; i++) { for (unsigned i = 1; i < srv_n_log_files; i++) {
sprintf(logfilename + dirnamelen, "ib_logfile%u", i); sprintf(logfilename + dirnamelen, "ib_logfile%u", i);
if (!fil_node_create(logfilename, size, log_space->add(logfilename, OS_FILE_CLOSED, size,
log_space, false, false)) { false, false);
ib::error()
<< "Cannot create file node for log file "
<< logfilename;
return(DB_ERROR);
}
} }
log_sys.log.create(srv_n_log_files); log_sys.log.create(srv_n_log_files);
...@@ -628,83 +621,68 @@ srv_undo_tablespace_create( ...@@ -628,83 +621,68 @@ srv_undo_tablespace_create(
return(err); return(err);
} }
/*********************************************************************//**
Open an undo tablespace. /** Open an undo tablespace.
@return DB_SUCCESS or error code */ @param[in] name tablespace file name
static @param[in] space_id tablespace ID
dberr_t @param[in] create_new_db whether undo tablespaces are being created
srv_undo_tablespace_open( @return whether the tablespace was opened */
/*=====================*/ static bool srv_undo_tablespace_open(const char* name, ulint space_id,
const char* name, /*!< in: tablespace file name */ bool create_new_db)
ulint space_id) /*!< in: tablespace id */
{ {
pfs_os_file_t fh; pfs_os_file_t fh;
bool ret; bool success;
dberr_t err = DB_ERROR;
char undo_name[sizeof "innodb_undo000"]; char undo_name[sizeof "innodb_undo000"];
snprintf(undo_name, sizeof(undo_name), snprintf(undo_name, sizeof(undo_name),
"innodb_undo%03u", static_cast<unsigned>(space_id)); "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( fh = os_file_create(
innodb_data_file_key, name, innodb_data_file_key, name, OS_FILE_OPEN
OS_FILE_OPEN_RETRY | OS_FILE_ON_ERROR_NO_EXIT | OS_FILE_ON_ERROR_SILENT,
| OS_FILE_ON_ERROR_NO_EXIT OS_FILE_AIO, OS_DATA_FILE, srv_read_only_mode, &success);
| OS_FILE_ON_ERROR_SILENT, if (!success) {
OS_FILE_NORMAL, return false;
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);
ret = os_file_close(fh); os_offset_t size = os_file_get_size(fh);
ut_a(ret); ut_a(size != os_offset_t(-1));
/* Load the tablespace into InnoDB's internal /* Load the tablespace into InnoDB's internal data structures. */
data structures. */
/* We set the biggest space id to the undo tablespace /* We set the biggest space id to the undo tablespace
because InnoDB hasn't opened any other tablespace apart because InnoDB hasn't opened any other tablespace apart
from the system tablespace. */ 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( fil_space_t* space = fil_space_create(
undo_name, space_id, FSP_FLAGS_PAGE_SSIZE(), undo_name, space_id, FSP_FLAGS_PAGE_SSIZE(),
FIL_TYPE_TABLESPACE, NULL); FIL_TYPE_TABLESPACE, NULL);
ut_a(fil_validate()); ut_a(fil_validate());
ut_a(space); 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 mutex_enter(&fil_system.mutex);
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)) {
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 /** Check if undo tablespaces and redo log files exist before creating a
...@@ -930,12 +908,11 @@ srv_undo_tablespaces_init(bool create_new_db) ...@@ -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] != 0);
ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED); ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED);
err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]); if (!srv_undo_tablespace_open(name, undo_tablespace_ids[i],
create_new_db)) {
if (err != DB_SUCCESS) {
ib::error() << "Unable to open undo tablespace '" ib::error() << "Unable to open undo tablespace '"
<< name << "'."; << name << "'.";
return(err); return DB_ERROR;
} }
prev_space_id = undo_tablespace_ids[i]; prev_space_id = undo_tablespace_ids[i];
...@@ -960,9 +937,8 @@ srv_undo_tablespaces_init(bool create_new_db) ...@@ -960,9 +937,8 @@ srv_undo_tablespaces_init(bool create_new_db)
name, sizeof(name), name, sizeof(name),
"%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i); "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i);
err = srv_undo_tablespace_open(name, i); if (!srv_undo_tablespace_open(name, i, create_new_db)) {
err = DB_ERROR;
if (err != DB_SUCCESS) {
break; break;
} }
...@@ -1863,10 +1839,8 @@ dberr_t srv_start(bool create_new_db) ...@@ -1863,10 +1839,8 @@ dberr_t srv_start(bool create_new_db)
for (unsigned j = 0; j < srv_n_log_files_found; j++) { for (unsigned j = 0; j < srv_n_log_files_found; j++) {
sprintf(logfilename + dirnamelen, "ib_logfile%u", j); sprintf(logfilename + dirnamelen, "ib_logfile%u", j);
if (!fil_node_create(logfilename, size, log_space->add(logfilename, OS_FILE_CLOSED, size,
log_space, false, false)) { false, false);
return(srv_init_abort(DB_ERROR));
}
} }
log_sys.log.create(srv_n_log_files_found); log_sys.log.create(srv_n_log_files_found);
......
...@@ -779,9 +779,7 @@ trx_lists_init_at_db_start() ...@@ -779,9 +779,7 @@ trx_lists_init_at_db_start()
evenly distributed between 0 and innodb_undo_logs-1 evenly distributed between 0 and innodb_undo_logs-1
@return persistent rollback segment @return persistent rollback segment
@retval NULL if innodb_read_only */ @retval NULL if innodb_read_only */
static static trx_rseg_t* trx_assign_rseg_low()
trx_rseg_t*
trx_assign_rseg_low()
{ {
if (srv_read_only_mode) { if (srv_read_only_mode) {
ut_ad(srv_undo_logs == ULONG_UNDEFINED); ut_ad(srv_undo_logs == ULONG_UNDEFINED);
...@@ -832,8 +830,8 @@ trx_assign_rseg_low() ...@@ -832,8 +830,8 @@ trx_assign_rseg_low()
ut_ad(rseg->is_persistent()); ut_ad(rseg->is_persistent());
if (rseg->space != fil_system.sys_space) { 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; continue;
} }
} else if (trx_rseg_t* next } else if (trx_rseg_t* next
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment