diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-06-30 10:49:37 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-07-05 11:43:28 +0300 |
commit | 8c71c6aa8b9f4c78cfa164fad1d324ba0cf9b888 (patch) | |
tree | 018dc06431015490e06196316ef334e492431e6d /extra/mariabackup | |
parent | dc722559cc996950a6f13ba62fa675ff2fa9828a (diff) | |
download | mariadb-git-8c71c6aa8b9f4c78cfa164fad1d324ba0cf9b888.tar.gz |
MDEV-12548 Initial implementation of Mariabackup for MariaDB 10.2
InnoDB I/O and buffer pool interfaces and the redo log format
have been changed between MariaDB 10.1 and 10.2, and the backup
code has to be adjusted accordingly.
The code has been simplified, and many memory leaks have been fixed.
Instead of the file name xtrabackup_logfile, the file name ib_logfile0
is being used for the copy of the redo log. Unnecessary InnoDB startup and
shutdown and some unnecessary threads have been removed.
Some help was provided by Vladislav Vaintroub.
Parameters have been cleaned up and aligned with those of MariaDB 10.2.
The --dbug option has been added, so that in debug builds,
--dbug=d,ib_log can be specified to enable diagnostic messages
for processing redo log entries.
By default, innodb_doublewrite=OFF, so that --prepare works faster.
If more crash-safety for --prepare is needed, double buffering
can be enabled.
The parameter innodb_log_checksums=OFF can be used to ignore redo log
checksums in --backup.
Some messages have been cleaned up.
Unless --export is specified, Mariabackup will not deal with undo log.
The InnoDB mini-transaction redo log is not only about user-level
transactions; it is actually about mini-transactions. To avoid confusion,
call it the redo log, not transaction log.
We disable any undo log processing in --prepare.
Because MariaDB 10.2 supports indexed virtual columns, the
undo log processing would need to be able to evaluate virtual column
expressions. To reduce the amount of code dependencies, we will not
process any undo log in prepare.
This means that the --export option must be disabled for now.
This also means that the following options are redundant
and have been removed:
xtrabackup --apply-log-only
innobackupex --redo-only
In addition to disabling any undo log processing, we will disable any
further changes to data pages during --prepare, including the change
buffer merge. This means that restoring incremental backups should
reliably work even when change buffering is being used on the server.
Because of this, preparing a backup will not generate any further
redo log, and the redo log file can be safely deleted. (If the
--export option is enabled in the future, it must generate redo log
when processing undo logs and buffered changes.)
In --prepare, we cannot easily know if a partial backup was used,
especially when restoring a series of incremental backups. So, we
simply warn about any missing files, and ignore the redo log for them.
FIXME: Enable the --export option.
FIXME: Improve the handling of the MLOG_INDEX_LOAD record, and write
a test that initiates a backup while an ALGORITHM=INPLACE operation
is creating indexes or rebuilding a table. An error should be detected
when preparing the backup.
FIXME: In --incremental --prepare, xtrabackup_apply_delta() should
ensure that if FSP_SIZE is modified, the file size will be adjusted
accordingly.
Diffstat (limited to 'extra/mariabackup')
-rw-r--r-- | extra/mariabackup/CMakeLists.txt | 4 | ||||
-rw-r--r-- | extra/mariabackup/backup_copy.cc | 212 | ||||
-rw-r--r-- | extra/mariabackup/backup_mysql.cc | 57 | ||||
-rw-r--r-- | extra/mariabackup/backup_wsrep.h (renamed from extra/mariabackup/wsrep.h) | 4 | ||||
-rw-r--r-- | extra/mariabackup/changed_page_bitmap.cc | 63 | ||||
-rw-r--r-- | extra/mariabackup/encryption_plugin.cc | 21 | ||||
-rw-r--r-- | extra/mariabackup/fil_cur.cc | 183 | ||||
-rw-r--r-- | extra/mariabackup/fil_cur.h | 21 | ||||
-rw-r--r-- | extra/mariabackup/innobackupex.cc | 21 | ||||
-rw-r--r-- | extra/mariabackup/read_filt.cc | 15 | ||||
-rw-r--r-- | extra/mariabackup/read_filt.h | 8 | ||||
-rw-r--r-- | extra/mariabackup/write_filt.cc | 20 | ||||
-rw-r--r-- | extra/mariabackup/xb0xb.h | 36 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 2636 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.h | 50 |
15 files changed, 1296 insertions, 2055 deletions
diff --git a/extra/mariabackup/CMakeLists.txt b/extra/mariabackup/CMakeLists.txt index ac15460660c..f7202a7f3b7 100644 --- a/extra/mariabackup/CMakeLists.txt +++ b/extra/mariabackup/CMakeLists.txt @@ -30,7 +30,7 @@ ENDIF() INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include - ${CMAKE_SOURCE_DIR}/storage/xtradb/include + ${CMAKE_SOURCE_DIR}/storage/innodb/include ${CMAKE_SOURCE_DIR}/sql ${CMAKE_CURRENT_SOURCE_DIR}/quicklz ${CMAKE_CURRENT_SOURCE_DIR} @@ -74,9 +74,9 @@ MYSQL_ADD_EXECUTABLE(mariabackup backup_mysql.cc backup_copy.cc encryption_plugin.cc - ${PROJECT_SOURCE_DIR}/libmysql/libmysql.c ${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 156e0b20e7c..d9e2db0cb66 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -89,7 +89,7 @@ struct datadir_iter_t { ulint filepath_len; char *filepath_rel; ulint filepath_rel_len; - os_ib_mutex_t mutex; + pthread_mutex_t mutex; os_file_dir_t dir; os_file_dir_t dbdir; os_file_stat_t dbinfo; @@ -107,7 +107,7 @@ struct datadir_thread_ctxt_t { datadir_iter_t *it; uint n_thread; uint *count; - os_ib_mutex_t count_mutex; + pthread_mutex_t count_mutex; os_thread_id_t id; bool ret; }; @@ -134,12 +134,12 @@ datadir_node_fill(datadir_node_t *node, datadir_iter_t *it) { if (node->filepath_len < it->filepath_len) { free(node->filepath); - node->filepath = (char*)(ut_malloc(it->filepath_len)); + node->filepath = (char*)(malloc(it->filepath_len)); node->filepath_len = it->filepath_len; } if (node->filepath_rel_len < it->filepath_rel_len) { free(node->filepath_rel); - node->filepath_rel = (char*)(ut_malloc(it->filepath_rel_len)); + node->filepath_rel = (char*)(malloc(it->filepath_rel_len)); node->filepath_rel_len = it->filepath_rel_len; } @@ -153,8 +153,8 @@ static void datadir_node_free(datadir_node_t *node) { - ut_free(node->filepath); - ut_free(node->filepath_rel); + free(node->filepath); + free(node->filepath_rel); memset(node, 0, sizeof(datadir_node_t)); } @@ -178,10 +178,10 @@ datadir_iter_new(const char *path, bool skip_first_level = true) { datadir_iter_t *it; - it = static_cast<datadir_iter_t *>(ut_malloc(sizeof(datadir_iter_t))); + it = static_cast<datadir_iter_t *>(malloc(sizeof(datadir_iter_t))); memset(it, 0, sizeof(datadir_iter_t)); - it->mutex = os_mutex_create(); + pthread_mutex_init(&it->mutex, NULL); it->datadir_path = strdup(path); it->dir = os_file_opendir(it->datadir_path, TRUE); @@ -194,20 +194,20 @@ datadir_iter_new(const char *path, bool skip_first_level = true) it->err = DB_SUCCESS; it->dbpath_len = FN_REFLEN; - it->dbpath = static_cast<char*>(ut_malloc(it->dbpath_len)); + it->dbpath = static_cast<char*>(malloc(it->dbpath_len)); it->filepath_len = FN_REFLEN; - it->filepath = static_cast<char*>(ut_malloc(it->filepath_len)); + it->filepath = static_cast<char*>(malloc(it->filepath_len)); it->filepath_rel_len = FN_REFLEN; - it->filepath_rel = static_cast<char*>(ut_malloc(it->filepath_rel_len)); + it->filepath_rel = static_cast<char*>(malloc(it->filepath_rel_len)); it->skip_first_level = skip_first_level; return(it); error: - ut_free(it); + free(it); return(NULL); } @@ -246,19 +246,15 @@ datadir_iter_next_database(datadir_iter_t *it) + strlen (it->dbinfo.name) + 2; if (len > it->dbpath_len) { it->dbpath_len = len; + free(it->dbpath); - if (it->dbpath) { - - ut_free(it->dbpath); - } - - it->dbpath = static_cast<char*> - (ut_malloc(it->dbpath_len)); + it->dbpath = static_cast<char*>( + malloc(it->dbpath_len)); } ut_snprintf(it->dbpath, it->dbpath_len, "%s/%s", it->datadir_path, it->dbinfo.name); - srv_normalize_path_for_win(it->dbpath); + os_normalize_path(it->dbpath); if (it->dbinfo.type == OS_FILE_TYPE_FILE) { it->is_file = true; @@ -306,8 +302,8 @@ make_path_n(int n, char **path, ulint *path_len, ...) va_end(vl); if (len_needed < *path_len) { - ut_free(*path); - *path = static_cast<char*>(ut_malloc(len_needed)); + free(*path); + *path = static_cast<char*>(malloc(len_needed)); } va_start(vl, path_len); @@ -378,7 +374,7 @@ datadir_iter_next(datadir_iter_t *it, datadir_node_t *node) { bool ret = true; - os_mutex_enter(it->mutex); + pthread_mutex_lock(&it->mutex); if (datadir_iter_next_file(it)) { @@ -413,7 +409,7 @@ datadir_iter_next(datadir_iter_t *it, datadir_node_t *node) ret = false; done: - os_mutex_exit(it->mutex); + pthread_mutex_unlock(&it->mutex); return(ret); } @@ -427,7 +423,7 @@ static void datadir_iter_free(datadir_iter_t *it) { - os_mutex_free(it->mutex); + pthread_mutex_destroy(&it->mutex); if (it->dbdir) { @@ -439,11 +435,11 @@ datadir_iter_free(datadir_iter_t *it) os_file_closedir(it->dir); } - ut_free(it->dbpath); - ut_free(it->filepath); - ut_free(it->filepath_rel); + free(it->dbpath); + free(it->filepath); + free(it->filepath_rel); free(it->datadir_path); - ut_free(it); + free(it); } @@ -466,17 +462,17 @@ static void datafile_close(datafile_cur_t *cursor) { - if (cursor->file != 0) { + if (cursor->file != OS_FILE_CLOSED) { os_file_close(cursor->file); } - ut_free(cursor->buf); + free(cursor->buf); } static bool datafile_open(const char *file, datafile_cur_t *cursor, uint thread_n) { - ulint success; + bool success; memset(cursor, 0, sizeof(datafile_cur_t)); @@ -490,11 +486,9 @@ datafile_open(const char *file, datafile_cur_t *cursor, uint thread_n) xb_get_relative_path(cursor->abs_path, FALSE), sizeof(cursor->rel_path)); - cursor->file = os_file_create_simple_no_error_handling(0, - cursor->abs_path, - OS_FILE_OPEN, - OS_FILE_READ_ONLY, - &success, 0); + cursor->file = os_file_create_simple_no_error_handling( + 0, cursor->abs_path, + OS_FILE_OPEN, OS_FILE_READ_ALLOW_DELETE, true, &success); if (!success) { /* The following call prints an error message */ os_file_get_last_error(TRUE); @@ -518,7 +512,7 @@ datafile_open(const char *file, datafile_cur_t *cursor, uint thread_n) posix_fadvise(cursor->file, 0, 0, POSIX_FADV_SEQUENTIAL); cursor->buf_size = 10 * 1024 * 1024; - cursor->buf = static_cast<byte *>(ut_malloc((ulint)cursor->buf_size)); + cursor->buf = static_cast<byte *>(malloc((ulint)cursor->buf_size)); return(true); } @@ -528,7 +522,6 @@ static xb_fil_cur_result_t datafile_read(datafile_cur_t *cursor) { - ulint success; ulint to_read; xtrabackup_io_throttling(); @@ -540,14 +533,14 @@ datafile_read(datafile_cur_t *cursor) return(XB_FIL_CUR_EOF); } - success = os_file_read(cursor->file, cursor->buf, cursor->buf_offset, - to_read); - if (!success) { + if (!os_file_read(IORequestRead, + cursor->file, cursor->buf, cursor->buf_offset, + to_read)) { return(XB_FIL_CUR_ERROR); } posix_fadvise(cursor->file, cursor->buf_offset, to_read, - POSIX_FADV_DONTNEED); + POSIX_FADV_DONTNEED); cursor->buf_read = to_read; cursor->buf_offset += to_read; @@ -917,13 +910,13 @@ run_data_threads(datadir_iter_t *it, os_thread_func_t func, uint n) { datadir_thread_ctxt_t *data_threads; uint i, count; - os_ib_mutex_t count_mutex; + pthread_mutex_t count_mutex; bool ret; data_threads = (datadir_thread_ctxt_t*) - (ut_malloc(sizeof(datadir_thread_ctxt_t) * n)); + malloc(sizeof(datadir_thread_ctxt_t) * n); - count_mutex = os_mutex_create(); + pthread_mutex_init(&count_mutex, NULL); count = n; for (i = 0; i < n; i++) { @@ -937,15 +930,15 @@ run_data_threads(datadir_iter_t *it, os_thread_func_t func, uint n) /* Wait for threads to exit */ while (1) { os_thread_sleep(100000); - os_mutex_enter(count_mutex); + pthread_mutex_lock(&count_mutex); if (count == 0) { - os_mutex_exit(count_mutex); + pthread_mutex_unlock(&count_mutex); break; } - os_mutex_exit(count_mutex); + pthread_mutex_unlock(&count_mutex); } - os_mutex_free(count_mutex); + pthread_mutex_destroy(&count_mutex); ret = true; for (i = 0; i < n; i++) { @@ -955,7 +948,7 @@ run_data_threads(datadir_iter_t *it, os_thread_func_t func, uint n) } } - ut_free(data_threads); + free(data_threads); return(ret); } @@ -974,7 +967,6 @@ copy_file(ds_ctxt_t *datasink, ds_file_t *dstfile = NULL; datafile_cur_t cursor; xb_fil_cur_result_t res; - const char *action; if (!datafile_open(src_file_path, &cursor, thread_n)) { goto error_close; @@ -991,9 +983,8 @@ copy_file(ds_ctxt_t *datasink, goto error; } - action = xb_get_copy_action(); msg_ts("[%02u] %s %s to %s\n", - thread_n, action, src_file_path, dstfile->path); + thread_n, xb_get_copy_action(), src_file_path, dstfile->path); /* The main copy loop */ while ((res = datafile_read(&cursor)) == XB_FIL_CUR_SUCCESS) { @@ -1111,7 +1102,7 @@ read_link_file(const char *ibd_filepath, const char *link_filepath) while (lastch > 4 && filepath[lastch] <= 0x20) { filepath[lastch--] = 0x00; } - srv_normalize_path_for_win(filepath); + os_normalize_path(filepath); } tablespace_locations[ibd_filepath] = filepath; @@ -1629,14 +1620,9 @@ apply_log_finish() return(true); } -extern void -os_io_init_simple(void); - bool copy_back() { - char *innobase_data_file_path_copy; - ulint i; bool ret; datadir_iter_t *it = NULL; datadir_node_t node; @@ -1679,24 +1665,16 @@ copy_back() if (!innobase_data_file_path) { innobase_data_file_path = (char*) "ibdata1:10M:autoextend"; } - innobase_data_file_path_copy = strdup(innobase_data_file_path); - if (!(ret = srv_parse_data_file_paths_and_sizes( - innobase_data_file_path_copy))) { + srv_sys_space.set_path("."); + + if (!srv_sys_space.parse_params(innobase_data_file_path, true)) { msg("syntax error in innodb_data_file_path\n"); return(false); } srv_max_n_threads = 1000; - //os_sync_mutex = NULL; - ut_mem_init(); - /* temporally dummy value to avoid crash */ - srv_page_size_shift = 14; - srv_page_size = (1 << srv_page_size_shift); - os_sync_init(); - sync_init(); - os_io_init_simple(); - mem_init(srv_mem_pool_size); + sync_check_init(); ut_crc32_init(); /* copy undo tablespaces */ @@ -1707,9 +1685,9 @@ copy_back() ds_data = ds_create(dst_dir, DS_TYPE_LOCAL); - for (i = 1; i <= srv_undo_tablespaces; i++) { + for (ulong i = 1; i <= srv_undo_tablespaces; i++) { char filename[20]; - sprintf(filename, "undo%03u", (uint)i); + sprintf(filename, "undo%03lu", i); if (!(ret = copy_or_move_file(filename, filename, dst_dir, 1))) { goto cleanup; @@ -1720,29 +1698,30 @@ copy_back() ds_data = NULL; } - /* copy redo logs */ - dst_dir = (srv_log_group_home_dir && *srv_log_group_home_dir) - ? srv_log_group_home_dir : mysql_data_home; - - ds_data = ds_create(dst_dir, DS_TYPE_LOCAL); + ? srv_log_group_home_dir : mysql_data_home; - for (i = 0; i < (ulong)innobase_log_files_in_group; i++) { - char filename[20]; - sprintf(filename, "ib_logfile%lu", i); - - if (!file_exists(filename)) { - continue; - } + /* --backup generates a single ib_logfile0, which we must copy + if it exists. */ - if (!(ret = copy_or_move_file(filename, filename, - dst_dir, 1))) { - goto cleanup; + ds_data = ds_create(dst_dir, DS_TYPE_LOCAL); + if (!file_exists("ib_logfile0")) { + /* After completed --prepare, redo log files are redundant. + We must delete any redo logs at the destination, so that + the database will not jump to a different log sequence number + (LSN). */ + + for (uint i = 0; i <= SRV_N_LOG_FILES_MAX + 1; i++) { + char filename[FN_REFLEN]; + snprintf(filename, sizeof filename, "%s/ib_logfile%u", + dst_dir, i); + unlink(filename); } + } else if (!(ret = copy_or_move_file("ib_logfile0", "ib_logfile0", + dst_dir, 1))) { + goto cleanup; } - ds_destroy(ds_data); - ds_data = NULL; /* copy innodb system tablespace(s) */ @@ -1751,17 +1730,19 @@ copy_back() ds_data = ds_create(dst_dir, DS_TYPE_LOCAL); - for (i = 0; i < srv_n_data_files; i++) { - const char *filename = base_name(srv_data_file_names[i]); + for (Tablespace::const_iterator iter(srv_sys_space.begin()), + end(srv_sys_space.end()); + iter != end; + ++iter) { + const char *filename = base_name(iter->name()); - if (!(ret = copy_or_move_file(filename, srv_data_file_names[i], + if (!(ret = copy_or_move_file(filename, iter->name(), dst_dir, 1))) { goto cleanup; } } ds_destroy(ds_data); - ds_data = NULL; /* copy the rest of tablespaces */ ds_data = ds_create(mysql_data_home, DS_TYPE_LOCAL); @@ -1771,7 +1752,7 @@ copy_back() datadir_node_init(&node); while (datadir_iter_next(it, &node)) { - const char *ext_list[] = {"backup-my.cnf", "xtrabackup_logfile", + const char *ext_list[] = {"backup-my.cnf", "xtrabackup_binary", "xtrabackup_binlog_info", "xtrabackup_checkpoints", ".qp", ".pmap", ".tmp", NULL}; @@ -1817,21 +1798,18 @@ copy_back() continue; } - /* skip redo logs */ - if (sscanf(filename, "ib_logfile%d%c", &i_tmp, &c_tmp) == 1) { + /* skip the redo log (it was already copied) */ + if (!strcmp(filename, "ib_logfile0")) { continue; } /* skip innodb data files */ is_ibdata_file = false; - for (i = 0; i < srv_n_data_files; i++) { - const char *ibfile; - - ibfile = base_name(srv_data_file_names[i]); - - if (strcmp(ibfile, filename) == 0) { + for (Tablespace::const_iterator iter(srv_sys_space.begin()), + end(srv_sys_space.end()); iter != end; ++iter) { + if (strcmp(iter->name(), filename) == 0) { is_ibdata_file = true; - continue; + break; } } if (is_ibdata_file) { @@ -1873,20 +1851,13 @@ cleanup: datadir_node_free(&node); - free(innobase_data_file_path_copy); - if (ds_data != NULL) { ds_destroy(ds_data); } ds_data = NULL; - //os_sync_free(); - mem_close(); - //os_sync_mutex = NULL; - ut_free_all_mem(); - sync_close(); - sync_initialized = FALSE; + sync_check_close(); return(ret); } @@ -1965,9 +1936,9 @@ cleanup: datadir_node_free(&node); - os_mutex_enter(ctxt->count_mutex); + pthread_mutex_lock(&ctxt->count_mutex); --(*ctxt->count); - os_mutex_exit(ctxt->count_mutex); + pthread_mutex_unlock(&ctxt->count_mutex); ctxt->ret = ret; @@ -1982,10 +1953,7 @@ decrypt_decompress() datadir_iter_t *it = NULL; srv_max_n_threads = 1000; - //os_sync_mutex = NULL; - ut_mem_init(); - os_sync_init(); - sync_init(); + sync_check_init(); /* cd to backup directory */ if (my_setwd(xtrabackup_target_dir, MYF(MY_WME))) @@ -2014,11 +1982,7 @@ decrypt_decompress() ds_data = NULL; - sync_close(); - sync_initialized = FALSE; - //os_sync_free(); - //os_sync_mutex = NULL; - ut_free_all_mem(); + sync_check_close(); return(ret); } diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index 2353c7692cb..c6ec54c3a6c 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -54,6 +54,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "mysqld.h" #include "encryption_plugin.h" #include <sstream> +#include <sql_error.h> char *tool_name; @@ -494,7 +495,7 @@ get_mysql_vars(MYSQL *connection) && innodb_log_files_in_group_var) { char *endptr; - innobase_log_files_in_group = strtol( + srv_n_log_files = strtol( innodb_log_files_in_group_var, &endptr, 10); ut_ad(*endptr == 0); } @@ -503,7 +504,7 @@ get_mysql_vars(MYSQL *connection) && innodb_log_file_size_var) { char *endptr; - innobase_log_file_size = strtoll( + srv_log_file_size = strtoll( innodb_log_file_size_var, &endptr, 10); ut_ad(*endptr == 0); } @@ -850,9 +851,9 @@ static void start_query_killer() { - kill_query_thread_stop = os_event_create(); - kill_query_thread_started = os_event_create(); - kill_query_thread_stopped = os_event_create(); + 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, NULL, &kill_query_thread_id); @@ -1368,17 +1369,27 @@ cleanup: return(result); } -static string escape_and_quote(MYSQL *mysql,const char *str) +struct escape_and_quote { - if (!str) - return "NULL"; - size_t len = strlen(str); - char* escaped = (char *)alloca(2 * len + 3); - escaped[0] = '\''; - size_t new_len = mysql_real_escape_string(mysql, escaped+1, str, len); - escaped[new_len + 1] = '\''; - escaped[new_len + 2] = 0; - return string(escaped); + escape_and_quote(MYSQL *mysql, const char *str) + : mysql(mysql), str(str) {} + MYSQL * const mysql; + const char * const str; +}; + +static +std::ostream& +operator<<(std::ostream& s, const escape_and_quote& eq) +{ + if (!eq.str) + return s << "NULL"; + s << '\''; + size_t len = strlen(eq.str); + char* escaped = (char *)alloca(2 * len + 1); + len = mysql_real_escape_string(eq.mysql, escaped, eq.str, len); + s << std::string(escaped, len); + s << '\''; + return s; } /*********************************************************************//** @@ -1395,12 +1406,9 @@ write_xtrabackup_info(MYSQL *connection) char buf_start_time[100]; char buf_end_time[100]; tm tm; - ostringstream oss; + std::ostringstream oss; const char *xb_stream_name[] = {"file", "tar", "xbstream"}; - - ut_ad(xtrabackup_stream_fmt < 3); - uuid = read_mysql_one_value(connection, "SELECT UUID()"); server_version = read_mysql_one_value(connection, "SELECT VERSION()"); localtime_r(&history_start_time, &tm); @@ -1528,28 +1536,21 @@ bool write_backup_config_file() "# The MySQL server\n" "[mysqld]\n" "innodb_checksum_algorithm=%s\n" - "innodb_log_checksum_algorithm=%s\n" "innodb_data_file_path=%s\n" "innodb_log_files_in_group=%lu\n" - "innodb_log_file_size=%lld\n" + "innodb_log_file_size=%llu\n" "innodb_page_size=%lu\n" - "innodb_log_block_size=%lu\n" "innodb_undo_directory=%s\n" "innodb_undo_tablespaces=%lu\n" "%s%s\n" - "%s%s\n" "%s\n", innodb_checksum_algorithm_names[srv_checksum_algorithm], - innodb_checksum_algorithm_names[srv_log_checksum_algorithm], innobase_data_file_path, srv_n_log_files, - innobase_log_file_size, + srv_log_file_size, srv_page_size, - srv_log_block_size, srv_undo_dir, srv_undo_tablespaces, - innobase_doublewrite_file ? "innodb_doublewrite_file=" : "", - innobase_doublewrite_file ? innobase_doublewrite_file : "", innobase_buffer_pool_filename ? "innodb_buffer_pool_filename=" : "", innobase_buffer_pool_filename ? diff --git a/extra/mariabackup/wsrep.h b/extra/mariabackup/backup_wsrep.h index 7638d1f2b54..6537b304e12 100644 --- a/extra/mariabackup/wsrep.h +++ b/extra/mariabackup/backup_wsrep.h @@ -19,8 +19,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *******************************************************/ -#ifndef WSREP_H -#define WSREP_H +#ifndef BACKUP_WSREP_H +#define BACKUP_WSREP_H /*********************************************************************** Store Galera checkpoint info in the 'xtrabackup_galera_info' file, if that diff --git a/extra/mariabackup/changed_page_bitmap.cc b/extra/mariabackup/changed_page_bitmap.cc index 86a873ef69c..ce769375a16 100644 --- a/extra/mariabackup/changed_page_bitmap.cc +++ b/extra/mariabackup/changed_page_bitmap.cc @@ -193,9 +193,9 @@ log_online_read_bitmap_page( 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(bitmap_file->file, page, bitmap_file->offset, - MODIFIED_PAGE_BLOCK_SIZE); + success = os_file_read(IORequestRead, + bitmap_file->file, page, bitmap_file->offset, + MODIFIED_PAGE_BLOCK_SIZE); if (UNIV_UNLIKELY(!success)) { @@ -355,8 +355,7 @@ log_online_setup_bitmap_file_range( bitmap_files->files = static_cast<log_online_bitmap_file_range_t::files_t *> - (ut_malloc(bitmap_files->count - * sizeof(bitmap_files->files[0]))); + (malloc(bitmap_files->count * sizeof(bitmap_files->files[0]))); memset(bitmap_files->files, 0, bitmap_files->count * sizeof(bitmap_files->files[0])); @@ -426,9 +425,9 @@ log_online_setup_bitmap_file_range( /****************************************************************//** Open a bitmap file for reading. -@return TRUE if opened successfully */ +@return whether opened successfully */ static -ibool +bool log_online_open_bitmap_file_read_only( /*==================================*/ const char* name, /*!<in: bitmap file @@ -438,23 +437,21 @@ log_online_open_bitmap_file_read_only( log_online_bitmap_file_t* bitmap_file) /*!<out: opened bitmap file */ { - ibool success = FALSE; + bool success = false; xb_ad(name[0] != '\0'); ut_snprintf(bitmap_file->name, FN_REFLEN, "%s%s", srv_data_home, name); - bitmap_file->file - = os_file_create_simple_no_error_handling(0, bitmap_file->name, - OS_FILE_OPEN, - OS_FILE_READ_ONLY, - &success,0); + bitmap_file->file = os_file_create_simple_no_error_handling( + 0, bitmap_file->name, + OS_FILE_OPEN, OS_FILE_READ_ONLY, true, &success); if (UNIV_UNLIKELY(!success)) { /* Here and below assume that bitmap file names do not contain apostrophes, thus no need for ut_print_filename(). */ msg("InnoDB: Warning: error opening the changed page " "bitmap \'%s\'\n", bitmap_file->name); - return FALSE; + return success; } bitmap_file->size = os_file_get_size(bitmap_file->file); @@ -465,7 +462,7 @@ log_online_open_bitmap_file_read_only( posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_NOREUSE); #endif - return TRUE; + return success; } /****************************************************************//** @@ -909,6 +906,37 @@ xb_page_bitmap_setup_next_page( return TRUE; } +/** Find the node with the smallest key that greater than equal to search key. +@param[in] tree red-black tree +@param[in] key search key +@return node with the smallest greater-than-or-equal key +@retval NULL if none was found */ +static +const ib_rbt_node_t* +rbt_lower_bound(const ib_rbt_t* tree, const void* key) +{ + ut_ad(!tree->cmp_arg); + const ib_rbt_node_t* ge = NULL; + + for (const ib_rbt_node_t *node = tree->root->left; + node != tree->nil; ) { + int result = tree->compare(node->value, key); + + if (result < 0) { + node = node->right; + } else { + ge = node; + if (result == 0) { + break; + } + + node = node->left; + } + } + + return(ge); +} + /****************************************************************//** Set up a new bitmap range iterator over a given space id changed pages in a given bitmap. @@ -922,8 +950,7 @@ xb_page_bitmap_range_init( { byte search_page[MODIFIED_PAGE_BLOCK_SIZE]; xb_page_bitmap_range *result - = static_cast<xb_page_bitmap_range *> - (ut_malloc(sizeof(*result))); + = static_cast<xb_page_bitmap_range *>(malloc(sizeof(*result))); memset(result, 0, sizeof(*result)); result->bitmap = bitmap; @@ -1014,5 +1041,5 @@ xb_page_bitmap_range_deinit( /*========================*/ xb_page_bitmap_range* bitmap_range) /*! in/out: bitmap range */ { - ut_free(bitmap_range); + free(bitmap_range); } diff --git a/extra/mariabackup/encryption_plugin.cc b/extra/mariabackup/encryption_plugin.cc index 8f7741b057a..76512c185e2 100644 --- a/extra/mariabackup/encryption_plugin.cc +++ b/extra/mariabackup/encryption_plugin.cc @@ -8,6 +8,7 @@ #include <vector> #include <common.h> #include <backup_mysql.h> +#include <log0crypt.h> extern struct st_maria_plugin *mysql_optional_plugins[]; @@ -18,14 +19,14 @@ extern char *xb_plugin_load; extern char *xb_plugin_dir; const int PLUGIN_MAX_ARGS = 1024; -vector<string> backup_plugins_args; +std::vector<std::string> backup_plugins_args; const char *QUERY_PLUGIN = "SELECT plugin_name, plugin_library, @@plugin_dir" " FROM information_schema.plugins WHERE plugin_type='ENCRYPTION'" " AND plugin_status='ACTIVE'"; -string encryption_plugin_config; +std::string encryption_plugin_config; static void add_to_plugin_load_list(const char *plugin_def) { @@ -38,7 +39,7 @@ void encryption_plugin_backup_init(MYSQL *mysql) { MYSQL_RES *result; MYSQL_ROW row; - ostringstream oss; + std::ostringstream oss; char *argv[PLUGIN_MAX_ARGS]; int argc; @@ -59,17 +60,17 @@ void encryption_plugin_backup_init(MYSQL *mysql) if (*p == '\\') *p = '/'; #endif - string plugin_load(name); + std::string plugin_load(name); if (library) - plugin_load += string("=") + library; + plugin_load += std::string("=") + library; - oss << "plugin_load=" << plugin_load << endl; + oss << "plugin_load=" << plugin_load << std::endl; /* Required to load the plugin later.*/ add_to_plugin_load_list(plugin_load.c_str()); strncpy(opt_plugin_dir, dir, FN_REFLEN); - oss << "plugin_dir=" << '"' << dir << '"' << endl; + oss << "plugin_dir=" << '"' << dir << '"' << std::endl; /* Read plugin variables. */ @@ -80,12 +81,12 @@ void encryption_plugin_backup_init(MYSQL *mysql) result = xb_mysql_query(mysql, query, true, true); while ((row = mysql_fetch_row(result))) { - string arg("--"); + std::string arg("--"); arg += row[0]; arg += "="; arg += row[1]; backup_plugins_args.push_back(arg); - oss << row[0] << "=" << row[1] << endl; + oss << row[0] << "=" << row[1] << std::endl; } mysql_free_result(result); @@ -94,7 +95,7 @@ void encryption_plugin_backup_init(MYSQL *mysql) result = xb_mysql_query(mysql, "select @@innodb_encrypt_log", true, true); row = mysql_fetch_row(result); srv_encrypt_log = (row != 0 && row[0][0] == '1'); - oss << "innodb_encrypt_log=" << row[0] << endl; + oss << "innodb_encrypt_log=" << row[0] << std::endl; mysql_free_result(result); diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index 820d8e10c29..9df5f8e8fa3 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -24,8 +24,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #include <my_base.h> -#include <univ.i> #include <fil0fil.h> +#include <fsp0fsp.h> #include <srv0start.h> #include <trx0sys.h> @@ -63,7 +63,7 @@ xb_get_relative_path( prev = NULL; cur = path; - while ((next = strchr(cur, SRV_PATH_SEPARATOR)) != NULL) { + while ((next = strchr(cur, OS_PATH_SEPARATOR)) != NULL) { prev = cur; cur = next + 1; @@ -96,7 +96,7 @@ xb_fil_node_close_file( ut_a(node->n_pending_flushes == 0); ut_a(!node->being_extended); - if (!node->open) { + if (!node->is_open()) { mutex_exit(&fil_system->mutex); @@ -106,19 +106,19 @@ xb_fil_node_close_file( ret = os_file_close(node->handle); ut_a(ret); - node->open = FALSE; + node->handle = OS_FILE_CLOSED; ut_a(fil_system->n_open > 0); fil_system->n_open--; fil_n_file_opened--; - if (node->space->purpose == FIL_TABLESPACE && + if (node->space->purpose == FIL_TYPE_TABLESPACE && fil_is_user_tablespace_id(node->space->id)) { ut_a(UT_LIST_GET_LEN(fil_system->LRU) > 0); /* The node is in the LRU list, remove it */ - UT_LIST_REMOVE(LRU, fil_system->LRU, node); + UT_LIST_REMOVE(fil_system->LRU, node); } mutex_exit(&fil_system->mutex); @@ -137,10 +137,7 @@ xb_fil_cur_open( fil_node_t* node, /*!< in: source tablespace node */ uint thread_n) /*!< thread number for diagnostics */ { - ulint page_size; - ulint page_size_shift; - ulint zip_size; - ibool success; + bool success; /* Initialize these first so xb_fil_cur_close() handles them correctly in case of error */ @@ -148,27 +145,26 @@ xb_fil_cur_open( cursor->node = NULL; cursor->space_id = node->space->id; - cursor->is_system = !fil_is_user_tablespace_id(node->space->id); strncpy(cursor->abs_path, node->name, sizeof(cursor->abs_path)); /* Get the relative path for the destination tablespace name, i.e. the one that can be appended to the backup root directory. Non-system - tablespaces may have absolute paths for remote tablespaces in MySQL - 5.6+. We want to make "local" copies for the backup. */ + tablespaces may have absolute paths for DATA DIRECTORY. + We want to make "local" copies for the backup. */ strncpy(cursor->rel_path, - xb_get_relative_path(cursor->abs_path, cursor->is_system), + xb_get_relative_path(cursor->abs_path, cursor->is_system()), sizeof(cursor->rel_path)); /* In the backup mode we should already have a tablespace handle created - by fil_load_single_table_tablespace() unless it is a system + by fil_ibd_load() unless it is a system tablespace. Otherwise we open the file here. */ - if (cursor->is_system || !srv_backup_mode || srv_close_files) { - node->handle = - os_file_create_simple_no_error_handling(0, node->name, - OS_FILE_OPEN, - OS_FILE_READ_ONLY, - &success,0); + if (cursor->is_system() || srv_operation == SRV_OPERATION_RESTORE + || xb_close_files) { + node->handle = os_file_create_simple_no_error_handling( + 0, node->name, + OS_FILE_OPEN, + OS_FILE_READ_ALLOW_DELETE, true, &success); if (!success) { /* The following call prints an error message */ os_file_get_last_error(TRUE); @@ -181,22 +177,20 @@ xb_fil_cur_open( } mutex_enter(&fil_system->mutex); - node->open = TRUE; - fil_system->n_open++; fil_n_file_opened++; - if (node->space->purpose == FIL_TABLESPACE && + if (node->space->purpose == FIL_TYPE_TABLESPACE && fil_is_user_tablespace_id(node->space->id)) { /* Put the node to the LRU list */ - UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); + UT_LIST_ADD_FIRST(fil_system->LRU, node); } mutex_exit(&fil_system->mutex); } - ut_ad(node->open); + ut_ad(node->is_open()); cursor->node = node; cursor->file = node->handle; @@ -210,8 +204,8 @@ xb_fil_cur_open( return(XB_FIL_CUR_ERROR); } - if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT - || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC) { + if (srv_file_flush_method == SRV_O_DIRECT + || srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) { os_file_set_nocache(cursor->file, node->name, "OPEN"); } @@ -219,32 +213,29 @@ xb_fil_cur_open( posix_fadvise(cursor->file, 0, 0, POSIX_FADV_SEQUENTIAL); /* Determine the page size */ - zip_size = xb_get_zip_size(cursor->file); - if (zip_size == ULINT_UNDEFINED) { + ulint flags = xb_get_space_flags(cursor->file); + if (flags == ULINT_UNDEFINED) { xb_fil_cur_close(cursor); return(XB_FIL_CUR_SKIP); - } else if (zip_size) { - page_size = zip_size; - page_size_shift = get_bit_shift(page_size); - msg("[%02u] %s is compressed with page size = " - "%lu bytes\n", thread_n, node->name, page_size); - if (page_size_shift < 10 || page_size_shift > 14) { + } + + if (!fsp_flags_is_valid(flags)) { + ulint cflags = fsp_flags_convert_from_101(flags); + if (cflags == ULINT_UNDEFINED) { msg("[%02u] xtrabackup: Error: Invalid " - "page size: %lu.\n", thread_n, page_size); - ut_error; + "tablespace flags: %x.\n", thread_n, uint(flags)); + return(XB_FIL_CUR_SKIP); } - } else { - page_size = UNIV_PAGE_SIZE; - page_size_shift = UNIV_PAGE_SIZE_SHIFT; + flags = cflags; } + + const page_size_t page_size(flags); cursor->page_size = page_size; - cursor->page_size_shift = page_size_shift; - cursor->zip_size = zip_size; /* Allocate read buffer */ - cursor->buf_size = XB_FIL_CUR_PAGES * page_size; + cursor->buf_size = XB_FIL_CUR_PAGES * page_size.physical(); cursor->orig_buf = static_cast<byte *> - (ut_malloc(cursor->buf_size + UNIV_PAGE_SIZE)); + (malloc(cursor->buf_size + UNIV_PAGE_SIZE)); cursor->buf = static_cast<byte *> (ut_align(cursor->orig_buf, UNIV_PAGE_SIZE)); @@ -254,7 +245,8 @@ xb_fil_cur_open( cursor->buf_page_no = 0; cursor->thread_n = thread_n; - cursor->space_size = (ulint)(cursor->statinfo.st_size / page_size); + cursor->space_size = (ulint)(cursor->statinfo.st_size + / page_size.physical()); cursor->read_filter = read_filter; cursor->read_filter->init(&cursor->read_filter_ctxt, cursor, @@ -282,6 +274,8 @@ xb_fil_cur_read( xb_fil_cur_result_t ret; ib_int64_t offset; ib_int64_t to_read; + const ulint page_size = cursor->page_size.physical(); + xb_ad(!cursor->is_system() || page_size == UNIV_PAGE_SIZE); cursor->read_filter->get_next_batch(&cursor->read_filter_ctxt, &offset, &to_read); @@ -296,10 +290,10 @@ xb_fil_cur_read( xb_a(to_read > 0 && to_read <= 0xFFFFFFFFLL); - if (to_read % cursor->page_size != 0 && - offset + to_read == cursor->statinfo.st_size) { + if ((to_read & ~(page_size - 1)) + && offset + to_read == cursor->statinfo.st_size) { - if (to_read < (ib_int64_t) cursor->page_size) { + if (to_read < (ib_int64_t) page_size) { msg("[%02u] xtrabackup: Warning: junk at the end of " "%s:\n", cursor->thread_n, cursor->abs_path); msg("[%02u] xtrabackup: Warning: offset = %llu, " @@ -312,12 +306,12 @@ xb_fil_cur_read( } to_read = (ib_int64_t) (((ulint) to_read) & - ~(cursor->page_size - 1)); + ~(page_size - 1)); } - xb_a(to_read % cursor->page_size == 0); + xb_a((to_read & (page_size - 1)) == 0); - npages = (ulint) (to_read >> cursor->page_size_shift); + npages = (ulint) (to_read / cursor->page_size.physical()); retry_count = 10; ret = XB_FIL_CUR_SUCCESS; @@ -328,59 +322,59 @@ read_retry: cursor->buf_read = 0; cursor->buf_npages = 0; cursor->buf_offset = offset; - cursor->buf_page_no = (ulint)(offset >> cursor->page_size_shift); + cursor->buf_page_no = (ulint)(offset / cursor->page_size.physical()); - success = os_file_read(cursor->file, cursor->buf, offset, - (ulint)to_read); - if (!success) { + FilSpace space(cursor->space_id); + + if (!space()) { return(XB_FIL_CUR_ERROR); } - fil_system_enter(); - fil_space_t *space = fil_space_get_by_id(cursor->space_id); - fil_system_exit(); + success = os_file_read(IORequestRead, + cursor->file, cursor->buf, offset, + (ulint) to_read); + if (!success) { + return(XB_FIL_CUR_ERROR); + } /* 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 += cursor->page_size, i++) { - ib_int64_t page_no = cursor->buf_page_no + i; - - bool checksum_ok = fil_space_verify_crypt_checksum(page, cursor->zip_size,space, (ulint)page_no); - - if (!checksum_ok && - buf_page_is_corrupted(true, page, cursor->zip_size,space)) { - - if (cursor->is_system && - page_no >= (ib_int64_t)FSP_EXTENT_SIZE && - page_no < (ib_int64_t) FSP_EXTENT_SIZE * 3) { - /* skip doublewrite buffer pages */ - xb_a(cursor->page_size == UNIV_PAGE_SIZE); + page += page_size, i++) { + ulint page_no = cursor->buf_page_no + i; + + if (cursor->space_id == TRX_SYS_SPACE && + page_no >= FSP_EXTENT_SIZE && + page_no < FSP_EXTENT_SIZE * 3) { + /* We ignore the doublewrite buffer pages */ + } else if (!fil_space_verify_crypt_checksum( + page, cursor->page_size, space->id, page_no) + && buf_page_is_corrupted(true, page, + cursor->page_size, + space)) { + retry_count--; + if (retry_count == 0) { msg("[%02u] xtrabackup: " - "Page %lu is a doublewrite buffer page, " - "skipping.\n", cursor->thread_n, page_no); - } else { - retry_count--; - if (retry_count == 0) { - msg("[%02u] xtrabackup: " - "Error: failed to read page after " - "10 retries. File %s seems to be " - "corrupted.\n", cursor->thread_n, - cursor->abs_path); - ret = XB_FIL_CUR_ERROR; - break; - } + "Error: failed to read page after " + "10 retries. File %s seems to be " + "corrupted.\n", cursor->thread_n, + cursor->abs_path); + ret = XB_FIL_CUR_ERROR; + break; + } + + if (retry_count == 9) { msg("[%02u] xtrabackup: " "Database page corruption detected at page " - "%lu, retrying...\n", cursor->thread_n, - page_no); + ULINTPF ", retrying...\n", + cursor->thread_n, page_no); + } - os_thread_sleep(100000); + os_thread_sleep(100000); - goto read_retry; - } + goto read_retry; } - cursor->buf_read += cursor->page_size; + cursor->buf_read += page_size; cursor->buf_npages++; } @@ -399,11 +393,10 @@ xb_fil_cur_close( { cursor->read_filter->deinit(&cursor->read_filter_ctxt); - if (cursor->orig_buf != NULL) { - ut_free(cursor->orig_buf); - } + free(cursor->orig_buf); + if (cursor->node != NULL) { xb_fil_node_close_file(cursor->node); - cursor->file = XB_FILE_UNDEFINED; + cursor->file = OS_FILE_CLOSED; } } diff --git a/extra/mariabackup/fil_cur.h b/extra/mariabackup/fil_cur.h index f3601823a5a..e3f356a346c 100644 --- a/extra/mariabackup/fil_cur.h +++ b/extra/mariabackup/fil_cur.h @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #include <my_dir.h> #include "read_filt.h" +#include "srv0start.h" struct xb_fil_cur_t { pfs_os_file_t file; /*!< source file handle */ @@ -36,14 +37,7 @@ struct xb_fil_cur_t { char abs_path[FN_REFLEN]; /*!< absolute file path */ MY_STAT statinfo; /*!< information about the file */ - ulint zip_size; /*!< compressed page size in bytes or 0 - for uncompressed pages */ - ulint page_size; /*!< = zip_size for compressed pages or - UNIV_PAGE_SIZE for uncompressed ones */ - ulint page_size_shift;/*!< bit shift corresponding to - page_size */ - my_bool is_system; /*!< TRUE for system tablespace, FALSE - otherwise */ + page_size_t page_size; /*!< page size */ xb_read_filt_t* read_filter; /*!< read filter */ xb_read_filt_ctxt_t read_filter_ctxt; /*!< read filter context */ @@ -61,6 +55,17 @@ struct xb_fil_cur_t { uint thread_n; /*!< thread number for diagnostics */ ulint space_id; /*!< ID of tablespace */ ulint space_size; /*!< space size in pages */ + + /** TODO: remove this default constructor */ + xb_fil_cur_t() : page_size(0), read_filter_ctxt() {} + + /** @return whether this is not a file-per-table tablespace */ + bool is_system() const + { + ut_ad(space_id != SRV_TMP_SPACE_ID); + return(space_id == TRX_SYS_SPACE + || srv_is_undo_tablespace(space_id)); + } }; typedef enum { diff --git a/extra/mariabackup/innobackupex.cc b/extra/mariabackup/innobackupex.cc index 7e97b258489..4fb85208eff 100644 --- a/extra/mariabackup/innobackupex.cc +++ b/extra/mariabackup/innobackupex.cc @@ -45,7 +45,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include <mysql.h> #include <my_dir.h> #include <ut0mem.h> -#include <os0sync.h> #include <os0file.h> #include <srv0start.h> #include <algorithm> @@ -70,7 +69,6 @@ using std::max; my_bool opt_ibx_version = FALSE; my_bool opt_ibx_help = FALSE; my_bool opt_ibx_apply_log = FALSE; -my_bool opt_ibx_redo_only = FALSE; my_bool opt_ibx_incremental = FALSE; my_bool opt_ibx_notimestamp = FALSE; @@ -226,21 +224,11 @@ static struct my_option ibx_long_options[] = GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"apply-log", OPT_APPLY_LOG, "Prepare a backup in BACKUP-DIR by " - "applying the transaction log file named \"xtrabackup_logfile\" " - "located in the same directory. Also, create new transaction logs. " + "applying the redo log 'ib_logfile0' and creating new redo log. " "The InnoDB configuration is read from the file \"backup-my.cnf\".", (uchar*) &opt_ibx_apply_log, (uchar*) &opt_ibx_apply_log, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"redo-only", OPT_REDO_ONLY, "This option should be used when " - "preparing the base full backup and when merging all incrementals " - "except the last one. This forces xtrabackup to skip the \"rollback\" " - "phase and do a \"redo\" only. This is necessary if the backup will " - "have incremental changes applied to it later. See the xtrabackup " - "documentation for details.", - (uchar *) &opt_ibx_redo_only, (uchar *) &opt_ibx_redo_only, 0, - GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"copy-back", OPT_COPY_BACK, "Copy all the files in a previously made " "backup from the backup directory to their original locations.", (uchar *) &opt_ibx_copy_back, (uchar *) &opt_ibx_copy_back, 0, @@ -682,7 +670,7 @@ innobackupex [--compress] [--compress-threads=NUMBER-OF-THREADS] [--compress-chu \n\ innobackupex --apply-log [--use-memory=B]\n\ [--defaults-file=MY.CNF]\n\ - [--export] [--redo-only] [--ibbackup=IBBACKUP-BINARY]\n\ + [--export] [--ibbackup=IBBACKUP-BINARY]\n\ BACKUP-DIR\n\ \n\ innobackupex --copy-back [--defaults-file=MY.CNF] [--defaults-group=GROUP-NAME] BACKUP-DIR\n\ @@ -710,7 +698,7 @@ process.\n\ \n\ The --apply-log command prepares a backup for starting a MySQL\n\ server on the backup. This command recovers InnoDB data files as specified\n\ -in BACKUP-DIR/backup-my.cnf using BACKUP-DIR/xtrabackup_logfile,\n\ +in BACKUP-DIR/backup-my.cnf using BACKUP-DIR/ib_logfile0,\n\ and creates new InnoDB log files as specified in BACKUP-DIR/backup-my.cnf.\n\ The BACKUP-DIR should be the path to a backup directory created by\n\ xtrabackup. This command runs xtrabackup as a child process, but it does not \n\ @@ -980,9 +968,6 @@ ibx_init() switch (ibx_mode) { case IBX_MODE_APPLY_LOG: xtrabackup_prepare = TRUE; - if (opt_ibx_redo_only) { - xtrabackup_apply_log_only = TRUE; - } xtrabackup_target_dir = ibx_position_arg; run = "apply-log"; break; diff --git a/extra/mariabackup/read_filt.cc b/extra/mariabackup/read_filt.cc index 05e6b7c86c7..a48591abf29 100644 --- a/extra/mariabackup/read_filt.cc +++ b/extra/mariabackup/read_filt.cc @@ -127,10 +127,11 @@ rf_bitmap_get_next_batch( of pages */ { ulint start_page_id; + const ulint page_size = ctxt->page_size.physical(); - start_page_id = (ulint)(ctxt->offset / ctxt->page_size); + start_page_id = (ulint)(ctxt->offset / page_size); - xb_a (ctxt->offset % ctxt->page_size == 0); + xb_a (ctxt->offset % page_size == 0); if (start_page_id == ctxt->filter_batch_end) { @@ -146,7 +147,7 @@ rf_bitmap_get_next_batch( return; } - ctxt->offset = next_page_id * ctxt->page_size; + ctxt->offset = next_page_id * page_size; /* Find the end of the current changed page block by searching for the next cleared bitmap bit */ @@ -162,7 +163,7 @@ rf_bitmap_get_next_batch( remaining pages. */ *read_batch_len = ctxt->data_file_size - ctxt->offset; } else { - *read_batch_len = ctxt->filter_batch_end * ctxt->page_size + *read_batch_len = ctxt->filter_batch_end * page_size - ctxt->offset; } @@ -175,9 +176,9 @@ rf_bitmap_get_next_batch( } ctxt->offset += *read_batch_len; - xb_a (ctxt->offset % ctxt->page_size == 0); - xb_a (*read_batch_start % ctxt->page_size == 0); - xb_a (*read_batch_len % ctxt->page_size == 0); + xb_a (ctxt->offset % page_size == 0); + xb_a (*read_batch_start % page_size == 0); + xb_a (*read_batch_len % page_size == 0); } /****************************************************************//** diff --git a/extra/mariabackup/read_filt.h b/extra/mariabackup/read_filt.h index d16f4e1093d..cebc714eed8 100644 --- a/extra/mariabackup/read_filt.h +++ b/extra/mariabackup/read_filt.h @@ -27,6 +27,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #include "changed_page_bitmap.h" +typedef ulint space_id_t; + struct xb_fil_cur_t; /* The read filter context */ @@ -34,15 +36,17 @@ struct xb_read_filt_ctxt_t { ib_int64_t offset; /*!< current file offset */ ib_int64_t data_file_size; /*!< data file size */ size_t buffer_capacity;/*!< read buffer capacity */ - ib_int64_t space_id; /*!< space id */ + space_id_t space_id; /*!< space id */ /* The following fields used only in bitmap filter */ /* Move these to union if any other filters are added in future */ xb_page_bitmap_range *bitmap_range; /*!< changed page bitmap range iterator for space_id */ - size_t page_size; /*!< page size */ + page_size_t page_size; /*!< page size */ ulint filter_batch_end;/*!< the ending page id of the current changed page block in the bitmap */ + /** TODO: remove this default constructor */ + xb_read_filt_ctxt_t() : page_size(0) {} }; /* The read filter */ diff --git a/extra/mariabackup/write_filt.cc b/extra/mariabackup/write_filt.cc index cf7753bf380..a0633818405 100644 --- a/extra/mariabackup/write_filt.cc +++ b/extra/mariabackup/write_filt.cc @@ -67,7 +67,6 @@ wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name, xb_fil_cur_t *cursor) { char meta_name[FN_REFLEN]; - xb_delta_info_t info; ulint buf_size; xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt); @@ -75,8 +74,9 @@ wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name, ctxt->cursor = cursor; /* allocate buffer for incremental backup (4096 pages) */ - buf_size = (cursor->page_size / 4 + 1) * cursor->page_size; - cp->delta_buf_base = static_cast<byte *>(ut_malloc(buf_size)); + buf_size = (cursor->page_size.physical() / 4 + 1) + * cursor->page_size.physical(); + cp->delta_buf_base = static_cast<byte *>(malloc(buf_size)); memset(cp->delta_buf_base, 0, buf_size); cp->delta_buf = static_cast<byte *> (ut_align(cp->delta_buf_base, UNIV_PAGE_SIZE_MAX)); @@ -84,9 +84,7 @@ wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name, /* write delta meta info */ snprintf(meta_name, sizeof(meta_name), "%s%s", dst_name, XB_DELTA_INFO_SUFFIX); - info.page_size = cursor->page_size; - info.zip_size = cursor->zip_size; - info.space_id = cursor->space_id; + const xb_delta_info_t info(cursor->page_size, cursor->space_id); if (!xb_write_delta_metadata(meta_name, &info)) { msg("[%02u] xtrabackup: Error: " "failed to write meta info for %s\n", @@ -113,8 +111,9 @@ wf_incremental_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile) { ulint i; xb_fil_cur_t *cursor = ctxt->cursor; - ulint page_size = cursor->page_size; byte *page; + const ulint page_size + = cursor->page_size.physical(); xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt); for (i = 0, page = cursor->buf; i < cursor->buf_npages; @@ -159,7 +158,8 @@ static my_bool wf_incremental_finalize(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile) { xb_fil_cur_t *cursor = ctxt->cursor; - ulint page_size = cursor->page_size; + const ulint page_size + = cursor->page_size.physical(); xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt); if (cp->npages != page_size / 4) { @@ -184,9 +184,7 @@ wf_incremental_deinit(xb_write_filt_ctxt_t *ctxt) { xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt); - if (cp->delta_buf_base != NULL) { - ut_free(cp->delta_buf_base); - } + free(cp->delta_buf_base); } /************************************************************************ diff --git a/extra/mariabackup/xb0xb.h b/extra/mariabackup/xb0xb.h index a8b17f59579..59938a014c6 100644 --- a/extra/mariabackup/xb0xb.h +++ b/extra/mariabackup/xb0xb.h @@ -21,43 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #ifndef xb0xb_h #define xb0xb_h - -extern void os_io_init_simple(void); -extern pfs_os_file_t files[1000]; extern const char *innodb_checksum_algorithm_names[]; extern TYPELIB innodb_checksum_algorithm_typelib; -extern dberr_t open_or_create_data_files( - bool* create_new_db, -#ifdef UNIV_LOG_ARCHIVE - lsn_t* min_arch_log_no, - lsn_t* max_arch_log_no, -#endif - lsn_t* flushed_lsn, - ulint* sum_of_new_sizes) - ; -int -fil_file_readdir_next_file( -/*=======================*/ -dberr_t* err, /*!< out: this is set to DB_ERROR if an error - was encountered, otherwise not changed */ - const char* dirname,/*!< in: directory name or path */ - os_file_dir_t dir, /*!< in: directory stream */ - os_file_stat_t* info) /*!< in/out: buffer where the - info is returned */; -fil_space_t* -fil_space_get_by_name(const char *); -ibool -recv_check_cp_is_consistent(const byte* buf); -void -innodb_log_checksum_func_update( -/*============================*/ -ulint algorithm) /*!< in: algorithm */; -dberr_t -srv_undo_tablespaces_init( -/*======================*/ -ibool create_new_db, -ibool backup_mode, -const ulint n_conf_tablespaces, -ulint* n_opened); #endif diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index baad5b12118..6e9c172efc1 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -4,6 +4,8 @@ XtraBackup: hot backup tool for InnoDB Originally Created 3/3/2009 Yasufumi Kinoshita Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko, Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz. +(c) 2017, MariaDB Corporation. +Portions written by Marko Mäkelä. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -41,6 +43,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA //#define XTRABACKUP_TARGET_IS_PLUGIN +#include <my_config.h> +#include <unireg.h> #include <mysql_version.h> #include <my_base.h> #include <my_getopt.h> @@ -61,6 +65,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include <dict0priv.h> #include <lock0lock.h> #include <log0recv.h> +#include <log0crypt.h> #include <row0mysql.h> #include <row0quiesce.h> #include <srv0start.h> @@ -85,7 +90,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "xbstream.h" #include "changed_page_bitmap.h" #include "read_filt.h" -#include "wsrep.h" +#include "backup_wsrep.h" #include "innobackupex.h" #include "backup_mysql.h" #include "backup_copy.h" @@ -95,48 +100,39 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include <sql_plugin.h> #include <srv0srv.h> #include <crc_glue.h> - -/* TODO: replace with appropriate macros used in InnoDB 5.6 */ -#define PAGE_ZIP_MIN_SIZE_SHIFT 10 -#define DICT_TF_ZSSIZE_SHIFT 1 -#define DICT_TF_FORMAT_ZIP 1 -#define DICT_TF_FORMAT_SHIFT 5 +#include <log.h> int sys_var_init(); -my_bool innodb_inited= 0; - /* === xtrabackup specific options === */ char xtrabackup_real_target_dir[FN_REFLEN] = "./xtrabackup_backupfiles/"; char *xtrabackup_target_dir= xtrabackup_real_target_dir; -my_bool xtrabackup_version = FALSE; -my_bool xtrabackup_backup = FALSE; -my_bool xtrabackup_prepare = FALSE; -my_bool xtrabackup_copy_back = FALSE; -my_bool xtrabackup_move_back = FALSE; -my_bool xtrabackup_decrypt_decompress = FALSE; -my_bool xtrabackup_print_param = FALSE; - -my_bool xtrabackup_export = FALSE; -my_bool xtrabackup_apply_log_only = FALSE; - -longlong xtrabackup_use_memory = 100*1024*1024L; -my_bool xtrabackup_create_ib_logfile = FALSE; - -long xtrabackup_throttle = 0; /* 0:unlimited */ -lint io_ticket; -os_event_t wait_throttle = NULL; -os_event_t log_copying_stop = NULL; - -char *xtrabackup_incremental = NULL; +static my_bool xtrabackup_version; +my_bool xtrabackup_backup; +my_bool xtrabackup_prepare; +my_bool xtrabackup_copy_back; +my_bool xtrabackup_move_back; +my_bool xtrabackup_decrypt_decompress; +my_bool xtrabackup_print_param; + +my_bool xtrabackup_export; + +longlong xtrabackup_use_memory; + +long xtrabackup_throttle; /* 0:unlimited */ +static lint io_ticket; +static os_event_t wait_throttle; +static os_event_t log_copying_stop; + +char *xtrabackup_incremental; lsn_t incremental_lsn; lsn_t incremental_to_lsn; lsn_t incremental_last_lsn; -xb_page_bitmap *changed_page_bitmap = NULL; +xb_page_bitmap *changed_page_bitmap; -char *xtrabackup_incremental_basedir = NULL; /* for --backup */ -char *xtrabackup_extra_lsndir = NULL; /* for --backup with --extra-lsndir */ -char *xtrabackup_incremental_dir = NULL; /* for --prepare */ +char *xtrabackup_incremental_basedir; /* for --backup */ +char *xtrabackup_extra_lsndir; /* for --backup with --extra-lsndir */ +char *xtrabackup_incremental_dir; /* for --prepare */ char xtrabackup_real_incremental_basedir[FN_REFLEN]; char xtrabackup_real_extra_lsndir[FN_REFLEN]; @@ -144,9 +140,9 @@ char xtrabackup_real_incremental_dir[FN_REFLEN]; char *xtrabackup_tmpdir; -char *xtrabackup_tables = NULL; -char *xtrabackup_tables_file = NULL; -char *xtrabackup_tables_exclude = NULL; +char *xtrabackup_tables; +char *xtrabackup_tables_file; +char *xtrabackup_tables_exclude; typedef std::list<regex_t> regex_list_t; static regex_list_t regex_include_list; @@ -170,17 +166,12 @@ struct xb_filter_entry_struct{ }; typedef struct xb_filter_entry_struct xb_filter_entry_t; -static ulint thread_nr[SRV_MAX_N_IO_THREADS + 6]; -static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6]; - lsn_t checkpoint_lsn_start; lsn_t checkpoint_no_start; -lsn_t log_copy_scanned_lsn; -ibool log_copying = TRUE; -ibool log_copying_running = FALSE; -ibool io_watching_thread_running = FALSE; - -ibool xtrabackup_logfile_is_renamed = FALSE; +static lsn_t log_copy_scanned_lsn; +static bool log_copying; +static bool log_copying_running; +static bool io_watching_thread_running; int xtrabackup_parallel; @@ -199,19 +190,16 @@ ulint xtrabackup_log_copy_interval = 1000; static ulong max_buf_pool_modified_pct; /* Ignored option (--log) for MySQL option compatibility */ -char* log_ignored_opt = NULL; +static char* log_ignored_opt; /* === metadata of backup === */ #define XTRABACKUP_METADATA_FILENAME "xtrabackup_checkpoints" -char metadata_type[30] = ""; /*[full-backuped|log-applied| - full-prepared|incremental]*/ -lsn_t metadata_from_lsn = 0; -lsn_t metadata_to_lsn = 0; -lsn_t metadata_last_lsn = 0; - -#define XB_LOG_FILENAME "xtrabackup_logfile" +char metadata_type[30] = ""; /*[full-backuped|log-applied|incremental]*/ +lsn_t metadata_from_lsn; +lsn_t metadata_to_lsn; +lsn_t metadata_last_lsn; -ds_file_t *dst_log_file = NULL; +static ds_file_t* dst_log_file; static char mysql_data_home_buff[2]; @@ -227,24 +215,17 @@ ulong innobase_large_page_size = 0; /* The default values for the following, type long or longlong, start-up parameters are declared in mysqld.cc: */ -long innobase_additional_mem_pool_size = 1*1024*1024L; long innobase_buffer_pool_awe_mem_mb = 0; long innobase_file_io_threads = 4; long innobase_read_io_threads = 4; long innobase_write_io_threads = 4; -long innobase_force_recovery = 0; long innobase_log_buffer_size = 1024*1024L; -long innobase_log_files_in_group = 2; long innobase_open_files = 300L; longlong innobase_page_size = (1LL << 14); /* 16KB */ -static ulong innobase_log_block_size = 512; -my_bool innobase_fast_checksum = FALSE; -char* innobase_doublewrite_file = NULL; char* innobase_buffer_pool_filename = NULL; longlong innobase_buffer_pool_size = 8*1024*1024L; -longlong innobase_log_file_size = 48*1024*1024L; /* The default values for the following char* start-up parameters are determined in innobase_init below: */ @@ -256,20 +237,12 @@ char* innobase_data_file_path = NULL; affects Windows: */ char* innobase_unix_file_flush_method = NULL; -/* Below we have boolean-valued start-up parameters, and their default -values */ - -ulong innobase_fast_shutdown = 1; -my_bool innobase_use_doublewrite = TRUE; -my_bool innobase_use_checksums = TRUE; -my_bool innobase_use_large_pages = FALSE; -my_bool innobase_file_per_table = FALSE; -my_bool innobase_locks_unsafe_for_binlog = FALSE; -my_bool innobase_rollback_on_timeout = FALSE; -my_bool innobase_create_status_file = FALSE; -my_bool innobase_adaptive_hash_index = TRUE; - -static char *internal_innobase_data_file_path = NULL; +my_bool innobase_use_doublewrite; +my_bool innobase_use_large_pages; +my_bool innobase_file_per_table; +my_bool innobase_locks_unsafe_for_binlog; +my_bool innobase_rollback_on_timeout; +my_bool innobase_create_status_file; /* The following counter is used to convey information to InnoDB about server activity: in selects it is not sensible to call @@ -290,7 +263,7 @@ lsn_t flushed_lsn= 0; ulong xb_open_files_limit= 0; char *xb_plugin_dir; char *xb_plugin_load; -my_bool xb_close_files= FALSE; +my_bool xb_close_files; /* Datasinks */ ds_ctxt_t *ds_data = NULL; @@ -299,10 +272,6 @@ ds_ctxt_t *ds_redo = NULL; static bool innobackupex_mode = false; -static long innobase_log_files_in_group_save; -static char *srv_log_group_home_dir_save; -static longlong innobase_log_file_size_save; - /* String buffer used by --print-param to accumulate server options as they are parsed from the defaults file */ static std::ostringstream print_param_str; @@ -313,6 +282,7 @@ std::set<std::string> param_set; static ulonglong global_max_value; extern "C" sig_handler handle_fatal_signal(int sig); +extern LOGGER logger; my_bool opt_galera_info = FALSE; my_bool opt_slave_info = FALSE; @@ -361,9 +331,6 @@ const char *opt_history = NULL; #if defined(HAVE_OPENSSL) my_bool opt_ssl_verify_server_cert = FALSE; -#if !defined(HAVE_YASSL) -char *opt_server_public_key = NULL; -#endif #endif /* Whether xtrabackup_binlog_info should be created on recovery */ @@ -383,14 +350,23 @@ xtrabackup_add_datasink(ds_ctxt_t *ds) } /* ======== Datafiles iterator ======== */ +struct datafiles_iter_t { + fil_system_t *system; + fil_space_t *space; + fil_node_t *node; + ibool started; + pthread_mutex_t mutex; +}; + +/* ======== Datafiles iterator ======== */ +static datafiles_iter_t * datafiles_iter_new(fil_system_t *f_system) { datafiles_iter_t *it; - it = static_cast<datafiles_iter_t *> - (ut_malloc(sizeof(datafiles_iter_t))); - it->mutex = os_mutex_create(); + it = static_cast<datafiles_iter_t *>(malloc(sizeof(datafiles_iter_t))); + pthread_mutex_init(&it->mutex, NULL); it->system = f_system; it->space = NULL; @@ -400,12 +376,13 @@ datafiles_iter_new(fil_system_t *f_system) return it; } +static fil_node_t * datafiles_iter_next(datafiles_iter_t *it) { fil_node_t *new_node; - os_mutex_enter(it->mutex); + pthread_mutex_lock(&it->mutex); if (it->node == NULL) { if (it->started) @@ -422,7 +399,7 @@ datafiles_iter_next(datafiles_iter_t *it) UT_LIST_GET_NEXT(space_list, it->space); while (it->space != NULL && - (it->space->purpose != FIL_TABLESPACE || + (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) @@ -432,16 +409,17 @@ datafiles_iter_next(datafiles_iter_t *it) end: new_node = it->node; - os_mutex_exit(it->mutex); + pthread_mutex_unlock(&it->mutex); return new_node; } +static void datafiles_iter_free(datafiles_iter_t *it) { - os_mutex_free(it->mutex); - ut_free(it); + pthread_mutex_destroy(&it->mutex); + free(it); } /* ======== Date copying thread context ======== */ @@ -450,7 +428,7 @@ typedef struct { datafiles_iter_t *it; uint num; uint *count; - os_ib_mutex_t count_mutex; + pthread_mutex_t count_mutex; os_thread_id_t id; } data_thread_ctxt_t; @@ -463,7 +441,6 @@ enum options_xtrabackup OPT_XTRA_BACKUP, OPT_XTRA_PREPARE, OPT_XTRA_EXPORT, - OPT_XTRA_APPLY_LOG_ONLY, OPT_XTRA_PRINT_PARAM, OPT_XTRA_USE_MEMORY, OPT_XTRA_THROTTLE, @@ -476,7 +453,6 @@ enum options_xtrabackup OPT_XTRA_TABLES_FILE, OPT_XTRA_DATABASES, OPT_XTRA_DATABASES_FILE, - OPT_XTRA_CREATE_IB_LOGFILE, OPT_XTRA_PARALLEL, OPT_XTRA_STREAM, OPT_XTRA_COMPRESS, @@ -484,12 +460,10 @@ enum options_xtrabackup OPT_XTRA_COMPRESS_CHUNK_SIZE, OPT_LOG, OPT_INNODB, - OPT_INNODB_CHECKSUMS, OPT_INNODB_DATA_FILE_PATH, OPT_INNODB_DATA_HOME_DIR, OPT_INNODB_ADAPTIVE_HASH_INDEX, OPT_INNODB_DOUBLEWRITE, - OPT_INNODB_FAST_SHUTDOWN, OPT_INNODB_FILE_PER_TABLE, OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT, OPT_INNODB_FLUSH_METHOD, @@ -499,7 +473,6 @@ enum options_xtrabackup OPT_INNODB_MAX_PURGE_LAG, OPT_INNODB_ROLLBACK_ON_TIMEOUT, OPT_INNODB_STATUS_FILE, - OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE, OPT_INNODB_AUTOEXTEND_INCREMENT, OPT_INNODB_BUFFER_POOL_SIZE, OPT_INNODB_COMMIT_CONCURRENCY, @@ -510,25 +483,17 @@ enum options_xtrabackup OPT_INNODB_WRITE_IO_THREADS, OPT_INNODB_USE_NATIVE_AIO, OPT_INNODB_PAGE_SIZE, - OPT_INNODB_LOG_BLOCK_SIZE, - OPT_INNODB_FAST_CHECKSUM, - OPT_INNODB_EXTRA_UNDOSLOTS, - OPT_INNODB_DOUBLEWRITE_FILE, OPT_INNODB_BUFFER_POOL_FILENAME, - OPT_INNODB_FORCE_RECOVERY, OPT_INNODB_LOCK_WAIT_TIMEOUT, OPT_INNODB_LOG_BUFFER_SIZE, OPT_INNODB_LOG_FILE_SIZE, OPT_INNODB_LOG_FILES_IN_GROUP, OPT_INNODB_OPEN_FILES, - OPT_INNODB_SYNC_SPIN_LOOPS, - OPT_INNODB_THREAD_CONCURRENCY, - OPT_INNODB_THREAD_SLEEP_DELAY, OPT_XTRA_DEBUG_SYNC, OPT_INNODB_CHECKSUM_ALGORITHM, OPT_INNODB_UNDO_DIRECTORY, OPT_INNODB_UNDO_TABLESPACES, - OPT_INNODB_LOG_CHECKSUM_ALGORITHM, + OPT_INNODB_LOG_CHECKSUMS, OPT_XTRA_INCREMENTAL_FORCE_SCAN, OPT_DEFAULTS_GROUP, OPT_OPEN_FILES_LIMIT, @@ -563,10 +528,6 @@ enum options_xtrabackup OPT_BINLOG_INFO, OPT_XB_SECURE_AUTH, - OPT_SSL_SSL, - OPT_SSL_VERIFY_SERVER_CERT, - OPT_SERVER_PUBLIC_KEY, - OPT_XTRA_TABLES_EXCLUDE, OPT_XTRA_DATABASES_EXCLUDE, }; @@ -587,10 +548,6 @@ struct my_option xb_client_options[] = {"export", OPT_XTRA_EXPORT, "create files to import to another database when prepare.", (G_PTR*) &xtrabackup_export, (G_PTR*) &xtrabackup_export, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"apply-log-only", OPT_XTRA_APPLY_LOG_ONLY, - "stop recovery process not to progress LSN after applying log when prepare.", - (G_PTR*) &xtrabackup_apply_log_only, (G_PTR*) &xtrabackup_apply_log_only, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"print-param", OPT_XTRA_PRINT_PARAM, "print parameter of mysqld needed for copyback.", (G_PTR*) &xtrabackup_print_param, (G_PTR*) &xtrabackup_print_param, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -628,7 +585,7 @@ struct my_option xb_client_options[] = {"databases", OPT_XTRA_DATABASES, "filtering by list of databases.", (G_PTR*) &xtrabackup_databases, (G_PTR*) &xtrabackup_databases, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"databases_file", OPT_XTRA_TABLES_FILE, + {"databases_file", OPT_XTRA_DATABASES_FILE, "filtering by list of databases in the file.", (G_PTR*) &xtrabackup_databases_file, (G_PTR*) &xtrabackup_databases_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -642,9 +599,6 @@ struct my_option xb_client_options[] = "Note that this option has a higher priority than --databases.", (G_PTR*) &xtrabackup_databases_exclude, (G_PTR*) &xtrabackup_databases_exclude, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"create-ib-logfile", OPT_XTRA_CREATE_IB_LOGFILE, "** not work for now** creates ib_logfile* also after '--prepare'. ### If you want create ib_logfile*, only re-execute this command in same options. ###", - (G_PTR*) &xtrabackup_create_ib_logfile, (G_PTR*) &xtrabackup_create_ib_logfile, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"stream", OPT_XTRA_STREAM, "Stream all backup files to the standard output " "in the specified format." @@ -922,6 +876,11 @@ struct my_option xb_client_options[] = uint xb_client_options_count = array_elements(xb_client_options); +#ifndef DBUG_OFF +/** Parameters to DBUG */ +static const char *dbug_option; +#endif + struct my_option xb_server_options[] = { {"datadir", 'h', "Path to the database root.", (G_PTR*) &mysql_data_home, @@ -952,40 +911,34 @@ struct my_option xb_server_options[] = {"innodb", OPT_INNODB, "Ignored option for MySQL option compatibility", (G_PTR*) &innobase_ignored_opt, (G_PTR*) &innobase_ignored_opt, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - +#ifdef BTR_CUR_HASH_ADAPT {"innodb_adaptive_hash_index", OPT_INNODB_ADAPTIVE_HASH_INDEX, "Enable InnoDB adaptive hash index (enabled by default). " "Disable with --skip-innodb-adaptive-hash-index.", - (G_PTR*) &innobase_adaptive_hash_index, - (G_PTR*) &innobase_adaptive_hash_index, + &btr_search_enabled, + &btr_search_enabled, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"innodb_additional_mem_pool_size", OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE, - "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.", - (G_PTR*) &innobase_additional_mem_pool_size, - (G_PTR*) &innobase_additional_mem_pool_size, 0, GET_LONG, REQUIRED_ARG, - 1*1024*1024L, 512*1024L, LONG_MAX, 0, 1024, 0}, +#endif /* BTR_CUR_HASH_ADAPT */ {"innodb_autoextend_increment", OPT_INNODB_AUTOEXTEND_INCREMENT, "Data file autoextend increment in megabytes", - (G_PTR*) &srv_auto_extend_increment, - (G_PTR*) &srv_auto_extend_increment, + (G_PTR*) &sys_tablespace_auto_extend_increment, + (G_PTR*) &sys_tablespace_auto_extend_increment, 0, GET_ULONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0}, {"innodb_buffer_pool_size", OPT_INNODB_BUFFER_POOL_SIZE, "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", (G_PTR*) &innobase_buffer_pool_size, (G_PTR*) &innobase_buffer_pool_size, 0, GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 0, 1024*1024L, 0}, - {"innodb_checksums", OPT_INNODB_CHECKSUMS, "Enable InnoDB checksums validation (enabled by default). \ -Disable with --skip-innodb-checksums.", (G_PTR*) &innobase_use_checksums, - (G_PTR*) &innobase_use_checksums, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"innodb_data_file_path", OPT_INNODB_DATA_FILE_PATH, "Path to individual files and their sizes.", &innobase_data_file_path, &innobase_data_file_path, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_data_home_dir", OPT_INNODB_DATA_HOME_DIR, "The common part for InnoDB table spaces.", &innobase_data_home_dir, &innobase_data_home_dir, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"innodb_doublewrite", OPT_INNODB_DOUBLEWRITE, "Enable InnoDB doublewrite buffer (enabled by default). \ -Disable with --skip-innodb-doublewrite.", (G_PTR*) &innobase_use_doublewrite, - (G_PTR*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"innodb_doublewrite", OPT_INNODB_DOUBLEWRITE, + "Enable InnoDB doublewrite buffer during --prepare.", + (G_PTR*) &innobase_use_doublewrite, + (G_PTR*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_io_capacity", OPT_INNODB_IO_CAPACITY, "Number of IOPs the server can do. Tunes the background IO rate", (G_PTR*) &srv_io_capacity, (G_PTR*) &srv_io_capacity, @@ -1013,26 +966,19 @@ Disable with --skip-innodb-doublewrite.", (G_PTR*) &innobase_use_doublewrite, (G_PTR*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -/* ####### Should we use this option? ####### */ - {"innodb_force_recovery", OPT_INNODB_FORCE_RECOVERY, - "Helps to save your data in case the disk image of the database becomes corrupt.", - (G_PTR*) &innobase_force_recovery, (G_PTR*) &innobase_force_recovery, 0, - GET_LONG, REQUIRED_ARG, 0, 0, 6, 0, 1, 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.", (G_PTR*) &innobase_log_buffer_size, (G_PTR*) &innobase_log_buffer_size, 0, GET_LONG, REQUIRED_ARG, 1024*1024L, 256*1024L, LONG_MAX, 0, 1024, 0}, {"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE, - "Size of each log file in a log group.", - (G_PTR*) &innobase_log_file_size, (G_PTR*) &innobase_log_file_size, 0, - GET_LL, REQUIRED_ARG, 48*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 0, - 1024*1024L, 0}, + "Ignored for mysqld option compatibility", + (G_PTR*) &srv_log_file_size, (G_PTR*) &srv_log_file_size, 0, + GET_ULL, REQUIRED_ARG, 48 << 20, 1 << 20, 512ULL << 30, 0, + UNIV_PAGE_SIZE_MAX, 0}, {"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP, - "Number of log files in the log group. InnoDB writes to the files in a " - "circular fashion. Value 3 is recommended here.", - &innobase_log_files_in_group, &innobase_log_files_in_group, - 0, GET_LONG, REQUIRED_ARG, 2, 2, 100, 0, 1, 0}, + "Ignored for mysqld option compatibility", + &srv_n_log_files, &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_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -1054,25 +1000,17 @@ Disable with --skip-innodb-doublewrite.", (G_PTR*) &innobase_use_doublewrite, /* Use GET_LL to support numeric suffixes in 5.6 */ GET_LL, REQUIRED_ARG, (1LL << 14), (1LL << 12), (1LL << UNIV_PAGE_SIZE_SHIFT_MAX), 0, 1L, 0}, - {"innodb_log_block_size", OPT_INNODB_LOG_BLOCK_SIZE, - "The log block size of the transaction log file. " - "Changing for created log file is not supported. Use on your own risk!", - (G_PTR*) &innobase_log_block_size, (G_PTR*) &innobase_log_block_size, 0, - GET_ULONG, REQUIRED_ARG, 512, 512, 1 << UNIV_PAGE_SIZE_SHIFT_MAX, 0, 1L, 0}, - {"innodb_fast_checksum", OPT_INNODB_FAST_CHECKSUM, - "Change the algorithm of checksum for the whole of datapage to 4-bytes word based.", - (G_PTR*) &innobase_fast_checksum, - (G_PTR*) &innobase_fast_checksum, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"innodb_doublewrite_file", OPT_INNODB_DOUBLEWRITE_FILE, - "Path to special datafile for doublewrite buffer. (default is "": not used)", - (G_PTR*) &innobase_doublewrite_file, (G_PTR*) &innobase_doublewrite_file, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_buffer_pool_filename", OPT_INNODB_BUFFER_POOL_FILENAME, - "Filename to/from which to dump/load the InnoDB buffer pool", + "Ignored for mysqld option compatibility", (G_PTR*) &innobase_buffer_pool_filename, (G_PTR*) &innobase_buffer_pool_filename, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#ifndef DBUG_OFF /* unfortunately "debug" collides with existing options */ + {"dbug", '#', "Built in DBUG debugger.", + &dbug_option, &dbug_option, 0, GET_STR, OPT_ARG, + 0, 0, 0, 0, 0, 0}, +#endif #ifndef __WIN__ {"debug-sync", OPT_XTRA_DEBUG_SYNC, "Debug sync point. This is only used by the xtrabackup test suite", @@ -1086,11 +1024,7 @@ Disable with --skip-innodb-doublewrite.", (G_PTR*) &innobase_use_doublewrite, "INNODB, STRICT_INNODB, NONE, STRICT_NONE]", &srv_checksum_algorithm, &srv_checksum_algorithm, &innodb_checksum_algorithm_typelib, GET_ENUM, REQUIRED_ARG, SRV_CHECKSUM_ALGORITHM_INNODB, 0, 0, 0, 0, 0}, - {"innodb_log_checksum_algorithm", OPT_INNODB_LOG_CHECKSUM_ALGORITHM, - "The algorithm InnoDB uses for log checksumming. [CRC32, STRICT_CRC32, " - "INNODB, STRICT_INNODB, NONE, STRICT_NONE]", &srv_log_checksum_algorithm, - &srv_log_checksum_algorithm, &innodb_checksum_algorithm_typelib, GET_ENUM, - REQUIRED_ARG, SRV_CHECKSUM_ALGORITHM_INNODB, 0, 0, 0, 0, 0}, + {"innodb_undo_directory", OPT_INNODB_UNDO_DIRECTORY, "Directory where undo tablespace files live, this path can be absolute.", &srv_undo_dir, &srv_undo_dir, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, @@ -1116,7 +1050,12 @@ Disable with --skip-innodb-doublewrite.", (G_PTR*) &innobase_use_doublewrite, { "innodb-encrypt-log", OPT_INNODB_ENCRYPT_LOG, "encrypton plugin to load", &srv_encrypt_log, &srv_encrypt_log, 0, GET_BOOL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - + + {"innodb-log-checksums", OPT_INNODB_LOG_CHECKSUMS, + "Whether to require checksums for InnoDB redo log blocks", + &innodb_log_checksums, &innodb_log_checksums, + 0, GET_BOOL, REQUIRED_ARG, 1, 0, 0, 0, 0, 0 }, + {"open_files_limit", OPT_OPEN_FILES_LIMIT, "the maximum number of file " "descriptors to reserve with setrlimit().", (G_PTR*) &xb_open_files_limit, (G_PTR*) &xb_open_files_limit, 0, GET_ULONG, @@ -1270,13 +1209,7 @@ xb_get_one_option(int optid, break; case OPT_INNODB_LOG_FILES_IN_GROUP: - - ADD_PRINT_PARAM_OPT(innobase_log_files_in_group); - break; - case OPT_INNODB_LOG_FILE_SIZE: - - ADD_PRINT_PARAM_OPT(innobase_log_file_size); break; case OPT_INNODB_FLUSH_METHOD: @@ -1289,21 +1222,6 @@ xb_get_one_option(int optid, ADD_PRINT_PARAM_OPT(innobase_page_size); break; - case OPT_INNODB_FAST_CHECKSUM: - - ADD_PRINT_PARAM_OPT(!!innobase_fast_checksum); - break; - - case OPT_INNODB_LOG_BLOCK_SIZE: - - ADD_PRINT_PARAM_OPT(innobase_log_block_size); - break; - - case OPT_INNODB_DOUBLEWRITE_FILE: - - ADD_PRINT_PARAM_OPT(innobase_doublewrite_file); - break; - case OPT_INNODB_UNDO_DIRECTORY: ADD_PRINT_PARAM_OPT(srv_undo_dir); @@ -1321,13 +1239,6 @@ xb_get_one_option(int optid, ADD_PRINT_PARAM_OPT(innodb_checksum_algorithm_names[srv_checksum_algorithm]); break; - case OPT_INNODB_LOG_CHECKSUM_ALGORITHM: - - ut_a(srv_log_checksum_algorithm <= SRV_CHECKSUM_ALGORITHM_STRICT_NONE); - - ADD_PRINT_PARAM_OPT(innodb_checksum_algorithm_names[srv_log_checksum_algorithm]); - break; - case OPT_INNODB_BUFFER_POOL_FILENAME: ADD_PRINT_PARAM_OPT(innobase_buffer_pool_filename); @@ -1400,40 +1311,9 @@ xb_get_one_option(int optid, return 0; } -/*********************************************************************** -Initializes log_block_size */ -static -ibool -xb_init_log_block_size(void) -{ - srv_log_block_size = 0; - if (innobase_log_block_size != 512) { - uint n_shift = (uint)get_bit_shift(innobase_log_block_size);; - - if (n_shift > 0) { - srv_log_block_size = (ulint)(1LL << n_shift); - msg("InnoDB: The log block size is set to %lu.\n", - srv_log_block_size); - } - } else { - srv_log_block_size = 512; - } - if (!srv_log_block_size) { - msg("InnoDB: Error: %lu is not valid value for " - "innodb_log_block_size.\n", innobase_log_block_size); - return FALSE; - } - - return TRUE; -} - static my_bool innodb_init_param(void) { - /* innobase_init */ - static char current_dir[3]; /* Set if using current lib */ - my_bool ret; - char *default_path; srv_is_being_started = TRUE; /* === some variables from mysqld === */ memset((G_PTR) &mysql_tmpdir_list, 0, sizeof(mysql_tmpdir_list)); @@ -1465,10 +1345,6 @@ innodb_init_param(void) srv_page_size = (1 << srv_page_size_shift); } - if (!xb_init_log_block_size()) { - goto error; - } - /* Check that values don't overflow on 32-bit systems. */ if (sizeof(ulint) == 4) { if (xtrabackup_use_memory > UINT_MAX32) { @@ -1482,30 +1358,10 @@ innodb_init_param(void) goto error; } - - if (innobase_log_file_size > UINT_MAX32) { - msg("xtrabackup: innobase_log_file_size can't be " - "over 4GB on 32-bit systemsi\n"); - - goto error; - } } - os_innodb_umask = (ulint)0664; - - /* First calculate the default path for innodb_data_home_dir etc., - in case the user has not given any value. - - Note that when using the embedded server, the datadirectory is not - necessarily the current directory of this program. */ - - /* It's better to use current lib, to keep paths short */ - current_dir[0] = FN_CURLIB; - current_dir[1] = FN_LIBCHAR; - current_dir[2] = 0; - default_path = current_dir; - - ut_a(default_path); + static char default_path[2] = { FN_CURLIB, 0 }; + fil_path_to_mysql_datadir = default_path; /* Set InnoDB initialization parameters according to the values read from MySQL .cnf file */ @@ -1535,37 +1391,20 @@ innodb_init_param(void) msg("xtrabackup: innodb_data_file_path = %s\n", innobase_data_file_path); - /* Since InnoDB edits the argument in the next call, we make another - copy of it: */ + /* This is the first time univ_page_size is used. + It was initialized to 16k pages before srv_page_size was set */ + univ_page_size.copy_from( + page_size_t(srv_page_size, srv_page_size, false)); - internal_innobase_data_file_path = strdup(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); + srv_sys_space.set_flags(FSP_FLAGS_PAGE_SSIZE()); - ret = (my_bool) srv_parse_data_file_paths_and_sizes( - internal_innobase_data_file_path); - if (ret == FALSE) { - msg("xtrabackup: syntax error in innodb_data_file_path\n"); -mem_free_and_error: - free(internal_innobase_data_file_path); - internal_innobase_data_file_path = NULL; + if (!srv_sys_space.parse_params(innobase_data_file_path, true)) { goto error; } - if (xtrabackup_prepare) { - /* "--prepare" needs filenames only */ - ulint i; - - for (i=0; i < srv_n_data_files; i++) { - char *p; - - p = srv_data_file_names[i]; - while ((p = strchr(p, SRV_PATH_SEPARATOR)) != NULL) - { - p++; - srv_data_file_names[i] = p; - } - } - } - /* -------------- Log files ---------------------------*/ /* The default dir for log files is the datadir of MySQL */ @@ -1579,60 +1418,38 @@ mem_free_and_error: msg("xtrabackup: innodb_log_group_home_dir = %s\n", srv_log_group_home_dir); - srv_normalize_path_for_win(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 mem_free_and_error; + goto error; } srv_adaptive_flushing = FALSE; - srv_use_sys_malloc = TRUE; srv_file_format = 1; /* Barracuda */ srv_max_file_format_at_startup = UNIV_FORMAT_MIN; /* on */ /* --------------------------------------------------*/ srv_file_flush_method_str = innobase_unix_file_flush_method; - srv_n_log_files = (ulint) innobase_log_files_in_group; - srv_log_file_size = (ulint) innobase_log_file_size; - msg("xtrabackup: innodb_log_files_in_group = %ld\n", - srv_n_log_files); - msg("xtrabackup: innodb_log_file_size = %lld\n", - (long long int) srv_log_file_size); - srv_log_buffer_size = (ulint) innobase_log_buffer_size; /* We set srv_pool_size here in units of 1 kB. InnoDB internally changes the value so that it becomes the number of database pages. */ - //srv_buf_pool_size = (ulint) innobase_buffer_pool_size; srv_buf_pool_size = (ulint) xtrabackup_use_memory; - - srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size; + srv_buf_pool_chunk_unit = srv_buf_pool_size; + srv_buf_pool_instances = 1; srv_n_file_io_threads = (ulint) innobase_file_io_threads; srv_n_read_io_threads = (ulint) innobase_read_io_threads; srv_n_write_io_threads = (ulint) innobase_write_io_threads; - srv_force_recovery = (ulint) innobase_force_recovery; - srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite; - if (!innobase_use_checksums) { - - srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_NONE; - } - - btr_search_enabled = (char) innobase_adaptive_hash_index; - btr_search_index_num = 1; - os_use_large_pages = (ibool) innobase_use_large_pages; os_large_page_size = (ulint) innobase_large_page_size; - static char default_dir[3] = "./"; - srv_arch_dir = default_dir; row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout; srv_file_per_table = (my_bool) innobase_file_per_table; @@ -1650,18 +1467,8 @@ mem_free_and_error: /* We cannot treat characterset here for now!! */ data_mysql_default_charset_coll = (ulint)default_charset_info->number; - ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL == - my_charset_latin1.number); ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number); - /* Store the latin1_swedish_ci character ordering table to InnoDB. For - non-latin1_swedish_ci charsets we use the MySQL comparison functions, - and consequently we do not need to know the ordering internally in - InnoDB. */ - - ut_a(0 == strcmp(my_charset_latin1.name, "latin1_swedish_ci")); - srv_latin1_ordering = my_charset_latin1.sort_order; - //innobase_commit_concurrency_init_default(); /* Since we in this module access directly the fields of a trx @@ -1675,31 +1482,8 @@ mem_free_and_error: innobase_start_or_create_for_mysql(). As we don't call it in xtrabackup, we have to duplicate checks from that function here. */ -#ifdef __WIN__ - switch (os_get_os_version()) { - case OS_WIN95: - case OS_WIN31: - case OS_WINNT: - /* On Win 95, 98, ME, Win32 subsystem for Windows 3.1, - and NT use simulated aio. In NT Windows provides async i/o, - but when run in conjunction with InnoDB Hot Backup, it seemed - to corrupt the data files. */ - - srv_use_native_aio = FALSE; - break; - - case OS_WIN2000: - case OS_WINXP: - /* On 2000 and XP, async IO is available. */ - srv_use_native_aio = TRUE; - break; - - default: - /* Vista and later have both async IO and condition variables */ - srv_use_native_aio = TRUE; - srv_use_native_conditions = TRUE; - break; - } +#ifdef _WIN32 + srv_use_native_aio = TRUE; #elif defined(LINUX_NATIVE_AIO) @@ -1726,7 +1510,9 @@ mem_free_and_error: srv_undo_dir = my_strdup(".", MYF(MY_FAE)); } - innodb_log_checksum_func_update(srv_log_checksum_algorithm); + log_checksum_algorithm_ptr = innodb_log_checksums || srv_encrypt_log + ? log_block_calc_checksum_crc32 + : log_block_calc_checksum_none; return(FALSE); @@ -1735,57 +1521,17 @@ error: return(TRUE); } -static my_bool -innodb_init(void) +static bool innodb_init() { - int err; - srv_is_being_started = TRUE; - err = innobase_start_or_create_for_mysql(); - + dberr_t err = innobase_start_or_create_for_mysql(); if (err != DB_SUCCESS) { - free(internal_innobase_data_file_path); - internal_innobase_data_file_path = NULL; - goto error; + msg("xtrabackup: innodb_init() returned %d (%s).\n", + err, ut_strerr(err)); + innodb_shutdown(); + return(TRUE); } - /* They may not be needed for now */ -// (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0, -// (hash_get_key) innobase_get_key, 0, 0); -// pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST); -// pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST); -// pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST); -// pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST); -// pthread_cond_init(&commit_cond, NULL); - - innodb_inited= 1; - return(FALSE); - -error: - msg("xtrabackup: innodb_init(): Error occured.\n"); - return(TRUE); -} - -static void -innodb_end() -{ - srv_fast_shutdown = (ulint) innobase_fast_shutdown; - innodb_inited = 0; - - msg("xtrabackup: starting shutdown with innodb_fast_shutdown = %lu\n", - srv_fast_shutdown); - - innodb_shutdown(); - free(internal_innobase_data_file_path); - internal_innobase_data_file_path = NULL; - - /* They may not be needed for now */ -// hash_free(&innobase_open_tables); -// pthread_mutex_destroy(&innobase_share_mutex); -// pthread_mutex_destroy(&prepare_commit_mutex); -// pthread_mutex_destroy(&commit_threads_m); -// pthread_mutex_destroy(&commit_cond_m); -// pthread_cond_destroy(&commit_cond); } /* ================= common ================= */ @@ -1940,8 +1686,7 @@ xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info) my_bool r = TRUE; /* set defaults */ - info->page_size = ULINT_UNDEFINED; - info->zip_size = ULINT_UNDEFINED; + ulint page_size = ULINT_UNDEFINED, zip_size = 0; info->space_id = ULINT_UNDEFINED; fp = fopen(filepath, "r"); @@ -1953,9 +1698,9 @@ xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info) while (!feof(fp)) { if (fscanf(fp, "%50s = %50s\n", key, value) == 2) { if (strcmp(key, "page_size") == 0) { - info->page_size = strtoul(value, NULL, 10); + page_size = strtoul(value, NULL, 10); } else if (strcmp(key, "zip_size") == 0) { - info->zip_size = strtoul(value, NULL, 10); + zip_size = strtoul(value, NULL, 10); } else if (strcmp(key, "space_id") == 0) { info->space_id = strtoul(value, NULL, 10); } @@ -1964,10 +1709,14 @@ xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info) fclose(fp); - if (info->page_size == ULINT_UNDEFINED) { + if (page_size == ULINT_UNDEFINED) { msg("xtrabackup: page_size is required in %s\n", filepath); r = FALSE; + } else { + info->page_size = page_size_t(zip_size ? zip_size : page_size, + page_size, zip_size != 0); } + if (info->space_id == ULINT_UNDEFINED) { msg("xtrabackup: Warning: This backup was taken with XtraBackup 2.0.1 " "or earlier, some DDL operations between full and incremental " @@ -1993,7 +1742,10 @@ xb_write_delta_metadata(const char *filename, const xb_delta_info_t *info) "page_size = %lu\n" "zip_size = %lu\n" "space_id = %lu\n", - info->page_size, info->zip_size, info->space_id); + info->page_size.logical(), + info->page_size.is_compressed() + ? info->page_size.physical() : 0, + info->space_id); len = strlen(buf); mystat.st_size = len; @@ -2150,7 +1902,7 @@ check_if_skip_database_by_path( return(FALSE); } - const char* db_name = strrchr(path, SRV_PATH_SEPARATOR); + const char* db_name = strrchr(path, OS_PATH_SEPARATOR); if (db_name == NULL) { db_name = path; } else { @@ -2258,33 +2010,26 @@ check_if_skip_table( return(FALSE); } -/*********************************************************************** -Reads the space flags from a given data file and returns the compressed -page size, or 0 if the space is not compressed. */ -ulint -xb_get_zip_size(pfs_os_file_t file) +/** @return the tablespace flags from a given data file +@retval ULINT_UNDEFINED if the file is not readable */ +ulint xb_get_space_flags(pfs_os_file_t file) { byte *buf; byte *page; - ulint zip_size = ULINT_UNDEFINED; - ibool success; - ulint space; + ulint flags; - buf = static_cast<byte *>(ut_malloc(2 * UNIV_PAGE_SIZE)); + buf = static_cast<byte *>(malloc(2 * UNIV_PAGE_SIZE)); page = static_cast<byte *>(ut_align(buf, UNIV_PAGE_SIZE)); - success = os_file_read(file, page, 0, UNIV_PAGE_SIZE); - if (!success) { - goto end; + if (os_file_read(IORequestRead, file, page, 0, UNIV_PAGE_SIZE)) { + flags = fsp_header_get_flags(page); + } else { + flags = ULINT_UNDEFINED; } - space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - zip_size = (space == 0 ) ? 0 : - dict_tf_get_zip_size(fsp_header_get_flags(page)); -end: - ut_free(buf); + free(buf); - return(zip_size); + return(flags); } const char* @@ -2323,7 +2068,6 @@ xtrabackup_copy_datafile(fil_node_t* node, uint thread_n) xb_write_filt_ctxt_t write_filt_ctxt; const char *action; xb_read_filt_t *read_filter; - ibool is_system; my_bool rc = FALSE; /* Get the name and the path for the tablespace. node->name always @@ -2338,9 +2082,8 @@ xtrabackup_copy_datafile(fil_node_t* node, uint thread_n) const char* const node_name = node->space->name; const char* const node_path = node->name; - is_system = !fil_is_user_tablespace_id(node->space->id); - - if (!is_system && check_if_skip_table(node_name)) { + if (fil_is_user_tablespace_id(node->space->id) + && check_if_skip_table(node_name)) { msg("[%02u] Skipping %s.\n", thread_n, node_name); return(FALSE); } @@ -2449,50 +2192,29 @@ skip: return(FALSE); } -extern ibool log_block_checksum_is_ok_or_old_format(const byte* block); - -/*******************************************************//** -Scans log from a buffer and writes new log data to the outpud datasinc. -@return true if success */ +/** Copy redo log blocks to the data sink. +@param[in] is_last whether this is the last log segment to copy +@param[in] start_lsn buffer start LSN +@param[in] end_lsn buffer end LSN +@return last copied LSN +@retval 0 on failure */ static -bool -xtrabackup_scan_log_recs( -/*===============*/ - log_group_t* group, /*!< in: log group */ - bool is_last, /*!< in: whether it is last segment - to copy */ - lsn_t start_lsn, /*!< in: buffer start lsn */ - lsn_t* contiguous_lsn, /*!< in/out: it is known that all log - groups contain contiguous log data up - to this lsn */ - lsn_t* group_scanned_lsn,/*!< out: scanning succeeded up to - this lsn */ - bool* finished) /*!< out: false if is not able to scan - any more in this log group */ +lsn_t +xtrabackup_copy_log(bool is_last, lsn_t start_lsn, lsn_t end_lsn) { - lsn_t scanned_lsn; - ulint data_len; - ulint write_size; - const byte* log_block; - - ulint scanned_checkpoint_no = 0; + lsn_t scanned_lsn = start_lsn; - *finished = false; - scanned_lsn = start_lsn; - log_block = log_sys->buf; + const ulint blocks_in_group = log_block_convert_lsn_to_no( + log_sys->log.capacity()) - 1; + const byte* log_block = log_sys->buf; - while (log_block < log_sys->buf + RECV_SCAN_SIZE && !*finished) { + for (ulint scanned_checkpoint = 0; + scanned_lsn < end_lsn; + log_block += OS_FILE_LOG_BLOCK_SIZE) { ulint no = log_block_get_hdr_no(log_block); ulint scanned_no = log_block_convert_lsn_to_no(scanned_lsn); - ibool checksum_is_ok = - log_block_checksum_is_ok_or_old_format(log_block); - - if (no != scanned_no && checksum_is_ok) { - ulint blocks_in_group; - - blocks_in_group = log_block_convert_lsn_to_no( - log_group_get_capacity(group)) - 1; + if (no != scanned_no) { if ((no < scanned_no && ((scanned_no - no) % blocks_in_group) == 0) || no == 0 || @@ -2501,15 +2223,15 @@ xtrabackup_scan_log_recs( blocks_in_group == 0) { /* old log block, do nothing */ - *finished = true; break; } msg("xtrabackup: error:" " log block numbers mismatch:\n" - "xtrabackup: error: expected log block no. %lu," - " but got no. %lu from the log file.\n", - (ulong) scanned_no, (ulong) no); + "xtrabackup: error: expected log block no. " + ULINTPF ", but got no. " ULINTPF + " from the log file.\n", + scanned_no, no); if ((no - scanned_no) % blocks_in_group == 0) { msg("xtrabackup: error:" @@ -2520,155 +2242,115 @@ xtrabackup_scan_log_recs( " log files being too small.\n"); } - return(false); - } else if (!checksum_is_ok) { - /* Garbage or an incompletely written log block */ - - msg("xtrabackup: warning: Log block checksum mismatch" - " (block no %lu at lsn " LSN_PF "): \n" - "expected %lu, calculated checksum %lu\n", - (ulong) no, - scanned_lsn, - (ulong) log_block_get_checksum(log_block), - (ulong) log_block_calc_checksum(log_block)); - msg("xtrabackup: warning: this is possible when the " - "log block has not been fully written by the " - "server, will retry later.\n"); - *finished = true; - break; - } - - if (log_block_get_flush_bit(log_block)) { - /* This block was a start of a log flush operation: - we know that the previous flush operation must have - been completed for all log groups before this block - can have been flushed to any of the groups. Therefore, - we know that log data is contiguous up to scanned_lsn - in all non-corrupt log groups. */ - - if (scanned_lsn > *contiguous_lsn) { - - *contiguous_lsn = scanned_lsn; - } + return(0); } - data_len = log_block_get_data_len(log_block); - - if ( - (scanned_checkpoint_no > 0) - && (log_block_get_checkpoint_no(log_block) - < scanned_checkpoint_no) - && (scanned_checkpoint_no - - log_block_get_checkpoint_no(log_block) - > 0x80000000UL)) { + ulint checkpoint = log_block_get_checkpoint_no(log_block); + if (scanned_checkpoint > checkpoint + && scanned_checkpoint - checkpoint >= 0x80000000UL) { /* Garbage from a log buffer flush which was made before the most recent database recovery */ - - *finished = true; break; } - scanned_lsn = scanned_lsn + data_len; - scanned_checkpoint_no = log_block_get_checkpoint_no(log_block); - - if (data_len < OS_FILE_LOG_BLOCK_SIZE) { - /* Log data for this group ends here */ + scanned_checkpoint = checkpoint; + ulint data_len = log_block_get_data_len(log_block); + scanned_lsn += data_len; - *finished = true; - } else { - log_block += OS_FILE_LOG_BLOCK_SIZE; + if (data_len != OS_FILE_LOG_BLOCK_SIZE) { + break; } } - *group_scanned_lsn = scanned_lsn; - - /* ===== write log to 'xtrabackup_logfile' ====== */ - if (!*finished) { - write_size = RECV_SCAN_SIZE; - } else { - write_size = (ulint)(ut_uint64_align_up(scanned_lsn, - OS_FILE_LOG_BLOCK_SIZE) - start_lsn); - if (!is_last && scanned_lsn % OS_FILE_LOG_BLOCK_SIZE) { - write_size -= OS_FILE_LOG_BLOCK_SIZE; - } + if (!is_last && scanned_lsn & (OS_FILE_LOG_BLOCK_SIZE - 1)) { + /* Omit the partial last block. */ + scanned_lsn &= ~(OS_FILE_LOG_BLOCK_SIZE - 1); } - if (write_size == 0) { - return(true); - } + log_sys->log.scanned_lsn = scanned_lsn; - if (srv_encrypt_log) { - log_encrypt_before_write(scanned_checkpoint_no, - log_sys->buf, write_size); - } + if (ulint write_size = ulint(ut_uint64_align_up(scanned_lsn, + OS_FILE_LOG_BLOCK_SIZE) + - start_lsn)) { + if (srv_encrypt_log) { + log_crypt(log_sys->buf, write_size); + } - if (ds_write(dst_log_file, log_sys->buf, write_size)) { - msg("xtrabackup: Error: " - "write to logfile failed\n"); - return(false); + if (ds_write(dst_log_file, log_sys->buf, write_size)) { + msg("xtrabackup: Error: " + "write to logfile failed\n"); + return(0); + } } - return(true); + return(scanned_lsn); } -static my_bool -xtrabackup_copy_logfile(lsn_t from_lsn, my_bool is_last) +/** Copy redo log until the current end of the log is reached +@param is_last whether this is the last run at the end of backup +@return whether the operation failed */ +static bool +xtrabackup_copy_logfile(bool is_last) { - /* definition from recv_recovery_from_checkpoint_start() */ - lsn_t contiguous_lsn; - ut_a(dst_log_file != NULL); + ut_ad(recv_sys != NULL); - /* read from checkpoint_lsn_start to current */ - contiguous_lsn = ut_uint64_align_down(from_lsn, OS_FILE_LOG_BLOCK_SIZE); - - /* TODO: We must check the contiguous_lsn still exists in log file.. */ - - bool finished; lsn_t start_lsn; lsn_t end_lsn; - /* reference recv_group_scan_log_recs() */ - - start_lsn = contiguous_lsn; + start_lsn = ut_uint64_align_down(log_copy_scanned_lsn, + OS_FILE_LOG_BLOCK_SIZE); - do { + /* When copying the last part of the log, retry a few times to + ensure that all log up to the last checkpoint will be read. */ + for (unsigned retries = is_last ? 3 : 0;;) { end_lsn = start_lsn + RECV_SCAN_SIZE; xtrabackup_io_throttling(); log_mutex_enter(); - log_group_read_log_seg(LOG_RECOVER, log_sys->buf, - &log_sys->log, start_lsn, end_lsn); + lsn_t lsn = log_group_read_log_seg(log_sys->buf, &log_sys->log, + start_lsn, end_lsn); - bool success = xtrabackup_scan_log_recs( - &log_sys->log, is_last, - start_lsn, &contiguous_lsn, - &log_sys->log.scanned_lsn, - &finished); + start_lsn = xtrabackup_copy_log(is_last, start_lsn, lsn); log_mutex_exit(); - if (!success) { + if (!start_lsn) { ds_close(dst_log_file); + dst_log_file = NULL; msg("xtrabackup: Error: xtrabackup_copy_logfile()" " failed.\n"); - return(TRUE); + return(true); } - start_lsn = end_lsn; - } while (!finished); + if (start_lsn == end_lsn) { + /* All RECV_SCAN_SIZE bytes that were read + were valid redo log. Proceed to read more. */ + } else if (start_lsn & (OS_FILE_LOG_BLOCK_SIZE - 1)) { + /* The end of the log was encountered. */ + ut_ad(is_last); + break; + } else if (retries--) { + /* Retry copying the last log segment. */ + ut_ad(is_last); + os_thread_sleep(xtrabackup_log_copy_interval * 1000); + } else { + break; + } + } - msg_ts(">> log scanned up to (" LSN_PF ")\n", - log_sys->log.scanned_lsn); + ut_ad(start_lsn == log_sys->log.scanned_lsn); + + msg_ts(">> log scanned up to (" LSN_PF ")\n", start_lsn); /* update global variable*/ - log_copy_scanned_lsn = log_sys->log.scanned_lsn; + log_copy_scanned_lsn = start_lsn; debug_sync_point("xtrabackup_copy_logfile_pause"); - return(FALSE); + return(false); } static @@ -2677,8 +2359,7 @@ void* #else ulint #endif -log_copying_thread( - void* arg __attribute__((unused))) +log_copying_thread(void*) { /* Initialize mysys thread-specific memory so we can @@ -2686,31 +2367,17 @@ log_copying_thread( */ my_thread_init(); - ut_a(dst_log_file != NULL); - - log_copying_running = TRUE; - - while(log_copying) { + while (log_copying) { os_event_reset(log_copying_stop); os_event_wait_time_low(log_copying_stop, xtrabackup_log_copy_interval * 1000ULL, 0); - if (log_copying) { - if(xtrabackup_copy_logfile(log_copy_scanned_lsn, - FALSE)) { - - exit(EXIT_FAILURE); - } + if (log_copying && xtrabackup_copy_logfile(false)) { + break; } } - /* last copying */ - if(xtrabackup_copy_logfile(log_copy_scanned_lsn, TRUE)) { - - exit(EXIT_FAILURE); - } - - log_copying_running = FALSE; + log_copying_running = false; my_thread_end(); os_thread_exit(NULL); @@ -2724,15 +2391,11 @@ void* #else ulint #endif -io_watching_thread( - void* arg) +io_watching_thread(void*) { - (void)arg; /* currently, for --backup only */ ut_a(xtrabackup_backup); - io_watching_thread_running = TRUE; - while (log_copying) { os_thread_sleep(1000000); /*1 sec*/ io_ticket = xtrabackup_throttle; @@ -2743,47 +2406,11 @@ io_watching_thread( xtrabackup_throttle = 0; os_event_set(wait_throttle); - io_watching_thread_running = FALSE; - - os_thread_exit(NULL); - - return(0); -} - -/************************************************************************ -I/o-handler thread function. */ -static - -#ifndef __WIN__ -void* -#else -ulint -#endif -io_handler_thread( -/*==============*/ - void* arg) -{ - ulint segment; - - - segment = *((ulint*)arg); - - while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) { - fil_aio_wait(segment); - } - - /* We count the number of threads in os_thread_exit(). A created - thread should always use that to exit and not use return() to exit. - The thread actually never comes here because it is exited in an - os_event_wait(). */ + io_watching_thread_running = false; os_thread_exit(NULL); -#ifndef __WIN__ - return(NULL); /* Not reached */ -#else return(0); -#endif } /************************************************************************** @@ -2816,9 +2443,9 @@ data_copy_thread_func( } } - os_mutex_enter(ctxt->count_mutex); + pthread_mutex_lock(&ctxt->count_mutex); (*ctxt->count)--; - os_mutex_exit(ctxt->count_mutex); + pthread_mutex_unlock(&ctxt->count_mutex); my_thread_end(); os_thread_exit(NULL); @@ -2831,7 +2458,7 @@ Initialize the appropriate datasink(s). Both local backups and streaming in the Otherwise (i.e. when streaming in the 'tar' format) we need 2 separate datasinks for the data stream (and don't allow parallel data copying) and for metainfo -files (including xtrabackup_logfile). The second datasink writes to temporary +files (including ib_logfile0). The second datasink writes to temporary files first, and then streams them in a serialized way when closed. */ static void xtrabackup_init_datasinks(void) @@ -2917,41 +2544,261 @@ static void xtrabackup_destroy_datasinks(void) ds_redo = NULL; } -#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD #define SRV_MAX_N_PENDING_SYNC_IOS 100 -/************************************************************************ -@return TRUE if table should be opened. */ +/** Initialize the tablespace cache subsystem. */ static -ibool -xb_check_if_open_tablespace( - const char* db, - const char* table) +void +xb_fil_io_init() { - char buf[FN_REFLEN]; - - snprintf(buf, sizeof(buf), "%s/%s", db, table); + fil_init(srv_file_per_table ? 50000 : 5000, LONG_MAX); + fsp_init(); +} - return !check_if_skip_table(buf); +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); + } } -/************************************************************************ -Initializes the I/O and tablespace cache subsystems. */ static void -xb_fil_io_init(void) -/*================*/ +xb_load_single_table_tablespace( + const char *dirname, + const char *filname, + bool is_remote) { - srv_n_file_io_threads = srv_n_read_io_threads; + /* Ignore .isl files on XtraBackup recovery. All tablespaces must be + local. */ + if (is_remote && srv_operation == SRV_OPERATION_RESTORE) { + return; + } + if (check_if_skip_table(filname)) { + return; + } - os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD, - srv_n_read_io_threads, - srv_n_write_io_threads, - SRV_MAX_N_PENDING_SYNC_IOS); + /* The name ends in .ibd or .isl; + try opening the file */ + char* name; + size_t dirlen = dirname == NULL ? 0 : strlen(dirname); + size_t namelen = strlen(filname); + ulint pathlen = dirname == NULL ? namelen + 1: dirlen + namelen + 2; + lsn_t flush_lsn; + dberr_t err; + fil_space_t *space; - fil_init(srv_file_per_table ? 50000 : 5000, LONG_MAX); + name = static_cast<char*>(ut_malloc_nokey(pathlen)); - fsp_init(); + if (dirname != NULL) { + ut_snprintf(name, pathlen, "%s/%s", dirname, filname); + name[pathlen - 5] = 0; + } else { + ut_snprintf(name, pathlen, "%s", filname); + name[pathlen - 5] = 0; + } + + Datafile *file = xb_new_datafile(name, is_remote); + + if (file->open_read_only(true) != DB_SUCCESS) { + ut_free(name); + exit(EXIT_FAILURE); + } + + err = file->validate_first_page(&flush_lsn); + + if (err == DB_SUCCESS && file->space_id() != SRV_TMP_SPACE_ID) { + os_offset_t node_size = os_file_get_size(file->handle()); + os_offset_t n_pages; + + ut_a(node_size != (os_offset_t) -1); + + n_pages = node_size / page_size_t(file->flags()).physical(); + + space = fil_space_create( + name, file->space_id(), file->flags(), + FIL_TYPE_TABLESPACE, NULL/* TODO: crypt_data */); + + ut_a(space != NULL); + + if (!fil_node_create(file->filepath(), n_pages, space, + false, false)) { + ut_error; + } + + /* by opening the tablespace we forcing node and space objects + in the cache to be populated with fields from space header */ + fil_space_open(space->name); + + if (srv_operation == SRV_OPERATION_RESTORE || xb_close_files) { + fil_space_close(space->name); + } + } + + ut_free(name); + + if (fil_space_crypt_t* crypt_info = file->get_crypt_info()) { + fil_space_destroy_crypt_data(&crypt_info); + } + + delete file; + + if (err != DB_SUCCESS && err != DB_CORRUPTION && xtrabackup_backup) { + /* allow corrupted first page for xtrabackup, it could be just + zero-filled page, which we restore from redo log later */ + exit(EXIT_FAILURE); + } +} + +/** Scan the database directories under the MySQL datadir, looking for +.ibd files and determining the space id in each of them. +@return DB_SUCCESS or error number */ +static +dberr_t +xb_load_single_table_tablespaces() +{ + int ret; + char* dbpath = NULL; + ulint dbpath_len = 100; + os_file_dir_t dir; + os_file_dir_t dbdir; + os_file_stat_t dbinfo; + os_file_stat_t fileinfo; + dberr_t err = DB_SUCCESS; + + /* The datadir of MySQL is always the default directory of mysqld */ + + dir = os_file_opendir(fil_path_to_mysql_datadir, true); + + if (dir == NULL) { + + return(DB_ERROR); + } + + dbpath = static_cast<char*>(ut_malloc_nokey(dbpath_len)); + + /* Scan all directories under the datadir. They are the database + directories of MySQL. */ + + ret = fil_file_readdir_next_file(&err, fil_path_to_mysql_datadir, dir, + &dbinfo); + while (ret == 0) { + size_t len = strlen(dbinfo.name); + + /* General tablespaces are always at the first level of the + data home dir */ + if (dbinfo.type == OS_FILE_TYPE_FILE && len > 4) { + bool is_isl = !strcmp(dbinfo.name + len - 4, ".isl"); + bool is_ibd = !is_isl + && !strcmp(dbinfo.name + len - 4, ".ibd"); + + if (is_isl || is_ibd) { + xb_load_single_table_tablespace( + NULL, dbinfo.name, is_isl); + } + } + + if (dbinfo.type == OS_FILE_TYPE_FILE + || dbinfo.type == OS_FILE_TYPE_UNKNOWN) { + + goto next_datadir_item; + } + + /* We found a symlink or a directory; try opening it to see + if a symlink is a directory */ + + len = strlen(fil_path_to_mysql_datadir) + + strlen (dbinfo.name) + 2; + if (len > dbpath_len) { + dbpath_len = len; + + if (dbpath) { + ut_free(dbpath); + } + + dbpath = static_cast<char*>(ut_malloc_nokey(dbpath_len)); + } + ut_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); + goto next_datadir_item; + } + + /* We want wrong directory permissions to be a fatal error for + XtraBackup. */ + dbdir = os_file_opendir(dbpath, true); + + if (dbdir != NULL) { + + /* We found a database directory; loop through it, + looking for possible .ibd files in it */ + + for (ret = fil_file_readdir_next_file(&err, dbpath, + dbdir, + &fileinfo); + ret == 0; + ret = fil_file_readdir_next_file(&err, dbpath, + dbdir, + &fileinfo)) { + if (fileinfo.type == OS_FILE_TYPE_DIR) { + continue; + } + + size_t len = strlen(fileinfo.name); + + /* We found a symlink or a file */ + if (len > 4 + && !strcmp(fileinfo.name + len - 4, + ".ibd")) { + xb_load_single_table_tablespace( + dbinfo.name, fileinfo.name, + false); + } + } + + if (0 != os_file_closedir(dbdir)) { + fprintf(stderr, "InnoDB: Warning: could not" + " close database directory %s\n", + dbpath); + + err = DB_ERROR; + } + + } else { + + err = DB_ERROR; + break; + + } + +next_datadir_item: + ret = fil_file_readdir_next_file(&err, + fil_path_to_mysql_datadir, + dir, &dbinfo); + } + + ut_free(dbpath); + + if (0 != os_file_closedir(dir)) { + fprintf(stderr, + "InnoDB: Error: could not close MySQL datadir\n"); + + return(DB_ERROR); + } + + return(err); } /**************************************************************************** @@ -2961,25 +2808,26 @@ static dberr_t xb_load_tablespaces() { - ulint i; bool create_new_db; dberr_t err; ulint sum_of_new_sizes; - lsn_t min_arch_logno, max_arch_logno; + lsn_t flush_lsn; - for (i = 0; i < srv_n_file_io_threads; i++) { - thread_nr[i] = i; + ut_ad(srv_operation == SRV_OPERATION_BACKUP + || srv_operation == SRV_OPERATION_RESTORE); - os_thread_create(io_handler_thread, thread_nr + i, - thread_ids + i); - } + err = srv_sys_space.check_file_spec(&create_new_db, 0); - os_thread_sleep(200000); /*0.2 sec*/ + /* create_new_db must not be true. */ + if (err != DB_SUCCESS || create_new_db) { + msg("xtrabackup: could not find data files at the " + "specified datadir\n"); + return(DB_ERROR); + } + + err = srv_sys_space.open_or_create(false, false, &sum_of_new_sizes, + &flush_lsn); - err = open_or_create_data_files(&create_new_db, - &min_arch_logno, &max_arch_logno, - &flushed_lsn, - &sum_of_new_sizes); if (err != DB_SUCCESS) { msg("xtrabackup: Could not open or create data files.\n" "xtrabackup: If you tried to add new data files, and it " @@ -2997,30 +2845,21 @@ xb_load_tablespaces() return(err); } - /* create_new_db must not be TRUE.. */ - if (create_new_db) { - msg("xtrabackup: could not find data files at the " - "specified datadir\n"); - return(DB_ERROR); - } - /* Add separate undo tablespaces to fil_system */ - err = srv_undo_tablespaces_init(FALSE, - TRUE, - srv_undo_tablespaces, - &srv_undo_tablespaces_open); + err = srv_undo_tablespaces_init(false); + if (err != DB_SUCCESS) { return(err); } - /* It is important to call fil_load_single_table_tablespace() after + /* It is important to call xb_load_single_table_tablespaces() after srv_undo_tablespaces_init(), because fil_is_user_tablespace_id() * relies on srv_undo_tablespaces_open to be properly initialized */ msg("xtrabackup: Generating a list of tablespaces\n"); - err = fil_load_single_table_tablespaces(xb_check_if_open_tablespace); + err = xb_load_single_table_tablespaces(); if (err != DB_SUCCESS) { return(err); } @@ -3049,42 +2888,11 @@ static void xb_data_files_close() { - ulint i; - - /* Shutdown the aio threads. This has been copied from - innobase_shutdown_for_mysql(). */ - - srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS; - - for (i = 0; i < 1000; i++) { - os_aio_wake_all_threads_at_shutdown(); - - if (os_thread_count == 0) { - break; - } - os_thread_sleep(10000); - } - - if (i == 1000) { - msg("xtrabackup: Warning: %lu threads created by InnoDB" - " had not exited at shutdown!\n", - (ulong) os_thread_count); - } - - os_aio_free(); - + ut_ad(!os_thread_count); fil_close_all_files(); - - /* Free the double write data structures. */ if (buf_dblwr) { buf_dblwr_free(); } - - /* Reset srv_file_io_threads to its default value to avoid confusing - warning on --prepare in innobase_start_or_create_for_mysql()*/ - srv_n_file_io_threads = 4; - - srv_shutdown_state = SRV_SHUTDOWN_NONE; } /*********************************************************************** @@ -3103,7 +2911,7 @@ xb_new_filter_entry( ut_a(namelen <= NAME_LEN * 2 + 1); entry = static_cast<xb_filter_entry_t *> - (ut_malloc(sizeof(xb_filter_entry_t) + namelen + 1)); + (malloc(sizeof(xb_filter_entry_t) + namelen + 1)); memset(entry, '\0', sizeof(xb_filter_entry_t) + namelen + 1); entry->name = ((char*)entry) + sizeof(xb_filter_entry_t); strcpy(entry->name, name); @@ -3402,7 +3210,7 @@ xb_filter_hash_free(hash_table_t* hash) HASH_DELETE(xb_filter_entry_t, name_hash, hash, ut_fold_string(prev_table->name), prev_table); - ut_free(prev_table); + free(prev_table); } } @@ -3451,77 +3259,33 @@ static ulint open_or_create_log_file( /*====================*/ - ibool create_new_db, /*!< in: TRUE if we should create a - new database */ + fil_space_t* space, ibool* log_file_created, /*!< out: TRUE if new log file created */ - ibool log_file_has_been_opened,/*!< in: TRUE if a log file has been - opened before: then it is an error - to try to create another log file */ ulint i) /*!< in: log file number in group */ { - ibool ret; - os_offset_t size; char name[10000]; ulint dirnamelen; - UT_NOT_USED(create_new_db); - UT_NOT_USED(log_file_has_been_opened); - *log_file_created = FALSE; - srv_normalize_path_for_win(srv_log_group_home_dir); + os_normalize_path(srv_log_group_home_dir); dirnamelen = strlen(srv_log_group_home_dir); ut_a(dirnamelen < (sizeof name) - 10 - sizeof "ib_logfile"); memcpy(name, srv_log_group_home_dir, dirnamelen); /* Add a path separator if needed. */ - if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) { - name[dirnamelen++] = SRV_PATH_SEPARATOR; + if (dirnamelen && name[dirnamelen - 1] != OS_PATH_SEPARATOR) { + name[dirnamelen++] = OS_PATH_SEPARATOR; } sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i); - files[i] = os_file_create(innodb_file_log_key, name, - OS_FILE_OPEN, OS_FILE_NORMAL, - OS_LOG_FILE, &ret,0); - if (ret == FALSE) { - fprintf(stderr, "InnoDB: Error in opening %s\n", name); - - return(DB_ERROR); - } - - size = os_file_get_size(files[i]); - - if (size != srv_log_file_size * UNIV_PAGE_SIZE) { - - fprintf(stderr, - "InnoDB: Error: log file %s is" - " of different size " UINT64PF " bytes\n" - "InnoDB: than specified in the .cnf" - " file " UINT64PF " bytes!\n", - name, size, srv_log_file_size * UNIV_PAGE_SIZE); - - return(DB_ERROR); - } - - ret = os_file_close(files[i]); - ut_a(ret); - - if (i == 0) { - /* Create in memory the file space object - which is for this log group */ - - fil_space_create(name, - SRV_LOG_SPACE_FIRST_ID, 0, FIL_TYPE_LOG, 0, 0); - log_init(srv_n_log_files, srv_log_file_size * UNIV_PAGE_SIZE); - } - ut_a(fil_validate()); - ut_a(fil_node_create(name, (ulint)srv_log_file_size, - SRV_LOG_SPACE_FIRST_ID, FALSE)); + ut_a(fil_node_create(name, srv_log_file_size >> srv_page_size_shift, + space, false, false)); return(DB_SUCCESS); } @@ -3534,20 +3298,8 @@ void xb_normalize_init_values(void) /*==========================*/ { - ulint i; - - for (i = 0; i < srv_n_data_files; i++) { - srv_data_file_sizes[i] = srv_data_file_sizes[i] - * ((1024 * 1024) / UNIV_PAGE_SIZE); - } - - srv_last_file_size_max = srv_last_file_size_max - * ((1024 * 1024) / UNIV_PAGE_SIZE); - - srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE; - - srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE; - + srv_sys_space.normalize(); + srv_log_buffer_size /= UNIV_PAGE_SIZE; srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE); } @@ -3608,8 +3360,11 @@ end: #endif } -void -xtrabackup_backup_func(void) +/** Implement --backup +@return whether the operation succeeded */ +static +bool +xtrabackup_backup_func() { MY_STAT stat_info; lsn_t latest_cp; @@ -3627,7 +3382,7 @@ xtrabackup_backup_func(void) if (my_setwd(mysql_real_data_home,MYF(MY_WME))) { msg("xtrabackup: cannot my_setwd %s\n", mysql_real_data_home); - exit(EXIT_FAILURE); + return(false); } msg("xtrabackup: cd to %s\n", mysql_real_data_home); @@ -3642,49 +3397,50 @@ xtrabackup_backup_func(void) srv_n_purge_threads = 1; srv_read_only_mode = TRUE; - srv_backup_mode = TRUE; - srv_close_files = (bool)xb_close_files; + srv_operation = SRV_OPERATION_BACKUP; - if (srv_close_files) + if (xb_close_files) msg("xtrabackup: warning: close-files specified. Use it " "at your own risk. If there are DDL operations like table DROP TABLE " "or RENAME TABLE during the backup, inconsistent backup will be " "produced.\n"); /* initialize components */ - if(innodb_init_param()) - exit(EXIT_FAILURE); + if(innodb_init_param()) { +fail: + innodb_shutdown(); + return(false); + } xb_normalize_init_values(); if (srv_file_flush_method_str == NULL) { - /* These are the default options */ - srv_unix_file_flush_method = SRV_UNIX_FSYNC; + /* These are the default options */ + srv_file_flush_method = SRV_FSYNC; } else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) { - srv_unix_file_flush_method = SRV_UNIX_FSYNC; + srv_file_flush_method = SRV_FSYNC; } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) { - srv_unix_file_flush_method = SRV_UNIX_O_DSYNC; + srv_file_flush_method = SRV_O_DSYNC; } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) { - srv_unix_file_flush_method = SRV_UNIX_O_DIRECT; + srv_file_flush_method = SRV_O_DIRECT; msg("xtrabackup: using O_DIRECT\n"); } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) { - srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC; - + srv_file_flush_method = SRV_LITTLESYNC; } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) { - srv_unix_file_flush_method = SRV_UNIX_NOSYNC; + srv_file_flush_method = SRV_NOSYNC; } else if (0 == ut_strcmp(srv_file_flush_method_str, "ALL_O_DIRECT")) { - srv_unix_file_flush_method = SRV_UNIX_ALL_O_DIRECT; + srv_file_flush_method = SRV_ALL_O_DIRECT_FSYNC; msg("xtrabackup: using ALL_O_DIRECT\n"); } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT_NO_FSYNC")) { - srv_unix_file_flush_method = SRV_UNIX_O_DIRECT_NO_FSYNC; + srv_file_flush_method = SRV_O_DIRECT_NO_FSYNC; msg("xtrabackup: using O_DIRECT_NO_FSYNC\n"); } else { - msg("xtrabackup: Unrecognized value %s for " + msg("xtrabackup: Unrecognized value %s for " "innodb_flush_method\n", srv_file_flush_method_str); - exit(EXIT_FAILURE); + goto fail; } /* We can only use synchronous unbuffered IO on Windows for now */ @@ -3694,8 +3450,8 @@ xtrabackup_backup_func(void) } #ifdef _WIN32 - srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; - srv_use_native_aio = FALSE; + srv_file_flush_method = SRV_ALL_O_DIRECT_FSYNC; + srv_use_native_aio = TRUE; #endif if (srv_buf_pool_size >= 1000 * 1024 * 1024) { @@ -3715,12 +3471,19 @@ xtrabackup_backup_func(void) computers */ } - srv_general_init(); + sync_check_init(); + ut_d(sync_check_enable()); + /* Reset the system variables in the recovery module. */ + recv_sys_var_init(); + trx_pool_init(); + row_mysql_init(); + ut_crc32_init(); crc_init(); + recv_sys_init(); #ifdef WITH_INNODB_DISALLOW_WRITES - srv_allow_writes_event = os_event_create(); + srv_allow_writes_event = os_event_create(0); os_event_set(srv_allow_writes_event); #endif @@ -3734,18 +3497,23 @@ xtrabackup_backup_func(void) ulint i; xb_fil_io_init(); + srv_n_file_io_threads = srv_n_read_io_threads; + + os_aio_init(srv_n_read_io_threads, srv_n_write_io_threads, + SRV_MAX_N_PENDING_SYNC_IOS); log_sys_init(); + log_init(srv_n_log_files); + fil_space_t* space = fil_space_create( + "innodb_redo_log", SRV_LOG_SPACE_FIRST_ID, 0, + FIL_TYPE_LOG, NULL); lock_sys_create(srv_lock_table_size); for (i = 0; i < srv_n_log_files; i++) { - err = open_or_create_log_file(FALSE, &log_file_created, - log_opened, i); + err = open_or_create_log_file(space, &log_file_created, i); if (err != DB_SUCCESS) { - - //return((int) err); - exit(EXIT_FAILURE); + goto fail; } if (log_file_created) { @@ -3762,15 +3530,14 @@ xtrabackup_backup_func(void) "xtrabackup: Then delete the existing log files. Edit the .cnf file\n" "xtrabackup: and start the database again.\n"); - //return(DB_ERROR); - exit(EXIT_FAILURE); + goto fail; } } /* log_file_created must not be TRUE, if online */ if (log_file_created) { msg("xtrabackup: Something wrong with source files...\n"); - exit(EXIT_FAILURE); + goto fail; } } @@ -3781,7 +3548,7 @@ xtrabackup_backup_func(void) && (my_mkdir(xtrabackup_extra_lsndir,0777,MYF(0)) < 0)) { msg("xtrabackup: Error: cannot mkdir %d: %s\n", my_errno, xtrabackup_extra_lsndir); - exit(EXIT_FAILURE); + goto fail; } /* create target dir if not exist */ @@ -3789,12 +3556,10 @@ xtrabackup_backup_func(void) && (my_mkdir(xtrabackup_target_dir,0777,MYF(0)) < 0)){ msg("xtrabackup: Error: cannot mkdir %d: %s\n", my_errno, xtrabackup_target_dir); - exit(EXIT_FAILURE); + goto fail; } { - fil_system_t* f_system = fil_system; - /* definition from recv_recovery_from_checkpoint_start() */ ulint max_cp_field; @@ -3810,14 +3575,17 @@ xtrabackup_backup_func(void) dberr_t err = recv_find_max_checkpoint(&max_cp_field); if (err != DB_SUCCESS) { - exit(EXIT_FAILURE); +log_fail: + log_mutex_exit(); + goto fail; } if (log_sys->log.format == 0) { old_format: msg("xtrabackup: Error: cannot process redo log" " before MariaDB 10.2.2\n"); - exit(EXIT_FAILURE); + log_mutex_exit(); + goto log_fail; } ut_ad(!((log_sys->log.format ^ LOG_HEADER_FORMAT_CURRENT) @@ -3832,7 +3600,7 @@ reread_log_header: err = recv_find_max_checkpoint(&max_cp_field); if (err != DB_SUCCESS) { - exit(EXIT_FAILURE); + goto log_fail; } if (log_sys->log.format == 0) { @@ -3842,7 +3610,7 @@ reread_log_header: ut_ad(!((log_sys->log.format ^ LOG_HEADER_FORMAT_CURRENT) & ~LOG_HEADER_FORMAT_ENCRYPTED)); - if(checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) { + if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) { checkpoint_lsn_start = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); checkpoint_no_start = mach_read_from_8(buf + LOG_CHECKPOINT_NO); @@ -3854,34 +3622,50 @@ reread_log_header: xtrabackup_init_datasinks(); if (!select_history()) { - exit(EXIT_FAILURE); + goto fail; } /* open the log file */ memset(&stat_info, 0, sizeof(MY_STAT)); - dst_log_file = ds_open(ds_redo, XB_LOG_FILENAME, &stat_info); + dst_log_file = ds_open(ds_redo, "ib_logfile0", &stat_info); if (dst_log_file == NULL) { msg("xtrabackup: error: failed to open the target stream for " - "'%s'.\n", XB_LOG_FILENAME); - ut_free(log_hdr_buf_); - exit(EXIT_FAILURE); + "'ib_logfile0'.\n"); + goto fail; } /* label it */ - strcpy((char*) log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, - "xtrabkup "); - ut_sprintf_timestamp( - (char*) log_hdr_buf + (LOG_FILE_WAS_CREATED_BY_HOT_BACKUP - + (sizeof "xtrabkup ") - 1)); - - if (ds_write(dst_log_file, log_hdr_buf, LOG_FILE_HDR_SIZE)) { + byte MY_ALIGNED(OS_FILE_LOG_BLOCK_SIZE) log_hdr[OS_FILE_LOG_BLOCK_SIZE]; + memset(log_hdr, 0, sizeof log_hdr); + mach_write_to_4(LOG_HEADER_FORMAT + log_hdr, log_sys->log.format); + mach_write_to_8(LOG_HEADER_START_LSN + log_hdr, checkpoint_lsn_start); + strcpy(reinterpret_cast<char*>(LOG_HEADER_CREATOR + log_hdr), + "Backup " MYSQL_SERVER_VERSION); + log_block_set_checksum(log_hdr, + log_block_calc_checksum_crc32(log_hdr)); + + /* Write the log header. */ + if (ds_write(dst_log_file, log_hdr, sizeof log_hdr)) { + log_write_fail: msg("xtrabackup: error: write to logfile failed\n"); - ut_free(log_hdr_buf_); - exit(EXIT_FAILURE); + goto fail; + } + /* Adjust the checkpoint page. */ + memcpy(log_hdr, buf, OS_FILE_LOG_BLOCK_SIZE); + mach_write_to_8(log_hdr + LOG_CHECKPOINT_OFFSET, + (checkpoint_lsn_start & (OS_FILE_LOG_BLOCK_SIZE - 1)) + | LOG_FILE_HDR_SIZE); + log_block_set_checksum(log_hdr, + log_block_calc_checksum_crc32(log_hdr)); + /* Write checkpoint page 1 and two empty log pages before the + payload. */ + if (ds_write(dst_log_file, log_hdr, OS_FILE_LOG_BLOCK_SIZE) + || !memset(log_hdr, 0, sizeof log_hdr) + || ds_write(dst_log_file, log_hdr, sizeof log_hdr) + || ds_write(dst_log_file, log_hdr, sizeof log_hdr)) { + goto log_write_fail; } - ut_free(log_hdr_buf_); - /* start flag */ log_copying = TRUE; @@ -3890,18 +3674,20 @@ reread_log_header: os_thread_id_t io_watching_thread_id; io_ticket = xtrabackup_throttle; - wait_throttle = os_event_create(); + wait_throttle = os_event_create(0); + io_watching_thread_running = true; os_thread_create(io_watching_thread, NULL, &io_watching_thread_id); } /* copy log file by current position */ - if(xtrabackup_copy_logfile(checkpoint_lsn_start, FALSE)) - exit(EXIT_FAILURE); + log_copy_scanned_lsn = checkpoint_lsn_start; + if (xtrabackup_copy_logfile(false)) + goto fail; - - log_copying_stop = os_event_create(); + log_copying_stop = os_event_create(0); + log_copying_running = true; os_thread_create(log_copying_thread, NULL, &log_copying_thread_id); /* Populate fil_system with tablespaces to copy */ @@ -3909,12 +3695,12 @@ reread_log_header: if (err != DB_SUCCESS) { msg("xtrabackup: error: xb_load_tablespaces() failed with" "error code %u\n", err); - exit(EXIT_FAILURE); + goto fail; } /* FLUSH CHANGED_PAGE_BITMAPS call */ if (!flush_changed_page_bitmaps()) { - exit(EXIT_FAILURE); + goto fail; } debug_sync_point("xtrabackup_suspend_at_start"); @@ -3939,17 +3725,17 @@ reread_log_header: "files transfer\n", xtrabackup_parallel); } - it = datafiles_iter_new(f_system); + it = datafiles_iter_new(fil_system); if (it == NULL) { msg("xtrabackup: Error: datafiles_iter_new() failed.\n"); - exit(EXIT_FAILURE); + goto fail; } /* Create data copying threads */ data_threads = (data_thread_ctxt_t *) - ut_malloc(sizeof(data_thread_ctxt_t) * xtrabackup_parallel); + malloc(sizeof(data_thread_ctxt_t) * xtrabackup_parallel); count = xtrabackup_parallel; - count_mutex = os_mutex_create(); + pthread_mutex_init(&count_mutex, NULL); for (i = 0; i < (uint) xtrabackup_parallel; i++) { data_threads[i].it = it; @@ -3963,16 +3749,16 @@ reread_log_header: /* Wait for threads to exit */ while (1) { os_thread_sleep(1000000); - os_mutex_enter(count_mutex); - if (count == 0) { - os_mutex_exit(count_mutex); + pthread_mutex_lock(&count_mutex); + bool stop = count == 0; + pthread_mutex_unlock(&count_mutex); + if (stop) { break; } - os_mutex_exit(count_mutex); } - os_mutex_free(count_mutex); - ut_free(data_threads); + pthread_mutex_destroy(&count_mutex); + free(data_threads); datafiles_iter_free(it); if (changed_page_bitmap) { @@ -3981,7 +3767,7 @@ reread_log_header: } if (!backup_start()) { - exit(EXIT_FAILURE); + goto fail; } /* read the latest checkpoint lsn */ @@ -4013,11 +3799,19 @@ reread_log_header: } msg("\n"); - os_event_free(log_copying_stop); + os_event_destroy(log_copying_stop); + + if (!dst_log_file || xtrabackup_copy_logfile(true)) { + goto fail; + } + if (ds_close(dst_log_file)) { - exit(EXIT_FAILURE); + dst_log_file = NULL; + goto fail; } + dst_log_file = NULL; + if(!xtrabackup_incremental) { strcpy(metadata_type, "full-backuped"); metadata_from_lsn = 0; @@ -4030,7 +3824,7 @@ reread_log_header: if (!xtrabackup_stream_metadata(ds_meta)) { msg("xtrabackup: Error: failed to stream metadata.\n"); - exit(EXIT_FAILURE); + goto fail; } if (xtrabackup_extra_lsndir) { char filename[FN_REFLEN]; @@ -4040,13 +3834,13 @@ reread_log_header: if (!xtrabackup_write_metadata(filename)) { msg("xtrabackup: Error: failed to write metadata " "to '%s'.\n", filename); - exit(EXIT_FAILURE); + goto fail; } } if (!backup_finish()) { - exit(EXIT_FAILURE); + goto fail; } xtrabackup_destroy_datasinks(); @@ -4056,319 +3850,29 @@ reread_log_header: while (io_watching_thread_running) { os_thread_sleep(1000000); } - os_event_free(wait_throttle); - wait_throttle = NULL; + os_event_destroy(wait_throttle); } - msg("xtrabackup: Transaction log of lsn (" LSN_PF ") to (" LSN_PF + msg("xtrabackup: Redo log (from LSN " LSN_PF " to " LSN_PF ") was copied.\n", checkpoint_lsn_start, log_copy_scanned_lsn); xb_filters_free(); xb_data_files_close(); - /* Make sure that the latest checkpoint made it to xtrabackup_logfile */ + /* Make sure that the latest checkpoint was included */ if (latest_cp > log_copy_scanned_lsn) { msg("xtrabackup: error: last checkpoint LSN (" LSN_PF ") is larger than last copied LSN (" LSN_PF ").\n", latest_cp, log_copy_scanned_lsn); - exit(EXIT_FAILURE); + goto fail; } + + innodb_shutdown(); + return(true); } /* ================= prepare ================= */ -static my_bool -xtrabackup_init_temp_log(void) -{ - pfs_os_file_t src_file; - char src_path[FN_REFLEN]; - char dst_path[FN_REFLEN]; - ibool success; - - ulint field; - byte* log_buf= (byte *)malloc(UNIV_PAGE_SIZE_MAX * 128); /* 2 MB */ - - ib_int64_t file_size; - - lsn_t max_no; - lsn_t max_lsn; - lsn_t checkpoint_no; - - ulint fold; - - bool checkpoint_found; - - max_no = 0; - - if (!log_buf) { - goto error; - } - - if (!xb_init_log_block_size()) { - goto error; - } - - if(!xtrabackup_incremental_dir) { - sprintf(dst_path, "%s/ib_logfile0", xtrabackup_target_dir); - sprintf(src_path, "%s/%s", xtrabackup_target_dir, - XB_LOG_FILENAME); - } else { - sprintf(dst_path, "%s/ib_logfile0", xtrabackup_incremental_dir); - sprintf(src_path, "%s/%s", xtrabackup_incremental_dir, - XB_LOG_FILENAME); - } - - srv_normalize_path_for_win(dst_path); - srv_normalize_path_for_win(src_path); -retry: - src_file = os_file_create_simple_no_error_handling(0, src_path, - OS_FILE_OPEN, - OS_FILE_READ_WRITE, - &success,0); - if (!success) { - /* The following call prints an error message */ - os_file_get_last_error(TRUE); - - msg("xtrabackup: Warning: cannot open %s. will try to find.\n", - src_path); - - /* check if ib_logfile0 may be xtrabackup_logfile */ - src_file = os_file_create_simple_no_error_handling(0, dst_path, - OS_FILE_OPEN, - OS_FILE_READ_WRITE, - &success,0); - if (!success) { - os_file_get_last_error(TRUE); - msg(" xtrabackup: Fatal error: cannot find %s.\n", - src_path); - - goto error; - } - - success = os_file_read(src_file, log_buf, 0, - LOG_FILE_HDR_SIZE); - if (!success) { - goto error; - } - - if ( ut_memcmp(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, - (byte*)"xtrabkup", (sizeof "xtrabkup") - 1) == 0) { - msg(" xtrabackup: 'ib_logfile0' seems to be " - "'xtrabackup_logfile'. will retry.\n"); - - os_file_close(src_file); - src_file = XB_FILE_UNDEFINED; - - /* rename and try again */ - success = os_file_rename(0, dst_path, src_path); - if (!success) { - goto error; - } - - goto retry; - } - - msg(" xtrabackup: Fatal error: cannot find %s.\n", - src_path); - - os_file_close(src_file); - src_file = XB_FILE_UNDEFINED; - - goto error; - } - - file_size = os_file_get_size(src_file); - - - /* TODO: We should skip the following modifies, if it is not the first time. */ - - /* read log file header */ - success = os_file_read(src_file, log_buf, 0, LOG_FILE_HDR_SIZE); - if (!success) { - goto error; - } - - if ( ut_memcmp(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, - (byte*)"xtrabkup", (sizeof "xtrabkup") - 1) != 0 ) { - msg("xtrabackup: notice: xtrabackup_logfile was already used " - "to '--prepare'.\n"); - goto skip_modify; - } else { - /* clear it later */ - //memset(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, - // ' ', 4); - } - - checkpoint_found = false; - - /* read last checkpoint lsn */ - for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; - field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { - if (!recv_check_cp_is_consistent(const_cast<const byte *> - (log_buf + field))) - goto not_consistent; - - checkpoint_no = mach_read_from_8(log_buf + field + - LOG_CHECKPOINT_NO); - - if (checkpoint_no >= max_no) { - - max_no = checkpoint_no; - max_lsn = mach_read_from_8(log_buf + field + - LOG_CHECKPOINT_LSN); - checkpoint_found = true; - } -not_consistent: - ; - } - - if (!checkpoint_found) { - msg("xtrabackup: No valid checkpoint found.\n"); - goto error; - } - - - /* It seems to be needed to overwrite the both checkpoint area. */ - mach_write_to_8(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN, - max_lsn); - mach_write_to_4(log_buf + LOG_CHECKPOINT_1 - + LOG_CHECKPOINT_OFFSET_LOW32, - LOG_FILE_HDR_SIZE + - (ulint)(max_lsn - - ut_uint64_align_down(max_lsn, - OS_FILE_LOG_BLOCK_SIZE))); - mach_write_to_4(log_buf + LOG_CHECKPOINT_1 - + LOG_CHECKPOINT_OFFSET_HIGH32, 0); - fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_1, LOG_CHECKPOINT_CHECKSUM_1); - mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_CHECKSUM_1, fold); - - fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN, - LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN); - mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_CHECKSUM_2, fold); - - mach_write_to_8(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN, - max_lsn); - mach_write_to_4(log_buf + LOG_CHECKPOINT_2 - + LOG_CHECKPOINT_OFFSET_LOW32, - LOG_FILE_HDR_SIZE + - (ulint)(max_lsn - - ut_uint64_align_down(max_lsn, - OS_FILE_LOG_BLOCK_SIZE))); - mach_write_to_4(log_buf + LOG_CHECKPOINT_2 - + LOG_CHECKPOINT_OFFSET_HIGH32, 0); - fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_2, LOG_CHECKPOINT_CHECKSUM_1); - mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_CHECKSUM_1, fold); - - fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN, - LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN); - mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_CHECKSUM_2, fold); - - - success = os_file_write(src_path, src_file, log_buf, 0, - LOG_FILE_HDR_SIZE); - if (!success) { - goto error; - } - - /* expand file size (9/8) and align to UNIV_PAGE_SIZE_MAX */ - - if (file_size % UNIV_PAGE_SIZE_MAX) { - memset(log_buf, 0, UNIV_PAGE_SIZE_MAX); - success = os_file_write(src_path, src_file, log_buf, - file_size, - UNIV_PAGE_SIZE_MAX - - (ulint) (file_size - % UNIV_PAGE_SIZE_MAX)); - if (!success) { - goto error; - } - - file_size = os_file_get_size(src_file); - } - - /* TODO: We should judge whether the file is already expanded or not... */ - { - ulint expand; - - memset(log_buf, 0, UNIV_PAGE_SIZE_MAX * 128); - expand = (ulint) (file_size / UNIV_PAGE_SIZE_MAX / 8); - - for (; expand > 128; expand -= 128) { - success = os_file_write(src_path, src_file, log_buf, - file_size, - UNIV_PAGE_SIZE_MAX * 128); - if (!success) { - goto error; - } - file_size += UNIV_PAGE_SIZE_MAX * 128; - } - - if (expand) { - success = os_file_write(src_path, src_file, log_buf, - file_size, - expand * UNIV_PAGE_SIZE_MAX); - if (!success) { - goto error; - } - file_size += UNIV_PAGE_SIZE_MAX * expand; - } - } - - /* make larger than 2MB */ - if (file_size < 2*1024*1024L) { - memset(log_buf, 0, UNIV_PAGE_SIZE_MAX); - while (file_size < 2*1024*1024L) { - success = os_file_write(src_path, src_file, log_buf, - file_size, - UNIV_PAGE_SIZE_MAX); - if (!success) { - goto error; - } - file_size += UNIV_PAGE_SIZE_MAX; - } - file_size = os_file_get_size(src_file); - } - - msg("xtrabackup: xtrabackup_logfile detected: size=" INT64PF ", " - "start_lsn=(" LSN_PF ")\n", file_size, max_lsn); - - os_file_close(src_file); - src_file = XB_FILE_UNDEFINED; - - /* fake InnoDB */ - innobase_log_files_in_group_save = innobase_log_files_in_group; - srv_log_group_home_dir_save = srv_log_group_home_dir; - innobase_log_file_size_save = innobase_log_file_size; - - srv_log_group_home_dir = NULL; - innobase_log_file_size = file_size; - innobase_log_files_in_group = 1; - - srv_thread_concurrency = 0; - - /* rename 'xtrabackup_logfile' to 'ib_logfile0' */ - success = os_file_rename(0, src_path, dst_path); - if (!success) { - goto error; - } - xtrabackup_logfile_is_renamed = TRUE; - free(log_buf); - return(FALSE); - -skip_modify: - free(log_buf); - os_file_close(src_file); - src_file = XB_FILE_UNDEFINED; - return(FALSE); - -error: - free(log_buf); - if (src_file != XB_FILE_UNDEFINED) - os_file_close(src_file); - msg("xtrabackup: Error: xtrabackup_init_temp_log() failed.\n"); - return(TRUE); /*ERROR*/ -} - /*********************************************************************** Generates path to the meta file path from a given path to an incremental .delta by replacing trailing ".delta" with ".meta", or returns error if 'delta_path' @@ -4398,31 +3902,30 @@ file. Code adopted from fil_create_new_single_table_tablespace with the main difference that only disk file is created without updating the InnoDB in-memory dictionary data structures. -@return TRUE on success, FALSE on error. */ +@return true on success, false on error. */ static -ibool +bool xb_space_create_file( /*==================*/ const char* path, /*!<in: path to tablespace */ ulint space_id, /*!<in: space id */ - ulint flags __attribute__((unused)),/*!<in: tablespace - flags */ + ulint flags, /*!<in: tablespace flags */ pfs_os_file_t* file) /*!<out: file handle */ { - ibool ret; + bool ret; byte* buf; byte* page; - *file = os_file_create_simple_no_error_handling(0, path, OS_FILE_CREATE, - OS_FILE_READ_WRITE, - &ret,0); + *file = os_file_create_simple_no_error_handling( + 0, path, OS_FILE_CREATE, OS_FILE_READ_WRITE, false, &ret); if (!ret) { msg("xtrabackup: cannot create file %s\n", path); return ret; } ret = os_file_set_size(path, *file, - FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE); + FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE, + false); if (!ret) { msg("xtrabackup: cannot set size for file %s\n", path); os_file_close(*file); @@ -4430,7 +3933,7 @@ xb_space_create_file( return ret; } - buf = static_cast<byte *>(ut_malloc(3 * UNIV_PAGE_SIZE)); + buf = static_cast<byte *>(malloc(3 * UNIV_PAGE_SIZE)); /* Align the memory for file i/o if we might have O_DIRECT set */ page = static_cast<byte *>(ut_align(buf, UNIV_PAGE_SIZE)); @@ -4439,19 +3942,19 @@ xb_space_create_file( fsp_header_init_fields(page, space_id, flags); mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id); - if (!fsp_flags_is_compressed(flags)) { - buf_flush_init_for_writing(page, NULL, 0); + const page_size_t page_size(flags); - ret = os_file_write(path, *file, page, 0, UNIV_PAGE_SIZE); - } - else { - page_zip_des_t page_zip; - ulint zip_size; + if (!page_size.is_compressed()) { + buf_flush_init_for_writing(NULL, page, NULL, 0, false); - zip_size = fsp_flags_get_zip_size(flags); + ret = os_file_write(IORequestWrite, path, *file, page, 0, + UNIV_PAGE_SIZE); + } else { + page_zip_des_t page_zip; + ulint zip_size = page_size.physical(); page_zip_set_size(&page_zip, zip_size); page_zip.data = page + UNIV_PAGE_SIZE; - fprintf(stderr, "zip_size = %lu\n", zip_size); + fprintf(stderr, "zip_size = " ULINTPF "\n", zip_size); #ifdef UNIV_DEBUG page_zip.m_start = @@ -4459,13 +3962,13 @@ xb_space_create_file( page_zip.m_end = page_zip.m_nonempty = page_zip.n_blobs = 0; - buf_flush_init_for_writing(page, &page_zip, 0); + buf_flush_init_for_writing(NULL, page, &page_zip, 0, false); - ret = os_file_write(path, *file, page_zip.data, 0, - zip_size); + ret = os_file_write(IORequestWrite, path, *file, + page_zip.data, 0, zip_size); } - ut_free(buf); + free(buf); if (!ret) { msg("xtrabackup: could not write the first page to %s\n", @@ -4490,35 +3993,32 @@ pfs_os_file_t xb_delta_open_matching_space( const char* dbname, /* in: path to destination database dir */ const char* name, /* in: name of delta file (without .delta) */ - ulint space_id, /* in: space id of delta file */ - ulint zip_size, /* in: zip_size of tablespace */ + const xb_delta_info_t& info, char* real_name, /* out: full path of destination file */ size_t real_name_len, /* out: buffer size for real_name */ - ibool* success) /* out: indicates error. TRUE = success */ + bool* success) /* out: indicates error. true = success */ { char dest_dir[FN_REFLEN]; char dest_space_name[FN_REFLEN]; - ibool ok; fil_space_t* fil_space; pfs_os_file_t file; - ulint tablespace_flags; xb_filter_entry_t* table; ut_a(dbname != NULL || - !fil_is_user_tablespace_id(space_id) || - space_id == ULINT_UNDEFINED); + !fil_is_user_tablespace_id(info.space_id) || + info.space_id == ULINT_UNDEFINED); - *success = FALSE; + *success = false; if (dbname) { snprintf(dest_dir, FN_REFLEN, "%s/%s", xtrabackup_target_dir, dbname); - srv_normalize_path_for_win(dest_dir); + 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); - srv_normalize_path_for_win(dest_dir); + os_normalize_path(dest_dir); snprintf(dest_space_name, FN_REFLEN, "%s", name); } @@ -4526,7 +4026,7 @@ xb_delta_open_matching_space( snprintf(real_name, real_name_len, "%s/%s", xtrabackup_target_dir, dest_space_name); - srv_normalize_path_for_win(real_name); + os_normalize_path(real_name); /* Truncate ".ibd" */ dest_space_name[strlen(dest_space_name) - 4] = '\0'; @@ -4536,13 +4036,26 @@ xb_delta_open_matching_space( return file; } - if (!fil_is_user_tablespace_id(space_id)) { - goto found; + log_mutex_enter(); + if (!fil_is_user_tablespace_id(info.space_id)) { +found: + /* open the file and return its handle */ + + file = os_file_create_simple_no_error_handling( + 0, real_name, + OS_FILE_OPEN, OS_FILE_READ_WRITE, false, success); + + if (!*success) { + msg("xtrabackup: Cannot open file %s\n", real_name); + } +exit: + log_mutex_exit(); + return file; } /* remember space name for further reference */ table = static_cast<xb_filter_entry_t *> - (ut_malloc(sizeof(xb_filter_entry_t) + + (malloc(sizeof(xb_filter_entry_t) + strlen(dest_space_name) + 1)); table->name = ((char*)table) + sizeof(xb_filter_entry_t); @@ -4555,7 +4068,8 @@ xb_delta_open_matching_space( mutex_exit(&fil_system->mutex); if (fil_space != NULL) { - if (fil_space->id == space_id || space_id == ULINT_UNDEFINED) { + if (fil_space->id == info.space_id + || info.space_id == ULINT_UNDEFINED) { /* we found matching space */ goto found; } else { @@ -4568,8 +4082,10 @@ xb_delta_open_matching_space( msg("xtrabackup: Renaming %s to %s.ibd\n", fil_space->name, tmpname); - if (!fil_rename_tablespace(NULL, fil_space->id, - tmpname, NULL)) + if (!fil_rename_tablespace( + fil_space->id, + fil_space->chain.start->name, + tmpname, NULL)) { msg("xtrabackup: Cannot rename %s to %s\n", fil_space->name, tmpname); @@ -4578,14 +4094,14 @@ xb_delta_open_matching_space( } } - if (space_id == ULINT_UNDEFINED) + if (info.space_id == ULINT_UNDEFINED) { msg("xtrabackup: Error: Cannot handle DDL operation on tablespace " "%s\n", dest_space_name); exit(EXIT_FAILURE); } mutex_enter(&fil_system->mutex); - fil_space = fil_space_get_by_id(space_id); + fil_space = fil_space_get_by_id(info.space_id); mutex_exit(&fil_system->mutex); if (fil_space != NULL) { char tmpname[FN_REFLEN]; @@ -4595,7 +4111,9 @@ xb_delta_open_matching_space( msg("xtrabackup: Renaming %s to %s\n", fil_space->name, dest_space_name); - if (!fil_rename_tablespace(NULL, fil_space->id, tmpname, + if (!fil_rename_tablespace(fil_space->id, + fil_space->chain.start->name, + tmpname, NULL)) { msg("xtrabackup: Cannot rename %s to %s\n", @@ -4607,49 +4125,30 @@ xb_delta_open_matching_space( } /* No matching space found. create the new one. */ - - if (!fil_space_create(dest_space_name, space_id, 0, - FIL_TABLESPACE, 0, false)) { + const ulint flags = info.page_size.is_compressed() + ? get_bit_shift(info.page_size.physical() + >> (UNIV_ZIP_SIZE_SHIFT_MIN - 1)) + << FSP_FLAGS_POS_ZIP_SSIZE + | FSP_FLAGS_MASK_POST_ANTELOPE + | FSP_FLAGS_MASK_ATOMIC_BLOBS + | (info.page_size.logical() == UNIV_PAGE_SIZE_ORIG + ? 0 + : get_bit_shift(info.page_size.logical() + >> (UNIV_ZIP_SIZE_SHIFT_MIN - 1)) + << FSP_FLAGS_POS_PAGE_SSIZE) + : FSP_FLAGS_PAGE_SSIZE(); + ut_ad(page_size_t(flags).equals_to(info.page_size)); + + if (fil_space_create(dest_space_name, info.space_id, flags, + FIL_TYPE_TABLESPACE, 0)) { + *success = xb_space_create_file(real_name, info.space_id, + flags, &file); + } else { msg("xtrabackup: Cannot create tablespace %s\n", - dest_space_name); - goto exit; + dest_space_name); } - /* Calculate correct tablespace flags for compressed tablespaces. */ - if (!zip_size || zip_size == ULINT_UNDEFINED) { - tablespace_flags = 0; - } - else { - tablespace_flags - = (get_bit_shift(zip_size >> PAGE_ZIP_MIN_SIZE_SHIFT - << 1) - << DICT_TF_ZSSIZE_SHIFT) - | DICT_TF_COMPACT - | (DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT); - ut_a(dict_tf_get_zip_size(tablespace_flags) - == zip_size); - } - *success = xb_space_create_file(real_name, space_id, tablespace_flags, - &file); goto exit; - -found: - /* open the file and return it's handle */ - - file = os_file_create_simple_no_error_handling(0, real_name, - OS_FILE_OPEN, - OS_FILE_READ_WRITE, - &ok,0); - - if (ok) { - *success = TRUE; - } else { - msg("xtrabackup: Cannot open file %s\n", real_name); - } - -exit: - - return file; } /************************************************************************ @@ -4670,13 +4169,13 @@ xtrabackup_apply_delta( char dst_path[FN_REFLEN]; char meta_path[FN_REFLEN]; char space_name[FN_REFLEN]; - ibool success; + bool success; ibool last_buffer = FALSE; ulint page_in_buffer; ulint incremental_buffers = 0; - xb_delta_info_t info; + xb_delta_info_t info(univ_page_size, SRV_TMP_SPACE_ID); ulint page_size; ulint page_size_shift; byte* incremental_buffer_base = NULL; @@ -4706,15 +4205,15 @@ xtrabackup_apply_delta( goto error; } - srv_normalize_path_for_win(dst_path); - srv_normalize_path_for_win(src_path); - srv_normalize_path_for_win(meta_path); + 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; } - page_size = info.page_size; + page_size = info.page_size.physical(); page_size_shift = get_bit_shift(page_size); msg("xtrabackup: page size for %s is %lu bytes\n", src_path, page_size); @@ -4725,10 +4224,9 @@ xtrabackup_apply_delta( goto error; } - src_file = os_file_create_simple_no_error_handling(0, src_path, - OS_FILE_OPEN, - OS_FILE_READ_WRITE, - &success,0); + src_file = os_file_create_simple_no_error_handling( + 0, src_path, + OS_FILE_OPEN, OS_FILE_READ_WRITE, false, &success); if (!success) { os_file_get_last_error(TRUE); msg("xtrabackup: error: cannot open %s\n", src_path); @@ -4740,7 +4238,7 @@ xtrabackup_apply_delta( os_file_set_nocache(src_file, src_path, "OPEN"); dst_file = xb_delta_open_matching_space( - dbname, space_name, info.space_id, info.zip_size, + dbname, space_name, info, dst_path, sizeof(dst_path), &success); if (!success) { msg("xtrabackup: error: cannot open %s\n", dst_path); @@ -4753,8 +4251,7 @@ xtrabackup_apply_delta( /* allocate buffer for incremental backup (4096 pages) */ incremental_buffer_base = static_cast<byte *> - (ut_malloc((page_size / 4 + 1) * - page_size)); + (malloc((page_size / 4 + 1) * page_size)); incremental_buffer = static_cast<byte *> (ut_align(incremental_buffer_base, page_size)); @@ -4768,8 +4265,8 @@ xtrabackup_apply_delta( /* first block of block cluster */ offset = ((incremental_buffers * (page_size / 4)) << page_size_shift); - success = os_file_read(src_file, incremental_buffer, - offset, page_size); + success = os_file_read(IORequestRead, src_file, + incremental_buffer, offset, page_size); if (!success) { goto error; } @@ -4787,6 +4284,9 @@ xtrabackup_apply_delta( goto error; } + /* FIXME: If the .delta modifies FSP_SIZE on page 0, + extend the file to that size. */ + for (page_in_buffer = 1; page_in_buffer < page_size / 4; page_in_buffer++) { if (mach_read_from_4(incremental_buffer + page_in_buffer * 4) @@ -4797,8 +4297,9 @@ xtrabackup_apply_delta( ut_a(last_buffer || page_in_buffer == page_size / 4); /* read whole of the cluster */ - success = os_file_read(src_file, incremental_buffer, - offset, page_in_buffer * page_size); + success = os_file_read(IORequestRead, src_file, + incremental_buffer, + offset, page_in_buffer * page_size); if (!success) { goto error; } @@ -4815,7 +4316,8 @@ xtrabackup_apply_delta( if (offset_on_page == 0xFFFFFFFFUL) break; - success = os_file_write(dst_path, dst_file, + success = os_file_write(IORequestWrite, + dst_path, dst_file, incremental_buffer + page_in_buffer * page_size, (offset_on_page << @@ -4829,20 +4331,18 @@ xtrabackup_apply_delta( incremental_buffers++; } - if (incremental_buffer_base) - ut_free(incremental_buffer_base); - if (src_file != XB_FILE_UNDEFINED) + free(incremental_buffer_base); + if (src_file != OS_FILE_CLOSED) os_file_close(src_file); - if (dst_file != XB_FILE_UNDEFINED) + if (dst_file != OS_FILE_CLOSED) os_file_close(dst_file); return TRUE; error: - if (incremental_buffer_base) - ut_free(incremental_buffer_base); - if (src_file != XB_FILE_UNDEFINED) + free(incremental_buffer_base); + if (src_file != OS_FILE_CLOSED) os_file_close(src_file); - if (dst_file != XB_FILE_UNDEFINED) + if (dst_file != OS_FILE_CLOSED) os_file_close(dst_file); msg("xtrabackup: Error: xtrabackup_apply_delta(): " "failed to apply %s to %s.\n", src_path, dst_path); @@ -4903,9 +4403,7 @@ xb_process_datadir( const char* path, /*!<in: datadir path */ const char* suffix, /*!<in: suffix to match against */ - handle_datadir_entry_func_t func, /*!<in: callback */ - void* data) /*!<in: additional argument for - callback */ + handle_datadir_entry_func_t func) /*!<in: callback */ { ulint ret; char dbpath[FN_REFLEN]; @@ -4940,7 +4438,7 @@ xb_process_datadir( suffix)) { if (!func( path, NULL, - fileinfo.name, data)) + fileinfo.name, NULL)) { return(FALSE); } @@ -4976,7 +4474,7 @@ next_file_item_1: sprintf(dbpath, "%s/%s", path, dbinfo.name); - srv_normalize_path_for_win(dbpath); + os_normalize_path(dbpath); dbdir = os_file_opendir(dbpath, FALSE); @@ -5001,7 +4499,7 @@ next_file_item_1: if (!func( path, dbinfo.name, - fileinfo.name, data)) + fileinfo.name, NULL)) { return(FALSE); } @@ -5033,82 +4531,9 @@ ibool xtrabackup_apply_deltas() { return xb_process_datadir(xtrabackup_incremental_dir, ".delta", - xtrabackup_apply_delta, NULL); -} - -static my_bool -xtrabackup_close_temp_log(my_bool clear_flag) -{ - pfs_os_file_t src_file; - char src_path[FN_REFLEN]; - char dst_path[FN_REFLEN]; - ibool success; - byte log_buf[UNIV_PAGE_SIZE_MAX]; - - if (!xtrabackup_logfile_is_renamed) - return(FALSE); - - /* rename 'ib_logfile0' to 'xtrabackup_logfile' */ - if(!xtrabackup_incremental_dir) { - sprintf(dst_path, "%s/ib_logfile0", xtrabackup_target_dir); - sprintf(src_path, "%s/%s", xtrabackup_target_dir, - XB_LOG_FILENAME); - } else { - sprintf(dst_path, "%s/ib_logfile0", xtrabackup_incremental_dir); - sprintf(src_path, "%s/%s", xtrabackup_incremental_dir, - XB_LOG_FILENAME); - } - - srv_normalize_path_for_win(dst_path); - srv_normalize_path_for_win(src_path); - - success = os_file_rename(0, dst_path, src_path); - if (!success) { - goto error; - } - xtrabackup_logfile_is_renamed = FALSE; - - if (!clear_flag) - return(FALSE); - - /* clear LOG_FILE_WAS_CREATED_BY_HOT_BACKUP field */ - src_file = os_file_create_simple_no_error_handling(0, src_path, - OS_FILE_OPEN, - OS_FILE_READ_WRITE, - &success,0); - if (!success) { - goto error; - } - - success = os_file_read(src_file, log_buf, 0, LOG_FILE_HDR_SIZE); - if (!success) { - goto error; - } - - memset(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, ' ', 4); - - success = os_file_write(src_path, src_file, log_buf, 0, - LOG_FILE_HDR_SIZE); - if (!success) { - goto error; - } - - os_file_close(src_file); - src_file = XB_FILE_UNDEFINED; - - innobase_log_files_in_group = innobase_log_files_in_group_save; - srv_log_group_home_dir = srv_log_group_home_dir_save; - innobase_log_file_size = innobase_log_file_size_save; - - return(FALSE); -error: - if (src_file != XB_FILE_UNDEFINED) - os_file_close(src_file); - msg("xtrabackup: Error: xtrabackup_close_temp_log() failed.\n"); - return(TRUE); /*ERROR*/ + xtrabackup_apply_delta); } - /*********************************************************************//** Write the meta data (index user fields) config file. @return true in case of success otherwise false. */ @@ -5359,14 +4784,15 @@ xb_export_cfg_write_header( } /* The table name includes the NUL byte. */ - ut_a(table->name != 0); - len = (ib_uint32_t)strlen(table->name) + 1; + const char* table_name = table->name.m_name; + ut_a(table_name != 0); + len = (ib_uint32_t)strlen(table_name) + 1; /* Write the table name. */ mach_write_to_4(value, len); if (fwrite(&value, 1, sizeof(value), file) != sizeof(value) - || fwrite(table->name, 1, len, file) != len) { + || fwrite(table_name, 1, len, file) != len) { msg("xtrabackup: Error: writing table name."); @@ -5456,48 +4882,38 @@ static void innodb_free_param() { - srv_free_paths_and_sizes(); - free(internal_innobase_data_file_path); - internal_innobase_data_file_path = NULL; + srv_sys_space.shutdown(); free_tmpdir(&mysql_tmpdir_list); } -/************************************************************************** -Store the current binary log coordinates in a specified file. -@return 'false' on error. */ +/** Store the current binary log coordinates in a specified file. +@param[in] filename file name +@param[in] name binary log file name +@param[in] pos binary log file position +@return whether the operation succeeded */ static bool -store_binlog_info( -/*==============*/ - const char *filename) /*!< in: output file name */ +store_binlog_info(const char* filename, const char* name, ulonglong pos) { - FILE *fp; - - if (trx_sys_mysql_bin_log_name[0] == '\0') { - return(true); - } - - fp = fopen(filename, "w"); + FILE *fp = fopen(filename, "w"); if (!fp) { msg("xtrabackup: failed to open '%s'\n", filename); return(false); } - fprintf(fp, "%s\t" UINT64PF "\n", - trx_sys_mysql_bin_log_name, trx_sys_mysql_bin_log_pos); + fprintf(fp, "%s\t%llu\n", name, pos); fclose(fp); return(true); } -static void -xtrabackup_prepare_func(int argc, char ** argv) +/** Implement --prepare +@return whether the operation succeeded */ +static bool +xtrabackup_prepare_func(char** argv) { - ulint err; datafiles_iter_t *it; - fil_node_t *node; - fil_space_t *space; char metadata_path[FN_REFLEN]; /* cd to target-dir */ @@ -5506,10 +4922,11 @@ xtrabackup_prepare_func(int argc, char ** argv) { msg("xtrabackup: cannot my_setwd %s\n", xtrabackup_real_target_dir); - exit(EXIT_FAILURE); + return(false); } msg("xtrabackup: cd to %s\n", xtrabackup_real_target_dir); + int argc; for (argc = 0; argv[argc]; argc++) {} encryption_plugin_prepare_init(argc, argv); xtrabackup_target_dir= mysql_data_home_buff; @@ -5525,116 +4942,100 @@ xtrabackup_prepare_func(int argc, char ** argv) if (!xtrabackup_read_metadata(metadata_path)) { msg("xtrabackup: Error: failed to read metadata from '%s'\n", metadata_path); - exit(EXIT_FAILURE); + return(false); } if (!strcmp(metadata_type, "full-backuped")) { + if (xtrabackup_incremental) { + msg("xtrabackup: error: applying incremental backup " + "needs a prepared target.\n"); + return(false); + } msg("xtrabackup: This target seems to be not prepared yet.\n"); } else if (!strcmp(metadata_type, "log-applied")) { - msg("xtrabackup: This target seems to be already " - "prepared with --apply-log-only.\n"); - goto skip_check; - } else if (!strcmp(metadata_type, "full-prepared")) { msg("xtrabackup: This target seems to be already prepared.\n"); } else { - msg("xtrabackup: This target seems not to have correct " - "metadata...\n"); - exit(EXIT_FAILURE); + msg("xtrabackup: This target does not have correct metadata.\n"); + return(false); } - if (xtrabackup_incremental) { - msg("xtrabackup: error: applying incremental backup " - "needs target prepared with --apply-log-only.\n"); - exit(EXIT_FAILURE); - } -skip_check: - if (xtrabackup_incremental - && metadata_to_lsn != incremental_lsn) { + bool ok = !xtrabackup_incremental + || metadata_to_lsn == incremental_lsn; + if (!ok) { msg("xtrabackup: error: This incremental backup seems " "not to be proper for the target.\n" "xtrabackup: Check 'to_lsn' of the target and " "'from_lsn' of the incremental.\n"); - exit(EXIT_FAILURE); + return(false); } - /* Create logfiles for recovery from 'xtrabackup_logfile', before start InnoDB */ srv_max_n_threads = 1000; + srv_undo_logs = 1; srv_n_purge_threads = 1; - ut_mem_init(); - /* temporally dummy value to avoid crash */ - srv_page_size_shift = 14; - srv_page_size = (1 << srv_page_size_shift); - os_sync_init(); - sync_init(); - os_io_init_simple(); - mem_init(srv_mem_pool_size); - ut_crc32_init(); - -#ifdef WITH_INNODB_DISALLOW_WRITES - srv_allow_writes_event = os_event_create(); - os_event_set(srv_allow_writes_event); -#endif xb_filters_init(); - if (xtrabackup_init_temp_log()) - goto error_cleanup; + srv_log_group_home_dir = NULL; + srv_thread_concurrency = 1; - if(innodb_init_param()) { - goto error_cleanup; - } + if (xtrabackup_incremental) { + if (innodb_init_param()) { +error_cleanup: + xb_filters_free(); + return(false); + } - xb_normalize_init_values(); + xb_normalize_init_values(); + sync_check_init(); + ut_d(sync_check_enable()); + ut_crc32_init(); + recv_sys_init(); + log_sys_init(); + recv_recovery_on = true; - if (xtrabackup_incremental) { - err = xb_data_files_init(); +#ifdef WITH_INNODB_DISALLOW_WRITES + srv_allow_writes_event = os_event_create(0); + os_event_set(srv_allow_writes_event); +#endif + + dberr_t err = xb_data_files_init(); if (err != DB_SUCCESS) { msg("xtrabackup: error: xb_data_files_init() failed " - "with error code %lu\n", err); + "with error %s\n", ut_strerr(err)); goto error_cleanup; } - } - if (xtrabackup_incremental) { + inc_dir_tables_hash = hash_create(1000); - if(!xtrabackup_apply_deltas()) { - xb_data_files_close(); - xb_filter_hash_free(inc_dir_tables_hash); - goto error_cleanup; - } - } - if (xtrabackup_incremental) { + ok = xtrabackup_apply_deltas(); + xb_data_files_close(); - } - if (xtrabackup_incremental) { - /* Cleanup datadir from tablespaces deleted between full and - incremental backups */ - xb_process_datadir("./", ".ibd", rm_if_not_found, NULL); + if (ok) { + /* Cleanup datadir from tablespaces deleted + between full and incremental backups */ + + xb_process_datadir("./", ".ibd", rm_if_not_found); + } xb_filter_hash_free(inc_dir_tables_hash); - } - if (fil_system) { + fil_close(); +#ifdef WITH_INNODB_DISALLOW_WRITES + os_event_destroy(srv_allow_writes_event); +#endif + innodb_free_param(); + log_shutdown(); + sync_check_close(); + if (!ok) goto error_cleanup; } - mem_close(); - ut_free_all_mem(); - - innodb_free_param(); - sync_close(); - sync_initialized = FALSE; - - /* Reset the configuration as it might have been changed by - xb_data_files_init(). */ - if(innodb_init_param()) { + if (innodb_init_param()) { goto error_cleanup; } - srv_apply_log_only = (bool) xtrabackup_apply_log_only; - /* increase IO threads */ - if(srv_n_file_io_threads < 10) { + if (srv_n_file_io_threads < 10) { srv_n_read_io_threads = 4; srv_n_write_io_threads = 4; } @@ -5649,85 +5050,51 @@ skip_check: srv_max_dirty_pages_pct_lwm = srv_max_buf_pool_modified_pct; } - if(innodb_init()) + if (innodb_init()) { goto error_cleanup; - - if (xtrabackup_incremental) { - - it = datafiles_iter_new(fil_system); - if (it == NULL) { - msg("xtrabackup: Error: datafiles_iter_new() failed.\n"); - exit(EXIT_FAILURE); - } - - while ((node = datafiles_iter_next(it)) != NULL) { - byte *header; - ulint size; - ulint actual_size; - mtr_t mtr; - buf_block_t *block; - ulint flags; - - space = node->space; - - /* Align space sizes along with fsp header. We want to process - each space once, so skip all nodes except the first one in a - multi-node space. */ - if (UT_LIST_GET_PREV(chain, node) != NULL) { - continue; - } - - mtr_start(&mtr); - - mtr_s_lock(fil_space_get_latch(space->id, &flags), &mtr); - - block = buf_page_get(space->id, - dict_tf_get_zip_size(flags), - 0, RW_S_LATCH, &mtr); - header = FSP_HEADER_OFFSET + buf_block_get_frame(block); - - size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, - &mtr); - - mtr_commit(&mtr); - - fil_extend_space_to_desired_size(&actual_size, space->id, size); } - datafiles_iter_free(it); - - } /* if (xtrabackup_incremental) */ - if (xtrabackup_export) { +#if 1 // FIXME: remove the option or fix the logic + /* In MariaDB 10.2, undo log processing would need the + ability to evaluate indexed virtual columns, and we + have not initialized the necessary infrastructure. */ + msg("xtrabackup: --export does not work!\n"); + ok = false; + } else if (xtrabackup_export) { +#endif msg("xtrabackup: export option is specified.\n"); + + /* To allow subsequent MariaDB server startup independent + of the value of --innodb-log-checksums, + unconditionally enable redo log checksums. */ + log_checksum_algorithm_ptr = log_block_calc_checksum_crc32; + pfs_os_file_t info_file; char info_file_path[FN_REFLEN]; - ibool success; + bool success; char table_name[FN_REFLEN]; byte* page; byte* buf = NULL; - buf = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE * 2)); + buf = static_cast<byte *>(malloc(UNIV_PAGE_SIZE * 2)); page = static_cast<byte *>(ut_align(buf, UNIV_PAGE_SIZE)); - /* flush insert buffer at shutdwon */ - innobase_fast_shutdown = 0; - it = datafiles_iter_new(fil_system); if (it == NULL) { msg("xtrabackup: Error: datafiles_iter_new() " "failed.\n"); - exit(EXIT_FAILURE); - } - while ((node = datafiles_iter_next(it)) != NULL) { + ok = false; + } else + while (fil_node_t *node = datafiles_iter_next(it)) { int len; char *next, *prev, *p; dict_table_t* table; dict_index_t* index; ulint n_index; - space = node->space; + const fil_space_t* space = node->space; /* treat file_per_table only */ if (!fil_is_user_tablespace_id(space->id)) { @@ -5782,15 +5149,14 @@ skip_check: "than 31 indexes, .exp file was not " "generated. Table will fail to import " "on server version prior to 5.6.\n", - table->name); + table->name.m_name); goto next_node; } /* init exp file */ - memset(page, 0, UNIV_PAGE_SIZE); - mach_write_to_4(page , 0x78706f72UL); - mach_write_to_4(page + 4, 0x74696e66UL);/*"xportinf"*/ + memcpy(page, "xportinf", 8); mach_write_to_4(page + 8, n_index); + memset(page + 12, 0, UNIV_PAGE_SIZE - 12); strncpy((char *) page + 12, table_name, 500); @@ -5810,7 +5176,7 @@ skip_check: msg("xtrabackup: name=%s, " "id.low=%lu, page=%lu\n", - index->name, + index->name(), (ulint)(index->id & 0xFFFFFFFFUL), (ulint) index->page); @@ -5818,18 +5184,18 @@ skip_check: n_index++; } - srv_normalize_path_for_win(info_file_path); + os_normalize_path(info_file_path); info_file = os_file_create( 0, info_file_path, OS_FILE_OVERWRITE, OS_FILE_NORMAL, OS_DATA_FILE, - &success,0); + false, &success); if (!success) { os_file_get_last_error(TRUE); goto next_node; } - success = os_file_write(info_file_path, + success = os_file_write(IORequestWrite, info_file_path, info_file, page, 0, UNIV_PAGE_SIZE); if (!success) { @@ -5842,76 +5208,73 @@ skip_check: goto next_node; } next_node: - if (info_file != XB_FILE_UNDEFINED) { + if (info_file != OS_FILE_CLOSED) { os_file_close(info_file); - info_file = XB_FILE_UNDEFINED; + info_file = OS_FILE_CLOSED; } mutex_exit(&(dict_sys->mutex)); } - ut_free(buf); + free(buf); } - /* print the binary log position */ - trx_sys_print_mysql_binlog_offset(); - msg("\n"); - - /* output to xtrabackup_binlog_pos_innodb and (if - backup_safe_binlog_info was available on the server) to - xtrabackup_binlog_info. In the latter case xtrabackup_binlog_pos_innodb - becomes redundant and is created only for compatibility. */ - if (!store_binlog_info("xtrabackup_binlog_pos_innodb") || - (recover_binlog_info && - !store_binlog_info(XTRABACKUP_BINLOG_INFO))) { + if (ok) { + mtr_t mtr; + mtr.start(); + const trx_sysf_t* sys_header = trx_sysf_get(&mtr); + + if (mach_read_from_4(TRX_SYS_MYSQL_LOG_INFO + + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD + + sys_header) + == TRX_SYS_MYSQL_LOG_MAGIC_N) { + ulonglong pos = mach_read_from_8( + TRX_SYS_MYSQL_LOG_INFO + + TRX_SYS_MYSQL_LOG_OFFSET + + sys_header); + const char* name = reinterpret_cast<const char*>( + TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_NAME + + sys_header); + msg("Last binlog file %s, position %llu\n", name, pos); + + /* output to xtrabackup_binlog_pos_innodb and + (if backup_safe_binlog_info was available on + the server) to xtrabackup_binlog_info. In the + latter case xtrabackup_binlog_pos_innodb + becomes redundant and is created only for + compatibility. */ + ok = store_binlog_info( + "xtrabackup_binlog_pos_innodb", name, pos) + && (!recover_binlog_info || store_binlog_info( + XTRABACKUP_BINLOG_INFO, + name, pos)); + } - exit(EXIT_FAILURE); + mtr.commit(); } /* Check whether the log is applied enough or not. */ - if ((xtrabackup_incremental - && srv_start_lsn < incremental_to_lsn) - ||(!xtrabackup_incremental - && srv_start_lsn < metadata_to_lsn)) { + const lsn_t target_lsn = xtrabackup_incremental + ? incremental_to_lsn : metadata_to_lsn; + if ((srv_start_lsn || fil_space_get(SRV_LOG_SPACE_FIRST_ID)) + && srv_start_lsn < target_lsn) { msg("xtrabackup: error: " - "The transaction log file is corrupted.\n" - "xtrabackup: error: " - "The log was not applied to the intended LSN!\n"); - msg("xtrabackup: Log applied to lsn " LSN_PF "\n", - srv_start_lsn); - if (xtrabackup_incremental) { - msg("xtrabackup: The intended lsn is " LSN_PF "\n", - incremental_to_lsn); - } else { - msg("xtrabackup: The intended lsn is " LSN_PF "\n", - metadata_to_lsn); - } - exit(EXIT_FAILURE); + "The log was only applied up to LSN " LSN_PF + ", instead of " LSN_PF "\n", + srv_start_lsn, target_lsn); + ok = false; } #ifdef WITH_WSREP - xb_write_galera_info(xtrabackup_incremental); + else if (ok) xb_write_galera_info(xtrabackup_incremental); #endif - innodb_end(); - - innodb_free_param(); - - sync_initialized = FALSE; - - /* re-init necessary components */ - ut_mem_init(); - os_sync_init(); - sync_init(); - os_io_init_simple(); - - if(xtrabackup_close_temp_log(TRUE)) - exit(EXIT_FAILURE); + innodb_shutdown(); + innodb_free_param(); /* output to metadata file */ - { + if (ok) { char filename[FN_REFLEN]; - strcpy(metadata_type, srv_apply_log_only ? - "log-applied" : "full-prepared"); + strcpy(metadata_type, "log-applied"); if(xtrabackup_incremental && metadata_to_lsn < incremental_to_lsn) @@ -5925,73 +5288,21 @@ next_node: msg("xtrabackup: Error: failed to write metadata " "to '%s'\n", filename); - exit(EXIT_FAILURE); - } - - if(xtrabackup_extra_lsndir) { + ok = false; + } else if (xtrabackup_extra_lsndir) { sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME); if (!xtrabackup_write_metadata(filename)) { msg("xtrabackup: Error: failed to write " "metadata to '%s'\n", filename); - exit(EXIT_FAILURE); + ok = false; } } } - if (!apply_log_finish()) { - exit(EXIT_FAILURE); - } - - sync_close(); - sync_initialized = FALSE; - if (fil_system) { - fil_close(); - } - - ut_free_all_mem(); - - /* start InnoDB once again to create log files */ - - if (!xtrabackup_apply_log_only) { - - /* xtrabackup_incremental_dir is used to indicate that - we are going to apply incremental backup. Here we already - applied incremental backup and are about to do final prepare - of the full backup */ - xtrabackup_incremental_dir = NULL; - - if(innodb_init_param()) { - goto error; - } - - srv_apply_log_only = false; - - /* increase IO threads */ - if(srv_n_file_io_threads < 10) { - srv_n_read_io_threads = 4; - srv_n_write_io_threads = 4; - } - - srv_shutdown_state = SRV_SHUTDOWN_NONE; - - if(innodb_init()) - goto error; - - innodb_end(); - innodb_free_param(); - - } - - xb_filters_free(); - - return; + if (ok) ok = apply_log_finish(); -error_cleanup: - xtrabackup_close_temp_log(FALSE); xb_filters_free(); - -error: - exit(EXIT_FAILURE); + return ok; } /************************************************************************** @@ -6084,7 +5395,8 @@ extern void init_signals(void); /* Messages . Avoid loading errmsg.sys file */ void setup_error_messages() { - static const char *all_msgs[ER_ERROR_LAST - ER_ERROR_FIRST +1]; + static const char *my_msgs[ERRORS_PER_RANGE]; + static const char **all_msgs[] = { my_msgs, my_msgs, my_msgs, my_msgs }; my_default_lc_messages = &my_locale_en_US; my_default_lc_messages->errmsgs->errmsgs = all_msgs; @@ -6111,24 +5423,20 @@ void setup_error_messages() }; for (int i = 0; i < (int)array_elements(all_msgs); i++) - all_msgs[i] = "Unknown error"; + all_msgs[0][i] = "Unknown error"; for (int i = 0; i < (int)array_elements(xb_msgs); i++) - all_msgs[xb_msgs[i].id - ER_ERROR_FIRST] = xb_msgs[i].fmt; + all_msgs[0][xb_msgs[i].id - ER_ERROR_FIRST] = xb_msgs[i].fmt; } -extern my_bool(*dict_check_if_skip_table)(const char* name) ; - void handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) { /* Setup some variables for Innodb.*/ - srv_xtrabackup = true; - + srv_operation = SRV_OPERATION_RESTORE; files_charset_info = &my_charset_utf8_general_ci; - dict_check_if_skip_table = check_if_skip_table; setup_error_messages(); sys_var_init(); @@ -6312,25 +5620,21 @@ handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) } } -/* ================= main =================== */ -extern my_bool(*fil_check_if_skip_database_by_path)(const char* name); +static int main_low(char** argv); +/* ================= main =================== */ int main(int argc, char **argv) { char **client_defaults, **server_defaults; - char cwd[FN_REFLEN]; - static char INNOBACKUPEX_EXE[]= "innobackupex"; + static char INNOBACKUPEX_EXE[]= "innobackupex"; if (argc > 1 && (strcmp(argv[1], "--innobackupex") == 0)) { argv++; argc--; - argv[0] = INNOBACKUPEX_EXE; + argv[0] = INNOBACKUPEX_EXE; innobackupex_mode = true; } - /* Setup skip fil_load_single_tablespaces callback.*/ - fil_check_if_skip_database_by_path = check_if_skip_database_by_path; - init_signals(); MY_INIT(argv[0]); @@ -6349,30 +5653,69 @@ int main(int argc, char **argv) system_charset_info = &my_charset_utf8_general_ci; key_map_full.set_all(); + logger.init_base(); + logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE); + mysql_mutex_init(key_LOCK_error_log, &LOCK_error_log, + MY_MUTEX_INIT_FAST); + handle_options(argc, argv, &client_defaults, &server_defaults); - int argc_server; - for (argc_server = 0; server_defaults[argc_server]; argc_server++) {} +#ifndef DBUG_OFF + if (dbug_option) { + DBUG_SET_INITIAL(dbug_option); + DBUG_SET(dbug_option); + } +#endif - int argc_client; - for (argc_client = 0; client_defaults[argc_client]; argc_client++) {} + int status = main_low(server_defaults); + backup_cleanup(); if (innobackupex_mode) { + ibx_cleanup(); + } + + free_defaults(client_defaults); + free_defaults(server_defaults); + +#ifndef DBUG_OFF + if (dbug_option) { + DBUG_END(); + } +#endif + + if (THR_THD) + (void) pthread_key_delete(THR_THD); + + logger.cleanup_base(); + mysql_mutex_destroy(&LOCK_error_log); + + if (status == EXIT_SUCCESS) { + msg_ts("completed OK!\n"); + } + + return status; +} + +static int main_low(char** argv) +{ + if (innobackupex_mode) { if (!ibx_init()) { - exit(EXIT_FAILURE); + return(EXIT_FAILURE); } } - if ((!xtrabackup_print_param) && (!xtrabackup_prepare) && (strcmp(mysql_data_home, "./") == 0)) { + if (!xtrabackup_print_param && !xtrabackup_prepare + && !strcmp(mysql_data_home, "./")) { if (!xtrabackup_print_param) usage(); msg("\nxtrabackup: Error: Please set parameter 'datadir'\n"); - exit(EXIT_FAILURE); + return(EXIT_FAILURE); } /* Expand target-dir, incremental-basedir, etc. */ + char cwd[FN_REFLEN]; my_getwd(cwd, sizeof(cwd), MYF(0)); my_load_path(xtrabackup_real_target_dir, @@ -6438,7 +5781,7 @@ int main(int argc, char **argv) if (error) { msg("xtrabackup: value '%s' may be wrong format for " "incremental option.\n", xtrabackup_incremental); - exit(EXIT_FAILURE); + return(EXIT_FAILURE); } } else if (xtrabackup_backup && xtrabackup_incremental_basedir) { char filename[FN_REFLEN]; @@ -6448,7 +5791,7 @@ int main(int argc, char **argv) if (!xtrabackup_read_metadata(filename)) { msg("xtrabackup: error: failed to read metadata from " "%s\n", filename); - exit(EXIT_FAILURE); + return(EXIT_FAILURE); } incremental_lsn = metadata_to_lsn; @@ -6461,7 +5804,7 @@ int main(int argc, char **argv) if (!xtrabackup_read_metadata(filename)) { msg("xtrabackup: error: failed to read metadata from " "%s\n", filename); - exit(EXIT_FAILURE); + return(EXIT_FAILURE); } incremental_lsn = metadata_from_lsn; @@ -6478,15 +5821,13 @@ int main(int argc, char **argv) } if (!xb_init()) { - exit(EXIT_FAILURE); + return(EXIT_FAILURE); } /* --print-param */ if (xtrabackup_print_param) { - printf("%s", print_param_str.str().c_str()); - - exit(EXIT_SUCCESS); + return(EXIT_SUCCESS); } print_version(); @@ -6512,7 +5853,7 @@ int main(int argc, char **argv) if (xtrabackup_decrypt_decompress) num++; if (num != 1) { /* !XOR (for now) */ usage(); - exit(EXIT_FAILURE); + return(EXIT_FAILURE); } } @@ -6523,41 +5864,28 @@ int main(int argc, char **argv) #endif /* --backup */ - if (xtrabackup_backup) - xtrabackup_backup_func(); + if (xtrabackup_backup && !xtrabackup_backup_func()) { + return(EXIT_FAILURE); + } /* --prepare */ - if (xtrabackup_prepare) { - xtrabackup_prepare_func(argc_server, server_defaults); + if (xtrabackup_prepare + && !xtrabackup_prepare_func(argv)) { + return(EXIT_FAILURE); } if (xtrabackup_copy_back || xtrabackup_move_back) { if (!check_if_param_set("datadir")) { msg("Error: datadir must be specified.\n"); - exit(EXIT_FAILURE); + return(EXIT_FAILURE); } if (!copy_back()) - exit(EXIT_FAILURE); + return(EXIT_FAILURE); } if (xtrabackup_decrypt_decompress && !decrypt_decompress()) { - exit(EXIT_FAILURE); - } - - backup_cleanup(); - - if (innobackupex_mode) { - ibx_cleanup(); + return(EXIT_FAILURE); } - - free_defaults(client_defaults); - free_defaults(server_defaults); - - if (THR_THD) - (void) pthread_key_delete(THR_THD); - - msg_ts("completed OK!\n"); - - exit(EXIT_SUCCESS); + return(EXIT_SUCCESS); } diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h index eafc848fd43..b883194ef86 100644 --- a/extra/mariabackup/xtrabackup.h +++ b/extra/mariabackup/xtrabackup.h @@ -26,26 +26,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #include "xbstream.h" #include "changed_page_bitmap.h" -#ifdef __WIN__ -#define XB_FILE_UNDEFINED INVALID_HANDLE_VALUE -#else -#define XB_FILE_UNDEFINED (-1) -#endif +struct xb_delta_info_t +{ + xb_delta_info_t(page_size_t page_size, ulint space_id) + : page_size(page_size), space_id(space_id) {} -typedef struct { - ulint page_size; - ulint zip_size; - ulint space_id; -} xb_delta_info_t; - -/* ======== Datafiles iterator ======== */ -typedef struct { - fil_system_t *system; - fil_space_t *space; - fil_node_t *node; - ibool started; - os_ib_mutex_t mutex; -} datafiles_iter_t; + page_size_t page_size; + ulint space_id; +}; /* value of the --incremental option */ extern lsn_t incremental_lsn; @@ -84,15 +72,11 @@ extern ibool xtrabackup_compress; extern my_bool xtrabackup_backup; extern my_bool xtrabackup_prepare; -extern my_bool xtrabackup_apply_log_only; extern my_bool xtrabackup_copy_back; extern my_bool xtrabackup_move_back; extern my_bool xtrabackup_decrypt_decompress; extern char *innobase_data_file_path; -extern char *innobase_doublewrite_file; -extern longlong innobase_log_file_size; -extern long innobase_log_files_in_group; extern longlong innobase_page_size; extern int xtrabackup_parallel; @@ -108,9 +92,7 @@ extern "C"{ } #endif extern my_bool xtrabackup_export; -extern char *xtrabackup_incremental_basedir; extern char *xtrabackup_extra_lsndir; -extern char *xtrabackup_incremental_dir; extern ulint xtrabackup_log_copy_interval; extern char *xtrabackup_stream_str; extern long xtrabackup_throttle; @@ -166,14 +148,9 @@ void xtrabackup_io_throttling(void); my_bool xb_write_delta_metadata(const char *filename, const xb_delta_info_t *info); -datafiles_iter_t *datafiles_iter_new(fil_system_t *f_system); -fil_node_t *datafiles_iter_next(datafiles_iter_t *it); -void datafiles_iter_free(datafiles_iter_t *it); - -/*********************************************************************** -Reads the space flags from a given data file and returns the compressed -page size, or 0 if the space is not compressed. */ -ulint xb_get_zip_size(pfs_os_file_t file); +/** @return the tablespace flags from a given data file +@retval ULINT_UNDEFINED if the file is not readable */ +ulint xb_get_space_flags(pfs_os_file_t file); /************************************************************************ Checks if a table specified as a name in the form "database/name" (InnoDB 5.6) @@ -204,17 +181,10 @@ bool check_if_param_set(const char *param); #if defined(HAVE_OPENSSL) -extern my_bool opt_use_ssl; extern my_bool opt_ssl_verify_server_cert; -#if !defined(HAVE_YASSL) -extern char *opt_server_public_key; -#endif #endif -void -xtrabackup_backup_func(void); - my_bool xb_get_one_option(int optid, const struct my_option *opt __attribute__((unused)), |