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

MDEV-25312 Replace fil_space_t::name with fil_space_t::name()

A consistency check for fil_space_t::name is causing recovery failures
in MDEV-25180 (Atomic ALTER TABLE). So, we'd better remove that field
altogether.

fil_space_t::name was more or less a copy of dict_table_t::name
(except for some special cases), and it was not being used for
anything useful.

There used to be a name_hash, but it had been removed already in
commit a75dbfd7 (MDEV-12266).

We will also remove os_normalize_path(), OS_PATH_SEPARATOR,
OS_PATH_SEPATOR_ALT. On Microsoft Windows, we will treat \ and /
roughly in the same way. The intention is that for per-table
tablespaces, the filenames will always follow the pattern
prefix/databasename/tablename.ibd. (Any \ in the prefix must not
be converted.)

ut_basename_noext(): Remove (unused function).

read_link_file(): Replaces RemoteDatafile::read_link_file().
We will ensure that the last two path component separators are
forward slashes (converting up to 2 trailing backslashes on
Microsoft Windows), so that everywhere else we can
assume that data file names end in "/databasename/tablename.ibd".

Note: On Microsoft Windows, path names that start with \\?\ must
not contain / as path component separators. Previously, such paths
did work in the DATA DIRECTORY argument of InnoDB tables.

