summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-04-07 18:01:13 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-04-07 18:01:13 +0300
commitcf552f5886968fc022122960d3a9274ce9f27819 (patch)
tree07e6d40bdd128c9c12ccd9f21a382371a65eb7c4
parentc2a63ac526bf4cd269def30a3d55ff29fdba8f86 (diff)
downloadmariadb-git-bb-10.6-MDEV-25312.tar.gz
MDEV-25312 Replace fil_space_t::name with fil_space_t::name()bb-10.6-MDEV-25312
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 a75dbfd7183cc96680f3e3e684fd36500dac8158 (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
-rw-r--r--extra/mariabackup/backup_copy.cc35
-rw-r--r--extra/mariabackup/backup_debug.h18
-rw-r--r--extra/mariabackup/fil_cur.cc13
-rw-r--r--extra/mariabackup/xtrabackup.cc216
-rw-r--r--mysql-test/suite/innodb/r/log_file.result2
-rw-r--r--mysql-test/suite/innodb/t/log_file.test4
-rw-r--r--mysql-test/suite/innodb/t/restart.test9
-rw-r--r--storage/innobase/buf/buf0dblwr.cc4
-rw-r--r--storage/innobase/buf/buf0dump.cc28
-rw-r--r--storage/innobase/dict/dict0crea.cc12
-rw-r--r--storage/innobase/dict/dict0dict.cc39
-rw-r--r--storage/innobase/dict/dict0load.cc21
-rw-r--r--storage/innobase/fil/fil0crypt.cc2
-rw-r--r--storage/innobase/fil/fil0fil.cc398
-rw-r--r--storage/innobase/fsp/fsp0file.cc295
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc9
-rw-r--r--storage/innobase/fsp/fsp0space.cc24
-rw-r--r--storage/innobase/fsp/fsp0sysspace.cc92
-rw-r--r--storage/innobase/fts/fts0fts.cc42
-rw-r--r--storage/innobase/handler/ha_innodb.cc39
-rw-r--r--storage/innobase/handler/i_s.cc27
-rw-r--r--storage/innobase/include/fil0fil.h76
-rw-r--r--storage/innobase/include/fil0fil.ic3
-rw-r--r--storage/innobase/include/fsp0file.h129
-rw-r--r--storage/innobase/include/fsp0space.h11
-rw-r--r--storage/innobase/include/os0file.h35
-rw-r--r--storage/innobase/include/univ.i16
-rw-r--r--storage/innobase/include/ut0new.h2
-rw-r--r--storage/innobase/include/ut0ut.h21
-rw-r--r--storage/innobase/lock/lock0lock.cc2
-rw-r--r--storage/innobase/log/log0log.cc14
-rw-r--r--storage/innobase/log/log0recv.cc17
-rw-r--r--storage/innobase/os/os0file.cc120
-rw-r--r--storage/innobase/row/row0import.cc29
-rw-r--r--storage/innobase/row/row0mysql.cc17
-rw-r--r--storage/innobase/srv/srv0start.cc34
-rw-r--r--storage/innobase/ut/ut0ut.cc51
37 files changed, 767 insertions, 1139 deletions
diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc
index 9de11e8e6a0..5f44e031245 100644
--- a/extra/mariabackup/backup_copy.cc
+++ b/extra/mariabackup/backup_copy.cc
@@ -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;
}
diff --git a/extra/mariabackup/backup_debug.h b/extra/mariabackup/backup_debug.h
index cefbc287361..777b4f4adeb 100644
--- a/extra/mariabackup/backup_debug.h
+++ b/extra/mariabackup/backup_debug.h
@@ -1,7 +1,7 @@
#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
diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc
index c502c8bac78..99aeb45ccd1 100644
--- a/extra/mariabackup/fil_cur.cc
+++ b/extra/mariabackup/fil_cur.cc
@@ -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 @@ read_retry:
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));
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 160a804af85..5fbf9fd9892 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -362,7 +362,7 @@ struct ddl_tracker_t {
static ddl_tracker_t ddl_tracker;
// Convert non-null terminated filename to space name
-std::string filename_to_spacename(const byte *filename, size_t len);
+static std::string filename_to_spacename(const void *filename, size_t len);
CorruptedPages::CorruptedPages() { ut_a(!pthread_mutex_init(&m_mutex, NULL)); }
@@ -374,11 +374,9 @@ void CorruptedPages::add_page_no_lock(const char *space_name, ulint space_id,
{
space_info_t &space_info = m_spaces[space_id];
if (space_info.space_name.empty())
- space_info.space_name=
- convert_space_name
- ? filename_to_spacename(reinterpret_cast<const byte *>(space_name),
- strlen(space_name))
- : space_name;
+ space_info.space_name= convert_space_name
+ ? filename_to_spacename(space_name, strlen(space_name))
+ : space_name;
(void)space_info.pages.insert(page_no);
}
@@ -724,21 +722,25 @@ end:
void mdl_lock_all()
{
- mdl_lock_init();
- datafiles_iter_t it;
-
- while (fil_node_t *node = datafiles_iter_next(&it)) {
- if (fil_is_user_tablespace_id(node->space->id)
- && check_if_skip_table(node->space->name))
- continue;
+ mdl_lock_init();
+ datafiles_iter_t it;
- mdl_lock_table(node->space->id);
- }
+ while (fil_node_t *node= datafiles_iter_next(&it))
+ {
+ const auto id= node->space->id;
+ if (const char *name= (fil_is_user_tablespace_id(id) &&
+ node->space->chain.start)
+ ? node->space->chain.start->name : nullptr)
+ if (check_if_skip_table(filename_to_spacename(name,
+ strlen(name)).c_str()))
+ continue;
+ mdl_lock_table(id);
+ }
}
// Convert non-null terminated filename to space name
-std::string filename_to_spacename(const byte *filename, size_t len)
+static std::string filename_to_spacename(const void *filename, size_t len)
{
// null- terminate filename
char *f = (char *)malloc(len + 1);
@@ -2045,7 +2047,6 @@ static bool innodb_init_param()
innobase_data_file_path);
srv_sys_space.set_space_id(TRX_SYS_SPACE);
- srv_sys_space.set_name("innodb_system");
srv_sys_space.set_path(srv_data_home);
switch (srv_checksum_algorithm) {
case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
@@ -2077,8 +2078,6 @@ static bool innodb_init_param()
msg("innodb_log_group_home_dir = %s",
srv_log_group_home_dir);
- os_normalize_path(srv_log_group_home_dir);
-
if (strchr(srv_log_group_home_dir, ';')) {
msg("syntax error in innodb_log_group_home_dir, ");
goto error;
@@ -2531,7 +2530,15 @@ check_if_skip_database_by_path(
return(FALSE);
}
- const char* db_name = strrchr(path, OS_PATH_SEPARATOR);
+ const char* db_name = strrchr(path, '/');
+#ifdef _WIN32
+ if (const char* last = strrchr(path, '\\')) {
+ if (!db_name || last > db_name) {
+ db_name = last;
+ }
+ }
+#endif
+
if (db_name == NULL) {
db_name = path;
} else {
@@ -2690,21 +2697,11 @@ static my_bool xtrabackup_copy_datafile(fil_node_t *node, uint thread_n,
xb_read_filt_t *read_filter;
my_bool rc = FALSE;
- /* Get the name and the path for the tablespace. node->name always
- contains the path (which may be absolute for remote tablespaces in
- 5.6+). space->name contains the tablespace name in the form
- "./database/table.ibd" (in 5.5-) or "database/table" (in 5.6+). For a
- multi-node shared tablespace, space->name contains the name of the first
- node, but that's irrelevant, since we only need node_name to match them
- against filters, and the shared tablespace is always copied regardless
- of the filters value. */
-
- const char* const node_name = node->space->name;
- const char* const node_path = node->name;
-
if (fil_is_user_tablespace_id(node->space->id)
- && check_if_skip_table(node_name)) {
- msg(thread_n, "Skipping %s.", node_name);
+ && check_if_skip_table(filename_to_spacename(node->name,
+ strlen(node->name)).
+ c_str())) {
+ msg(thread_n, "Skipping %s.", node->name);
return(FALSE);
}
@@ -2759,9 +2756,10 @@ static my_bool xtrabackup_copy_datafile(fil_node_t *node, uint thread_n,
action = xb_get_copy_action();
if (xtrabackup_stream) {
- msg(thread_n, "%s %s", action, node_path);
+ msg(thread_n, "%s %s", action, node->name);
} else {
- msg(thread_n, "%s %s to %s", action, node_path, dstfile->path);
+ msg(thread_n, "%s %s to %s", action, node->name,
+ dstfile->path);
}
/* The main copy loop */
@@ -2779,11 +2777,15 @@ static my_bool xtrabackup_copy_datafile(fil_node_t *node, uint thread_n,
if (write_filter.finalize
&& !write_filter.finalize(&write_filt_ctxt, dstfile)) {
goto error;
- }
+ } else {
+ const fil_space_t::name_type name = node->space->name();
- pthread_mutex_lock(&backup_mutex);
- ddl_tracker.tables_in_backup[node->space->id] = node_name;
- pthread_mutex_unlock(&backup_mutex);
+ pthread_mutex_lock(&backup_mutex);
+ ddl_tracker.tables_in_backup.emplace(node->space->id,
+ std::string(name.data(),
+ name.size()));
+ pthread_mutex_unlock(&backup_mutex);
+ }
/* close */
msg(thread_n," ...done");
@@ -2815,7 +2817,7 @@ skip:
if (write_filter.deinit) {
write_filter.deinit(&write_filt_ctxt);
}
- msg(thread_n,"Warning: We assume the table was dropped during xtrabackup execution and ignore the tablespace %s", node_name);
+ msg(thread_n,"Warning: We assume the table was dropped during xtrabackup execution and ignore the tablespace %s", node->name);
return(FALSE);
}
@@ -3032,19 +3034,23 @@ static void *io_watching_thread(void*)
}
#ifndef DBUG_OFF
-char *dbug_mariabackup_get_val(const char *event, const char *key)
+char *dbug_mariabackup_get_val(const char *event,
+ const fil_space_t::name_type key)
{
- char envvar[FN_REFLEN];
- if (key) {
- snprintf(envvar, sizeof(envvar), "%s_%s", event, key);
- char *slash = strchr(envvar, '/');
- if (slash)
- *slash = '_';
- } else {
- strncpy(envvar, event, sizeof envvar - 1);
- envvar[sizeof envvar - 1] = '\0';
- }
- return getenv(envvar);
+ char envvar[FN_REFLEN];
+ strncpy(envvar, event, sizeof envvar - 1);
+ envvar[(sizeof envvar) - 1] = '\0';
+
+ if (key.size() && key.size() + strlen(envvar) < (sizeof envvar) - 2)
+ {
+ strcat(envvar, "_");
+ strncat(envvar, key.data(), key.size());
+ if (char *slash= strchr(envvar, '/'))
+ *slash= '_';
+ }
+
+ char *val = getenv(envvar);
+ return val && *val ? val : nullptr;
}
/*
@@ -3059,7 +3065,8 @@ To use this facility, you need to
for the variable)
3. start mariabackup with --dbug=+d,debug_mariabackup_events
*/
-void dbug_mariabackup_event(const char *event,const char *key)
+static void dbug_mariabackup_event(const char *event,
+ const fil_space_t::name_type key)
{
char *sql = dbug_mariabackup_get_val(event, key);
if (sql && *sql) {
@@ -3067,6 +3074,10 @@ void dbug_mariabackup_event(const char *event,const char *key)
xb_mysql_query(mysql_connection, sql, false, true);
}
}
+# define DBUG_MARIABACKUP_EVENT(A, B) \
+ DBUG_EXECUTE_IF("mariabackup_events", dbug_mariabackup_event(A,B);)
+#else
+# define DBUG_MARIABACKUP_EVENT(A, B) /* empty */
#endif // DBUG_OFF
/** Datafiles copying thread.*/
@@ -3085,8 +3096,9 @@ static void data_copy_thread_func(data_thread_ctxt_t *ctxt) /* thread context */
debug_sync_point("data_copy_thread_func");
while ((node = datafiles_iter_next(ctxt->it)) != NULL) {
- DBUG_MARIABACKUP_EVENT("before_copy", node->space->name);
- DBUG_EXECUTE_FOR_KEY("wait_innodb_redo_before_copy", node->space->name,
+ DBUG_MARIABACKUP_EVENT("before_copy", node->space->name());
+ DBUG_EXECUTE_FOR_KEY("wait_innodb_redo_before_copy",
+ node->space->name(),
backup_wait_for_lsn(get_current_lsn(mysql_connection)););
/* copy the datafile */
if (xtrabackup_copy_datafile(node, num, NULL,
@@ -3094,8 +3106,7 @@ static void data_copy_thread_func(data_thread_ctxt_t *ctxt) /* thread context */
*ctxt->corrupted_pages))
die("failed to copy datafile.");
- DBUG_MARIABACKUP_EVENT("after_copy", node->space->name);
-
+ DBUG_MARIABACKUP_EVENT("after_copy", node->space->name());
}
pthread_mutex_lock(ctxt->count_mutex);
@@ -3209,23 +3220,6 @@ xb_fil_io_init()
fil_system.space_id_reuse_warned = true;
}
-static
-Datafile*
-xb_new_datafile(const char *name, bool is_remote)
-{
- if (is_remote) {
- RemoteDatafile *remote_file = new RemoteDatafile();
- remote_file->set_name(name);
- return(remote_file);
- } else {
- Datafile *file = new Datafile();
- file->set_name(name);
- file->make_filepath(".", name, IBD);
- return(file);
- }
-}
-
-
/** Load tablespace.
@param[in] dirname directory name of the tablespace to open
@@ -3273,7 +3267,20 @@ static void xb_load_single_table_tablespace(const char *dirname,
name[pathlen - 5] = 0;
}
- Datafile *file = xb_new_datafile(name, is_remote);
+ Datafile *file;
+
+ if (is_remote) {
+ RemoteDatafile* rf = new RemoteDatafile();
+ if (!rf->open_link_file(name)) {
+ die("Can't open datafile %s", name);
+ }
+ file = rf;
+ } else {
+ file = new Datafile();
+ file->make_filepath(".",
+ fil_space_t::name_type{name, strlen(name)},
+ IBD);
+ }
if (file->open_read_only(true) != DB_SUCCESS) {
die("Can't open datafile %s", name);
@@ -3292,7 +3299,7 @@ static void xb_load_single_table_tablespace(const char *dirname,
if (err == DB_SUCCESS && file->space_id() != SRV_TMP_SPACE_ID) {
space = fil_space_t::create(
- name, file->space_id(), file->flags(),
+ file->space_id(), file->flags(),
FIL_TYPE_TABLESPACE, NULL/* TODO: crypt_data */);
ut_a(space != NULL);
@@ -3407,7 +3414,6 @@ static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback)
}
snprintf(dbpath, dbpath_len,
"%s/%s", fil_path_to_mysql_datadir, dbinfo.name);
- os_normalize_path(dbpath);
if (check_if_skip_database_by_path(dbpath)) {
fprintf(stderr, "Skipping db: %s\n", dbpath);
@@ -3622,7 +3628,7 @@ xb_load_tablespaces()
}
debug_sync_point("xtrabackup_load_tablespaces_pause");
- DBUG_MARIABACKUP_EVENT("after_load_tablespaces", 0);
+ DBUG_MARIABACKUP_EVENT("after_load_tablespaces", {});
return(DB_SUCCESS);
}
@@ -4386,7 +4392,7 @@ fail_before_log_copying_thread_start:
if (log_copy_failed)
goto fail_before_log_copying_thread_start;
- DBUG_MARIABACKUP_EVENT("before_innodb_log_copy_thread_started",0);
+ DBUG_MARIABACKUP_EVENT("before_innodb_log_copy_thread_started", {});
mysql_cond_init(0, &log_copying_stop, nullptr);
std::thread(log_copying_thread).detach();
@@ -4528,7 +4534,7 @@ void backup_fix_ddl(CorruptedPages &corrupted_pages)
log_file_op = backup_file_op_fail;
pthread_mutex_unlock(&backup_mutex);
- DBUG_MARIABACKUP_EVENT("backup_fix_ddl",0);
+ DBUG_MARIABACKUP_EVENT("backup_fix_ddl", {});
for (space_id_to_name_t::iterator iter = ddl_tracker.tables_in_backup.begin();
iter != ddl_tracker.tables_in_backup.end();
@@ -4624,10 +4630,10 @@ void backup_fix_ddl(CorruptedPages &corrupted_pages)
datafiles_iter_t it2;
while (fil_node_t *node = datafiles_iter_next(&it2)) {
- fil_space_t * space = node->space;
- if (!fil_is_user_tablespace_id(space->id))
+ if (!fil_is_user_tablespace_id(node->space->id))
continue;
- std::string dest_name(node->space->name);
+ std::string dest_name= filename_to_spacename(
+ node->name, strlen(node->name));
dest_name.append(".new");
xtrabackup_copy_datafile(node, 0, dest_name.c_str(), wf_write_through,
corrupted_pages);
@@ -4746,10 +4752,15 @@ xb_space_create_file(
static fil_space_t* fil_space_get_by_name(const char* name)
{
- mysql_mutex_assert_owner(&fil_system.mutex);
- for (fil_space_t& space :fil_system.space_list)
- if (!strcmp(space.name, name)) return &space;
- return NULL;
+ mysql_mutex_assert_owner(&fil_system.mutex);
+ for (fil_space_t &space : fil_system.space_list)
+ if (space.chain.start)
+ if (const char *str= strstr(space.chain.start->name, name))
+ if (!strcmp(str + strlen(name), ".ibd") &&
+ (str == space.chain.start->name ||
+ IF_WIN(str[-1] == '\\' ||,) str[-1] == '/'))
+ return &space;
+ return nullptr;
}
/***********************************************************************
@@ -4784,20 +4795,15 @@ xb_delta_open_matching_space(
if (dbname) {
snprintf(dest_dir, FN_REFLEN, "%s/%s",
xtrabackup_target_dir, dbname);
- os_normalize_path(dest_dir);
-
snprintf(dest_space_name, FN_REFLEN, "%s/%s", dbname, name);
} else {
snprintf(dest_dir, FN_REFLEN, "%s", xtrabackup_target_dir);
- os_normalize_path(dest_dir);
-
snprintf(dest_space_name, FN_REFLEN, "%s", name);
}
snprintf(real_name, real_name_len,
"%s/%s",
xtrabackup_target_dir, dest_space_name);
- os_normalize_path(real_name);
/* Truncate ".ibd" */
dest_space_name[strlen(dest_space_name) - 4] = '\0';
@@ -4867,12 +4873,12 @@ exit:
dbname, fil_space->id);
msg("mariabackup: Renaming %s to %s.ibd",
- fil_space->name, tmpname);
+ fil_space->chain.start->name, tmpname);
if (fil_space->rename(tmpname, NULL, false)
!= DB_SUCCESS) {
msg("mariabackup: Cannot rename %s to %s",
- fil_space->name, tmpname);
+ fil_space->chain.start->name, tmpname);
goto exit;
}
}
@@ -4889,15 +4895,14 @@ exit:
if (fil_space != NULL) {
char tmpname[FN_REFLEN];
- strncpy(tmpname, dest_space_name, FN_REFLEN);
+ snprintf(tmpname, sizeof tmpname, "%s.ibd", dest_space_name);
msg("mariabackup: Renaming %s to %s",
- fil_space->name, dest_space_name);
+ fil_space->chain.start->name, tmpname);
- if (fil_space->rename(tmpname, NULL, false) != DB_SUCCESS)
- {
+ if (fil_space->rename(tmpname, false) != DB_SUCCESS) {
msg("mariabackup: Cannot rename %s to %s",
- fil_space->name, dest_space_name);
+ fil_space->chain.start->name, tmpname);
goto exit;
}
@@ -4920,7 +4925,7 @@ exit:
ut_ad(fil_space_t::zip_size(flags) == info.zip_size);
ut_ad(fil_space_t::physical_size(flags) == info.page_size);
- if (fil_space_t::create(dest_space_name, info.space_id, flags,
+ if (fil_space_t::create(info.space_id, flags,
FIL_TYPE_TABLESPACE, 0)) {
*success = xb_space_create_file(real_name, info.space_id,
flags, &file);
@@ -4985,10 +4990,6 @@ xtrabackup_apply_delta(
goto error;
}
- os_normalize_path(dst_path);
- os_normalize_path(src_path);
- os_normalize_path(meta_path);
-
if (!xb_read_delta_metadata(meta_path, &info)) {
goto error;
}
@@ -5380,8 +5381,6 @@ next_file_item_1:
OS_FILE_MAX_PATH/2-1,
dbinfo.name);
- os_normalize_path(dbpath);
-
dbdir = os_file_opendir(dbpath, FALSE);
if (dbdir != NULL) {
@@ -5502,8 +5501,7 @@ static void rename_table_in_prepare(const std::string &datadir, const std::strin
if (file_exists(dest)) {
ren2= std::string(datadir) + "/" + to + ".ren";
if (!file_exists(ren2)) {
- msg("ERROR : File %s was not found, but expected during rename processing\n", ren2.c_str());
- ut_a(0);
+ die("ERROR : File %s was not found, but expected during rename processing\n", ren2.c_str());
}
tmp = to + "#";
rename_table_in_prepare(datadir, to, tmp);
diff --git a/mysql-test/suite/innodb/r/log_file.result b/mysql-test/suite/innodb/r/log_file.result
index 83ca8f07b63..10479e5004a 100644
--- a/mysql-test/suite/innodb/r/log_file.result
+++ b/mysql-test/suite/innodb/r/log_file.result
@@ -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
diff --git a/mysql-test/suite/innodb/t/log_file.test b/mysql-test/suite/innodb/t/log_file.test
index 76fb013fb8b..5524ecb7858 100644
--- a/mysql-test/suite/innodb/t/log_file.test
+++ b/mysql-test/suite/innodb/t/log_file.test
@@ -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
diff --git a/mysql-test/suite/innodb/t/restart.test b/mysql-test/suite/innodb/t/restart.test
index a7a7855ba7b..7b4de9db63f 100644
--- a/mysql-test/suite/innodb/t/restart.test
+++ b/mysql-test/suite/innodb/t/restart.test
@@ -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
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
index 635a60918f5..ba1c386687e 100644
--- a/storage/innobase/buf/buf0dblwr.cc
+++ b/storage/innobase/buf/buf0dblwr.cc
@@ -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 @@ next_page:
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)))
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc
index db7b0032ec7..eb0b04c55fa 100644
--- a/storage/innobase/buf/buf0dump.cc
+++ b/storage/innobase/buf/buf0dump.cc
@@ -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);
}
}
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 9d5daef6332..5bb222389ef 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -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);
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 046490e713c..fd17f09148e 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -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 */
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index fea22112178..3758fbe3b2c 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -1050,15 +1050,12 @@ next:
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);
}
}
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index 3243a16c33d..5931c820064 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -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="
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index be5cd0b9475..c96c5f2d595 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -114,8 +114,6 @@ bool fil_space_t::try_to_close(bool print_info)
The tablespace must exist in the memory cache.
@param[in] id tablespace identifier
@param[in] old_path old file name
-@param[in] new_name new table name in the
-databasename/tablename format
@param[in] new_path_in new file name,
or NULL if it is located in the normal data directory
@return true if success */
@@ -123,7 +121,6 @@ static bool
fil_rename_tablespace(
ulint id,
const char* old_path,
- const char* new_name,
const char* new_path_in);
/*
@@ -842,7 +839,6 @@ fil_space_free_low(
fil_space_destroy_crypt_data(&space->crypt_data);
space->~fil_space_t();
- ut_free(space->name);
ut_free(space);
}
@@ -903,7 +899,7 @@ fil_space_free(
@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) */
-fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags,
+fil_space_t *fil_space_t::create(ulint id, ulint flags,
fil_type_t purpose,
fil_space_crypt_t *crypt_data,
fil_encryption_t mode)
@@ -921,7 +917,6 @@ fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags,
space= new (ut_zalloc_nokey(sizeof(*space))) fil_space_t;
space->id = id;
- space->name = mem_strdup(name);
UT_LIST_INIT(space->chain, &fil_node_t::chain);
@@ -932,11 +927,10 @@ fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags,
space->crypt_data = crypt_data;
space->n_pending.store(CLOSING, std::memory_order_relaxed);
- DBUG_LOG("tablespace",
- "Created metadata for " << id << " name " << name);
+ DBUG_LOG("tablespace", "Created metadata for " << id);
if (crypt_data) {
DBUG_LOG("crypt",
- "Tablespace " << id << " name " << name
+ "Tablespace " << id
<< " encryption " << crypt_data->encryption
<< " key id " << crypt_data->key_id
<< ":" << fil_crypt_get_mode(crypt_data)
@@ -958,13 +952,14 @@ fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags,
mysql_mutex_lock(&fil_system.mutex);
if (const fil_space_t *old_space = fil_space_get_by_id(id)) {
- ib::error() << "Trying to add tablespace '" << name
- << "' with id " << id
- << " to the tablespace memory cache, but tablespace '"
- << old_space->name << "' already exists in the cache!";
+ ib::error() << "Trying to add tablespace with id " << id
+ << " to the cache, but tablespace '"
+ << (old_space->chain.start
+ ? old_space->chain.start->name
+ : "")
+ << "' already exists in the cache!";
mysql_mutex_unlock(&fil_system.mutex);
space->~fil_space_t();
- ut_free(space->name);
ut_free(space);
return(NULL);
}
@@ -989,7 +984,7 @@ fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags,
}
if (!fil_system.space_id_reuse_warned) {
ib::warn() << "Allocated tablespace ID " << id
- << " for " << name << ", old maximum was "
+ << ", old maximum was "
<< fil_system.max_assigned_id;
}
@@ -1471,7 +1466,7 @@ inline void mtr_t::log_file_op(mfile_type_t type, ulint space_id,
/* fil_name_parse() requires that there be at least one path
separator and that the file path end with ".ibd". */
- ut_ad(strchr(path, OS_PATH_SEPARATOR) != NULL);
+ ut_ad(strchr(path, '/'));
ut_ad(!strcmp(&path[strlen(path) - strlen(DOT_IBD)], DOT_IBD));
flag_modified();
@@ -1509,7 +1504,7 @@ inline void mtr_t::log_file_op(mfile_type_t type, ulint space_id,
if (type == FILE_RENAME)
{
- ut_ad(strchr(new_path, OS_PATH_SEPARATOR));
+ ut_ad(strchr(new_path, '/'));
m_log.push(reinterpret_cast<const byte*>(path), uint32_t(len + 1));
m_log.push(reinterpret_cast<const byte*>(new_path), uint32_t(new_len));
}
@@ -1583,7 +1578,7 @@ static ulint fil_check_pending_ops(const fil_space_t* space, ulint count)
/* Give a warning every 10 second, starting after 1 second */
if ((count % 500) == 50) {
ib::warn() << "Trying to delete"
- " tablespace '" << space->name
+ " tablespace '" << space->chain.start->name
<< "' but there are " << n_pending_ops
<< " pending operations on it.";
}
@@ -1619,7 +1614,7 @@ fil_check_pending_io(
/* Give a warning every 10 second, starting after 1 second */
if ((count % 500) == 50) {
ib::info() << "Trying to delete"
- " tablespace '" << space->name
+ " tablespace '" << space->chain.start->name
<< "' but there are " << p
<< " pending i/o's on it.";
}
@@ -1745,7 +1740,8 @@ void fil_close_tablespace(ulint id)
/* If it is a delete then also delete any generated files, otherwise
when we drop the database the remove directory will fail. */
- if (char* cfg_name = fil_make_filepath(path, NULL, CFG, false)) {
+ if (char* cfg_name = fil_make_filepath(path, fil_space_t::name_type{},
+ CFG, false)) {
os_file_delete_if_exists(innodb_data_file_key, cfg_name, NULL);
ut_free(cfg_name);
}
@@ -1819,16 +1815,17 @@ dberr_t fil_delete_tablespace(ulint id, bool if_exists,
written to the redo log. */
log_write_up_to(mtr.commit_lsn(), true);
- char* cfg_name = fil_make_filepath(path, NULL, CFG, false);
- if (cfg_name != NULL) {
- os_file_delete_if_exists(innodb_data_file_key, cfg_name, NULL);
+ if (char* cfg_name = fil_make_filepath(
+ path, fil_space_t::name_type{}, CFG, false)) {
+ os_file_delete_if_exists(innodb_data_file_key,
+ cfg_name, nullptr);
ut_free(cfg_name);
}
}
/* Delete the link file pointing to the ibd file we are deleting. */
if (FSP_FLAGS_HAS_DATA_DIR(space->flags)) {
- RemoteDatafile::delete_link_file(space->name);
+ RemoteDatafile::delete_link_file(space->name());
}
mysql_mutex_lock(&fil_system.mutex);
@@ -1889,25 +1886,21 @@ fil_space_t *fil_truncate_prepare(ulint space_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 ext,
- bool trim_name)
+char* fil_make_filepath(const char *path, const fil_space_t::name_type &name,
+ ib_extention ext, bool trim_name)
{
/* The path may contain the basename of the file, if so we do not
need the name. If the path is NULL, we can use the default path,
but there needs to be a name. */
- ut_ad(path != NULL || name != NULL);
+ ut_ad(path || name.data());
/* If we are going to strip a name off the path, there better be a
path and a new name to put back on. */
- ut_ad(!trim_name || (path != NULL && name != NULL));
+ ut_ad(!trim_name || (path && name.data()));
if (path == NULL) {
path = fil_path_to_mysql_datadir;
@@ -1915,20 +1908,20 @@ fil_make_filepath(
ulint len = 0; /* current length */
ulint path_len = strlen(path);
- ulint name_len = (name ? strlen(name) : 0);
const char* suffix = dot_ext[ext];
ulint suffix_len = strlen(suffix);
- ulint full_len = path_len + 1 + name_len + suffix_len + 1;
+ ulint full_len = path_len + 1 + name.size() + suffix_len + 1;
char* full_name = static_cast<char*>(ut_malloc_nokey(full_len));
if (full_name == NULL) {
return NULL;
}
- /* If the name is a relative path, do not prepend "./". */
+ /* If the name is a relative or absolute path, do not prepend "./". */
if (path[0] == '.'
- && (path[1] == '\0' || path[1] == OS_PATH_SEPARATOR)
- && name != NULL && name[0] == '.') {
+ && (path[1] == '\0' || path[1] == '/' IF_WIN(|| path[1] == '\\',))
+ && name.size() && (name.data()[0] == '.'
+ || is_absolute_path(name.data()))) {
path = NULL;
path_len = 0;
}
@@ -1937,31 +1930,36 @@ fil_make_filepath(
memcpy(full_name, path, path_len);
len = path_len;
full_name[len] = '\0';
- os_normalize_path(full_name);
}
if (trim_name) {
/* Find the offset of the last DIR separator and set it to
null in order to strip off the old basename from this path. */
- char* last_dir_sep = strrchr(full_name, OS_PATH_SEPARATOR);
+ char* last_dir_sep = strrchr(full_name, '/');
+#ifdef _WIN32
+ if (char *last = strrchr(full_name, '\\')) {
+ if (last > last_dir_sep) {
+ last_dir_sep = last;
+ }
+ }
+#endif
if (last_dir_sep) {
last_dir_sep[0] = '\0';
len = strlen(full_name);
}
}
- if (name != NULL) {
- if (len && full_name[len - 1] != OS_PATH_SEPARATOR) {
+ if (name.size()) {
+ if (len && full_name[len - 1] != '/') {
/* Add a DIR separator */
- full_name[len] = OS_PATH_SEPARATOR;
+ full_name[len] = '/';
full_name[++len] = '\0';
}
char* ptr = &full_name[len];
- memcpy(ptr, name, name_len);
- len += name_len;
+ memcpy(ptr, name.data(), name.size());
+ len += name.size();
full_name[len] = '\0';
- os_normalize_path(ptr);
}
/* Make sure that the specified suffix is at the end of the filepath
@@ -1989,6 +1987,13 @@ fil_make_filepath(
return(full_name);
}
+char *fil_make_filepath(const char* path, const table_name_t name,
+ ib_extention suffix, bool strip_name)
+{
+ return fil_make_filepath(path, {name.m_name, strlen(name.m_name)},
+ suffix, strip_name);
+}
+
/** Test if a tablespace file can be renamed to a new filepath by checking
if that the old filepath exists and the new filepath does not exist.
@param[in] old_path old filepath
@@ -2055,8 +2060,7 @@ retry:
return(DB_SUCCESS);
}
-dberr_t fil_space_t::rename(const char* name, const char* path, bool log,
- bool replace)
+dberr_t fil_space_t::rename(const char* path, bool log, bool replace)
{
ut_ad(UT_LIST_GET_LEN(chain) == 1);
ut_ad(!is_system_tablespace(id));
@@ -2070,7 +2074,7 @@ dberr_t fil_space_t::rename(const char* name, const char* path, bool log,
fil_name_write_rename(id, chain.start->name, path);
}
- return fil_rename_tablespace(id, chain.start->name, name, path)
+ return fil_rename_tablespace(id, chain.start->name, path)
? DB_SUCCESS : DB_ERROR;
}
@@ -2078,8 +2082,6 @@ dberr_t fil_space_t::rename(const char* name, const char* path, bool log,
The tablespace must exist in the memory cache.
@param[in] id tablespace identifier
@param[in] old_path old file name
-@param[in] new_name new table name in the
-databasename/tablename format
@param[in] new_path_in new file name,
or NULL if it is located in the normal data directory
@return true if success */
@@ -2087,15 +2089,12 @@ static bool
fil_rename_tablespace(
ulint id,
const char* old_path,
- const char* new_name,
const char* new_path_in)
{
fil_space_t* space;
fil_node_t* node;
ut_a(id != 0);
- ut_ad(strchr(new_name, '/') != NULL);
-
mysql_mutex_lock(&fil_system.mutex);
space = fil_space_get_by_id(id);
@@ -2117,15 +2116,11 @@ fil_rename_tablespace(
mysql_mutex_unlock(&fil_system.mutex);
- char* new_file_name = new_path_in == NULL
- ? fil_make_filepath(NULL, new_name, IBD, false)
- : mem_strdup(new_path_in);
+ char* new_file_name = mem_strdup(new_path_in);
char* old_file_name = node->name;
- char* new_space_name = mem_strdup(new_name);
- char* old_space_name = space->name;
- ut_ad(strchr(old_file_name, OS_PATH_SEPARATOR) != NULL);
- ut_ad(strchr(new_file_name, OS_PATH_SEPARATOR) != NULL);
+ ut_ad(strchr(old_file_name, '/'));
+ ut_ad(strchr(new_file_name, '/'));
if (!recv_recovery_is_on()) {
mysql_mutex_lock(&log_sys.mutex);
@@ -2135,7 +2130,6 @@ fil_rename_tablespace(
mysql_mutex_assert_owner(&log_sys.mutex);
mysql_mutex_lock(&fil_system.mutex);
space->release();
- ut_ad(space->name == old_space_name);
ut_ad(node->name == old_file_name);
bool success;
DBUG_EXECUTE_IF("fil_rename_tablespace_failure_2",
@@ -2151,26 +2145,17 @@ skip_second_rename:
if (success) {
node->name = new_file_name;
+ } else {
+ old_file_name = new_file_name;
}
if (!recv_recovery_is_on()) {
mysql_mutex_unlock(&log_sys.mutex);
}
- ut_ad(space->name == old_space_name);
- if (success) {
- space->name = new_space_name;
- } else {
- /* Because nothing was renamed, we must free the new
- names, not the old ones. */
- old_file_name = new_file_name;
- old_space_name = new_space_name;
- }
-
mysql_mutex_unlock(&fil_system.mutex);
ut_free(old_file_name);
- ut_free(old_space_name);
return(success);
}
@@ -2193,7 +2178,7 @@ 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,
@@ -2341,6 +2326,7 @@ err_exit:
}
aligned_free(page);
+ fil_space_t::name_type space_name;
if (*err != DB_SUCCESS) {
ib::error()
@@ -2359,13 +2345,14 @@ err_exit:
if (has_data_dir) {
/* Make the ISL file if the IBD file is not
in the default location. */
- *err = RemoteDatafile::create_link_file(name, path);
+ space_name = {name.m_name, strlen(name.m_name)};
+ *err = RemoteDatafile::create_link_file(space_name, path);
if (*err != DB_SUCCESS) {
goto err_exit;
}
}
- if (fil_space_t* space = fil_space_t::create(name, space_id, flags,
+ if (fil_space_t* space = fil_space_t::create(space_id, flags,
FIL_TYPE_TABLESPACE,
crypt_data, mode)) {
space->punch_hole = punch_hole;
@@ -2380,8 +2367,8 @@ err_exit:
return space;
}
- if (has_data_dir) {
- RemoteDatafile::delete_link_file(name);
+ if (space_name.data()) {
+ RemoteDatafile::delete_link_file(space_name);
}
*err = DB_ERROR;
@@ -2424,23 +2411,12 @@ 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)
{
mysql_mutex_lock(&fil_system.mutex);
if (fil_space_t* space = fil_space_get_by_id(id)) {
- if (strcmp(space->name, tablename.m_name)) {
- table_name_t space_name;
- space_name.m_name = space->name;
- ib::error()
- << "Trying to open table " << tablename
- << " with id " << id
- << ", conflicting with " << space_name;
- space = NULL;
- if (err) *err = DB_TABLESPACE_EXISTS;
- } else if (err) *err = DB_SUCCESS;
-
mysql_mutex_unlock(&fil_system.mutex);
if (space && validate && !srv_read_only_mode) {
@@ -2466,27 +2442,32 @@ corrupted:
}
ut_ad(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, id));
- df_default.init(tablename.m_name, flags);
- df_remote.init(tablename.m_name, flags);
+ df_default.init(flags);
+ df_remote.init(flags);
/* Discover the correct file by looking in three possible locations
while avoiding unecessary effort. */
/* We will always look for an ibd in the default location. */
- df_default.make_filepath(NULL, tablename.m_name, IBD);
+ df_default.make_filepath(nullptr, {tablename.m_name,
+ strlen(tablename.m_name)}, IBD);
/* Look for a filepath embedded in an ISL where the default file
would be. */
- if (df_remote.open_read_only(true) == DB_SUCCESS) {
- ut_ad(df_remote.is_open());
-
- /* Always validate a file opened from an ISL pointer */
- validate = true;
- ++tablespaces_found;
- } else if (df_remote.filepath() != NULL) {
- /* An ISL file was found but contained a bad filepath in it.
- Better validate anything we do find. */
+ if (df_remote.open_link_file(tablename)) {
validate = true;
+ if (df_remote.open_read_only(true) == DB_SUCCESS) {
+ ut_ad(df_remote.is_open());
+ ++tablespaces_found;
+ } else {
+ /* The following call prints an error message */
+ os_file_get_last_error(true);
+ ib::error() << "A link file was found named '"
+ << df_remote.link_filepath()
+ << "' but the linked tablespace '"
+ << df_remote.filepath()
+ << "' could not be opened read-only.";
+ }
}
/* Attempt to open the tablespace at the dictionary filepath. */
@@ -2619,7 +2600,7 @@ skip_validate:
: NULL;
fil_space_t* space = fil_space_t::create(
- tablename.m_name, id, flags, purpose, crypt_data);
+ id, flags, purpose, crypt_data);
if (!space) {
goto error;
}
@@ -2647,89 +2628,6 @@ skip_validate:
return space;
}
-/** 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] filepath The filepath of the first datafile for the
-tablespace.
-@return true if tablespace is found, false if not. */
-bool
-fil_space_read_name_and_filepath(
- ulint space_id,
- char** name,
- char** filepath)
-{
- bool success = false;
- *name = NULL;
- *filepath = NULL;
-
- mysql_mutex_lock(&fil_system.mutex);
-
- fil_space_t* space = fil_space_get_by_id(space_id);
-
- if (space != NULL) {
- *name = mem_strdup(space->name);
-
- fil_node_t* node = UT_LIST_GET_FIRST(space->chain);
- *filepath = mem_strdup(node->name);
-
- success = true;
- }
-
- mysql_mutex_unlock(&fil_system.mutex);
-
- return(success);
-}
-
-/** 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)
-{
- /* Strip the file name prefix and suffix, leaving
- only databasename/tablename. */
- ulint filename_len = strlen(filename);
- const char* end = filename + filename_len;
-#ifdef HAVE_MEMRCHR
- const char* tablename = 1 + static_cast<const char*>(
- memrchr(filename, OS_PATH_SEPARATOR,
- filename_len));
- const char* dbname = 1 + static_cast<const char*>(
- memrchr(filename, OS_PATH_SEPARATOR,
- tablename - filename - 1));
-#else /* HAVE_MEMRCHR */
- const char* tablename = filename;
- const char* dbname = NULL;
-
- while (const char* t = static_cast<const char*>(
- memchr(tablename, OS_PATH_SEPARATOR,
- ulint(end - tablename)))) {
- dbname = tablename;
- tablename = t + 1;
- }
-#endif /* HAVE_MEMRCHR */
-
- ut_ad(dbname != NULL);
- ut_ad(tablename > dbname);
- ut_ad(tablename < end);
- ut_ad(end - tablename > 4);
- ut_ad(memcmp(end - 4, DOT_IBD, 4) == 0);
-
- char* name = mem_strdupl(dbname, ulint(end - dbname) - 4);
-
- ut_ad(name[tablename - dbname - 1] == OS_PATH_SEPARATOR);
-#if OS_PATH_SEPARATOR != '/'
- /* space->name uses '/', not OS_PATH_SEPARATOR. */
- name[tablename - dbname - 1] = '/';
-#endif
-
- return(name);
-}
-
/** Discover the correct IBD file to open given a remote or missing
filepath from the REDO log. Administrators can move a crashed
database to another location on the same machine and try to recover it.
@@ -2760,14 +2658,18 @@ fil_ibd_discover(
ulint sep_found = 0;
const char* db = basename;
for (; db > filename && sep_found < 2; db--) {
- if (db[0] == OS_PATH_SEPARATOR) {
+ switch (db[0]) {
+#ifdef _WIN32
+ case '\\':
+#endif
+ case '/':
sep_found++;
}
}
if (sep_found == 2) {
db += 2;
- df_def_per.init(db, 0);
- df_def_per.make_filepath(NULL, db, IBD);
+ df_def_per.init(0);
+ df_def_per.set_filepath(db);
if (df_def_per.open_read_only(false) == DB_SUCCESS
&& df_def_per.validate_for_recovery() == DB_SUCCESS
&& df_def_per.space_id() == space_id) {
@@ -2787,8 +2689,16 @@ fil_ibd_discover(
case SRV_OPERATION_RESTORE:
break;
case SRV_OPERATION_NORMAL:
- df_rem_per.set_name(db);
- if (df_rem_per.open_link_file() != DB_SUCCESS) {
+ char* name = const_cast<char*>(db);
+ size_t len= strlen(name);
+ if (len <= 4 || strcmp(name + len - 4, dot_ext[IBD])) {
+ break;
+ }
+ name[len - 4] = '\0';
+ df_rem_per.open_link_file(table_name_t{name});
+ name[len - 4] = *dot_ext[IBD];
+
+ if (!df_rem_per.filepath()) {
break;
}
@@ -2811,7 +2721,7 @@ fil_ibd_discover(
}
/* Use this file if it has the space_id from the
- MLOG record. */
+ FILE_ record. */
if (df_rem_per.space_id() == space_id) {
df.set_filepath(df_rem_per.filepath());
df.open_read_only(false);
@@ -2883,9 +2793,20 @@ fil_ibd_load(
if (srv_operation == SRV_OPERATION_RESTORE) {
/* Replace absolute DATA DIRECTORY file paths with
short names relative to the backup directory. */
- if (const char* name = strrchr(filename, OS_PATH_SEPARATOR)) {
+ const char* name = strrchr(filename, '/');
+#ifdef _WIN32
+ if (const char *last = strrchr(filename, '\\')) {
+ if (last > name) {
+ name = last;
+ }
+ }
+#endif
+ if (name) {
while (--name > filename
- && *name != OS_PATH_SEPARATOR);
+#ifdef _WIN32
+ && *name != '\\'
+#endif
+ && *name != '/');
if (name > filename) {
filename = name + 1;
}
@@ -2971,7 +2892,7 @@ fil_ibd_load(
first_page)
: NULL;
space = fil_space_t::create(
- file.name(), space_id, flags, FIL_TYPE_TABLESPACE, crypt_data);
+ space_id, flags, FIL_TYPE_TABLESPACE, crypt_data);
if (space == NULL) {
return(FIL_LOAD_INVALID);
@@ -3075,15 +2996,10 @@ func_exit:
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)
{
const ulint expected_flags = dict_tf_to_fsp_flags(table_flags);
@@ -3097,17 +3013,6 @@ fil_space_for_table_exists_in_mem(
goto func_exit;
}
- if (strcmp(space->name, name)) {
- ib::error() << "Table " << name
- << " in InnoDB data dictionary"
- " has tablespace id " << id
- << ", but the tablespace"
- " with that id has name " << space->name << "."
- " Have you deleted or moved .ibd files?";
- ib::info() << TROUBLESHOOT_DATADICT_MSG;
- goto func_exit;
- }
-
/* Adjust the flags that are in FSP_FLAGS_MEM_MASK.
FSP_SPACE_FLAGS will not be written back here. */
space->flags = (space->flags & ~FSP_FLAGS_MEM_MASK)
@@ -3206,8 +3111,8 @@ fil_io_t fil_space_t::io(const IORequest &type, os_offset_t offset, size_t len,
release();
return {DB_ERROR, nullptr};
}
- fil_report_invalid_page_access(name, offset,
- len,
+ fil_report_invalid_page_access(node->name,
+ offset, len,
type.is_read());
}
}
@@ -3422,23 +3327,18 @@ fil_page_set_type(
Delete the tablespace file and any related files like .cfg.
This should not be called for temporary tables.
@param[in] ibd_filepath File path of the IBD tablespace */
-void
-fil_delete_file(
-/*============*/
- const char* ibd_filepath)
+void fil_delete_file(const char *ibd_filepath)
{
- /* Force a delete of any stale .ibd files that are lying around. */
-
- ib::info() << "Deleting " << ibd_filepath;
- os_file_delete_if_exists(innodb_data_file_key, ibd_filepath, NULL);
+ ib::info() << "Deleting " << ibd_filepath;
+ os_file_delete_if_exists(innodb_data_file_key, ibd_filepath, nullptr);
- char* cfg_filepath = fil_make_filepath(
- ibd_filepath, NULL, CFG, false);
- if (cfg_filepath != NULL) {
- os_file_delete_if_exists(
- innodb_data_file_key, cfg_filepath, NULL);
- ut_free(cfg_filepath);
- }
+ if (char *cfg_filepath= fil_make_filepath(ibd_filepath,
+ fil_space_t::name_type{}, CFG,
+ false))
+ {
+ os_file_delete_if_exists(innodb_data_file_key, cfg_filepath, nullptr);
+ ut_free(cfg_filepath);
+ }
}
#ifdef UNIV_DEBUG
@@ -3512,7 +3412,6 @@ void fil_names_dirty_and_write(fil_space_t* space)
DBUG_EXECUTE_IF("fil_names_write_bogus",
{
char bogus_name[] = "./test/bogus file.ibd";
- os_normalize_path(bogus_name);
fil_name_write(
SRV_SPACE_ID_UPPER_BOUND,
bogus_name, &mtr);
@@ -3666,6 +3565,43 @@ fil_space_get_block_size(const fil_space_t* space, unsigned offset)
return block_size;
}
+/** @return the tablespace name (databasename/tablename) */
+fil_space_t::name_type fil_space_t::name() const
+{
+ switch (id) {
+ case 0:
+ return name_type{"innodb_system", 13};
+ case SRV_TMP_SPACE_ID:
+ return name_type{"innodb_temporary", 16};
+ }
+
+ if (!UT_LIST_GET_FIRST(chain) || srv_is_undo_tablespace(id))
+ return name_type{};
+
+ ut_ad(purpose != FIL_TYPE_TEMPORARY);
+ ut_ad(UT_LIST_GET_LEN(chain) == 1);
+
+ const char *path= UT_LIST_GET_FIRST(chain)->name;
+ const char *sep= strchr(path, '/');
+ ut_ad(sep);
+
+ while (const char *next_sep= strchr(sep + 1, '/'))
+ path= sep + 1, sep= next_sep;
+
+#ifdef _WIN32
+ if (const char *last_sep= strchr(path, '\\'))
+ if (last_sep < sep)
+ path= last_sep;
+#endif
+
+ size_t len= strlen(path);
+ ut_ad(len > 4);
+ len-= 4;
+ ut_ad(!strcmp(&path[len], DOT_IBD));
+
+ return name_type{path, len};
+}
+
#ifdef UNIV_DEBUG
fil_space_t *fil_space_t::next_in_space_list()
diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc
index 57164113647..77faf58edcf 100644
--- a/storage/innobase/fsp/fsp0file.cc
+++ b/storage/innobase/fsp/fsp0file.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
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
@@ -30,29 +30,12 @@ Created 2013-7-26 by Kevin Lewis
#include "page0page.h"
#include "srv0start.h"
-/** Initialize the name, size and order of this datafile
-@param[in] name tablespace name, will be copied
-@param[in] flags tablespace flags */
-void
-Datafile::init(
- const char* name,
- ulint flags)
-{
- ut_ad(m_name == NULL);
- ut_ad(name != NULL);
-
- m_name = mem_strdup(name);
- m_flags = flags;
-}
-
/** Release the resources. */
void
Datafile::shutdown()
{
close();
- ut_free(m_name);
- m_name = NULL;
free_filepath();
free_first_page();
}
@@ -119,13 +102,12 @@ Datafile::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 */
-dberr_t
-Datafile::open_read_write(bool read_only_mode)
+inline dberr_t Datafile::open_read_write()
{
bool success = false;
ut_ad(m_handle == OS_FILE_CLOSED);
+ ut_ad(!srv_read_only_mode);
/* This function can be called for file objects that do not need
to be opened, which is the case when the m_filepath is NULL */
@@ -136,7 +118,7 @@ Datafile::open_read_write(bool read_only_mode)
set_open_flags(OS_FILE_OPEN);
m_handle = os_file_create_simple_no_error_handling(
innodb_data_file_key, m_filepath, m_open_flags,
- OS_FILE_READ_WRITE, read_only_mode, &success);
+ OS_FILE_READ_WRITE, false, &success);
if (!success) {
m_last_os_error = os_file_get_last_error(true);
@@ -182,24 +164,17 @@ Datafile::close()
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
-Datafile::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 Datafile::make_filepath(const char *dirpath, fil_space_t::name_type name,
+ ib_extention ext)
{
- ut_ad(dirpath != NULL || filename != NULL);
-
- free_filepath();
-
- m_filepath = fil_make_filepath(dirpath, filename, ext, false);
-
- ut_ad(m_filepath != NULL);
-
- set_filename();
+ ut_ad(dirpath || name.size());
+ free_filepath();
+ m_filepath= fil_make_filepath(dirpath, name, ext, false);
+ ut_ad(m_filepath);
+ set_filename();
}
/** Set the filepath by duplicating the filepath sent in. This is the
@@ -258,23 +233,6 @@ Datafile::same_as(
#endif /* WIN32 */
}
-/** 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
-Datafile::set_name(const char* name)
-{
- ut_free(m_name);
-
- if (name != NULL) {
- m_name = mem_strdup(name);
- } else {
- m_name = fil_path_to_space_name(m_filepath);
- }
-}
-
/** Reads a few significant fields from the first page of the first
datafile. The Datafile must already be open.
@param[in] read_only_mode If true, then readonly mode checks are enforced.
@@ -454,7 +412,7 @@ Datafile::validate_for_recovery()
page 0 from doublewrite and read the space ID from a survey
of the first few pages. */
close();
- err = open_read_write(srv_read_only_mode);
+ err = open_read_write();
if (err != DB_SUCCESS) {
return(err);
}
@@ -476,10 +434,6 @@ Datafile::validate_for_recovery()
err = validate_first_page(0);
}
- if (err == DB_SUCCESS) {
- set_name(NULL);
- }
-
return(err);
}
@@ -491,11 +445,8 @@ m_is_valid is set true on success, else false.
@retval DB_SUCCESS on if the datafile is valid
@retval DB_CORRUPTION if the datafile is not readable
@retval DB_TABLESPACE_EXISTS if there is a duplicate space_id */
-dberr_t
-Datafile::validate_first_page(lsn_t* flush_lsn)
+dberr_t Datafile::validate_first_page(lsn_t *flush_lsn)
{
- char* prev_name;
- char* prev_filepath;
const char* error_txt = NULL;
m_is_valid = true;
@@ -576,26 +527,30 @@ err_exit:
goto err_exit;
}
- if (fil_space_read_name_and_filepath(
- m_space_id, &prev_name, &prev_filepath)) {
+ mysql_mutex_lock(&fil_system.mutex);
- if (0 == strcmp(m_filepath, prev_filepath)) {
- ut_free(prev_name);
- ut_free(prev_filepath);
- return(DB_SUCCESS);
+ fil_space_t* space = fil_space_get_by_id(m_space_id);
+
+ if (space) {
+ fil_node_t* node = UT_LIST_GET_FIRST(space->chain);
+
+ if (node && !strcmp(m_filepath, node->name)) {
+ mysql_mutex_unlock(&fil_system.mutex);
+ return DB_SUCCESS;
}
/* Make sure the space_id has not already been opened. */
ib::error() << "Attempted to open a previously opened"
- " tablespace. Previous tablespace " << prev_name
- << " at filepath: " << prev_filepath
- << " uses space ID: " << m_space_id
- << ". Cannot open filepath: " << m_filepath
- << " which uses the same space ID.";
+ " tablespace. Previous tablespace: "
+ << (node ? node->name : "(unknown)")
+ << " uses space ID: " << m_space_id
+ << ". Cannot open filepath: " << m_filepath
+ << " which uses the same space ID.";
+ }
- ut_free(prev_name);
- ut_free(prev_filepath);
+ mysql_mutex_unlock(&fil_system.mutex);
+ if (space) {
m_is_valid = false;
free_first_page();
@@ -809,68 +764,61 @@ Datafile::restore_from_doublewrite()
!= DB_SUCCESS);
}
-/** 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
-RemoteDatafile::open_link_file()
-{
- if (m_link_filepath == NULL) {
- m_link_filepath = fil_make_filepath(NULL, name(), ISL, false);
- }
-
- m_filepath = read_link_file(m_link_filepath);
-
- return(m_filepath == NULL ? DB_CANNOT_OPEN_FILE : DB_SUCCESS);
-}
-
-/** Opens 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 if remote linked tablespace file is found and opened. */
-dberr_t
-RemoteDatafile::open_read_only(bool strict)
+/** Read an InnoDB Symbolic Link (ISL) file by name.
+@param link_filepath filepath of the ISL file
+@return data file name (must be freed by the caller)
+@retval nullptr on error */
+static char *read_link_file(const char *link_filepath)
{
- if (m_filepath == NULL && open_link_file() == DB_CANNOT_OPEN_FILE) {
- return(DB_ERROR);
- }
-
- dberr_t err = Datafile::open_read_only(strict);
-
- if (err != DB_SUCCESS && strict) {
- /* The following call prints an error message */
- os_file_get_last_error(true);
- ib::error() << "A link file was found named '"
- << m_link_filepath << "' but the linked tablespace '"
- << m_filepath << "' could not be opened read-only.";
- }
-
- return(err);
+ if (FILE* file= fopen(link_filepath, "r+b" STR_O_CLOEXEC))
+ {
+ char *filepath= static_cast<char*>(ut_malloc_nokey(OS_FILE_MAX_PATH));
+
+ os_file_read_string(file, filepath, OS_FILE_MAX_PATH);
+ fclose(file);
+
+ if (size_t len= strlen(filepath))
+ {
+ /* Trim whitespace from end of filepath */
+ len--;
+ while (filepath[len] >= 0 && filepath[len] <= 0x20)
+ filepath[len--]= 0;
+ if (!*filepath)
+ return nullptr;
+ /* Ensure that the last 2 path separators are forward slashes,
+ because elsewhere we are assuming that tablespace file names end
+ in "/databasename/tablename.ibd". */
+ unsigned trailing_slashes= 0;
+ for (; len; len--)
+ {
+ switch (filepath[len]) {
+#ifdef _WIN32
+ case '\\':
+ filepath[len]= '/';
+ /* fall through */
+#endif
+ case '/':
+ if (++trailing_slashes >= 2)
+ return filepath;
+ }
+ }
+ }
+ }
+
+ return nullptr;
}
-/** 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 if remote linked tablespace file is found and opened. */
-dberr_t
-RemoteDatafile::open_read_write(bool read_only_mode)
+/** Create a link filename,
+open that file, and read the contents into m_filepath.
+@param name table name
+@return filepath()
+@retval nullptr if the .isl file does not exist or cannot be read */
+const char *RemoteDatafile::open_link_file(const table_name_t &name)
{
- if (m_filepath == NULL && open_link_file() == DB_CANNOT_OPEN_FILE) {
- return(DB_ERROR);
- }
-
- dberr_t err = Datafile::open_read_write(read_only_mode);
-
- if (err != DB_SUCCESS) {
- /* The following call prints an error message */
- m_last_os_error = os_file_get_last_error(true);
- ib::error() << "A link file was found named '"
- << m_link_filepath << "' but the linked data file '"
- << m_filepath << "' could not be opened for writing.";
- }
-
- return(err);
+ if (!m_link_filepath)
+ m_link_filepath= fil_make_filepath(nullptr, name, ISL, false);
+ m_filepath= read_link_file(m_link_filepath);
+ return m_filepath;
}
/** Release the resources. */
@@ -885,16 +833,12 @@ RemoteDatafile::shutdown()
}
}
-/** 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 */
-dberr_t
-RemoteDatafile::create_link_file(
- const char* name,
- const char* filepath)
+dberr_t RemoteDatafile::create_link_file(fil_space_t::name_type name,
+ const char *filepath)
{
bool success;
dberr_t err = DB_SUCCESS;
@@ -902,7 +846,6 @@ RemoteDatafile::create_link_file(
char* prev_filepath = NULL;
ut_ad(!srv_read_only_mode);
- ut_ad(0 == strcmp(&filepath[strlen(filepath) - 4], DOT_IBD));
link_filepath = fil_make_filepath(NULL, name, ISL, false);
@@ -915,7 +858,8 @@ RemoteDatafile::create_link_file(
/* Truncate (starting with MySQL 5.6, probably no
longer since MariaDB Server 10.2.19) used to call this
with an existing link file which contains the same filepath. */
- bool same = !strcmp(prev_filepath, filepath);
+ bool same = !strncmp(prev_filepath, name.data(), name.size())
+ && !strcmp(prev_filepath + name.size(), DOT_IBD);
ut_free(prev_filepath);
if (same) {
ut_free(link_filepath);
@@ -963,9 +907,8 @@ RemoteDatafile::create_link_file(
return(err);
}
- ulint rbytes = fwrite(filepath, 1, strlen(filepath), file);
-
- if (rbytes != strlen(filepath)) {
+ const size_t len = strlen(filepath);
+ if (fwrite(filepath, 1, len, file) != len) {
error = os_file_get_last_error(true);
ib::error() <<
"Cannot write link file: "
@@ -994,50 +937,12 @@ RemoteDatafile::delete_link_file(void)
}
/** Delete an InnoDB Symbolic Link (ISL) file by name.
-@param[in] name tablespace name */
-void
-RemoteDatafile::delete_link_file(
- const char* name)
-{
- char* link_filepath = fil_make_filepath(NULL, name, ISL, false);
-
- if (link_filepath != NULL) {
- os_file_delete_if_exists(
- innodb_data_file_key, link_filepath, NULL);
-
- ut_free(link_filepath);
- }
-}
-
-/** 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 */
-char*
-RemoteDatafile::read_link_file(
- const char* link_filepath)
+@param name tablespace name */
+void RemoteDatafile::delete_link_file(fil_space_t::name_type name)
{
- FILE* file = fopen(link_filepath, "r+b" STR_O_CLOEXEC);
- if (file == NULL) {
- return(NULL);
- }
-
- char* filepath = static_cast<char*>(ut_malloc_nokey(OS_FILE_MAX_PATH));
-
- os_file_read_string(file, filepath, OS_FILE_MAX_PATH);
- fclose(file);
-
- if (filepath[0] != '\0') {
- /* Trim whitespace from end of filepath */
- ulint last_ch = strlen(filepath) - 1;
- while (last_ch > 4 && filepath[last_ch] <= 0x20) {
- filepath[last_ch--] = 0x00;
- }
- os_normalize_path(filepath);
- }
-
- return(filepath);
+ if (char *link_filepath= fil_make_filepath(NULL, name, ISL, false))
+ {
+ os_file_delete_if_exists(innodb_data_file_key, link_filepath, nullptr);
+ ut_free(link_filepath);
+ }
}
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index 5ef65564b64..defdb35b575 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -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);
}
diff --git a/storage/innobase/fsp/fsp0space.cc b/storage/innobase/fsp/fsp0space.cc
index b0a80efe7c4..b069250ff9f 100644
--- a/storage/innobase/fsp/fsp0space.cc
+++ b/storage/innobase/fsp/fsp0space.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
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);
}
diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc
index a2c9e1bc688..aba7dac4a19 100644
--- a/storage/innobase/fsp/fsp0sysspace.cc
+++ b/storage/innobase/fsp/fsp0sysspace.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
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;
}
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index 1c8dcc157ce..cc7ffa4d8bc 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -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);
}
}
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index ba13cc15fb5..20b59b94aa6 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -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);
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index 9d130a934fe..6565985fef6 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -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));
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index d0be38f0468..95009bc0bc1 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -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 @@ public:
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 @@ public:
#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 @@ public:
@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 @@ public:
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*
diff --git a/storage/innobase/include/fil0fil.ic b/storage/innobase/include/fil0fil.ic
index fd5f5bc1db9..3194e54c5b5 100644
--- a/storage/innobase/include/fil0fil.ic
+++ b/storage/innobase/include/fil0fil.ic
@@ -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)
diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h
index 7db85e87ed0..517b3f72499 100644
--- a/storage/innobase/include/fsp0file.h
+++ b/storage/innobase/include/fsp0file.h
@@ -1,7 +1,7 @@
/*****************************************************************************
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 @@ public:
Datafile()
:
- m_name(),
m_filepath(),
m_filename(),
m_handle(),
@@ -68,9 +67,8 @@ public:
/* 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 @@ public:
m_last_os_error(),
m_file_info()
{
- ut_ad(m_name != NULL);
- /* No op */
}
Datafile(const Datafile& file)
@@ -105,9 +101,6 @@ public:
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 @@ public:
{
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ private:
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 @@ private:
/* 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 @@ public:
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 */
diff --git a/storage/innobase/include/fsp0space.h b/storage/innobase/include/fsp0space.h
index c00c8d689bf..ed65af52bc8 100644
--- a/storage/innobase/include/fsp0space.h
+++ b/storage/innobase/include/fsp0space.h
@@ -1,7 +1,7 @@
/*****************************************************************************
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 @@ public:
Tablespace()
:
m_files(),
- m_name(),
m_space_id(ULINT_UNDEFINED),
m_path(),
m_flags(),
@@ -79,9 +78,6 @@ public:
/** 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 @@ public:
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 @@ private:
/* DATA MEMBERS */
- /** Name of the tablespace. */
- const char* m_name;
-
/** Tablespace ID */
ulint m_space_id;
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index 94abb375526..1a321a72b09 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -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"
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index c8d4ef9444a..4367213b810 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -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"
diff --git a/storage/innobase/include/ut0new.h b/storage/innobase/include/ut0new.h
index 78ceb2cccfe..82c80994e72 100644
--- a/storage/innobase/include/ut0new.h
+++ b/storage/innobase/include/ut0new.h
@@ -135,7 +135,7 @@ InnoDB:
#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" \
diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h
index dc9a9597b0f..1437cee9b85 100644
--- a/storage/innobase/include/ut0ut.h
+++ b/storage/innobase/include/ut0ut.h
@@ -1,7 +1,7 @@
/*****************************************************************************
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
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 515134edc33..7c266eccb3c 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -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;
}
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 69c4df9b1b8..2dd41890502 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -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;
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 2b8c9e64b47..8820f840337 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -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 @@ next_page:
}
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;
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 30955b949fa..7aeee774915 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -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 @@ invalid:
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;
- }
- }
- }
-}
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index a2cf148fc56..e1864fd27bc 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -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",
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index cc648f0f2e1..768bc52b6aa 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -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 @@ do_drop:
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) {
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index bbd14ddf401..4ae427b767d 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -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 @@ err_exit:
}
space_id= id;
- snprintf(undo_name, sizeof undo_name, "innodb_undo%03u", id);
aligned_free(page);
}
@@ -554,7 +550,7 @@ err_exit:
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);
diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc
index fa04af6de13..b0738b899fb 100644
--- a/storage/innobase/ut/ut0ut.cc
+++ b/storage/innobase/ut/ut0ut.cc
@@ -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)