diff options
Diffstat (limited to 'extra/mariabackup')
-rw-r--r-- | extra/mariabackup/CMakeLists.txt | 7 | ||||
-rw-r--r-- | extra/mariabackup/backup_copy.cc | 151 | ||||
-rw-r--r-- | extra/mariabackup/backup_debug.h | 18 | ||||
-rw-r--r-- | extra/mariabackup/backup_mysql.cc | 183 | ||||
-rw-r--r-- | extra/mariabackup/changed_page_bitmap.cc | 11 | ||||
-rw-r--r-- | extra/mariabackup/ds_stdout.cc | 2 | ||||
-rw-r--r-- | extra/mariabackup/fil_cur.cc | 46 | ||||
-rw-r--r-- | extra/mariabackup/xbstream_read.cc | 2 | ||||
-rw-r--r-- | extra/mariabackup/xbstream_write.cc | 2 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 982 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.h | 12 |
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 >id_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 = ⁢ 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 */ |