Reviewed by: Vladislav Vaintroub
parent c2a63ac5
......@@ -273,7 +273,6 @@ datadir_iter_next_database(datadir_iter_t *it)
}
snprintf(it->dbpath, it->dbpath_len, "%s/%s",
it->datadir_path, it->dbinfo.name);
os_normalize_path(it->dbpath);
if (it->dbinfo.type == OS_FILE_TYPE_FILE) {
it->is_file = true;
......@@ -1133,13 +1132,12 @@ read_link_file(const char *ibd_filepath, const char *link_filepath)
os_file_read_string(file, filepath, OS_FILE_MAX_PATH);
fclose(file);
if (strlen(filepath)) {
if (size_t len = strlen(filepath)) {
/* Trim whitespace from end of filepath */
ulint lastch = strlen(filepath) - 1;
ulint lastch = len - 1;
while (lastch > 4 && filepath[lastch] <= 0x20) {
filepath[lastch--] = 0x00;
}
os_normalize_path(filepath);
}
tablespace_locations[ibd_filepath] = filepath;
......@@ -1852,9 +1850,8 @@ copy_back()
end(srv_sys_space.end());
iter != end;
++iter) {
const char *filename = base_name(iter->name());
if (!(ret = copy_or_move_file(filename, iter->name(),
const char *filepath = iter->filepath();
if (!(ret = copy_or_move_file(base_name(filepath), filepath,
dst_dir, 1))) {
goto cleanup;
}
......@@ -1877,7 +1874,6 @@ copy_back()
const char *filename;
char c_tmp;
int i_tmp;
bool is_ibdata_file;
if (strstr(node.filepath,"/" ROCKSDB_BACKUP_DIR "/")
#ifdef _WIN32
......@@ -1932,23 +1928,19 @@ copy_back()
}
/* skip innodb data files */
is_ibdata_file = false;
for (Tablespace::const_iterator iter(srv_sys_space.begin()),
end(srv_sys_space.end()); iter != end; ++iter) {
const char *ibfile = base_name(iter->name());
if (strcmp(ibfile, filename) == 0) {
is_ibdata_file = true;
break;
if (!strcmp(base_name(iter->filepath()), filename)) {
goto next_file;
}
}
if (is_ibdata_file) {
continue;
}
if (!(ret = copy_or_move_file(node.filepath, node.filepath_rel,
mysql_data_home, 1))) {
goto cleanup;
}
next_file:
continue;
}
/* copy buffer pool dump */
......@@ -2123,7 +2115,14 @@ static bool backup_files_from_datadir(const char *dir_path)
if (info.type != OS_FILE_TYPE_FILE)
continue;
const char *pname = strrchr(info.name, OS_PATH_SEPARATOR);
const char *pname = strrchr(info.name, '/');
#ifdef _WIN32
if (const char *last = strrchr(info.name, '\\')) {
if (!pname || last >pname) {
pname = last;
}
}
#endif
if (!pname)
pname = info.name;
......@@ -2140,7 +2139,7 @@ static bool backup_files_from_datadir(const char *dir_path)
unlink(info.name);
std::string full_path(dir_path);
full_path.append(1, OS_PATH_SEPARATOR).append(info.name);
full_path.append(1, '/').append(info.name);
if (!(ret = copy_file(ds_data, full_path.c_str() , info.name, 1)))
break;
}
......
#pragma once
#include "my_dbug.h"
#ifndef DBUG_OFF
extern char *dbug_mariabackup_get_val(const char *event, const char *key);
char *dbug_mariabackup_get_val(const char *event, fil_space_t::name_type key);
/*
In debug mode, execute SQL statement that was passed via environment.
To use this facility, you need to
......@@ -14,19 +14,11 @@ To use this facility, you need to
for the variable)
3. start mariabackup with --dbug=+d,debug_mariabackup_events
*/
extern void dbug_mariabackup_event(
const char *event,const char *key);
#define DBUG_MARIABACKUP_EVENT(A, B) \
DBUG_EXECUTE_IF("mariabackup_events", \
dbug_mariabackup_event(A,B););
#define DBUG_EXECUTE_FOR_KEY(EVENT, KEY, CODE) \
DBUG_EXECUTE_IF("mariabackup_inject_code", {\
char *dbug_val = dbug_mariabackup_get_val(EVENT, KEY); \
if (dbug_val && *dbug_val) CODE \
})
#define DBUG_EXECUTE_FOR_KEY(EVENT, KEY, CODE) \
DBUG_EXECUTE_IF("mariabackup_inject_code", \
{ char *dbug_val= dbug_mariabackup_get_val(EVENT, KEY); \
if (dbug_val) CODE })
#else
#define DBUG_MARIABACKUP_EVENT(A,B)
#define DBUG_MARIABACKUP_EVENT_LOCK(A,B)
#define DBUG_EXECUTE_FOR_KEY(EVENT, KEY, CODE)
#endif
......@@ -65,17 +65,21 @@ xb_get_relative_path(
prev = NULL;
cur = path;
while ((next = strchr(cur, OS_PATH_SEPARATOR)) != NULL) {
#ifdef _WIN32
while ((next = strchr(cur, '\\')) != NULL) {
prev = cur;
cur = next + 1;
}
#endif
while ((next = strchr(cur, '/')) != NULL) {
prev = cur;
cur = next + 1;
}
if (is_system) {
return(cur);
} else {
return((prev == NULL) ? cur : prev);
}
......@@ -462,7 +466,8 @@ xb_fil_cur_result_t xb_fil_cur_read(xb_fil_cur_t* cursor,
goto read_retry;
}
}
DBUG_EXECUTE_FOR_KEY("add_corrupted_page_for", cursor->node->space->name,
DBUG_EXECUTE_FOR_KEY("add_corrupted_page_for",
cursor->node->space->name(),
{
unsigned corrupted_page_no =
static_cast<unsigned>(strtoul(dbug_val, NULL, 10));
......
This diff is collapsed.
......@@ -31,7 +31,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
FOUND 1 /The innodb_system data file 'ibdata1' was not found but one of the other data files 'ibdata2' exists/ in mysqld.1.err
FOUND 1 /The data file '.*ibdata1' was not found but one of the other data files '.*ibdata2' exists/ in mysqld.1.err
bak_ib_logfile0
bak_ibdata1
bak_ibdata2
......
......@@ -14,7 +14,7 @@ call mtr.add_suppression("InnoDB: The error means the system cannot find the pat
call mtr.add_suppression("InnoDB: If you are installing InnoDB, remember that you must create directories yourself");
call mtr.add_suppression("InnoDB: File .path.to.non-existent.ib_logfile101: 'create' returned OS error \d+");
call mtr.add_suppression("InnoDB: Cannot create .path.to.non-existent.ib_logfile101");
call mtr.add_suppression("InnoDB: The innodb_system data file 'ibdata1' was not found but one of the other data files 'ibdata2' exists");
call mtr.add_suppression("InnoDB: The data file '.*ibdata1' was not found but one of the other data files '.*ibdata2' exists");
call mtr.add_suppression("InnoDB: Tablespace size stored in header is \d+ pages, but the sum of data file sizes is \d+ pages");
call mtr.add_suppression("InnoDB: Cannot start InnoDB. The tail of the system tablespace is missing");
call mtr.add_suppression("InnoDB: undo tablespace '.*undo001' exists\. Creating system tablespace with existing undo tablespaces is not supported\. Please delete all undo tablespaces before creating new system tablespace\.");
......@@ -90,7 +90,7 @@ eval $check_yes_innodb;
--source include/start_mysqld.inc
eval $check_no_innodb;
--source include/shutdown_mysqld.inc
let SEARCH_PATTERN=The innodb_system data file 'ibdata1' was not found but one of the other data files 'ibdata2' exists;
let SEARCH_PATTERN=The data file '.*ibdata1' was not found but one of the other data files '.*ibdata2' exists;
--source include/search_pattern_in_file.inc
# clean up & Restore
......
......@@ -48,6 +48,15 @@ close OUT or die;
die unless open OUT, ">", "$ENV{MYSQL_TMP_DIR}/test/td.ibd";
print OUT "xyz " x $ENV{page_size};
close OUT or die;
die unless open ISL, "+<", "$ENV{datadir}/test/td.isl";
$_=<ISL>;
if (m|^[a-zA-Z]:|)
{
tr|/|\\|;
seek(ISL, 0, SEEK_SET) or die;
print ISL or die;
}
close ISL or die;
EOF
--let $restart_parameters= --skip-innodb-buffer-pool-load-at-startup
......
......@@ -374,7 +374,7 @@ void buf_dblwr_t::recover()
if (!srv_is_undo_tablespace(space_id))
ib::warn() << "A copy of page " << page_no
<< " in the doublewrite buffer slot " << page_no_dblwr
<< " is beyond the end of tablespace " << space->name
<< " is beyond the end of " << space->chain.start->name
<< " (" << space->size << " pages)";
next_page:
space->release();
......@@ -395,7 +395,7 @@ void buf_dblwr_t::recover()
if (UNIV_UNLIKELY(fio.err != DB_SUCCESS))
ib::warn() << "Double write buffer recovery: " << page_id
<< " (tablespace '" << space->name
<< " ('" << space->chain.start->name
<< "') read failed with error: " << fio.err;
if (buf_is_zeroes(span<const byte>(read_buf, physical_size)))
......
......@@ -181,8 +181,8 @@ static void buf_dump_generate_path(char *path, size_t path_size)
char buf[FN_REFLEN];
mysql_mutex_lock(&LOCK_global_system_variables);
snprintf(buf, sizeof(buf), "%s%c%s", get_buf_dump_dir(),
OS_PATH_SEPARATOR, srv_buf_dump_filename);
snprintf(buf, sizeof buf, "%s/%s", get_buf_dump_dir(),
srv_buf_dump_filename);
mysql_mutex_unlock(&LOCK_global_system_variables);
os_file_type_t type;
......@@ -205,19 +205,21 @@ static void buf_dump_generate_path(char *path, size_t path_size)
char srv_data_home_full[FN_REFLEN];
my_realpath(srv_data_home_full, get_buf_dump_dir(), 0);
const char *format;
if (srv_data_home_full[strlen(srv_data_home_full) - 1]
== OS_PATH_SEPARATOR) {
snprintf(path, path_size, "%s%s",
srv_data_home_full,
srv_buf_dump_filename);
} else {
snprintf(path, path_size, "%s%c%s",
srv_data_home_full,
OS_PATH_SEPARATOR,
srv_buf_dump_filename);
switch (srv_data_home_full[strlen(srv_data_home_full) - 1]) {
#ifdef _WIN32
case '\\':
#endif
case '/':
format = "%s%s";
break;
default:
format = "%s/%s";
}
snprintf(path, path_size, format,
srv_data_home_full, srv_buf_dump_filename);
}
}
......
......@@ -407,11 +407,11 @@ dict_build_table_def_step(
bool has_data_dir = DICT_TF_HAS_DATA_DIR(table->flags);
ulint fsp_flags = dict_tf_to_fsp_flags(table->flags);
ut_ad(!has_data_dir || table->data_dir_path);
char* filepath = has_data_dir
? fil_make_filepath(table->data_dir_path,
table->name.m_name, IBD, true)
: fil_make_filepath(NULL,
table->name.m_name, IBD, false);
char* filepath = fil_make_filepath(has_data_dir
? table->data_dir_path
: nullptr,
table->name, IBD,
has_data_dir);
/* We create a new single-table tablespace for the table.
We initially let it be 4 pages:
......@@ -423,7 +423,7 @@ dict_build_table_def_step(
dberr_t err;
table->space = fil_ibd_create(
space_id, table->name.m_name, filepath, fsp_flags,
space_id, table->name, filepath, fsp_flags,
FIL_IBD_FILE_INITIAL_SIZE,
node->mode, node->key_id, &err);
......
......@@ -1603,16 +1603,12 @@ dict_table_rename_in_cache(
/* Make sure the data_dir_path is set. */
dict_get_and_save_data_dir_path(table, true);
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
ut_a(table->data_dir_path);
const char* data_dir = DICT_TF_HAS_DATA_DIR(table->flags)
? table->data_dir_path : nullptr;
ut_ad(data_dir || !DICT_TF_HAS_DATA_DIR(table->flags));
filepath = fil_make_filepath(
table->data_dir_path, table->name.m_name,
IBD, true);
} else {
filepath = fil_make_filepath(
NULL, table->name.m_name, IBD, false);
}
filepath = fil_make_filepath(data_dir, table->name, IBD,
data_dir != nullptr);
if (filepath == NULL) {
return(DB_OUT_OF_MEMORY);
......@@ -1637,11 +1633,14 @@ dict_table_rename_in_cache(
ut_ad(!table->is_temporary());
const fil_space_t::name_type new_space_name{
new_name, strlen(new_name)};
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
new_path = os_file_make_new_pathname(
old_path, new_name);
err = RemoteDatafile::create_link_file(
new_name, new_path);
new_space_name, new_path);
if (err != DB_SUCCESS) {
ut_free(new_path);
......@@ -1649,24 +1648,30 @@ dict_table_rename_in_cache(
}
} else {
new_path = fil_make_filepath(
NULL, new_name, IBD, false);
NULL, new_space_name, IBD, false);
}
/* New filepath must not exist. */
err = table->space->rename(new_name, new_path, true,
replace_new_file);
err = table->space->rename(new_path, true, replace_new_file);
ut_free(new_path);
/* If the tablespace is remote, a new .isl file was created
If success, delete the old one. If not, delete the new one. */
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
RemoteDatafile::delete_link_file(
err == DB_SUCCESS ? old_name : new_name);
}
if (err != DB_SUCCESS) {
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
RemoteDatafile::delete_link_file(
new_space_name);
}
return err;
}
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
RemoteDatafile::delete_link_file(
{old_name, strlen(old_name)});
}
}
/* Remove table from the hash tables of tables */
......
......@@ -1050,15 +1050,12 @@ static ulint dict_check_sys_tables()
newly created or rebuilt tables or partitions, but
will otherwise ignore the flag. */
/* Now that we have the proper name for this tablespace,
look to see if it is already in the tablespace cache. */
if (fil_space_for_table_exists_in_mem(
space_id, table_name.m_name, flags)) {
if (fil_space_for_table_exists_in_mem(space_id, flags)) {
goto next;
}
char* filepath = fil_make_filepath(
NULL, table_name.m_name, IBD, false);
char* filepath = fil_make_filepath(nullptr, table_name,
IBD, false);
/* Check that the .ibd file exists. */
if (!fil_ibd_open(
......@@ -2278,9 +2275,8 @@ dict_save_data_dir_path(
ut_a(filepath);
/* Be sure this filepath is not the default filepath. */
char* default_filepath = fil_make_filepath(
NULL, table->name.m_name, IBD, false);
if (default_filepath) {
if (char* default_filepath = fil_make_filepath(nullptr, table->name,
IBD, false)) {
if (0 != strcmp(filepath, default_filepath)) {
ulint pathlen = strlen(filepath);
ut_a(pathlen < OS_FILE_MAX_PATH);
......@@ -2397,8 +2393,8 @@ dict_load_tablespace(
}
/* The tablespace may already be open. */
table->space = fil_space_for_table_exists_in_mem(
table->space_id, table->name.m_name, table->flags);
table->space = fil_space_for_table_exists_in_mem(table->space_id,
table->flags);
if (table->space) {
return;
}
......@@ -2425,8 +2421,7 @@ dict_load_tablespace(
if (table->data_dir_path) {
filepath = fil_make_filepath(
table->data_dir_path,
table->name.m_name, IBD, true);
table->data_dir_path, table->name, IBD, true);
}
}
......
......@@ -2362,7 +2362,7 @@ fil_space_crypt_close_tablespace(
ib::warn() << "Waited "
<< now - start
<< " seconds to drop space: "
<< space->name << " ("
<< space->chain.start->name << " ("
<< space->id << ") active threads "
<< crypt_data->rotate_state.active_threads
<< "flushing="
......
This diff is collapsed.
This diff is collapsed.
......@@ -1142,10 +1142,11 @@ fsp_alloc_free_page(
ut_a(!is_system_tablespace(space_id));
if (page_no >= FSP_EXTENT_SIZE) {
ib::error() << "Trying to extend a single-table"
" tablespace " << space->name << " , by single"
" page(s) though the space size " << space_size
<< ". Page no " << page_no << ".";
ib::error() << "Trying to extend "
<< space->chain.start->name
<< " by single page(s) though the size is "
<< space_size
<< ". Page no " << page_no << ".";
return(NULL);
}
......
/*****************************************************************************
Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -131,7 +131,7 @@ Tablespace::open_or_create(bool is_temp)
}
space = fil_space_t::create(
m_name, m_space_id, fsp_flags,
m_space_id, fsp_flags,
is_temp
? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE,
NULL);
......@@ -178,7 +178,7 @@ Tablespace::delete_files()
if (success && file_pre_exists) {
ib::info() << "Removed temporary tablespace data"
" file: \"" << it->m_name << "\"";
" file: \"" << it->m_filepath << "\"";
}
}
}
......@@ -191,18 +191,13 @@ must end with the extension .ibd and have a basename of at least 1 byte.
Set tablespace m_path member and add a Datafile with the filename.
@param[in] datafile_path full path of the tablespace file. */
dberr_t
Tablespace::add_datafile(
const char* datafile_added)
dberr_t Tablespace::add_datafile(const char *filepath)
{
/* The path provided ends in ".ibd". This was assured by
validate_create_tablespace_info() */
ut_d(const char* dot = strrchr(datafile_added, '.'));
ut_d(const char* dot = strrchr(filepath, '.'));
ut_ad(dot != NULL && 0 == strcmp(dot, DOT_IBD));
char* filepath = mem_strdup(datafile_added);
os_normalize_path(filepath);
/* If the path is an absolute path, separate it onto m_path and a
basename. For relative paths, make the whole thing a basename so that
it can be appended to the datadir. */
......@@ -219,12 +214,9 @@ Tablespace::add_datafile(
/* Now add a new Datafile and set the filepath
using the m_path created above. */
m_files.push_back(Datafile(m_name, m_flags,
FIL_IBD_FILE_INITIAL_SIZE, 0));
Datafile* datafile = &m_files.back();
datafile->make_filepath(m_path, basename, IBD);
ut_free(filepath);
m_files.push_back(Datafile(m_flags, FIL_IBD_FILE_INITIAL_SIZE, 0));
m_files.back().make_filepath(m_path, {basename, strlen(basename) - 4},
IBD);
return(DB_SUCCESS);
}
/*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2020, MariaDB Corporation.
Copyright (c) 2016, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -275,10 +275,10 @@ SysTablespace::parse_params(
}
}
m_files.push_back(Datafile(filepath, flags(), uint32_t(size),
order));
Datafile* datafile = &m_files.back();
datafile->make_filepath(path(), filepath, NO_EXT);
m_files.push_back(Datafile(flags(), uint32_t(size), order));
m_files.back().make_filepath(path(),
{filepath, strlen(filepath)},
NO_EXT);
if (::strlen(str) >= 6
&& *str == 'n'
......@@ -361,13 +361,12 @@ SysTablespace::check_size(
if (file.m_size > rounded_size_pages
|| (m_last_file_size_max > 0
&& m_last_file_size_max < rounded_size_pages)) {
ib::error() << "The Auto-extending " << name()
<< " data file '" << file.filepath() << "' is"
" of a different size " << rounded_size_pages
<< " pages than specified"
" in the .cnf file: initial " << file.m_size
<< " pages, max " << m_last_file_size_max
<< " (relevant if non-zero) pages!";
ib::error() << "The Auto-extending data file '"
<< file.filepath()
<< "' is of a different size "
<< rounded_size_pages
<< " pages than specified"
" by innodb_data_file_path";
return(DB_ERROR);
}
......@@ -375,11 +374,11 @@ SysTablespace::check_size(
}
if (rounded_size_pages != file.m_size) {
ib::error() << "The " << name() << " data file '"
ib::error() << "The data file '"
<< file.filepath() << "' is of a different size "
<< rounded_size_pages << " pages"
" than the " << file.m_size << " pages specified in"
" the .cnf file!";
" than the " << file.m_size << " pages specified by"
" innodb_data_file_path";
return(DB_ERROR);
}
......@@ -584,7 +583,7 @@ SysTablespace::read_lsn_and_check_flags(lsn_t* flushed_lsn)
if (space_id() != it->m_space_id) {
ib::error()
<< "The " << name() << " data file '" << it->name()
<< "The data file '" << it->filepath()
<< "' has the wrong space ID. It should be "
<< space_id() << ", but " << it->m_space_id
<< " was found";
......@@ -628,20 +627,16 @@ SysTablespace::check_file_status(
break;
case DB_SUCCESS:
/* Note: stat.rw_perm is only valid for "regular" files */
if (stat.type == OS_FILE_TYPE_FILE) {
if (!stat.rw_perm) {
const char *p = (!srv_read_only_mode
|| m_ignore_read_only)
? "writable"
: "readable";
ib::error() << "The " << name() << " data file"
<< " '" << file.name() << "' must be "
<< p;
ib::error() << "The data file"
<< " '" << file.filepath()
<< ((!srv_read_only_mode
|| m_ignore_read_only)
? "' must be writable"
: "' must be readable");
err = DB_ERROR;
reason = FILE_STATUS_READ_WRITE_ERROR;
......@@ -649,9 +644,8 @@ SysTablespace::check_file_status(
} else {
/* Not a regular file, bail out. */
ib::error() << "The " << name() << " data file '"
<< file.name() << "' is not a regular"
" InnoDB data file.";
ib::error() << "The data file '" << file.filepath()
<< "' is not a regular file.";
err = DB_ERROR;
reason = FILE_STATUS_NOT_REGULAR_FILE_ERROR;
......@@ -692,14 +686,14 @@ SysTablespace::file_not_found(
*create_new_db = TRUE;
if (space_id() == TRX_SYS_SPACE) {
ib::info() << "The first " << name() << " data file '"
<< file.name() << "' did not exist."
ib::info() << "The first data file '"
<< file.filepath() << "' did not exist."
" A new tablespace will be created!";
}
} else {
ib::info() << "Need to create a new " << name()
<< " data file '" << file.name() << "'.";
ib::info() << "Need to create a new data file '"
<< file.filepath() << "'.";
}
/* Set the file create mode. */
......@@ -758,8 +752,8 @@ SysTablespace::check_file_spec(
*create_new_db = FALSE;
if (m_files.size() >= 1000) {
ib::error() << "There must be < 1000 data files in "
<< name() << " but " << m_files.size() << " have been"
ib::error() << "There must be < 1000 data files "
" but " << m_files.size() << " have been"
" defined.";
return(DB_ERROR);
......@@ -798,22 +792,23 @@ SysTablespace::check_file_spec(
} else if (err != DB_SUCCESS) {
if (reason_if_failed == FILE_STATUS_READ_WRITE_ERROR) {
const char* p = (!srv_read_only_mode
|| m_ignore_read_only)
? "writable" : "readable";
ib::error() << "The " << name() << " data file"
<< " '" << it->name() << "' must be "
<< p;
ib::error() << "The data file '"
<< it->filepath()
<< ((!srv_read_only_mode
|| m_ignore_read_only)
? "' must be writable"
: "' must be readable");
}
ut_a(err != DB_FAIL);
break;
} else if (*create_new_db) {
ib::error() << "The " << name() << " data file '"
<< begin->m_name << "' was not found but"
" one of the other data files '" << it->m_name
<< "' exists.";
ib::error() << "The data file '"
<< begin->filepath()
<< "' was not found but"
" one of the other data files '"
<< it->filepath() << "' exists.";
err = DB_ERROR;
break;
......@@ -907,7 +902,7 @@ SysTablespace::open_or_create(
} else if (is_temp) {
ut_ad(space_id() == SRV_TMP_SPACE_ID);
space = fil_space_t::create(
name(), SRV_TMP_SPACE_ID, flags(),
SRV_TMP_SPACE_ID, flags(),
FIL_TYPE_TEMPORARY, NULL);
ut_ad(space == fil_system.temp_space);
if (!space) {
......@@ -918,7 +913,7 @@ SysTablespace::open_or_create(
} else {
ut_ad(space_id() == TRX_SYS_SPACE);
space = fil_space_t::create(
name(), TRX_SYS_SPACE, it->flags(),
TRX_SYS_SPACE, it->flags(),
FIL_TYPE_TABLESPACE, NULL);
ut_ad(space == fil_system.sys_space);
if (!space) {
......@@ -965,8 +960,7 @@ uint32_t SysTablespace::get_increment() const
if (!is_valid_size())
{
ib::error() << "The last data file in " << name()
<< " has a size of " << last_file_size()
ib::error() << "The last data file has a size of " << last_file_size()
<< " but the max size allowed is "
<< m_last_file_size_max;
}
......
......@@ -1583,7 +1583,7 @@ fts_drop_common_tables(
if (drop_orphan && err == DB_FAIL) {
char* path = fil_make_filepath(
NULL, table_name, IBD, false);
NULL, table_name_t{table_name}, IBD, false);
if (path != NULL) {
os_file_delete_if_exists(
innodb_data_file_key, path, NULL);
......@@ -5652,17 +5652,18 @@ bool fts_check_aux_table(const char *name,
ut_ad(len <= MAX_FULL_NAME_LEN);
ptr= static_cast<const char*>(memchr(name, '/', len));
IF_WIN(if (!ptr) ptr= static_cast<const char*>(memchr(name, '\\', len)), );
if (ptr != NULL)
{
/* We will start the match after the '/' */
++ptr;
len = end - ptr;
}
if (!ptr)
return false;
/* We will start the match after the '/' */
++ptr;
len= end - ptr;
/* All auxiliary tables are prefixed with "FTS_" and the name
length will be at the very least greater than 20 bytes. */
if (ptr && len > 20 && !memcmp(ptr, "FTS_", 4))
if (len > 24 && !memcmp(ptr, "FTS_", 4))
{
/* Skip the prefix. */
ptr+= 4;
......@@ -5706,6 +5707,11 @@ bool fts_check_aux_table(const char *name,
ut_a(end > ptr);
len= end - ptr;
if (len <= 4)
return false;
len-= 4; /* .ibd suffix */
if (len > 7)
return false;
......@@ -5740,8 +5746,9 @@ static void fil_get_fts_spaces(fts_space_set_t& fts_space_set)
index_id_t index_id= 0;
table_id_t table_id= 0;
if (space.purpose == FIL_TYPE_TABLESPACE
&& fts_check_aux_table(space.name, &table_id, &index_id))
if (space.purpose == FIL_TYPE_TABLESPACE && space.id &&
space.chain.start &&
fts_check_aux_table(space.chain.start->name, &table_id, &index_id))
fts_space_set.insert(std::make_pair(table_id, index_id));
}
......@@ -5823,17 +5830,14 @@ static void fts_drop_all_aux_tables(trx_t *trx, fts_table_t *fts_table)
fts_get_table_name(fts_table, fts_table_name, true);
/* Drop all fts aux and common table */
dberr_t err= fts_drop_table(trx, fts_table_name);
if (fts_drop_table(trx, fts_table_name) != DB_FAIL)
continue;
if (err == DB_FAIL)
if (char *path= fil_make_filepath(nullptr, table_name_t{fts_table_name},
IBD, false))
{
char *path= fil_make_filepath(NULL, fts_table_name, IBD, false);
if (path != NULL)
{
os_file_delete_if_exists(innodb_data_file_key, path , NULL);
ut_free(path);
}
os_file_delete_if_exists(innodb_data_file_key, path, nullptr);
ut_free(path);
}
}
}
......
......@@ -758,7 +758,6 @@ innodb_tmpdir_validate(
return(1);
}
os_normalize_path(alter_tmp_dir);
my_realpath(tmp_abs_path, alter_tmp_dir, 0);
size_t tmp_abs_len = strlen(tmp_abs_path);
......@@ -3292,8 +3291,6 @@ static int innodb_init_params()
{
DBUG_ENTER("innodb_init_params");
static char current_dir[3];
char *default_path;
ulong num_pll_degree;
/* Check that values don't overflow on 32-bit systems. */
......@@ -3385,19 +3382,11 @@ static int innodb_init_params()
Note that when using the embedded server, the datadirectory is not
necessarily the current directory of this program. */
if (mysqld_embedded) {
default_path = mysql_real_data_home;
} else {
/* It's better to use current lib, to keep paths short */
current_dir[0] = FN_CURLIB;
current_dir[1] = FN_LIBCHAR;
current_dir[2] = 0;
default_path = current_dir;
}
ut_a(default_path);
fil_path_to_mysql_datadir = default_path;
fil_path_to_mysql_datadir =
#ifndef HAVE_REPLICATION
mysqld_embedded ? mysql_real_data_home :
#endif
"./";
/* Set InnoDB initialization parameters according to the values
read from MySQL .cnf file */
......@@ -3405,7 +3394,8 @@ static int innodb_init_params()
/* The default dir for data files is the datadir of MySQL */
srv_data_home = innobase_data_home_dir
? innobase_data_home_dir : default_path;
? innobase_data_home_dir
: const_cast<char*>(fil_path_to_mysql_datadir);
#ifdef WITH_WSREP
/* If we use the wsrep API, then we need to tell the server
the path to the data files (for passing it to the SST scripts): */
......@@ -3437,7 +3427,6 @@ static int innodb_init_params()
srv_sys_space.set_flags(FSP_FLAGS_PAGE_SSIZE());
}
srv_sys_space.set_name("innodb_system");
srv_sys_space.set_path(srv_data_home);
/* Supports raw devices */
......@@ -3447,7 +3436,6 @@ static int innodb_init_params()
DBUG_RETURN(HA_ERR_INITIALIZATION);
}
srv_tmp_space.set_name("innodb_temporary");
srv_tmp_space.set_path(srv_data_home);
/* Temporary tablespace is in full crc32 format. */
......@@ -3462,8 +3450,8 @@ static int innodb_init_params()
/* Perform all sanity check before we take action of deleting files*/
if (srv_sys_space.intersection(&srv_tmp_space)) {
sql_print_error("%s and %s file names seem to be the same.",
srv_tmp_space.name(), srv_sys_space.name());
sql_print_error("innodb_temporary and innodb_system"
" file names seem to be the same.");
DBUG_RETURN(HA_ERR_INITIALIZATION);
}
......@@ -3472,11 +3460,9 @@ static int innodb_init_params()
/* ------------ UNDO tablespaces files ---------------------*/
if (!srv_undo_dir) {
srv_undo_dir = default_path;
srv_undo_dir = const_cast<char*>(fil_path_to_mysql_datadir);
}
os_normalize_path(srv_undo_dir);
if (strchr(srv_undo_dir, ';')) {
sql_print_error("syntax error in innodb_undo_directory");
DBUG_RETURN(HA_ERR_INITIALIZATION);
......@@ -3487,11 +3473,10 @@ static int innodb_init_params()
/* The default dir for log files is the datadir of MySQL */
if (!srv_log_group_home_dir) {
srv_log_group_home_dir = default_path;
srv_log_group_home_dir
= const_cast<char*>(fil_path_to_mysql_datadir);
}
os_normalize_path(srv_log_group_home_dir);
if (strchr(srv_log_group_home_dir, ';')) {
sql_print_error("syntax error in innodb_log_group_home_dir");
DBUG_RETURN(HA_ERR_INITIALIZATION);
......
......@@ -6495,7 +6495,19 @@ static int i_s_sys_tablespaces_fill(THD *thd, const fil_space_t &s, TABLE *t)
Field **fields= t->field;
OK(fields[SYS_TABLESPACES_SPACE]->store(s.id, true));
OK(field_store_string(fields[SYS_TABLESPACES_NAME], s.name));
{
Field *f= fields[SYS_TABLESPACES_NAME];
const auto name= s.name();
if (name.data())
{
OK(f->store(name.data(), name.size(), system_charset_info));
f->set_notnull();
}
else
f->set_notnull();
}
fields[SYS_TABLESPACES_NAME]->set_null();
OK(fields[SYS_TABLESPACES_FLAGS]->store(s.flags, true));
OK(field_store_string(fields[SYS_TABLESPACES_ROW_FORMAT], row_format));
const char *filepath= s.chain.start->name;
......@@ -6711,8 +6723,17 @@ i_s_dict_fill_tablespaces_encryption(
OK(fields[TABLESPACES_ENCRYPTION_SPACE]->store(space->id, true));
OK(field_store_string(fields[TABLESPACES_ENCRYPTION_NAME],
space->name));
{
const auto name = space->name();
if (name.data()) {
OK(fields[TABLESPACES_ENCRYPTION_NAME]->store(
name.data(), name.size(),
system_charset_info));
fields[TABLESPACES_ENCRYPTION_NAME]->set_notnull();
} else {
fields[TABLESPACES_ENCRYPTION_NAME]->set_null();
}
}
OK(fields[TABLESPACES_ENCRYPTION_ENCRYPTION_SCHEME]->store(
status.scheme, true));
......
......@@ -39,6 +39,7 @@ Created 10/25/1995 Heikki Tuuri
#include "log0recv.h"
#include "dict0types.h"
#include "ilist.h"
#include "span.h"
#include <set>
#include <mutex>
......@@ -353,7 +354,6 @@ struct fil_space_t final
}
ulint id; /*!< space id */
hash_node_t hash; /*!< hash chain node */
char* name; /*!< Tablespace name */
lsn_t max_lsn;
/*!< LSN of the most recent
fil_names_write_if_was_clean().
......@@ -490,15 +490,14 @@ struct fil_space_t final
n_reserved_extents -= n_reserved;
}
/** Rename a file.
@param[in] name table name after renaming
@param[in] path tablespace file name after renaming
@param[in] log whether to write redo log
@param[in] replace whether to ignore the existence of path
@return error code
@retval DB_SUCCESS on success */
dberr_t rename(const char* name, const char* path, bool log,
bool replace = false);
/** Rename a file.
@param[in] path tablespace file name after renaming
@param[in] log whether to write redo log
@param[in] replace whether to ignore the existence of path
@return error code
@retval DB_SUCCESS on success */
dberr_t rename(const char *path, bool log, bool replace= false)
MY_ATTRIBUTE((nonnull));
/** Note that the tablespace has been imported.
Initially, purpose=FIL_TYPE_IMPORT so that no redo log is
......@@ -908,7 +907,6 @@ struct fil_space_t final
#ifndef UNIV_INNOCHECKSUM
MY_ATTRIBUTE((warn_unused_result))
/** Create a tablespace in fil_system.
@param name tablespace name
@param id tablespace identifier
@param flags tablespace flags
@param purpose tablespace purpose
......@@ -916,7 +914,7 @@ struct fil_space_t final
@param mode encryption mode
@return pointer to created tablespace, to be filled in with add()
@retval nullptr on failure (such as when the same tablespace exists) */
static fil_space_t *create(const char *name, ulint id, ulint flags,
static fil_space_t *create(ulint id, ulint flags,
fil_type_t purpose, fil_space_crypt_t *crypt_data,
fil_encryption_t mode= FIL_ENCRYPTION_DEFAULT);
......@@ -1036,6 +1034,11 @@ struct fil_space_t final
latch.rd_unlock();
}
typedef span<const char> name_type;
/** @return the tablespace name (databasename/tablename) */
name_type name() const;
private:
/** @return whether the file is usable for io() */
ATTRIBUTE_COLD bool prepare(bool have_mutex= false);
......@@ -1592,15 +1595,15 @@ void fil_close_tablespace(ulint id);
Allocates and builds a file name from a path, a table or tablespace name
and a suffix. The string must be freed by caller with ut_free().
@param[in] path NULL or the directory path or the full path and filename.
@param[in] name NULL if path is full, or Table/Tablespace name
@param[in] suffix NULL or the file extention to use.
@param[in] name {} if path is full, or Table/Tablespace name
@param[in] ext the file extension to use
@param[in] trim_name true if the last name on the path should be trimmed.
@return own: file name */
char*
fil_make_filepath(
const char* path,
const char* name,
ib_extention suffix,
bool strip_name);
char* fil_make_filepath(const char *path, const fil_space_t::name_type &name,
ib_extention ext, bool trim_name);
char *fil_make_filepath(const char* path, const table_name_t name,
ib_extention ext, bool trim_name);
/** Create a tablespace file.
@param[in] space_id Tablespace ID
......@@ -1617,14 +1620,14 @@ must be >= FIL_IBD_FILE_INITIAL_SIZE
fil_space_t*
fil_ibd_create(
ulint space_id,
const char* name,
const table_name_t name,
const char* path,
ulint flags,
uint32_t size,
fil_encryption_t mode,
uint32_t key_id,
dberr_t* err)
MY_ATTRIBUTE((nonnull(2,8), warn_unused_result));
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations.
(Typically when upgrading from MariaDB 10.1.0..10.1.20.)
......@@ -1668,7 +1671,7 @@ fil_ibd_open(
fil_type_t purpose,
ulint id,
ulint flags,
const table_name_t& tablename,
const table_name_t tablename,
const char* path_in,
dberr_t* err = NULL)
MY_ATTRIBUTE((warn_unused_result));
......@@ -1716,15 +1719,10 @@ fil_file_readdir_next_file(
memory cache. Note that if we have not done a crash recovery at the database
startup, there may be many tablespaces which are not yet in the memory cache.
@param[in] id Tablespace ID
@param[in] name Tablespace name used in fil_space_t::create().
@param[in] table_flags table flags
@return the tablespace
@retval NULL if no matching tablespace exists in the memory cache */
fil_space_t*
fil_space_for_table_exists_in_mem(
ulint id,
const char* name,
ulint table_flags);
fil_space_t *fil_space_for_table_exists_in_mem(ulint id, ulint table_flags);
/** Try to extend a tablespace if it is smaller than the specified size.
@param[in,out] space tablespace
......@@ -1755,26 +1753,6 @@ fil_delete_file(
/*============*/
const char* path); /*!< in: filepath of the ibd tablespace */
/********************************************************************//**
Looks for a pre-existing fil_space_t with the given tablespace ID
and, if found, returns the name and filepath in newly allocated buffers that the caller must free.
@param[in] space_id The tablespace ID to search for.
@param[out] name Name of the tablespace found.
@param[out] fileapth The filepath of the first datafile for thtablespace found.
@return true if tablespace is found, false if not. */
bool
fil_space_read_name_and_filepath(
ulint space_id,
char** name,
char** filepath);
/** Convert a file name to a tablespace name.
@param[in] filename directory/databasename/tablename.ibd
@return database/tablename string, to be freed with ut_free() */
char*
fil_path_to_space_name(
const char* filename);
/*******************************************************************//**
Returns the table space by a given id, NULL if not found. */
fil_space_t*
......
......@@ -129,7 +129,8 @@ fil_page_type_validate(
/* Dump out the page info */
ib::fatal() << "Page " << space_id << ":" << offset
<< " name " << (space ? space->name : "???")
<< " name " << (space && space->chain.start
? space->chain.start->name : "???")
<< " page_type " << page_type
<< " key_version " << key_version
<< " lsn " << mach_read_from_8(page + FIL_PAGE_LSN)
......
/*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, 2020, MariaDB Corporation.
Copyright (c) 2018, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -49,7 +49,6 @@ class Datafile {
Datafile()
:
m_name(),
m_filepath(),
m_filename(),
m_handle(),
......@@ -68,9 +67,8 @@ class Datafile {
/* No op */
}
Datafile(const char* name, ulint flags, uint32_t size, ulint order)
Datafile(ulint flags, uint32_t size, ulint order)
:
m_name(mem_strdup(name)),
m_filepath(),
m_filename(),
m_handle(),
......@@ -86,8 +84,6 @@ class Datafile {
m_last_os_error(),
m_file_info()
{
ut_ad(m_name != NULL);
/* No op */
}
Datafile(const Datafile& file)
......@@ -105,9 +101,6 @@ class Datafile {
m_last_os_error(),
m_file_info()
{
m_name = mem_strdup(file.m_name);
ut_ad(m_name != NULL);
if (file.m_filepath != NULL) {
m_filepath = mem_strdup(file.m_filepath);
ut_a(m_filepath != NULL);
......@@ -127,10 +120,6 @@ class Datafile {
{
ut_a(this != &file);
ut_ad(m_name == NULL);
m_name = mem_strdup(file.m_name);
ut_a(m_name != NULL);
m_size = file.m_size;
m_order = file.m_order;
m_type = file.m_type;
......@@ -164,10 +153,8 @@ class Datafile {
return(*this);
}
/** Initialize the name and flags of this datafile.
@param[in] name tablespace name, will be copied
@param[in] flags tablespace flags */
void init(const char* name, ulint flags);
/** Initialize the tablespace flags */
void init(ulint flags) { m_flags= flags; }
/** Release the resources. */
virtual void shutdown();
......@@ -176,14 +163,12 @@ class Datafile {
so that it can be validated.
@param[in] strict whether to issue error messages
@return DB_SUCCESS or error code */
virtual dberr_t open_read_only(bool strict);
dberr_t open_read_only(bool strict);
/** Open a data file in read-write mode during start-up so that
doublewrite pages can be restored and then it can be validated.
@param[in] read_only_mode if true, then readonly mode checks
are enforced.
@return DB_SUCCESS or error code */
virtual dberr_t open_read_write(bool read_only_mode)
inline dberr_t open_read_write()
MY_ATTRIBUTE((warn_unused_result));
/** Initialize OS specific file info. */
......@@ -197,24 +182,15 @@ class Datafile {
Prepend the dirpath to filename using the extension given.
If dirpath is NULL, prepend the default datadir to filepath.
Store the result in m_filepath.
@param[in] dirpath directory path
@param[in] filename filename or filepath
@param[in] ext filename extension */
void make_filepath(
const char* dirpath,
const char* filename,
ib_extention ext);
@param dirpath directory path
@param name tablespace (table) name
@param ext filename extension */
void make_filepath(const char* dirpath, fil_space_t::name_type name,
ib_extention ext);
/** Set the filepath by duplicating the filepath sent in */
void set_filepath(const char* filepath);
/** Allocate and set the datafile or tablespace name in m_name.
If a name is provided, use it; else extract a file-per-table
tablespace name from m_filepath. The value of m_name
will be freed in the destructor.
@param[in] name Tablespace Name if known, NULL if not */
void set_name(const char* name);
/** Validates the datafile and checks that it conforms with
the expected space ID and flags. The file should exist and be
successfully opened in order for this function to validate it.
......@@ -247,13 +223,6 @@ class Datafile {
dberr_t validate_first_page(lsn_t* flush_lsn)
MY_ATTRIBUTE((warn_unused_result));
/** Get Datafile::m_name.
@return m_name */
const char* name() const
{
return(m_name);
}
/** Get Datafile::m_filepath.
@return m_filepath */
const char* filepath() const
......@@ -363,13 +332,22 @@ class Datafile {
in the filepath. */
void set_filename()
{
if (m_filepath == NULL) {
if (!m_filepath) {
return;
}
char* last_slash = strrchr(m_filepath, OS_PATH_SEPARATOR);
m_filename = last_slash ? last_slash + 1 : m_filepath;
if (char *last_slash = strrchr(m_filepath, '/')) {
#if _WIN32
if (char *last = strrchr(m_filepath, '\\')) {
if (last > last_slash) {
last_slash = last;
}
}
#endif
m_filename = last_slash + 1;
} else {
m_filename = m_filepath;
}
}
/** Create/open a data file.
......@@ -406,12 +384,6 @@ class Datafile {
/* DATA MEMBERS */
/** Datafile name at the tablespace location.
This is either the basename of the file if an absolute path
was entered, or it is the relative path to the datadir or
Tablespace::m_path. */
char* m_name;
protected:
/** Physical file path with base name and extension */
char* m_filepath;
......@@ -520,57 +492,28 @@ class RemoteDatafile : public Datafile
return(m_link_filepath);
}
/** Create a link filename based on the contents of m_name,
open that file, and read the contents into m_filepath.
@retval DB_SUCCESS if remote linked tablespace file is opened and read.
@retval DB_CANNOT_OPEN_FILE if the link file does not exist. */
dberr_t open_link_file();
/** Attempt to read the contents of an .isl file into m_filepath.
@param name table name
@return filepath()
@retval nullptr if the .isl file does not exist or cannot be read */
const char* open_link_file(const table_name_t& name);
/** Delete an InnoDB Symbolic Link (ISL) file. */
void delete_link_file(void);
/** Open a handle to the file linked to in an InnoDB Symbolic Link file
in read-only mode so that it can be validated.
@param[in] strict whether to issue error messages
@return DB_SUCCESS or error code */
dberr_t open_read_only(bool strict) override;
/** Opens a handle to the file linked to in an InnoDB Symbolic Link
file in read-write mode so that it can be restored from doublewrite
and validated.
@param[in] read_only_mode If true, then readonly mode checks
are enforced.
@return DB_SUCCESS or error code */
dberr_t open_read_write(bool read_only_mode) override
MY_ATTRIBUTE((warn_unused_result));
/******************************************************************
Global Static Functions; Cannot refer to data members.
******************************************************************/
/** Creates a new InnoDB Symbolic Link (ISL) file. It is always
created under the 'datadir' of MySQL. The datadir is the directory
of a running mysqld program. We can refer to it by simply using
the path ".".
@param[in] name tablespace name
@param[in] filepath remote filepath of tablespace datafile
/** Create InnoDB Symbolic Link (ISL) file.
@param name tablespace name
@param filepath full file name
@return DB_SUCCESS or error code */
static dberr_t create_link_file(
const char* name,
const char* filepath);
static dberr_t create_link_file(fil_space_t::name_type name,
const char *filepath);
/** Delete an InnoDB Symbolic Link (ISL) file by name.
@param[in] name tablespace name */
static void delete_link_file(const char* name);
/** Read an InnoDB Symbolic Link (ISL) file by name.
It is always created under the datadir of MySQL.
For file-per-table tablespaces, the isl file is expected to be
in a 'database' directory and called 'tablename.isl'.
The caller must free the memory returned if it is not null.
@param[in] link_filepath filepath of the ISL file
@return Filepath of the IBD file read from the ISL file */
static char* read_link_file(
const char* link_filepath);
@param name tablespace name */
static void delete_link_file(fil_space_t::name_type name);
};
#endif /* fsp0file_h */
/*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation.
Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -50,7 +50,6 @@ class Tablespace {
Tablespace()
:
m_files(),
m_name(),
m_space_id(ULINT_UNDEFINED),
m_path(),
m_flags(),
......@@ -79,9 +78,6 @@ class Tablespace {
/** Data file iterator */
iterator end() { return m_files.end(); }
void set_name(const char* name) { m_name = name; }
const char* name() const { return m_name; }
/** Set tablespace path and filename members.
@param[in] path where tablespace file(s) resides
@param[in] len length of the file path */
......@@ -90,8 +86,6 @@ class Tablespace {
ut_ad(m_path == NULL);
m_path = mem_strdupl(path, len);
ut_ad(m_path != NULL);
os_normalize_path(m_path);
}
/** Set tablespace path and filename members.
......@@ -218,9 +212,6 @@ class Tablespace {
/* DATA MEMBERS */
/** Name of the tablespace. */
const char* m_name;
/** Tablespace ID */
ulint m_space_id;
......
......@@ -1240,31 +1240,34 @@ os_file_punch_hole(
os_offset_t len)
MY_ATTRIBUTE((warn_unused_result));
/** Normalizes a directory path for the current OS:
On Windows, we convert '/' to '\', else we convert '\' to '/'.
@param[in,out] str A null-terminated directory and file path */
void os_normalize_path(char* str);
/* Determine if a path is an absolute path or not.
@param[in] OS directory or file path to evaluate
@retval true if an absolute path
@retval false if a relative path */
UNIV_INLINE
bool
is_absolute_path(
const char* path)
inline bool is_absolute_path(const char *path)
{
if (path[0] == OS_PATH_SEPARATOR) {
return(true);
}
switch (path[0]) {
#ifdef _WIN32
case '\0':
return false;
case '\\':
#endif
case '/':
return true;
}
#ifdef _WIN32
if (path[1] == ':' && path[2] == OS_PATH_SEPARATOR) {
return(true);
}
if (path[1] == ':')
{
switch (path[2]) {
case '/':
case '\\':
return true;
}
}
#endif /* _WIN32 */
return(false);
return false;
}
#include "os0file.ic"
......
......@@ -531,22 +531,6 @@ it is read or written. */
/* Compile-time constant of the given array's size. */
#define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/* The return type from a thread's start function differs between Unix and
Windows, so define a typedef for it and a macro to use at the end of such
functions. */
#ifdef _WIN32
typedef DWORD os_thread_ret_t;
# define OS_THREAD_DUMMY_RETURN return(0)
# define OS_PATH_SEPARATOR '\\'
# define OS_PATH_SEPARATOR_ALT '/'
#else
typedef void* os_thread_ret_t;
# define OS_THREAD_DUMMY_RETURN return(NULL)
# define OS_PATH_SEPARATOR '/'
# define OS_PATH_SEPARATOR_ALT '\\'
#endif
#include <stdio.h>
#include "db0err.h"
#include "ut0dbg.h"
......
......@@ -135,7 +135,7 @@ with (), thus:
#include "mysql/psi/psi_memory.h" /* PSI_memory_key, PSI_memory_info */
#include "ut0ut.h" /* ut_strcmp_functor, ut_basename_noext() */
#include "ut0ut.h" /* ut_strcmp_functor */
#define OUT_OF_MEMORY_MSG \
"Check if you should increase the swap file or ulimits of your" \
......
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2019, 2020, MariaDB Corporation.
Copyright (c) 2019, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -276,25 +276,6 @@ ut_strerr(
#endif /* !UNIV_INNOCHECKSUM */
#ifdef UNIV_PFS_MEMORY
/** Extract the basename of a file without its extension.
For example, extract "foo0bar" out of "/path/to/foo0bar.cc".
@param[in] file file path, e.g. "/path/to/foo0bar.cc"
@param[out] base result, e.g. "foo0bar"
@param[in] base_size size of the output buffer 'base', if there
is not enough space, then the result will be truncated, but always
'\0'-terminated
@return number of characters that would have been printed if the size
were unlimited (not including the final ‘\0’) */
size_t
ut_basename_noext(
const char* file,
char* base,
size_t base_size);
#endif /* UNIV_PFS_MEMORY */
namespace ib {
/** This is a wrapper class, used to print any unsigned integer type
......
......@@ -4581,7 +4581,7 @@ static void lock_rec_block_validate(const page_id_t page_id)
if (err != DB_SUCCESS) {
ib::error() << "Lock rec block validate failed for tablespace "
<< space->name
<< space->chain.start->name
<< page_id << " err " << err;
}
......
......@@ -1306,11 +1306,15 @@ std::string get_log_file_path(const char *filename)
path.reserve(size);
path.assign(srv_log_group_home_dir);
std::replace(path.begin(), path.end(), OS_PATH_SEPARATOR_ALT,
OS_PATH_SEPARATOR);
if (path.back() != OS_PATH_SEPARATOR)
path.push_back(OS_PATH_SEPARATOR);
switch (path.back()) {
#ifdef _WIN32
case '\\':
#endif
case '/':
break;
default:
path.push_back('/');
}
path.append(filename);
return path;
......
......@@ -807,7 +807,6 @@ fil_name_process(char* name, ulint len, ulint space_id, bool deleted)
further checks can ensure that a FILE_MODIFY record was
scanned before applying any page records for the space_id. */
os_normalize_path(name);
const file_name_t fname(std::string(name, len), deleted);
std::pair<recv_spaces_t::iterator,bool> p = recv_spaces.emplace(
space_id, fname);
......@@ -2853,22 +2852,8 @@ void recv_sys_t::apply(bool last_batch)
}
else
{
size_t base= r.second.rfind(OS_PATH_SEPARATOR);
ut_ad(base != std::string::npos);
size_t start= r.second.rfind(OS_PATH_SEPARATOR, base - 1);
if (start == std::string::npos)
start= 0;
else
++start;
/* Keep only databasename/tablename without .ibd suffix */
std::string space_name(r.second, start, r.second.size() - start - 4);
ut_ad(space_name[base - start] == OS_PATH_SEPARATOR);
#if OS_PATH_SEPARATOR != '/'
space_name[base - start]= '/';
#endif
mysql_mutex_lock(&log_sys.mutex);
if (dberr_t err= space->rename(space_name.c_str(), r.second.c_str(),
false))
if (dberr_t err= space->rename(r.second.c_str(), false))
{
ib::error() << "Cannot replay rename of tablespace " << id
<< " to '" << r.second << "': " << err;
......
......@@ -425,36 +425,32 @@ responsibility to free the return value after it is no longer needed.
@param[in] old_path Pathname
@param[in] tablename Contains new base name
@return own: new full pathname */
char*
os_file_make_new_pathname(
const char* old_path,
const char* tablename)
char *os_file_make_new_pathname(const char *old_path, const char *tablename)
{
ulint dir_len;
char* last_slash;
char* base_name;
char* new_path;
ulint new_path_len;
/* Split the tablename into its database and table name components.
They are separated by a '/'. */
last_slash = strrchr((char*) tablename, '/');
base_name = last_slash ? last_slash + 1 : (char*) tablename;
/* Find the offset of the last slash. We will strip off the
old basename.ibd which starts after that slash. */
last_slash = strrchr((char*) old_path, OS_PATH_SEPARATOR);
dir_len = last_slash ? ulint(last_slash - old_path) : strlen(old_path);
/* allocate a new path and move the old directory path to it. */
new_path_len = dir_len + strlen(base_name) + sizeof "/.ibd";
new_path = static_cast<char*>(ut_malloc_nokey(new_path_len));
memcpy(new_path, old_path, dir_len);
snprintf(new_path + dir_len, new_path_len - dir_len,
"%c%s.ibd", OS_PATH_SEPARATOR, base_name);
return(new_path);
/* Split the tablename into its database and table name components.
They are separated by a '/'. */
const char *last_slash= strrchr(tablename, '/');
const char *base_name= last_slash ? last_slash + 1 : tablename;
/* Find the offset of the last slash. We will strip off the
old basename.ibd which starts after that slash. */
last_slash = strrchr(old_path, '/');
#ifdef _WIN32
if (const char *last= strrchr(old_path, '\\'))
if (last > last_slash)
last_slash= last;
#endif
size_t dir_len= last_slash
? size_t(last_slash - old_path)
: strlen(old_path);
/* allocate a new path and move the old directory path to it. */
size_t new_path_len= dir_len + strlen(base_name) + sizeof "/.ibd";
char *new_path= static_cast<char*>(ut_malloc_nokey(new_path_len));
memcpy(new_path, old_path, dir_len);
snprintf(new_path + dir_len, new_path_len - dir_len, "/%s.ibd", base_name);
return new_path;
}
/** This function reduces a null-terminated full remote path name into
......@@ -474,7 +470,7 @@ os_file_make_data_dir_path(
char* data_dir_path)
{
/* Replace the period before the extension with a null byte. */
char* ptr = strrchr((char*) data_dir_path, '.');
char* ptr = strrchr(data_dir_path, '.');
if (ptr == NULL) {
return;
......@@ -483,7 +479,8 @@ os_file_make_data_dir_path(
ptr[0] = '\0';
/* The tablename starts after the last slash. */
ptr = strrchr((char*) data_dir_path, OS_PATH_SEPARATOR);
ptr = strrchr(data_dir_path, '/');
if (ptr == NULL) {
return;
......@@ -494,7 +491,14 @@ os_file_make_data_dir_path(
char* tablename = ptr + 1;
/* The databasename starts after the next to last slash. */
ptr = strrchr((char*) data_dir_path, OS_PATH_SEPARATOR);
ptr = strrchr(data_dir_path, '/');
#ifdef _WIN32
if (char *aptr = strrchr(data_dir_path, '\\')) {
if (aptr > ptr) {
ptr = aptr;
}
}
#endif
if (ptr == NULL) {
return;
......@@ -541,10 +545,16 @@ char*
os_file_get_parent_dir(
const char* path)
{
bool has_trailing_slash = false;
/* Find the offset of the last slash */
const char* last_slash = strrchr(path, OS_PATH_SEPARATOR);
const char* last_slash = strrchr(path, '/');
#ifdef _WIN32
if (const char *last = strrchr(path, '\\')) {
if (last > last_slash) {
last_slash = last;
}
}
#endif
if (!last_slash) {
/* No slash in the path, return NULL */
......@@ -552,13 +562,11 @@ os_file_get_parent_dir(
}
/* Ok, there is a slash. Is there anything after it? */
if (static_cast<size_t>(last_slash - path + 1) == strlen(path)) {
has_trailing_slash = true;
}
const bool has_trailing_slash = last_slash[1] == '\0';
/* Reduce repetative slashes. */
/* Reduce repetitive slashes. */
while (last_slash > path
&& last_slash[-1] == OS_PATH_SEPARATOR) {
&& (IF_WIN(last_slash[-1] == '\\' ||,) last_slash[-1] == '/')) {
last_slash--;
}
......@@ -573,13 +581,15 @@ os_file_get_parent_dir(
/* Back up to the previous slash. */
last_slash--;
while (last_slash > path
&& last_slash[0] != OS_PATH_SEPARATOR) {
&& (IF_WIN(last_slash[0] != '\\' &&,)
last_slash[0] != '/')) {
last_slash--;
}
/* Reduce repetative slashes. */
/* Reduce repetitive slashes. */
while (last_slash > path
&& last_slash[-1] == OS_PATH_SEPARATOR) {
&& (IF_WIN(last_slash[-1] == '\\' ||,)
last_slash[-1] == '/')) {
last_slash--;
}
}
......@@ -611,11 +621,6 @@ test_os_file_get_parent_dir(
char* expected = expected_dir == NULL ? NULL
: mem_strdup(expected_dir);
/* os_file_get_parent_dir() assumes that separators are
converted to OS_PATH_SEPARATOR. */
os_normalize_path(child);
os_normalize_path(expected);
char* parent = os_file_get_parent_dir(child);
bool unexpected = (expected == NULL
......@@ -4583,23 +4588,4 @@ bool fil_node_t::read_page0()
space->free_len = free_len;
return true;
}
#else
#include "univ.i"
#endif /* !UNIV_INNOCHECKSUM */
/** Normalizes a directory path for the current OS:
On Windows, we convert '/' to '\', else we convert '\' to '/'.
@param[in,out] str A null-terminated directory and file path */
void
os_normalize_path(
char* str)
{
if (str != NULL) {
for (; *str; str++) {
if (*str == OS_PATH_SEPARATOR_ALT) {
*str = OS_PATH_SEPARATOR;
}
}
}
}
......@@ -3761,16 +3761,15 @@ fil_tablespace_iterate(
/* Make sure the data_dir_path is set. */
dict_get_and_save_data_dir_path(table, false);
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
ut_a(table->data_dir_path);
ut_ad(!DICT_TF_HAS_DATA_DIR(table->flags) || table->data_dir_path);
filepath = fil_make_filepath(
table->data_dir_path, table->name.m_name, IBD, true);
} else {
filepath = fil_make_filepath(
NULL, table->name.m_name, IBD, false);
}
const char *data_dir_path = DICT_TF_HAS_DATA_DIR(table->flags)
? table->data_dir_path : nullptr;
filepath = fil_make_filepath(data_dir_path,
{table->name.m_name,
strlen(table->name.m_name)},
IBD, data_dir_path != nullptr);
if (!filepath) {
return(DB_OUT_OF_MEMORY);
} else {
......@@ -4095,16 +4094,10 @@ row_import_for_mysql(
dict_get_and_save_data_dir_path(table, true);
ut_ad(!DICT_TF_HAS_DATA_DIR(table->flags) || table->data_dir_path);
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
ut_a(table->data_dir_path);
filepath = fil_make_filepath(
table->data_dir_path, table->name.m_name, IBD, true);
} else {
filepath = fil_make_filepath(
NULL, table->name.m_name, IBD, false);
}
const char *data_dir_path = DICT_TF_HAS_DATA_DIR(table->flags)
? table->data_dir_path : nullptr;
filepath = fil_make_filepath(data_dir_path, table->name, IBD,
data_dir_path != nullptr);
DBUG_EXECUTE_IF(
"ib_import_OOM_15",
......
......@@ -3359,7 +3359,9 @@ row_drop_table_for_mysql(
if (table->space != fil_system.sys_space) {
/* Delete the link file if used. */
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
RemoteDatafile::delete_link_file(name);
RemoteDatafile::delete_link_file(
{table->name.m_name,
strlen(table->name.m_name)});
}
}
......@@ -3648,15 +3650,14 @@ row_drop_table_for_mysql(
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
dict_get_and_save_data_dir_path(table, true);
ut_ad(table->data_dir_path || !space);
filepath = space ? NULL : fil_make_filepath(
table->data_dir_path,
table->name.m_name, IBD,
table->data_dir_path != NULL);
} else {
filepath = space ? NULL : fil_make_filepath(
NULL, table->name.m_name, IBD, false);
}
filepath = space
? nullptr
: fil_make_filepath(table->data_dir_path, table->name,
IBD,
table->data_dir_path != nullptr);
/* Free the dict_table_t object. */
err = row_drop_table_from_cache(tablename, table, trx);
if (err != DB_SUCCESS) {
......
......@@ -479,15 +479,12 @@ static ulint trx_rseg_get_n_undo_tablespaces()
static ulint srv_undo_tablespace_open(bool create, const char* name, ulint i)
{
bool success;
char undo_name[sizeof "innodb_undo000"];
ulint space_id= 0;
ulint fsp_flags= 0;
if (create)
{
space_id= srv_undo_space_id_start + i;
snprintf(undo_name, sizeof(undo_name),
"innodb_undo%03u", static_cast<unsigned>(space_id));
switch (srv_checksum_algorithm) {
case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
......@@ -542,7 +539,6 @@ static ulint srv_undo_tablespace_open(bool create, const char* name, ulint i)
}
space_id= id;
snprintf(undo_name, sizeof undo_name, "innodb_undo%03u", id);
aligned_free(page);
}
......@@ -554,7 +550,7 @@ static ulint srv_undo_tablespace_open(bool create, const char* name, ulint i)
fil_set_max_space_id_if_bigger(space_id);
fil_space_t *space= fil_space_t::create(undo_name, space_id, fsp_flags,
fil_space_t *space= fil_space_t::create(space_id, fsp_flags,
FIL_TYPE_TABLESPACE, NULL);
ut_a(fil_validate());
ut_a(space);
......@@ -594,11 +590,7 @@ srv_check_undo_redo_logs_exists()
/* Check if any undo tablespaces exist */
for (ulint i = 1; i <= srv_undo_tablespaces; ++i) {
snprintf(
name, sizeof(name),
"%s%cundo%03zu",
srv_undo_dir, OS_PATH_SEPARATOR,
i);
snprintf(name, sizeof name, "%s/undo%03zu", srv_undo_dir, i);
fh = os_file_create(
innodb_data_file_key, name,
......@@ -656,8 +648,7 @@ static dberr_t srv_all_undo_tablespaces_open(bool create_new_db, ulint n_undo)
for (ulint i= 0; i < n_undo; ++i)
{
char name[OS_FILE_MAX_PATH];
snprintf(name, sizeof name, "%s%cundo%03zu", srv_undo_dir,
OS_PATH_SEPARATOR, i + 1);
snprintf(name, sizeof name, "%s/undo%03zu", srv_undo_dir, i + 1);
ulint space_id= srv_undo_tablespace_open(create_new_db, name, i);
if (!space_id)
{
......@@ -687,8 +678,7 @@ static dberr_t srv_all_undo_tablespaces_open(bool create_new_db, ulint n_undo)
++i)
{
char name[OS_FILE_MAX_PATH];
snprintf(name, sizeof(name),
"%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i);
snprintf(name, sizeof name, "%s/undo%03zu", srv_undo_dir, i);
if (!srv_undo_tablespace_open(create_new_db, name, i))
break;
++srv_undo_tablespaces_open;
......@@ -722,8 +712,7 @@ srv_undo_tablespaces_init(bool create_new_db)
for (ulint i= 0; i < srv_undo_tablespaces; ++i)
{
char name[OS_FILE_MAX_PATH];
snprintf(name, sizeof name, "%s%cundo%03zu",
srv_undo_dir, OS_PATH_SEPARATOR, i + 1);
snprintf(name, sizeof name, "%s/undo%03zu", srv_undo_dir, i + 1);
if (dberr_t err= srv_undo_tablespace_create(name))
{
ib::error() << "Could not create undo tablespace '" << name << "'.";
......@@ -2106,15 +2095,12 @@ srv_get_meta_data_filename(
/* Make sure the data_dir_path is set. */
dict_get_and_save_data_dir_path(table, false);
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
ut_a(table->data_dir_path);
path = fil_make_filepath(
table->data_dir_path, table->name.m_name, CFG, true);
} else {
path = fil_make_filepath(NULL, table->name.m_name, CFG, false);
}
const char* data_dir_path = DICT_TF_HAS_DATA_DIR(table->flags)
? table->data_dir_path : nullptr;
ut_ad(!DICT_TF_HAS_DATA_DIR(table->flags) || data_dir_path);
path = fil_make_filepath(data_dir_path, table->name, CFG,
data_dir_path != nullptr);
ut_a(path);
len = strlen(path);
ut_a(max_len >= len);
......
......@@ -482,57 +482,6 @@ ut_strerr(
return("Unknown error");
}
#ifdef UNIV_PFS_MEMORY
/** Extract the basename of a file without its extension.
For example, extract "foo0bar" out of "/path/to/foo0bar.cc".
@param[in] file file path, e.g. "/path/to/foo0bar.cc"
@param[out] base result, e.g. "foo0bar"
@param[in] base_size size of the output buffer 'base', if there
is not enough space, then the result will be truncated, but always
'\0'-terminated
@return number of characters that would have been printed if the size
were unlimited (not including the final ‘\0’) */
size_t
ut_basename_noext(
const char* file,
char* base,
size_t base_size)
{
/* Assuming 'file' contains something like the following,
extract the file name without the extenstion out of it by
setting 'beg' and 'len'.
...mysql-trunk/storage/innobase/dict/dict0dict.cc:302
^-- beg, len=9
*/
const char* beg = strrchr(file, OS_PATH_SEPARATOR);
if (beg == NULL) {
beg = file;
} else {
beg++;
}
size_t len = strlen(beg);
const char* end = strrchr(beg, '.');
if (end != NULL) {
len = end - beg;
}
const size_t copy_len = std::min(len, base_size - 1);
memcpy(base, beg, copy_len);
base[copy_len] = '\0';
return(len);
}
#endif /* UNIV_PFS_MEMORY */
namespace ib {
ATTRIBUTE_COLD logger& logger::operator<<(dberr_t err)
......
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