1 /****************************************************** 2 MariaBackup: hot backup tool for InnoDB 3 (c) 2009-2017 Percona LLC and/or its affiliates 4 Originally Created 3/3/2009 Yasufumi Kinoshita 5 Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko, 6 Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz. 7 (c) 2017, 2021, MariaDB Corporation. 8 Portions written by Marko Mäkelä. 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; version 2 of the License. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 22 23 ******************************************************* 24 25 This file incorporates work covered by the following copyright and 26 permission notice: 27 28 Copyright (c) 2000, 2011, MySQL AB & Innobase Oy. All Rights Reserved. 29 30 This program is free software; you can redistribute it and/or modify it under 31 the terms of the GNU General Public License as published by the Free Software 32 Foundation; version 2 of the License. 33 34 This program is distributed in the hope that it will be useful, but WITHOUT 35 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 36 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 37 38 You should have received a copy of the GNU General Public License along with 39 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin 40 Street, Fifth Floor, Boston, MA 02110-1335 USA 41 42 *******************************************************/ 43 44 //#define XTRABACKUP_TARGET_IS_PLUGIN 45 46 #include <my_global.h> 47 #include <my_config.h> 48 #include <unireg.h> 49 #include <mysql_version.h> 50 #include <my_base.h> 51 #include <my_getopt.h> 52 #include <mysql_com.h> 53 #include <my_default.h> 54 #include <sql_class.h> 55 56 #include <fcntl.h> 57 #include <string.h> 58 59 #ifdef __linux__ 60 # include <sys/prctl.h> 61 #include <sys/resource.h> 62 #endif 63 64 #ifdef __APPLE__ 65 # include "libproc.h" 66 #endif 67 68 69 #include <btr0sea.h> 70 #include <dict0priv.h> 71 #include <lock0lock.h> 72 #include <log0recv.h> 73 #include <log0crypt.h> 74 #include <row0mysql.h> 75 #include <row0quiesce.h> 76 #include <srv0start.h> 77 #include "trx0sys.h" 78 #include <buf0dblwr.h> 79 #include "ha_innodb.h" 80 81 #include <list> 82 #include <sstream> 83 #include <set> 84 #include <fstream> 85 #include <mysql.h> 86 87 #define G_PTR uchar* 88 89 #include "common.h" 90 #include "datasink.h" 91 92 #include "xb_regex.h" 93 #include "fil_cur.h" 94 #include "write_filt.h" 95 #include "xtrabackup.h" 96 #include "ds_buffer.h" 97 #include "ds_tmpfile.h" 98 #include "xbstream.h" 99 #include "changed_page_bitmap.h" 100 #include "read_filt.h" 101 #include "backup_wsrep.h" 102 #include "innobackupex.h" 103 #include "backup_mysql.h" 104 #include "backup_copy.h" 105 #include "backup_mysql.h" 106 #include "encryption_plugin.h" 107 #include <sql_plugin.h> 108 #include <srv0srv.h> 109 #include <crc_glue.h> 110 #include <log.h> 111 #include <derror.h> 112 #include "backup_debug.h" 113 114 #define MB_CORRUPTED_PAGES_FILE "innodb_corrupted_pages" 115 116 int sys_var_init(); 117 118 /* === xtrabackup specific options === */ 119 char xtrabackup_real_target_dir[FN_REFLEN] = "./xtrabackup_backupfiles/"; 120 char *xtrabackup_target_dir= xtrabackup_real_target_dir; 121 static my_bool xtrabackup_version; 122 static my_bool verbose; 123 my_bool xtrabackup_backup; 124 my_bool xtrabackup_prepare; 125 my_bool xtrabackup_copy_back; 126 my_bool xtrabackup_move_back; 127 my_bool xtrabackup_decrypt_decompress; 128 my_bool xtrabackup_print_param; 129 my_bool xtrabackup_mysqld_args; 130 my_bool xtrabackup_help; 131 132 my_bool xtrabackup_export; 133 134 my_bool xtrabackup_rollback_xa; 135 136 longlong xtrabackup_use_memory; 137 138 uint opt_protocol; 139 long xtrabackup_throttle; /* 0:unlimited */ 140 static lint io_ticket; 141 static os_event_t wait_throttle; 142 static os_event_t log_copying_stop; 143 144 char *xtrabackup_incremental; 145 lsn_t incremental_lsn; 146 lsn_t incremental_to_lsn; 147 lsn_t incremental_last_lsn; 148 xb_page_bitmap *changed_page_bitmap; 149 150 char *xtrabackup_incremental_basedir; /* for --backup */ 151 char *xtrabackup_extra_lsndir; /* for --backup with --extra-lsndir */ 152 char *xtrabackup_incremental_dir; /* for --prepare */ 153 154 char xtrabackup_real_incremental_basedir[FN_REFLEN]; 155 char xtrabackup_real_extra_lsndir[FN_REFLEN]; 156 char xtrabackup_real_incremental_dir[FN_REFLEN]; 157 158 159 char *xtrabackup_tmpdir; 160 161 char *xtrabackup_tables; 162 char *xtrabackup_tables_file; 163 char *xtrabackup_tables_exclude; 164 char *xb_rocksdb_datadir; 165 my_bool xb_backup_rocksdb = 1; 166 167 typedef std::list<regex_t> regex_list_t; 168 static regex_list_t regex_include_list; 169 static regex_list_t regex_exclude_list; 170 171 static hash_table_t* tables_include_hash = NULL; 172 static hash_table_t* tables_exclude_hash = NULL; 173 174 char *xtrabackup_databases = NULL; 175 char *xtrabackup_databases_file = NULL; 176 char *xtrabackup_databases_exclude = NULL; 177 static hash_table_t* databases_include_hash = NULL; 178 static hash_table_t* databases_exclude_hash = NULL; 179 180 static hash_table_t* inc_dir_tables_hash; 181 182 struct xb_filter_entry_struct{ 183 char* name; 184 ibool has_tables; 185 hash_node_t name_hash; 186 }; 187 typedef struct xb_filter_entry_struct xb_filter_entry_t; 188 189 lsn_t checkpoint_lsn_start; 190 lsn_t checkpoint_no_start; 191 static lsn_t log_copy_scanned_lsn; 192 static bool log_copying_running; 193 static bool io_watching_thread_running; 194 195 int xtrabackup_parallel; 196 197 char *xtrabackup_stream_str = NULL; 198 xb_stream_fmt_t xtrabackup_stream_fmt = XB_STREAM_FMT_NONE; 199 ibool xtrabackup_stream = FALSE; 200 201 const char *xtrabackup_compress_alg = NULL; 202 uint xtrabackup_compress = FALSE; 203 uint xtrabackup_compress_threads; 204 ulonglong xtrabackup_compress_chunk_size = 0; 205 206 /* sleep interval beetween log copy iterations in log copying thread 207 in milliseconds (default is 1 second) */ 208 ulint xtrabackup_log_copy_interval = 1000; 209 static ulong max_buf_pool_modified_pct; 210 211 /* Ignored option (--log) for MySQL option compatibility */ 212 static char* log_ignored_opt; 213 214 215 extern my_bool opt_use_ssl; 216 extern char *opt_tls_version; 217 my_bool opt_ssl_verify_server_cert; 218 my_bool opt_extended_validation; 219 my_bool opt_encrypted_backup; 220 221 /* === metadata of backup === */ 222 #define XTRABACKUP_METADATA_FILENAME "xtrabackup_checkpoints" 223 char metadata_type[30] = ""; /*[full-backuped|log-applied|incremental]*/ 224 static lsn_t metadata_from_lsn; 225 lsn_t metadata_to_lsn; 226 static lsn_t metadata_last_lsn; 227 228 static ds_file_t* dst_log_file; 229 230 static char mysql_data_home_buff[2]; 231 232 const char *defaults_group = "mysqld"; 233 234 /* === static parameters in ha_innodb.cc */ 235 236 #define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */ 237 #define HA_INNOBASE_RANGE_COUNT 100 238 239 /* The default values for the following, type long or longlong, start-up 240 parameters are declared in mysqld.cc: */ 241 242 long innobase_buffer_pool_awe_mem_mb = 0; 243 long innobase_file_io_threads = 4; 244 long innobase_read_io_threads = 4; 245 long innobase_write_io_threads = 4; 246 247 longlong innobase_page_size = (1LL << 14); /* 16KB */ 248 char* innobase_buffer_pool_filename = NULL; 249 250 /* The default values for the following char* start-up parameters 251 are determined in innobase_init below: */ 252 253 static char* innobase_ignored_opt; 254 char* innobase_data_home_dir; 255 char* innobase_data_file_path; 256 257 my_bool innobase_use_doublewrite; 258 my_bool innobase_file_per_table; 259 my_bool innobase_locks_unsafe_for_binlog; 260 my_bool innobase_rollback_on_timeout; 261 my_bool innobase_create_status_file; 262 263 /* The following counter is used to convey information to InnoDB 264 about server activity: in selects it is not sensible to call 265 srv_active_wake_master_thread after each fetch or search, we only do 266 it every INNOBASE_WAKE_INTERVAL'th step. */ 267 268 #define INNOBASE_WAKE_INTERVAL 32 269 ulong innobase_active_counter = 0; 270 271 272 my_bool xtrabackup_incremental_force_scan = FALSE; 273 274 /* 275 * Ignore corrupt pages (disabled by default; used 276 * by "innobackupex" as a command line argument). 277 */ 278 ulong xtrabackup_innodb_force_recovery = 0; 279 280 /* The flushed lsn which is read from data files */ 281 lsn_t flushed_lsn= 0; 282 283 ulong xb_open_files_limit= 0; 284 char *xb_plugin_dir; 285 char *xb_plugin_load; 286 my_bool xb_close_files; 287 288 /* Datasinks */ 289 ds_ctxt_t *ds_data = NULL; 290 ds_ctxt_t *ds_meta = NULL; 291 ds_ctxt_t *ds_redo = NULL; 292 293 static bool innobackupex_mode = false; 294 295 /* String buffer used by --print-param to accumulate server options as they are 296 parsed from the defaults file */ 297 static std::ostringstream print_param_str; 298 299 /* Set of specified parameters */ 300 std::set<std::string> param_set; 301 302 static ulonglong global_max_value; 303 304 extern "C" sig_handler handle_fatal_signal(int sig); 305 extern LOGGER logger; 306 307 my_bool opt_galera_info = FALSE; 308 my_bool opt_slave_info = FALSE; 309 my_bool opt_no_lock = FALSE; 310 my_bool opt_safe_slave_backup = FALSE; 311 my_bool opt_rsync = FALSE; 312 my_bool opt_force_non_empty_dirs = FALSE; 313 my_bool opt_noversioncheck = FALSE; 314 my_bool opt_no_backup_locks = FALSE; 315 my_bool opt_decompress = FALSE; 316 my_bool opt_remove_original; 317 my_bool opt_log_innodb_page_corruption; 318 319 my_bool opt_lock_ddl_per_table = FALSE; 320 static my_bool opt_check_privileges; 321 322 extern const char *innodb_checksum_algorithm_names[]; 323 extern TYPELIB innodb_checksum_algorithm_typelib; 324 extern const char *innodb_flush_method_names[]; 325 extern TYPELIB innodb_flush_method_typelib; 326 327 static const char *binlog_info_values[] = {"off", "lockless", "on", "auto", 328 NullS}; 329 static TYPELIB binlog_info_typelib = {array_elements(binlog_info_values)-1, "", 330 binlog_info_values, NULL}; 331 ulong opt_binlog_info; 332 333 char *opt_incremental_history_name; 334 char *opt_incremental_history_uuid; 335 336 char *opt_user; 337 char *opt_password; 338 char *opt_host; 339 char *opt_defaults_group; 340 char *opt_socket; 341 uint opt_port; 342 char *opt_log_bin; 343 344 const char *query_type_names[] = { "ALL", "UPDATE", "SELECT", NullS}; 345 346 TYPELIB query_type_typelib= {array_elements(query_type_names) - 1, "", 347 query_type_names, NULL}; 348 349 ulong opt_lock_wait_query_type; 350 ulong opt_kill_long_query_type; 351 352 uint opt_kill_long_queries_timeout = 0; 353 uint opt_lock_wait_timeout = 0; 354 uint opt_lock_wait_threshold = 0; 355 uint opt_debug_sleep_before_unlock = 0; 356 uint opt_safe_slave_backup_timeout = 0; 357 358 const char *opt_history = NULL; 359 360 361 char mariabackup_exe[FN_REFLEN]; 362 char orig_argv1[FN_REFLEN]; 363 364 pthread_mutex_t backup_mutex; 365 pthread_cond_t scanned_lsn_cond; 366 367 typedef std::map<space_id_t,std::string> space_id_to_name_t; 368 369 struct ddl_tracker_t { 370 /** Tablspaces with their ID and name, as they were copied to backup.*/ 371 space_id_to_name_t tables_in_backup; 372 /** Tablespaces for that optimized DDL without redo log was found.*/ 373 std::set<space_id_t> optimized_ddl; 374 /** Drop operations found in redo log. */ 375 std::set<space_id_t> drops; 376 /* For DDL operation found in redo log, */ 377 space_id_to_name_t id_to_name; 378 }; 379 380 static ddl_tracker_t ddl_tracker; 381 382 // Convert non-null terminated filename to space name 383 std::string filename_to_spacename(const byte *filename, size_t len); 384 385 CorruptedPages::CorruptedPages() { ut_a(!pthread_mutex_init(&m_mutex, NULL)); } 386 387 CorruptedPages::~CorruptedPages() { ut_a(!pthread_mutex_destroy(&m_mutex)); } 388 389 void CorruptedPages::add_page_no_lock(const char *space_name, ulint space_id, 390 ulint page_no, bool convert_space_name) 391 { 392 space_info_t &space_info = m_spaces[space_id]; 393 if (space_info.space_name.empty()) 394 space_info.space_name= 395 convert_space_name 396 ? filename_to_spacename(reinterpret_cast<const byte *>(space_name), 397 strlen(space_name)) 398 : space_name; 399 (void)space_info.pages.insert(page_no); 400 } 401 402 void CorruptedPages::add_page(const char *file_name, ulint space_id, 403 ulint page_no) 404 { 405 ut_a(!pthread_mutex_lock(&m_mutex)); 406 add_page_no_lock(file_name, space_id, page_no, true); 407 ut_a(!pthread_mutex_unlock(&m_mutex)); 408 } 409 410 bool CorruptedPages::contains(ulint space_id, ulint page_no) const 411 { 412 bool result = false; 413 ut_a(!pthread_mutex_lock(&m_mutex)); 414 container_t::const_iterator space_it= m_spaces.find(space_id); 415 if (space_it != m_spaces.end()) 416 result = space_it->second.pages.count(page_no); 417 ut_a(!pthread_mutex_unlock(&m_mutex)); 418 return result; 419 } 420 421 void CorruptedPages::drop_space(ulint space_id) 422 { 423 ut_a(!pthread_mutex_lock(&m_mutex)); 424 m_spaces.erase(space_id); 425 ut_a(!pthread_mutex_unlock(&m_mutex)); 426 } 427 428 void CorruptedPages::rename_space(ulint space_id, const std::string &new_name) 429 { 430 ut_a(!pthread_mutex_lock(&m_mutex)); 431 container_t::iterator space_it = m_spaces.find(space_id); 432 if (space_it != m_spaces.end()) 433 space_it->second.space_name = new_name; 434 ut_a(!pthread_mutex_unlock(&m_mutex)); 435 } 436 437 bool CorruptedPages::print_to_file(const char *filename) const 438 { 439 std::ostringstream out; 440 ut_a(!pthread_mutex_lock(&m_mutex)); 441 if (!m_spaces.size()) 442 { 443 ut_a(!pthread_mutex_unlock(&m_mutex)); 444 return true; 445 } 446 for (container_t::const_iterator space_it= 447 m_spaces.begin(); 448 space_it != m_spaces.end(); ++space_it) 449 { 450 out << space_it->second.space_name << " " << space_it->first << "\n"; 451 bool first_page_no= true; 452 for (std::set<ulint>::const_iterator page_it= 453 space_it->second.pages.begin(); 454 page_it != space_it->second.pages.end(); ++page_it) 455 if (first_page_no) 456 { 457 out << *page_it; 458 first_page_no= false; 459 } 460 else 461 out << " " << *page_it; 462 out << "\n"; 463 } 464 ut_a(!pthread_mutex_unlock(&m_mutex)); 465 if (xtrabackup_backup) 466 return backup_file_print_buf(filename, out.str().c_str(), 467 static_cast<int>(out.str().size())); 468 std::ofstream outfile; 469 outfile.open(filename); 470 if (!outfile.is_open()) 471 die("Can't open %s, error number: %d, error message: %s", filename, errno, 472 strerror(errno)); 473 outfile << out.str(); 474 return true; 475 } 476 477 void CorruptedPages::read_from_file(const char *file_name) 478 { 479 MY_STAT mystat; 480 if (!my_stat(file_name, &mystat, MYF(0))) 481 return; 482 std::ifstream infile; 483 infile.open(file_name); 484 if (!infile.is_open()) 485 die("Can't open %s, error number: %d, error message: %s", file_name, errno, 486 strerror(errno)); 487 std::string line; 488 std::string space_name; 489 ulint space_id; 490 ulint line_number= 0; 491 while (std::getline(infile, line)) 492 { 493 ++line_number; 494 std::istringstream iss(line); 495 if (line_number & 1) { 496 if (!(iss >> space_name)) 497 die("Can't parse space name from corrupted pages file at " 498 "line " ULINTPF, 499 line_number); 500 if (!(iss >> space_id)) 501 die("Can't parse space id from corrupted pages file at line " ULINTPF, 502 line_number); 503 } 504 else 505 { 506 ulint page_no; 507 while ((iss >> page_no)) 508 add_page_no_lock(space_name.c_str(), space_id, page_no, false); 509 if (!iss.eof()) 510 die("Corrupted pages file parse error on line number " ULINTPF, 511 line_number); 512 } 513 } 514 } 515 516 bool CorruptedPages::empty() const 517 { 518 ut_a(!pthread_mutex_lock(&m_mutex)); 519 bool result= !m_spaces.size(); 520 ut_a(!pthread_mutex_unlock(&m_mutex)); 521 return result; 522 } 523 524 static void xb_load_single_table_tablespace(const std::string &space_name, 525 bool set_size); 526 static void xb_data_files_close(); 527 static fil_space_t* fil_space_get_by_name(const char* name); 528 529 void CorruptedPages::zero_out_free_pages() 530 { 531 container_t non_free_pages; 532 byte* buf= static_cast<byte*>(ut_malloc_nokey(2 * srv_page_size)); 533 byte* zero_page = static_cast<byte*>(ut_align(buf, srv_page_size)); 534 memset(zero_page, 0, srv_page_size); 535 536 ut_a(!pthread_mutex_lock(&m_mutex)); 537 for (container_t::const_iterator space_it= m_spaces.begin(); 538 space_it != m_spaces.end(); ++space_it) 539 { 540 ulint space_id = space_it->first; 541 const std::string &space_name = space_it->second.space_name; 542 // There is no need to close tablespaces explixitly as they will be closed 543 // in innodb_shutdown(). 544 xb_load_single_table_tablespace(space_name, false); 545 mutex_enter(&fil_system.mutex); 546 fil_space_t *space = fil_space_get_by_name(space_name.c_str()); 547 mutex_exit(&fil_system.mutex); 548 if (!space) 549 die("Can't find space object for space name %s to check corrupted page", 550 space_name.c_str()); 551 for (std::set<ulint>::const_iterator page_it= 552 space_it->second.pages.begin(); 553 page_it != space_it->second.pages.end(); ++page_it) 554 { 555 bool is_free= fseg_page_is_free(space, static_cast<unsigned>(*page_it)); 556 if (!is_free) { 557 space_info_t &space_info = non_free_pages[space_id]; 558 space_info.pages.insert(*page_it); 559 if (space_info.space_name.empty()) 560 space_info.space_name = space_name; 561 msg("Error: corrupted page " ULINTPF 562 " of tablespace %s can not be fixed", 563 *page_it, space_name.c_str()); 564 } 565 else 566 { 567 const page_id_t page_id(space->id, *page_it); 568 dberr_t err= fil_io(IORequestWrite, true, page_id, 0, 0, 569 srv_page_size, zero_page, NULL); 570 if (err != DB_SUCCESS) 571 die("Can't zero out corrupted page " ULINTPF " of tablespace %s", 572 *page_it, space_name.c_str()); 573 msg("Corrupted page " ULINTPF 574 " of tablespace %s was successfuly fixed.", 575 *page_it, space_name.c_str()); 576 } 577 } 578 } 579 m_spaces.swap(non_free_pages); 580 ut_a(!pthread_mutex_unlock(&m_mutex)); 581 ut_free(buf); 582 } 583 584 /* Simple datasink creation tracking...add datasinks in the reverse order you 585 want them destroyed. */ 586 #define XTRABACKUP_MAX_DATASINKS 10 587 static ds_ctxt_t *datasinks[XTRABACKUP_MAX_DATASINKS]; 588 static uint actual_datasinks = 0; 589 static inline 590 void 591 xtrabackup_add_datasink(ds_ctxt_t *ds) 592 { 593 xb_ad(actual_datasinks < XTRABACKUP_MAX_DATASINKS); 594 datasinks[actual_datasinks] = ds; actual_datasinks++; 595 } 596 597 typedef void (*process_single_tablespace_func_t)(const char *dirname, 598 const char *filname, 599 bool is_remote, 600 bool set_size); 601 static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback); 602 603 /* ======== Datafiles iterator ======== */ 604 struct datafiles_iter_t { 605 fil_space_t *space; 606 fil_node_t *node; 607 ibool started; 608 pthread_mutex_t mutex; 609 }; 610 611 /* ======== Datafiles iterator ======== */ 612 static 613 datafiles_iter_t * 614 datafiles_iter_new() 615 { 616 datafiles_iter_t *it; 617 618 it = static_cast<datafiles_iter_t *>(malloc(sizeof(datafiles_iter_t))); 619 pthread_mutex_init(&it->mutex, NULL); 620 621 it->space = NULL; 622 it->node = NULL; 623 it->started = FALSE; 624 625 return it; 626 } 627 628 static 629 fil_node_t * 630 datafiles_iter_next(datafiles_iter_t *it) 631 { 632 fil_node_t *new_node; 633 634 pthread_mutex_lock(&it->mutex); 635 636 if (it->node == NULL) { 637 if (it->started) 638 goto end; 639 it->started = TRUE; 640 } else { 641 it->node = UT_LIST_GET_NEXT(chain, it->node); 642 if (it->node != NULL) 643 goto end; 644 } 645 646 it->space = (it->space == NULL) ? 647 UT_LIST_GET_FIRST(fil_system.space_list) : 648 UT_LIST_GET_NEXT(space_list, it->space); 649 650 while (it->space != NULL && 651 (it->space->purpose != FIL_TYPE_TABLESPACE || 652 UT_LIST_GET_LEN(it->space->chain) == 0)) 653 it->space = UT_LIST_GET_NEXT(space_list, it->space); 654 if (it->space == NULL) 655 goto end; 656 657 it->node = UT_LIST_GET_FIRST(it->space->chain); 658 659 end: 660 new_node = it->node; 661 pthread_mutex_unlock(&it->mutex); 662 663 return new_node; 664 } 665 666 static 667 void 668 datafiles_iter_free(datafiles_iter_t *it) 669 { 670 pthread_mutex_destroy(&it->mutex); 671 free(it); 672 } 673 674 #ifndef DBUG_OFF 675 struct dbug_thread_param_t 676 { 677 MYSQL *con; 678 const char *query; 679 int expect_err; 680 int expect_errno; 681 os_event_t done_event; 682 }; 683 684 685 /* Thread procedure used in dbug_start_query_thread. */ 686 extern "C" 687 os_thread_ret_t 688 DECLARE_THREAD(dbug_execute_in_new_connection)(void *arg) 689 { 690 mysql_thread_init(); 691 dbug_thread_param_t *par= (dbug_thread_param_t *)arg; 692 int err = mysql_query(par->con, par->query); 693 int err_no = mysql_errno(par->con); 694 if(par->expect_err != err) 695 { 696 msg("FATAL: dbug_execute_in_new_connection : mysql_query '%s' returns %d, instead of expected %d", 697 par->query, err, par->expect_err); 698 _exit(1); 699 } 700 if (err && par->expect_errno && par->expect_errno != err_no) 701 { 702 msg("FATAL: dbug_execute_in_new_connection: mysql_query '%s' returns mysql_errno %d, instead of expected %d", 703 par->query, err_no, par->expect_errno); 704 _exit(1); 705 } 706 mysql_close(par->con); 707 mysql_thread_end(); 708 os_event_t done = par->done_event; 709 delete par; 710 os_event_set(done); 711 os_thread_exit(); 712 return os_thread_ret_t(0); 713 } 714 715 /* 716 Execute query from a new connection, in own thread. 717 718 @param query - query to be executed 719 @param wait_state - if not NULL, wait until query from new connection 720 reaches this state (value of column State in I_S.PROCESSLIST) 721 @param expected_err - if 0, query is supposed to finish successfully, 722 otherwise query should return error. 723 @param expected_errno - if not 0, and query finished with error, 724 expected mysql_errno() 725 */ 726 static os_event_t dbug_start_query_thread( 727 const char *query, 728 const char *wait_state, 729 int expected_err, 730 int expected_errno) 731 732 { 733 dbug_thread_param_t *par = new dbug_thread_param_t; 734 par->query = query; 735 par->expect_err = expected_err; 736 par->expect_errno = expected_errno; 737 par->done_event = os_event_create(0); 738 par->con = xb_mysql_connect(); 739 os_thread_create(dbug_execute_in_new_connection, par, 0); 740 741 if (!wait_state) 742 return par->done_event; 743 744 char q[256]; 745 snprintf(q, sizeof(q), 746 "SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST where ID=%lu" 747 " AND Command='Query' AND State='%s'", 748 mysql_thread_id(par->con), wait_state); 749 for (;;) { 750 MYSQL_RES *result = xb_mysql_query(mysql_connection,q, true, true); 751 bool exists = mysql_fetch_row(result) != NULL; 752 mysql_free_result(result); 753 if (exists) { 754 goto end; 755 } 756 msg("Waiting for query '%s' on connection %lu to " 757 " reach state '%s'", query, mysql_thread_id(par->con), 758 wait_state); 759 my_sleep(1000); 760 } 761 end: 762 msg("query '%s' on connection %lu reached state '%s'", query, 763 mysql_thread_id(par->con), wait_state); 764 return par->done_event; 765 } 766 767 os_event_t dbug_alter_thread_done; 768 #endif 769 770 void mdl_lock_all() 771 { 772 mdl_lock_init(); 773 datafiles_iter_t *it = datafiles_iter_new(); 774 if (!it) 775 return; 776 777 while (fil_node_t *node = datafiles_iter_next(it)){ 778 if (fil_is_user_tablespace_id(node->space->id) 779 && check_if_skip_table(node->space->name)) 780 continue; 781 782 mdl_lock_table(node->space->id); 783 } 784 datafiles_iter_free(it); 785 } 786 787 788 // Convert non-null terminated filename to space name 789 std::string filename_to_spacename(const byte *filename, size_t len) 790 { 791 // null- terminate filename 792 char *f = (char *)malloc(len + 1); 793 ut_a(f); 794 memcpy(f, filename, len); 795 f[len] = 0; 796 for (size_t i = 0; i < len; i++) 797 if (f[i] == '\\') 798 f[i] = '/'; 799 char *p = strrchr(f, '.'); 800 ut_a(p); 801 *p = 0; 802 char *table = strrchr(f, '/'); 803 ut_a(table); 804 *table = 0; 805 char *db = strrchr(f, '/'); 806 ut_a(db); 807 *table = '/'; 808 std::string s(db+1); 809 free(f); 810 return s; 811 } 812 813 /** Report an operation to create, delete, or rename a file during backup. 814 @param[in] space_id tablespace identifier 815 @param[in] flags tablespace flags (NULL if not create) 816 @param[in] name file name (not NUL-terminated) 817 @param[in] len length of name, in bytes 818 @param[in] new_name new file name (NULL if not rename) 819 @param[in] new_len length of new_name, in bytes (0 if NULL) */ 820 static void backup_file_op(ulint space_id, const byte* flags, 821 const byte* name, ulint len, 822 const byte* new_name, ulint new_len) 823 { 824 825 ut_ad(!flags || !new_name); 826 ut_ad(name); 827 ut_ad(len); 828 ut_ad(!new_name == !new_len); 829 pthread_mutex_lock(&backup_mutex); 830 831 if (flags) { 832 ddl_tracker.id_to_name[space_id] = filename_to_spacename(name, len); 833 msg("DDL tracking : create %zu \"%.*s\": %x", 834 space_id, int(len), name, mach_read_from_4(flags)); 835 } 836 else if (new_name) { 837 ddl_tracker.id_to_name[space_id] = filename_to_spacename(new_name, new_len); 838 msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"", 839 space_id, int(len), name, int(new_len), new_name); 840 } else { 841 ddl_tracker.drops.insert(space_id); 842 msg("DDL tracking : delete %zu \"%.*s\"", space_id, int(len), name); 843 } 844 pthread_mutex_unlock(&backup_mutex); 845 } 846 847 848 /* 849 This callback is called if DDL operation is detected, 850 at the end of backup 851 852 Normally, DDL operations are blocked due to FTWRL, 853 but in rare cases of --no-lock, they are not. 854 855 We will abort backup in this case. 856 */ 857 static void backup_file_op_fail(ulint space_id, const byte* flags, 858 const byte* name, ulint len, 859 const byte* new_name, ulint new_len) 860 { 861 bool fail; 862 if (flags) { 863 msg("DDL tracking : create %zu \"%.*s\": %x", 864 space_id, int(len), name, mach_read_from_4(flags)); 865 std::string spacename = filename_to_spacename(name, len); 866 fail = !check_if_skip_table(spacename.c_str()); 867 } 868 else if (new_name) { 869 msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"", 870 space_id, int(len), name, int(new_len), new_name); 871 std::string spacename = filename_to_spacename(name, len); 872 std::string new_spacename = filename_to_spacename(new_name, new_len); 873 fail = !check_if_skip_table(spacename.c_str()) || !check_if_skip_table(new_spacename.c_str()); 874 } 875 else { 876 std::string spacename = filename_to_spacename(name, len); 877 fail = !check_if_skip_table(spacename.c_str()); 878 msg("DDL tracking : delete %zu \"%.*s\"", space_id, int(len), name); 879 } 880 if (fail) { 881 ut_a(opt_no_lock); 882 die("DDL operation detected in the late phase of backup." 883 "Backup is inconsistent. Remove --no-lock option to fix."); 884 } 885 } 886 887 888 /** Callback whenever MLOG_INDEX_LOAD happens. 889 @param[in] space_id space id to check */ 890 static void backup_optimized_ddl_op(ulint space_id) 891 { 892 pthread_mutex_lock(&backup_mutex); 893 ddl_tracker.optimized_ddl.insert(space_id); 894 pthread_mutex_unlock(&backup_mutex); 895 } 896 897 /* 898 Optimized DDL callback at the end of backup that 899 run with --no-lock. Usually aborts the backup. 900 */ 901 static void backup_optimized_ddl_op_fail(ulint space_id) { 902 msg("DDL tracking : optimized DDL on space %zu", space_id); 903 if (ddl_tracker.tables_in_backup.find(space_id) != ddl_tracker.tables_in_backup.end()) { 904 ut_a(opt_no_lock); 905 msg("ERROR : Optimized DDL operation detected in the late phase of backup." 906 "Backup is inconsistent. Remove --no-lock option to fix."); 907 exit(EXIT_FAILURE); 908 } 909 } 910 911 912 /* 913 Retrieve default data directory, to be used with --copy-back. 914 915 On Windows, default datadir is ..\data, relative to the 916 directory where mariabackup.exe is located(usually "bin") 917 918 Elsewhere, the compiled-in constant MYSQL_DATADIR is used. 919 */ 920 static char *get_default_datadir() { 921 static char ddir[] = MYSQL_DATADIR; 922 #ifdef _WIN32 923 static char buf[MAX_PATH]; 924 DWORD size = (DWORD)sizeof(buf) - 1; 925 if (GetModuleFileName(NULL, buf, size) <= size) 926 { 927 char *p; 928 if ((p = strrchr(buf, '\\'))) 929 { 930 *p = 0; 931 if ((p = strrchr(buf, '\\'))) 932 { 933 strncpy(p + 1, "data", buf + MAX_PATH - p); 934 return buf; 935 } 936 } 937 } 938 #endif 939 return ddir; 940 } 941 942 943 /* ======== Date copying thread context ======== */ 944 945 typedef struct { 946 datafiles_iter_t *it; 947 uint num; 948 uint *count; 949 pthread_mutex_t* count_mutex; 950 os_thread_id_t id; 951 CorruptedPages *corrupted_pages; 952 } data_thread_ctxt_t; 953 954 /* ======== for option and variables ======== */ 955 #include <../../client/client_priv.h> 956 957 enum options_xtrabackup 958 { 959 OPT_XTRA_TARGET_DIR= 1000, /* make sure it is larger 960 than OPT_MAX_CLIENT_OPTION */ 961 OPT_XTRA_BACKUP, 962 OPT_XTRA_PREPARE, 963 OPT_XTRA_EXPORT, 964 OPT_XTRA_ROLLBACK_XA, 965 OPT_XTRA_PRINT_PARAM, 966 OPT_XTRA_USE_MEMORY, 967 OPT_XTRA_THROTTLE, 968 OPT_XTRA_LOG_COPY_INTERVAL, 969 OPT_XTRA_INCREMENTAL, 970 OPT_XTRA_INCREMENTAL_BASEDIR, 971 OPT_XTRA_EXTRA_LSNDIR, 972 OPT_XTRA_INCREMENTAL_DIR, 973 OPT_XTRA_TABLES, 974 OPT_XTRA_TABLES_FILE, 975 OPT_XTRA_DATABASES, 976 OPT_XTRA_DATABASES_FILE, 977 OPT_XTRA_PARALLEL, 978 OPT_XTRA_EXTENDED_VALIDATION, 979 OPT_XTRA_ENCRYPTED_BACKUP, 980 OPT_XTRA_STREAM, 981 OPT_XTRA_COMPRESS, 982 OPT_XTRA_COMPRESS_THREADS, 983 OPT_XTRA_COMPRESS_CHUNK_SIZE, 984 OPT_LOG, 985 OPT_INNODB, 986 OPT_INNODB_DATA_FILE_PATH, 987 OPT_INNODB_DATA_HOME_DIR, 988 OPT_INNODB_ADAPTIVE_HASH_INDEX, 989 OPT_INNODB_DOUBLEWRITE, 990 OPT_INNODB_FILE_PER_TABLE, 991 OPT_INNODB_FLUSH_METHOD, 992 OPT_INNODB_LOG_GROUP_HOME_DIR, 993 OPT_INNODB_MAX_DIRTY_PAGES_PCT, 994 OPT_INNODB_MAX_PURGE_LAG, 995 OPT_INNODB_STATUS_FILE, 996 OPT_INNODB_AUTOEXTEND_INCREMENT, 997 OPT_INNODB_BUFFER_POOL_SIZE, 998 OPT_INNODB_COMMIT_CONCURRENCY, 999 OPT_INNODB_CONCURRENCY_TICKETS, 1000 OPT_INNODB_FILE_IO_THREADS, 1001 OPT_INNODB_IO_CAPACITY, 1002 OPT_INNODB_READ_IO_THREADS, 1003 OPT_INNODB_WRITE_IO_THREADS, 1004 OPT_INNODB_USE_NATIVE_AIO, 1005 OPT_INNODB_PAGE_SIZE, 1006 OPT_INNODB_BUFFER_POOL_FILENAME, 1007 OPT_INNODB_LOCK_WAIT_TIMEOUT, 1008 OPT_INNODB_LOG_BUFFER_SIZE, 1009 OPT_INNODB_LOG_FILE_SIZE, 1010 OPT_INNODB_LOG_FILES_IN_GROUP, 1011 OPT_INNODB_OPEN_FILES, 1012 OPT_XTRA_DEBUG_SYNC, 1013 OPT_INNODB_CHECKSUM_ALGORITHM, 1014 OPT_INNODB_UNDO_DIRECTORY, 1015 OPT_INNODB_UNDO_TABLESPACES, 1016 OPT_INNODB_LOG_CHECKSUMS, 1017 OPT_XTRA_INCREMENTAL_FORCE_SCAN, 1018 OPT_DEFAULTS_GROUP, 1019 OPT_CLOSE_FILES, 1020 OPT_CORE_FILE, 1021 1022 OPT_COPY_BACK, 1023 OPT_MOVE_BACK, 1024 OPT_GALERA_INFO, 1025 OPT_SLAVE_INFO, 1026 OPT_NO_LOCK, 1027 OPT_SAFE_SLAVE_BACKUP, 1028 OPT_RSYNC, 1029 OPT_FORCE_NON_EMPTY_DIRS, 1030 OPT_NO_VERSION_CHECK, 1031 OPT_NO_BACKUP_LOCKS, 1032 OPT_DECOMPRESS, 1033 OPT_INCREMENTAL_HISTORY_NAME, 1034 OPT_INCREMENTAL_HISTORY_UUID, 1035 OPT_REMOVE_ORIGINAL, 1036 OPT_LOCK_WAIT_QUERY_TYPE, 1037 OPT_KILL_LONG_QUERY_TYPE, 1038 OPT_HISTORY, 1039 OPT_KILL_LONG_QUERIES_TIMEOUT, 1040 OPT_LOCK_WAIT_TIMEOUT, 1041 OPT_LOCK_WAIT_THRESHOLD, 1042 OPT_DEBUG_SLEEP_BEFORE_UNLOCK, 1043 OPT_SAFE_SLAVE_BACKUP_TIMEOUT, 1044 OPT_BINLOG_INFO, 1045 OPT_XB_SECURE_AUTH, 1046 1047 OPT_XTRA_TABLES_EXCLUDE, 1048 OPT_XTRA_DATABASES_EXCLUDE, 1049 OPT_PROTOCOL, 1050 OPT_INNODB_COMPRESSION_LEVEL, 1051 OPT_LOCK_DDL_PER_TABLE, 1052 OPT_ROCKSDB_DATADIR, 1053 OPT_BACKUP_ROCKSDB, 1054 OPT_XTRA_CHECK_PRIVILEGES, 1055 OPT_XTRA_MYSQLD_ARGS, 1056 OPT_XB_IGNORE_INNODB_PAGE_CORRUPTION, 1057 OPT_INNODB_FORCE_RECOVERY 1058 }; 1059 1060 struct my_option xb_client_options[]= { 1061 {"verbose", 'V', "display verbose output", (G_PTR *) &verbose, 1062 (G_PTR *) &verbose, 0, GET_BOOL, NO_ARG, FALSE, 0, 0, 0, 0, 0}, 1063 {"version", 'v', "print version information", 1064 (G_PTR *) &xtrabackup_version, (G_PTR *) &xtrabackup_version, 0, GET_BOOL, 1065 NO_ARG, 0, 0, 0, 0, 0, 0}, 1066 {"target-dir", OPT_XTRA_TARGET_DIR, "destination directory", 1067 (G_PTR *) &xtrabackup_target_dir, (G_PTR *) &xtrabackup_target_dir, 0, 1068 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1069 {"backup", OPT_XTRA_BACKUP, "take backup to target-dir", 1070 (G_PTR *) &xtrabackup_backup, (G_PTR *) &xtrabackup_backup, 0, GET_BOOL, 1071 NO_ARG, 0, 0, 0, 0, 0, 0}, 1072 {"prepare", OPT_XTRA_PREPARE, 1073 "prepare a backup for starting mysql server on the backup.", 1074 (G_PTR *) &xtrabackup_prepare, (G_PTR *) &xtrabackup_prepare, 0, GET_BOOL, 1075 NO_ARG, 0, 0, 0, 0, 0, 0}, 1076 {"export", OPT_XTRA_EXPORT, 1077 "create files to import to another database when prepare.", 1078 (G_PTR *) &xtrabackup_export, (G_PTR *) &xtrabackup_export, 0, GET_BOOL, 1079 NO_ARG, 0, 0, 0, 0, 0, 0}, 1080 {"rollback-xa", OPT_XTRA_ROLLBACK_XA, 1081 "Rollback prepared XA's on --prepare. " 1082 "After preparing target directory with this option " 1083 "it can no longer be a base for incremental backup.", 1084 (G_PTR *) &xtrabackup_rollback_xa, (G_PTR *) &xtrabackup_rollback_xa, 0, 1085 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1086 {"print-param", OPT_XTRA_PRINT_PARAM, 1087 "print parameter of mysqld needed for copyback.", 1088 (G_PTR *) &xtrabackup_print_param, (G_PTR *) &xtrabackup_print_param, 0, 1089 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1090 {"use-memory", OPT_XTRA_USE_MEMORY, 1091 "The value is used instead of buffer_pool_size", 1092 (G_PTR *) &xtrabackup_use_memory, (G_PTR *) &xtrabackup_use_memory, 0, 1093 GET_LL, REQUIRED_ARG, 100 * 1024 * 1024L, 1024 * 1024L, LONGLONG_MAX, 0, 1094 1024 * 1024L, 0}, 1095 {"throttle", OPT_XTRA_THROTTLE, 1096 "limit count of IO operations (pairs of read&write) per second to IOS " 1097 "values (for '--backup')", 1098 (G_PTR *) &xtrabackup_throttle, (G_PTR *) &xtrabackup_throttle, 0, 1099 GET_LONG, REQUIRED_ARG, 0, 0, LONG_MAX, 0, 1, 0}, 1100 {"log", OPT_LOG, "Ignored option for MySQL option compatibility", 1101 (G_PTR *) &log_ignored_opt, (G_PTR *) &log_ignored_opt, 0, GET_STR, 1102 OPT_ARG, 0, 0, 0, 0, 0, 0}, 1103 {"log-copy-interval", OPT_XTRA_LOG_COPY_INTERVAL, 1104 "time interval between checks done by log copying thread in milliseconds " 1105 "(default is 1 second).", 1106 (G_PTR *) &xtrabackup_log_copy_interval, 1107 (G_PTR *) &xtrabackup_log_copy_interval, 0, GET_LONG, REQUIRED_ARG, 1000, 1108 0, LONG_MAX, 0, 1, 0}, 1109 {"extra-lsndir", OPT_XTRA_EXTRA_LSNDIR, 1110 "(for --backup): save an extra copy of the xtrabackup_checkpoints file " 1111 "in this directory.", 1112 (G_PTR *) &xtrabackup_extra_lsndir, (G_PTR *) &xtrabackup_extra_lsndir, 0, 1113 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1114 {"incremental-lsn", OPT_XTRA_INCREMENTAL, 1115 "(for --backup): copy only .ibd pages newer than specified LSN " 1116 "'high:low'. ##ATTENTION##: If a wrong LSN value is specified, it is " 1117 "impossible to diagnose this, causing the backup to be unusable. Be " 1118 "careful!", 1119 (G_PTR *) &xtrabackup_incremental, (G_PTR *) &xtrabackup_incremental, 0, 1120 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1121 {"incremental-basedir", OPT_XTRA_INCREMENTAL_BASEDIR, 1122 "(for --backup): copy only .ibd pages newer than backup at specified " 1123 "directory.", 1124 (G_PTR *) &xtrabackup_incremental_basedir, 1125 (G_PTR *) &xtrabackup_incremental_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 1126 0, 0, 0, 0}, 1127 {"incremental-dir", OPT_XTRA_INCREMENTAL_DIR, 1128 "(for --prepare): apply .delta files and logfile in the specified " 1129 "directory.", 1130 (G_PTR *) &xtrabackup_incremental_dir, 1131 (G_PTR *) &xtrabackup_incremental_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 1132 0, 0, 0}, 1133 {"tables", OPT_XTRA_TABLES, "filtering by regexp for table names.", 1134 (G_PTR *) &xtrabackup_tables, (G_PTR *) &xtrabackup_tables, 0, GET_STR, 1135 REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1136 {"tables_file", OPT_XTRA_TABLES_FILE, 1137 "filtering by list of the exact database.table name in the file.", 1138 (G_PTR *) &xtrabackup_tables_file, (G_PTR *) &xtrabackup_tables_file, 0, 1139 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1140 {"databases", OPT_XTRA_DATABASES, "filtering by list of databases.", 1141 (G_PTR *) &xtrabackup_databases, (G_PTR *) &xtrabackup_databases, 0, 1142 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1143 {"databases_file", OPT_XTRA_DATABASES_FILE, 1144 "filtering by list of databases in the file.", 1145 (G_PTR *) &xtrabackup_databases_file, 1146 (G_PTR *) &xtrabackup_databases_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 1147 0, 0, 0}, 1148 {"tables-exclude", OPT_XTRA_TABLES_EXCLUDE, 1149 "filtering by regexp for table names. " 1150 "Operates the same way as --tables, but matched names are excluded from " 1151 "backup. " 1152 "Note that this option has a higher priority than --tables.", 1153 (G_PTR *) &xtrabackup_tables_exclude, 1154 (G_PTR *) &xtrabackup_tables_exclude, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 1155 0, 0, 0}, 1156 {"databases-exclude", OPT_XTRA_DATABASES_EXCLUDE, 1157 "Excluding databases based on name, " 1158 "Operates the same way as --databases, but matched names are excluded " 1159 "from backup. " 1160 "Note that this option has a higher priority than --databases.", 1161 (G_PTR *) &xtrabackup_databases_exclude, 1162 (G_PTR *) &xtrabackup_databases_exclude, 0, GET_STR, REQUIRED_ARG, 0, 0, 1163 0, 0, 0, 0}, 1164 1165 {"stream", OPT_XTRA_STREAM, 1166 "Stream all backup files to the standard output " 1167 "in the specified format." 1168 "Supported format is 'mbstream' or 'xbstream'.", 1169 (G_PTR *) &xtrabackup_stream_str, (G_PTR *) &xtrabackup_stream_str, 0, 1170 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1171 1172 {"compress", OPT_XTRA_COMPRESS, 1173 "Compress individual backup files using the " 1174 "specified compression algorithm. Currently the only supported algorithm " 1175 "is 'quicklz'. It is also the default algorithm, i.e. the one used when " 1176 "--compress is used without an argument.", 1177 (G_PTR *) &xtrabackup_compress_alg, (G_PTR *) &xtrabackup_compress_alg, 0, 1178 GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 1179 1180 {"compress-threads", OPT_XTRA_COMPRESS_THREADS, 1181 "Number of threads for parallel data compression. The default value is " 1182 "1.", 1183 (G_PTR *) &xtrabackup_compress_threads, 1184 (G_PTR *) &xtrabackup_compress_threads, 0, GET_UINT, REQUIRED_ARG, 1, 1, 1185 UINT_MAX, 0, 0, 0}, 1186 1187 {"compress-chunk-size", OPT_XTRA_COMPRESS_CHUNK_SIZE, 1188 "Size of working buffer(s) for compression threads in bytes. The default " 1189 "value is 64K.", 1190 (G_PTR *) &xtrabackup_compress_chunk_size, 1191 (G_PTR *) &xtrabackup_compress_chunk_size, 0, GET_ULL, REQUIRED_ARG, 1192 (1 << 16), 1024, ULONGLONG_MAX, 0, 0, 0}, 1193 1194 {"incremental-force-scan", OPT_XTRA_INCREMENTAL_FORCE_SCAN, 1195 "Perform a full-scan incremental backup even in the presence of changed " 1196 "page bitmap data", 1197 (G_PTR *) &xtrabackup_incremental_force_scan, 1198 (G_PTR *) &xtrabackup_incremental_force_scan, 0, GET_BOOL, NO_ARG, 0, 0, 1199 0, 0, 0, 0}, 1200 1201 {"close_files", OPT_CLOSE_FILES, 1202 "do not keep files opened. Use at your own " 1203 "risk.", 1204 (G_PTR *) &xb_close_files, (G_PTR *) &xb_close_files, 0, GET_BOOL, NO_ARG, 1205 0, 0, 0, 0, 0, 0}, 1206 1207 {"core-file", OPT_CORE_FILE, "Write core on fatal signals", 0, 0, 0, 1208 GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 1209 1210 {"copy-back", OPT_COPY_BACK, 1211 "Copy all the files in a previously made " 1212 "backup from the backup directory to their original locations.", 1213 (uchar *) &xtrabackup_copy_back, (uchar *) &xtrabackup_copy_back, 0, 1214 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1215 1216 {"move-back", OPT_MOVE_BACK, 1217 "Move all the files in a previously made " 1218 "backup from the backup directory to the actual datadir location. " 1219 "Use with caution, as it removes backup files.", 1220 (uchar *) &xtrabackup_move_back, (uchar *) &xtrabackup_move_back, 0, 1221 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1222 1223 {"galera-info", OPT_GALERA_INFO, 1224 "This options creates the " 1225 "xtrabackup_galera_info file which contains the local node state at " 1226 "the time of the backup. Option should be used when performing the " 1227 "backup of MariaDB Galera Cluster. Has no effect when backup locks " 1228 "are used to create the backup.", 1229 (uchar *) &opt_galera_info, (uchar *) &opt_galera_info, 0, GET_BOOL, 1230 NO_ARG, 0, 0, 0, 0, 0, 0}, 1231 1232 {"slave-info", OPT_SLAVE_INFO, 1233 "This option is useful when backing " 1234 "up a replication slave server. It prints the binary log position " 1235 "and name of the master server. It also writes this information to " 1236 "the \"xtrabackup_slave_info\" file as a \"CHANGE MASTER\" command. " 1237 "A new slave for this master can be set up by starting a slave server " 1238 "on this backup and issuing a \"CHANGE MASTER\" command with the " 1239 "binary log position saved in the \"xtrabackup_slave_info\" file.", 1240 (uchar *) &opt_slave_info, (uchar *) &opt_slave_info, 0, GET_BOOL, NO_ARG, 1241 0, 0, 0, 0, 0, 0}, 1242 1243 {"no-lock", OPT_NO_LOCK, 1244 "Use this option to disable table lock " 1245 "with \"FLUSH TABLES WITH READ LOCK\". Use it only if ALL your " 1246 "tables are InnoDB and you DO NOT CARE about the binary log " 1247 "position of the backup. This option shouldn't be used if there " 1248 "are any DDL statements being executed or if any updates are " 1249 "happening on non-InnoDB tables (this includes the system MyISAM " 1250 "tables in the mysql database), otherwise it could lead to an " 1251 "inconsistent backup. If you are considering to use --no-lock " 1252 "because your backups are failing to acquire the lock, this could " 1253 "be because of incoming replication events preventing the lock " 1254 "from succeeding. Please try using --safe-slave-backup to " 1255 "momentarily stop the replication slave thread, this may help " 1256 "the backup to succeed and you then don't need to resort to " 1257 "using this option.", 1258 (uchar *) &opt_no_lock, (uchar *) &opt_no_lock, 0, GET_BOOL, NO_ARG, 0, 0, 1259 0, 0, 0, 0}, 1260 1261 {"safe-slave-backup", OPT_SAFE_SLAVE_BACKUP, 1262 "Stop slave SQL thread " 1263 "and wait to start backup until Slave_open_temp_tables in " 1264 "\"SHOW STATUS\" is zero. If there are no open temporary tables, " 1265 "the backup will take place, otherwise the SQL thread will be " 1266 "started and stopped until there are no open temporary tables. " 1267 "The backup will fail if Slave_open_temp_tables does not become " 1268 "zero after --safe-slave-backup-timeout seconds. The slave SQL " 1269 "thread will be restarted when the backup finishes.", 1270 (uchar *) &opt_safe_slave_backup, (uchar *) &opt_safe_slave_backup, 0, 1271 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1272 1273 {"rsync", OPT_RSYNC, 1274 "Uses the rsync utility to optimize local file " 1275 "transfers. When this option is specified, innobackupex uses rsync " 1276 "to copy all non-InnoDB files instead of spawning a separate cp for " 1277 "each file, which can be much faster for servers with a large number " 1278 "of databases or tables. This option cannot be used together with " 1279 "--stream.", 1280 (uchar *) &opt_rsync, (uchar *) &opt_rsync, 0, GET_BOOL, NO_ARG, 0, 0, 0, 1281 0, 0, 0}, 1282 1283 {"force-non-empty-directories", OPT_FORCE_NON_EMPTY_DIRS, 1284 "This " 1285 "option, when specified, makes --copy-back or --move-back transfer " 1286 "files to non-empty directories. Note that no existing files will be " 1287 "overwritten. If --copy-back or --move-back has to copy a file from " 1288 "the backup directory which already exists in the destination " 1289 "directory, it will still fail with an error.", 1290 (uchar *) &opt_force_non_empty_dirs, (uchar *) &opt_force_non_empty_dirs, 1291 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1292 1293 {"no-version-check", OPT_NO_VERSION_CHECK, 1294 "This option disables the " 1295 "version check which is enabled by the --version-check option.", 1296 (uchar *) &opt_noversioncheck, (uchar *) &opt_noversioncheck, 0, GET_BOOL, 1297 NO_ARG, 0, 0, 0, 0, 0, 0}, 1298 1299 {"no-backup-locks", OPT_NO_BACKUP_LOCKS, 1300 "This option controls if " 1301 "backup locks should be used instead of FLUSH TABLES WITH READ LOCK " 1302 "on the backup stage. The option has no effect when backup locks are " 1303 "not supported by the server. This option is enabled by default, " 1304 "disable with --no-backup-locks.", 1305 (uchar *) &opt_no_backup_locks, (uchar *) &opt_no_backup_locks, 0, 1306 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1307 1308 {"decompress", OPT_DECOMPRESS, 1309 "Decompresses all files with the .qp " 1310 "extension in a backup previously made with the --compress option.", 1311 (uchar *) &opt_decompress, (uchar *) &opt_decompress, 0, GET_BOOL, NO_ARG, 1312 0, 0, 0, 0, 0, 0}, 1313 1314 {"user", 'u', 1315 "This option specifies the MySQL username used " 1316 "when connecting to the server, if that's not the current user. " 1317 "The option accepts a string argument. See mysql --help for details.", 1318 (uchar *) &opt_user, (uchar *) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 1319 0, 0, 0, 0}, 1320 1321 {"host", 'H', 1322 "This option specifies the host to use when " 1323 "connecting to the database server with TCP/IP. The option accepts " 1324 "a string argument. See mysql --help for details.", 1325 (uchar *) &opt_host, (uchar *) &opt_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 1326 0, 0, 0, 0}, 1327 1328 {"port", 'P', 1329 "This option specifies the port to use when " 1330 "connecting to the database server with TCP/IP. The option accepts " 1331 "a string argument. See mysql --help for details.", 1332 &opt_port, &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1333 1334 {"password", 'p', 1335 "This option specifies the password to use " 1336 "when connecting to the database. It accepts a string argument. " 1337 "See mysql --help for details.", 1338 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1339 1340 {"protocol", OPT_PROTOCOL, 1341 "The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0, 1342 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1343 1344 {"socket", 'S', 1345 "This option specifies the socket to use when " 1346 "connecting to the local database server with a UNIX domain socket. " 1347 "The option accepts a string argument. See mysql --help for details.", 1348 (uchar *) &opt_socket, (uchar *) &opt_socket, 0, GET_STR, REQUIRED_ARG, 0, 1349 0, 0, 0, 0, 0}, 1350 1351 {"incremental-history-name", OPT_INCREMENTAL_HISTORY_NAME, 1352 "This option specifies the name of the backup series stored in the " 1353 "PERCONA_SCHEMA.xtrabackup_history history record to base an " 1354 "incremental backup on. Xtrabackup will search the history table " 1355 "looking for the most recent (highest innodb_to_lsn), successful " 1356 "backup in the series and take the to_lsn value to use as the " 1357 "starting lsn for the incremental backup. This will be mutually " 1358 "exclusive with --incremental-history-uuid, --incremental-basedir " 1359 "and --incremental-lsn. If no valid lsn can be found (no series by " 1360 "that name, no successful backups by that name), an error will be returned." 1361 " It is used with the --incremental option.", 1362 (uchar *) &opt_incremental_history_name, 1363 (uchar *) &opt_incremental_history_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 1364 0, 0, 0, 0}, 1365 1366 {"incremental-history-uuid", OPT_INCREMENTAL_HISTORY_UUID, 1367 "This option specifies the UUID of the specific history record " 1368 "stored in the PERCONA_SCHEMA.xtrabackup_history to base an " 1369 "incremental backup on. --incremental-history-name, " 1370 "--incremental-basedir and --incremental-lsn. If no valid lsn can be " 1371 "found (no success record with that uuid), an error will be returned." 1372 " It is used with the --incremental option.", 1373 (uchar *) &opt_incremental_history_uuid, 1374 (uchar *) &opt_incremental_history_uuid, 0, GET_STR, REQUIRED_ARG, 0, 0, 1375 0, 0, 0, 0}, 1376 1377 {"remove-original", OPT_REMOVE_ORIGINAL, 1378 "Remove .qp files after decompression.", (uchar *) &opt_remove_original, 1379 (uchar *) &opt_remove_original, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1380 1381 {"ftwrl-wait-query-type", OPT_LOCK_WAIT_QUERY_TYPE, 1382 "This option specifies which types of queries are allowed to complete " 1383 "before innobackupex will issue the global lock. Default is all.", 1384 (uchar *) &opt_lock_wait_query_type, (uchar *) &opt_lock_wait_query_type, 1385 &query_type_typelib, GET_ENUM, REQUIRED_ARG, QUERY_TYPE_ALL, 0, 0, 0, 0, 1386 0}, 1387 1388 {"kill-long-query-type", OPT_KILL_LONG_QUERY_TYPE, 1389 "This option specifies which types of queries should be killed to " 1390 "unblock the global lock. Default is \"all\".", 1391 (uchar *) &opt_kill_long_query_type, (uchar *) &opt_kill_long_query_type, 1392 &query_type_typelib, GET_ENUM, REQUIRED_ARG, QUERY_TYPE_SELECT, 0, 0, 0, 1393 0, 0}, 1394 1395 {"history", OPT_HISTORY, 1396 "This option enables the tracking of backup history in the " 1397 "PERCONA_SCHEMA.xtrabackup_history table. An optional history " 1398 "series name may be specified that will be placed with the history " 1399 "record for the current backup being taken.", 1400 NULL, NULL, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 1401 1402 {"kill-long-queries-timeout", OPT_KILL_LONG_QUERIES_TIMEOUT, 1403 "This option specifies the number of seconds innobackupex waits " 1404 "between starting FLUSH TABLES WITH READ LOCK and killing those " 1405 "queries that block it. Default is 0 seconds, which means " 1406 "innobackupex will not attempt to kill any queries.", 1407 (uchar *) &opt_kill_long_queries_timeout, 1408 (uchar *) &opt_kill_long_queries_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 1409 0, 0, 0, 0}, 1410 1411 {"ftwrl-wait-timeout", OPT_LOCK_WAIT_TIMEOUT, 1412 "This option specifies time in seconds that innobackupex should wait " 1413 "for queries that would block FTWRL before running it. If there are " 1414 "still such queries when the timeout expires, innobackupex terminates " 1415 "with an error. Default is 0, in which case innobackupex does not " 1416 "wait for queries to complete and starts FTWRL immediately.", 1417 (uchar *) &opt_lock_wait_timeout, (uchar *) &opt_lock_wait_timeout, 0, 1418 GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1419 1420 {"ftwrl-wait-threshold", OPT_LOCK_WAIT_THRESHOLD, 1421 "This option specifies the query run time threshold which is used by " 1422 "innobackupex to detect long-running queries with a non-zero value " 1423 "of --ftwrl-wait-timeout. FTWRL is not started until such " 1424 "long-running queries exist. This option has no effect if " 1425 "--ftwrl-wait-timeout is 0. Default value is 60 seconds.", 1426 (uchar *) &opt_lock_wait_threshold, (uchar *) &opt_lock_wait_threshold, 0, 1427 GET_UINT, REQUIRED_ARG, 60, 0, 0, 0, 0, 0}, 1428 1429 1430 {"safe-slave-backup-timeout", OPT_SAFE_SLAVE_BACKUP_TIMEOUT, 1431 "How many seconds --safe-slave-backup should wait for " 1432 "Slave_open_temp_tables to become zero. (default 300)", 1433 (uchar *) &opt_safe_slave_backup_timeout, 1434 (uchar *) &opt_safe_slave_backup_timeout, 0, GET_UINT, REQUIRED_ARG, 300, 1435 0, 0, 0, 0, 0}, 1436 1437 {"binlog-info", OPT_BINLOG_INFO, 1438 "This option controls how backup should retrieve server's binary log " 1439 "coordinates corresponding to the backup. Possible values are OFF, ON, " 1440 "LOCKLESS and AUTO.", 1441 &opt_binlog_info, &opt_binlog_info, &binlog_info_typelib, GET_ENUM, 1442 OPT_ARG, BINLOG_INFO_AUTO, 0, 0, 0, 0, 0}, 1443 1444 {"secure-auth", OPT_XB_SECURE_AUTH, 1445 "Refuse client connecting to server if it" 1446 " uses old (pre-4.1.1) protocol.", 1447 &opt_secure_auth, &opt_secure_auth, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 1448 0}, 1449 1450 {"log-innodb-page-corruption", OPT_XB_IGNORE_INNODB_PAGE_CORRUPTION, 1451 "Continue backup if innodb corrupted pages are found. The pages are " 1452 "logged in " MB_CORRUPTED_PAGES_FILE 1453 " and backup is finished with error. " 1454 "--prepare will try to fix corrupted pages. If " MB_CORRUPTED_PAGES_FILE 1455 " exists after --prepare in base backup directory, backup still contains " 1456 "corrupted pages and can not be considered as consistent.", 1457 &opt_log_innodb_page_corruption, &opt_log_innodb_page_corruption, 0, 1458 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1459 1460 #define MYSQL_CLIENT 1461 #include "sslopt-longopts.h" 1462 #undef MYSQL_CLIENT 1463 {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}}; 1464 1465 uint xb_client_options_count = array_elements(xb_client_options); 1466 1467 #ifndef DBUG_OFF 1468 /** Parameters to DBUG */ 1469 static const char *dbug_option; 1470 #endif 1471 1472 struct my_option xb_server_options[] = 1473 { 1474 {"datadir", 'h', "Path to the database root.", (G_PTR*) &mysql_data_home, 1475 (G_PTR*) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1476 {"tmpdir", 't', 1477 "Path for temporary files. Several paths may be specified, separated by a " 1478 #if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) 1479 "semicolon (;)" 1480 #else 1481 "colon (:)" 1482 #endif 1483 ", in this case they are used in a round-robin fashion.", 1484 (G_PTR*) &opt_mysql_tmpdir, 1485 (G_PTR*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1486 {"parallel", OPT_XTRA_PARALLEL, 1487 "Number of threads to use for parallel datafiles transfer. " 1488 "The default value is 1.", 1489 (G_PTR*) &xtrabackup_parallel, (G_PTR*) &xtrabackup_parallel, 0, GET_INT, 1490 REQUIRED_ARG, 1, 1, INT_MAX, 0, 0, 0}, 1491 1492 {"extended_validation", OPT_XTRA_EXTENDED_VALIDATION, 1493 "Enable extended validation for Innodb data pages during backup phase. " 1494 "Will slow down backup considerably, in case encryption is used. " 1495 "May fail if tables are created during the backup.", 1496 (G_PTR*)&opt_extended_validation, 1497 (G_PTR*)&opt_extended_validation, 1498 0, GET_BOOL, NO_ARG, FALSE, 0, 0, 0, 0, 0}, 1499 1500 {"encrypted_backup", OPT_XTRA_ENCRYPTED_BACKUP, 1501 "In --backup, assume that nonzero key_version implies that the page" 1502 " is encrypted. Use --backup --skip-encrypted-backup to allow" 1503 " copying unencrypted that were originally created before MySQL 5.1.48.", 1504 (G_PTR*)&opt_encrypted_backup, 1505 (G_PTR*)&opt_encrypted_backup, 1506 0, GET_BOOL, NO_ARG, TRUE, 0, 0, 0, 0, 0}, 1507 1508 {"log", OPT_LOG, "Ignored option for MySQL option compatibility", 1509 (G_PTR*) &log_ignored_opt, (G_PTR*) &log_ignored_opt, 0, 1510 GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 1511 1512 {"log_bin", OPT_LOG, "Base name for the log sequence", 1513 &opt_log_bin, &opt_log_bin, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 1514 1515 {"innodb", OPT_INNODB, "Ignored option for MySQL option compatibility", 1516 (G_PTR*) &innobase_ignored_opt, (G_PTR*) &innobase_ignored_opt, 0, 1517 GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 1518 #ifdef BTR_CUR_HASH_ADAPT 1519 {"innodb_adaptive_hash_index", OPT_INNODB_ADAPTIVE_HASH_INDEX, 1520 "Enable InnoDB adaptive hash index (enabled by default). " 1521 "Disable with --skip-innodb-adaptive-hash-index.", 1522 &btr_search_enabled, 1523 &btr_search_enabled, 1524 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, 1525 #endif /* BTR_CUR_HASH_ADAPT */ 1526 {"innodb_autoextend_increment", OPT_INNODB_AUTOEXTEND_INCREMENT, 1527 "Data file autoextend increment in megabytes", 1528 (G_PTR*) &sys_tablespace_auto_extend_increment, 1529 (G_PTR*) &sys_tablespace_auto_extend_increment, 1530 0, GET_ULONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0}, 1531 {"innodb_data_file_path", OPT_INNODB_DATA_FILE_PATH, 1532 "Path to individual files and their sizes.", &innobase_data_file_path, 1533 &innobase_data_file_path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1534 {"innodb_data_home_dir", OPT_INNODB_DATA_HOME_DIR, 1535 "The common part for InnoDB table spaces.", &innobase_data_home_dir, 1536 &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1537 {"innodb_doublewrite", OPT_INNODB_DOUBLEWRITE, 1538 "Enable InnoDB doublewrite buffer during --prepare.", 1539 (G_PTR*) &innobase_use_doublewrite, 1540 (G_PTR*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1541 {"innodb_io_capacity", OPT_INNODB_IO_CAPACITY, 1542 "Number of IOPs the server can do. Tunes the background IO rate", 1543 (G_PTR*) &srv_io_capacity, (G_PTR*) &srv_io_capacity, 1544 0, GET_ULONG, OPT_ARG, 200, 100, ~0UL, 0, 0, 0}, 1545 {"innodb_file_io_threads", OPT_INNODB_FILE_IO_THREADS, 1546 "Number of file I/O threads in InnoDB.", (G_PTR*) &innobase_file_io_threads, 1547 (G_PTR*) &innobase_file_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 4, 64, 0, 1548 1, 0}, 1549 {"innodb_read_io_threads", OPT_INNODB_READ_IO_THREADS, 1550 "Number of background read I/O threads in InnoDB.", (G_PTR*) &innobase_read_io_threads, 1551 (G_PTR*) &innobase_read_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 1, 64, 0, 1552 1, 0}, 1553 {"innodb_write_io_threads", OPT_INNODB_WRITE_IO_THREADS, 1554 "Number of background write I/O threads in InnoDB.", (G_PTR*) &innobase_write_io_threads, 1555 (G_PTR*) &innobase_write_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 1, 64, 0, 1556 1, 0}, 1557 {"innodb_file_per_table", OPT_INNODB_FILE_PER_TABLE, 1558 "Stores each InnoDB table to an .ibd file in the database dir.", 1559 (G_PTR*) &innobase_file_per_table, 1560 (G_PTR*) &innobase_file_per_table, 0, GET_BOOL, NO_ARG, 1561 FALSE, 0, 0, 0, 0, 0}, 1562 1563 {"innodb_flush_method", OPT_INNODB_FLUSH_METHOD, 1564 "With which method to flush data.", 1565 &srv_file_flush_method, &srv_file_flush_method, 1566 &innodb_flush_method_typelib, GET_ENUM, REQUIRED_ARG, 1567 IF_WIN(SRV_ALL_O_DIRECT_FSYNC, SRV_FSYNC), 0, 0, 0, 0, 0}, 1568 1569 {"innodb_log_buffer_size", OPT_INNODB_LOG_BUFFER_SIZE, 1570 "The size of the buffer which InnoDB uses to write log to the log files on disk.", 1571 (G_PTR*) &srv_log_buffer_size, (G_PTR*) &srv_log_buffer_size, 0, 1572 GET_ULONG, REQUIRED_ARG, 1024*1024L, 256*1024L, LONG_MAX, 0, 1024, 0}, 1573 {"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE, 1574 "Ignored for mysqld option compatibility", 1575 (G_PTR*) &srv_log_file_size, (G_PTR*) &srv_log_file_size, 0, 1576 GET_ULL, REQUIRED_ARG, 48 << 20, 1 << 20, log_group_max_size, 0, 1577 UNIV_PAGE_SIZE_MAX, 0}, 1578 {"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP, 1579 "Ignored for mysqld option compatibility", 1580 &srv_n_log_files, &srv_n_log_files, 1581 0, GET_LONG, REQUIRED_ARG, 1, 1, 100, 0, 1, 0}, 1582 {"innodb_log_group_home_dir", OPT_INNODB_LOG_GROUP_HOME_DIR, 1583 "Path to InnoDB log files.", &srv_log_group_home_dir, 1584 &srv_log_group_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1585 {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT, 1586 "Percentage of dirty pages allowed in bufferpool.", (G_PTR*) &srv_max_buf_pool_modified_pct, 1587 (G_PTR*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0}, 1588 {"innodb_use_native_aio", OPT_INNODB_USE_NATIVE_AIO, 1589 "Use native AIO if supported on this platform.", 1590 (G_PTR*) &srv_use_native_aio, 1591 (G_PTR*) &srv_use_native_aio, 0, GET_BOOL, NO_ARG, 1592 TRUE, 0, 0, 0, 0, 0}, 1593 {"innodb_page_size", OPT_INNODB_PAGE_SIZE, 1594 "The universal page size of the database.", 1595 (G_PTR*) &innobase_page_size, (G_PTR*) &innobase_page_size, 0, 1596 /* Use GET_LL to support numeric suffixes in 5.6 */ 1597 GET_LL, REQUIRED_ARG, 1598 (1LL << 14), (1LL << 12), (1LL << UNIV_PAGE_SIZE_SHIFT_MAX), 0, 1L, 0}, 1599 {"innodb_buffer_pool_filename", OPT_INNODB_BUFFER_POOL_FILENAME, 1600 "Ignored for mysqld option compatibility", 1601 (G_PTR*) &innobase_buffer_pool_filename, 1602 (G_PTR*) &innobase_buffer_pool_filename, 1603 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1604 1605 #ifndef DBUG_OFF /* unfortunately "debug" collides with existing options */ 1606 {"dbug", '#', "Built in DBUG debugger.", 1607 &dbug_option, &dbug_option, 0, GET_STR, OPT_ARG, 1608 0, 0, 0, 0, 0, 0}, 1609 #endif 1610 1611 {"innodb_checksum_algorithm", OPT_INNODB_CHECKSUM_ALGORITHM, 1612 "The algorithm InnoDB uses for page checksumming. [CRC32, STRICT_CRC32, " 1613 "INNODB, STRICT_INNODB, NONE, STRICT_NONE]", &srv_checksum_algorithm, 1614 &srv_checksum_algorithm, &innodb_checksum_algorithm_typelib, GET_ENUM, 1615 REQUIRED_ARG, SRV_CHECKSUM_ALGORITHM_CRC32, 0, 0, 0, 0, 0}, 1616 1617 {"innodb_undo_directory", OPT_INNODB_UNDO_DIRECTORY, 1618 "Directory where undo tablespace files live, this path can be absolute.", 1619 &srv_undo_dir, &srv_undo_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 1620 0}, 1621 1622 {"innodb_undo_tablespaces", OPT_INNODB_UNDO_TABLESPACES, 1623 "Number of undo tablespaces to use.", 1624 (G_PTR*)&srv_undo_tablespaces, (G_PTR*)&srv_undo_tablespaces, 1625 0, GET_ULONG, REQUIRED_ARG, 0, 0, 126, 0, 1, 0}, 1626 1627 {"innodb_compression_level", OPT_INNODB_COMPRESSION_LEVEL, 1628 "Compression level used for zlib compression.", 1629 (G_PTR*)&page_zip_level, (G_PTR*)&page_zip_level, 1630 0, GET_UINT, REQUIRED_ARG, 6, 0, 9, 0, 0, 0}, 1631 1632 {"defaults_group", OPT_DEFAULTS_GROUP, "defaults group in config file (default \"mysqld\").", 1633 (G_PTR*) &defaults_group, (G_PTR*) &defaults_group, 1634 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1635 1636 {"plugin-dir", OPT_PLUGIN_DIR, 1637 "Server plugin directory. Used to load encryption plugin during 'prepare' phase." 1638 "Has no effect in the 'backup' phase (plugin directory during backup is the same as server's)", 1639 &xb_plugin_dir, &xb_plugin_dir, 1640 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 1641 1642 {"innodb-log-checksums", OPT_INNODB_LOG_CHECKSUMS, 1643 "Whether to require checksums for InnoDB redo log blocks", 1644 &innodb_log_checksums, &innodb_log_checksums, 1645 0, GET_BOOL, REQUIRED_ARG, 1, 0, 0, 0, 0, 0 }, 1646 1647 {"open_files_limit", OPT_OPEN_FILES_LIMIT, "the maximum number of file " 1648 "descriptors to reserve with setrlimit().", 1649 (G_PTR*) &xb_open_files_limit, (G_PTR*) &xb_open_files_limit, 0, GET_ULONG, 1650 REQUIRED_ARG, 0, 0, UINT_MAX, 0, 1, 0}, 1651 1652 {"lock-ddl-per-table", OPT_LOCK_DDL_PER_TABLE, "Lock DDL for each table " 1653 "before backup starts to copy it and until the backup is completed.", 1654 (uchar*) &opt_lock_ddl_per_table, (uchar*) &opt_lock_ddl_per_table, 0, 1655 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1656 1657 {"rocksdb-datadir", OPT_ROCKSDB_DATADIR, "RocksDB data directory." 1658 "This option is only used with --copy-back or --move-back option", 1659 &xb_rocksdb_datadir, &xb_rocksdb_datadir, 1660 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 1661 1662 { "rocksdb-backup", OPT_BACKUP_ROCKSDB, "Backup rocksdb data, if rocksdb plugin is installed." 1663 "Used only with --backup option. Can be useful for partial backups, to exclude all rocksdb data", 1664 &xb_backup_rocksdb, &xb_backup_rocksdb, 1665 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, 1666 1667 {"check-privileges", OPT_XTRA_CHECK_PRIVILEGES, "Check database user " 1668 "privileges fro the backup user", 1669 &opt_check_privileges, &opt_check_privileges, 1670 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, 1671 1672 {"innodb_force_recovery", OPT_INNODB_FORCE_RECOVERY, 1673 "(for --prepare): Crash recovery mode (ignores " 1674 "page corruption; for emergencies only).", 1675 (G_PTR*)&srv_force_recovery, 1676 (G_PTR*)&srv_force_recovery, 1677 0, GET_ULONG, OPT_ARG, 0, 0, SRV_FORCE_IGNORE_CORRUPT, 0, 0, 0}, 1678 1679 {"mysqld-args", OPT_XTRA_MYSQLD_ARGS, 1680 "All arguments that follow this argument are considered as server " 1681 "options, and if some of them are not supported by mariabackup, they " 1682 "will be ignored.", 1683 (G_PTR *) &xtrabackup_mysqld_args, (G_PTR *) &xtrabackup_mysqld_args, 0, 1684 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1685 1686 {"help", '?', 1687 "Display this help and exit.", 1688 (G_PTR *) &xtrabackup_help, (G_PTR *) &xtrabackup_help, 0, 1689 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1690 1691 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} 1692 }; 1693 1694 uint xb_server_options_count = array_elements(xb_server_options); 1695 1696 1697 static std::set<std::string> tables_for_export; 1698 1699 static void append_export_table(const char *dbname, const char *tablename, 1700 bool is_remote, bool set_size) 1701 { 1702 if(dbname && tablename && !is_remote) 1703 { 1704 char buf[3*FN_REFLEN]; 1705 snprintf(buf,sizeof(buf),"%s/%s",dbname, tablename); 1706 // trim .ibd 1707 char *p=strrchr(buf, '.'); 1708 if (p) *p=0; 1709 1710 std::string name=ut_get_name(0, buf); 1711 /* Strip partition name comment from table name, if any */ 1712 if (ends_with(name.c_str(), "*/")) 1713 { 1714 size_t pos= name.rfind("/*"); 1715 if (pos != std::string::npos) 1716 name.resize(pos); 1717 } 1718 tables_for_export.insert(name); 1719 } 1720 } 1721 1722 1723 #define BOOTSTRAP_FILENAME "mariabackup_prepare_for_export.sql" 1724 1725 static int create_bootstrap_file() 1726 { 1727 FILE *f= fopen(BOOTSTRAP_FILENAME,"wb"); 1728 if(!f) 1729 return -1; 1730 1731 fputs("SET NAMES UTF8;\n",f); 1732 enumerate_ibd_files(append_export_table); 1733 for (std::set<std::string>::iterator it = tables_for_export.begin(); 1734 it != tables_for_export.end(); it++) 1735 { 1736 const char *tab = it->c_str(); 1737 fprintf(f, 1738 "BEGIN NOT ATOMIC " 1739 "DECLARE CONTINUE HANDLER FOR NOT FOUND,SQLEXCEPTION BEGIN END;" 1740 "FLUSH TABLES %s FOR EXPORT;" 1741 "END;\n" 1742 "UNLOCK TABLES;\n", 1743 tab); 1744 } 1745 fclose(f); 1746 return 0; 1747 } 1748 1749 static int prepare_export() 1750 { 1751 int err= -1; 1752 1753 char cmdline[2*FN_REFLEN]; 1754 FILE *outf; 1755 1756 if (create_bootstrap_file()) 1757 return -1; 1758 1759 // Process defaults-file , it can have some --lc-language stuff, 1760 // which is* unfortunately* still necessary to get mysqld up 1761 if (strncmp(orig_argv1,"--defaults-file=", 16) == 0) 1762 { 1763 snprintf(cmdline, sizeof cmdline, 1764 IF_WIN("\"","") "\"%s\" --mysqld \"%s\"" 1765 " --defaults-extra-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." 1766 " --innodb --innodb-fast-shutdown=0 --loose-partition" 1767 " --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu" 1768 " --console --skip-log-error --skip-log-bin --bootstrap %s< " 1769 BOOTSTRAP_FILENAME IF_WIN("\"",""), 1770 mariabackup_exe, 1771 orig_argv1, (my_defaults_group_suffix?my_defaults_group_suffix:""), 1772 xtrabackup_use_memory, 1773 (srv_force_recovery ? "--innodb-force-recovery=1 " : "")); 1774 } 1775 else 1776 { 1777 snprintf(cmdline, sizeof cmdline, 1778 IF_WIN("\"","") "\"%s\" --mysqld" 1779 " --defaults-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." 1780 " --innodb --innodb-fast-shutdown=0 --loose-partition" 1781 " --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu" 1782 " --console --log-error= --skip-log-bin --bootstrap %s< " 1783 BOOTSTRAP_FILENAME IF_WIN("\"",""), 1784 mariabackup_exe, 1785 (my_defaults_group_suffix?my_defaults_group_suffix:""), 1786 xtrabackup_use_memory, 1787 (srv_force_recovery ? "--innodb-force-recovery=1 " : "")); 1788 } 1789 1790 msg("Prepare export : executing %s\n", cmdline); 1791 fflush(stderr); 1792 1793 outf= popen(cmdline,"r"); 1794 if (!outf) 1795 goto end; 1796 1797 char outline[FN_REFLEN]; 1798 while(fgets(outline, sizeof(outline)-1, outf)) 1799 fprintf(stderr,"%s",outline); 1800 1801 err = pclose(outf); 1802 end: 1803 unlink(BOOTSTRAP_FILENAME); 1804 return err; 1805 } 1806 1807 static const char *xb_client_default_groups[]= { 1808 "client", "client-server", "client-mariadb", 0, 0, 0}; 1809 1810 static const char *backup_default_groups[]= { 1811 "xtrabackup", "mariabackup", "mariadb-backup", 0, 0, 0}; 1812 1813 static void print_version(void) 1814 { 1815 fprintf(stderr, "%s based on MariaDB server %s %s (%s)\n", 1816 my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); 1817 } 1818 1819 static void usage(void) 1820 { 1821 puts("Open source backup tool for InnoDB and XtraDB\n\ 1822 \n\ 1823 Copyright (C) 2009-2015 Percona LLC and/or its affiliates.\n\ 1824 Portions Copyright (C) 2000, 2011, MySQL AB & Innobase Oy. All Rights Reserved.\n\ 1825 \n\ 1826 This program is free software; you can redistribute it and/or\n\ 1827 modify it under the terms of the GNU General Public License\n\ 1828 as published by the Free Software Foundation version 2\n\ 1829 of the License.\n\ 1830 \n\ 1831 This program is distributed in the hope that it will be useful,\n\ 1832 but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ 1833 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ 1834 GNU General Public License for more details.\n\ 1835 \n\ 1836 You can download full text of the license on http://www.gnu.org/licenses/gpl-2.0.txt\n"); 1837 1838 printf("Usage: %s [--defaults-file=#] [--backup | --prepare | --copy-back | --move-back] [OPTIONS]\n",my_progname); 1839 print_defaults("my", load_default_groups); 1840 my_print_help(xb_client_options); 1841 my_print_help(xb_server_options); 1842 my_print_variables(xb_server_options); 1843 my_print_variables(xb_client_options); 1844 } 1845 1846 #define ADD_PRINT_PARAM_OPT(value) \ 1847 { \ 1848 print_param_str << opt->name << "=" << value << "\n"; \ 1849 param_set.insert(opt->name); \ 1850 } 1851 1852 /************************************************************************ 1853 Check if parameter is set in defaults file or via command line argument 1854 @return true if parameter is set. */ 1855 bool 1856 check_if_param_set(const char *param) 1857 { 1858 return param_set.find(param) != param_set.end(); 1859 } 1860 1861 my_bool 1862 xb_get_one_option(int optid, 1863 const struct my_option *opt __attribute__((unused)), 1864 char *argument) 1865 { 1866 switch(optid) { 1867 case 'h': 1868 strmake(mysql_real_data_home,argument, FN_REFLEN - 1); 1869 mysql_data_home= mysql_real_data_home; 1870 1871 ADD_PRINT_PARAM_OPT(mysql_real_data_home); 1872 break; 1873 1874 case 't': 1875 1876 ADD_PRINT_PARAM_OPT(opt_mysql_tmpdir); 1877 break; 1878 1879 case OPT_INNODB_DATA_HOME_DIR: 1880 1881 ADD_PRINT_PARAM_OPT(innobase_data_home_dir); 1882 break; 1883 1884 case OPT_INNODB_DATA_FILE_PATH: 1885 1886 ADD_PRINT_PARAM_OPT(innobase_data_file_path); 1887 break; 1888 1889 case OPT_INNODB_LOG_GROUP_HOME_DIR: 1890 1891 ADD_PRINT_PARAM_OPT(srv_log_group_home_dir); 1892 break; 1893 1894 case OPT_INNODB_LOG_FILES_IN_GROUP: 1895 case OPT_INNODB_LOG_FILE_SIZE: 1896 break; 1897 1898 case OPT_INNODB_FLUSH_METHOD: 1899 ut_a(srv_file_flush_method 1900 <= IF_WIN(SRV_ALL_O_DIRECT_FSYNC, SRV_O_DIRECT_NO_FSYNC)); 1901 ADD_PRINT_PARAM_OPT(innodb_flush_method_names[srv_file_flush_method]); 1902 break; 1903 1904 case OPT_INNODB_PAGE_SIZE: 1905 1906 ADD_PRINT_PARAM_OPT(innobase_page_size); 1907 break; 1908 1909 case OPT_INNODB_UNDO_DIRECTORY: 1910 1911 ADD_PRINT_PARAM_OPT(srv_undo_dir); 1912 break; 1913 1914 case OPT_INNODB_UNDO_TABLESPACES: 1915 1916 ADD_PRINT_PARAM_OPT(srv_undo_tablespaces); 1917 break; 1918 1919 case OPT_INNODB_CHECKSUM_ALGORITHM: 1920 1921 ut_a(srv_checksum_algorithm <= SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32); 1922 1923 ADD_PRINT_PARAM_OPT(innodb_checksum_algorithm_names[srv_checksum_algorithm]); 1924 break; 1925 1926 case OPT_INNODB_COMPRESSION_LEVEL: 1927 ADD_PRINT_PARAM_OPT(page_zip_level); 1928 break; 1929 1930 case OPT_INNODB_BUFFER_POOL_FILENAME: 1931 1932 ADD_PRINT_PARAM_OPT(innobase_buffer_pool_filename); 1933 break; 1934 1935 case OPT_INNODB_FORCE_RECOVERY: 1936 1937 if (srv_force_recovery) { 1938 ADD_PRINT_PARAM_OPT(srv_force_recovery); 1939 } 1940 break; 1941 1942 case OPT_XTRA_TARGET_DIR: 1943 strmake(xtrabackup_real_target_dir,argument, sizeof(xtrabackup_real_target_dir)-1); 1944 xtrabackup_target_dir= xtrabackup_real_target_dir; 1945 break; 1946 case OPT_XTRA_STREAM: 1947 if (!strcasecmp(argument, "mbstream") || 1948 !strcasecmp(argument, "xbstream")) 1949 xtrabackup_stream_fmt = XB_STREAM_FMT_XBSTREAM; 1950 else 1951 { 1952 msg("Invalid --stream argument: %s", argument); 1953 return 1; 1954 } 1955 xtrabackup_stream = TRUE; 1956 break; 1957 case OPT_XTRA_COMPRESS: 1958 if (argument == NULL) 1959 xtrabackup_compress_alg = "quicklz"; 1960 else if (strcasecmp(argument, "quicklz")) 1961 { 1962 msg("Invalid --compress argument: %s", argument); 1963 return 1; 1964 } 1965 xtrabackup_compress = TRUE; 1966 break; 1967 case OPT_DECOMPRESS: 1968 opt_decompress = TRUE; 1969 xtrabackup_decrypt_decompress = true; 1970 break; 1971 case (int) OPT_CORE_FILE: 1972 test_flags |= TEST_CORE_ON_SIGNAL; 1973 break; 1974 case OPT_HISTORY: 1975 if (argument) { 1976 opt_history = argument; 1977 } else { 1978 opt_history = ""; 1979 } 1980 break; 1981 case 'p': 1982 opt_password = argument; 1983 break; 1984 case OPT_PROTOCOL: 1985 if (argument) 1986 { 1987 if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib, 1988 opt->name)) <= 0) 1989 { 1990 sf_leaking_memory= 1; /* no memory leak reports here */ 1991 exit(1); 1992 } 1993 } 1994 break; 1995 #define MYSQL_CLIENT 1996 #include "sslopt-case.h" 1997 #undef MYSQL_CLIENT 1998 1999 case '?': 2000 usage(); 2001 exit(EXIT_SUCCESS); 2002 break; 2003 case 'v': 2004 print_version(); 2005 exit(EXIT_SUCCESS); 2006 break; 2007 default: 2008 break; 2009 } 2010 return 0; 2011 } 2012 2013 static bool innodb_init_param() 2014 { 2015 srv_is_being_started = TRUE; 2016 /* === some variables from mysqld === */ 2017 memset((G_PTR) &mysql_tmpdir_list, 0, sizeof(mysql_tmpdir_list)); 2018 2019 if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) { 2020 msg("init_tmpdir() failed"); 2021 return true; 2022 } 2023 xtrabackup_tmpdir = my_tmpdir(&mysql_tmpdir_list); 2024 /* dummy for initialize all_charsets[] */ 2025 get_charset_name(0); 2026 2027 srv_page_size = 0; 2028 srv_page_size_shift = 0; 2029 #ifdef BTR_CUR_HASH_ADAPT 2030 btr_ahi_parts = 1; 2031 #endif /* BTR_CUR_HASH_ADAPT */ 2032 2033 if (innobase_page_size != (1LL << 14)) { 2034 size_t n_shift = get_bit_shift(size_t(innobase_page_size)); 2035 2036 if (n_shift >= 12 && n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX) { 2037 srv_page_size_shift = ulong(n_shift); 2038 srv_page_size = 1U << n_shift; 2039 msg("InnoDB: The universal page size of the " 2040 "database is set to %lu.", srv_page_size); 2041 } else { 2042 msg("invalid value of " 2043 "innobase_page_size: %lld", innobase_page_size); 2044 goto error; 2045 } 2046 } else { 2047 srv_page_size_shift = 14; 2048 srv_page_size = 1U << 14; 2049 } 2050 2051 /* Check that values don't overflow on 32-bit systems. */ 2052 if (sizeof(ulint) == 4) { 2053 if (xtrabackup_use_memory > UINT_MAX32) { 2054 msg("mariabackup: use-memory can't be over 4GB" 2055 " on 32-bit systems"); 2056 } 2057 } 2058 2059 static char default_path[2] = { FN_CURLIB, 0 }; 2060 fil_path_to_mysql_datadir = default_path; 2061 2062 /* Set InnoDB initialization parameters according to the values 2063 read from MySQL .cnf file */ 2064 2065 if (xtrabackup_backup) { 2066 msg("mariabackup: using the following InnoDB configuration:"); 2067 } else { 2068 msg("mariabackup: using the following InnoDB configuration " 2069 "for recovery:"); 2070 } 2071 2072 /*--------------- Data files -------------------------*/ 2073 2074 /* The default dir for data files is the datadir of MySQL */ 2075 2076 srv_data_home = (xtrabackup_backup && innobase_data_home_dir 2077 ? innobase_data_home_dir : default_path); 2078 msg("innodb_data_home_dir = %s", srv_data_home); 2079 2080 /* Set default InnoDB data file size to 10 MB and let it be 2081 auto-extending. Thus users can use InnoDB in >= 4.0 without having 2082 to specify any startup options. */ 2083 2084 if (!innobase_data_file_path) { 2085 innobase_data_file_path = (char*) "ibdata1:10M:autoextend"; 2086 } 2087 msg("innodb_data_file_path = %s", 2088 innobase_data_file_path); 2089 2090 srv_sys_space.set_space_id(TRX_SYS_SPACE); 2091 srv_sys_space.set_name("innodb_system"); 2092 srv_sys_space.set_path(srv_data_home); 2093 switch (srv_checksum_algorithm) { 2094 case SRV_CHECKSUM_ALGORITHM_FULL_CRC32: 2095 case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32: 2096 srv_sys_space.set_flags(FSP_FLAGS_FCRC32_MASK_MARKER 2097 | FSP_FLAGS_FCRC32_PAGE_SSIZE()); 2098 break; 2099 default: 2100 srv_sys_space.set_flags(FSP_FLAGS_PAGE_SSIZE()); 2101 } 2102 2103 if (!srv_sys_space.parse_params(innobase_data_file_path, true)) { 2104 goto error; 2105 } 2106 2107 srv_sys_space.normalize_size(); 2108 srv_lock_table_size = 5 * (srv_buf_pool_size >> srv_page_size_shift); 2109 2110 /* -------------- Log files ---------------------------*/ 2111 2112 /* The default dir for log files is the datadir of MySQL */ 2113 2114 if (!(xtrabackup_backup && srv_log_group_home_dir)) { 2115 srv_log_group_home_dir = default_path; 2116 } 2117 if (xtrabackup_prepare && xtrabackup_incremental_dir) { 2118 srv_log_group_home_dir = xtrabackup_incremental_dir; 2119 } 2120 msg("innodb_log_group_home_dir = %s", 2121 srv_log_group_home_dir); 2122 2123 os_normalize_path(srv_log_group_home_dir); 2124 2125 if (strchr(srv_log_group_home_dir, ';')) { 2126 msg("syntax error in innodb_log_group_home_dir, "); 2127 goto error; 2128 } 2129 2130 srv_adaptive_flushing = FALSE; 2131 2132 /* We set srv_pool_size here in units of 1 kB. InnoDB internally 2133 changes the value so that it becomes the number of database pages. */ 2134 2135 srv_buf_pool_size = (ulint) xtrabackup_use_memory; 2136 srv_buf_pool_chunk_unit = (ulong)srv_buf_pool_size; 2137 srv_buf_pool_instances = 1; 2138 srv_n_page_cleaners = 1; 2139 2140 srv_n_file_io_threads = (ulint) innobase_file_io_threads; 2141 srv_n_read_io_threads = (ulint) innobase_read_io_threads; 2142 srv_n_write_io_threads = (ulint) innobase_write_io_threads; 2143 2144 srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite; 2145 2146 row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout; 2147 2148 srv_file_per_table = (my_bool) innobase_file_per_table; 2149 2150 srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog; 2151 2152 srv_max_n_open_files = ULINT_UNDEFINED - 5; 2153 srv_innodb_status = (ibool) innobase_create_status_file; 2154 2155 srv_print_verbose_log = verbose ? 2 : 1; 2156 2157 /* Store the default charset-collation number of this MySQL 2158 installation */ 2159 2160 /* We cannot treat characterset here for now!! */ 2161 data_mysql_default_charset_coll = (ulint)default_charset_info->number; 2162 2163 ut_ad(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number); 2164 2165 #ifdef _WIN32 2166 srv_use_native_aio = TRUE; 2167 2168 #elif defined(LINUX_NATIVE_AIO) 2169 2170 if (srv_use_native_aio) { 2171 msg("InnoDB: Using Linux native AIO"); 2172 } 2173 #else 2174 /* Currently native AIO is supported only on windows and linux 2175 and that also when the support is compiled in. In all other 2176 cases, we ignore the setting of innodb_use_native_aio. */ 2177 srv_use_native_aio = FALSE; 2178 2179 #endif 2180 2181 /* Assign the default value to srv_undo_dir if it's not specified, as 2182 my_getopt does not support default values for string options. We also 2183 ignore the option and override innodb_undo_directory on --prepare, 2184 because separate undo tablespaces are copied to the root backup 2185 directory. */ 2186 2187 if (!srv_undo_dir || !xtrabackup_backup) { 2188 srv_undo_dir = (char*) "."; 2189 } 2190 2191 compile_time_assert(SRV_FORCE_IGNORE_CORRUPT == 1); 2192 2193 /* 2194 * This option can be read both from the command line, and the 2195 * defaults file. The assignment should account for both cases, 2196 * and for "--innobackupex". Since the command line argument is 2197 * parsed after the defaults file, it takes precedence. 2198 */ 2199 if (xtrabackup_innodb_force_recovery) { 2200 srv_force_recovery = xtrabackup_innodb_force_recovery; 2201 } 2202 2203 if (srv_force_recovery >= SRV_FORCE_IGNORE_CORRUPT) { 2204 if (!xtrabackup_prepare) { 2205 msg("mariabackup: The option \"innodb_force_recovery\"" 2206 " should only be used with \"%s\".", 2207 (innobackupex_mode ? "--apply-log" : "--prepare")); 2208 goto error; 2209 } else { 2210 msg("innodb_force_recovery = %lu", srv_force_recovery); 2211 } 2212 } 2213 2214 #ifdef _WIN32 2215 srv_use_native_aio = TRUE; 2216 #endif 2217 return false; 2218 2219 error: 2220 msg("mariabackup: innodb_init_param(): Error occurred.\n"); 2221 return true; 2222 } 2223 2224 static bool innodb_init() 2225 { 2226 bool create_new_db = false; 2227 /* Check if the data files exist or not. */ 2228 dberr_t err = srv_sys_space.check_file_spec(&create_new_db, 5U << 20); 2229 2230 if (err == DB_SUCCESS) { 2231 err = srv_start(create_new_db); 2232 } 2233 2234 if (err != DB_SUCCESS) { 2235 die("mariabackup: innodb_init() returned %d (%s).", 2236 err, ut_strerr(err)); 2237 } 2238 2239 return(FALSE); 2240 } 2241 2242 /* ================= common ================= */ 2243 2244 /*********************************************************************** 2245 Read backup meta info. 2246 @return TRUE on success, FALSE on failure. */ 2247 static 2248 my_bool 2249 xtrabackup_read_metadata(char *filename) 2250 { 2251 FILE *fp; 2252 my_bool r = TRUE; 2253 2254 fp = fopen(filename,"r"); 2255 if(!fp) { 2256 msg("Error: cannot open %s", filename); 2257 return(FALSE); 2258 } 2259 2260 if (fscanf(fp, "backup_type = %29s\n", metadata_type) 2261 != 1) { 2262 r = FALSE; 2263 goto end; 2264 } 2265 /* Use UINT64PF instead of LSN_PF here, as we have to maintain the file 2266 format. */ 2267 if (fscanf(fp, "from_lsn = " UINT64PF "\n", &metadata_from_lsn) 2268 != 1) { 2269 r = FALSE; 2270 goto end; 2271 } 2272 if (fscanf(fp, "to_lsn = " UINT64PF "\n", &metadata_to_lsn) 2273 != 1) { 2274 r = FALSE; 2275 goto end; 2276 } 2277 if (fscanf(fp, "last_lsn = " UINT64PF "\n", &metadata_last_lsn) 2278 != 1) { 2279 metadata_last_lsn = 0; 2280 } 2281 /* Optional fields */ 2282 2283 end: 2284 fclose(fp); 2285 2286 return(r); 2287 } 2288 2289 /*********************************************************************** 2290 Print backup meta info to a specified buffer. */ 2291 static 2292 void 2293 xtrabackup_print_metadata(char *buf, size_t buf_len) 2294 { 2295 /* Use UINT64PF instead of LSN_PF here, as we have to maintain the file 2296 format. */ 2297 snprintf(buf, buf_len, 2298 "backup_type = %s\n" 2299 "from_lsn = " UINT64PF "\n" 2300 "to_lsn = " UINT64PF "\n" 2301 "last_lsn = " UINT64PF "\n", 2302 metadata_type, 2303 metadata_from_lsn, 2304 metadata_to_lsn, 2305 metadata_last_lsn); 2306 } 2307 2308 /*********************************************************************** 2309 Stream backup meta info to a specified datasink. 2310 @return TRUE on success, FALSE on failure. */ 2311 static 2312 my_bool 2313 xtrabackup_stream_metadata(ds_ctxt_t *ds_ctxt) 2314 { 2315 char buf[1024]; 2316 size_t len; 2317 ds_file_t *stream; 2318 MY_STAT mystat; 2319 my_bool rc = TRUE; 2320 2321 xtrabackup_print_metadata(buf, sizeof(buf)); 2322 2323 len = strlen(buf); 2324 2325 mystat.st_size = len; 2326 mystat.st_mtime = my_time(0); 2327 2328 stream = ds_open(ds_ctxt, XTRABACKUP_METADATA_FILENAME, &mystat); 2329 if (stream == NULL) { 2330 msg("Error: cannot open output stream for %s", XTRABACKUP_METADATA_FILENAME); 2331 return(FALSE); 2332 } 2333 2334 if (ds_write(stream, buf, len)) { 2335 rc = FALSE; 2336 } 2337 2338 if (ds_close(stream)) { 2339 rc = FALSE; 2340 } 2341 2342 return(rc); 2343 } 2344 2345 /*********************************************************************** 2346 Write backup meta info to a specified file. 2347 @return TRUE on success, FALSE on failure. */ 2348 static 2349 my_bool 2350 xtrabackup_write_metadata(const char *filepath) 2351 { 2352 char buf[1024]; 2353 size_t len; 2354 FILE *fp; 2355 2356 xtrabackup_print_metadata(buf, sizeof(buf)); 2357 2358 len = strlen(buf); 2359 2360 fp = fopen(filepath, "w"); 2361 if(!fp) { 2362 msg("Error: cannot open %s", filepath); 2363 return(FALSE); 2364 } 2365 if (fwrite(buf, len, 1, fp) < 1) { 2366 fclose(fp); 2367 return(FALSE); 2368 } 2369 2370 fclose(fp); 2371 2372 return(TRUE); 2373 } 2374 2375 /*********************************************************************** 2376 Read meta info for an incremental delta. 2377 @return TRUE on success, FALSE on failure. */ 2378 static my_bool 2379 xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info) 2380 { 2381 FILE* fp; 2382 char key[51]; 2383 char value[51]; 2384 my_bool r = TRUE; 2385 2386 /* set defaults */ 2387 ulint page_size = ULINT_UNDEFINED, zip_size = 0; 2388 info->space_id = ULINT_UNDEFINED; 2389 2390 fp = fopen(filepath, "r"); 2391 if (!fp) { 2392 /* Meta files for incremental deltas are optional */ 2393 return(TRUE); 2394 } 2395 2396 while (!feof(fp)) { 2397 if (fscanf(fp, "%50s = %50s\n", key, value) == 2) { 2398 if (strcmp(key, "page_size") == 0) { 2399 page_size = strtoul(value, NULL, 10); 2400 } else if (strcmp(key, "zip_size") == 0) { 2401 zip_size = strtoul(value, NULL, 10); 2402 } else if (strcmp(key, "space_id") == 0) { 2403 info->space_id = strtoul(value, NULL, 10); 2404 } 2405 } 2406 } 2407 2408 fclose(fp); 2409 2410 if (page_size == ULINT_UNDEFINED) { 2411 msg("page_size is required in %s", filepath); 2412 r = FALSE; 2413 } else { 2414 info->page_size = zip_size ? zip_size : page_size; 2415 } 2416 2417 if (info->space_id == ULINT_UNDEFINED) { 2418 msg("mariabackup: Warning: This backup was taken with XtraBackup 2.0.1 " 2419 "or earlier, some DDL operations between full and incremental " 2420 "backups may be handled incorrectly"); 2421 } 2422 2423 return(r); 2424 } 2425 2426 /*********************************************************************** 2427 Write meta info for an incremental delta. 2428 @return TRUE on success, FALSE on failure. */ 2429 my_bool 2430 xb_write_delta_metadata(const char *filename, const xb_delta_info_t *info) 2431 { 2432 ds_file_t *f; 2433 char buf[64]; 2434 my_bool ret; 2435 size_t len; 2436 MY_STAT mystat; 2437 2438 snprintf(buf, sizeof(buf), 2439 "page_size = " ULINTPF "\n" 2440 "zip_size = " ULINTPF " \n" 2441 "space_id = " ULINTPF "\n", 2442 info->page_size, 2443 info->zip_size, 2444 info->space_id); 2445 len = strlen(buf); 2446 2447 mystat.st_size = len; 2448 mystat.st_mtime = my_time(0); 2449 2450 f = ds_open(ds_meta, filename, &mystat); 2451 if (f == NULL) { 2452 msg("Error: Can't open output stream for %s",filename); 2453 return(FALSE); 2454 } 2455 2456 ret = (ds_write(f, buf, len) == 0); 2457 2458 if (ds_close(f)) { 2459 ret = FALSE; 2460 } 2461 2462 return(ret); 2463 } 2464 2465 /* ================= backup ================= */ 2466 void 2467 xtrabackup_io_throttling(void) 2468 { 2469 if (xtrabackup_backup && xtrabackup_throttle && (io_ticket--) < 0) { 2470 os_event_reset(wait_throttle); 2471 os_event_wait(wait_throttle); 2472 } 2473 } 2474 2475 static 2476 my_bool regex_list_check_match( 2477 const regex_list_t& list, 2478 const char* name) 2479 { 2480 regmatch_t tables_regmatch[1]; 2481 for (regex_list_t::const_iterator i = list.begin(), end = list.end(); 2482 i != end; ++i) { 2483 const regex_t& regex = *i; 2484 int regres = regexec(®ex, name, 1, tables_regmatch, 0); 2485 2486 if (regres != REG_NOMATCH) { 2487 return(TRUE); 2488 } 2489 } 2490 return(FALSE); 2491 } 2492 2493 static 2494 my_bool 2495 find_filter_in_hashtable( 2496 const char* name, 2497 hash_table_t* table, 2498 xb_filter_entry_t** result 2499 ) 2500 { 2501 xb_filter_entry_t* found = NULL; 2502 HASH_SEARCH(name_hash, table, ut_fold_string(name), 2503 xb_filter_entry_t*, 2504 found, (void) 0, 2505 !strcmp(found->name, name)); 2506 2507 if (found && result) { 2508 *result = found; 2509 } 2510 return (found != NULL); 2511 } 2512 2513 /************************************************************************ 2514 Checks if a given table name matches any of specifications given in 2515 regex_list or tables_hash. 2516 2517 @return TRUE on match or both regex_list and tables_hash are empty.*/ 2518 static my_bool 2519 check_if_table_matches_filters(const char *name, 2520 const regex_list_t& regex_list, 2521 hash_table_t* tables_hash) 2522 { 2523 if (regex_list.empty() && !tables_hash) { 2524 return(FALSE); 2525 } 2526 2527 if (regex_list_check_match(regex_list, name)) { 2528 return(TRUE); 2529 } 2530 2531 if (tables_hash && find_filter_in_hashtable(name, tables_hash, NULL)) { 2532 return(TRUE); 2533 } 2534 2535 return FALSE; 2536 } 2537 2538 enum skip_database_check_result { 2539 DATABASE_SKIP, 2540 DATABASE_SKIP_SOME_TABLES, 2541 DATABASE_DONT_SKIP, 2542 DATABASE_DONT_SKIP_UNLESS_EXPLICITLY_EXCLUDED, 2543 }; 2544 2545 /************************************************************************ 2546 Checks if a database specified by name should be skipped from backup based on 2547 the --databases, --databases_file or --databases_exclude options. 2548 2549 @return TRUE if entire database should be skipped, 2550 FALSE otherwise. 2551 */ 2552 static 2553 skip_database_check_result 2554 check_if_skip_database( 2555 const char* name /*!< in: path to the database */ 2556 ) 2557 { 2558 /* There are some filters for databases, check them */ 2559 xb_filter_entry_t* database = NULL; 2560 2561 if (databases_exclude_hash && 2562 find_filter_in_hashtable(name, databases_exclude_hash, 2563 &database) && 2564 (!database->has_tables || !databases_include_hash)) { 2565 /* Database is found and there are no tables specified, 2566 skip entire db. */ 2567 return DATABASE_SKIP; 2568 } 2569 2570 if (databases_include_hash) { 2571 if (!find_filter_in_hashtable(name, databases_include_hash, 2572 &database)) { 2573 /* Database isn't found, skip the database */ 2574 return DATABASE_SKIP; 2575 } else if (database->has_tables) { 2576 return DATABASE_SKIP_SOME_TABLES; 2577 } else { 2578 return DATABASE_DONT_SKIP_UNLESS_EXPLICITLY_EXCLUDED; 2579 } 2580 } 2581 2582 return DATABASE_DONT_SKIP; 2583 } 2584 2585 /************************************************************************ 2586 Checks if a database specified by path should be skipped from backup based on 2587 the --databases, --databases_file or --databases_exclude options. 2588 2589 @return TRUE if the table should be skipped. */ 2590 my_bool 2591 check_if_skip_database_by_path( 2592 const char* path /*!< in: path to the db directory. */ 2593 ) 2594 { 2595 if (databases_include_hash == NULL && 2596 databases_exclude_hash == NULL) { 2597 return(FALSE); 2598 } 2599 2600 const char* db_name = strrchr(path, OS_PATH_SEPARATOR); 2601 if (db_name == NULL) { 2602 db_name = path; 2603 } else { 2604 ++db_name; 2605 } 2606 2607 return check_if_skip_database(db_name) == DATABASE_SKIP; 2608 } 2609 2610 /************************************************************************ 2611 Checks if a table specified as a name in the form "database/name" (InnoDB 5.6) 2612 or "./database/name.ibd" (InnoDB 5.5-) should be skipped from backup based on 2613 the --tables or --tables-file options. 2614 2615 @return TRUE if the table should be skipped. */ 2616 my_bool 2617 check_if_skip_table( 2618 /******************/ 2619 const char* name) /*!< in: path to the table */ 2620 { 2621 char buf[FN_REFLEN]; 2622 const char *dbname, *tbname; 2623 const char *ptr; 2624 char *eptr; 2625 2626 2627 dbname = NULL; 2628 tbname = name; 2629 while ((ptr = strchr(tbname, '/')) != NULL) { 2630 dbname = tbname; 2631 tbname = ptr + 1; 2632 } 2633 2634 if (strncmp(tbname, tmp_file_prefix, tmp_file_prefix_length) == 0) { 2635 return TRUE; 2636 } 2637 2638 if (regex_exclude_list.empty() && 2639 regex_include_list.empty() && 2640 tables_include_hash == NULL && 2641 tables_exclude_hash == NULL && 2642 databases_include_hash == NULL && 2643 databases_exclude_hash == NULL) { 2644 return(FALSE); 2645 } 2646 2647 if (dbname == NULL) { 2648 return(FALSE); 2649 } 2650 2651 strncpy(buf, dbname, FN_REFLEN - 1); 2652 buf[FN_REFLEN - 1] = '\0'; 2653 buf[tbname - 1 - dbname] = '\0'; 2654 2655 const skip_database_check_result skip_database = 2656 check_if_skip_database(buf); 2657 if (skip_database == DATABASE_SKIP) { 2658 return (TRUE); 2659 } 2660 2661 buf[tbname - 1 - dbname] = '.'; 2662 2663 /* Check if there's a suffix in the table name. If so, truncate it. We 2664 rely on the fact that a dot cannot be a part of a table name (it is 2665 encoded by the server with the @NNNN syntax). */ 2666 if ((eptr = strchr(&buf[tbname - dbname], '.')) != NULL) { 2667 2668 *eptr = '\0'; 2669 } 2670 2671 /* For partitioned tables first try to match against the regexp 2672 without truncating the #P#... suffix so we can backup individual 2673 partitions with regexps like '^test[.]t#P#p5' */ 2674 if (check_if_table_matches_filters(buf, regex_exclude_list, 2675 tables_exclude_hash)) { 2676 return(TRUE); 2677 } 2678 if (check_if_table_matches_filters(buf, regex_include_list, 2679 tables_include_hash)) { 2680 return(FALSE); 2681 } 2682 if ((eptr = strstr(buf, "#P#")) != NULL) { 2683 *eptr = 0; 2684 2685 if (check_if_table_matches_filters(buf, regex_exclude_list, 2686 tables_exclude_hash)) { 2687 return (TRUE); 2688 } 2689 if (check_if_table_matches_filters(buf, regex_include_list, 2690 tables_include_hash)) { 2691 return(FALSE); 2692 } 2693 } 2694 2695 if (skip_database == DATABASE_DONT_SKIP_UNLESS_EXPLICITLY_EXCLUDED) { 2696 /* Database is in include-list, and qualified name wasn't 2697 found in any of exclusion filters.*/ 2698 return (FALSE); 2699 } 2700 2701 if (skip_database == DATABASE_SKIP_SOME_TABLES || 2702 !regex_include_list.empty() || 2703 tables_include_hash) { 2704 2705 /* Include lists are present, but qualified name 2706 failed to match any.*/ 2707 return(TRUE); 2708 } 2709 2710 return(FALSE); 2711 } 2712 2713 const char* 2714 xb_get_copy_action(const char *dflt) 2715 { 2716 const char *action; 2717 2718 if (xtrabackup_stream) { 2719 if (xtrabackup_compress) { 2720 action = "Compressing and streaming"; 2721 } else { 2722 action = "Streaming"; 2723 } 2724 } else { 2725 if (xtrabackup_compress) { 2726 action = "Compressing"; 2727 } else { 2728 action = dflt; 2729 } 2730 } 2731 2732 return(action); 2733 } 2734 2735 2736 /** Copy innodb data file to the specified destination. 2737 2738 @param[in] node file node of a tablespace 2739 @param[in] thread_n thread id, used in the text of diagnostic messages 2740 @param[in] dest_name destination file name 2741 @param[in] write_filter write filter to copy data, can be pass-through filter 2742 for full backup, pages filter for incremental backup, etc. 2743 2744 @return FALSE on success and TRUE on error */ 2745 static my_bool xtrabackup_copy_datafile(fil_node_t *node, uint thread_n, 2746 const char *dest_name, 2747 const xb_write_filt_t &write_filter, 2748 CorruptedPages &corrupted_pages) 2749 { 2750 char dst_name[FN_REFLEN]; 2751 ds_file_t *dstfile = NULL; 2752 xb_fil_cur_t cursor; 2753 xb_fil_cur_result_t res; 2754 xb_write_filt_ctxt_t write_filt_ctxt; 2755 const char *action; 2756 xb_read_filt_t *read_filter; 2757 my_bool rc = FALSE; 2758 2759 /* Get the name and the path for the tablespace. node->name always 2760 contains the path (which may be absolute for remote tablespaces in 2761 5.6+). space->name contains the tablespace name in the form 2762 "./database/table.ibd" (in 5.5-) or "database/table" (in 5.6+). For a 2763 multi-node shared tablespace, space->name contains the name of the first 2764 node, but that's irrelevant, since we only need node_name to match them 2765 against filters, and the shared tablespace is always copied regardless 2766 of the filters value. */ 2767 2768 const char* const node_name = node->space->name; 2769 const char* const node_path = node->name; 2770 2771 if (fil_is_user_tablespace_id(node->space->id) 2772 && check_if_skip_table(node_name)) { 2773 msg(thread_n, "Skipping %s.", node_name); 2774 return(FALSE); 2775 } 2776 2777 memset(&write_filt_ctxt, 0, sizeof(xb_write_filt_ctxt_t)); 2778 2779 bool was_dropped; 2780 pthread_mutex_lock(&backup_mutex); 2781 was_dropped = (ddl_tracker.drops.find(node->space->id) != ddl_tracker.drops.end()); 2782 pthread_mutex_unlock(&backup_mutex); 2783 if (was_dropped) { 2784 if (node->is_open()) { 2785 mutex_enter(&fil_system.mutex); 2786 node->close(); 2787 mutex_exit(&fil_system.mutex); 2788 } 2789 goto skip; 2790 } 2791 2792 if (!changed_page_bitmap) { 2793 read_filter = &rf_pass_through; 2794 } 2795 else { 2796 read_filter = &rf_bitmap; 2797 } 2798 2799 res = xb_fil_cur_open(&cursor, read_filter, node, thread_n, ULLONG_MAX); 2800 if (res == XB_FIL_CUR_SKIP) { 2801 goto skip; 2802 } else if (res == XB_FIL_CUR_ERROR) { 2803 goto error; 2804 } 2805 2806 strncpy(dst_name, dest_name ? dest_name : cursor.rel_path, 2807 sizeof dst_name - 1); 2808 dst_name[sizeof dst_name - 1] = '\0'; 2809 2810 ut_a(write_filter.process != NULL); 2811 2812 if (write_filter.init != NULL && 2813 !write_filter.init(&write_filt_ctxt, dst_name, &cursor, 2814 opt_log_innodb_page_corruption ? &corrupted_pages : NULL)) { 2815 msg (thread_n, "mariabackup: error: failed to initialize page write filter."); 2816 goto error; 2817 } 2818 2819 dstfile = ds_open(ds_data, dst_name, &cursor.statinfo); 2820 if (dstfile == NULL) { 2821 msg(thread_n,"mariabackup: error: can't open the destination stream for %s", dst_name); 2822 goto error; 2823 } 2824 2825 action = xb_get_copy_action(); 2826 2827 if (xtrabackup_stream) { 2828 msg(thread_n, "%s %s", action, node_path); 2829 } else { 2830 msg(thread_n, "%s %s to %s", action, node_path, dstfile->path); 2831 } 2832 2833 /* The main copy loop */ 2834 while ((res = xb_fil_cur_read(&cursor, corrupted_pages)) == 2835 XB_FIL_CUR_SUCCESS) { 2836 if (!write_filter.process(&write_filt_ctxt, dstfile)) { 2837 goto error; 2838 } 2839 } 2840 2841 if (res == XB_FIL_CUR_ERROR) { 2842 goto error; 2843 } 2844 2845 if (write_filter.finalize 2846 && !write_filter.finalize(&write_filt_ctxt, dstfile)) { 2847 goto error; 2848 } 2849 2850 pthread_mutex_lock(&backup_mutex); 2851 ddl_tracker.tables_in_backup[node->space->id] = node_name; 2852 pthread_mutex_unlock(&backup_mutex); 2853 2854 /* close */ 2855 msg(thread_n," ...done"); 2856 xb_fil_cur_close(&cursor); 2857 if (ds_close(dstfile)) { 2858 rc = TRUE; 2859 } 2860 if (write_filter.deinit) { 2861 write_filter.deinit(&write_filt_ctxt); 2862 } 2863 return(rc); 2864 2865 error: 2866 xb_fil_cur_close(&cursor); 2867 if (dstfile != NULL) { 2868 ds_close(dstfile); 2869 } 2870 if (write_filter.deinit) { 2871 write_filter.deinit(&write_filt_ctxt);; 2872 } 2873 msg(thread_n, "mariabackup: xtrabackup_copy_datafile() failed."); 2874 return(TRUE); /*ERROR*/ 2875 2876 skip: 2877 2878 if (dstfile != NULL) { 2879 ds_close(dstfile); 2880 } 2881 if (write_filter.deinit) { 2882 write_filter.deinit(&write_filt_ctxt); 2883 } 2884 msg(thread_n,"Warning: We assume the table was dropped during xtrabackup execution and ignore the tablespace %s", node_name); 2885 return(FALSE); 2886 } 2887 2888 /** Copy redo log blocks to the data sink. 2889 @param start_lsn buffer start LSN 2890 @param end_lsn buffer end LSN 2891 @param last whether we are copying the final part of the log 2892 @return last scanned LSN 2893 @retval 0 on failure */ 2894 static lsn_t xtrabackup_copy_log(lsn_t start_lsn, lsn_t end_lsn, bool last) 2895 { 2896 lsn_t scanned_lsn = start_lsn; 2897 const byte* log_block = log_sys.buf; 2898 bool more_data = false; 2899 2900 for (ulint scanned_checkpoint = 0; 2901 scanned_lsn < end_lsn; 2902 log_block += OS_FILE_LOG_BLOCK_SIZE) { 2903 ulint checkpoint = log_block_get_checkpoint_no(log_block); 2904 2905 if (scanned_checkpoint > checkpoint 2906 && scanned_checkpoint - checkpoint >= 0x80000000UL) { 2907 /* Garbage from a log buffer flush which was made 2908 before the most recent database recovery */ 2909 msg(0,"checkpoint wrap: " LSN_PF ",%zx,%zx", 2910 scanned_lsn, scanned_checkpoint, checkpoint); 2911 break; 2912 } 2913 2914 scanned_checkpoint = checkpoint; 2915 2916 ulint data_len = log_block_get_data_len(log_block); 2917 2918 more_data = recv_sys_add_to_parsing_buf( 2919 log_block, 2920 scanned_lsn + data_len); 2921 2922 recv_sys.scanned_lsn = scanned_lsn + data_len; 2923 2924 if (data_len == OS_FILE_LOG_BLOCK_SIZE) { 2925 /* We got a full log block. */ 2926 scanned_lsn += data_len; 2927 } else if (data_len >= log_sys.trailer_offset() 2928 || data_len < LOG_BLOCK_HDR_SIZE) { 2929 /* We got a garbage block (abrupt end of the log). */ 2930 msg(0,"garbage block: " LSN_PF ",%zu",scanned_lsn, data_len); 2931 break; 2932 } else { 2933 /* We got a partial block (abrupt end of the log). */ 2934 scanned_lsn += data_len; 2935 break; 2936 } 2937 } 2938 2939 store_t store = STORE_NO; 2940 2941 if (more_data && recv_parse_log_recs(0, &store, 0, false)) { 2942 2943 msg("Error: copying the log failed"); 2944 2945 return(0); 2946 } 2947 2948 recv_sys_justify_left_parsing_buf(); 2949 2950 log_sys.log.scanned_lsn = scanned_lsn; 2951 2952 end_lsn = last 2953 ? ut_uint64_align_up(scanned_lsn, OS_FILE_LOG_BLOCK_SIZE) 2954 : scanned_lsn & ~lsn_t(OS_FILE_LOG_BLOCK_SIZE - 1); 2955 2956 if (ulint write_size = ulint(end_lsn - start_lsn)) { 2957 if (srv_encrypt_log) { 2958 log_crypt(log_sys.buf, start_lsn, write_size); 2959 } 2960 2961 if (ds_write(dst_log_file, log_sys.buf, write_size)) { 2962 msg("Error: write to logfile failed"); 2963 return(0); 2964 } 2965 } 2966 2967 return(scanned_lsn); 2968 } 2969 2970 /** Copy redo log until the current end of the log is reached 2971 @param last whether we are copying the final part of the log 2972 @return whether the operation failed */ 2973 static bool xtrabackup_copy_logfile(bool last = false) 2974 { 2975 ut_a(dst_log_file != NULL); 2976 ut_ad(recv_sys.is_initialised()); 2977 2978 bool overwritten_block = false; 2979 lsn_t start_lsn; 2980 lsn_t end_lsn; 2981 2982 recv_sys.parse_start_lsn = log_copy_scanned_lsn; 2983 recv_sys.scanned_lsn = log_copy_scanned_lsn; 2984 2985 start_lsn = ut_uint64_align_down(log_copy_scanned_lsn, 2986 OS_FILE_LOG_BLOCK_SIZE); 2987 do { 2988 end_lsn = start_lsn + RECV_SCAN_SIZE; 2989 2990 xtrabackup_io_throttling(); 2991 2992 log_mutex_enter(); 2993 lsn_t lsn= start_lsn; 2994 for (int retries= 0; retries < 100; retries++) { 2995 if (log_sys.log.read_log_seg(&lsn, end_lsn) 2996 || lsn != start_lsn) { 2997 break; 2998 } 2999 msg("Retrying read of log at LSN=" LSN_PF, lsn); 3000 my_sleep(1000); 3001 } 3002 3003 if (lsn == start_lsn) { 3004 overwritten_block= !recv_sys.found_corrupt_log 3005 && (innodb_log_checksums || log_sys.log.is_encrypted()) 3006 && log_block_calc_checksum_crc32(log_sys.buf) == 3007 log_block_get_checksum(log_sys.buf) 3008 && log_block_get_hdr_no(log_sys.buf) > 3009 log_block_convert_lsn_to_no(start_lsn); 3010 start_lsn = 0; 3011 } else { 3012 mutex_enter(&recv_sys.mutex); 3013 start_lsn = xtrabackup_copy_log(start_lsn, lsn, last); 3014 mutex_exit(&recv_sys.mutex); 3015 } 3016 3017 log_mutex_exit(); 3018 3019 if (!start_lsn) { 3020 const char *reason = recv_sys.found_corrupt_log 3021 ? "corrupt log." 3022 : (overwritten_block 3023 ? "redo log block is overwritten, please increase redo log size with innodb_log_file_size parameter." 3024 : ((innodb_log_checksums || log_sys.log.is_encrypted()) 3025 ? "redo log block checksum does not match." 3026 : "unknown reason as innodb_log_checksums is switched off and redo" 3027 " log is not encrypted.")); 3028 die("xtrabackup_copy_logfile() failed: %s", reason); 3029 return true; 3030 } 3031 } while (start_lsn == end_lsn); 3032 3033 ut_ad(start_lsn == log_sys.log.scanned_lsn); 3034 3035 msg(">> log scanned up to (" LSN_PF ")", start_lsn); 3036 3037 /* update global variable*/ 3038 pthread_mutex_lock(&backup_mutex); 3039 log_copy_scanned_lsn = start_lsn; 3040 pthread_cond_broadcast(&scanned_lsn_cond); 3041 pthread_mutex_unlock(&backup_mutex); 3042 return(false); 3043 } 3044 3045 /** 3046 Wait until redo log copying thread processes given lsn 3047 */ 3048 void backup_wait_for_lsn(lsn_t lsn) { 3049 bool completed = false; 3050 pthread_mutex_lock(&backup_mutex); 3051 do { 3052 pthread_cond_wait(&scanned_lsn_cond, &backup_mutex); 3053 completed = log_copy_scanned_lsn >= lsn; 3054 } while (!completed); 3055 pthread_mutex_unlock(&backup_mutex); 3056 } 3057 3058 extern lsn_t server_lsn_after_lock; 3059 3060 static os_thread_ret_t DECLARE_THREAD(log_copying_thread)(void*) 3061 { 3062 /* 3063 Initialize mysys thread-specific memory so we can 3064 use mysys functions in this thread. 3065 */ 3066 my_thread_init(); 3067 3068 for (;;) { 3069 os_event_reset(log_copying_stop); 3070 os_event_wait_time_low(log_copying_stop, 3071 xtrabackup_log_copy_interval * 1000ULL, 3072 0); 3073 if (xtrabackup_copy_logfile()) { 3074 break; 3075 } 3076 3077 log_mutex_enter(); 3078 bool completed = metadata_to_lsn 3079 && metadata_to_lsn <= log_copy_scanned_lsn; 3080 log_mutex_exit(); 3081 if (completed) { 3082 break; 3083 } 3084 } 3085 3086 log_copying_running = false; 3087 my_thread_end(); 3088 os_thread_exit(); 3089 3090 return(0); 3091 } 3092 3093 /* io throttle watching (rough) */ 3094 static os_thread_ret_t DECLARE_THREAD(io_watching_thread)(void*) 3095 { 3096 /* currently, for --backup only */ 3097 ut_a(xtrabackup_backup); 3098 3099 while (log_copying_running && !metadata_to_lsn) { 3100 os_thread_sleep(1000000); /*1 sec*/ 3101 io_ticket = xtrabackup_throttle; 3102 os_event_set(wait_throttle); 3103 } 3104 3105 /* stop io throttle */ 3106 xtrabackup_throttle = 0; 3107 os_event_set(wait_throttle); 3108 3109 io_watching_thread_running = false; 3110 3111 os_thread_exit(); 3112 3113 return(0); 3114 } 3115 3116 #ifndef DBUG_OFF 3117 char *dbug_mariabackup_get_val(const char *event, const char *key) 3118 { 3119 char envvar[FN_REFLEN]; 3120 if (key) { 3121 snprintf(envvar, sizeof(envvar), "%s_%s", event, key); 3122 char *slash = strchr(envvar, '/'); 3123 if (slash) 3124 *slash = '_'; 3125 } else { 3126 strncpy(envvar, event, sizeof envvar - 1); 3127 envvar[sizeof envvar - 1] = '\0'; 3128 } 3129 return getenv(envvar); 3130 } 3131 3132 /* 3133 In debug mode, execute SQL statement that was passed via environment. 3134 To use this facility, you need to 3135 3136 1. Add code DBUG_EXECUTE_MARIABACKUP_EVENT("my_event_name", key);); 3137 to the code. key is usually a table name 3138 2. Set environment variable my_event_name_$key SQL statement you want to execute 3139 when event occurs, in DBUG_EXECUTE_IF from above. 3140 In mtr , you can set environment via 'let' statement (do not use $ as the first char 3141 for the variable) 3142 3. start mariabackup with --dbug=+d,debug_mariabackup_events 3143 */ 3144 void dbug_mariabackup_event(const char *event,const char *key) 3145 { 3146 char *sql = dbug_mariabackup_get_val(event, key); 3147 if (sql && *sql) { 3148 msg("dbug_mariabackup_event : executing '%s'", sql); 3149 xb_mysql_query(mysql_connection, sql, false, true); 3150 } 3151 } 3152 #endif // DBUG_OFF 3153 3154 /************************************************************************** 3155 Datafiles copying thread.*/ 3156 static 3157 os_thread_ret_t 3158 DECLARE_THREAD(data_copy_thread_func)( 3159 /*==================*/ 3160 void *arg) /* thread context */ 3161 { 3162 data_thread_ctxt_t *ctxt = (data_thread_ctxt_t *) arg; 3163 uint num = ctxt->num; 3164 fil_node_t* node; 3165 ut_ad(ctxt->corrupted_pages); 3166 3167 /* 3168 Initialize mysys thread-specific memory so we can 3169 use mysys functions in this thread. 3170 */ 3171 my_thread_init(); 3172 3173 while ((node = datafiles_iter_next(ctxt->it)) != NULL) { 3174 DBUG_MARIABACKUP_EVENT("before_copy", node->space->name); 3175 DBUG_EXECUTE_FOR_KEY("wait_innodb_redo_before_copy", node->space->name, 3176 backup_wait_for_lsn(get_current_lsn(mysql_connection));); 3177 /* copy the datafile */ 3178 if (xtrabackup_copy_datafile(node, num, NULL, 3179 xtrabackup_incremental ? wf_incremental : wf_write_through, 3180 *ctxt->corrupted_pages)) 3181 die("failed to copy datafile."); 3182 3183 DBUG_MARIABACKUP_EVENT("after_copy", node->space->name); 3184 3185 } 3186 3187 pthread_mutex_lock(ctxt->count_mutex); 3188 (*ctxt->count)--; 3189 pthread_mutex_unlock(ctxt->count_mutex); 3190 3191 my_thread_end(); 3192 os_thread_exit(); 3193 OS_THREAD_DUMMY_RETURN; 3194 } 3195 3196 /************************************************************************ 3197 Initialize the appropriate datasink(s). Both local backups and streaming in the 3198 'xbstream' format allow parallel writes so we can write directly. 3199 3200 Otherwise (i.e. when streaming in the 'tar' format) we need 2 separate datasinks 3201 for the data stream (and don't allow parallel data copying) and for metainfo 3202 files (including ib_logfile0). The second datasink writes to temporary 3203 files first, and then streams them in a serialized way when closed. */ 3204 static void 3205 xtrabackup_init_datasinks(void) 3206 { 3207 /* Start building out the pipelines from the terminus back */ 3208 if (xtrabackup_stream) { 3209 /* All streaming goes to stdout */ 3210 ds_data = ds_meta = ds_redo = ds_create(xtrabackup_target_dir, 3211 DS_TYPE_STDOUT); 3212 } else { 3213 /* Local filesystem */ 3214 ds_data = ds_meta = ds_redo = ds_create(xtrabackup_target_dir, 3215 DS_TYPE_LOCAL); 3216 } 3217 3218 /* Track it for destruction */ 3219 xtrabackup_add_datasink(ds_data); 3220 3221 /* Stream formatting */ 3222 if (xtrabackup_stream) { 3223 ds_ctxt_t *ds; 3224 3225 ut_a(xtrabackup_stream_fmt == XB_STREAM_FMT_XBSTREAM); 3226 ds = ds_create(xtrabackup_target_dir, DS_TYPE_XBSTREAM); 3227 3228 xtrabackup_add_datasink(ds); 3229 3230 ds_set_pipe(ds, ds_data); 3231 ds_data = ds; 3232 3233 3234 ds_redo = ds_meta = ds_data; 3235 } 3236 3237 /* Compression for ds_data and ds_redo */ 3238 if (xtrabackup_compress) { 3239 ds_ctxt_t *ds; 3240 3241 /* Use a 1 MB buffer for compressed output stream */ 3242 ds = ds_create(xtrabackup_target_dir, DS_TYPE_BUFFER); 3243 ds_buffer_set_size(ds, 1024 * 1024); 3244 xtrabackup_add_datasink(ds); 3245 ds_set_pipe(ds, ds_data); 3246 if (ds_data != ds_redo) { 3247 ds_data = ds; 3248 ds = ds_create(xtrabackup_target_dir, DS_TYPE_BUFFER); 3249 ds_buffer_set_size(ds, 1024 * 1024); 3250 xtrabackup_add_datasink(ds); 3251 ds_set_pipe(ds, ds_redo); 3252 ds_redo = ds; 3253 } else { 3254 ds_redo = ds_data = ds; 3255 } 3256 3257 ds = ds_create(xtrabackup_target_dir, DS_TYPE_COMPRESS); 3258 xtrabackup_add_datasink(ds); 3259 ds_set_pipe(ds, ds_data); 3260 if (ds_data != ds_redo) { 3261 ds_data = ds; 3262 ds = ds_create(xtrabackup_target_dir, DS_TYPE_COMPRESS); 3263 xtrabackup_add_datasink(ds); 3264 ds_set_pipe(ds, ds_redo); 3265 ds_redo = ds; 3266 } else { 3267 ds_redo = ds_data = ds; 3268 } 3269 } 3270 } 3271 3272 /************************************************************************ 3273 Destroy datasinks. 3274 3275 Destruction is done in the specific order to not violate their order in the 3276 pipeline so that each datasink is able to flush data down the pipeline. */ 3277 static void xtrabackup_destroy_datasinks(void) 3278 { 3279 for (uint i = actual_datasinks; i > 0; i--) { 3280 ds_destroy(datasinks[i-1]); 3281 datasinks[i-1] = NULL; 3282 } 3283 ds_data = NULL; 3284 ds_meta = NULL; 3285 ds_redo = NULL; 3286 } 3287 3288 #define SRV_MAX_N_PENDING_SYNC_IOS 100 3289 3290 /** Initialize the tablespace cache subsystem. */ 3291 static 3292 void 3293 xb_fil_io_init() 3294 { 3295 fil_system.create(srv_file_per_table ? 50000 : 5000); 3296 } 3297 3298 static 3299 Datafile* 3300 xb_new_datafile(const char *name, bool is_remote) 3301 { 3302 if (is_remote) { 3303 RemoteDatafile *remote_file = new RemoteDatafile(); 3304 remote_file->set_name(name); 3305 return(remote_file); 3306 } else { 3307 Datafile *file = new Datafile(); 3308 file->set_name(name); 3309 file->make_filepath(".", name, IBD); 3310 return(file); 3311 } 3312 } 3313 3314 3315 /** Load tablespace. 3316 3317 @param[in] dirname directory name of the tablespace to open 3318 @param[in] filname file name of the tablespece to open 3319 @param[in] is_remote true if tablespace file is .isl 3320 @param[in] set_size true if we need to set tablespace size in pages explixitly. 3321 If this parameter is set, the size and free pages limit will not be read 3322 from page 0. 3323 */ 3324 static void xb_load_single_table_tablespace(const char *dirname, 3325 const char *filname, 3326 bool is_remote, bool set_size) 3327 { 3328 ut_ad(srv_operation == SRV_OPERATION_BACKUP 3329 || srv_operation == SRV_OPERATION_RESTORE_DELTA 3330 || srv_operation == SRV_OPERATION_RESTORE); 3331 /* Ignore .isl files on XtraBackup recovery. All tablespaces must be 3332 local. */ 3333 if (is_remote && srv_operation == SRV_OPERATION_RESTORE_DELTA) { 3334 return; 3335 } 3336 if (check_if_skip_table(filname)) { 3337 return; 3338 } 3339 3340 /* The name ends in .ibd or .isl; 3341 try opening the file */ 3342 char* name; 3343 size_t dirlen = dirname == NULL ? 0 : strlen(dirname); 3344 size_t namelen = strlen(filname); 3345 ulint pathlen = dirname == NULL ? namelen + 1: dirlen + namelen + 2; 3346 lsn_t flush_lsn; 3347 dberr_t err; 3348 fil_space_t *space; 3349 3350 name = static_cast<char*>(ut_malloc_nokey(pathlen)); 3351 3352 if (dirname != NULL) { 3353 snprintf(name, pathlen, "%s/%s", dirname, filname); 3354 name[pathlen - 5] = 0; 3355 } else { 3356 snprintf(name, pathlen, "%s", filname); 3357 name[pathlen - 5] = 0; 3358 } 3359 3360 Datafile *file = xb_new_datafile(name, is_remote); 3361 3362 if (file->open_read_only(true) != DB_SUCCESS) { 3363 die("Can't open datafile %s", name); 3364 } 3365 3366 for (int i = 0; i < 10; i++) { 3367 err = file->validate_first_page(&flush_lsn); 3368 if (err != DB_CORRUPTION) { 3369 break; 3370 } 3371 3372 my_sleep(1000); 3373 } 3374 3375 bool is_empty_file = file->exists() && file->is_empty_file(); 3376 3377 if (err == DB_SUCCESS && file->space_id() != SRV_TMP_SPACE_ID) { 3378 os_offset_t n_pages = 0; 3379 if (set_size) { 3380 os_offset_t node_size = os_file_get_size(file->handle()); 3381 ut_a(node_size != (os_offset_t) -1); 3382 n_pages = node_size / fil_space_t::physical_size(file->flags()); 3383 } 3384 space = fil_space_create( 3385 name, file->space_id(), file->flags(), 3386 FIL_TYPE_TABLESPACE, NULL/* TODO: crypt_data */); 3387 3388 ut_a(space != NULL); 3389 3390 space->add(file->filepath(), OS_FILE_CLOSED, ulint(n_pages), 3391 false, false); 3392 /* by opening the tablespace we forcing node and space objects 3393 in the cache to be populated with fields from space header */ 3394 space->open(); 3395 3396 if (srv_operation == SRV_OPERATION_RESTORE_DELTA 3397 || xb_close_files) { 3398 space->close(); 3399 } 3400 } 3401 3402 delete file; 3403 3404 if (err != DB_SUCCESS && xtrabackup_backup && !is_empty_file) { 3405 die("Failed to validate first page of the file %s, error %d",name, (int)err); 3406 } 3407 3408 ut_free(name); 3409 } 3410 3411 static void xb_load_single_table_tablespace(const std::string &space_name, 3412 bool set_size) 3413 { 3414 std::string name(space_name); 3415 bool is_remote= access((name + ".ibd").c_str(), R_OK) != 0; 3416 const char *extension= is_remote ? ".isl" : ".ibd"; 3417 name.append(extension); 3418 char buf[FN_REFLEN]; 3419 strncpy(buf, name.c_str(), sizeof buf - 1); 3420 buf[sizeof buf - 1]= '\0'; 3421 const char *dbname= buf; 3422 char *p= strchr(buf, '/'); 3423 if (p == 0) 3424 die("Unexpected tablespace %s filename %s", space_name.c_str(), 3425 name.c_str()); 3426 ut_a(p); 3427 *p= 0; 3428 const char *tablename= p + 1; 3429 xb_load_single_table_tablespace(dbname, tablename, is_remote, set_size); 3430 } 3431 3432 #ifdef _WIN32 3433 /** 3434 The os_file_opendir() function opens a directory stream corresponding to the 3435 directory named by the dirname argument. The directory stream is positioned 3436 at the first entry. In both Unix and Windows we automatically skip the '.' 3437 and '..' items at the start of the directory listing. 3438 @param[in] dirname directory name; it must not contain a trailing 3439 '\' or '/' 3440 @return directory stream, NULL if error */ 3441 os_file_dir_t os_file_opendir(const char *dirname) 3442 { 3443 char path[OS_FILE_MAX_PATH + 3]; 3444 3445 ut_a(strlen(dirname) < OS_FILE_MAX_PATH); 3446 3447 strcpy(path, dirname); 3448 strcpy(path + strlen(path), "\\*"); 3449 3450 /* Note that in Windows opening the 'directory stream' also retrieves 3451 the first entry in the directory. Since it is '.', that is no problem, 3452 as we will skip over the '.' and '..' entries anyway. */ 3453 3454 LPWIN32_FIND_DATA lpFindFileData= static_cast<LPWIN32_FIND_DATA> 3455 (ut_malloc_nokey(sizeof(WIN32_FIND_DATA))); 3456 os_file_dir_t dir= FindFirstFile((LPCTSTR) path, lpFindFileData); 3457 ut_free(lpFindFileData); 3458 3459 return dir; 3460 } 3461 #endif 3462 3463 /** This function returns information of the next file in the directory. We jump 3464 over the '.' and '..' entries in the directory. 3465 @param[in] dirname directory name or path 3466 @param[in] dir directory stream 3467 @param[out] info buffer where the info is returned 3468 @return 0 if ok, -1 if error, 1 if at the end of the directory */ 3469 int 3470 os_file_readdir_next_file( 3471 const char* dirname, 3472 os_file_dir_t dir, 3473 os_file_stat_t* info) 3474 { 3475 #ifdef _WIN32 3476 BOOL ret; 3477 int status; 3478 WIN32_FIND_DATA find_data; 3479 3480 next_file: 3481 ret = FindNextFile(dir, &find_data); 3482 3483 if (ret > 0) { 3484 3485 const char* name; 3486 3487 name = static_cast<const char*>(find_data.cFileName); 3488 3489 ut_a(strlen(name) < OS_FILE_MAX_PATH); 3490 3491 if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { 3492 3493 goto next_file; 3494 } 3495 3496 strcpy(info->name, name); 3497 3498 info->size = find_data.nFileSizeHigh; 3499 info->size <<= 32; 3500 info->size |= find_data.nFileSizeLow; 3501 3502 if (find_data.dwFileAttributes 3503 & FILE_ATTRIBUTE_REPARSE_POINT) { 3504 3505 /* TODO: test Windows symlinks */ 3506 /* TODO: MySQL has apparently its own symlink 3507 implementation in Windows, dbname.sym can 3508 redirect a database directory: 3509 REFMAN "windows-symbolic-links.html" */ 3510 3511 info->type = OS_FILE_TYPE_LINK; 3512 3513 } else if (find_data.dwFileAttributes 3514 & FILE_ATTRIBUTE_DIRECTORY) { 3515 3516 info->type = OS_FILE_TYPE_DIR; 3517 3518 } else { 3519 3520 /* It is probably safest to assume that all other 3521 file types are normal. Better to check them rather 3522 than blindly skip them. */ 3523 3524 info->type = OS_FILE_TYPE_FILE; 3525 } 3526 3527 status = 0; 3528 3529 } else { 3530 DWORD err = GetLastError(); 3531 if (err == ERROR_NO_MORE_FILES) { 3532 status = 1; 3533 } else { 3534 msg("FindNextFile in %s returned %lu", dirname, err); 3535 status = -1; 3536 } 3537 } 3538 3539 return(status); 3540 #else 3541 struct dirent* ent; 3542 char* full_path; 3543 int ret; 3544 struct stat statinfo; 3545 3546 next_file: 3547 3548 ent = readdir(dir); 3549 3550 if (ent == NULL) { 3551 3552 return(1); 3553 } 3554 3555 ut_a(strlen(ent->d_name) < OS_FILE_MAX_PATH); 3556 3557 if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { 3558 3559 goto next_file; 3560 } 3561 3562 strcpy(info->name, ent->d_name); 3563 3564 full_path = static_cast<char*>( 3565 ut_malloc_nokey(strlen(dirname) + strlen(ent->d_name) + 10)); 3566 3567 sprintf(full_path, "%s/%s", dirname, ent->d_name); 3568 3569 ret = stat(full_path, &statinfo); 3570 3571 if (ret) { 3572 3573 if (errno == ENOENT) { 3574 /* readdir() returned a file that does not exist, 3575 it must have been deleted in the meantime. Do what 3576 would have happened if the file was deleted before 3577 readdir() - ignore and go to the next entry. 3578 If this is the last entry then info->name will still 3579 contain the name of the deleted file when this 3580 function returns, but this is not an issue since the 3581 caller shouldn't be looking at info when end of 3582 directory is returned. */ 3583 3584 ut_free(full_path); 3585 3586 goto next_file; 3587 } 3588 3589 msg("stat %s: Got error %d", full_path, errno); 3590 3591 ut_free(full_path); 3592 3593 return(-1); 3594 } 3595 3596 info->size = statinfo.st_size; 3597 3598 if (S_ISDIR(statinfo.st_mode)) { 3599 info->type = OS_FILE_TYPE_DIR; 3600 } else if (S_ISLNK(statinfo.st_mode)) { 3601 info->type = OS_FILE_TYPE_LINK; 3602 } else if (S_ISREG(statinfo.st_mode)) { 3603 info->type = OS_FILE_TYPE_FILE; 3604 } else { 3605 info->type = OS_FILE_TYPE_UNKNOWN; 3606 } 3607 3608 ut_free(full_path); 3609 return(0); 3610 #endif 3611 } 3612 3613 /***********************************************************************//** 3614 A fault-tolerant function that tries to read the next file name in the 3615 directory. We retry 100 times if os_file_readdir_next_file() returns -1. The 3616 idea is to read as much good data as we can and jump over bad data. 3617 @return 0 if ok, -1 if error even after the retries, 1 if at the end 3618 of the directory */ 3619 int 3620 fil_file_readdir_next_file( 3621 /*=======================*/ 3622 dberr_t* err, /*!< out: this is set to DB_ERROR if an error 3623 was encountered, otherwise not changed */ 3624 const char* dirname,/*!< in: directory name or path */ 3625 os_file_dir_t dir, /*!< in: directory stream */ 3626 os_file_stat_t* info) /*!< in/out: buffer where the 3627 info is returned */ 3628 { 3629 for (ulint i = 0; i < 100; i++) { 3630 int ret = os_file_readdir_next_file(dirname, dir, info); 3631 3632 if (ret != -1) { 3633 3634 return(ret); 3635 } 3636 3637 ib::error() << "os_file_readdir_next_file() returned -1 in" 3638 " directory " << dirname 3639 << ", crash recovery may have failed" 3640 " for some .ibd files!"; 3641 3642 *err = DB_ERROR; 3643 } 3644 3645 return(-1); 3646 } 3647 3648 /** Scan the database directories under the MySQL datadir, looking for 3649 .ibd files and determining the space id in each of them. 3650 @return DB_SUCCESS or error number */ 3651 3652 static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback) 3653 { 3654 int ret; 3655 char* dbpath = NULL; 3656 ulint dbpath_len = 100; 3657 os_file_dir_t dir; 3658 os_file_dir_t dbdir; 3659 os_file_stat_t dbinfo; 3660 os_file_stat_t fileinfo; 3661 dberr_t err = DB_SUCCESS; 3662 size_t len; 3663 3664 /* The datadir of MySQL is always the default directory of mysqld */ 3665 3666 dir = os_file_opendir(fil_path_to_mysql_datadir); 3667 3668 if (UNIV_UNLIKELY(dir == IF_WIN(INVALID_HANDLE_VALUE, nullptr))) { 3669 msg("cannot open dir %s", fil_path_to_mysql_datadir); 3670 return(DB_ERROR); 3671 } 3672 3673 dbpath = static_cast<char*>(ut_malloc_nokey(dbpath_len)); 3674 3675 /* Scan all directories under the datadir. They are the database 3676 directories of MySQL. */ 3677 3678 ret = fil_file_readdir_next_file(&err, fil_path_to_mysql_datadir, dir, 3679 &dbinfo); 3680 while (ret == 0) { 3681 3682 /* General tablespaces are always at the first level of the 3683 data home dir */ 3684 if (dbinfo.type == OS_FILE_TYPE_FILE) { 3685 bool is_isl = ends_with(dbinfo.name, ".isl"); 3686 bool is_ibd = !is_isl && ends_with(dbinfo.name,".ibd"); 3687 3688 if (is_isl || is_ibd) { 3689 (*callback)(NULL, dbinfo.name, is_isl, false); 3690 } 3691 } 3692 3693 if (dbinfo.type == OS_FILE_TYPE_FILE 3694 || dbinfo.type == OS_FILE_TYPE_UNKNOWN) { 3695 3696 goto next_datadir_item; 3697 } 3698 3699 /* We found a symlink or a directory; try opening it to see 3700 if a symlink is a directory */ 3701 3702 len = strlen(fil_path_to_mysql_datadir) 3703 + strlen (dbinfo.name) + 2; 3704 if (len > dbpath_len) { 3705 dbpath_len = len; 3706 3707 if (dbpath) { 3708 ut_free(dbpath); 3709 } 3710 3711 dbpath = static_cast<char*>(ut_malloc_nokey(dbpath_len)); 3712 } 3713 snprintf(dbpath, dbpath_len, 3714 "%s/%s", fil_path_to_mysql_datadir, dbinfo.name); 3715 os_normalize_path(dbpath); 3716 3717 if (check_if_skip_database_by_path(dbpath)) { 3718 fprintf(stderr, "Skipping db: %s\n", dbpath); 3719 goto next_datadir_item; 3720 } 3721 3722 dbdir = os_file_opendir(dbpath); 3723 3724 if (UNIV_UNLIKELY(dbdir != IF_WIN(INVALID_HANDLE_VALUE,NULL))){ 3725 /* We found a database directory; loop through it, 3726 looking for possible .ibd files in it */ 3727 3728 for (ret = fil_file_readdir_next_file(&err, dbpath, 3729 dbdir, 3730 &fileinfo); 3731 ret == 0; 3732 ret = fil_file_readdir_next_file(&err, dbpath, 3733 dbdir, 3734 &fileinfo)) { 3735 if (fileinfo.type == OS_FILE_TYPE_DIR) { 3736 continue; 3737 } 3738 3739 /* We found a symlink or a file */ 3740 if (strlen(fileinfo.name) > 4) { 3741 bool is_isl= false; 3742 if (ends_with(fileinfo.name, ".ibd") || ((is_isl = ends_with(fileinfo.name, ".isl")))) 3743 (*callback)(dbinfo.name, fileinfo.name, is_isl, false); 3744 } 3745 } 3746 3747 if (os_file_closedir_failed(dbdir)) { 3748 fprintf(stderr, "InnoDB: Warning: could not" 3749 " close database directory %s\n", 3750 dbpath); 3751 3752 err = DB_ERROR; 3753 } 3754 3755 } else { 3756 msg("Can't open dir %s", dbpath); 3757 err = DB_ERROR; 3758 break; 3759 3760 } 3761 3762 next_datadir_item: 3763 ret = fil_file_readdir_next_file(&err, 3764 fil_path_to_mysql_datadir, 3765 dir, &dbinfo); 3766 } 3767 3768 ut_free(dbpath); 3769 3770 if (os_file_closedir_failed(dir)) { 3771 fprintf(stderr, 3772 "InnoDB: Error: could not close MySQL datadir\n"); 3773 return(DB_ERROR); 3774 } 3775 3776 return(err); 3777 } 3778 3779 /** Assign srv_undo_space_id_start variable if there are undo tablespace present. 3780 Read the TRX_SYS page from ibdata1 file and get the minimum space id from 3781 the first slot rollback segments of TRX_SYS_PAGE_NO. 3782 @retval DB_ERROR if file open or page read failed. 3783 @retval DB_SUCCESS if srv_undo_space_id assigned successfully. */ 3784 static dberr_t xb_assign_undo_space_start() 3785 { 3786 3787 pfs_os_file_t file; 3788 byte* buf; 3789 byte* page; 3790 bool ret; 3791 dberr_t error = DB_SUCCESS; 3792 ulint space; 3793 int n_retries = 5; 3794 ulint fsp_flags; 3795 3796 if (srv_undo_tablespaces == 0) { 3797 return error; 3798 } 3799 3800 file = os_file_create(0, srv_sys_space.first_datafile()->filepath(), 3801 OS_FILE_OPEN, OS_FILE_NORMAL, OS_DATA_FILE, true, &ret); 3802 3803 if (!ret) { 3804 msg("Error opening %s", srv_sys_space.first_datafile()->filepath()); 3805 return DB_ERROR; 3806 } 3807 3808 buf = static_cast<byte*>(ut_malloc_nokey(2U << srv_page_size_shift)); 3809 page = static_cast<byte*>(ut_align(buf, srv_page_size)); 3810 3811 if (os_file_read(IORequestRead, file, page, 0, srv_page_size) 3812 != DB_SUCCESS) { 3813 msg("Reading first page failed.\n"); 3814 error = DB_ERROR; 3815 goto func_exit; 3816 } 3817 3818 fsp_flags = mach_read_from_4( 3819 page + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS); 3820 retry: 3821 if (os_file_read(IORequestRead, file, page, 3822 TRX_SYS_PAGE_NO << srv_page_size_shift, 3823 srv_page_size) != DB_SUCCESS) { 3824 msg("Reading TRX_SYS page failed."); 3825 error = DB_ERROR; 3826 goto func_exit; 3827 } 3828 3829 /* TRX_SYS page can't be compressed or encrypted. */ 3830 if (buf_page_is_corrupted(false, page, fsp_flags)) { 3831 if (n_retries--) { 3832 os_thread_sleep(1000); 3833 goto retry; 3834 } else { 3835 msg("mariabackup: TRX_SYS page corrupted.\n"); 3836 error = DB_ERROR; 3837 goto func_exit; 3838 } 3839 } 3840 3841 /* 0th slot always points to system tablespace. 3842 1st slot should point to first undotablespace which is minimum. */ 3843 3844 ut_ad(mach_read_from_4(TRX_SYS + TRX_SYS_RSEGS 3845 + TRX_SYS_RSEG_SLOT_SIZE 3846 + TRX_SYS_RSEG_PAGE_NO + page) 3847 != FIL_NULL); 3848 3849 space = mach_read_from_4(TRX_SYS + TRX_SYS_RSEGS 3850 + TRX_SYS_RSEG_SLOT_SIZE 3851 + TRX_SYS_RSEG_SPACE + page); 3852 3853 srv_undo_space_id_start = space; 3854 3855 func_exit: 3856 ut_free(buf); 3857 ret = os_file_close(file); 3858 ut_a(ret); 3859 3860 return error; 3861 } 3862 3863 /**************************************************************************** 3864 Populates the tablespace memory cache by scanning for and opening data files. 3865 @returns DB_SUCCESS or error code.*/ 3866 static 3867 dberr_t 3868 xb_load_tablespaces() 3869 { 3870 bool create_new_db; 3871 dberr_t err; 3872 ulint sum_of_new_sizes; 3873 lsn_t flush_lsn; 3874 3875 ut_ad(srv_operation == SRV_OPERATION_BACKUP 3876 || srv_operation == SRV_OPERATION_RESTORE_DELTA); 3877 3878 err = srv_sys_space.check_file_spec(&create_new_db, 0); 3879 3880 /* create_new_db must not be true. */ 3881 if (err != DB_SUCCESS || create_new_db) { 3882 msg("Could not find data files at the specified datadir"); 3883 return(DB_ERROR); 3884 } 3885 3886 for (int i= 0; i < 10; i++) { 3887 err = srv_sys_space.open_or_create(false, false, &sum_of_new_sizes, 3888 &flush_lsn); 3889 if (err == DB_PAGE_CORRUPTED || err == DB_CORRUPTION) { 3890 my_sleep(1000); 3891 } 3892 else 3893 break; 3894 } 3895 3896 if (err != DB_SUCCESS) { 3897 msg("Could not open data files.\n"); 3898 return(err); 3899 } 3900 3901 /* Add separate undo tablespaces to fil_system */ 3902 3903 err = xb_assign_undo_space_start(); 3904 3905 if (err != DB_SUCCESS) { 3906 return err; 3907 } 3908 3909 err = srv_undo_tablespaces_init(false); 3910 3911 if (err != DB_SUCCESS) { 3912 return(err); 3913 } 3914 3915 /* It is important to call xb_load_single_table_tablespaces() after 3916 srv_undo_tablespaces_init(), because fil_is_user_tablespace_id() * 3917 relies on srv_undo_tablespaces_open to be properly initialized */ 3918 3919 msg("mariabackup: Generating a list of tablespaces"); 3920 3921 err = enumerate_ibd_files(xb_load_single_table_tablespace); 3922 if (err != DB_SUCCESS) { 3923 return(err); 3924 } 3925 DBUG_MARIABACKUP_EVENT("after_load_tablespaces", 0); 3926 return(DB_SUCCESS); 3927 } 3928 3929 /************************************************************************ 3930 Initialize the tablespace memory cache and populate it by scanning for and 3931 opening data files. 3932 @returns DB_SUCCESS or error code.*/ 3933 static 3934 dberr_t 3935 xb_data_files_init() 3936 { 3937 xb_fil_io_init(); 3938 3939 return(xb_load_tablespaces()); 3940 } 3941 3942 /************************************************************************ 3943 Destroy the tablespace memory cache. */ 3944 static 3945 void 3946 xb_data_files_close() 3947 { 3948 ut_ad(!os_thread_count); 3949 fil_close_all_files(); 3950 if (buf_dblwr) { 3951 buf_dblwr_free(); 3952 } 3953 } 3954 3955 /*********************************************************************** 3956 Allocate and initialize the entry for databases and tables filtering 3957 hash tables. If memory allocation is not successful, terminate program. 3958 @return pointer to the created entry. */ 3959 static 3960 xb_filter_entry_t * 3961 xb_new_filter_entry( 3962 /*================*/ 3963 const char* name) /*!< in: name of table/database */ 3964 { 3965 xb_filter_entry_t *entry; 3966 ulint namelen = strlen(name); 3967 3968 ut_a(namelen <= NAME_LEN * 2 + 1); 3969 3970 entry = static_cast<xb_filter_entry_t *> 3971 (malloc(sizeof(xb_filter_entry_t) + namelen + 1)); 3972 memset(entry, '\0', sizeof(xb_filter_entry_t) + namelen + 1); 3973 entry->name = ((char*)entry) + sizeof(xb_filter_entry_t); 3974 strcpy(entry->name, name); 3975 entry->has_tables = FALSE; 3976 3977 return entry; 3978 } 3979 3980 /*********************************************************************** 3981 Add entry to hash table. If hash table is NULL, allocate and initialize 3982 new hash table */ 3983 static 3984 xb_filter_entry_t* 3985 xb_add_filter( 3986 /*========================*/ 3987 const char* name, /*!< in: name of table/database */ 3988 hash_table_t** hash) /*!< in/out: hash to insert into */ 3989 { 3990 xb_filter_entry_t* entry; 3991 3992 entry = xb_new_filter_entry(name); 3993 3994 if (UNIV_UNLIKELY(*hash == NULL)) { 3995 *hash = hash_create(1000); 3996 } 3997 HASH_INSERT(xb_filter_entry_t, 3998 name_hash, *hash, 3999 ut_fold_string(entry->name), 4000 entry); 4001 4002 return entry; 4003 } 4004 4005 /*********************************************************************** 4006 Validate name of table or database. If name is invalid, program will 4007 be finished with error code */ 4008 static 4009 void 4010 xb_validate_name( 4011 /*=============*/ 4012 const char* name, /*!< in: name */ 4013 size_t len) /*!< in: length of name */ 4014 { 4015 const char* p; 4016 4017 /* perform only basic validation. validate length and 4018 path symbols */ 4019 if (len > NAME_LEN) { 4020 die("name `%s` is too long.", name); 4021 } 4022 p = strpbrk(name, "/\\~"); 4023 if (p && (uint) (p - name) < NAME_LEN) { 4024 die("name `%s` is not valid.", name); 4025 } 4026 } 4027 4028 /*********************************************************************** 4029 Register new filter entry which can be either database 4030 or table name. */ 4031 static 4032 void 4033 xb_register_filter_entry( 4034 /*=====================*/ 4035 const char* name, /*!< in: name */ 4036 hash_table_t** databases_hash, 4037 hash_table_t** tables_hash 4038 ) 4039 { 4040 const char* p; 4041 size_t namelen; 4042 xb_filter_entry_t* db_entry = NULL; 4043 4044 namelen = strlen(name); 4045 if ((p = strchr(name, '.')) != NULL) { 4046 char dbname[NAME_LEN + 1]; 4047 4048 xb_validate_name(name, p - name); 4049 xb_validate_name(p + 1, namelen - (p - name)); 4050 4051 strncpy(dbname, name, p - name); 4052 dbname[p - name] = 0; 4053 4054 if (*databases_hash) { 4055 HASH_SEARCH(name_hash, (*databases_hash), 4056 ut_fold_string(dbname), 4057 xb_filter_entry_t*, 4058 db_entry, (void) 0, 4059 !strcmp(db_entry->name, dbname)); 4060 } 4061 if (!db_entry) { 4062 db_entry = xb_add_filter(dbname, databases_hash); 4063 } 4064 db_entry->has_tables = TRUE; 4065 xb_add_filter(name, tables_hash); 4066 } else { 4067 xb_validate_name(name, namelen); 4068 4069 xb_add_filter(name, databases_hash); 4070 } 4071 } 4072 4073 static 4074 void 4075 xb_register_include_filter_entry( 4076 const char* name 4077 ) 4078 { 4079 xb_register_filter_entry(name, &databases_include_hash, 4080 &tables_include_hash); 4081 } 4082 4083 static 4084 void 4085 xb_register_exclude_filter_entry( 4086 const char* name 4087 ) 4088 { 4089 xb_register_filter_entry(name, &databases_exclude_hash, 4090 &tables_exclude_hash); 4091 } 4092 4093 void register_ignore_db_dirs_filter(const char *name) 4094 { 4095 xb_add_filter(name, &databases_exclude_hash); 4096 } 4097 4098 /*********************************************************************** 4099 Register new table for the filter. */ 4100 static 4101 void 4102 xb_register_table( 4103 /*==============*/ 4104 const char* name) /*!< in: name of table */ 4105 { 4106 if (strchr(name, '.') == NULL) { 4107 die("`%s` is not fully qualified name.", name); 4108 } 4109 4110 xb_register_include_filter_entry(name); 4111 } 4112 4113 static 4114 void 4115 xb_add_regex_to_list( 4116 const char* regex, /*!< in: regex */ 4117 const char* error_context, /*!< in: context to error message */ 4118 regex_list_t* list) /*! in: list to put new regex to */ 4119 { 4120 char errbuf[100]; 4121 int ret; 4122 4123 regex_t compiled_regex; 4124 ret = regcomp(&compiled_regex, regex, REG_EXTENDED); 4125 4126 if (ret != 0) { 4127 regerror(ret, &compiled_regex, errbuf, sizeof(errbuf)); 4128 msg("mariabackup: error: %s regcomp(%s): %s", 4129 error_context, regex, errbuf); 4130 exit(EXIT_FAILURE); 4131 } 4132 4133 list->push_back(compiled_regex); 4134 } 4135 4136 /*********************************************************************** 4137 Register new regex for the include filter. */ 4138 static 4139 void 4140 xb_register_include_regex( 4141 /*==============*/ 4142 const char* regex) /*!< in: regex */ 4143 { 4144 xb_add_regex_to_list(regex, "tables", ®ex_include_list); 4145 } 4146 4147 /*********************************************************************** 4148 Register new regex for the exclude filter. */ 4149 static 4150 void 4151 xb_register_exclude_regex( 4152 /*==============*/ 4153 const char* regex) /*!< in: regex */ 4154 { 4155 xb_add_regex_to_list(regex, "tables-exclude", ®ex_exclude_list); 4156 } 4157 4158 typedef void (*insert_entry_func_t)(const char*); 4159 4160 /* Scan string and load filter entries from it. 4161 @param[in] list string representing a list 4162 @param[in] delimiters delimiters of entries 4163 @param[in] ins callback to add entry */ 4164 void xb_load_list_string(char *list, const char *delimiters, 4165 insert_entry_func_t ins) 4166 { 4167 char *p; 4168 char *saveptr; 4169 4170 p= strtok_r(list, delimiters, &saveptr); 4171 while (p) 4172 { 4173 4174 ins(p); 4175 4176 p= strtok_r(NULL, delimiters, &saveptr); 4177 } 4178 } 4179 4180 /*********************************************************************** 4181 Scan file and load filter entries from it. */ 4182 static 4183 void 4184 xb_load_list_file( 4185 /*==============*/ 4186 const char* filename, /*!< in: name of file */ 4187 insert_entry_func_t ins) /*!< in: callback to add entry */ 4188 { 4189 char name_buf[NAME_LEN*2+2]; 4190 FILE* fp; 4191 4192 /* read and store the filenames */ 4193 fp = fopen(filename, "r"); 4194 if (!fp) { 4195 die("Can't open %s", 4196 filename); 4197 } 4198 while (fgets(name_buf, sizeof(name_buf), fp) != NULL) { 4199 char* p = strchr(name_buf, '\n'); 4200 if (p) { 4201 *p = '\0'; 4202 } else { 4203 die("`%s...` name is too long", name_buf); 4204 } 4205 4206 ins(name_buf); 4207 } 4208 4209 fclose(fp); 4210 } 4211 4212 4213 static 4214 void 4215 xb_filters_init() 4216 { 4217 if (xtrabackup_databases) { 4218 xb_load_list_string(xtrabackup_databases, " \t", 4219 xb_register_include_filter_entry); 4220 } 4221 4222 if (xtrabackup_databases_file) { 4223 xb_load_list_file(xtrabackup_databases_file, 4224 xb_register_include_filter_entry); 4225 } 4226 4227 if (xtrabackup_databases_exclude) { 4228 xb_load_list_string(xtrabackup_databases_exclude, " \t", 4229 xb_register_exclude_filter_entry); 4230 } 4231 4232 if (xtrabackup_tables) { 4233 xb_load_list_string(xtrabackup_tables, ",", 4234 xb_register_include_regex); 4235 } 4236 4237 if (xtrabackup_tables_file) { 4238 xb_load_list_file(xtrabackup_tables_file, xb_register_table); 4239 } 4240 4241 if (xtrabackup_tables_exclude) { 4242 xb_load_list_string(xtrabackup_tables_exclude, ",", 4243 xb_register_exclude_regex); 4244 } 4245 } 4246 4247 static 4248 void 4249 xb_filter_hash_free(hash_table_t* hash) 4250 { 4251 ulint i; 4252 4253 /* free the hash elements */ 4254 for (i = 0; i < hash_get_n_cells(hash); i++) { 4255 xb_filter_entry_t* table; 4256 4257 table = static_cast<xb_filter_entry_t *> 4258 (HASH_GET_FIRST(hash, i)); 4259 4260 while (table) { 4261 xb_filter_entry_t* prev_table = table; 4262 4263 table = static_cast<xb_filter_entry_t *> 4264 (HASH_GET_NEXT(name_hash, prev_table)); 4265 4266 HASH_DELETE(xb_filter_entry_t, name_hash, hash, 4267 ut_fold_string(prev_table->name), prev_table); 4268 free(prev_table); 4269 } 4270 } 4271 4272 /* free hash */ 4273 hash_table_free(hash); 4274 } 4275 4276 static void xb_regex_list_free(regex_list_t* list) 4277 { 4278 while (list->size() > 0) { 4279 xb_regfree(&list->front()); 4280 list->pop_front(); 4281 } 4282 } 4283 4284 /************************************************************************ 4285 Destroy table filters for partial backup. */ 4286 static 4287 void 4288 xb_filters_free() 4289 { 4290 xb_regex_list_free(®ex_include_list); 4291 xb_regex_list_free(®ex_exclude_list); 4292 4293 if (tables_include_hash) { 4294 xb_filter_hash_free(tables_include_hash); 4295 } 4296 4297 if (tables_exclude_hash) { 4298 xb_filter_hash_free(tables_exclude_hash); 4299 } 4300 4301 if (databases_include_hash) { 4302 xb_filter_hash_free(databases_include_hash); 4303 } 4304 4305 if (databases_exclude_hash) { 4306 xb_filter_hash_free(databases_exclude_hash); 4307 } 4308 } 4309 4310 /*********************************************************************//** 4311 Create log file metadata. */ 4312 static 4313 void 4314 open_or_create_log_file( 4315 /*====================*/ 4316 fil_space_t* space, 4317 ulint i) /*!< in: log file number in group */ 4318 { 4319 char name[FN_REFLEN]; 4320 ulint dirnamelen; 4321 4322 os_normalize_path(srv_log_group_home_dir); 4323 4324 dirnamelen = strlen(srv_log_group_home_dir); 4325 ut_a(dirnamelen < (sizeof name) - 10 - sizeof "ib_logfile"); 4326 memcpy(name, srv_log_group_home_dir, dirnamelen); 4327 4328 /* Add a path separator if needed. */ 4329 if (dirnamelen && name[dirnamelen - 1] != OS_PATH_SEPARATOR) { 4330 name[dirnamelen++] = OS_PATH_SEPARATOR; 4331 } 4332 4333 sprintf(name + dirnamelen, "%s%zu", "ib_logfile", i); 4334 4335 ut_a(fil_validate()); 4336 4337 space->add(name, OS_FILE_CLOSED, 4338 ulint(srv_log_file_size >> srv_page_size_shift), 4339 false, false); 4340 } 4341 4342 /*********************************************************************** 4343 Set the open files limit. Based on set_max_open_files(). 4344 4345 @return the resulting open files limit. May be less or more than the requested 4346 value. */ 4347 static uint 4348 xb_set_max_open_files( 4349 /*==================*/ 4350 uint max_file_limit) /*!<in: open files limit */ 4351 { 4352 #if defined(RLIMIT_NOFILE) 4353 struct rlimit rlimit; 4354 uint old_cur; 4355 4356 if (getrlimit(RLIMIT_NOFILE, &rlimit)) { 4357 4358 goto end; 4359 } 4360 4361 old_cur = (uint) rlimit.rlim_cur; 4362 4363 if (rlimit.rlim_cur == RLIM_INFINITY) { 4364 4365 rlimit.rlim_cur = max_file_limit; 4366 } 4367 4368 if (rlimit.rlim_cur >= max_file_limit) { 4369 4370 max_file_limit = rlimit.rlim_cur; 4371 goto end; 4372 } 4373 4374 rlimit.rlim_cur = rlimit.rlim_max = max_file_limit; 4375 4376 if (setrlimit(RLIMIT_NOFILE, &rlimit)) { 4377 4378 max_file_limit = old_cur; /* Use original value */ 4379 } else { 4380 4381 rlimit.rlim_cur = 0; /* Safety if next call fails */ 4382 4383 (void) getrlimit(RLIMIT_NOFILE, &rlimit); 4384 4385 if (rlimit.rlim_cur) { 4386 4387 /* If call didn't fail */ 4388 max_file_limit = (uint) rlimit.rlim_cur; 4389 } 4390 } 4391 4392 end: 4393 return(max_file_limit); 4394 #else 4395 return(0); 4396 #endif 4397 } 4398 4399 static void stop_backup_threads() 4400 { 4401 if (log_copying_stop && log_copying_running) { 4402 os_event_set(log_copying_stop); 4403 fputs("mariabackup: Stopping log copying thread", stderr); 4404 fflush(stderr); 4405 while (log_copying_running) { 4406 putc('.', stderr); 4407 fflush(stderr); 4408 os_thread_sleep(200000); /*0.2 sec*/ 4409 } 4410 putc('\n', stderr); 4411 os_event_destroy(log_copying_stop); 4412 } 4413 4414 if (wait_throttle) { 4415 /* wait for io_watching_thread completion */ 4416 while (io_watching_thread_running) { 4417 os_thread_sleep(1000000); 4418 } 4419 os_event_destroy(wait_throttle); 4420 } 4421 } 4422 4423 /** Implement the core of --backup 4424 @return whether the operation succeeded */ 4425 static bool xtrabackup_backup_low() 4426 { 4427 ut_ad(!metadata_to_lsn); 4428 4429 /* read the latest checkpoint lsn */ 4430 { 4431 ulint max_cp_field; 4432 4433 log_mutex_enter(); 4434 4435 if (recv_find_max_checkpoint(&max_cp_field) == DB_SUCCESS 4436 && log_sys.log.format != 0) { 4437 if (max_cp_field == LOG_CHECKPOINT_1) { 4438 log_header_read(max_cp_field); 4439 } 4440 metadata_to_lsn = mach_read_from_8( 4441 log_sys.checkpoint_buf + LOG_CHECKPOINT_LSN); 4442 msg("mariabackup: The latest check point" 4443 " (for incremental): '" LSN_PF "'", 4444 metadata_to_lsn); 4445 } else { 4446 msg("Error: recv_find_max_checkpoint() failed."); 4447 } 4448 log_mutex_exit(); 4449 } 4450 4451 stop_backup_threads(); 4452 4453 if (metadata_to_lsn && xtrabackup_copy_logfile(true)) { 4454 ds_close(dst_log_file); 4455 dst_log_file = NULL; 4456 return false; 4457 } 4458 4459 if (ds_close(dst_log_file) || !metadata_to_lsn) { 4460 dst_log_file = NULL; 4461 return false; 4462 } 4463 4464 dst_log_file = NULL; 4465 4466 if(!xtrabackup_incremental) { 4467 strcpy(metadata_type, "full-backuped"); 4468 metadata_from_lsn = 0; 4469 } else { 4470 strcpy(metadata_type, "incremental"); 4471 metadata_from_lsn = incremental_lsn; 4472 } 4473 metadata_last_lsn = log_copy_scanned_lsn; 4474 4475 if (!xtrabackup_stream_metadata(ds_meta)) { 4476 msg("Error: failed to stream metadata."); 4477 return false; 4478 } 4479 if (xtrabackup_extra_lsndir) { 4480 char filename[FN_REFLEN]; 4481 4482 sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, 4483 XTRABACKUP_METADATA_FILENAME); 4484 if (!xtrabackup_write_metadata(filename)) { 4485 msg("Error: failed to write metadata " 4486 "to '%s'.", filename); 4487 return false; 4488 } 4489 sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, 4490 XTRABACKUP_INFO); 4491 if (!write_xtrabackup_info(mysql_connection, filename, false, false)) { 4492 msg("Error: failed to write info " 4493 "to '%s'.", filename); 4494 return false; 4495 } 4496 } 4497 4498 return true; 4499 } 4500 4501 /** Implement --backup 4502 @return whether the operation succeeded */ 4503 static bool xtrabackup_backup_func() 4504 { 4505 MY_STAT stat_info; 4506 uint i; 4507 uint count; 4508 pthread_mutex_t count_mutex; 4509 CorruptedPages corrupted_pages; 4510 data_thread_ctxt_t *data_threads; 4511 pthread_mutex_init(&backup_mutex, NULL); 4512 pthread_cond_init(&scanned_lsn_cond, NULL); 4513 4514 #ifdef USE_POSIX_FADVISE 4515 msg("uses posix_fadvise()."); 4516 #endif 4517 4518 /* cd to datadir */ 4519 4520 if (my_setwd(mysql_real_data_home,MYF(MY_WME))) 4521 { 4522 msg("my_setwd() failed , %s", mysql_real_data_home); 4523 return(false); 4524 } 4525 msg("cd to %s", mysql_real_data_home); 4526 encryption_plugin_backup_init(mysql_connection); 4527 msg("open files limit requested %u, set to %u", 4528 (uint) xb_open_files_limit, 4529 xb_set_max_open_files(xb_open_files_limit)); 4530 4531 mysql_data_home= mysql_data_home_buff; 4532 mysql_data_home[0]=FN_CURLIB; // all paths are relative from here 4533 mysql_data_home[1]=0; 4534 4535 srv_n_purge_threads = 1; 4536 srv_read_only_mode = TRUE; 4537 4538 srv_operation = SRV_OPERATION_BACKUP; 4539 log_file_op = backup_file_op; 4540 metadata_to_lsn = 0; 4541 4542 /* initialize components */ 4543 if(innodb_init_param()) { 4544 fail: 4545 metadata_to_lsn = log_copying_running; 4546 stop_backup_threads(); 4547 log_file_op = NULL; 4548 if (dst_log_file) { 4549 ds_close(dst_log_file); 4550 dst_log_file = NULL; 4551 } 4552 if (fil_system.is_initialised()) { 4553 innodb_shutdown(); 4554 } 4555 return(false); 4556 } 4557 4558 if (srv_buf_pool_size >= 1000 * 1024 * 1024) { 4559 /* Here we still have srv_pool_size counted 4560 in kilobytes (in 4.0 this was in bytes) 4561 srv_boot() converts the value to 4562 pages; if buffer pool is less than 1000 MB, 4563 assume fewer threads. */ 4564 srv_max_n_threads = 50000; 4565 4566 } else if (srv_buf_pool_size >= 8 * 1024 * 1024) { 4567 4568 srv_max_n_threads = 10000; 4569 } else { 4570 srv_max_n_threads = 1000; /* saves several MB of memory, 4571 especially in 64-bit 4572 computers */ 4573 } 4574 4575 sync_check_init(); 4576 ut_d(sync_check_enable()); 4577 /* Reset the system variables in the recovery module. */ 4578 recv_sys_var_init(); 4579 trx_pool_init(); 4580 4581 ut_crc32_init(); 4582 crc_init(); 4583 recv_sys.create(); 4584 4585 #ifdef WITH_INNODB_DISALLOW_WRITES 4586 srv_allow_writes_event = os_event_create(0); 4587 os_event_set(srv_allow_writes_event); 4588 #endif 4589 4590 xb_filters_init(); 4591 4592 xb_fil_io_init(); 4593 srv_n_file_io_threads = srv_n_read_io_threads; 4594 4595 os_aio_init(srv_n_read_io_threads, srv_n_write_io_threads, 4596 SRV_MAX_N_PENDING_SYNC_IOS); 4597 4598 log_sys.create(); 4599 log_sys.log.create(srv_n_log_files); 4600 fil_space_t* space = fil_space_create( 4601 "innodb_redo_log", SRV_LOG_SPACE_FIRST_ID, 0, 4602 FIL_TYPE_LOG, NULL); 4603 4604 for (ulint i = 0; i < srv_n_log_files; i++) { 4605 open_or_create_log_file(space, i); 4606 } 4607 4608 /* create extra LSN dir if it does not exist. */ 4609 if (xtrabackup_extra_lsndir 4610 &&!my_stat(xtrabackup_extra_lsndir,&stat_info,MYF(0)) 4611 && (my_mkdir(xtrabackup_extra_lsndir,0777,MYF(0)) < 0)) { 4612 msg("Error: cannot mkdir %d: %s\n", 4613 my_errno, xtrabackup_extra_lsndir); 4614 goto fail; 4615 } 4616 4617 /* create target dir if not exist */ 4618 if (!xtrabackup_stream_str && !my_stat(xtrabackup_target_dir,&stat_info,MYF(0)) 4619 && (my_mkdir(xtrabackup_target_dir,0777,MYF(0)) < 0)){ 4620 msg("Error: cannot mkdir %d: %s\n", 4621 my_errno, xtrabackup_target_dir); 4622 goto fail; 4623 } 4624 4625 { 4626 /* definition from recv_recovery_from_checkpoint_start() */ 4627 ulint max_cp_field; 4628 4629 /* start back ground thread to copy newer log */ 4630 os_thread_id_t log_copying_thread_id; 4631 4632 /* get current checkpoint_lsn */ 4633 /* Look for the latest checkpoint from any of the log groups */ 4634 4635 log_mutex_enter(); 4636 4637 reread_log_header: 4638 dberr_t err = recv_find_max_checkpoint(&max_cp_field); 4639 4640 if (err != DB_SUCCESS) { 4641 msg("Error: cannot read redo log header"); 4642 log_mutex_exit(); 4643 goto fail; 4644 } 4645 4646 if (log_sys.log.format == 0) { 4647 msg("Error: cannot process redo log before MariaDB 10.2.2"); 4648 log_mutex_exit(); 4649 goto fail; 4650 } 4651 4652 const byte* buf = log_sys.checkpoint_buf; 4653 checkpoint_lsn_start = log_sys.log.get_lsn(); 4654 checkpoint_no_start = log_sys.next_checkpoint_no; 4655 4656 log_header_read(max_cp_field); 4657 4658 if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO) 4659 || checkpoint_lsn_start 4660 != mach_read_from_8(buf + LOG_CHECKPOINT_LSN) 4661 || log_sys.log.get_lsn_offset() 4662 != mach_read_from_8(buf + LOG_CHECKPOINT_OFFSET)) 4663 goto reread_log_header; 4664 4665 log_mutex_exit(); 4666 4667 xtrabackup_init_datasinks(); 4668 4669 if (!select_history()) { 4670 goto fail; 4671 } 4672 4673 /* open the log file */ 4674 memset(&stat_info, 0, sizeof(MY_STAT)); 4675 dst_log_file = ds_open(ds_redo, "ib_logfile0", &stat_info); 4676 if (dst_log_file == NULL) { 4677 msg("Error: failed to open the target stream for " 4678 "'ib_logfile0'."); 4679 goto fail; 4680 } 4681 4682 /* label it */ 4683 byte MY_ALIGNED(OS_FILE_LOG_BLOCK_SIZE) log_hdr_buf[LOG_FILE_HDR_SIZE]; 4684 memset(log_hdr_buf, 0, sizeof log_hdr_buf); 4685 4686 byte *log_hdr_field = log_hdr_buf; 4687 mach_write_to_4(LOG_HEADER_FORMAT + log_hdr_field, log_sys.log.format); 4688 mach_write_to_4(LOG_HEADER_SUBFORMAT + log_hdr_field, log_sys.log.subformat); 4689 mach_write_to_8(LOG_HEADER_START_LSN + log_hdr_field, checkpoint_lsn_start); 4690 strcpy(reinterpret_cast<char*>(LOG_HEADER_CREATOR + log_hdr_field), 4691 "Backup " MYSQL_SERVER_VERSION); 4692 log_block_set_checksum(log_hdr_field, 4693 log_block_calc_checksum_crc32(log_hdr_field)); 4694 4695 /* copied from log_group_checkpoint() */ 4696 log_hdr_field += 4697 (log_sys.next_checkpoint_no & 1) ? LOG_CHECKPOINT_2 : LOG_CHECKPOINT_1; 4698 /* The least significant bits of LOG_CHECKPOINT_OFFSET must be 4699 stored correctly in the copy of the ib_logfile. The most significant 4700 bits, which identify the start offset of the log block in the file, 4701 we did choose freely, as LOG_FILE_HDR_SIZE. */ 4702 ut_ad(!((log_sys.log.get_lsn() ^ checkpoint_lsn_start) 4703 & (OS_FILE_LOG_BLOCK_SIZE - 1))); 4704 /* Adjust the checkpoint page. */ 4705 memcpy(log_hdr_field, log_sys.checkpoint_buf, OS_FILE_LOG_BLOCK_SIZE); 4706 mach_write_to_8(log_hdr_field + LOG_CHECKPOINT_OFFSET, 4707 (checkpoint_lsn_start & (OS_FILE_LOG_BLOCK_SIZE - 1)) 4708 | LOG_FILE_HDR_SIZE); 4709 log_block_set_checksum(log_hdr_field, 4710 log_block_calc_checksum_crc32(log_hdr_field)); 4711 4712 /* Write log header*/ 4713 if (ds_write(dst_log_file, log_hdr_buf, sizeof(log_hdr_buf))) { 4714 msg("error: write to logfile failed"); 4715 goto fail; 4716 } 4717 4718 log_copying_running = true; 4719 /* start io throttle */ 4720 if(xtrabackup_throttle) { 4721 os_thread_id_t io_watching_thread_id; 4722 4723 io_ticket = xtrabackup_throttle; 4724 wait_throttle = os_event_create(0); 4725 io_watching_thread_running = true; 4726 4727 os_thread_create(io_watching_thread, NULL, 4728 &io_watching_thread_id); 4729 } 4730 4731 /* Populate fil_system with tablespaces to copy */ 4732 err = xb_load_tablespaces(); 4733 if (err != DB_SUCCESS) { 4734 msg("merror: xb_load_tablespaces() failed with" 4735 " error %s.", ut_strerr(err)); 4736 fail_before_log_copying_thread_start: 4737 log_copying_running = false; 4738 goto fail; 4739 } 4740 4741 /* copy log file by current position */ 4742 log_copy_scanned_lsn = checkpoint_lsn_start; 4743 recv_sys.recovered_lsn = log_copy_scanned_lsn; 4744 log_optimized_ddl_op = backup_optimized_ddl_op; 4745 4746 if (xtrabackup_copy_logfile()) 4747 goto fail_before_log_copying_thread_start; 4748 4749 DBUG_MARIABACKUP_EVENT("before_innodb_log_copy_thread_started",0); 4750 4751 log_copying_stop = os_event_create(0); 4752 os_thread_create(log_copying_thread, NULL, &log_copying_thread_id); 4753 4754 /* FLUSH CHANGED_PAGE_BITMAPS call */ 4755 if (!flush_changed_page_bitmaps()) { 4756 goto fail; 4757 } 4758 4759 ut_a(xtrabackup_parallel > 0); 4760 4761 if (xtrabackup_parallel > 1) { 4762 msg("mariabackup: Starting %u threads for parallel data " 4763 "files transfer", xtrabackup_parallel); 4764 } 4765 4766 if (opt_lock_ddl_per_table) { 4767 mdl_lock_all(); 4768 4769 DBUG_EXECUTE_IF("check_mdl_lock_works", 4770 dbug_alter_thread_done = 4771 dbug_start_query_thread("ALTER TABLE test.t ADD COLUMN mdl_lock_column int", 4772 "Waiting for table metadata lock", 0, 0);); 4773 } 4774 4775 datafiles_iter_t *it = datafiles_iter_new(); 4776 if (it == NULL) { 4777 msg("mariabackup: Error: datafiles_iter_new() failed."); 4778 goto fail; 4779 } 4780 4781 /* Create data copying threads */ 4782 data_threads = (data_thread_ctxt_t *) 4783 malloc(sizeof(data_thread_ctxt_t) * xtrabackup_parallel); 4784 count = xtrabackup_parallel; 4785 pthread_mutex_init(&count_mutex, NULL); 4786 4787 for (i = 0; i < (uint) xtrabackup_parallel; i++) { 4788 data_threads[i].it = it; 4789 data_threads[i].num = i+1; 4790 data_threads[i].count = &count; 4791 data_threads[i].count_mutex = &count_mutex; 4792 data_threads[i].corrupted_pages = &corrupted_pages; 4793 os_thread_create(data_copy_thread_func, data_threads + i, 4794 &data_threads[i].id); 4795 } 4796 4797 /* Wait for threads to exit */ 4798 while (1) { 4799 os_thread_sleep(1000000); 4800 pthread_mutex_lock(&count_mutex); 4801 bool stop = count == 0; 4802 pthread_mutex_unlock(&count_mutex); 4803 if (stop) { 4804 break; 4805 } 4806 } 4807 4808 pthread_mutex_destroy(&count_mutex); 4809 free(data_threads); 4810 datafiles_iter_free(it); 4811 } 4812 4813 bool ok = backup_start(corrupted_pages); 4814 4815 if (ok) { 4816 ok = xtrabackup_backup_low(); 4817 4818 backup_release(); 4819 4820 DBUG_EXECUTE_IF("check_mdl_lock_works", 4821 os_event_wait(dbug_alter_thread_done); 4822 os_event_destroy(dbug_alter_thread_done); 4823 ); 4824 4825 if (ok) { 4826 backup_finish(); 4827 } 4828 } 4829 4830 if (opt_log_innodb_page_corruption) 4831 ok = corrupted_pages.print_to_file(MB_CORRUPTED_PAGES_FILE); 4832 4833 if (!ok) { 4834 goto fail; 4835 } 4836 4837 if (changed_page_bitmap) { 4838 xb_page_bitmap_deinit(changed_page_bitmap); 4839 } 4840 xtrabackup_destroy_datasinks(); 4841 4842 msg("Redo log (from LSN " LSN_PF " to " LSN_PF 4843 ") was copied.", checkpoint_lsn_start, log_copy_scanned_lsn); 4844 xb_filters_free(); 4845 4846 xb_data_files_close(); 4847 4848 /* Make sure that the latest checkpoint was included */ 4849 if (metadata_to_lsn > log_copy_scanned_lsn) { 4850 msg("Error: failed to copy enough redo log (" 4851 "LSN=" LSN_PF "; checkpoint LSN=" LSN_PF ").", 4852 log_copy_scanned_lsn, metadata_to_lsn); 4853 goto fail; 4854 } 4855 4856 innodb_shutdown(); 4857 log_file_op = NULL; 4858 pthread_mutex_destroy(&backup_mutex); 4859 pthread_cond_destroy(&scanned_lsn_cond); 4860 if (!corrupted_pages.empty()) { 4861 ut_ad(opt_log_innodb_page_corruption); 4862 msg("Error: corrupted innodb pages are found and logged to " 4863 MB_CORRUPTED_PAGES_FILE " file"); 4864 } 4865 return(true); 4866 } 4867 4868 4869 /** 4870 This function handles DDL changes at the end of backup, under protection of 4871 FTWRL. This ensures consistent backup in presence of DDL. 4872 4873 - New tables, that were created during backup, are now copied into backup. 4874 Also, tablespaces with optimized (no redo loggin DDL) are re-copied into 4875 backup. This tablespaces will get the extension ".new" in the backup 4876 4877 - Tables that were renamed during backup, are marked as renamed 4878 For these, file <old_name>.ren will be created. 4879 The content of the file is the new tablespace name. 4880 4881 - Tables that were deleted during backup, are marked as deleted 4882 For these , an empty file <name>.del will be created 4883 4884 It is the responsibility of the prepare phase to deal with .new, .ren, and .del 4885 files. 4886 */ 4887 void backup_fix_ddl(CorruptedPages &corrupted_pages) 4888 { 4889 std::set<std::string> new_tables; 4890 std::set<std::string> dropped_tables; 4891 std::map<std::string, std::string> renamed_tables; 4892 4893 /* Disable further DDL on backed up tables (only needed for --no-lock).*/ 4894 pthread_mutex_lock(&backup_mutex); 4895 log_file_op = backup_file_op_fail; 4896 log_optimized_ddl_op = backup_optimized_ddl_op_fail; 4897 pthread_mutex_unlock(&backup_mutex); 4898 4899 DBUG_MARIABACKUP_EVENT("backup_fix_ddl",0); 4900 4901 for (space_id_to_name_t::iterator iter = ddl_tracker.tables_in_backup.begin(); 4902 iter != ddl_tracker.tables_in_backup.end(); 4903 iter++) { 4904 4905 const std::string name = iter->second; 4906 ulint id = iter->first; 4907 4908 if (ddl_tracker.drops.find(id) != ddl_tracker.drops.end()) { 4909 dropped_tables.insert(name); 4910 corrupted_pages.drop_space(id); 4911 continue; 4912 } 4913 4914 bool has_optimized_ddl = 4915 ddl_tracker.optimized_ddl.find(id) != ddl_tracker.optimized_ddl.end(); 4916 4917 if (ddl_tracker.id_to_name.find(id) == ddl_tracker.id_to_name.end()) { 4918 if (has_optimized_ddl) { 4919 new_tables.insert(name); 4920 } 4921 continue; 4922 } 4923 4924 /* tablespace was affected by DDL. */ 4925 const std::string new_name = ddl_tracker.id_to_name[id]; 4926 if (new_name != name) { 4927 if (has_optimized_ddl) { 4928 /* table was renamed, but we need a full copy 4929 of it because of optimized DDL. We emulate a drop/create.*/ 4930 dropped_tables.insert(name); 4931 if (opt_log_innodb_page_corruption) 4932 corrupted_pages.drop_space(id); 4933 new_tables.insert(new_name); 4934 } else { 4935 /* Renamed, and no optimized DDL*/ 4936 renamed_tables[name] = new_name; 4937 if (opt_log_innodb_page_corruption) 4938 corrupted_pages.rename_space(id, new_name); 4939 } 4940 } else if (has_optimized_ddl) { 4941 /* Table was recreated, or optimized DDL ran. 4942 In both cases we need a full copy in the backup.*/ 4943 new_tables.insert(name); 4944 if (opt_log_innodb_page_corruption) 4945 corrupted_pages.drop_space(id); 4946 } 4947 } 4948 4949 /* Find tables that were created during backup (and not removed).*/ 4950 for(space_id_to_name_t::iterator iter = ddl_tracker.id_to_name.begin(); 4951 iter != ddl_tracker.id_to_name.end(); 4952 iter++) { 4953 4954 ulint id = iter->first; 4955 std::string name = iter->second; 4956 4957 if (ddl_tracker.tables_in_backup.find(id) != ddl_tracker.tables_in_backup.end()) { 4958 /* already processed above */ 4959 continue; 4960 } 4961 4962 if (ddl_tracker.drops.find(id) == ddl_tracker.drops.end()) { 4963 dropped_tables.erase(name); 4964 new_tables.insert(name); 4965 if (opt_log_innodb_page_corruption) 4966 corrupted_pages.drop_space(id); 4967 } 4968 } 4969 4970 // Mark tablespaces for rename 4971 for (std::map<std::string, std::string>::iterator iter = renamed_tables.begin(); 4972 iter != renamed_tables.end(); ++iter) { 4973 const std::string old_name = iter->first; 4974 std::string new_name = iter->second; 4975 backup_file_printf((old_name + ".ren").c_str(), "%s", new_name.c_str()); 4976 } 4977 4978 // Mark tablespaces for drop 4979 for (std::set<std::string>::iterator iter = dropped_tables.begin(); 4980 iter != dropped_tables.end(); 4981 iter++) { 4982 const std::string name(*iter); 4983 backup_file_printf((name + ".del").c_str(), "%s", ""); 4984 } 4985 4986 // Load and copy new tables. 4987 // Close all datanodes first, reload only new tables. 4988 std::vector<fil_node_t *> all_nodes; 4989 datafiles_iter_t *it = datafiles_iter_new(); 4990 if (!it) 4991 return; 4992 while (fil_node_t *node = datafiles_iter_next(it)) { 4993 all_nodes.push_back(node); 4994 } 4995 for (size_t i = 0; i < all_nodes.size(); i++) { 4996 fil_node_t *n = all_nodes[i]; 4997 if (n->space->id == 0) 4998 continue; 4999 if (n->is_open()) { 5000 mutex_enter(&fil_system.mutex); 5001 n->close(); 5002 mutex_exit(&fil_system.mutex); 5003 } 5004 fil_space_free(n->space->id, false); 5005 } 5006 datafiles_iter_free(it); 5007 5008 DBUG_EXECUTE_IF("check_mdl_lock_works", DBUG_ASSERT(new_tables.size() == 0);); 5009 for (std::set<std::string>::iterator iter = new_tables.begin(); 5010 iter != new_tables.end(); iter++) { 5011 const char *space_name = iter->c_str(); 5012 if (check_if_skip_table(space_name)) 5013 continue; 5014 xb_load_single_table_tablespace(*iter, false); 5015 } 5016 5017 it = datafiles_iter_new(); 5018 if (!it) 5019 return; 5020 5021 while (fil_node_t *node = datafiles_iter_next(it)) { 5022 fil_space_t * space = node->space; 5023 if (!fil_is_user_tablespace_id(space->id)) 5024 continue; 5025 std::string dest_name(node->space->name); 5026 dest_name.append(".new"); 5027 xtrabackup_copy_datafile(node, 0, dest_name.c_str(), wf_write_through, 5028 corrupted_pages); 5029 } 5030 5031 datafiles_iter_free(it); 5032 } 5033 5034 /* ================= prepare ================= */ 5035 5036 /*********************************************************************** 5037 Generates path to the meta file path from a given path to an incremental .delta 5038 by replacing trailing ".delta" with ".meta", or returns error if 'delta_path' 5039 does not end with the ".delta" character sequence. 5040 @return TRUE on success, FALSE on error. */ 5041 static 5042 ibool 5043 get_meta_path( 5044 const char *delta_path, /* in: path to a .delta file */ 5045 char *meta_path) /* out: path to the corresponding .meta 5046 file */ 5047 { 5048 size_t len = strlen(delta_path); 5049 5050 if (len <= 6 || strcmp(delta_path + len - 6, ".delta")) { 5051 return FALSE; 5052 } 5053 memcpy(meta_path, delta_path, len - 6); 5054 strcpy(meta_path + len - 6, XB_DELTA_INFO_SUFFIX); 5055 5056 return TRUE; 5057 } 5058 5059 /****************************************************************//** 5060 Create a new tablespace on disk and return the handle to its opened 5061 file. Code adopted from fil_create_new_single_table_tablespace with 5062 the main difference that only disk file is created without updating 5063 the InnoDB in-memory dictionary data structures. 5064 5065 @return true on success, false on error. */ 5066 static 5067 bool 5068 xb_space_create_file( 5069 /*==================*/ 5070 const char* path, /*!<in: path to tablespace */ 5071 ulint space_id, /*!<in: space id */ 5072 ulint flags, /*!<in: tablespace flags */ 5073 pfs_os_file_t* file) /*!<out: file handle */ 5074 { 5075 bool ret; 5076 byte* buf; 5077 byte* page; 5078 5079 *file = os_file_create_simple_no_error_handling( 5080 0, path, OS_FILE_CREATE, OS_FILE_READ_WRITE, false, &ret); 5081 if (!ret) { 5082 msg("Can't create file %s", path); 5083 return ret; 5084 } 5085 5086 ret = os_file_set_size(path, *file, 5087 FIL_IBD_FILE_INITIAL_SIZE 5088 << srv_page_size_shift); 5089 if (!ret) { 5090 msg("mariabackup: cannot set size for file %s", path); 5091 os_file_close(*file); 5092 os_file_delete(0, path); 5093 return ret; 5094 } 5095 5096 buf = static_cast<byte *>(malloc(3U << srv_page_size_shift)); 5097 /* Align the memory for file i/o if we might have O_DIRECT set */ 5098 page = static_cast<byte *>(ut_align(buf, srv_page_size)); 5099 5100 memset(page, '\0', srv_page_size); 5101 5102 fsp_header_init_fields(page, space_id, flags); 5103 mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id); 5104 5105 const ulint zip_size = fil_space_t::zip_size(flags); 5106 5107 if (!zip_size) { 5108 buf_flush_init_for_writing( 5109 NULL, page, NULL, 0, 5110 fil_space_t::full_crc32(flags)); 5111 5112 ret = os_file_write(IORequestWrite, path, *file, page, 0, 5113 srv_page_size); 5114 } else { 5115 page_zip_des_t page_zip; 5116 page_zip_set_size(&page_zip, zip_size); 5117 page_zip.data = page + srv_page_size; 5118 fprintf(stderr, "zip_size = " ULINTPF "\n", zip_size); 5119 5120 #ifdef UNIV_DEBUG 5121 page_zip.m_start = 5122 #endif /* UNIV_DEBUG */ 5123 page_zip.m_end = page_zip.m_nonempty = 5124 page_zip.n_blobs = 0; 5125 5126 buf_flush_init_for_writing(NULL, page, &page_zip, 0, false); 5127 5128 ret = os_file_write(IORequestWrite, path, *file, 5129 page_zip.data, 0, zip_size); 5130 } 5131 5132 free(buf); 5133 5134 if (ret != DB_SUCCESS) { 5135 msg("mariabackup: could not write the first page to %s", 5136 path); 5137 os_file_close(*file); 5138 os_file_delete(0, path); 5139 return ret; 5140 } 5141 5142 return TRUE; 5143 } 5144 5145 static fil_space_t* fil_space_get_by_name(const char* name) 5146 { 5147 ut_ad(mutex_own(&fil_system.mutex)); 5148 for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list); 5149 space != NULL; 5150 space = UT_LIST_GET_NEXT(space_list, space)) 5151 if (!strcmp(space->name, name)) return space; 5152 return NULL; 5153 } 5154 5155 /*********************************************************************** 5156 Searches for matching tablespace file for given .delta file and space_id 5157 in given directory. When matching tablespace found, renames it to match the 5158 name of .delta file. If there was a tablespace with matching name and 5159 mismatching ID, renames it to xtrabackup_tmp_#ID.ibd. If there was no 5160 matching file, creates a new tablespace. 5161 @return file handle of matched or created file */ 5162 static 5163 pfs_os_file_t 5164 xb_delta_open_matching_space( 5165 const char* dbname, /* in: path to destination database dir */ 5166 const char* name, /* in: name of delta file (without .delta) */ 5167 const xb_delta_info_t& info, 5168 char* real_name, /* out: full path of destination file */ 5169 size_t real_name_len, /* out: buffer size for real_name */ 5170 bool* success) /* out: indicates error. true = success */ 5171 { 5172 char dest_dir[FN_REFLEN]; 5173 char dest_space_name[FN_REFLEN]; 5174 fil_space_t* fil_space; 5175 pfs_os_file_t file; 5176 xb_filter_entry_t* table; 5177 5178 ut_a(dbname != NULL || 5179 !fil_is_user_tablespace_id(info.space_id) || 5180 info.space_id == ULINT_UNDEFINED); 5181 5182 *success = false; 5183 5184 if (dbname) { 5185 snprintf(dest_dir, FN_REFLEN, "%s/%s", 5186 xtrabackup_target_dir, dbname); 5187 os_normalize_path(dest_dir); 5188 5189 snprintf(dest_space_name, FN_REFLEN, "%s/%s", dbname, name); 5190 } else { 5191 snprintf(dest_dir, FN_REFLEN, "%s", xtrabackup_target_dir); 5192 os_normalize_path(dest_dir); 5193 5194 snprintf(dest_space_name, FN_REFLEN, "%s", name); 5195 } 5196 5197 snprintf(real_name, real_name_len, 5198 "%s/%s", 5199 xtrabackup_target_dir, dest_space_name); 5200 os_normalize_path(real_name); 5201 /* Truncate ".ibd" */ 5202 dest_space_name[strlen(dest_space_name) - 4] = '\0'; 5203 5204 /* Create the database directory if it doesn't exist yet */ 5205 if (!os_file_create_directory(dest_dir, FALSE)) { 5206 msg("mariabackup: error: cannot create dir %s", dest_dir); 5207 return file; 5208 } 5209 5210 log_mutex_enter(); 5211 if (!fil_is_user_tablespace_id(info.space_id)) { 5212 found: 5213 /* open the file and return its handle */ 5214 5215 file = os_file_create_simple_no_error_handling( 5216 0, real_name, 5217 OS_FILE_OPEN, OS_FILE_READ_WRITE, false, success); 5218 5219 if (!*success) { 5220 msg("mariabackup: Cannot open file %s\n", real_name); 5221 } 5222 exit: 5223 log_mutex_exit(); 5224 return file; 5225 } 5226 5227 /* remember space name for further reference */ 5228 table = static_cast<xb_filter_entry_t *> 5229 (malloc(sizeof(xb_filter_entry_t) + 5230 strlen(dest_space_name) + 1)); 5231 5232 table->name = ((char*)table) + sizeof(xb_filter_entry_t); 5233 strcpy(table->name, dest_space_name); 5234 HASH_INSERT(xb_filter_entry_t, name_hash, inc_dir_tables_hash, 5235 ut_fold_string(table->name), table); 5236 5237 mutex_enter(&fil_system.mutex); 5238 fil_space = fil_space_get_by_name(dest_space_name); 5239 mutex_exit(&fil_system.mutex); 5240 5241 if (fil_space != NULL) { 5242 if (fil_space->id == info.space_id 5243 || info.space_id == ULINT_UNDEFINED) { 5244 /* we found matching space */ 5245 goto found; 5246 } else { 5247 5248 char tmpname[FN_REFLEN]; 5249 5250 snprintf(tmpname, FN_REFLEN, "%s/xtrabackup_tmp_#" ULINTPF, 5251 dbname, fil_space->id); 5252 5253 msg("mariabackup: Renaming %s to %s.ibd", 5254 fil_space->name, tmpname); 5255 5256 if (fil_space->rename(tmpname, NULL, false) 5257 != DB_SUCCESS) { 5258 msg("mariabackup: Cannot rename %s to %s", 5259 fil_space->name, tmpname); 5260 goto exit; 5261 } 5262 } 5263 } 5264 5265 if (info.space_id == ULINT_UNDEFINED) 5266 { 5267 die("Can't handle DDL operation on tablespace " 5268 "%s\n", dest_space_name); 5269 } 5270 mutex_enter(&fil_system.mutex); 5271 fil_space = fil_space_get_by_id(info.space_id); 5272 mutex_exit(&fil_system.mutex); 5273 if (fil_space != NULL) { 5274 char tmpname[FN_REFLEN]; 5275 5276 strncpy(tmpname, dest_space_name, FN_REFLEN); 5277 5278 msg("mariabackup: Renaming %s to %s", 5279 fil_space->name, dest_space_name); 5280 5281 if (fil_space->rename(tmpname, NULL, false) != DB_SUCCESS) 5282 { 5283 msg("mariabackup: Cannot rename %s to %s", 5284 fil_space->name, dest_space_name); 5285 goto exit; 5286 } 5287 5288 goto found; 5289 } 5290 5291 /* No matching space found. create the new one. */ 5292 const ulint flags = info.zip_size 5293 ? get_bit_shift(info.page_size 5294 >> (UNIV_ZIP_SIZE_SHIFT_MIN - 1)) 5295 << FSP_FLAGS_POS_ZIP_SSIZE 5296 | FSP_FLAGS_MASK_POST_ANTELOPE 5297 | FSP_FLAGS_MASK_ATOMIC_BLOBS 5298 | (srv_page_size == UNIV_PAGE_SIZE_ORIG 5299 ? 0 5300 : get_bit_shift(srv_page_size 5301 >> (UNIV_ZIP_SIZE_SHIFT_MIN - 1)) 5302 << FSP_FLAGS_POS_PAGE_SSIZE) 5303 : FSP_FLAGS_PAGE_SSIZE(); 5304 ut_ad(fil_space_t::zip_size(flags) == info.zip_size); 5305 ut_ad(fil_space_t::physical_size(flags) == info.page_size); 5306 5307 if (fil_space_create(dest_space_name, info.space_id, flags, 5308 FIL_TYPE_TABLESPACE, 0)) { 5309 *success = xb_space_create_file(real_name, info.space_id, 5310 flags, &file); 5311 } else { 5312 msg("Can't create tablespace %s\n", dest_space_name); 5313 } 5314 5315 goto exit; 5316 } 5317 5318 /************************************************************************ 5319 Applies a given .delta file to the corresponding data file. 5320 @return TRUE on success */ 5321 static 5322 ibool 5323 xtrabackup_apply_delta( 5324 const char* dirname, /* in: dir name of incremental */ 5325 const char* dbname, /* in: database name (ibdata: NULL) */ 5326 const char* filename, /* in: file name (not a path), 5327 including the .delta extension */ 5328 void* /*data*/) 5329 { 5330 pfs_os_file_t src_file; 5331 pfs_os_file_t dst_file; 5332 char src_path[FN_REFLEN]; 5333 char dst_path[FN_REFLEN]; 5334 char meta_path[FN_REFLEN]; 5335 char space_name[FN_REFLEN]; 5336 bool success; 5337 5338 ibool last_buffer = FALSE; 5339 ulint page_in_buffer; 5340 ulint incremental_buffers = 0; 5341 5342 xb_delta_info_t info(srv_page_size, 0, SRV_TMP_SPACE_ID); 5343 ulint page_size; 5344 ulint page_size_shift; 5345 byte* incremental_buffer_base = NULL; 5346 byte* incremental_buffer; 5347 5348 size_t offset; 5349 5350 ut_a(xtrabackup_incremental); 5351 5352 if (dbname) { 5353 snprintf(src_path, sizeof(src_path), "%s/%s/%s", 5354 dirname, dbname, filename); 5355 snprintf(dst_path, sizeof(dst_path), "%s/%s/%s", 5356 xtrabackup_real_target_dir, dbname, filename); 5357 } else { 5358 snprintf(src_path, sizeof(src_path), "%s/%s", 5359 dirname, filename); 5360 snprintf(dst_path, sizeof(dst_path), "%s/%s", 5361 xtrabackup_real_target_dir, filename); 5362 } 5363 dst_path[strlen(dst_path) - 6] = '\0'; 5364 5365 strncpy(space_name, filename, FN_REFLEN - 1); 5366 space_name[FN_REFLEN - 1] = '\0'; 5367 space_name[strlen(space_name) - 6] = 0; 5368 5369 if (!get_meta_path(src_path, meta_path)) { 5370 goto error; 5371 } 5372 5373 os_normalize_path(dst_path); 5374 os_normalize_path(src_path); 5375 os_normalize_path(meta_path); 5376 5377 if (!xb_read_delta_metadata(meta_path, &info)) { 5378 goto error; 5379 } 5380 5381 page_size = info.page_size; 5382 page_size_shift = get_bit_shift(page_size); 5383 msg("page size for %s is %zu bytes", 5384 src_path, page_size); 5385 if (page_size_shift < 10 || 5386 page_size_shift > UNIV_PAGE_SIZE_SHIFT_MAX) { 5387 msg("error: invalid value of page_size " 5388 "(%zu bytes) read from %s", page_size, meta_path); 5389 goto error; 5390 } 5391 5392 src_file = os_file_create_simple_no_error_handling( 5393 0, src_path, 5394 OS_FILE_OPEN, OS_FILE_READ_WRITE, false, &success); 5395 if (!success) { 5396 os_file_get_last_error(TRUE); 5397 msg("error: can't open %s", src_path); 5398 goto error; 5399 } 5400 5401 posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL); 5402 5403 dst_file = xb_delta_open_matching_space( 5404 dbname, space_name, info, 5405 dst_path, sizeof(dst_path), &success); 5406 if (!success) { 5407 msg("error: can't open %s", dst_path); 5408 goto error; 5409 } 5410 5411 posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED); 5412 5413 /* allocate buffer for incremental backup (4096 pages) */ 5414 incremental_buffer_base = static_cast<byte *> 5415 (malloc((page_size / 4 + 1) * page_size)); 5416 incremental_buffer = static_cast<byte *> 5417 (ut_align(incremental_buffer_base, 5418 page_size)); 5419 5420 msg("Applying %s to %s...", src_path, dst_path); 5421 5422 while (!last_buffer) { 5423 ulint cluster_header; 5424 5425 /* read to buffer */ 5426 /* first block of block cluster */ 5427 offset = ((incremental_buffers * (page_size / 4)) 5428 << page_size_shift); 5429 if (os_file_read(IORequestRead, src_file, 5430 incremental_buffer, offset, page_size) 5431 != DB_SUCCESS) { 5432 goto error; 5433 } 5434 5435 cluster_header = mach_read_from_4(incremental_buffer); 5436 switch(cluster_header) { 5437 case 0x78747261UL: /*"xtra"*/ 5438 break; 5439 case 0x58545241UL: /*"XTRA"*/ 5440 last_buffer = TRUE; 5441 break; 5442 default: 5443 msg("error: %s seems not " 5444 ".delta file.", src_path); 5445 goto error; 5446 } 5447 5448 /* FIXME: If the .delta modifies FSP_SIZE on page 0, 5449 extend the file to that size. */ 5450 5451 for (page_in_buffer = 1; page_in_buffer < page_size / 4; 5452 page_in_buffer++) { 5453 if (mach_read_from_4(incremental_buffer + page_in_buffer * 4) 5454 == 0xFFFFFFFFUL) 5455 break; 5456 } 5457 5458 ut_a(last_buffer || page_in_buffer == page_size / 4); 5459 5460 /* read whole of the cluster */ 5461 if (os_file_read(IORequestRead, src_file, 5462 incremental_buffer, 5463 offset, page_in_buffer * page_size) 5464 != DB_SUCCESS) { 5465 goto error; 5466 } 5467 5468 posix_fadvise(src_file, offset, page_in_buffer * page_size, 5469 POSIX_FADV_DONTNEED); 5470 5471 for (page_in_buffer = 1; page_in_buffer < page_size / 4; 5472 page_in_buffer++) { 5473 ulint offset_on_page; 5474 5475 offset_on_page = mach_read_from_4(incremental_buffer + page_in_buffer * 4); 5476 5477 if (offset_on_page == 0xFFFFFFFFUL) 5478 break; 5479 5480 uchar *buf = incremental_buffer + page_in_buffer * page_size; 5481 const os_offset_t off = os_offset_t(offset_on_page)*page_size; 5482 5483 if (off == 0) { 5484 /* Read tablespace size from page 0, 5485 and extend the file to specified size.*/ 5486 os_offset_t n_pages = mach_read_from_4( 5487 buf + FSP_HEADER_OFFSET + FSP_SIZE); 5488 if (mach_read_from_4(buf 5489 + FIL_PAGE_SPACE_ID)) { 5490 if (!os_file_set_size( 5491 dst_path, dst_file, 5492 n_pages * page_size)) 5493 goto error; 5494 } else if (fil_space_t* space 5495 = fil_system.sys_space) { 5496 /* The system tablespace can 5497 consist of multiple files. The 5498 first one has full tablespace 5499 size in page 0, but only the last 5500 file should be extended. */ 5501 fil_node_t* n = UT_LIST_GET_FIRST( 5502 space->chain); 5503 bool fail = !strcmp(n->name, dst_path) 5504 && !fil_space_extend( 5505 space, (ulint)n_pages); 5506 if (fail) goto error; 5507 } 5508 } 5509 5510 if (os_file_write(IORequestWrite, 5511 dst_path, dst_file, buf, off, 5512 page_size) != DB_SUCCESS) { 5513 goto error; 5514 } 5515 } 5516 5517 /* Free file system buffer cache after the batch was written. */ 5518 #ifdef __linux__ 5519 os_file_flush_func(dst_file); 5520 #endif 5521 posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED); 5522 5523 5524 incremental_buffers++; 5525 } 5526 5527 free(incremental_buffer_base); 5528 if (src_file != OS_FILE_CLOSED) { 5529 os_file_close(src_file); 5530 os_file_delete(0,src_path); 5531 } 5532 if (dst_file != OS_FILE_CLOSED) 5533 os_file_close(dst_file); 5534 return TRUE; 5535 5536 error: 5537 free(incremental_buffer_base); 5538 if (src_file != OS_FILE_CLOSED) 5539 os_file_close(src_file); 5540 if (dst_file != OS_FILE_CLOSED) 5541 os_file_close(dst_file); 5542 msg("Error: xtrabackup_apply_delta(): " 5543 "failed to apply %s to %s.\n", src_path, dst_path); 5544 return FALSE; 5545 } 5546 5547 5548 std::string change_extension(std::string filename, std::string new_ext) { 5549 DBUG_ASSERT(new_ext.size() == 3); 5550 std::string new_name(filename); 5551 new_name.resize(new_name.size() - new_ext.size()); 5552 new_name.append(new_ext); 5553 return new_name; 5554 } 5555 5556 5557 static void rename_file(const char *from,const char *to) { 5558 msg("Renaming %s to %s\n", from, to); 5559 if (my_rename(from, to, MY_WME)) { 5560 die("Can't rename %s to %s errno %d", from, to, errno); 5561 } 5562 } 5563 5564 static void rename_file(const std::string& from, const std::string &to) { 5565 rename_file(from.c_str(), to.c_str()); 5566 } 5567 /************************************************************************ 5568 Callback to handle datadir entry. Function of this type will be called 5569 for each entry which matches the mask by xb_process_datadir. 5570 @return should return TRUE on success */ 5571 typedef ibool (*handle_datadir_entry_func_t)( 5572 /*=========================================*/ 5573 const char* data_home_dir, /*!<in: path to datadir */ 5574 const char* db_name, /*!<in: database name */ 5575 const char* file_name, /*!<in: file name with suffix */ 5576 void* arg); /*!<in: caller-provided data */ 5577 5578 /** Rename, and replace destination file, if exists */ 5579 static void rename_force(const char *from, const char *to) { 5580 if (access(to, R_OK) == 0) { 5581 msg("Removing %s", to); 5582 if (my_delete(to, MYF(MY_WME))) { 5583 msg("Can't remove %s, errno %d", to, errno); 5584 exit(EXIT_FAILURE); 5585 } 5586 } 5587 rename_file(from,to); 5588 } 5589 5590 5591 /** During prepare phase, rename ".new" files, that were created in 5592 backup_fix_ddl() and backup_optimized_ddl_op(), to ".ibd". In the case of 5593 incremental backup, i.e. of arg argument is set, move ".new" files to 5594 destination directory and rename them to ".ibd", remove existing ".ibd.delta" 5595 and ".idb.meta" files in incremental directory to avoid applying delta to 5596 ".ibd" file. 5597 5598 @param[in] data_home_dir path to datadir 5599 @param[in] db_name database name 5600 @param[in] file_name file name with suffix 5601 @param[in] arg destination path, used in incremental backup to notify, that 5602 *.new file must be moved to destibation directory 5603 5604 @return true */ 5605 static ibool prepare_handle_new_files(const char *data_home_dir, 5606 const char *db_name, 5607 const char *file_name, void *arg) 5608 { 5609 const char *dest_dir = static_cast<const char *>(arg); 5610 std::string src_path = std::string(data_home_dir) + '/' + std::string(db_name) + '/' + file_name; 5611 /* Copy "*.new" files from incremental to base dir for incremental backup */ 5612 std::string dest_path= 5613 dest_dir ? std::string(dest_dir) + '/' + std::string(db_name) + 5614 '/' + file_name : src_path; 5615 5616 size_t index = dest_path.find(".new"); 5617 DBUG_ASSERT(index != std::string::npos); 5618 dest_path.replace(index, strlen(".ibd"), ".ibd"); 5619 rename_force(src_path.c_str(),dest_path.c_str()); 5620 5621 if (dest_dir) { 5622 /* remove delta and meta files to avoid delta applying for new file */ 5623 index = src_path.find(".new"); 5624 DBUG_ASSERT(index != std::string::npos); 5625 src_path.replace(index, std::string::npos, ".ibd.delta"); 5626 if (access(src_path.c_str(), R_OK) == 0) { 5627 msg("Removing %s", src_path.c_str()); 5628 if (my_delete(src_path.c_str(), MYF(MY_WME))) 5629 die("Can't remove %s, errno %d", src_path.c_str(), errno); 5630 } 5631 src_path.replace(index, std::string::npos, ".ibd.meta"); 5632 if (access(src_path.c_str(), R_OK) == 0) { 5633 msg("Removing %s", src_path.c_str()); 5634 if (my_delete(src_path.c_str(), MYF(MY_WME))) 5635 die("Can't remove %s, errno %d", src_path.c_str(), errno); 5636 } 5637 5638 /* add table name to the container to avoid it's deletion at the end of 5639 prepare */ 5640 std::string table_name = std::string(db_name) + '/' 5641 + std::string(file_name, file_name + strlen(file_name) - strlen(".new")); 5642 xb_filter_entry_t *table = static_cast<xb_filter_entry_t *> 5643 (malloc(sizeof(xb_filter_entry_t) + table_name.size() + 1)); 5644 table->name = ((char*)table) + sizeof(xb_filter_entry_t); 5645 strcpy(table->name, table_name.c_str()); 5646 HASH_INSERT(xb_filter_entry_t, name_hash, inc_dir_tables_hash, 5647 ut_fold_string(table->name), table); 5648 } 5649 5650 return TRUE; 5651 } 5652 5653 /************************************************************************ 5654 Callback to handle datadir entry. Deletes entry if it has no matching 5655 fil_space in fil_system directory. 5656 @return FALSE if delete attempt was unsuccessful */ 5657 static 5658 ibool 5659 rm_if_not_found( 5660 const char* data_home_dir, /*!<in: path to datadir */ 5661 const char* db_name, /*!<in: database name */ 5662 const char* file_name, /*!<in: file name with suffix */ 5663 void* arg __attribute__((unused))) 5664 { 5665 char name[FN_REFLEN]; 5666 xb_filter_entry_t* table; 5667 5668 snprintf(name, FN_REFLEN, "%s/%s", db_name, file_name); 5669 /* Truncate ".ibd" */ 5670 name[strlen(name) - 4] = '\0'; 5671 5672 HASH_SEARCH(name_hash, inc_dir_tables_hash, ut_fold_string(name), 5673 xb_filter_entry_t*, 5674 table, (void) 0, 5675 !strcmp(table->name, name)); 5676 5677 if (!table) { 5678 snprintf(name, FN_REFLEN, "%s/%s/%s", data_home_dir, 5679 db_name, file_name); 5680 return os_file_delete(0, name); 5681 } 5682 5683 return(TRUE); 5684 } 5685 5686 /** Function enumerates files in datadir (provided by path) which are matched 5687 by provided suffix. For each entry callback is called. 5688 5689 @param[in] path datadir path 5690 @param[in] suffix suffix to match against 5691 @param[in] func callback 5692 @param[in] func_arg arguments for the above callback 5693 5694 @return FALSE if callback for some entry returned FALSE */ 5695 static ibool xb_process_datadir(const char *path, const char *suffix, 5696 handle_datadir_entry_func_t func, 5697 void *func_arg = NULL) 5698 { 5699 ulint ret; 5700 char dbpath[OS_FILE_MAX_PATH+2]; 5701 os_file_dir_t dir; 5702 os_file_dir_t dbdir; 5703 os_file_stat_t dbinfo; 5704 os_file_stat_t fileinfo; 5705 ulint suffix_len; 5706 dberr_t err = DB_SUCCESS; 5707 static char current_dir[2]; 5708 5709 current_dir[0] = FN_CURLIB; 5710 current_dir[1] = 0; 5711 srv_data_home = current_dir; 5712 5713 suffix_len = strlen(suffix); 5714 5715 /* datafile */ 5716 dbdir = os_file_opendir(path); 5717 if (UNIV_UNLIKELY(dbdir != IF_WIN(INVALID_HANDLE_VALUE, nullptr))) { 5718 ret = fil_file_readdir_next_file(&err, path, dbdir, &fileinfo); 5719 while (ret == 0) { 5720 if (fileinfo.type == OS_FILE_TYPE_DIR) { 5721 goto next_file_item_1; 5722 } 5723 5724 if (strlen(fileinfo.name) > suffix_len 5725 && 0 == strcmp(fileinfo.name + 5726 strlen(fileinfo.name) - suffix_len, 5727 suffix)) { 5728 if (!func( 5729 path, NULL, 5730 fileinfo.name, func_arg)) 5731 { 5732 os_file_closedir(dbdir); 5733 return(FALSE); 5734 } 5735 } 5736 next_file_item_1: 5737 ret = fil_file_readdir_next_file(&err, 5738 path, dbdir, 5739 &fileinfo); 5740 } 5741 5742 os_file_closedir(dbdir); 5743 } else { 5744 msg("Can't open dir %s", path); 5745 } 5746 5747 /* single table tablespaces */ 5748 dir = os_file_opendir(path); 5749 5750 if (UNIV_UNLIKELY(dbdir == IF_WIN(INVALID_HANDLE_VALUE, nullptr))) { 5751 msg("Can't open dir %s", path); 5752 return TRUE; 5753 } 5754 5755 ret = fil_file_readdir_next_file(&err, path, dir, &dbinfo); 5756 while (ret == 0) { 5757 if (dbinfo.type == OS_FILE_TYPE_FILE 5758 || dbinfo.type == OS_FILE_TYPE_UNKNOWN) { 5759 5760 goto next_datadir_item; 5761 } 5762 5763 snprintf(dbpath, sizeof(dbpath), "%.*s/%.*s", 5764 OS_FILE_MAX_PATH/2-1, 5765 path, 5766 OS_FILE_MAX_PATH/2-1, 5767 dbinfo.name); 5768 5769 os_normalize_path(dbpath); 5770 5771 dbdir = os_file_opendir(dbpath); 5772 5773 if (dbdir != IF_WIN(INVALID_HANDLE_VALUE, nullptr)) { 5774 ret = fil_file_readdir_next_file(&err, dbpath, dbdir, 5775 &fileinfo); 5776 while (ret == 0) { 5777 5778 if (fileinfo.type == OS_FILE_TYPE_DIR) { 5779 5780 goto next_file_item_2; 5781 } 5782 5783 if (strlen(fileinfo.name) > suffix_len 5784 && 0 == strcmp(fileinfo.name + 5785 strlen(fileinfo.name) - 5786 suffix_len, 5787 suffix)) { 5788 /* The name ends in suffix; process 5789 the file */ 5790 if (!func( 5791 path, 5792 dbinfo.name, 5793 fileinfo.name, func_arg)) 5794 { 5795 os_file_closedir(dbdir); 5796 os_file_closedir(dir); 5797 return(FALSE); 5798 } 5799 } 5800 next_file_item_2: 5801 ret = fil_file_readdir_next_file(&err, 5802 dbpath, dbdir, 5803 &fileinfo); 5804 } 5805 5806 os_file_closedir(dbdir); 5807 } 5808 next_datadir_item: 5809 ret = fil_file_readdir_next_file(&err, 5810 path, 5811 dir, &dbinfo); 5812 } 5813 5814 os_file_closedir(dir); 5815 5816 return(TRUE); 5817 } 5818 5819 /************************************************************************ 5820 Applies all .delta files from incremental_dir to the full backup. 5821 @return TRUE on success. */ 5822 static 5823 ibool 5824 xtrabackup_apply_deltas() 5825 { 5826 return xb_process_datadir(xtrabackup_incremental_dir, ".delta", 5827 xtrabackup_apply_delta); 5828 } 5829 5830 5831 static 5832 void 5833 innodb_free_param() 5834 { 5835 srv_sys_space.shutdown(); 5836 free_tmpdir(&mysql_tmpdir_list); 5837 } 5838 5839 5840 /** Check if file exists*/ 5841 static bool file_exists(std::string name) 5842 { 5843 return access(name.c_str(), R_OK) == 0 ; 5844 } 5845 5846 /** Read file content into STL string */ 5847 static std::string read_file_as_string(const std::string file) { 5848 char content[FN_REFLEN]; 5849 FILE *f = fopen(file.c_str(), "r"); 5850 if (!f) { 5851 msg("Can not open %s", file.c_str()); 5852 } 5853 size_t len = fread(content, 1, FN_REFLEN, f); 5854 fclose(f); 5855 return std::string(content, len); 5856 } 5857 5858 /** Delete file- Provide verbose diagnostics and exit, if operation fails. */ 5859 static void delete_file(const std::string& file, bool if_exists = false) { 5860 if (if_exists && !file_exists(file)) 5861 return; 5862 if (my_delete(file.c_str(), MYF(MY_WME))) { 5863 die("Can't remove %s, errno %d", file.c_str(), errno); 5864 } 5865 } 5866 5867 /** 5868 Rename tablespace during prepare. 5869 Backup in its end phase may generate some .ren files, recording 5870 tablespaces that should be renamed in --prepare. 5871 */ 5872 static void rename_table_in_prepare(const std::string &datadir, const std::string& from , const std::string& to, 5873 const char *extension=0) { 5874 if (!extension) { 5875 static const char *extensions_nonincremental[] = { ".ibd", 0 }; 5876 static const char *extensions_incremental[] = { ".ibd.delta", ".ibd.meta", 0 }; 5877 const char **extensions = xtrabackup_incremental_dir ? 5878 extensions_incremental : extensions_nonincremental; 5879 for (size_t i = 0; extensions[i]; i++) { 5880 rename_table_in_prepare(datadir, from, to, extensions[i]); 5881 } 5882 return; 5883 } 5884 std::string src = std::string(datadir) + "/" + from + extension; 5885 std::string dest = std::string(datadir) + "/" + to + extension; 5886 std::string ren2, tmp; 5887 if (file_exists(dest)) { 5888 ren2= std::string(datadir) + "/" + to + ".ren"; 5889 if (!file_exists(ren2)) { 5890 msg("ERROR : File %s was not found, but expected during rename processing\n", ren2.c_str()); 5891 ut_a(0); 5892 } 5893 tmp = to + "#"; 5894 rename_table_in_prepare(datadir, to, tmp); 5895 } 5896 rename_file(src, dest); 5897 if (ren2.size()) { 5898 // Make sure the temp. renamed file is processed. 5899 std::string to2 = read_file_as_string(ren2); 5900 rename_table_in_prepare(datadir, tmp, to2); 5901 delete_file(ren2); 5902 } 5903 } 5904 5905 static ibool prepare_handle_ren_files(const char *datadir, const char *db, const char *filename, void *) { 5906 5907 std::string ren_file = std::string(datadir) + "/" + db + "/" + filename; 5908 if (!file_exists(ren_file)) 5909 return TRUE; 5910 5911 std::string to = read_file_as_string(ren_file); 5912 std::string source_space_name = std::string(db) + "/" + filename; 5913 source_space_name.resize(source_space_name.size() - 4); // remove extension 5914 5915 rename_table_in_prepare(datadir, source_space_name.c_str(), to.c_str()); 5916 delete_file(ren_file); 5917 return TRUE; 5918 } 5919 5920 /* Remove tablespaces during backup, based on */ 5921 static ibool prepare_handle_del_files(const char *datadir, const char *db, const char *filename, void *) { 5922 std::string del_file = std::string(datadir) + "/" + db + "/" + filename; 5923 std::string path(del_file); 5924 path.resize(path.size() - 4); // remove extension; 5925 if (xtrabackup_incremental) { 5926 delete_file(path + ".ibd.delta", true); 5927 delete_file(path + ".ibd.meta", true); 5928 } 5929 else { 5930 delete_file(path + ".ibd", true); 5931 } 5932 delete_file(del_file); 5933 return TRUE; 5934 } 5935 5936 /** Implement --prepare 5937 @return whether the operation succeeded */ 5938 static bool xtrabackup_prepare_func(char** argv) 5939 { 5940 CorruptedPages corrupted_pages; 5941 char metadata_path[FN_REFLEN]; 5942 5943 /* cd to target-dir */ 5944 5945 if (my_setwd(xtrabackup_real_target_dir,MYF(MY_WME))) 5946 { 5947 msg("can't my_setwd %s", xtrabackup_real_target_dir); 5948 return(false); 5949 } 5950 msg("cd to %s", xtrabackup_real_target_dir); 5951 5952 fil_path_to_mysql_datadir = "."; 5953 5954 ut_ad(xtrabackup_incremental == xtrabackup_incremental_dir); 5955 if (xtrabackup_incremental) { 5956 inc_dir_tables_hash = hash_create(1000); 5957 ut_ad(inc_dir_tables_hash); 5958 } 5959 5960 msg("open files limit requested %u, set to %u", 5961 (uint) xb_open_files_limit, 5962 xb_set_max_open_files(xb_open_files_limit)); 5963 5964 /* Fix DDL for prepare. Process .del,.ren, and .new files. 5965 The order in which files are processed, is important 5966 (see MDEV-18185, MDEV-18201) 5967 */ 5968 xb_process_datadir(xtrabackup_incremental_dir ? xtrabackup_incremental_dir : ".", 5969 ".del", prepare_handle_del_files); 5970 xb_process_datadir(xtrabackup_incremental_dir? xtrabackup_incremental_dir:".", 5971 ".ren", prepare_handle_ren_files); 5972 if (xtrabackup_incremental_dir) { 5973 xb_process_datadir(xtrabackup_incremental_dir, ".new.meta", prepare_handle_new_files); 5974 xb_process_datadir(xtrabackup_incremental_dir, ".new.delta", prepare_handle_new_files); 5975 xb_process_datadir(xtrabackup_incremental_dir, ".new", 5976 prepare_handle_new_files, (void *)"."); 5977 } 5978 else { 5979 xb_process_datadir(".", ".new", prepare_handle_new_files); 5980 } 5981 5982 int argc; for (argc = 0; argv[argc]; argc++) {} 5983 encryption_plugin_prepare_init(argc, argv); 5984 5985 xtrabackup_target_dir= mysql_data_home_buff; 5986 xtrabackup_target_dir[0]=FN_CURLIB; // all paths are relative from here 5987 xtrabackup_target_dir[1]=0; 5988 const lsn_t target_lsn = xtrabackup_incremental 5989 ? incremental_to_lsn : metadata_to_lsn; 5990 5991 /* 5992 read metadata of target 5993 */ 5994 sprintf(metadata_path, "%s/%s", xtrabackup_target_dir, 5995 XTRABACKUP_METADATA_FILENAME); 5996 5997 if (!xtrabackup_read_metadata(metadata_path)) { 5998 msg("Error: failed to read metadata from '%s'\n", 5999 metadata_path); 6000 return(false); 6001 } 6002 6003 if (!strcmp(metadata_type, "full-backuped")) { 6004 if (xtrabackup_incremental) { 6005 msg("error: applying incremental backup " 6006 "needs a prepared target."); 6007 return(false); 6008 } 6009 msg("This target seems to be not prepared yet."); 6010 } else if (!strcmp(metadata_type, "log-applied")) { 6011 msg("This target seems to be already prepared."); 6012 } else { 6013 msg("This target does not have correct metadata."); 6014 return(false); 6015 } 6016 6017 bool ok = !xtrabackup_incremental 6018 || metadata_to_lsn == incremental_lsn; 6019 if (!ok) { 6020 msg("error: This incremental backup seems " 6021 "not to be proper for the target. Check 'to_lsn' of the target and " 6022 "'from_lsn' of the incremental."); 6023 return(false); 6024 } 6025 6026 srv_max_n_threads = 1000; 6027 srv_undo_logs = 1; 6028 srv_n_purge_threads = 1; 6029 6030 xb_filters_init(); 6031 6032 srv_log_group_home_dir = NULL; 6033 srv_thread_concurrency = 1; 6034 6035 if (xtrabackup_incremental) { 6036 srv_operation = SRV_OPERATION_RESTORE_DELTA; 6037 6038 if (innodb_init_param()) { 6039 goto error_cleanup; 6040 } 6041 6042 sync_check_init(); 6043 ut_d(sync_check_enable()); 6044 ut_crc32_init(); 6045 recv_sys.create(); 6046 log_sys.create(); 6047 recv_recovery_on = true; 6048 6049 #ifdef WITH_INNODB_DISALLOW_WRITES 6050 srv_allow_writes_event = os_event_create(0); 6051 os_event_set(srv_allow_writes_event); 6052 #endif 6053 dberr_t err = xb_data_files_init(); 6054 if (err != DB_SUCCESS) { 6055 msg("mariabackup: error: xb_data_files_init() failed " 6056 "with error %s\n", ut_strerr(err)); 6057 goto error_cleanup; 6058 } 6059 6060 ok = xtrabackup_apply_deltas(); 6061 6062 xb_data_files_close(); 6063 6064 if (ok) { 6065 /* Cleanup datadir from tablespaces deleted 6066 between full and incremental backups */ 6067 6068 xb_process_datadir("./", ".ibd", rm_if_not_found); 6069 } 6070 6071 xb_filter_hash_free(inc_dir_tables_hash); 6072 6073 fil_system.close(); 6074 #ifdef WITH_INNODB_DISALLOW_WRITES 6075 os_event_destroy(srv_allow_writes_event); 6076 #endif 6077 innodb_free_param(); 6078 log_sys.close(); 6079 sync_check_close(); 6080 if (!ok) goto error_cleanup; 6081 } 6082 6083 srv_operation= 6084 xtrabackup_export 6085 ? SRV_OPERATION_RESTORE_EXPORT 6086 : (xtrabackup_rollback_xa ? SRV_OPERATION_RESTORE_ROLLBACK_XA 6087 : SRV_OPERATION_RESTORE); 6088 6089 if (innodb_init_param()) { 6090 goto error_cleanup; 6091 } 6092 6093 /* increase IO threads */ 6094 if (srv_n_file_io_threads < 10) { 6095 srv_n_read_io_threads = 4; 6096 srv_n_write_io_threads = 4; 6097 } 6098 6099 msg("Starting InnoDB instance for recovery."); 6100 6101 msg("mariabackup: Using %lld bytes for buffer pool " 6102 "(set by --use-memory parameter)", xtrabackup_use_memory); 6103 6104 srv_max_buf_pool_modified_pct = (double)max_buf_pool_modified_pct; 6105 6106 if (srv_max_dirty_pages_pct_lwm > srv_max_buf_pool_modified_pct) { 6107 srv_max_dirty_pages_pct_lwm = srv_max_buf_pool_modified_pct; 6108 } 6109 6110 if (xtrabackup_rollback_xa) 6111 srv_fast_shutdown= 0; 6112 6113 if (innodb_init()) { 6114 goto error_cleanup; 6115 } 6116 6117 corrupted_pages.read_from_file(MB_CORRUPTED_PAGES_FILE); 6118 if (xtrabackup_incremental) 6119 { 6120 char inc_filename[FN_REFLEN]; 6121 sprintf(inc_filename, "%s/%s", xtrabackup_incremental_dir, 6122 MB_CORRUPTED_PAGES_FILE); 6123 corrupted_pages.read_from_file(inc_filename); 6124 } 6125 if (!corrupted_pages.empty()) 6126 corrupted_pages.zero_out_free_pages(); 6127 if (corrupted_pages.empty()) 6128 { 6129 if (!xtrabackup_incremental && unlink(MB_CORRUPTED_PAGES_FILE) && 6130 errno != ENOENT) 6131 { 6132 char errbuf[MYSYS_STRERROR_SIZE]; 6133 my_strerror(errbuf, sizeof(errbuf), errno); 6134 die("Error: unlink %s failed: %s", MB_CORRUPTED_PAGES_FILE, 6135 errbuf); 6136 } 6137 } 6138 else 6139 corrupted_pages.print_to_file(MB_CORRUPTED_PAGES_FILE); 6140 6141 if (xtrabackup_rollback_xa) 6142 { 6143 /* Please do not merge MDEV-21168 fix in 10.5+ */ 6144 compile_time_assert(MYSQL_VERSION_ID < 10 * 10000 + 5 * 100); 6145 XID *xid_list= 6146 (XID *) my_malloc(MAX_XID_LIST_SIZE * sizeof(XID), MYF(0)); 6147 if (!xid_list) 6148 { 6149 msg("Can't allocate %i bytes for XID's list", MAX_XID_LIST_SIZE); 6150 ok= false; 6151 goto error_cleanup; 6152 } 6153 int got; 6154 ut_ad(recv_no_log_write); 6155 ut_d(recv_no_log_write= false); 6156 while ((got= trx_recover_for_mysql(xid_list, MAX_XID_LIST_SIZE)) > 0) 6157 { 6158 for (int i= 0; i < got; i++) 6159 { 6160 #ifndef DBUG_OFF 6161 int rc= 6162 #endif // !DBUG_OFF 6163 innobase_rollback_by_xid(NULL, xid_list + i); 6164 #ifndef DBUG_OFF 6165 if (rc == 0) 6166 { 6167 char buf[XIDDATASIZE * 4 + 6]; // see xid_to_str 6168 DBUG_PRINT("info", 6169 ("rollback xid %s", xid_to_str(buf, xid_list[i]))); 6170 } 6171 #endif // !DBUG_OFF 6172 } 6173 } 6174 ut_d(recv_no_log_write= true); 6175 my_free(xid_list); 6176 } 6177 6178 if (ok) { 6179 msg("Last binlog file %s, position %lld", 6180 trx_sys.recovered_binlog_filename, 6181 longlong(trx_sys.recovered_binlog_offset)); 6182 } 6183 6184 /* Check whether the log is applied enough or not. */ 6185 if ((srv_start_lsn || fil_space_get(SRV_LOG_SPACE_FIRST_ID)) 6186 && srv_start_lsn < target_lsn) { 6187 msg("mariabackup: error: " 6188 "The log was only applied up to LSN " LSN_PF 6189 ", instead of " LSN_PF, 6190 srv_start_lsn, target_lsn); 6191 ok = false; 6192 } 6193 #ifdef WITH_WSREP 6194 else if (ok) xb_write_galera_info(xtrabackup_incremental); 6195 #endif 6196 6197 if (xtrabackup_rollback_xa) 6198 { 6199 // See innobase_end() and thd_destructor_proxy() 6200 while (srv_fast_shutdown == 0 && 6201 (trx_sys.any_active_transactions() || 6202 THD_count::value() > srv_n_purge_threads + 1)) 6203 os_thread_sleep(1000); 6204 6205 srv_shutdown_bg_undo_sources(); 6206 srv_purge_shutdown(); 6207 buf_flush_sync_all_buf_pools(); 6208 } 6209 6210 innodb_shutdown(); 6211 innodb_free_param(); 6212 6213 /* output to metadata file */ 6214 if (ok) { 6215 char filename[FN_REFLEN]; 6216 6217 strcpy(metadata_type, "log-applied"); 6218 6219 if(xtrabackup_incremental 6220 && metadata_to_lsn < incremental_to_lsn) 6221 { 6222 metadata_to_lsn = incremental_to_lsn; 6223 metadata_last_lsn = incremental_last_lsn; 6224 } 6225 6226 sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME); 6227 if (!xtrabackup_write_metadata(filename)) { 6228 6229 msg("mariabackup: Error: failed to write metadata " 6230 "to '%s'", filename); 6231 ok = false; 6232 } else if (xtrabackup_extra_lsndir) { 6233 sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME); 6234 if (!xtrabackup_write_metadata(filename)) { 6235 msg("mariabackup: Error: failed to write " 6236 "metadata to '%s'", filename); 6237 ok = false; 6238 } 6239 } 6240 } 6241 6242 if (ok) ok = apply_log_finish(); 6243 6244 if (ok && xtrabackup_export) 6245 ok= (prepare_export() == 0); 6246 6247 error_cleanup: 6248 xb_filters_free(); 6249 return ok && !ib::error::was_logged() && corrupted_pages.empty(); 6250 } 6251 6252 /************************************************************************** 6253 Append group name to xb_load_default_groups list. */ 6254 static 6255 void 6256 append_defaults_group(const char *group, const char *default_groups[], 6257 size_t default_groups_size) 6258 { 6259 uint i; 6260 bool appended = false; 6261 for (i = 0; i < default_groups_size - 1; i++) { 6262 if (default_groups[i] == NULL) { 6263 default_groups[i] = group; 6264 appended = true; 6265 break; 6266 } 6267 } 6268 ut_a(appended); 6269 } 6270 6271 static const char* 6272 normalize_privilege_target_name(const char* name) 6273 { 6274 if (strcmp(name, "*") == 0) { 6275 return "\\*"; 6276 } 6277 else { 6278 /* should have no regex special characters. */ 6279 ut_ad(strpbrk(name, ".()[]*+?") == 0); 6280 } 6281 return name; 6282 } 6283 6284 /******************************************************************//** 6285 Check if specific privilege is granted. 6286 Uses regexp magic to check if requested privilege is granted for given 6287 database.table or database.* or *.* 6288 or if user has 'ALL PRIVILEGES' granted. 6289 @return true if requested privilege is granted, false otherwise. */ 6290 static bool 6291 has_privilege(const std::list<std::string> &granted, 6292 const char* required, 6293 const char* db_name, 6294 const char* table_name) 6295 { 6296 char buffer[1000]; 6297 regex_t priv_re; 6298 regmatch_t tables_regmatch[1]; 6299 bool result = false; 6300 6301 db_name = normalize_privilege_target_name(db_name); 6302 table_name = normalize_privilege_target_name(table_name); 6303 6304 int written = snprintf(buffer, sizeof(buffer), 6305 "GRANT .*(%s)|(ALL PRIVILEGES).* ON (\\*|`%s`)\\.(\\*|`%s`)", 6306 required, db_name, table_name); 6307 if (written < 0 || written == sizeof(buffer) 6308 || regcomp(&priv_re, buffer, REG_EXTENDED)) { 6309 die("regcomp() failed for '%s'", buffer); 6310 } 6311 6312 typedef std::list<std::string>::const_iterator string_iter; 6313 for (string_iter i = granted.begin(), e = granted.end(); i != e; ++i) { 6314 int res = regexec(&priv_re, i->c_str(), 6315 1, tables_regmatch, 0); 6316 6317 if (res != REG_NOMATCH) { 6318 result = true; 6319 break; 6320 } 6321 } 6322 6323 xb_regfree(&priv_re); 6324 return result; 6325 } 6326 6327 enum { 6328 PRIVILEGE_OK = 0, 6329 PRIVILEGE_WARNING = 1, 6330 PRIVILEGE_ERROR = 2, 6331 }; 6332 6333 /******************************************************************//** 6334 Check if specific privilege is granted. 6335 Prints error message if required privilege is missing. 6336 @return PRIVILEGE_OK if requested privilege is granted, error otherwise. */ 6337 static 6338 int check_privilege( 6339 const std::list<std::string> &granted_priv, /* in: list of 6340 granted privileges*/ 6341 const char* required, /* in: required privilege name */ 6342 const char* target_database, /* in: required privilege target 6343 database name */ 6344 const char* target_table, /* in: required privilege target 6345 table name */ 6346 int error = PRIVILEGE_ERROR) /* in: return value if privilege 6347 is not granted */ 6348 { 6349 if (!has_privilege(granted_priv, 6350 required, target_database, target_table)) { 6351 msg("%s: missing required privilege %s on %s.%s", 6352 (error == PRIVILEGE_ERROR ? "Error" : "Warning"), 6353 required, target_database, target_table); 6354 return error; 6355 } 6356 return PRIVILEGE_OK; 6357 } 6358 6359 6360 /** 6361 Check DB user privileges according to the intended actions. 6362 6363 Fetches DB user privileges, determines intended actions based on 6364 command-line arguments and prints missing privileges. 6365 @return whether all the necessary privileges are granted */ 6366 static bool check_all_privileges() 6367 { 6368 if (!mysql_connection) { 6369 /* Not connected, no queries is going to be executed. */ 6370 return true; 6371 } 6372 6373 /* Fetch effective privileges. */ 6374 std::list<std::string> granted_privileges; 6375 MYSQL_RES* result = xb_mysql_query(mysql_connection, "SHOW GRANTS", 6376 true); 6377 while (MYSQL_ROW row = mysql_fetch_row(result)) { 6378 granted_privileges.push_back(*row); 6379 } 6380 mysql_free_result(result); 6381 6382 int check_result = PRIVILEGE_OK; 6383 6384 /* FLUSH TABLES WITH READ LOCK */ 6385 if (!opt_no_lock) 6386 { 6387 check_result |= check_privilege( 6388 granted_privileges, 6389 "RELOAD", "*", "*"); 6390 check_result |= check_privilege( 6391 granted_privileges, 6392 "PROCESS", "*", "*"); 6393 } 6394 6395 /* KILL ... */ 6396 if ((!opt_no_lock && (opt_kill_long_queries_timeout || opt_lock_ddl_per_table)) 6397 /* START SLAVE SQL_THREAD */ 6398 /* STOP SLAVE SQL_THREAD */ 6399 || opt_safe_slave_backup) { 6400 check_result |= check_privilege( 6401 granted_privileges, 6402 "SUPER", "*", "*", 6403 PRIVILEGE_WARNING); 6404 } 6405 6406 /* SHOW MASTER STATUS */ 6407 /* SHOW SLAVE STATUS */ 6408 if (opt_galera_info || opt_slave_info 6409 || (opt_no_lock && opt_safe_slave_backup)) { 6410 check_result |= check_privilege(granted_privileges, 6411 "REPLICATION CLIENT", "*", "*", 6412 PRIVILEGE_WARNING); 6413 } 6414 6415 if (check_result & PRIVILEGE_ERROR) { 6416 msg("Current privileges, as reported by 'SHOW GRANTS': "); 6417 int n=1; 6418 for (std::list<std::string>::const_iterator it = granted_privileges.begin(); 6419 it != granted_privileges.end(); 6420 it++,n++) { 6421 msg(" %d.%s", n, it->c_str()); 6422 } 6423 return false; 6424 } 6425 6426 return true; 6427 } 6428 6429 bool 6430 xb_init() 6431 { 6432 const char *mixed_options[4] = {NULL, NULL, NULL, NULL}; 6433 int n_mixed_options; 6434 6435 /* sanity checks */ 6436 6437 if (opt_slave_info 6438 && opt_no_lock 6439 && !opt_safe_slave_backup) { 6440 msg("Error: --slave-info is used with --no-lock but " 6441 "without --safe-slave-backup. The binlog position " 6442 "cannot be consistent with the backup data."); 6443 return(false); 6444 } 6445 6446 if (xtrabackup_backup && opt_rsync) 6447 { 6448 if (xtrabackup_stream_fmt) 6449 { 6450 msg("Error: --rsync doesn't work with --stream\n"); 6451 return(false); 6452 } 6453 bool have_rsync = IF_WIN(false, (system("rsync --version > /dev/null 2>&1") == 0)); 6454 if (!have_rsync) 6455 { 6456 msg("Error: rsync executable not found, cannot run backup with --rsync\n"); 6457 return false; 6458 } 6459 } 6460 6461 n_mixed_options = 0; 6462 6463 if (opt_decompress) { 6464 mixed_options[n_mixed_options++] = "--decompress"; 6465 } 6466 6467 if (xtrabackup_copy_back) { 6468 mixed_options[n_mixed_options++] = "--copy-back"; 6469 } 6470 6471 if (xtrabackup_move_back) { 6472 mixed_options[n_mixed_options++] = "--move-back"; 6473 } 6474 6475 if (xtrabackup_prepare) { 6476 mixed_options[n_mixed_options++] = "--apply-log"; 6477 } 6478 6479 if (n_mixed_options > 1) { 6480 msg("Error: %s and %s are mutually exclusive\n", 6481 mixed_options[0], mixed_options[1]); 6482 return(false); 6483 } 6484 6485 if (xtrabackup_backup) { 6486 if ((mysql_connection = xb_mysql_connect()) == NULL) { 6487 return(false); 6488 } 6489 6490 if (!get_mysql_vars(mysql_connection)) { 6491 return(false); 6492 } 6493 if (opt_check_privileges && !check_all_privileges()) { 6494 return(false); 6495 } 6496 history_start_time = time(NULL); 6497 6498 } 6499 6500 return(true); 6501 } 6502 6503 6504 extern void init_signals(void); 6505 6506 #include <sql_locale.h> 6507 6508 6509 void setup_error_messages() 6510 { 6511 my_default_lc_messages = &my_locale_en_US; 6512 if (init_errmessage()) 6513 die("could not initialize error messages"); 6514 } 6515 6516 /** Handle mariabackup options. The options are handled with the following 6517 order: 6518 6519 1) Load server groups and process server options, ignore unknown options 6520 2) Load client groups and process client options, ignore unknown options 6521 3) Load backup groups and process client-server options, exit on unknown option 6522 4) Process --mysqld-args options, ignore unknown options 6523 6524 @param[in] argc arguments count 6525 @param[in] argv arguments array 6526 @param[out] argv_server server options including loaded from server groups 6527 @param[out] argv_client client options including loaded from client groups 6528 @param[out] argv_backup backup options including loaded from backup groups */ 6529 void handle_options(int argc, char **argv, char ***argv_server, 6530 char ***argv_client, char ***argv_backup) 6531 { 6532 /* Setup some variables for Innodb.*/ 6533 srv_operation = SRV_OPERATION_RESTORE; 6534 6535 files_charset_info = &my_charset_utf8_general_ci; 6536 6537 6538 setup_error_messages(); 6539 sys_var_init(); 6540 plugin_mutex_init(); 6541 mysql_prlock_init(key_rwlock_LOCK_system_variables_hash, &LOCK_system_variables_hash); 6542 opt_stack_trace = 1; 6543 test_flags |= TEST_SIGINT; 6544 init_signals(); 6545 #ifndef _WIN32 6546 /* Exit process on SIGINT. */ 6547 my_sigset(SIGINT, SIG_DFL); 6548 #endif 6549 6550 sf_leaking_memory = 1; /* don't report memory leaks on early exist */ 6551 6552 int i; 6553 int ho_error; 6554 6555 char* target_dir = NULL; 6556 bool prepare = false; 6557 6558 char conf_file[FN_REFLEN]; 6559 6560 // array_elements() will not work for load_defaults, as it is defined 6561 // as external symbol, so let's use dynamic array to have ability to 6562 // add new server default groups 6563 std::vector<const char *> server_default_groups; 6564 6565 for (const char **default_group= load_default_groups; *default_group; 6566 ++default_group) 6567 server_default_groups.push_back(*default_group); 6568 6569 std::vector<char *> mysqld_args; 6570 std::vector<char *> mariabackup_args; 6571 mysqld_args.push_back(argv[0]); 6572 mariabackup_args.push_back(argv[0]); 6573 6574 /* scan options for group and config file to load defaults from */ 6575 for (i= 1; i < argc; i++) 6576 { 6577 char *optend= strcend(argv[i], '='); 6578 if (mysqld_args.size() > 1 || 6579 strncmp(argv[i], "--mysqld-args", optend - argv[i]) == 0) 6580 { 6581 mysqld_args.push_back(argv[i]); 6582 continue; 6583 } 6584 else 6585 mariabackup_args.push_back(argv[i]); 6586 6587 if (strncmp(argv[i], "--defaults-group", optend - argv[i]) == 0) 6588 { 6589 defaults_group= optend + 1; 6590 server_default_groups.push_back(defaults_group); 6591 } 6592 else if (strncmp(argv[i], "--login-path", optend - argv[i]) == 0) 6593 { 6594 append_defaults_group(optend + 1, xb_client_default_groups, 6595 array_elements(xb_client_default_groups)); 6596 } 6597 else if (!strncmp(argv[i], "--prepare", optend - argv[i])) 6598 { 6599 prepare= true; 6600 } 6601 else if (!strncmp(argv[i], "--apply-log", optend - argv[i])) 6602 { 6603 prepare= true; 6604 } 6605 else if (!strncmp(argv[i], "--target-dir", optend - argv[i]) && 6606 *optend) 6607 { 6608 target_dir= optend + 1; 6609 } 6610 else if (!*optend && argv[i][0] != '-') 6611 { 6612 target_dir= argv[i]; 6613 } 6614 } 6615 6616 server_default_groups.push_back(NULL); 6617 snprintf(conf_file, sizeof(conf_file), "my"); 6618 6619 if (prepare && target_dir) { 6620 snprintf(conf_file, sizeof(conf_file), 6621 "%s/backup-my.cnf", target_dir); 6622 if (!strncmp(argv[1], "--defaults-file=", 16)) { 6623 /* Remove defaults-file*/ 6624 for (int i = 2; ; i++) { 6625 if ((argv[i-1]= argv[i]) == 0) 6626 break; 6627 } 6628 argc--; 6629 } 6630 } 6631 6632 mariabackup_args.push_back(nullptr); 6633 *argv_client= *argv_server= *argv_backup= &mariabackup_args[0]; 6634 int argc_backup= static_cast<int>(mariabackup_args.size() - 1); 6635 int argc_client= argc_backup; 6636 int argc_server= argc_backup; 6637 6638 /* 1) Load server groups and process server options, ignore unknown 6639 options */ 6640 6641 load_defaults_or_exit(conf_file, &server_default_groups[0], 6642 &argc_server, argv_server); 6643 6644 int n; 6645 for (n = 0; (*argv_server)[n]; n++) {}; 6646 argc_server = n; 6647 6648 print_param_str << 6649 "# This MySQL options file was generated by XtraBackup.\n" 6650 "[" << defaults_group << "]\n"; 6651 6652 /* We want xtrabackup to ignore unknown options, because it only 6653 recognizes a small subset of server variables */ 6654 my_getopt_skip_unknown = TRUE; 6655 6656 /* Reset u_max_value for all options, as we don't want the 6657 --maximum-... modifier to set the actual option values */ 6658 for (my_option *optp= xb_server_options; optp->name; optp++) { 6659 optp->u_max_value = (G_PTR *) &global_max_value; 6660 } 6661 6662 /* Throw a descriptive error if --defaults-file or --defaults-extra-file 6663 is not the first command line argument */ 6664 for (int i = 2 ; i < argc ; i++) { 6665 char *optend = strcend((argv)[i], '='); 6666 6667 if (optend - argv[i] == 15 && 6668 !strncmp(argv[i], "--defaults-file", optend - argv[i])) { 6669 die("--defaults-file must be specified first on the command line"); 6670 } 6671 if (optend - argv[i] == 21 && 6672 !strncmp(argv[i], "--defaults-extra-file", 6673 optend - argv[i])) { 6674 die("--defaults-extra-file must be specified first on the command line"); 6675 } 6676 } 6677 6678 if (argc_server > 0 6679 && (ho_error=handle_options(&argc_server, argv_server, 6680 xb_server_options, xb_get_one_option))) 6681 exit(ho_error); 6682 6683 /* 2) Load client groups and process client options, ignore unknown 6684 options */ 6685 6686 load_defaults_or_exit(conf_file, xb_client_default_groups, 6687 &argc_client, argv_client); 6688 6689 for (n = 0; (*argv_client)[n]; n++) {}; 6690 argc_client = n; 6691 6692 if (innobackupex_mode && argc_client > 0) { 6693 if (!ibx_handle_options(&argc_client, argv_client)) { 6694 exit(EXIT_FAILURE); 6695 } 6696 } 6697 6698 if (argc_client > 0 6699 && (ho_error=handle_options(&argc_client, argv_client, 6700 xb_client_options, xb_get_one_option))) 6701 exit(ho_error); 6702 6703 /* 3) Load backup groups and process client-server options, exit on 6704 unknown option */ 6705 6706 load_defaults_or_exit(conf_file, backup_default_groups, &argc_backup, 6707 argv_backup); 6708 for (n= 0; (*argv_backup)[n]; n++) 6709 { 6710 }; 6711 argc_backup= n; 6712 6713 my_handle_options_init_variables = FALSE; 6714 6715 if (argc_backup > 0 && 6716 (ho_error= handle_options(&argc_backup, argv_backup, 6717 xb_server_options, xb_get_one_option))) 6718 exit(ho_error); 6719 6720 /* Add back the program name handle_options removes */ 6721 ++argc_backup; 6722 --(*argv_backup); 6723 6724 if (innobackupex_mode && argc_backup > 0 && 6725 !ibx_handle_options(&argc_backup, argv_backup)) 6726 exit(EXIT_FAILURE); 6727 6728 my_getopt_skip_unknown = FALSE; 6729 6730 if (argc_backup > 0 && 6731 (ho_error= handle_options(&argc_backup, argv_backup, 6732 xb_client_options, xb_get_one_option))) 6733 exit(ho_error); 6734 6735 if (opt_password) 6736 { 6737 char *argument= opt_password; 6738 char *start= argument; 6739 opt_password= my_strdup(opt_password, MYF(MY_FAE)); 6740 while (*argument) 6741 *argument++= 'x'; // Destroy argument 6742 if (*start) 6743 start[1]= 0; 6744 } 6745 6746 /* 4) Process --mysqld-args options, ignore unknown options */ 6747 6748 my_getopt_skip_unknown = TRUE; 6749 6750 int argc_mysqld = static_cast<int>(mysqld_args.size()); 6751 if (argc_mysqld > 1) 6752 { 6753 char **argv_mysqld= &mysqld_args[0]; 6754 if ((ho_error= handle_options(&argc_mysqld, &argv_mysqld, 6755 xb_server_options, xb_get_one_option))) 6756 exit(ho_error); 6757 } 6758 6759 my_handle_options_init_variables = TRUE; 6760 6761 /* Reject command line arguments that don't look like options, i.e. are 6762 not of the form '-X' (single-character options) or '--option' (long 6763 options) */ 6764 for (int i = 0 ; i < argc_backup ; i++) { 6765 const char * const opt = (*argv_backup)[i]; 6766 6767 if (strncmp(opt, "--", 2) && 6768 !(strlen(opt) == 2 && opt[0] == '-')) { 6769 bool server_option = true; 6770 6771 for (int j = 0; j < argc_backup; j++) { 6772 if (opt == (*argv_backup)[j]) { 6773 server_option = false; 6774 break; 6775 } 6776 } 6777 6778 if (!server_option) { 6779 msg("mariabackup: Error:" 6780 " unknown argument: '%s'", opt); 6781 exit(EXIT_FAILURE); 6782 } 6783 } 6784 } 6785 } 6786 6787 static int main_low(char** argv); 6788 static int get_exepath(char *buf, size_t size, const char *argv0); 6789 6790 /* ================= main =================== */ 6791 int main(int argc, char **argv) 6792 { 6793 char **server_defaults; 6794 char **client_defaults; 6795 char **backup_defaults; 6796 6797 my_getopt_prefix_matching= 0; 6798 6799 if (get_exepath(mariabackup_exe,FN_REFLEN, argv[0])) 6800 strncpy(mariabackup_exe,argv[0], FN_REFLEN-1); 6801 6802 6803 if (argc > 1 ) 6804 { 6805 /* In "prepare export", we need to start mysqld 6806 Since it is not always be installed on the machine, 6807 we start "mariabackup --mysqld", which acts as mysqld 6808 */ 6809 if (strcmp(argv[1], "--mysqld") == 0) 6810 { 6811 extern int mysqld_main(int argc, char **argv); 6812 argc--; 6813 argv++; 6814 argv[0]+=2; 6815 return mysqld_main(argc, argv); 6816 } 6817 if(strcmp(argv[1], "--innobackupex") == 0) 6818 { 6819 argv++; 6820 argc--; 6821 innobackupex_mode = true; 6822 } 6823 } 6824 6825 if (argc > 1) 6826 strncpy(orig_argv1,argv[1],sizeof(orig_argv1) -1); 6827 6828 init_signals(); 6829 MY_INIT(argv[0]); 6830 6831 pthread_key_create(&THR_THD, NULL); 6832 my_pthread_setspecific_ptr(THR_THD, NULL); 6833 6834 xb_regex_init(); 6835 6836 capture_tool_command(argc, argv); 6837 6838 if (mysql_server_init(-1, NULL, NULL)) 6839 { 6840 die("mysql_server_init() failed"); 6841 } 6842 6843 system_charset_info = &my_charset_utf8_general_ci; 6844 key_map_full.set_all(); 6845 6846 logger.init_base(); 6847 logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE); 6848 mysql_mutex_init(key_LOCK_error_log, &LOCK_error_log, 6849 MY_MUTEX_INIT_FAST); 6850 6851 handle_options(argc, argv, &server_defaults, &client_defaults, 6852 &backup_defaults); 6853 6854 #ifndef DBUG_OFF 6855 if (dbug_option) { 6856 DBUG_SET_INITIAL(dbug_option); 6857 DBUG_SET(dbug_option); 6858 } 6859 #endif 6860 6861 int status = main_low(server_defaults); 6862 6863 backup_cleanup(); 6864 6865 if (innobackupex_mode) { 6866 ibx_cleanup(); 6867 } 6868 6869 free_defaults(server_defaults); 6870 free_defaults(client_defaults); 6871 free_defaults(backup_defaults); 6872 6873 #ifndef DBUG_OFF 6874 if (dbug_option) { 6875 DBUG_END(); 6876 } 6877 #endif 6878 6879 if (THR_THD) 6880 (void) pthread_key_delete(THR_THD); 6881 6882 logger.cleanup_base(); 6883 cleanup_errmsgs(); 6884 free_error_messages(); 6885 mysql_mutex_destroy(&LOCK_error_log); 6886 6887 if (status == EXIT_SUCCESS) { 6888 msg("completed OK!"); 6889 } 6890 6891 return status; 6892 } 6893 6894 static int main_low(char** argv) 6895 { 6896 if (innobackupex_mode) { 6897 if (!ibx_init()) { 6898 return(EXIT_FAILURE); 6899 } 6900 } 6901 6902 if (!xtrabackup_print_param && !xtrabackup_prepare 6903 && !strcmp(mysql_data_home, "./")) { 6904 if (!xtrabackup_print_param) 6905 usage(); 6906 msg("mariabackup: Error: Please set parameter 'datadir'"); 6907 return(EXIT_FAILURE); 6908 } 6909 6910 /* Expand target-dir, incremental-basedir, etc. */ 6911 6912 char cwd[FN_REFLEN]; 6913 my_getwd(cwd, sizeof(cwd), MYF(0)); 6914 6915 my_load_path(xtrabackup_real_target_dir, 6916 xtrabackup_target_dir, cwd); 6917 unpack_dirname(xtrabackup_real_target_dir, 6918 xtrabackup_real_target_dir); 6919 xtrabackup_target_dir= xtrabackup_real_target_dir; 6920 6921 if (xtrabackup_incremental_basedir) { 6922 my_load_path(xtrabackup_real_incremental_basedir, 6923 xtrabackup_incremental_basedir, cwd); 6924 unpack_dirname(xtrabackup_real_incremental_basedir, 6925 xtrabackup_real_incremental_basedir); 6926 xtrabackup_incremental_basedir = 6927 xtrabackup_real_incremental_basedir; 6928 } 6929 6930 if (xtrabackup_incremental_dir) { 6931 my_load_path(xtrabackup_real_incremental_dir, 6932 xtrabackup_incremental_dir, cwd); 6933 unpack_dirname(xtrabackup_real_incremental_dir, 6934 xtrabackup_real_incremental_dir); 6935 xtrabackup_incremental_dir = xtrabackup_real_incremental_dir; 6936 } 6937 6938 if (xtrabackup_extra_lsndir) { 6939 my_load_path(xtrabackup_real_extra_lsndir, 6940 xtrabackup_extra_lsndir, cwd); 6941 unpack_dirname(xtrabackup_real_extra_lsndir, 6942 xtrabackup_real_extra_lsndir); 6943 xtrabackup_extra_lsndir = xtrabackup_real_extra_lsndir; 6944 } 6945 6946 /* get default temporary directory */ 6947 if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0]) { 6948 opt_mysql_tmpdir = getenv("TMPDIR"); 6949 #if defined(__WIN__) 6950 if (!opt_mysql_tmpdir) { 6951 opt_mysql_tmpdir = getenv("TEMP"); 6952 } 6953 if (!opt_mysql_tmpdir) { 6954 opt_mysql_tmpdir = getenv("TMP"); 6955 } 6956 #endif 6957 if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0]) { 6958 opt_mysql_tmpdir = const_cast<char*>(DEFAULT_TMPDIR); 6959 } 6960 } 6961 6962 /* temporary setting of enough size */ 6963 srv_page_size_shift = UNIV_PAGE_SIZE_SHIFT_MAX; 6964 srv_page_size = UNIV_PAGE_SIZE_MAX; 6965 if (xtrabackup_backup && xtrabackup_incremental) { 6966 /* direct specification is only for --backup */ 6967 /* and the lsn is prior to the other option */ 6968 6969 char* endchar; 6970 int error = 0; 6971 incremental_lsn = strtoll(xtrabackup_incremental, &endchar, 10); 6972 if (*endchar != '\0') 6973 error = 1; 6974 6975 if (error) { 6976 msg("mariabackup: value '%s' may be wrong format for " 6977 "incremental option.", xtrabackup_incremental); 6978 return(EXIT_FAILURE); 6979 } 6980 } else if (xtrabackup_backup && xtrabackup_incremental_basedir) { 6981 char filename[FN_REFLEN]; 6982 6983 sprintf(filename, "%s/%s", xtrabackup_incremental_basedir, XTRABACKUP_METADATA_FILENAME); 6984 6985 if (!xtrabackup_read_metadata(filename)) { 6986 msg("mariabackup: error: failed to read metadata from " 6987 "%s", filename); 6988 return(EXIT_FAILURE); 6989 } 6990 6991 incremental_lsn = metadata_to_lsn; 6992 xtrabackup_incremental = xtrabackup_incremental_basedir; //dummy 6993 } else if (xtrabackup_prepare && xtrabackup_incremental_dir) { 6994 char filename[FN_REFLEN]; 6995 6996 sprintf(filename, "%s/%s", xtrabackup_incremental_dir, XTRABACKUP_METADATA_FILENAME); 6997 6998 if (!xtrabackup_read_metadata(filename)) { 6999 msg("mariabackup: error: failed to read metadata from " 7000 "%s", filename); 7001 return(EXIT_FAILURE); 7002 } 7003 7004 incremental_lsn = metadata_from_lsn; 7005 incremental_to_lsn = metadata_to_lsn; 7006 incremental_last_lsn = metadata_last_lsn; 7007 xtrabackup_incremental = xtrabackup_incremental_dir; //dummy 7008 7009 } else if (opt_incremental_history_name) { 7010 xtrabackup_incremental = opt_incremental_history_name; 7011 } else if (opt_incremental_history_uuid) { 7012 xtrabackup_incremental = opt_incremental_history_uuid; 7013 } else { 7014 xtrabackup_incremental = NULL; 7015 } 7016 7017 if (xtrabackup_stream && !xtrabackup_backup) { 7018 msg("Warning: --stream parameter is ignored, it only works together with --backup."); 7019 } 7020 7021 if (!xb_init()) { 7022 return(EXIT_FAILURE); 7023 } 7024 7025 /* --print-param */ 7026 if (xtrabackup_print_param) { 7027 printf("%s", print_param_str.str().c_str()); 7028 return(EXIT_SUCCESS); 7029 } 7030 7031 print_version(); 7032 if (xtrabackup_incremental) { 7033 msg("incremental backup from " LSN_PF " is enabled.", 7034 incremental_lsn); 7035 } 7036 7037 if (xtrabackup_export && innobase_file_per_table == FALSE) { 7038 msg("mariabackup: auto-enabling --innodb-file-per-table due to " 7039 "the --export option"); 7040 innobase_file_per_table = TRUE; 7041 } 7042 7043 /* cannot execute both for now */ 7044 { 7045 int num = 0; 7046 7047 if (xtrabackup_backup) num++; 7048 if (xtrabackup_prepare) num++; 7049 if (xtrabackup_copy_back) num++; 7050 if (xtrabackup_move_back) num++; 7051 if (xtrabackup_decrypt_decompress) num++; 7052 if (num != 1) { /* !XOR (for now) */ 7053 usage(); 7054 return(EXIT_FAILURE); 7055 } 7056 } 7057 7058 /* --backup */ 7059 if (xtrabackup_backup && !xtrabackup_backup_func()) { 7060 return(EXIT_FAILURE); 7061 } 7062 7063 /* --prepare */ 7064 if (xtrabackup_prepare 7065 && !xtrabackup_prepare_func(argv)) { 7066 return(EXIT_FAILURE); 7067 } 7068 7069 if (xtrabackup_copy_back || xtrabackup_move_back) { 7070 if (!check_if_param_set("datadir")) { 7071 mysql_data_home = get_default_datadir(); 7072 } 7073 if (!copy_back()) 7074 return(EXIT_FAILURE); 7075 } 7076 7077 if (xtrabackup_decrypt_decompress && !decrypt_decompress()) { 7078 return(EXIT_FAILURE); 7079 } 7080 7081 return(EXIT_SUCCESS); 7082 } 7083 7084 7085 static int get_exepath(char *buf, size_t size, const char *argv0) 7086 { 7087 #ifdef _WIN32 7088 DWORD ret = GetModuleFileNameA(NULL, buf, (DWORD)size); 7089 if (ret > 0) 7090 return 0; 7091 #elif defined(__linux__) 7092 ssize_t ret = readlink("/proc/self/exe", buf, size-1); 7093 if(ret > 0) 7094 return 0; 7095 #elif defined(__APPLE__) 7096 size_t ret = proc_pidpath(getpid(), buf, static_cast<uint32_t>(size)); 7097 if (ret > 0) { 7098 buf[ret] = 0; 7099 return 0; 7100 } 7101 #endif 7102 7103 return my_realpath(buf, argv0, 0); 7104 } 7105 7106 7107 #if defined (__SANITIZE_ADDRESS__) && defined (__linux__) 7108 /* Avoid LeakSanitizer's false positives. */ 7109 const char* __asan_default_options() 7110 { 7111 return "detect_leaks=0"; 7112 } 7113 #endif 7114