summaryrefslogtreecommitdiff
path: root/extra/mariabackup
diff options
context:
space:
mode:
Diffstat (limited to 'extra/mariabackup')
-rw-r--r--extra/mariabackup/CMakeLists.txt7
-rw-r--r--extra/mariabackup/backup_copy.cc151
-rw-r--r--extra/mariabackup/backup_debug.h18
-rw-r--r--extra/mariabackup/backup_mysql.cc183
-rw-r--r--extra/mariabackup/changed_page_bitmap.cc11
-rw-r--r--extra/mariabackup/ds_stdout.cc2
-rw-r--r--extra/mariabackup/fil_cur.cc46
-rw-r--r--extra/mariabackup/xbstream_read.cc2
-rw-r--r--extra/mariabackup/xbstream_write.cc2
-rw-r--r--extra/mariabackup/xtrabackup.cc982
-rw-r--r--extra/mariabackup/xtrabackup.h12
11 files changed, 716 insertions, 700 deletions
diff --git a/extra/mariabackup/CMakeLists.txt b/extra/mariabackup/CMakeLists.txt
index 0ebfba54534..a7a35c58ac3 100644
--- a/extra/mariabackup/CMakeLists.txt
+++ b/extra/mariabackup/CMakeLists.txt
@@ -46,12 +46,6 @@ ADD_DEFINITIONS(-UMYSQL_SERVER)
# xtrabackup binary
########################################################################
-IF(WIN32)
- SET(NT_SERVICE_SOURCE ${PROJECT_SOURCE_DIR}/sql/nt_servc.cc)
-ELSE()
- SET(NT_SERVICE_SOURCE)
-ENDIF()
-
ADD_DEFINITIONS(-DPCRE_STATIC=1)
ADD_DEFINITIONS(${SSL_DEFINES})
MYSQL_ADD_EXECUTABLE(mariadb-backup
@@ -76,7 +70,6 @@ MYSQL_ADD_EXECUTABLE(mariadb-backup
encryption_plugin.cc
${PROJECT_BINARY_DIR}/sql/sql_builtin.cc
${PROJECT_SOURCE_DIR}/sql/net_serv.cc
- ${NT_SERVICE_SOURCE}
${PROJECT_SOURCE_DIR}/libmysqld/libmysql.c
COMPONENT backup
)
diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc
index 27c4ba29c91..9845d39d493 100644
--- a/extra/mariabackup/backup_copy.cc
+++ b/extra/mariabackup/backup_copy.cc
@@ -55,12 +55,18 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
#include "xtrabackup.h"
#include "common.h"
#include "backup_copy.h"
+#include "backup_debug.h"
#include "backup_mysql.h"
#include <btr0btr.h>
#ifdef _WIN32
#include <direct.h> /* rmdir */
#endif
+#ifdef _WIN32
+#include <aclapi.h>
+#endif
+
+
#define ROCKSDB_BACKUP_DIR "#rocksdb"
/* list of files to sync for --rsync mode */
@@ -127,7 +133,6 @@ struct datadir_thread_ctxt_t {
uint n_thread;
uint *count;
pthread_mutex_t* count_mutex;
- os_thread_id_t id;
bool ret;
};
@@ -272,7 +277,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;
@@ -560,8 +564,8 @@ datafile_read(datafile_cur_t *cursor)
}
if (os_file_read(IORequestRead,
- cursor->file, cursor->buf, cursor->buf_offset,
- to_read) != DB_SUCCESS) {
+ cursor->file, cursor->buf, cursor->buf_offset,
+ to_read, nullptr) != DB_SUCCESS) {
return(XB_FIL_CUR_ERROR);
}
@@ -944,7 +948,7 @@ backup_file_printf(const char *filename, const char *fmt, ...)
static
bool
-run_data_threads(datadir_iter_t *it, os_thread_func_t func, uint n)
+run_data_threads(datadir_iter_t *it, void (*func)(datadir_thread_ctxt_t *ctxt), uint n)
{
datadir_thread_ctxt_t *data_threads;
uint i, count;
@@ -962,12 +966,12 @@ run_data_threads(datadir_iter_t *it, os_thread_func_t func, uint n)
data_threads[i].n_thread = i + 1;
data_threads[i].count = &count;
data_threads[i].count_mutex = &count_mutex;
- data_threads[i].id = os_thread_create(func, data_threads + i);
+ std::thread(func, data_threads + i).detach();
}
/* Wait for threads to exit */
while (1) {
- os_thread_sleep(100000);
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
pthread_mutex_lock(&count_mutex);
if (count == 0) {
pthread_mutex_unlock(&count_mutex);
@@ -991,64 +995,6 @@ run_data_threads(datadir_iter_t *it, os_thread_func_t func, uint n)
return(ret);
}
-#ifdef _WIN32
-#include <windows.h>
-#include <accctrl.h>
-#include <aclapi.h>
-/*
- On Windows, fix permission of the file after "copyback"
- We assume that after copyback, mysqld will run as service as NetworkService
- user, thus well give full permission on given file to that user.
-*/
-
-static int fix_win_file_permissions(const char *file)
-{
- struct {
- TOKEN_USER tokenUser;
- BYTE buffer[SECURITY_MAX_SID_SIZE];
- } tokenInfoBuffer;
- HANDLE hFile = CreateFile(file, READ_CONTROL | WRITE_DAC, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (hFile == INVALID_HANDLE_VALUE)
- return -1;
- ACL* pOldDACL;
- SECURITY_DESCRIPTOR* pSD = NULL;
- EXPLICIT_ACCESS ea = { 0 };
- PSID pSid = NULL;
-
- GetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL,
- &pOldDACL, NULL, (void**)&pSD);
- DWORD size = SECURITY_MAX_SID_SIZE;
- pSid = (PSID)tokenInfoBuffer.buffer;
- if (!CreateWellKnownSid(WinNetworkServiceSid, NULL, pSid,
- &size))
- {
- return 1;
- }
- ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
- ea.Trustee.ptstrName = (LPTSTR)pSid;
-
- ea.grfAccessMode = GRANT_ACCESS;
- ea.grfAccessPermissions = GENERIC_ALL;
- ea.grfInheritance = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
- ea.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
- ACL* pNewDACL = 0;
- DWORD err = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
- if (!err)
- {
- DBUG_ASSERT(pNewDACL);
- SetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL,
- pNewDACL, NULL);
- LocalFree((HLOCAL)pNewDACL);
- }
- if (pSD != NULL)
- LocalFree((HLOCAL)pSD);
- CloseHandle(hFile);
- return 0;
-}
-
-#endif
-
/************************************************************************
Copy file for backup/restore.
@@ -1099,10 +1045,6 @@ copy_file(ds_ctxt_t *datasink,
/* close */
msg(thread_n," ...done");
datafile_close(&cursor);
-#ifdef _WIN32
- if (xtrabackup_copy_back || xtrabackup_move_back)
- ut_a(!fix_win_file_permissions(dstfile->path));
-#endif
if (ds_close(dstfile)) {
goto error_close;
}
@@ -1175,10 +1117,6 @@ move_file(ds_ctxt_t *datasink,
errbuf);
return(false);
}
-#ifdef _WIN32
- if (xtrabackup_copy_back || xtrabackup_move_back)
- ut_a(!fix_win_file_permissions(dst_file_path_abs));
-#endif
msg(thread_n," ...done");
return(true);
@@ -1201,13 +1139,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;
@@ -1511,6 +1448,13 @@ bool backup_start(CorruptedPages &corrupted_pages)
msg("Waiting for log copy thread to read lsn %llu", (ulonglong)server_lsn_after_lock);
backup_wait_for_lsn(server_lsn_after_lock);
+ DBUG_EXECUTE_FOR_KEY("sleep_after_waiting_for_lsn", {},
+ {
+ ulong milliseconds = strtoul(dbug_val, NULL, 10);
+ msg("sleep_after_waiting_for_lsn");
+ my_sleep(milliseconds*1000UL);
+ });
+
backup_fix_ddl(corrupted_pages);
// There is no need to stop slave thread before coping non-Innodb data when
@@ -1850,6 +1794,19 @@ copy_back()
return(false);
}
}
+
+#ifdef _WIN32
+ /* Initialize security descriptor for the new directories
+ to be the same as for datadir */
+ DWORD res = GetNamedSecurityInfoA(mysql_data_home,
+ SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL,
+ &my_dir_security_attributes.lpSecurityDescriptor);
+ if (res != ERROR_SUCCESS) {
+ msg("Unable to read security descriptor of %s",mysql_data_home);
+ }
+#endif
+
if (srv_undo_dir && *srv_undo_dir
&& !directory_exists(srv_undo_dir, true)) {
return(false);
@@ -1884,7 +1841,6 @@ copy_back()
}
srv_max_n_threads = 1000;
- sync_check_init();
/* copy undo tablespaces */
@@ -1947,9 +1903,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;
}
@@ -1972,7 +1927,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
@@ -2032,23 +1986,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 */
@@ -2075,7 +2025,6 @@ cleanup:
ds_data = NULL;
- sync_check_close();
return(ret);
}
@@ -2123,13 +2072,10 @@ decrypt_decompress_file(const char *filepath, uint thread_n)
return(true);
}
-static
-os_thread_ret_t STDCALL
-decrypt_decompress_thread_func(void *arg)
+static void decrypt_decompress_thread_func(datadir_thread_ctxt_t *ctxt)
{
bool ret = true;
datadir_node_t node;
- datadir_thread_ctxt_t *ctxt = (datadir_thread_ctxt_t *)(arg);
datadir_node_init(&node);
@@ -2159,9 +2105,6 @@ cleanup:
pthread_mutex_unlock(ctxt->count_mutex);
ctxt->ret = ret;
-
- os_thread_exit();
- OS_THREAD_DUMMY_RETURN;
}
bool
@@ -2171,7 +2114,6 @@ decrypt_decompress()
datadir_iter_t *it = NULL;
srv_max_n_threads = 1000;
- sync_check_init();
/* cd to backup directory */
if (my_setwd(xtrabackup_target_dir, MYF(MY_WME)))
@@ -2200,8 +2142,6 @@ decrypt_decompress()
ds_data = NULL;
- sync_check_close();
-
return(ret);
}
@@ -2222,7 +2162,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;
@@ -2239,7 +2186,7 @@ static bool backup_files_from_datadir(const char *dir_path)
unlink(info.name);
std::string full_path(dir_path);
- full_path.append(1, OS_PATH_SEPARATOR).append(info.name);
+ full_path.append(1, '/').append(info.name);
if (!(ret = copy_file(ds_data, full_path.c_str() , info.name, 1)))
break;
}
diff --git a/extra/mariabackup/backup_debug.h b/extra/mariabackup/backup_debug.h
index cefbc287361..777b4f4adeb 100644
--- a/extra/mariabackup/backup_debug.h
+++ b/extra/mariabackup/backup_debug.h
@@ -1,7 +1,7 @@
#pragma once
#include "my_dbug.h"
#ifndef DBUG_OFF
-extern char *dbug_mariabackup_get_val(const char *event, const char *key);
+char *dbug_mariabackup_get_val(const char *event, fil_space_t::name_type key);
/*
In debug mode, execute SQL statement that was passed via environment.
To use this facility, you need to
@@ -14,19 +14,11 @@ To use this facility, you need to
for the variable)
3. start mariabackup with --dbug=+d,debug_mariabackup_events
*/
-extern void dbug_mariabackup_event(
- const char *event,const char *key);
-#define DBUG_MARIABACKUP_EVENT(A, B) \
- DBUG_EXECUTE_IF("mariabackup_events", \
- dbug_mariabackup_event(A,B););
-#define DBUG_EXECUTE_FOR_KEY(EVENT, KEY, CODE) \
- DBUG_EXECUTE_IF("mariabackup_inject_code", {\
- char *dbug_val = dbug_mariabackup_get_val(EVENT, KEY); \
- if (dbug_val && *dbug_val) CODE \
- })
+#define DBUG_EXECUTE_FOR_KEY(EVENT, KEY, CODE) \
+ DBUG_EXECUTE_IF("mariabackup_inject_code", \
+ { char *dbug_val= dbug_mariabackup_get_val(EVENT, KEY); \
+ if (dbug_val) CODE })
#else
-#define DBUG_MARIABACKUP_EVENT(A,B)
-#define DBUG_MARIABACKUP_EVENT_LOCK(A,B)
#define DBUG_EXECUTE_FOR_KEY(EVENT, KEY, CODE)
#endif
diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc
index ef79c8d561e..9ddbb6387b9 100644
--- a/extra/mariabackup/backup_mysql.cc
+++ b/extra/mariabackup/backup_mysql.cc
@@ -76,9 +76,10 @@ bool have_multi_threaded_slave = false;
bool have_gtid_slave = false;
/* Kill long selects */
-os_event_t kill_query_thread_started;
-os_event_t kill_query_thread_stopped;
-os_event_t kill_query_thread_stop;
+static mysql_mutex_t kill_query_thread_mutex;
+static bool kill_query_thread_running, kill_query_thread_stopping;
+static mysql_cond_t kill_query_thread_stopped;
+static mysql_cond_t kill_query_thread_stop;
bool sql_thread_started = false;
char *mysql_slave_position = NULL;
@@ -103,7 +104,7 @@ xb_mysql_connect()
sprintf(mysql_port_str, "%d", opt_port);
if (connection == NULL) {
- msg("Failed to init MySQL struct: %s.",
+ msg("Failed to init MariaDB struct: %s.",
mysql_error(connection));
return(NULL);
}
@@ -126,7 +127,7 @@ xb_mysql_connect()
mysql_options(connection, MYSQL_OPT_PROTOCOL, &opt_protocol);
mysql_options(connection,MYSQL_SET_CHARSET_NAME, "utf8");
- msg("Connecting to server host: %s, user: %s, password: %s, "
+ msg("Connecting to MariaDB server host: %s, user: %s, password: %s, "
"port: %s, socket: %s", opt_host ? opt_host : "localhost",
opt_user ? opt_user : "not set",
opt_password ? "set" : "not set",
@@ -153,7 +154,7 @@ xb_mysql_connect()
opt_password,
"" /*database*/, opt_port,
opt_socket, 0)) {
- msg("Failed to connect to server: %s.", mysql_error(connection));
+ msg("Failed to connect to MariaDB server: %s.", mysql_error(connection));
mysql_close(connection);
return(NULL);
}
@@ -471,7 +472,7 @@ bool get_mysql_vars(MYSQL *connection)
}
if (!directory_exists(datadir_var, false))
{
- msg("Warning: MySQL variable 'datadir' points to "
+ msg("Warning: MariaDB variable 'datadir' points to "
"nonexistent directory '%s'",
datadir_var);
}
@@ -808,7 +809,7 @@ wait_for_no_updates(MYSQL *connection, uint timeout, uint threshold)
if (!have_queries_to_wait_for(connection, threshold)) {
return(true);
}
- os_thread_sleep(1000000);
+ std::this_thread::sleep_for(std::chrono::seconds(1));
}
msg("Unable to obtain lock. Please try again later.");
@@ -816,74 +817,70 @@ wait_for_no_updates(MYSQL *connection, uint timeout, uint threshold)
return(false);
}
-static
-os_thread_ret_t
-DECLARE_THREAD(kill_query_thread)(
-/*===============*/
- void *arg __attribute__((unused)))
+static void kill_query_thread()
{
- MYSQL *mysql;
- time_t start_time;
-
- start_time = time(NULL);
+ mysql_mutex_lock(&kill_query_thread_mutex);
- os_event_set(kill_query_thread_started);
+ msg("Kill query timeout %d seconds.", opt_kill_long_queries_timeout);
- msg("Kill query timeout %d seconds.",
- opt_kill_long_queries_timeout);
-
- while (time(NULL) - start_time <
- (time_t)opt_kill_long_queries_timeout) {
- if (os_event_wait_time(kill_query_thread_stop, 1000) !=
- OS_SYNC_TIME_EXCEEDED) {
- goto stop_thread;
- }
- }
-
- if ((mysql = xb_mysql_connect()) == NULL) {
- msg("Error: kill query thread failed");
- goto stop_thread;
- }
-
- while (true) {
- kill_long_queries(mysql, time(NULL) - start_time);
- if (os_event_wait_time(kill_query_thread_stop, 1000) !=
- OS_SYNC_TIME_EXCEEDED) {
- break;
- }
- }
+ time_t start_time= time(nullptr);
+ timespec abstime;
+ set_timespec(abstime, opt_kill_long_queries_timeout);
- mysql_close(mysql);
+ while (!kill_query_thread_stopping)
+ if (!mysql_cond_timedwait(&kill_query_thread_stop,
+ &kill_query_thread_mutex, &abstime))
+ goto func_exit;
-stop_thread:
- msg("Kill query thread stopped");
+ if (MYSQL *mysql= xb_mysql_connect())
+ {
+ do
+ {
+ kill_long_queries(mysql, time(nullptr) - start_time);
+ set_timespec(abstime, 1);
+ }
+ while (mysql_cond_timedwait(&kill_query_thread_stop,
+ &kill_query_thread_mutex, &abstime) &&
+ !kill_query_thread_stopping);
+ mysql_close(mysql);
+ }
+ else
+ msg("Error: kill query thread failed");
- os_event_set(kill_query_thread_stopped);
+func_exit:
+ msg("Kill query thread stopped");
- os_thread_exit();
- OS_THREAD_DUMMY_RETURN;
+ kill_query_thread_running= false;
+ mysql_cond_signal(&kill_query_thread_stopped);
+ mysql_mutex_unlock(&kill_query_thread_mutex);
}
-static
-void
-start_query_killer()
+static void start_query_killer()
{
- kill_query_thread_stop = os_event_create(0);
- kill_query_thread_started = os_event_create(0);
- kill_query_thread_stopped = os_event_create(0);
-
- os_thread_create(kill_query_thread);
-
- os_event_wait(kill_query_thread_started);
+ ut_ad(!kill_query_thread_running);
+ kill_query_thread_running= true;
+ kill_query_thread_stopping= false;
+ mysql_mutex_init(0, &kill_query_thread_mutex, nullptr);
+ mysql_cond_init(0, &kill_query_thread_stop, nullptr);
+ mysql_cond_init(0, &kill_query_thread_stopped, nullptr);
+ std::thread(kill_query_thread).detach();
}
-static
-void
-stop_query_killer()
+static void stop_query_killer()
{
- os_event_set(kill_query_thread_stop);
- os_event_wait_time(kill_query_thread_stopped, 60000);
+ mysql_mutex_lock(&kill_query_thread_mutex);
+ kill_query_thread_stopping= true;
+ mysql_cond_signal(&kill_query_thread_stop);
+
+ do
+ mysql_cond_wait(&kill_query_thread_stopped, &kill_query_thread_mutex);
+ while (kill_query_thread_running);
+
+ mysql_cond_destroy(&kill_query_thread_stop);
+ mysql_cond_destroy(&kill_query_thread_stopped);
+ mysql_mutex_unlock(&kill_query_thread_mutex);
+ mysql_mutex_destroy(&kill_query_thread_mutex);
}
@@ -934,7 +931,9 @@ bool lock_tables(MYSQL *connection)
}
xb_mysql_query(connection, "BACKUP STAGE START", true);
+ DBUG_MARIABACKUP_EVENT("after_backup_stage_start", {});
xb_mysql_query(connection, "BACKUP STAGE BLOCK_COMMIT", true);
+ DBUG_MARIABACKUP_EVENT("after_backup_stage_block_commit", {});
/* Set the maximum supported session value for
lock_wait_timeout to prevent unnecessary timeouts when the
global value is changed from the default */
@@ -979,8 +978,9 @@ unlock_all(MYSQL *connection)
if (opt_debug_sleep_before_unlock) {
msg("Debug sleep for %u seconds",
opt_debug_sleep_before_unlock);
- os_thread_sleep(opt_debug_sleep_before_unlock * 1000);
- }
+ std::this_thread::sleep_for(
+ std::chrono::milliseconds(opt_debug_sleep_before_unlock));
+ }
msg("Executing BACKUP STAGE END");
xb_mysql_query(connection, "BACKUP STAGE END", false);
@@ -1058,7 +1058,7 @@ wait_for_safe_slave(MYSQL *connection)
"remaining)...", sleep_time, n_attempts);
xb_mysql_query(connection, "START SLAVE SQL_THREAD", false);
- os_thread_sleep(sleep_time * 1000000);
+ std::this_thread::sleep_for(std::chrono::seconds(sleep_time));
xb_mysql_query(connection, "STOP SLAVE SQL_THREAD", false);
open_temp_tables = get_open_temp_tables(connection);
@@ -1151,22 +1151,23 @@ public:
bool print(String *to) const
{
ut_ad(m_value);
- return to->append(m_value);
+ return to->append(m_value, strlen(m_value));
}
bool print_quoted(String *to) const
{
ut_ad(m_value);
- return to->append("'") || to->append(m_value) || to->append("'");
+ return to->append('\'') || to->append(m_value, strlen(m_value)) ||
+ to->append('\'');
}
bool print_set_global(String *to) const
{
ut_ad(m_value);
return
- to->append("SET GLOBAL ") ||
- to->append(m_name) ||
- to->append(" = '") ||
- to->append(m_value) ||
- to->append("';\n");
+ to->append(STRING_WITH_LEN("SET GLOBAL ")) ||
+ to->append(m_name, strlen(m_name)) ||
+ to->append(STRING_WITH_LEN(" = '")) ||
+ to->append(m_value, strlen(m_value)) ||
+ to->append(STRING_WITH_LEN("';\n"));
}
};
@@ -1219,7 +1220,7 @@ public:
static bool start_comment_chunk(String *to)
{
- return to->length() ? to->append("; ") : false;
+ return to->length() ? to->append(STRING_WITH_LEN("; ")) : false;
}
bool print_connection_name_if_set(String *to) const
@@ -1231,24 +1232,28 @@ public:
bool print_comment_master_identity(String *comment) const
{
- if (comment->append("master "))
+ if (comment->append(STRING_WITH_LEN("master ")))
return true;
if (!m_mariadb_connection_name.is_null_or_empty())
return m_mariadb_connection_name.print_quoted(comment);
- return comment->append("''"); // Default not named master
+ return comment->append(STRING_WITH_LEN("''")); // Default not named master
}
bool print_using_master_log_pos(String *sql, String *comment) const
{
return
- sql->append("CHANGE MASTER ") ||
+ sql->append(STRING_WITH_LEN("CHANGE MASTER ")) ||
print_connection_name_if_set(sql) ||
- sql->append("TO MASTER_LOG_FILE=") || m_filename.print_quoted(sql) ||
- sql->append(", MASTER_LOG_POS=") || m_position.print(sql) ||
- sql->append(";\n") ||
+ sql->append(STRING_WITH_LEN("TO MASTER_LOG_FILE=")) ||
+ m_filename.print_quoted(sql) ||
+ sql->append(STRING_WITH_LEN(", MASTER_LOG_POS=")) ||
+ m_position.print(sql) ||
+ sql->append(STRING_WITH_LEN(";\n")) ||
print_comment_master_identity(comment) ||
- comment->append(" filename ") || m_filename.print_quoted(comment) ||
- comment->append(" position ") || m_position.print_quoted(comment);
+ comment->append(STRING_WITH_LEN(" filename ")) ||
+ m_filename.print_quoted(comment) ||
+ comment->append(STRING_WITH_LEN(" position ")) ||
+ m_position.print_quoted(comment);
}
bool print_mysql56(String *sql, String *comment) const
@@ -1259,23 +1264,23 @@ public:
CHANGE MASTER TO MASTER_AUTO_POSITION=1;
*/
return
- sql->append("SET GLOBAL gtid_purged=") ||
+ sql->append(STRING_WITH_LEN("SET GLOBAL gtid_purged=")) ||
m_mysql_gtid_executed.print_quoted(sql) ||
- sql->append(";\n") ||
- sql->append("CHANGE MASTER TO MASTER_AUTO_POSITION=1;\n") ||
+ sql->append(STRING_WITH_LEN(";\n")) ||
+ sql->append(STRING_WITH_LEN("CHANGE MASTER TO MASTER_AUTO_POSITION=1;\n")) ||
print_comment_master_identity(comment) ||
- comment->append(" purge list ") ||
+ comment->append(STRING_WITH_LEN(" purge list ")) ||
m_mysql_gtid_executed.print_quoted(comment);
}
bool print_mariadb10_using_gtid(String *sql, String *comment) const
{
return
- sql->append("CHANGE MASTER ") ||
+ sql->append(STRING_WITH_LEN("CHANGE MASTER ")) ||
print_connection_name_if_set(sql) ||
- sql->append("TO master_use_gtid = slave_pos;\n") ||
+ sql->append(STRING_WITH_LEN("TO master_use_gtid = slave_pos;\n")) ||
print_comment_master_identity(comment) ||
- comment->append(" master_use_gtid = slave_pos");
+ comment->append(STRING_WITH_LEN(" master_use_gtid = slave_pos"));
}
bool print(String *sql, String *comment, const Var &gtid_slave_pos) const
@@ -1314,7 +1319,7 @@ public:
if (status.is_mariadb_using_gtid())
{
if (gtid_slave_pos.print_set_global(sql) ||
- comment->append("gtid_slave_pos ") ||
+ comment->append(STRING_WITH_LEN("gtid_slave_pos ")) ||
gtid_slave_pos.print_quoted(comment))
return true; // Error
break;
diff --git a/extra/mariabackup/changed_page_bitmap.cc b/extra/mariabackup/changed_page_bitmap.cc
index 793d7378b0f..a6cc0e01492 100644
--- a/extra/mariabackup/changed_page_bitmap.cc
+++ b/extra/mariabackup/changed_page_bitmap.cc
@@ -188,18 +188,15 @@ log_online_read_bitmap_page(
{
ulint checksum;
ulint actual_checksum;
- ibool success;
ut_a(bitmap_file->size >= MODIFIED_PAGE_BLOCK_SIZE);
ut_a(bitmap_file->offset
<= bitmap_file->size - MODIFIED_PAGE_BLOCK_SIZE);
ut_a(bitmap_file->offset % MODIFIED_PAGE_BLOCK_SIZE == 0);
- success = os_file_read(IORequestRead,
- bitmap_file->file, page, bitmap_file->offset,
- MODIFIED_PAGE_BLOCK_SIZE) == DB_SUCCESS;
-
- if (UNIV_UNLIKELY(!success)) {
-
+ if (DB_SUCCESS !=
+ os_file_read(IORequestRead, bitmap_file->file, page,
+ bitmap_file->offset, MODIFIED_PAGE_BLOCK_SIZE,
+ nullptr)) {
/* The following call prints an error message */
os_file_get_last_error(TRUE);
msg("InnoDB: Warning: failed reading changed page bitmap "
diff --git a/extra/mariabackup/ds_stdout.cc b/extra/mariabackup/ds_stdout.cc
index 08776e99329..a9639ff7739 100644
--- a/extra/mariabackup/ds_stdout.cc
+++ b/extra/mariabackup/ds_stdout.cc
@@ -75,7 +75,7 @@ stdout_open(ds_ctxt_t *ctxt __attribute__((unused)),
stdout_file = (ds_stdout_file_t *) (file + 1);
-#ifdef __WIN__
+#ifdef _WIN32
setmode(fileno(stdout), _O_BINARY);
#endif
diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc
index 8d7fb3c7492..8820ce40c2b 100644
--- a/extra/mariabackup/fil_cur.cc
+++ b/extra/mariabackup/fil_cur.cc
@@ -65,17 +65,21 @@ xb_get_relative_path(
prev = NULL;
cur = path;
- while ((next = strchr(cur, OS_PATH_SEPARATOR)) != NULL) {
+#ifdef _WIN32
+ while ((next = strchr(cur, '\\')) != NULL) {
+ prev = cur;
+ cur = next + 1;
+ }
+#endif
+ while ((next = strchr(cur, '/')) != NULL) {
prev = cur;
cur = next + 1;
}
if (is_system) {
-
return(cur);
} else {
-
return((prev == NULL) ? cur : prev);
}
@@ -91,23 +95,18 @@ xb_fil_node_close_file(
{
ibool ret;
- mutex_enter(&fil_system.mutex);
+ mysql_mutex_lock(&fil_system.mutex);
ut_ad(node);
ut_a(!node->being_extended);
- if (!node->is_open()) {
-
- mutex_exit(&fil_system.mutex);
-
- return;
+ if (node->is_open()) {
+ ret = os_file_close(node->handle);
+ ut_a(ret);
+ node->handle = OS_FILE_CLOSED;
}
- ret = os_file_close(node->handle);
- ut_a(ret);
-
- node->handle = OS_FILE_CLOSED;
- mutex_exit(&fil_system.mutex);
+ mysql_mutex_unlock(&fil_system.mutex);
}
/************************************************************************
@@ -225,13 +224,13 @@ xb_fil_cur_open(
if (!node->space->crypt_data
&& os_file_read(IORequestRead,
node->handle, cursor->buf, 0,
- cursor->page_size) == DB_SUCCESS) {
- mutex_enter(&fil_system.mutex);
+ cursor->page_size, nullptr) == DB_SUCCESS) {
+ mysql_mutex_lock(&fil_system.mutex);
if (!node->space->crypt_data) {
node->space->crypt_data = fil_space_read_crypt_data(
node->space->zip_size(), cursor->buf);
}
- mutex_exit(&fil_system.mutex);
+ mysql_mutex_unlock(&fil_system.mutex);
}
cursor->space_size = (ulint)(cursor->statinfo.st_size
@@ -366,6 +365,7 @@ xb_fil_cur_result_t xb_fil_cur_read(xb_fil_cur_t* cursor,
ib_int64_t offset;
ib_int64_t to_read;
const ulint page_size = cursor->page_size;
+ bool defer = false;
xb_ad(!cursor->is_system() || page_size == srv_page_size);
cursor->read_filter->get_next_batch(&cursor->read_filter_ctxt,
@@ -418,7 +418,7 @@ read_retry:
cursor->buf_page_no = static_cast<unsigned>(offset / page_size);
if (os_file_read(IORequestRead, cursor->file, cursor->buf, offset,
- (ulint) to_read) != DB_SUCCESS) {
+ (ulint) to_read, nullptr) != DB_SUCCESS) {
if (!srv_is_undo_tablespace(cursor->space_id)) {
ret = XB_FIL_CUR_ERROR;
goto func_exit;
@@ -440,13 +440,15 @@ read_retry:
space->release();
goto reinit_buf;
}
+
+ defer = UT_LIST_GET_FIRST(space->chain)->deferred;
/* check pages for corruption and re-read if necessary. i.e. in case of
partially written pages */
for (page = cursor->buf, i = 0; i < npages;
page += page_size, i++) {
unsigned page_no = cursor->buf_page_no + i;
- if (page_is_corrupted(page, page_no, cursor, space)){
+ if (!defer && page_is_corrupted(page, page_no, cursor, space)) {
retry_count--;
if (retry_count == 0) {
@@ -473,11 +475,13 @@ read_retry:
msg(cursor->thread_n, "Database page corruption detected at page "
UINT32PF ", retrying...",
page_no);
- os_thread_sleep(100000);
+ std::this_thread::sleep_for(
+ std::chrono::milliseconds(100));
goto read_retry;
}
}
- DBUG_EXECUTE_FOR_KEY("add_corrupted_page_for", cursor->node->space->name,
+ DBUG_EXECUTE_FOR_KEY("add_corrupted_page_for",
+ cursor->node->space->name(),
{
unsigned corrupted_page_no =
static_cast<unsigned>(strtoul(dbug_val, NULL, 10));
diff --git a/extra/mariabackup/xbstream_read.cc b/extra/mariabackup/xbstream_read.cc
index 84bb279aba0..b54a98157ea 100644
--- a/extra/mariabackup/xbstream_read.cc
+++ b/extra/mariabackup/xbstream_read.cc
@@ -43,7 +43,7 @@ xb_stream_read_new(void)
stream = (xb_rstream_t *) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(xb_rstream_t), MYF(MY_FAE));
-#ifdef __WIN__
+#ifdef _WIN32
setmode(fileno(stdin), _O_BINARY);
#endif
diff --git a/extra/mariabackup/xbstream_write.cc b/extra/mariabackup/xbstream_write.cc
index 2c9ffde6c42..5801e867aac 100644
--- a/extra/mariabackup/xbstream_write.cc
+++ b/extra/mariabackup/xbstream_write.cc
@@ -110,7 +110,7 @@ xb_stream_write_open(xb_wstream_t *stream, const char *path,
file->chunk_ptr = file->chunk;
file->chunk_free = XB_STREAM_MIN_CHUNK_SIZE;
if (onwrite) {
-#ifdef __WIN__
+#ifdef _WIN32
setmode(fileno(stdout), _O_BINARY);
#endif
file->userdata = userdata;
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 7d45337bb18..9de1ef853b9 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -72,7 +72,6 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
#include <btr0sea.h>
-#include <dict0priv.h>
#include <lock0lock.h>
#include <log0recv.h>
#include <log0crypt.h>
@@ -141,8 +140,8 @@ longlong xtrabackup_use_memory;
uint opt_protocol;
long xtrabackup_throttle; /* 0:unlimited */
static lint io_ticket;
-static os_event_t wait_throttle;
-static os_event_t log_copying_stop;
+static mysql_cond_t wait_throttle;
+static mysql_cond_t log_copying_stop;
char *xtrabackup_incremental;
lsn_t incremental_lsn;
@@ -182,18 +181,17 @@ static hash_table_t databases_exclude_hash;
static hash_table_t inc_dir_tables_hash;
-struct xb_filter_entry_struct{
+struct xb_filter_entry_t{
char* name;
ibool has_tables;
- hash_node_t name_hash;
+ xb_filter_entry_t *name_hash;
};
-typedef struct xb_filter_entry_struct xb_filter_entry_t;
lsn_t checkpoint_lsn_start;
lsn_t checkpoint_no_start;
static lsn_t log_copy_scanned_lsn;
+/** whether log_copying_thread() is active; protected by log_sys.mutex */
static bool log_copying_running;
-static bool io_watching_thread_running;
int xtrabackup_parallel;
@@ -357,6 +355,9 @@ char orig_argv1[FN_REFLEN];
pthread_mutex_t backup_mutex;
pthread_cond_t scanned_lsn_cond;
+/** Store the deferred tablespace name during --backup */
+static std::set<std::string> defer_space_names;
+
typedef std::map<space_id_t,std::string> space_id_to_name_t;
struct ddl_tracker_t {
@@ -366,6 +367,45 @@ struct ddl_tracker_t {
std::set<space_id_t> drops;
/* For DDL operation found in redo log, */
space_id_to_name_t id_to_name;
+ /** Deferred tablespaces with their ID and name which was
+ found in redo log of DDL operations */
+ space_id_to_name_t deferred_tables;
+
+ /** Insert the deferred tablespace id with the name */
+ void insert_defer_id(space_id_t space_id, std::string name)
+ {
+ auto it= defer_space_names.find(name);
+ if (it != defer_space_names.end())
+ {
+ deferred_tables[space_id]= name;
+ defer_space_names.erase(it);
+ }
+ }
+
+ /** Rename the deferred tablespace with new name */
+ void rename_defer(space_id_t space_id, std::string old_name,
+ std::string new_name)
+ {
+ if (deferred_tables.find(space_id) != deferred_tables.end())
+ deferred_tables[space_id] = new_name;
+ auto defer_end= defer_space_names.end();
+ auto defer= defer_space_names.find(old_name);
+ if (defer == defer_end)
+ defer= defer_space_names.find(new_name);
+
+ if (defer != defer_end)
+ {
+ deferred_tables[space_id]= new_name;
+ defer_space_names.erase(defer);
+ }
+ }
+
+ /** Delete the deferred tablespace */
+ void delete_defer(space_id_t space_id, std::string name)
+ {
+ deferred_tables.erase(space_id);
+ defer_space_names.erase(name);
+ }
};
static ddl_tracker_t ddl_tracker;
@@ -374,8 +414,13 @@ static ddl_tracker_t ddl_tracker;
by recv_sys.mutex */
static std::set<uint32_t> undo_trunc_ids;
+/** Stores the space ids of page0 INIT_PAGE redo records. It is
+used to indicate whether the given deferred tablespace can
+be reconstructed. */
+static std::set<space_id_t> first_page_init_ids;
+
// 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)); }
@@ -387,11 +432,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);
}
@@ -519,7 +562,8 @@ bool CorruptedPages::empty() const
}
static void xb_load_single_table_tablespace(const std::string &space_name,
- bool set_size);
+ bool set_size,
+ ulint defer_space_id=0);
static void xb_data_files_close();
static fil_space_t* fil_space_get_by_name(const char* name);
@@ -547,8 +591,8 @@ void CorruptedPages::zero_out_free_pages()
space_it->second.pages.begin();
page_it != space_it->second.pages.end(); ++page_it)
{
- bool is_free= fseg_page_is_free(space, *page_it);
- if (!is_free) {
+ if (fseg_page_is_allocated(space, *page_it))
+ {
space_info_t &space_info = non_free_pages[space_id];
space_info.pages.insert(*page_it);
if (space_info.space_name.empty())
@@ -568,7 +612,7 @@ void CorruptedPages::zero_out_free_pages()
die("Can't zero out corrupted page " UINT32PF " of tablespace %s",
*page_it, space_name.c_str());
msg("Corrupted page " UINT32PF
- " of tablespace %s was successfuly fixed.",
+ " of tablespace %s was successfully fixed.",
*page_it, space_name.c_str());
}
}
@@ -596,41 +640,26 @@ xtrabackup_add_datasink(ds_ctxt_t *ds)
typedef void (*process_single_tablespace_func_t)(const char *dirname,
const char *filname,
bool is_remote,
- bool skip_node_page0);
+ bool skip_node_page0,
+ ulint defer_space_id);
static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback);
/* ======== Datafiles iterator ======== */
struct datafiles_iter_t {
- fil_space_t *space;
- fil_node_t *node;
- ibool started;
- pthread_mutex_t mutex;
+ space_list_t::iterator space = fil_system.space_list.end();
+ fil_node_t *node = nullptr;
+ bool started = false;
+ std::mutex mutex;
};
/* ======== Datafiles iterator ======== */
static
-datafiles_iter_t *
-datafiles_iter_new()
-{
- datafiles_iter_t *it;
-
- it = static_cast<datafiles_iter_t *>(malloc(sizeof(datafiles_iter_t)));
- pthread_mutex_init(&it->mutex, NULL);
-
- it->space = NULL;
- it->node = NULL;
- it->started = FALSE;
-
- return it;
-}
-
-static
fil_node_t *
datafiles_iter_next(datafiles_iter_t *it)
{
fil_node_t *new_node;
- pthread_mutex_lock(&it->mutex);
+ std::lock_guard<std::mutex> _(it->mutex);
if (it->node == NULL) {
if (it->started)
@@ -642,34 +671,25 @@ datafiles_iter_next(datafiles_iter_t *it)
goto end;
}
- it->space = (it->space == NULL) ?
- UT_LIST_GET_FIRST(fil_system.space_list) :
- UT_LIST_GET_NEXT(space_list, it->space);
+ it->space = (it->space == fil_system.space_list.end()) ?
+ fil_system.space_list.begin() :
+ std::next(it->space);
- while (it->space != NULL &&
+ while (it->space != fil_system.space_list.end() &&
(it->space->purpose != FIL_TYPE_TABLESPACE ||
UT_LIST_GET_LEN(it->space->chain) == 0))
- it->space = UT_LIST_GET_NEXT(space_list, it->space);
- if (it->space == NULL)
+ ++it->space;
+ if (it->space == fil_system.space_list.end())
goto end;
it->node = UT_LIST_GET_FIRST(it->space->chain);
end:
new_node = it->node;
- pthread_mutex_unlock(&it->mutex);
return new_node;
}
-static
-void
-datafiles_iter_free(datafiles_iter_t *it)
-{
- pthread_mutex_destroy(&it->mutex);
- free(it);
-}
-
#ifndef DBUG_OFF
struct dbug_thread_param_t
{
@@ -677,17 +697,14 @@ struct dbug_thread_param_t
const char *query;
int expect_err;
int expect_errno;
- os_event_t done_event;
};
/* Thread procedure used in dbug_start_query_thread. */
-extern "C"
-os_thread_ret_t
-DECLARE_THREAD(dbug_execute_in_new_connection)(void *arg)
+static void *dbug_execute_in_new_connection(void *arg)
{
mysql_thread_init();
- dbug_thread_param_t *par= (dbug_thread_param_t *)arg;
+ dbug_thread_param_t *par= static_cast<dbug_thread_param_t*>(arg);
int err = mysql_query(par->con, par->query);
int err_no = mysql_errno(par->con);
if(par->expect_err != err)
@@ -704,13 +721,12 @@ DECLARE_THREAD(dbug_execute_in_new_connection)(void *arg)
}
mysql_close(par->con);
mysql_thread_end();
- os_event_t done = par->done_event;
delete par;
- os_event_set(done);
- os_thread_exit();
- return os_thread_ret_t(0);
+ return nullptr;
}
+static pthread_t dbug_alter_thread;
+
/*
Execute query from a new connection, in own thread.
@@ -722,7 +738,7 @@ Execute query from a new connection, in own thread.
@param expected_errno - if not 0, and query finished with error,
expected mysql_errno()
*/
-static os_event_t dbug_start_query_thread(
+static void dbug_start_query_thread(
const char *query,
const char *wait_state,
int expected_err,
@@ -733,12 +749,13 @@ static os_event_t dbug_start_query_thread(
par->query = query;
par->expect_err = expected_err;
par->expect_errno = expected_errno;
- par->done_event = os_event_create(0);
par->con = xb_mysql_connect();
- os_thread_create(dbug_execute_in_new_connection, par);
+
+ mysql_thread_create(0, &dbug_alter_thread, nullptr,
+ dbug_execute_in_new_connection, par);
if (!wait_state)
- return par->done_event;
+ return;
char q[256];
snprintf(q, sizeof(q),
@@ -760,32 +777,30 @@ static os_event_t dbug_start_query_thread(
end:
msg("query '%s' on connection %lu reached state '%s'", query,
mysql_thread_id(par->con), wait_state);
- return par->done_event;
}
-
-os_event_t dbug_alter_thread_done;
#endif
void mdl_lock_all()
{
- mdl_lock_init();
- datafiles_iter_t *it = datafiles_iter_new();
- if (!it)
- return;
-
- while (fil_node_t *node = datafiles_iter_next(it)){
- if (fil_is_user_tablespace_id(node->space->id)
- && check_if_skip_table(node->space->name))
- continue;
+ mdl_lock_init();
+ datafiles_iter_t it;
- mdl_lock_table(node->space->id);
- }
- datafiles_iter_free(it);
+ 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);
@@ -811,33 +826,56 @@ std::string filename_to_spacename(const byte *filename, size_t len)
/** Report an operation to create, delete, or rename a file during backup.
@param[in] space_id tablespace identifier
-@param[in] create whether the file is being created
+@param[in] type redo log file operation type
@param[in] name file name (not NUL-terminated)
@param[in] len length of name, in bytes
@param[in] new_name new file name (NULL if not rename)
@param[in] new_len length of new_name, in bytes (0 if NULL) */
-static void backup_file_op(ulint space_id, bool create,
+static void backup_file_op(ulint space_id, int type,
const byte* name, ulint len,
const byte* new_name, ulint new_len)
{
- ut_ad(!create || !new_name);
ut_ad(name);
ut_ad(len);
ut_ad(!new_name == !new_len);
pthread_mutex_lock(&backup_mutex);
- if (create) {
- ddl_tracker.id_to_name[space_id] = filename_to_spacename(name, len);
+ switch(type) {
+ case FILE_CREATE:
+ {
+ std::string space_name = filename_to_spacename(name, len);
+ ddl_tracker.id_to_name[space_id] = space_name;
+ ddl_tracker.delete_defer(space_id, space_name);
msg("DDL tracking : create %zu \"%.*s\"", space_id, int(len), name);
}
- else if (new_name) {
- ddl_tracker.id_to_name[space_id] = filename_to_spacename(new_name, new_len);
+ break;
+ case FILE_MODIFY:
+ ddl_tracker.insert_defer_id(
+ space_id, filename_to_spacename(name, len));
+ break;
+ case FILE_RENAME:
+ {
+ std::string new_space_name = filename_to_spacename(
+ new_name, new_len);
+ std::string old_space_name = filename_to_spacename(
+ name, len);
+ ddl_tracker.id_to_name[space_id] = new_space_name;
+ ddl_tracker.rename_defer(space_id, old_space_name,
+ new_space_name);
msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"",
space_id, int(len), name, int(new_len), new_name);
- } else {
+ }
+ break;
+ case FILE_DELETE:
ddl_tracker.drops.insert(space_id);
+ ddl_tracker.delete_defer(
+ space_id, filename_to_spacename(name, len));
msg("DDL tracking : delete %zu \"%.*s\"", space_id, int(len), name);
+ break;
+ default:
+ ut_ad(0);
+ break;
}
pthread_mutex_unlock(&backup_mutex);
}
@@ -852,29 +890,37 @@ static void backup_file_op(ulint space_id, bool create,
We will abort backup in this case.
*/
-static void backup_file_op_fail(ulint space_id, bool create,
+static void backup_file_op_fail(ulint space_id, int type,
const byte* name, ulint len,
const byte* new_name, ulint new_len)
{
- bool fail;
- if (create) {
- msg("DDL tracking : create %zu \"%.*s\"",
- space_id, int(len), name);
- std::string spacename = filename_to_spacename(name, len);
- fail = !check_if_skip_table(spacename.c_str());
- }
- else if (new_name) {
+ bool fail = false;
+ switch(type) {
+ case FILE_CREATE:
+ msg("DDL tracking : create %zu \"%.*s\"", space_id, int(len), name);
+ fail = !check_if_skip_table(
+ filename_to_spacename(name, len).c_str());
+ break;
+ case FILE_MODIFY:
+ break;
+ case FILE_RENAME:
msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"",
space_id, int(len), name, int(new_len), new_name);
- std::string spacename = filename_to_spacename(name, len);
- std::string new_spacename = filename_to_spacename(new_name, new_len);
- fail = !check_if_skip_table(spacename.c_str()) || !check_if_skip_table(new_spacename.c_str());
- }
- else {
- std::string spacename = filename_to_spacename(name, len);
- fail = !check_if_skip_table(spacename.c_str());
+ fail = !check_if_skip_table(
+ filename_to_spacename(name, len).c_str())
+ || !check_if_skip_table(
+ filename_to_spacename(new_name, new_len).c_str());
+ break;
+ case FILE_DELETE:
+ fail = !check_if_skip_table(
+ filename_to_spacename(name, len).c_str());
msg("DDL tracking : delete %zu \"%.*s\"", space_id, int(len), name);
+ break;
+ default:
+ ut_ad(0);
+ break;
}
+
if (fail) {
ut_a(opt_no_lock);
die("DDL operation detected in the late phase of backup."
@@ -887,6 +933,13 @@ static void backup_undo_trunc(uint32_t space_id)
undo_trunc_ids.insert(space_id);
}
+/* Function to store the space id of page0 INIT_PAGE
+@param space_id space id which has page0 init page */
+static void backup_first_page_op(ulint space_id)
+{
+ first_page_init_ids.insert(space_id);
+}
+
/*
Retrieve default data directory, to be used with --copy-back.
@@ -925,7 +978,6 @@ typedef struct {
uint num;
uint *count;
pthread_mutex_t* count_mutex;
- os_thread_id_t id;
CorruptedPages *corrupted_pages;
} data_thread_ctxt_t;
@@ -1440,9 +1492,10 @@ uint xb_client_options_count = array_elements(xb_client_options);
static const char *dbug_option;
#endif
-namespace deprecated {
-extern ulong srv_n_log_files;
-}
+#ifdef HAVE_URING
+extern const char *io_uring_may_be_unsafe;
+bool innodb_use_native_aio_default();
+#endif
struct my_option xb_server_options[] =
{
@@ -1450,7 +1503,7 @@ struct my_option xb_server_options[] =
(G_PTR*) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"tmpdir", 't',
"Path for temporary files. Several paths may be specified, separated by a "
-#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
+#if defined(_WIN32)
"semicolon (;)"
#else
"colon (:)"
@@ -1538,7 +1591,7 @@ struct my_option xb_server_options[] =
"With which method to flush data.",
&srv_file_flush_method, &srv_file_flush_method,
&innodb_flush_method_typelib, GET_ENUM, REQUIRED_ARG,
- IF_WIN(SRV_ALL_O_DIRECT_FSYNC, SRV_FSYNC), 0, 0, 0, 0, 0},
+ IF_WIN(SRV_ALL_O_DIRECT_FSYNC, SRV_O_DIRECT), 0, 0, 0, 0, 0},
{"innodb_log_buffer_size", OPT_INNODB_LOG_BUFFER_SIZE,
"The size of the buffer which InnoDB uses to write log to the log files on disk.",
@@ -1550,10 +1603,6 @@ struct my_option xb_server_options[] =
GET_ULL, REQUIRED_ARG, 48 << 20, 1 << 20,
std::numeric_limits<ulonglong>::max(), 0,
UNIV_PAGE_SIZE_MAX, 0},
- {"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP,
- "Ignored for mysqld option compatibility",
- &deprecated::srv_n_log_files, &deprecated::srv_n_log_files,
- 0, GET_LONG, REQUIRED_ARG, 1, 1, 100, 0, 1, 0},
{"innodb_log_group_home_dir", OPT_INNODB_LOG_GROUP_HOME_DIR,
"Path to InnoDB log files.", &srv_log_group_home_dir,
&srv_log_group_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -1564,7 +1613,12 @@ struct my_option xb_server_options[] =
"Use native AIO if supported on this platform.",
(G_PTR*) &srv_use_native_aio,
(G_PTR*) &srv_use_native_aio, 0, GET_BOOL, NO_ARG,
- TRUE, 0, 0, 0, 0, 0},
+#ifdef HAVE_URING
+ innodb_use_native_aio_default(),
+#else
+ TRUE,
+#endif
+ 0, 0, 0, 0, 0},
{"innodb_page_size", OPT_INNODB_PAGE_SIZE,
"The universal page size of the database.",
(G_PTR*) &innobase_page_size, (G_PTR*) &innobase_page_size, 0,
@@ -1585,7 +1639,7 @@ struct my_option xb_server_options[] =
{"innodb_checksum_algorithm", OPT_INNODB_CHECKSUM_ALGORITHM,
"The algorithm InnoDB uses for page checksumming. [CRC32, STRICT_CRC32, "
- "INNODB, STRICT_INNODB, NONE, STRICT_NONE]", &srv_checksum_algorithm,
+ "FULL_CRC32, STRICT_FULL_CRC32]", &srv_checksum_algorithm,
&srv_checksum_algorithm, &innodb_checksum_algorithm_typelib, GET_ENUM,
REQUIRED_ARG, SRV_CHECKSUM_ALGORITHM_CRC32, 0, 0, 0, 0, 0},
@@ -1667,7 +1721,8 @@ uint xb_server_options_count = array_elements(xb_server_options);
static std::set<std::string> tables_for_export;
static void append_export_table(const char *dbname, const char *tablename,
- bool is_remote, bool skip_node_page0)
+ bool is_remote, bool skip_node_page0,
+ ulint defer_space_id)
{
if(dbname && tablename && !is_remote)
{
@@ -2078,7 +2133,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:
@@ -2110,8 +2164,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;
@@ -2148,6 +2200,15 @@ static bool innodb_init_param()
if (srv_use_native_aio) {
msg("InnoDB: Using Linux native AIO");
}
+#elif defined(HAVE_URING)
+ if (!srv_use_native_aio) {
+ } else if (io_uring_may_be_unsafe) {
+ msg("InnoDB: Using liburing on this kernel %s may cause hangs;"
+ " see https://jira.mariadb.org/browse/MDEV-26674",
+ io_uring_may_be_unsafe);
+ } else {
+ msg("InnoDB: Using liburing");
+ }
#else
/* Currently native AIO is supported only on windows and linux
and that also when the support is compiled in. In all other
@@ -2450,13 +2511,15 @@ xb_write_delta_metadata(const char *filename, const xb_delta_info_t *info)
}
/* ================= backup ================= */
-void
-xtrabackup_io_throttling(void)
+void xtrabackup_io_throttling()
{
- if (xtrabackup_backup && xtrabackup_throttle && (io_ticket--) < 0) {
- os_event_reset(wait_throttle);
- os_event_wait(wait_throttle);
- }
+ if (!xtrabackup_backup || !xtrabackup_throttle)
+ return;
+
+ mysql_mutex_lock(&log_sys.mutex);
+ if (io_ticket-- < 0)
+ mysql_cond_wait(&wait_throttle, &log_sys.mutex);
+ mysql_mutex_unlock(&log_sys.mutex);
}
static
@@ -2486,7 +2549,8 @@ find_filter_in_hashtable(
)
{
xb_filter_entry_t* found = NULL;
- HASH_SEARCH(name_hash, table, ut_fold_string(name),
+ const ulint fold = my_crc32c(0, name, strlen(name));
+ HASH_SEARCH(name_hash, table, fold,
xb_filter_entry_t*,
found, (void) 0,
!strcmp(found->name, name));
@@ -2580,7 +2644,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 {
@@ -2609,7 +2681,16 @@ check_if_skip_table(
dbname = NULL;
tbname = name;
- while ((ptr = strchr(tbname, '/')) != NULL) {
+ for (;;) {
+ ptr= strchr(tbname, '/');
+#ifdef _WIN32
+ if (!ptr) {
+ ptr= strchr(tbname,'\\');
+ }
+#endif
+ if (!ptr) {
+ break;
+ }
dbname = tbname;
tbname = ptr + 1;
}
@@ -2739,21 +2820,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);
}
@@ -2765,9 +2836,9 @@ static my_bool xtrabackup_copy_datafile(fil_node_t *node, uint thread_n,
pthread_mutex_unlock(&backup_mutex);
if (was_dropped) {
if (node->is_open()) {
- mutex_enter(&fil_system.mutex);
+ mysql_mutex_lock(&fil_system.mutex);
node->close();
- mutex_exit(&fil_system.mutex);
+ mysql_mutex_unlock(&fil_system.mutex);
}
goto skip;
}
@@ -2808,9 +2879,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 */
@@ -2840,11 +2912,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");
@@ -2876,7 +2952,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);
}
@@ -2964,6 +3040,8 @@ static lsn_t xtrabackup_copy_log(lsn_t start_lsn, lsn_t end_lsn, bool last)
@return whether the operation failed */
static bool xtrabackup_copy_logfile(bool last = false)
{
+ mysql_mutex_assert_owner(&log_sys.mutex);
+
ut_a(dst_log_file != NULL);
ut_ad(recv_sys.is_initialised());
@@ -2979,9 +3057,10 @@ static bool xtrabackup_copy_logfile(bool last = false)
do {
end_lsn = start_lsn + RECV_SCAN_SIZE;
- xtrabackup_io_throttling();
+ if (xtrabackup_throttle && (io_ticket--) < 0) {
+ mysql_cond_wait(&wait_throttle, &log_sys.mutex);
+ }
- mysql_mutex_lock(&log_sys.mutex);
lsn_t lsn= start_lsn;
for (int retries= 0; retries < 100; retries++) {
if (log_sys.log.read_log_seg(&lsn, end_lsn)
@@ -2993,22 +3072,20 @@ static bool xtrabackup_copy_logfile(bool last = false)
}
if (lsn == start_lsn) {
- overwritten_block= !recv_sys.found_corrupt_log
+ overwritten_block= !recv_sys.is_corrupt_log()
&& log_block_calc_checksum_crc32(log_sys.buf) ==
log_block_get_checksum(log_sys.buf)
&& log_block_get_hdr_no(log_sys.buf) >
log_block_convert_lsn_to_no(start_lsn);
start_lsn = 0;
} else {
- mutex_enter(&recv_sys.mutex);
+ mysql_mutex_lock(&recv_sys.mutex);
start_lsn = xtrabackup_copy_log(start_lsn, lsn, last);
- mutex_exit(&recv_sys.mutex);
+ mysql_mutex_unlock(&recv_sys.mutex);
}
- mysql_mutex_unlock(&log_sys.mutex);
-
if (!start_lsn) {
- const char *reason = recv_sys.found_corrupt_log
+ const char *reason = recv_sys.is_corrupt_log()
? "corrupt log."
: (overwritten_block
? "redo log block is overwritten, please increase redo log size with innodb_log_file_size parameter."
@@ -3048,76 +3125,70 @@ void backup_wait_for_lsn(lsn_t lsn) {
extern lsn_t server_lsn_after_lock;
-static os_thread_ret_t DECLARE_THREAD(log_copying_thread)(void*)
+static void log_copying_thread()
{
- /*
- Initialize mysys thread-specific memory so we can
- use mysys functions in this thread.
- */
- my_thread_init();
-
- for (;;) {
- os_event_reset(log_copying_stop);
- os_event_wait_time_low(log_copying_stop,
- xtrabackup_log_copy_interval * 1000U,
- 0);
- if (xtrabackup_copy_logfile()) {
- break;
- }
-
- mysql_mutex_lock(&log_sys.mutex);
- bool completed = metadata_to_lsn
- && metadata_to_lsn <= log_copy_scanned_lsn;
- mysql_mutex_unlock(&log_sys.mutex);
- if (completed) {
- break;
- }
- }
-
- log_copying_running = false;
- my_thread_end();
- os_thread_exit();
-
- return(0);
+ my_thread_init();
+ mysql_mutex_lock(&log_sys.mutex);
+ while (!xtrabackup_copy_logfile() &&
+ (!metadata_to_lsn || metadata_to_lsn > log_copy_scanned_lsn))
+ {
+ timespec abstime;
+ set_timespec_nsec(abstime, 1000000ULL * xtrabackup_log_copy_interval);
+ mysql_cond_timedwait(&log_copying_stop, &log_sys.mutex, &abstime);
+ }
+ log_copying_running= false;
+ mysql_mutex_unlock(&log_sys.mutex);
+ my_thread_end();
}
+/** whether io_watching_thread() is active; protected by log_sys.mutex */
+static bool have_io_watching_thread;
+
/* io throttle watching (rough) */
-static os_thread_ret_t DECLARE_THREAD(io_watching_thread)(void*)
+static void io_watching_thread()
{
- /* currently, for --backup only */
- ut_a(xtrabackup_backup);
-
- while (log_copying_running && !metadata_to_lsn) {
- os_thread_sleep(1000000); /*1 sec*/
- io_ticket = xtrabackup_throttle;
- os_event_set(wait_throttle);
- }
-
- /* stop io throttle */
- xtrabackup_throttle = 0;
- os_event_set(wait_throttle);
+ my_thread_init();
+ /* currently, for --backup only */
+ ut_ad(xtrabackup_backup);
- io_watching_thread_running = false;
+ mysql_mutex_lock(&log_sys.mutex);
+ ut_ad(have_io_watching_thread);
- os_thread_exit();
+ while (log_copying_running && !metadata_to_lsn)
+ {
+ timespec abstime;
+ set_timespec(abstime, 1);
+ mysql_cond_timedwait(&log_copying_stop, &log_sys.mutex, &abstime);
+ io_ticket= xtrabackup_throttle;
+ mysql_cond_broadcast(&wait_throttle);
+ }
- return(0);
+ /* stop io throttle */
+ xtrabackup_throttle= 0;
+ have_io_watching_thread= false;
+ mysql_cond_broadcast(&wait_throttle);
+ mysql_mutex_unlock(&log_sys.mutex);
+ my_thread_end();
}
#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;
}
/*
@@ -3132,7 +3203,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)
+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) {
@@ -3142,15 +3214,9 @@ void dbug_mariabackup_event(const char *event,const char *key)
}
#endif // DBUG_OFF
-/**************************************************************************
-Datafiles copying thread.*/
-static
-os_thread_ret_t
-DECLARE_THREAD(data_copy_thread_func)(
-/*==================*/
- void *arg) /* thread context */
+/** Datafiles copying thread.*/
+static void data_copy_thread_func(data_thread_ctxt_t *ctxt) /* thread context */
{
- data_thread_ctxt_t *ctxt = (data_thread_ctxt_t *) arg;
uint num = ctxt->num;
fil_node_t* node;
ut_ad(ctxt->corrupted_pages);
@@ -3162,8 +3228,9 @@ DECLARE_THREAD(data_copy_thread_func)(
my_thread_init();
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,
@@ -3171,8 +3238,7 @@ DECLARE_THREAD(data_copy_thread_func)(
*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);
@@ -3180,8 +3246,6 @@ DECLARE_THREAD(data_copy_thread_func)(
pthread_mutex_unlock(ctxt->count_mutex);
my_thread_end();
- os_thread_exit();
- OS_THREAD_DUMMY_RETURN;
}
/************************************************************************
@@ -3288,23 +3352,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
@@ -3314,15 +3361,19 @@ xb_new_datafile(const char *name, bool is_remote)
node page0 will be read, and it's size and free pages limit
will be set from page 0, what is neccessary for checking and fixing corrupted
pages.
+@param[in] defer_space_id use the space id to create space object
+when there is deferred tablespace
*/
static void xb_load_single_table_tablespace(const char *dirname,
const char *filname,
bool is_remote,
- bool skip_node_page0)
+ bool skip_node_page0,
+ ulint defer_space_id)
{
ut_ad(srv_operation == SRV_OPERATION_BACKUP
|| srv_operation == SRV_OPERATION_RESTORE_DELTA
- || srv_operation == SRV_OPERATION_RESTORE);
+ || srv_operation == SRV_OPERATION_RESTORE
+ || srv_operation == SRV_OPERATION_BACKUP_NO_DEFER);
/* Ignore .isl files on XtraBackup recovery. All tablespaces must be
local. */
if (is_remote && srv_operation == SRV_OPERATION_RESTORE_DELTA) {
@@ -3341,6 +3392,7 @@ static void xb_load_single_table_tablespace(const char *dirname,
lsn_t flush_lsn;
dberr_t err;
fil_space_t *space;
+ bool defer = false;
name = static_cast<char*>(ut_malloc_nokey(pathlen));
@@ -3352,36 +3404,71 @@ static void xb_load_single_table_tablespace(const char *dirname,
name[pathlen - 5] = 0;
}
- Datafile *file = xb_new_datafile(name, is_remote);
+ const fil_space_t::name_type n{name, pathlen - 5};
+ Datafile *file;
+
+ if (is_remote) {
+ RemoteDatafile* rf = new RemoteDatafile();
+ if (!rf->open_link_file(n)) {
+ die("Can't open datafile %s", name);
+ }
+ file = rf;
+ } else {
+ file = new Datafile();
+ file->make_filepath(".", n, IBD);
+ }
if (file->open_read_only(true) != DB_SUCCESS) {
die("Can't open datafile %s", name);
}
for (int i = 0; i < 10; i++) {
+ file->m_defer = false;
err = file->validate_first_page(&flush_lsn);
- if (err != DB_CORRUPTION) {
+
+ if (file->m_defer) {
+ if (defer_space_id) {
+ defer = true;
+ file->set_space_id(defer_space_id);
+ file->set_flags(FSP_FLAGS_PAGE_SSIZE());
+ err = DB_SUCCESS;
+ break;
+ }
+ } else if (err != DB_CORRUPTION) {
break;
}
my_sleep(1000);
}
+ if (!defer && file->m_defer) {
+ const char *file_path = file->filepath();
+ defer_space_names.insert(
+ filename_to_spacename(
+ file_path, strlen(file_path)));
+ delete file;
+ ut_free(name);
+ return;
+ }
+
bool is_empty_file = file->exists() && file->is_empty_file();
if (err == DB_SUCCESS && file->space_id() != SRV_TMP_SPACE_ID) {
space = fil_space_t::create(
- name, file->space_id(), file->flags(),
- FIL_TYPE_TABLESPACE, NULL/* TODO: crypt_data */,
+ file->space_id(), file->flags(),
+ FIL_TYPE_TABLESPACE, nullptr/* TODO: crypt_data */,
FIL_ENCRYPTION_DEFAULT,
file->handle() != OS_FILE_CLOSED);
ut_a(space != NULL);
- space->add(file->filepath(),
- skip_node_page0 ? file->detach() : pfs_os_file_t(), 0, false, false);
- mutex_enter(&fil_system.mutex);
+ fil_node_t* node= space->add(
+ file->filepath(),
+ skip_node_page0 ? file->detach() : pfs_os_file_t(),
+ 0, false, false);
+ node->deferred= defer;
+ mysql_mutex_lock(&fil_system.mutex);
space->read_page0();
- mutex_exit(&fil_system.mutex);
+ mysql_mutex_unlock(&fil_system.mutex);
if (srv_operation == SRV_OPERATION_RESTORE_DELTA
|| xb_close_files) {
@@ -3399,7 +3486,8 @@ static void xb_load_single_table_tablespace(const char *dirname,
}
static void xb_load_single_table_tablespace(const std::string &space_name,
- bool skip_node_page0)
+ bool skip_node_page0,
+ ulint defer_space_id)
{
std::string name(space_name);
bool is_remote= access((name + ".ibd").c_str(), R_OK) != 0;
@@ -3410,14 +3498,13 @@ static void xb_load_single_table_tablespace(const std::string &space_name,
buf[sizeof buf - 1]= '\0';
const char *dbname= buf;
char *p= strchr(buf, '/');
- if (p == 0)
+ if (!p)
die("Unexpected tablespace %s filename %s", space_name.c_str(),
name.c_str());
- ut_a(p);
*p= 0;
const char *tablename= p + 1;
xb_load_single_table_tablespace(dbname, tablename, is_remote,
- skip_node_page0);
+ skip_node_page0, defer_space_id);
}
#ifdef _WIN32
@@ -3675,12 +3762,11 @@ static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback)
/* General tablespaces are always at the first level of the
data home dir */
- if (dbinfo.type == OS_FILE_TYPE_FILE) {
- bool is_isl = ends_with(dbinfo.name, ".isl");
- bool is_ibd = !is_isl && ends_with(dbinfo.name,".ibd");
-
- if (is_isl || is_ibd) {
- (*callback)(NULL, dbinfo.name, is_isl, false);
+ if (dbinfo.type != OS_FILE_TYPE_FILE) {
+ const bool is_isl = ends_with(dbinfo.name, ".isl");
+ if (is_isl || ends_with(dbinfo.name,".ibd")) {
+ (*callback)(nullptr, dbinfo.name, is_isl,
+ false, 0);
}
}
@@ -3706,7 +3792,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);
@@ -3734,7 +3819,7 @@ static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback)
if (strlen(fileinfo.name) > 4) {
bool is_isl= false;
if (ends_with(fileinfo.name, ".ibd") || ((is_isl = ends_with(fileinfo.name, ".isl"))))
- (*callback)(dbinfo.name, fileinfo.name, is_isl, false);
+ (*callback)(dbinfo.name, fileinfo.name, is_isl, false, 0);
}
}
@@ -3763,7 +3848,7 @@ next_datadir_item:
if (os_file_closedir_failed(dir)) {
fprintf(stderr,
- "InnoDB: Error: could not close MySQL datadir\n");
+ "InnoDB: Error: could not close MariaDB datadir\n");
return(DB_ERROR);
}
@@ -3796,7 +3881,7 @@ static dberr_t xb_assign_undo_space_start()
byte* page = static_cast<byte*>
(aligned_malloc(srv_page_size, srv_page_size));
- if (os_file_read(IORequestRead, file, page, 0, srv_page_size)
+ if (os_file_read(IORequestRead, file, page, 0, srv_page_size, nullptr)
!= DB_SUCCESS) {
msg("Reading first page failed.\n");
error = DB_ERROR;
@@ -3808,7 +3893,7 @@ static dberr_t xb_assign_undo_space_start()
retry:
if (os_file_read(IORequestRead, file, page,
TRX_SYS_PAGE_NO << srv_page_size_shift,
- srv_page_size) != DB_SUCCESS) {
+ srv_page_size, nullptr) != DB_SUCCESS) {
msg("Reading TRX_SYS page failed.");
error = DB_ERROR;
goto func_exit;
@@ -3817,7 +3902,8 @@ retry:
/* TRX_SYS page can't be compressed or encrypted. */
if (buf_page_is_corrupted(false, page, fsp_flags)) {
if (n_retries--) {
- os_thread_sleep(1000);
+ std::this_thread::sleep_for(
+ std::chrono::milliseconds(1));
goto retry;
} else {
msg("mariabackup: TRX_SYS page corrupted.\n");
@@ -3930,7 +4016,7 @@ xb_load_tablespaces()
xb_close_undo_tablespaces();
}
- DBUG_MARIABACKUP_EVENT("after_load_tablespaces", 0);
+ DBUG_MARIABACKUP_EVENT("after_load_tablespaces", {});
return(DB_SUCCESS);
}
@@ -3972,22 +4058,16 @@ new hash table */
static
xb_filter_entry_t*
xb_add_filter(
-/*========================*/
const char* name, /*!< in: name of table/database */
hash_table_t* hash) /*!< in/out: hash to insert into */
{
- xb_filter_entry_t* entry;
-
- entry = xb_new_filter_entry(name);
+ xb_filter_entry_t* entry = xb_new_filter_entry(name);
if (UNIV_UNLIKELY(!hash->array)) {
hash->create(1000);
}
- HASH_INSERT(xb_filter_entry_t,
- name_hash, hash,
- ut_fold_string(entry->name),
- entry);
-
+ const ulint fold = my_crc32c(0, entry->name, strlen(entry->name));
+ HASH_INSERT(xb_filter_entry_t, name_hash, hash, fold, entry);
return entry;
}
@@ -4041,8 +4121,9 @@ xb_register_filter_entry(
dbname[p - name] = 0;
if (databases_hash && databases_hash->array) {
+ const ulint fold = my_crc32c(0, dbname, p - name);
HASH_SEARCH(name_hash, databases_hash,
- ut_fold_string(dbname),
+ fold,
xb_filter_entry_t*,
db_entry, (void) 0,
!strcmp(db_entry->name, dbname));
@@ -4251,9 +4332,10 @@ xb_filter_hash_free(hash_table_t* hash)
table = static_cast<xb_filter_entry_t *>
(HASH_GET_NEXT(name_hash, prev_table));
-
+ const ulint fold = my_crc32c(0, prev_table->name,
+ strlen(prev_table->name));
HASH_DELETE(xb_filter_entry_t, name_hash, hash,
- ut_fold_string(prev_table->name), prev_table);
+ fold, prev_table);
free(prev_table);
}
}
@@ -4351,40 +4433,40 @@ end:
static void stop_backup_threads()
{
- if (log_copying_stop && log_copying_running) {
- os_event_set(log_copying_stop);
- fputs("mariabackup: Stopping log copying thread", stderr);
- fflush(stderr);
- while (log_copying_running) {
- putc('.', stderr);
- fflush(stderr);
- os_thread_sleep(200000); /*0.2 sec*/
- }
- putc('\n', stderr);
- os_event_destroy(log_copying_stop);
- }
+ mysql_cond_broadcast(&log_copying_stop);
- if (wait_throttle) {
- /* wait for io_watching_thread completion */
- while (io_watching_thread_running) {
- os_thread_sleep(1000000);
- }
- os_event_destroy(wait_throttle);
- }
+ if (log_copying_running || have_io_watching_thread)
+ {
+ mysql_mutex_unlock(&log_sys.mutex);
+ fputs("mariabackup: Stopping log copying thread", stderr);
+ fflush(stderr);
+ mysql_mutex_lock(&log_sys.mutex);
+ while (log_copying_running || have_io_watching_thread)
+ {
+ mysql_cond_broadcast(&log_copying_stop);
+ mysql_mutex_unlock(&log_sys.mutex);
+ putc('.', stderr);
+ fflush(stderr);
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ mysql_mutex_lock(&log_sys.mutex);
+ }
+ putc('\n', stderr);
+ }
+
+ mysql_cond_destroy(&log_copying_stop);
}
/** Implement the core of --backup
@return whether the operation succeeded */
static bool xtrabackup_backup_low()
{
+ mysql_mutex_lock(&log_sys.mutex);
ut_ad(!metadata_to_lsn);
/* read the latest checkpoint lsn */
{
ulint max_cp_field;
- mysql_mutex_lock(&log_sys.mutex);
-
if (recv_find_max_checkpoint(&max_cp_field) == DB_SUCCESS
&& log_sys.log.format != 0) {
if (max_cp_field == LOG_CHECKPOINT_1) {
@@ -4400,16 +4482,17 @@ static bool xtrabackup_backup_low()
} else {
msg("Error: recv_find_max_checkpoint() failed.");
}
- mysql_mutex_unlock(&log_sys.mutex);
- }
- stop_backup_threads();
+ stop_backup_threads();
+ }
if (metadata_to_lsn && xtrabackup_copy_logfile(true)) {
+ mysql_mutex_unlock(&log_sys.mutex);
ds_close(dst_log_file);
dst_log_file = NULL;
return false;
}
+ mysql_mutex_unlock(&log_sys.mutex);
if (ds_close(dst_log_file) || !metadata_to_lsn) {
dst_log_file = NULL;
@@ -4512,15 +4595,22 @@ static bool xtrabackup_backup_func()
srv_operation = SRV_OPERATION_BACKUP;
log_file_op = backup_file_op;
undo_space_trunc = backup_undo_trunc;
+ first_page_init = backup_first_page_op;
metadata_to_lsn = 0;
/* initialize components */
if(innodb_init_param()) {
fail:
- metadata_to_lsn = log_copying_running;
- stop_backup_threads();
+ if (log_copying_running) {
+ mysql_mutex_lock(&log_sys.mutex);
+ metadata_to_lsn = 1;
+ stop_backup_threads();
+ mysql_mutex_unlock(&log_sys.mutex);
+ }
+
log_file_op = NULL;
undo_space_trunc = NULL;
+ first_page_init = NULL;
if (dst_log_file) {
ds_close(dst_log_file);
dst_log_file = NULL;
@@ -4548,7 +4638,6 @@ fail:
computers */
}
srv_thread_pool_init();
- sync_check_init();
/* Reset the system variables in the recovery module. */
trx_pool_init();
recv_sys.create();
@@ -4677,13 +4766,15 @@ reread_log_header:
aligned_free(log_hdr_buf);
log_copying_running = true;
+
+ mysql_cond_init(0, &log_copying_stop, nullptr);
+
/* start io throttle */
- if(xtrabackup_throttle) {
+ if (xtrabackup_throttle) {
io_ticket = xtrabackup_throttle;
- wait_throttle = os_event_create(0);
- io_watching_thread_running = true;
-
- os_thread_create(io_watching_thread);
+ have_io_watching_thread = true;
+ mysql_cond_init(0, &wait_throttle, nullptr);
+ std::thread(io_watching_thread).detach();
}
/* Populate fil_system with tablespaces to copy */
@@ -4700,13 +4791,18 @@ fail_before_log_copying_thread_start:
log_copy_scanned_lsn = checkpoint_lsn_start;
recv_sys.recovered_lsn = log_copy_scanned_lsn;
- if (xtrabackup_copy_logfile())
+ mysql_mutex_lock(&log_sys.mutex);
+
+ const bool log_copy_failed = xtrabackup_copy_logfile();
+
+ mysql_mutex_unlock(&log_sys.mutex);
+
+ 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", {});
- log_copying_stop = os_event_create(0);
- os_thread_create(log_copying_thread);
+ std::thread(log_copying_thread).detach();
/* FLUSH CHANGED_PAGE_BITMAPS call */
if (!flush_changed_page_bitmaps()) {
@@ -4724,16 +4820,11 @@ fail_before_log_copying_thread_start:
mdl_lock_all();
DBUG_EXECUTE_IF("check_mdl_lock_works",
- dbug_alter_thread_done =
dbug_start_query_thread("ALTER TABLE test.t ADD COLUMN mdl_lock_column int",
"Waiting for table metadata lock", 0, 0););
}
- datafiles_iter_t *it = datafiles_iter_new();
- if (it == NULL) {
- msg("mariabackup: Error: datafiles_iter_new() failed.");
- goto fail;
- }
+ datafiles_iter_t it;
/* Create data copying threads */
data_threads = (data_thread_ctxt_t *)
@@ -4742,18 +4833,17 @@ fail_before_log_copying_thread_start:
pthread_mutex_init(&count_mutex, NULL);
for (i = 0; i < (uint) xtrabackup_parallel; i++) {
- data_threads[i].it = it;
+ data_threads[i].it = &it;
data_threads[i].num = i+1;
data_threads[i].count = &count;
data_threads[i].count_mutex = &count_mutex;
data_threads[i].corrupted_pages = &corrupted_pages;
- data_threads[i].id = os_thread_create(data_copy_thread_func,
- data_threads + i);
+ std::thread(data_copy_thread_func, data_threads + i).detach();
}
/* Wait for threads to exit */
while (1) {
- os_thread_sleep(1000000);
+ std::this_thread::sleep_for(std::chrono::seconds(1));
pthread_mutex_lock(&count_mutex);
bool stop = count == 0;
pthread_mutex_unlock(&count_mutex);
@@ -4764,7 +4854,6 @@ fail_before_log_copying_thread_start:
pthread_mutex_destroy(&count_mutex);
free(data_threads);
- datafiles_iter_free(it);
}
bool ok = backup_start(corrupted_pages);
@@ -4775,9 +4864,7 @@ fail_before_log_copying_thread_start:
backup_release();
DBUG_EXECUTE_IF("check_mdl_lock_works",
- os_event_wait(dbug_alter_thread_done);
- os_event_destroy(dbug_alter_thread_done);
- );
+ pthread_join(dbug_alter_thread, nullptr););
if (ok) {
backup_finish();
@@ -4813,6 +4900,7 @@ fail_before_log_copying_thread_start:
innodb_shutdown();
log_file_op = NULL;
undo_space_trunc = NULL;
+ first_page_init = NULL;
pthread_mutex_destroy(&backup_mutex);
pthread_cond_destroy(&scanned_lsn_cond);
if (!corrupted_pages.empty()) {
@@ -4844,16 +4932,16 @@ FTWRL. This ensures consistent backup in presence of DDL.
*/
void backup_fix_ddl(CorruptedPages &corrupted_pages)
{
- std::set<std::string> new_tables;
std::set<std::string> dropped_tables;
std::map<std::string, std::string> renamed_tables;
+ space_id_to_name_t new_tables;
/* Disable further DDL on backed up tables (only needed for --no-lock).*/
pthread_mutex_lock(&backup_mutex);
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();
@@ -4894,9 +4982,11 @@ void backup_fix_ddl(CorruptedPages &corrupted_pages)
continue;
}
- if (ddl_tracker.drops.find(id) == ddl_tracker.drops.end()) {
+ if (ddl_tracker.drops.find(id) == ddl_tracker.drops.end()
+ && ddl_tracker.deferred_tables.find(id)
+ == ddl_tracker.deferred_tables.end()) {
dropped_tables.erase(name);
- new_tables.insert(name);
+ new_tables[id] = name;
if (opt_log_innodb_page_corruption)
corrupted_pages.drop_space(id);
}
@@ -4921,10 +5011,8 @@ void backup_fix_ddl(CorruptedPages &corrupted_pages)
// Load and copy new tables.
// Close all datanodes first, reload only new tables.
std::vector<fil_node_t *> all_nodes;
- datafiles_iter_t *it = datafiles_iter_new();
- if (!it)
- return;
- while (fil_node_t *node = datafiles_iter_next(it)) {
+ datafiles_iter_t it;
+ while (fil_node_t *node = datafiles_iter_next(&it)) {
all_nodes.push_back(node);
}
for (size_t i = 0; i < all_nodes.size(); i++) {
@@ -4932,38 +5020,69 @@ void backup_fix_ddl(CorruptedPages &corrupted_pages)
if (n->space->id == 0)
continue;
if (n->is_open()) {
- mutex_enter(&fil_system.mutex);
+ mysql_mutex_lock(&fil_system.mutex);
n->close();
- mutex_exit(&fil_system.mutex);
+ mysql_mutex_unlock(&fil_system.mutex);
}
fil_space_free(n->space->id, false);
}
- datafiles_iter_free(it);
DBUG_EXECUTE_IF("check_mdl_lock_works", DBUG_ASSERT(new_tables.size() == 0););
- for (std::set<std::string>::iterator iter = new_tables.begin();
- iter != new_tables.end(); iter++) {
- const char *space_name = iter->c_str();
- if (check_if_skip_table(space_name))
+
+ srv_operation = SRV_OPERATION_BACKUP_NO_DEFER;
+
+ /* Mariabackup detected the FILE_MODIFY or FILE_RENAME
+ for the deferred tablespace. So it needs to read the
+ tablespace again if innodb doesn't have page0 initialization
+ redo log for it */
+ for (space_id_to_name_t::iterator iter =
+ ddl_tracker.deferred_tables.begin();
+ iter != ddl_tracker.deferred_tables.end();
+ iter++) {
+ if (check_if_skip_table(iter->second.c_str())) {
continue;
- xb_load_single_table_tablespace(*iter, false);
+ }
+
+ if (first_page_init_ids.find(iter->first)
+ != first_page_init_ids.end()) {
+ new_tables[iter->first] = iter->second.c_str();
+ continue;
+ }
+
+ xb_load_single_table_tablespace(iter->second, false);
}
- it = datafiles_iter_new();
- if (!it)
- return;
+ /* Mariabackup doesn't detect any FILE_OP for the deferred
+ tablespace. There is a possiblity that page0 could've
+ been corrupted persistently in the disk */
+ for (auto space_name: defer_space_names) {
+ if (!check_if_skip_table(space_name.c_str())) {
+ xb_load_single_table_tablespace(
+ space_name, false);
+ }
+ }
+
+ srv_operation = SRV_OPERATION_BACKUP;
+
+ for (const auto &t : new_tables) {
+ if (!check_if_skip_table(t.second.c_str())) {
+ xb_load_single_table_tablespace(t.second, false,
+ t.first);
+ }
+ }
- while (fil_node_t *node = datafiles_iter_next(it)) {
- fil_space_t * space = node->space;
- if (!fil_is_user_tablespace_id(space->id))
+ datafiles_iter_t it2;
+
+ while (fil_node_t *node = datafiles_iter_next(&it2)) {
+ 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);
}
-
- datafiles_iter_free(it);
}
/* ================= prepare ================= */
@@ -5026,64 +5145,20 @@ xb_space_create_file(
return ret;
}
- /* Align the memory for file i/o if we might have O_DIRECT set */
- byte* page = static_cast<byte*>(aligned_malloc(2 * srv_page_size,
- srv_page_size));
-
- memset(page, '\0', srv_page_size);
-
- fsp_header_init_fields(page, space_id, flags);
- mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
-
- const ulint zip_size = fil_space_t::zip_size(flags);
-
- if (!zip_size) {
- buf_flush_init_for_writing(
- NULL, page, NULL,
- fil_space_t::full_crc32(flags));
-
- ret = os_file_write(IORequestWrite, path, *file, page, 0,
- srv_page_size);
- } else {
- page_zip_des_t page_zip;
- page_zip_set_size(&page_zip, zip_size);
- page_zip.data = page + srv_page_size;
- fprintf(stderr, "zip_size = " ULINTPF "\n", zip_size);
-
-#ifdef UNIV_DEBUG
- page_zip.m_start = 0;
-#endif /* UNIV_DEBUG */
- page_zip.m_end = 0;
- page_zip.m_nonempty = 0;
- page_zip.n_blobs = 0;
-
- buf_flush_init_for_writing(NULL, page, &page_zip, false);
-
- ret = os_file_write(IORequestWrite, path, *file,
- page_zip.data, 0, zip_size);
- }
-
- aligned_free(page);
-
- if (ret != DB_SUCCESS) {
- msg("mariabackup: could not write the first page to %s",
- path);
- os_file_close(*file);
- os_file_delete(0, path);
- return ret;
- }
-
return TRUE;
}
static fil_space_t* fil_space_get_by_name(const char* name)
{
- ut_ad(mutex_own(&fil_system.mutex));
- for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list);
- space != NULL;
- space = UT_LIST_GET_NEXT(space_list, space))
- 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;
}
/***********************************************************************
@@ -5118,20 +5193,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';
@@ -5174,19 +5244,21 @@ exit:
return file;
}
+ const size_t len = strlen(dest_space_name);
/* remember space name for further reference */
table = static_cast<xb_filter_entry_t *>
(malloc(sizeof(xb_filter_entry_t) +
- strlen(dest_space_name) + 1));
+ len + 1));
table->name = ((char*)table) + sizeof(xb_filter_entry_t);
- strcpy(table->name, dest_space_name);
+ memcpy(table->name, dest_space_name, len + 1);
+ const ulint fold = my_crc32c(0, dest_space_name, len);
HASH_INSERT(xb_filter_entry_t, name_hash, &inc_dir_tables_hash,
- ut_fold_string(table->name), table);
+ fold, table);
- mutex_enter(&fil_system.mutex);
+ mysql_mutex_lock(&fil_system.mutex);
fil_space = fil_space_get_by_name(dest_space_name);
- mutex_exit(&fil_system.mutex);
+ mysql_mutex_unlock(&fil_system.mutex);
if (fil_space != NULL) {
if (fil_space->id == info.space_id
@@ -5201,12 +5273,11 @@ 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) {
+ if (fil_space->rename(tmpname, false) != DB_SUCCESS) {
msg("mariabackup: Cannot rename %s to %s",
- fil_space->name, tmpname);
+ fil_space->chain.start->name, tmpname);
goto exit;
}
}
@@ -5217,21 +5288,20 @@ exit:
die("Can't handle DDL operation on tablespace "
"%s\n", dest_space_name);
}
- mutex_enter(&fil_system.mutex);
+ mysql_mutex_lock(&fil_system.mutex);
fil_space = fil_space_get_by_id(info.space_id);
- mutex_exit(&fil_system.mutex);
+ mysql_mutex_unlock(&fil_system.mutex);
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;
}
@@ -5254,7 +5324,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, FIL_ENCRYPTION_DEFAULT,
true)) {
*success = xb_space_create_file(real_name, info.space_id,
@@ -5320,10 +5390,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;
}
@@ -5374,7 +5440,8 @@ xtrabackup_apply_delta(
offset = ((incremental_buffers * (page_size / 4))
<< page_size_shift);
if (os_file_read(IORequestRead, src_file,
- incremental_buffer, offset, page_size)
+ incremental_buffer, offset, page_size,
+ nullptr)
!= DB_SUCCESS) {
goto error;
}
@@ -5407,7 +5474,7 @@ xtrabackup_apply_delta(
/* read whole of the cluster */
if (os_file_read(IORequestRead, src_file,
incremental_buffer,
- offset, page_in_buffer * page_size)
+ offset, page_in_buffer * page_size, nullptr)
!= DB_SUCCESS) {
goto error;
}
@@ -5602,8 +5669,10 @@ static ibool prepare_handle_new_files(const char *data_home_dir,
(malloc(sizeof(xb_filter_entry_t) + table_name.size() + 1));
table->name = ((char*)table) + sizeof(xb_filter_entry_t);
strcpy(table->name, table_name.c_str());
+ const ulint fold = my_crc32c(0, table->name,
+ table_name.size());
HASH_INSERT(xb_filter_entry_t, name_hash, &inc_dir_tables_hash,
- ut_fold_string(table->name), table);
+ fold, table);
}
return TRUE;
@@ -5626,9 +5695,11 @@ rm_if_not_found(
snprintf(name, FN_REFLEN, "%s/%s", db_name, file_name);
/* Truncate ".ibd" */
- name[strlen(name) - 4] = '\0';
+ const size_t len = strlen(name) - 4;
+ name[len] = '\0';
+ const ulint fold = my_crc32c(0, name, len);
- HASH_SEARCH(name_hash, &inc_dir_tables_hash, ut_fold_string(name),
+ HASH_SEARCH(name_hash, &inc_dir_tables_hash, fold,
xb_filter_entry_t*,
table, (void) 0,
!strcmp(table->name, name));
@@ -5725,8 +5796,6 @@ next_file_item_1:
OS_FILE_MAX_PATH/2-1,
dbinfo.name);
- os_normalize_path(dbpath);
-
dbdir = os_file_opendir(dbpath);
if (dbdir != IF_WIN(INVALID_HANDLE_VALUE, nullptr)) {
@@ -5846,8 +5915,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);
@@ -5994,7 +6062,6 @@ static bool xtrabackup_prepare_func(char** argv)
goto error_cleanup;
}
- sync_check_init();
recv_sys.create();
log_sys.create();
recv_sys.recovery_on = true;
@@ -6023,7 +6090,6 @@ static bool xtrabackup_prepare_func(char** argv)
fil_system.close();
innodb_free_param();
log_sys.close();
- sync_check_close();
if (!ok) goto error_cleanup;
}
@@ -6841,7 +6907,7 @@ static int main_low(char** argv)
/* get default temporary directory */
if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0]) {
opt_mysql_tmpdir = getenv("TMPDIR");
-#if defined(__WIN__)
+#if defined(_WIN32)
if (!opt_mysql_tmpdir) {
opt_mysql_tmpdir = getenv("TEMP");
}
diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h
index 394ea9ed87c..ff7adf49252 100644
--- a/extra/mariabackup/xtrabackup.h
+++ b/extra/mariabackup/xtrabackup.h
@@ -286,4 +286,16 @@ fil_file_readdir_next_file(
os_file_dir_t dir, /*!< in: directory stream */
os_file_stat_t* info); /*!< in/out: buffer where the
info is returned */
+
+#ifndef DBUG_OFF
+#include <fil0fil.h>
+extern void dbug_mariabackup_event(const char *event,
+ const fil_space_t::name_type key);
+
+#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
+
#endif /* XB_XTRABACKUP_H */