MDEV-25312 Replace fil_space_t::name with fil_space_t::name()
A consistency check for fil_space_t::name is causing recovery failures in MDEV-25180 (Atomic ALTER TABLE). So, we'd better remove that field altogether. fil_space_t::name was more or less a copy of dict_table_t::name (except for some special cases), and it was not being used for anything useful. There used to be a name_hash, but it had been removed already in commit 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
This commit is contained in:
parent
c2a63ac526
commit
cf552f5886
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
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_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);
|
||||
|
@ -31,7 +31,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES
|
||||
WHERE engine = 'innodb'
|
||||
AND support IN ('YES', 'DEFAULT', 'ENABLED');
|
||||
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
|
||||
FOUND 1 /The innodb_system data file 'ibdata1' was not found but one of the other data files 'ibdata2' exists/ in mysqld.1.err
|
||||
FOUND 1 /The data file '.*ibdata1' was not found but one of the other data files '.*ibdata2' exists/ in mysqld.1.err
|
||||
bak_ib_logfile0
|
||||
bak_ibdata1
|
||||
bak_ibdata2
|
||||
|
@ -14,7 +14,7 @@ call mtr.add_suppression("InnoDB: The error means the system cannot find the pat
|
||||
call mtr.add_suppression("InnoDB: If you are installing InnoDB, remember that you must create directories yourself");
|
||||
call mtr.add_suppression("InnoDB: File .path.to.non-existent.ib_logfile101: 'create' returned OS error \d+");
|
||||
call mtr.add_suppression("InnoDB: Cannot create .path.to.non-existent.ib_logfile101");
|
||||
call mtr.add_suppression("InnoDB: The innodb_system data file 'ibdata1' was not found but one of the other data files 'ibdata2' exists");
|
||||
call mtr.add_suppression("InnoDB: The data file '.*ibdata1' was not found but one of the other data files '.*ibdata2' exists");
|
||||
call mtr.add_suppression("InnoDB: Tablespace size stored in header is \d+ pages, but the sum of data file sizes is \d+ pages");
|
||||
call mtr.add_suppression("InnoDB: Cannot start InnoDB. The tail of the system tablespace is missing");
|
||||
call mtr.add_suppression("InnoDB: undo tablespace '.*undo001' exists\. Creating system tablespace with existing undo tablespaces is not supported\. Please delete all undo tablespaces before creating new system tablespace\.");
|
||||
@ -90,7 +90,7 @@ eval $check_yes_innodb;
|
||||
--source include/start_mysqld.inc
|
||||
eval $check_no_innodb;
|
||||
--source include/shutdown_mysqld.inc
|
||||
let SEARCH_PATTERN=The innodb_system data file 'ibdata1' was not found but one of the other data files 'ibdata2' exists;
|
||||
let SEARCH_PATTERN=The data file '.*ibdata1' was not found but one of the other data files '.*ibdata2' exists;
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
# clean up & Restore
|
||||
|
@ -48,6 +48,15 @@ close OUT or die;
|
||||
die unless open OUT, ">", "$ENV{MYSQL_TMP_DIR}/test/td.ibd";
|
||||
print OUT "xyz " x $ENV{page_size};
|
||||
close OUT or die;
|
||||
die unless open ISL, "+<", "$ENV{datadir}/test/td.isl";
|
||||
$_=<ISL>;
|
||||
if (m|^[a-zA-Z]:|)
|
||||
{
|
||||
tr|/|\\|;
|
||||
seek(ISL, 0, SEEK_SET) or die;
|
||||
print ISL or die;
|
||||
}
|
||||
close ISL or die;
|
||||
EOF
|
||||
|
||||
--let $restart_parameters= --skip-innodb-buffer-pool-load-at-startup
|
||||
|
@ -374,7 +374,7 @@ void buf_dblwr_t::recover()
|
||||
if (!srv_is_undo_tablespace(space_id))
|
||||
ib::warn() << "A copy of page " << page_no
|
||||
<< " in the doublewrite buffer slot " << page_no_dblwr
|
||||
<< " is beyond the end of tablespace " << space->name
|
||||
<< " is beyond the end of " << space->chain.start->name
|
||||
<< " (" << space->size << " pages)";
|
||||
next_page:
|
||||
space->release();
|
||||
@ -395,7 +395,7 @@ 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)))
|
||||
|
@ -181,8 +181,8 @@ static void buf_dump_generate_path(char *path, size_t path_size)
|
||||
char buf[FN_REFLEN];
|
||||
|
||||
mysql_mutex_lock(&LOCK_global_system_variables);
|
||||
snprintf(buf, sizeof(buf), "%s%c%s", get_buf_dump_dir(),
|
||||
OS_PATH_SEPARATOR, srv_buf_dump_filename);
|
||||
snprintf(buf, sizeof buf, "%s/%s", get_buf_dump_dir(),
|
||||
srv_buf_dump_filename);
|
||||
mysql_mutex_unlock(&LOCK_global_system_variables);
|
||||
|
||||
os_file_type_t type;
|
||||
@ -205,19 +205,21 @@ static void buf_dump_generate_path(char *path, size_t path_size)
|
||||
char srv_data_home_full[FN_REFLEN];
|
||||
|
||||
my_realpath(srv_data_home_full, get_buf_dump_dir(), 0);
|
||||
const char *format;
|
||||
|
||||
if (srv_data_home_full[strlen(srv_data_home_full) - 1]
|
||||
== OS_PATH_SEPARATOR) {
|
||||
|
||||
snprintf(path, path_size, "%s%s",
|
||||
srv_data_home_full,
|
||||
srv_buf_dump_filename);
|
||||
} else {
|
||||
snprintf(path, path_size, "%s%c%s",
|
||||
srv_data_home_full,
|
||||
OS_PATH_SEPARATOR,
|
||||
srv_buf_dump_filename);
|
||||
switch (srv_data_home_full[strlen(srv_data_home_full) - 1]) {
|
||||
#ifdef _WIN32
|
||||
case '\\':
|
||||
#endif
|
||||
case '/':
|
||||
format = "%s%s";
|
||||
break;
|
||||
default:
|
||||
format = "%s/%s";
|
||||
}
|
||||
|
||||
snprintf(path, path_size, format,
|
||||
srv_data_home_full, srv_buf_dump_filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -407,11 +407,11 @@ dict_build_table_def_step(
|
||||
bool has_data_dir = DICT_TF_HAS_DATA_DIR(table->flags);
|
||||
ulint fsp_flags = dict_tf_to_fsp_flags(table->flags);
|
||||
ut_ad(!has_data_dir || table->data_dir_path);
|
||||
char* filepath = has_data_dir
|
||||
? fil_make_filepath(table->data_dir_path,
|
||||
table->name.m_name, IBD, true)
|
||||
: fil_make_filepath(NULL,
|
||||
table->name.m_name, IBD, false);
|
||||
char* filepath = fil_make_filepath(has_data_dir
|
||||
? table->data_dir_path
|
||||
: nullptr,
|
||||
table->name, IBD,
|
||||
has_data_dir);
|
||||
|
||||
/* We create a new single-table tablespace for the table.
|
||||
We initially let it be 4 pages:
|
||||
@ -423,7 +423,7 @@ dict_build_table_def_step(
|
||||
|
||||
dberr_t err;
|
||||
table->space = fil_ibd_create(
|
||||
space_id, table->name.m_name, filepath, fsp_flags,
|
||||
space_id, table->name, filepath, fsp_flags,
|
||||
FIL_IBD_FILE_INITIAL_SIZE,
|
||||
node->mode, node->key_id, &err);
|
||||
|
||||
|
@ -1603,16 +1603,12 @@ dict_table_rename_in_cache(
|
||||
/* Make sure the data_dir_path is set. */
|
||||
dict_get_and_save_data_dir_path(table, true);
|
||||
|
||||
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
|
||||
ut_a(table->data_dir_path);
|
||||
const char* data_dir = DICT_TF_HAS_DATA_DIR(table->flags)
|
||||
? table->data_dir_path : nullptr;
|
||||
ut_ad(data_dir || !DICT_TF_HAS_DATA_DIR(table->flags));
|
||||
|
||||
filepath = fil_make_filepath(
|
||||
table->data_dir_path, table->name.m_name,
|
||||
IBD, true);
|
||||
} else {
|
||||
filepath = fil_make_filepath(
|
||||
NULL, table->name.m_name, IBD, false);
|
||||
}
|
||||
filepath = fil_make_filepath(data_dir, table->name, IBD,
|
||||
data_dir != nullptr);
|
||||
|
||||
if (filepath == NULL) {
|
||||
return(DB_OUT_OF_MEMORY);
|
||||
@ -1637,11 +1633,14 @@ dict_table_rename_in_cache(
|
||||
|
||||
ut_ad(!table->is_temporary());
|
||||
|
||||
const fil_space_t::name_type new_space_name{
|
||||
new_name, strlen(new_name)};
|
||||
|
||||
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
|
||||
new_path = os_file_make_new_pathname(
|
||||
old_path, new_name);
|
||||
err = RemoteDatafile::create_link_file(
|
||||
new_name, new_path);
|
||||
new_space_name, new_path);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
ut_free(new_path);
|
||||
@ -1649,24 +1648,30 @@ dict_table_rename_in_cache(
|
||||
}
|
||||
} else {
|
||||
new_path = fil_make_filepath(
|
||||
NULL, new_name, IBD, false);
|
||||
NULL, new_space_name, IBD, false);
|
||||
}
|
||||
|
||||
/* New filepath must not exist. */
|
||||
err = table->space->rename(new_name, new_path, true,
|
||||
replace_new_file);
|
||||
err = table->space->rename(new_path, true, replace_new_file);
|
||||
ut_free(new_path);
|
||||
|
||||
/* If the tablespace is remote, a new .isl file was created
|
||||
If success, delete the old one. If not, delete the new one. */
|
||||
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
|
||||
RemoteDatafile::delete_link_file(
|
||||
err == DB_SUCCESS ? old_name : new_name);
|
||||
}
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
|
||||
RemoteDatafile::delete_link_file(
|
||||
new_space_name);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
|
||||
RemoteDatafile::delete_link_file(
|
||||
{old_name, strlen(old_name)});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Remove table from the hash tables of tables */
|
||||
|
@ -1050,15 +1050,12 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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="
|
||||
|
@ -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, nullptr);
|
||||
|
||||
ib::info() << "Deleting " << ibd_filepath;
|
||||
os_file_delete_if_exists(innodb_data_file_key, ibd_filepath, NULL);
|
||||
|
||||
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()
|
||||
|
@ -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,
|
||||
/** 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 (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;
|
||||
}
|
||||
|
||||
/** Create a link filename,
|
||||
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()
|
||||
@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_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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/** 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)
|
||||
{
|
||||
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)
|
||||
@param name tablespace name */
|
||||
void RemoteDatafile::delete_link_file(fil_space_t::name_type 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1583,7 +1583,7 @@ fts_drop_common_tables(
|
||||
|
||||
if (drop_orphan && err == DB_FAIL) {
|
||||
char* path = fil_make_filepath(
|
||||
NULL, table_name, IBD, false);
|
||||
NULL, table_name_t{table_name}, IBD, false);
|
||||
if (path != NULL) {
|
||||
os_file_delete_if_exists(
|
||||
innodb_data_file_key, path, NULL);
|
||||
@ -5652,17 +5652,18 @@ bool fts_check_aux_table(const char *name,
|
||||
|
||||
ut_ad(len <= MAX_FULL_NAME_LEN);
|
||||
ptr= static_cast<const char*>(memchr(name, '/', len));
|
||||
IF_WIN(if (!ptr) ptr= static_cast<const char*>(memchr(name, '\\', len)), );
|
||||
|
||||
if (ptr != NULL)
|
||||
{
|
||||
/* We will start the match after the '/' */
|
||||
++ptr;
|
||||
len = end - ptr;
|
||||
}
|
||||
if (!ptr)
|
||||
return false;
|
||||
|
||||
/* We will start the match after the '/' */
|
||||
++ptr;
|
||||
len= end - ptr;
|
||||
|
||||
/* All auxiliary tables are prefixed with "FTS_" and the name
|
||||
length will be at the very least greater than 20 bytes. */
|
||||
if (ptr && len > 20 && !memcmp(ptr, "FTS_", 4))
|
||||
if (len > 24 && !memcmp(ptr, "FTS_", 4))
|
||||
{
|
||||
/* Skip the prefix. */
|
||||
ptr+= 4;
|
||||
@ -5706,6 +5707,11 @@ bool fts_check_aux_table(const char *name,
|
||||
ut_a(end > ptr);
|
||||
len= end - ptr;
|
||||
|
||||
if (len <= 4)
|
||||
return false;
|
||||
|
||||
len-= 4; /* .ibd suffix */
|
||||
|
||||
if (len > 7)
|
||||
return false;
|
||||
|
||||
@ -5740,8 +5746,9 @@ static void fil_get_fts_spaces(fts_space_set_t& fts_space_set)
|
||||
index_id_t index_id= 0;
|
||||
table_id_t table_id= 0;
|
||||
|
||||
if (space.purpose == FIL_TYPE_TABLESPACE
|
||||
&& fts_check_aux_table(space.name, &table_id, &index_id))
|
||||
if (space.purpose == FIL_TYPE_TABLESPACE && space.id &&
|
||||
space.chain.start &&
|
||||
fts_check_aux_table(space.chain.start->name, &table_id, &index_id))
|
||||
fts_space_set.insert(std::make_pair(table_id, index_id));
|
||||
}
|
||||
|
||||
@ -5823,17 +5830,14 @@ static void fts_drop_all_aux_tables(trx_t *trx, fts_table_t *fts_table)
|
||||
fts_get_table_name(fts_table, fts_table_name, true);
|
||||
|
||||
/* Drop all fts aux and common table */
|
||||
dberr_t err= fts_drop_table(trx, fts_table_name);
|
||||
if (fts_drop_table(trx, fts_table_name) != DB_FAIL)
|
||||
continue;
|
||||
|
||||
if (err == DB_FAIL)
|
||||
if (char *path= fil_make_filepath(nullptr, table_name_t{fts_table_name},
|
||||
IBD, false))
|
||||
{
|
||||
char *path= fil_make_filepath(NULL, fts_table_name, IBD, false);
|
||||
|
||||
if (path != NULL)
|
||||
{
|
||||
os_file_delete_if_exists(innodb_data_file_key, path , NULL);
|
||||
ut_free(path);
|
||||
}
|
||||
os_file_delete_if_exists(innodb_data_file_key, path, nullptr);
|
||||
ut_free(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -758,7 +758,6 @@ innodb_tmpdir_validate(
|
||||
return(1);
|
||||
}
|
||||
|
||||
os_normalize_path(alter_tmp_dir);
|
||||
my_realpath(tmp_abs_path, alter_tmp_dir, 0);
|
||||
size_t tmp_abs_len = strlen(tmp_abs_path);
|
||||
|
||||
@ -3292,8 +3291,6 @@ static int innodb_init_params()
|
||||
{
|
||||
DBUG_ENTER("innodb_init_params");
|
||||
|
||||
static char current_dir[3];
|
||||
char *default_path;
|
||||
ulong num_pll_degree;
|
||||
|
||||
/* Check that values don't overflow on 32-bit systems. */
|
||||
@ -3385,19 +3382,11 @@ static int innodb_init_params()
|
||||
Note that when using the embedded server, the datadirectory is not
|
||||
necessarily the current directory of this program. */
|
||||
|
||||
if (mysqld_embedded) {
|
||||
default_path = mysql_real_data_home;
|
||||
} else {
|
||||
/* It's better to use current lib, to keep paths short */
|
||||
current_dir[0] = FN_CURLIB;
|
||||
current_dir[1] = FN_LIBCHAR;
|
||||
current_dir[2] = 0;
|
||||
default_path = current_dir;
|
||||
}
|
||||
|
||||
ut_a(default_path);
|
||||
|
||||
fil_path_to_mysql_datadir = default_path;
|
||||
fil_path_to_mysql_datadir =
|
||||
#ifndef HAVE_REPLICATION
|
||||
mysqld_embedded ? mysql_real_data_home :
|
||||
#endif
|
||||
"./";
|
||||
|
||||
/* Set InnoDB initialization parameters according to the values
|
||||
read from MySQL .cnf file */
|
||||
@ -3405,7 +3394,8 @@ static int innodb_init_params()
|
||||
/* The default dir for data files is the datadir of MySQL */
|
||||
|
||||
srv_data_home = innobase_data_home_dir
|
||||
? innobase_data_home_dir : default_path;
|
||||
? innobase_data_home_dir
|
||||
: const_cast<char*>(fil_path_to_mysql_datadir);
|
||||
#ifdef WITH_WSREP
|
||||
/* If we use the wsrep API, then we need to tell the server
|
||||
the path to the data files (for passing it to the SST scripts): */
|
||||
@ -3437,7 +3427,6 @@ static int innodb_init_params()
|
||||
srv_sys_space.set_flags(FSP_FLAGS_PAGE_SSIZE());
|
||||
}
|
||||
|
||||
srv_sys_space.set_name("innodb_system");
|
||||
srv_sys_space.set_path(srv_data_home);
|
||||
|
||||
/* Supports raw devices */
|
||||
@ -3447,7 +3436,6 @@ static int innodb_init_params()
|
||||
DBUG_RETURN(HA_ERR_INITIALIZATION);
|
||||
}
|
||||
|
||||
srv_tmp_space.set_name("innodb_temporary");
|
||||
srv_tmp_space.set_path(srv_data_home);
|
||||
|
||||
/* Temporary tablespace is in full crc32 format. */
|
||||
@ -3462,8 +3450,8 @@ static int innodb_init_params()
|
||||
|
||||
/* Perform all sanity check before we take action of deleting files*/
|
||||
if (srv_sys_space.intersection(&srv_tmp_space)) {
|
||||
sql_print_error("%s and %s file names seem to be the same.",
|
||||
srv_tmp_space.name(), srv_sys_space.name());
|
||||
sql_print_error("innodb_temporary and innodb_system"
|
||||
" file names seem to be the same.");
|
||||
DBUG_RETURN(HA_ERR_INITIALIZATION);
|
||||
}
|
||||
|
||||
@ -3472,11 +3460,9 @@ static int innodb_init_params()
|
||||
|
||||
/* ------------ UNDO tablespaces files ---------------------*/
|
||||
if (!srv_undo_dir) {
|
||||
srv_undo_dir = default_path;
|
||||
srv_undo_dir = const_cast<char*>(fil_path_to_mysql_datadir);
|
||||
}
|
||||
|
||||
os_normalize_path(srv_undo_dir);
|
||||
|
||||
if (strchr(srv_undo_dir, ';')) {
|
||||
sql_print_error("syntax error in innodb_undo_directory");
|
||||
DBUG_RETURN(HA_ERR_INITIALIZATION);
|
||||
@ -3487,11 +3473,10 @@ static int innodb_init_params()
|
||||
/* The default dir for log files is the datadir of MySQL */
|
||||
|
||||
if (!srv_log_group_home_dir) {
|
||||
srv_log_group_home_dir = default_path;
|
||||
srv_log_group_home_dir
|
||||
= const_cast<char*>(fil_path_to_mysql_datadir);
|
||||
}
|
||||
|
||||
os_normalize_path(srv_log_group_home_dir);
|
||||
|
||||
if (strchr(srv_log_group_home_dir, ';')) {
|
||||
sql_print_error("syntax error in innodb_log_group_home_dir");
|
||||
DBUG_RETURN(HA_ERR_INITIALIZATION);
|
||||
|
@ -6495,7 +6495,19 @@ static int i_s_sys_tablespaces_fill(THD *thd, const fil_space_t &s, TABLE *t)
|
||||
Field **fields= t->field;
|
||||
|
||||
OK(fields[SYS_TABLESPACES_SPACE]->store(s.id, true));
|
||||
OK(field_store_string(fields[SYS_TABLESPACES_NAME], s.name));
|
||||
{
|
||||
Field *f= fields[SYS_TABLESPACES_NAME];
|
||||
const auto name= s.name();
|
||||
if (name.data())
|
||||
{
|
||||
OK(f->store(name.data(), name.size(), system_charset_info));
|
||||
f->set_notnull();
|
||||
}
|
||||
else
|
||||
f->set_notnull();
|
||||
}
|
||||
|
||||
fields[SYS_TABLESPACES_NAME]->set_null();
|
||||
OK(fields[SYS_TABLESPACES_FLAGS]->store(s.flags, true));
|
||||
OK(field_store_string(fields[SYS_TABLESPACES_ROW_FORMAT], row_format));
|
||||
const char *filepath= s.chain.start->name;
|
||||
@ -6711,8 +6723,17 @@ i_s_dict_fill_tablespaces_encryption(
|
||||
|
||||
OK(fields[TABLESPACES_ENCRYPTION_SPACE]->store(space->id, true));
|
||||
|
||||
OK(field_store_string(fields[TABLESPACES_ENCRYPTION_NAME],
|
||||
space->name));
|
||||
{
|
||||
const auto name = space->name();
|
||||
if (name.data()) {
|
||||
OK(fields[TABLESPACES_ENCRYPTION_NAME]->store(
|
||||
name.data(), name.size(),
|
||||
system_charset_info));
|
||||
fields[TABLESPACES_ENCRYPTION_NAME]->set_notnull();
|
||||
} else {
|
||||
fields[TABLESPACES_ENCRYPTION_NAME]->set_null();
|
||||
}
|
||||
}
|
||||
|
||||
OK(fields[TABLESPACES_ENCRYPTION_ENCRYPTION_SCHEME]->store(
|
||||
status.scheme, true));
|
||||
|
@ -39,6 +39,7 @@ Created 10/25/1995 Heikki Tuuri
|
||||
#include "log0recv.h"
|
||||
#include "dict0types.h"
|
||||
#include "ilist.h"
|
||||
#include "span.h"
|
||||
#include <set>
|
||||
#include <mutex>
|
||||
|
||||
@ -353,7 +354,6 @@ struct fil_space_t final
|
||||
}
|
||||
ulint id; /*!< space id */
|
||||
hash_node_t hash; /*!< hash chain node */
|
||||
char* name; /*!< Tablespace name */
|
||||
lsn_t max_lsn;
|
||||
/*!< LSN of the most recent
|
||||
fil_names_write_if_was_clean().
|
||||
@ -490,15 +490,14 @@ 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*
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -1240,31 +1240,34 @@ os_file_punch_hole(
|
||||
os_offset_t len)
|
||||
MY_ATTRIBUTE((warn_unused_result));
|
||||
|
||||
/** Normalizes a directory path for the current OS:
|
||||
On Windows, we convert '/' to '\', else we convert '\' to '/'.
|
||||
@param[in,out] str A null-terminated directory and file path */
|
||||
void os_normalize_path(char* str);
|
||||
|
||||
/* Determine if a path is an absolute path or not.
|
||||
@param[in] OS directory or file path to evaluate
|
||||
@retval true if an absolute path
|
||||
@retval false if a relative path */
|
||||
UNIV_INLINE
|
||||
bool
|
||||
is_absolute_path(
|
||||
const char* path)
|
||||
inline bool is_absolute_path(const char *path)
|
||||
{
|
||||
if (path[0] == OS_PATH_SEPARATOR) {
|
||||
return(true);
|
||||
}
|
||||
switch (path[0]) {
|
||||
#ifdef _WIN32
|
||||
case '\0':
|
||||
return false;
|
||||
case '\\':
|
||||
#endif
|
||||
case '/':
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (path[1] == ':' && path[2] == OS_PATH_SEPARATOR) {
|
||||
return(true);
|
||||
}
|
||||
if (path[1] == ':')
|
||||
{
|
||||
switch (path[2]) {
|
||||
case '/':
|
||||
case '\\':
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
#include "os0file.ic"
|
||||
|
@ -531,22 +531,6 @@ it is read or written. */
|
||||
/* Compile-time constant of the given array's size. */
|
||||
#define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
/* The return type from a thread's start function differs between Unix and
|
||||
Windows, so define a typedef for it and a macro to use at the end of such
|
||||
functions. */
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef DWORD os_thread_ret_t;
|
||||
# define OS_THREAD_DUMMY_RETURN return(0)
|
||||
# define OS_PATH_SEPARATOR '\\'
|
||||
# define OS_PATH_SEPARATOR_ALT '/'
|
||||
#else
|
||||
typedef void* os_thread_ret_t;
|
||||
# define OS_THREAD_DUMMY_RETURN return(NULL)
|
||||
# define OS_PATH_SEPARATOR '/'
|
||||
# define OS_PATH_SEPARATOR_ALT '\\'
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "db0err.h"
|
||||
#include "ut0dbg.h"
|
||||
|
@ -135,7 +135,7 @@ 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" \
|
||||
|
@ -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
|
||||
|
@ -4581,7 +4581,7 @@ static void lock_rec_block_validate(const page_id_t page_id)
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
ib::error() << "Lock rec block validate failed for tablespace "
|
||||
<< space->name
|
||||
<< space->chain.start->name
|
||||
<< page_id << " err " << err;
|
||||
}
|
||||
|
||||
|
@ -1306,11 +1306,15 @@ std::string get_log_file_path(const char *filename)
|
||||
path.reserve(size);
|
||||
path.assign(srv_log_group_home_dir);
|
||||
|
||||
std::replace(path.begin(), path.end(), OS_PATH_SEPARATOR_ALT,
|
||||
OS_PATH_SEPARATOR);
|
||||
|
||||
if (path.back() != OS_PATH_SEPARATOR)
|
||||
path.push_back(OS_PATH_SEPARATOR);
|
||||
switch (path.back()) {
|
||||
#ifdef _WIN32
|
||||
case '\\':
|
||||
#endif
|
||||
case '/':
|
||||
break;
|
||||
default:
|
||||
path.push_back('/');
|
||||
}
|
||||
path.append(filename);
|
||||
|
||||
return path;
|
||||
|
@ -807,7 +807,6 @@ fil_name_process(char* name, ulint len, ulint space_id, bool deleted)
|
||||
further checks can ensure that a FILE_MODIFY record was
|
||||
scanned before applying any page records for the space_id. */
|
||||
|
||||
os_normalize_path(name);
|
||||
const file_name_t fname(std::string(name, len), deleted);
|
||||
std::pair<recv_spaces_t::iterator,bool> p = recv_spaces.emplace(
|
||||
space_id, fname);
|
||||
@ -2853,22 +2852,8 @@ 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;
|
||||
|
@ -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 '/'. */
|
||||
const char *last_slash= strrchr(tablename, '/');
|
||||
const char *base_name= last_slash ? last_slash + 1 : tablename;
|
||||
|
||||
/* 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(old_path, '/');
|
||||
#ifdef _WIN32
|
||||
if (const char *last= strrchr(old_path, '\\'))
|
||||
if (last > last_slash)
|
||||
last_slash= last;
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
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. */
|
||||
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);
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3761,16 +3761,15 @@ fil_tablespace_iterate(
|
||||
/* Make sure the data_dir_path is set. */
|
||||
dict_get_and_save_data_dir_path(table, false);
|
||||
|
||||
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
|
||||
ut_a(table->data_dir_path);
|
||||
ut_ad(!DICT_TF_HAS_DATA_DIR(table->flags) || table->data_dir_path);
|
||||
|
||||
filepath = fil_make_filepath(
|
||||
table->data_dir_path, table->name.m_name, IBD, true);
|
||||
} else {
|
||||
filepath = fil_make_filepath(
|
||||
NULL, table->name.m_name, IBD, false);
|
||||
}
|
||||
const char *data_dir_path = DICT_TF_HAS_DATA_DIR(table->flags)
|
||||
? table->data_dir_path : nullptr;
|
||||
|
||||
filepath = fil_make_filepath(data_dir_path,
|
||||
{table->name.m_name,
|
||||
strlen(table->name.m_name)},
|
||||
IBD, data_dir_path != nullptr);
|
||||
if (!filepath) {
|
||||
return(DB_OUT_OF_MEMORY);
|
||||
} else {
|
||||
@ -4095,16 +4094,10 @@ row_import_for_mysql(
|
||||
dict_get_and_save_data_dir_path(table, true);
|
||||
|
||||
ut_ad(!DICT_TF_HAS_DATA_DIR(table->flags) || table->data_dir_path);
|
||||
|
||||
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
|
||||
ut_a(table->data_dir_path);
|
||||
|
||||
filepath = fil_make_filepath(
|
||||
table->data_dir_path, table->name.m_name, IBD, true);
|
||||
} else {
|
||||
filepath = fil_make_filepath(
|
||||
NULL, table->name.m_name, IBD, false);
|
||||
}
|
||||
const char *data_dir_path = DICT_TF_HAS_DATA_DIR(table->flags)
|
||||
? table->data_dir_path : nullptr;
|
||||
filepath = fil_make_filepath(data_dir_path, table->name, IBD,
|
||||
data_dir_path != nullptr);
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
"ib_import_OOM_15",
|
||||
|
@ -3359,7 +3359,9 @@ row_drop_table_for_mysql(
|
||||
if (table->space != fil_system.sys_space) {
|
||||
/* Delete the link file if used. */
|
||||
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
|
||||
RemoteDatafile::delete_link_file(name);
|
||||
RemoteDatafile::delete_link_file(
|
||||
{table->name.m_name,
|
||||
strlen(table->name.m_name)});
|
||||
}
|
||||
}
|
||||
|
||||
@ -3648,15 +3650,14 @@ 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) {
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user