00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef XTRABACKUP_VERSION
00023 #define XTRABACKUP_VERSION "undefined"
00024 #endif
00025 #ifndef XTRABACKUP_REVISION
00026 #define XTRABACKUP_REVISION "undefined"
00027 #endif
00028
00029 #include <config.h>
00030 #include <string>
00031 #include <drizzled/internal/my_sys.h>
00032 #include <drizzled/charset.h>
00033 #include <drizzled/gettext.h>
00034 #include <drizzled/constrained_value.h>
00035 #include <drizzled/configmake.h>
00036 #include <drizzled/error/priority_t.h>
00037
00038 #include "ha_prototypes.h"
00039
00040 #include <boost/program_options.hpp>
00041 #include <boost/scoped_array.hpp>
00042 #include <boost/scoped_ptr.hpp>
00043
00044 typedef drizzled::charset_info_st CHARSET_INFO;
00045
00046 #define my_progname "xtrabackup"
00047
00048 #define MYSQL_VERSION_ID 50507
00049
00050 #include <univ.i>
00051 #include <os0file.h>
00052 #include <os0thread.h>
00053 #include <srv0start.h>
00054 #include <srv0srv.h>
00055 #include <trx0roll.h>
00056 #include <trx0trx.h>
00057 #include <trx0sys.h>
00058 #include <mtr0mtr.h>
00059 #include <row0ins.h>
00060 #include <row0mysql.h>
00061 #include <row0sel.h>
00062 #include <row0upd.h>
00063 #include <log0log.h>
00064 #include <log0recv.h>
00065 #include <lock0lock.h>
00066 #include <dict0crea.h>
00067 #include <btr0cur.h>
00068 #include <btr0btr.h>
00069 #include <btr0sea.h>
00070 #include <fsp0fsp.h>
00071 #include <sync0sync.h>
00072 #include <fil0fil.h>
00073 #include <trx0xa.h>
00074
00075 #ifdef INNODB_VERSION_SHORT
00076 #include <ibuf0ibuf.h>
00077 #else
00078 #error ENOCOOL
00079 #endif
00080
00081 #define IB_INT64 ib_int64_t
00082 #define LSN64 ib_uint64_t
00083 #define MACH_READ_64 mach_read_from_8
00084 #define MACH_WRITE_64 mach_write_to_8
00085 #define OS_MUTEX_CREATE() os_mutex_create()
00086 #define ut_dulint_zero 0
00087 #define ut_dulint_cmp(A, B) (A > B ? 1 : (A == B ? 0 : -1))
00088 #define ut_dulint_add(A, B) (A + B)
00089 #define ut_dulint_minus(A, B) (A - B)
00090 #define ut_dulint_align_down(A, B) (A & ~((ib_int64_t)B - 1))
00091 #define ut_dulint_align_up(A, B) ((A + B - 1) & ~((ib_int64_t)B - 1))
00092
00093 #ifdef __WIN__
00094 #define SRV_PATH_SEPARATOR '\\'
00095 #define SRV_PATH_SEPARATOR_STR "\\"
00096 #else
00097 #define SRV_PATH_SEPARATOR '/'
00098 #define SRV_PATH_SEPARATOR_STR "/"
00099 #endif
00100
00101 #ifndef UNIV_PAGE_SIZE_MAX
00102 #define UNIV_PAGE_SIZE_MAX UNIV_PAGE_SIZE
00103 #endif
00104 #ifndef UNIV_PAGE_SIZE_SHIFT_MAX
00105 #define UNIV_PAGE_SIZE_SHIFT_MAX UNIV_PAGE_SIZE_SHIFT
00106 #endif
00107
00108 using namespace drizzled;
00109 namespace po=boost::program_options;
00110
00111 namespace drizzled {
00112 bool errmsg_printf (error::priority_t, char const *format, ...);
00113
00114 bool errmsg_printf (error::priority_t, char const *format, ...)
00115 {
00116 bool rv;
00117 va_list args;
00118 va_start(args, format);
00119 rv= vfprintf(stderr, format, args);
00120 va_end(args);
00121 fprintf(stderr, "\n");
00122 return rv;
00123 }
00124
00125 }
00126
00127 #include "xtrabackup_api.h"
00128
00129
00130
00131 ulint
00132 recv_find_max_checkpoint(
00133
00134
00135 log_group_t** max_group,
00136 ulint* max_field);
00137
00138
00139
00140 void
00141 os_file_set_nocache(
00142
00143 int fd,
00144 const char* file_name,
00145 const char* operation_name);
00146
00147
00148
00149
00150
00151 #include <fcntl.h>
00152 #include <regex.h>
00153
00154 #ifdef POSIX_FADV_NORMAL
00155 #define USE_POSIX_FADVISE
00156 #endif
00157
00158
00159
00160
00161
00162
00163
00165 struct fil_node_struct {
00166 fil_space_t* space;
00168 char* name;
00169 ibool open;
00170 os_file_t handle;
00171 ibool is_raw_disk;
00173 ulint size;
00176 ulint n_pending;
00180 ulint n_pending_flushes;
00184 ib_int64_t modification_counter;
00186 ib_int64_t flush_counter;
00189 UT_LIST_NODE_T(fil_node_t) chain;
00191 UT_LIST_NODE_T(fil_node_t) LRU;
00193 ulint magic_n;
00194 };
00195
00196 struct fil_space_struct {
00197 char* name;
00199 ulint id;
00200 ib_int64_t tablespace_version;
00206 ibool mark;
00210 ibool stop_ios;
00214 ibool stop_ibuf_merges;
00217 ibool is_being_deleted;
00224 ulint purpose;
00226 UT_LIST_BASE_NODE_T(fil_node_t) chain;
00228 ulint size;
00232 ulint flags;
00233 ulint n_reserved_extents;
00236 ulint n_pending_flushes;
00239 ulint n_pending_ibuf_merges;
00245 hash_node_t hash;
00246 hash_node_t name_hash;
00247 #ifndef UNIV_HOTBACKUP
00248 rw_lock_t latch;
00250 #endif
00251 UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
00254 ibool is_in_unflushed_spaces;
00256 #ifdef XTRADB_BASED
00257 ibool is_corrupt;
00258 #endif
00259 UT_LIST_NODE_T(fil_space_t) space_list;
00261 ulint magic_n;
00262 };
00263
00264 typedef struct fil_system_struct fil_system_t;
00265
00266 struct fil_system_struct {
00267 #ifndef UNIV_HOTBACKUP
00268 mutex_t mutex;
00269 #ifdef XTRADB55
00270 mutex_t file_extend_mutex;
00271 #endif
00272 #endif
00273 hash_table_t* spaces;
00276 hash_table_t* name_hash;
00278 UT_LIST_BASE_NODE_T(fil_node_t) LRU;
00289 UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
00295 ulint n_open;
00296 ulint max_n_open;
00298 ib_int64_t modification_counter;
00300 ulint max_assigned_id;
00306 ib_int64_t tablespace_version;
00314 UT_LIST_BASE_NODE_T(fil_space_t) space_list;
00316 };
00317
00318 typedef struct {
00319 ulint page_size;
00320 } xb_delta_info_t;
00321
00322 extern fil_system_t* fil_system;
00323
00324
00325
00326
00327 bool innodb_inited= 0;
00328
00329
00330 char xtrabackup_real_target_dir[FN_REFLEN] = "./xtrabackup_backupfiles/";
00331 const char *xtrabackup_target_dir= xtrabackup_real_target_dir;
00332 bool xtrabackup_backup = false;
00333 bool xtrabackup_stats = false;
00334 bool xtrabackup_prepare = false;
00335 bool xtrabackup_print_param = false;
00336
00337 bool xtrabackup_export = false;
00338 bool xtrabackup_apply_log_only = false;
00339
00340 bool xtrabackup_suspend_at_end = false;
00341 uint64_t xtrabackup_use_memory = 100*1024*1024L;
00342 bool xtrabackup_create_ib_logfile = false;
00343
00344 long xtrabackup_throttle = 0;
00345 lint io_ticket;
00346 os_event_t wait_throttle = NULL;
00347
00348 bool xtrabackup_stream = false;
00349 const char *xtrabackup_incremental = NULL;
00350 LSN64 incremental_lsn;
00351 LSN64 incremental_to_lsn;
00352 LSN64 incremental_last_lsn;
00353 byte* incremental_buffer = NULL;
00354 byte* incremental_buffer_base = NULL;
00355
00356 const char *xtrabackup_incremental_basedir = NULL;
00357 const char *xtrabackup_extra_lsndir = NULL;
00358 char *xtrabackup_incremental_dir = NULL;
00359
00360 char *xtrabackup_tables = NULL;
00361 int tables_regex_num;
00362 regex_t *tables_regex;
00363 regmatch_t tables_regmatch[1];
00364
00365 const char *xtrabackup_tables_file = NULL;
00366 hash_table_t* tables_hash;
00367
00368 struct xtrabackup_tables_struct{
00369 char* name;
00370 hash_node_t name_hash;
00371 };
00372 typedef struct xtrabackup_tables_struct xtrabackup_tables_t;
00373
00374 #ifdef XTRADB_BASED
00375 static ulint thread_nr[SRV_MAX_N_IO_THREADS + 6 + 64];
00376 static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6 + 64];
00377 #else
00378 static ulint thread_nr[SRV_MAX_N_IO_THREADS + 6];
00379 static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6];
00380 #endif
00381
00382 LSN64 checkpoint_lsn_start;
00383 LSN64 checkpoint_no_start;
00384 LSN64 log_copy_scanned_lsn;
00385 IB_INT64 log_copy_offset = 0;
00386 ibool log_copying = TRUE;
00387 ibool log_copying_running = FALSE;
00388 ibool log_copying_succeed = FALSE;
00389
00390 ibool xtrabackup_logfile_is_renamed = FALSE;
00391
00392 uint parallel;
00393
00394
00395 #define XTRABACKUP_METADATA_FILENAME "xtrabackup_checkpoints"
00396 char metadata_type[30] = "";
00397
00398 ib_uint64_t metadata_from_lsn = 0;
00399 ib_uint64_t metadata_to_lsn = 0;
00400 ib_uint64_t metadata_last_lsn = 0;
00401
00402 #define XB_DELTA_INFO_SUFFIX ".meta"
00403
00404
00405 os_file_t dst_log = -1;
00406 char dst_log_path[FN_REFLEN];
00407
00408
00409 char mysql_real_data_home[FN_REFLEN] = "./";
00410 char *mysql_data_home= mysql_real_data_home;
00411 std::string mysql_data_home_arg;
00412 static char mysql_data_home_buff[2];
00413
00414 const char *opt_mysql_tmpdir = NULL;
00415
00416
00417
00418 #define HA_INNOBASE_ROWS_IN_TABLE 10000
00419 #define HA_INNOBASE_RANGE_COUNT 100
00420
00421 ulong innobase_large_page_size = 0;
00422
00423
00424
00425
00426 long innobase_additional_mem_pool_size = 1*1024*1024L;
00427 long innobase_buffer_pool_awe_mem_mb = 0;
00428 long innobase_file_io_threads = 4;
00429 long innobase_read_io_threads = 4;
00430 long innobase_write_io_threads = 4;
00431 long innobase_force_recovery = 0;
00432 long innobase_lock_wait_timeout = 50;
00433 long innobase_log_buffer_size = 1024*1024L;
00434 long innobase_log_files_in_group = 2;
00435 long innobase_log_files_in_group_backup;
00436 long innobase_mirrored_log_groups = 1;
00437 long innobase_open_files = 300L;
00438
00439 long innobase_page_size = (1 << 14);
00440 static ulong innobase_log_block_size = 512;
00441 bool innobase_fast_checksum = false;
00442 bool innobase_extra_undoslots = false;
00443 char* innobase_doublewrite_file = NULL;
00444
00445 uint64_t innobase_buffer_pool_size = 8*1024*1024L;
00446
00447 typedef constrained_check<int64_t, INT64_MAX, 1024*1024, 1024*1024> log_file_constraint;
00448 static log_file_constraint innobase_log_file_size;
00449
00450 uint64_t innobase_log_file_size_backup;
00451
00452
00453
00454
00455 char* innobase_data_home_dir = NULL;
00456 const char* innobase_data_file_path = NULL;
00457 char* innobase_log_group_home_dir = NULL;
00458 char* innobase_log_group_home_dir_backup = NULL;
00459 char* innobase_log_arch_dir = NULL;
00460
00461
00462 char* innobase_unix_file_flush_method = NULL;
00463
00464
00465
00466
00467 ulong innobase_fast_shutdown = 1;
00468 bool innobase_log_archive = FALSE;
00469 bool innobase_use_doublewrite = TRUE;
00470 bool innobase_use_checksums = TRUE;
00471 bool innobase_use_large_pages = FALSE;
00472 bool innobase_file_per_table = FALSE;
00473 bool innobase_locks_unsafe_for_binlog = FALSE;
00474 bool innobase_rollback_on_timeout = FALSE;
00475 bool innobase_create_status_file = FALSE;
00476 bool innobase_adaptive_hash_index = TRUE;
00477
00478 static char *internal_innobase_data_file_path = NULL;
00479
00480
00481
00482
00483
00484
00485 #define INNOBASE_WAKE_INTERVAL 32
00486 ulong innobase_active_counter = 0;
00487
00488 UNIV_INTERN
00489 bool
00490 innobase_isspace(
00491 const void *cs,
00492 char char_to_test)
00493 {
00494 return static_cast<const CHARSET_INFO*>(cs)->isspace(char_to_test);
00495 }
00496
00497 UNIV_INTERN
00498 void
00499 innobase_rec_to_mysql(
00500 Table* ,
00501 const rec_t* ,
00502 const dict_index_t* ,
00503 const ulint* );
00504
00505 UNIV_INTERN
00506 void
00507 innobase_rec_to_mysql(
00508
00509 Table* ,
00510 const rec_t* ,
00511 const dict_index_t* ,
00512 const ulint* )
00514 {
00515 fprintf(stderr, "ERROR: innobase_rec_to_mysql called\n");
00516 return;
00517 }
00518
00519 UNIV_INTERN
00520 void
00521 innobase_rec_reset(Table*);
00522
00523 UNIV_INTERN
00524 void
00525 innobase_rec_reset(
00526
00527 Table* )
00528 {
00529 fprintf(stderr, "ERROR: innobase_rec_reset called\n");
00530 return;
00531 }
00532
00533 UNIV_INTERN
00534 void
00535 thd_set_lock_wait_time(
00536
00537 drizzled::Session* ,
00538 ulint );
00540 UNIV_INTERN
00541 void
00542 thd_set_lock_wait_time(
00543
00544 drizzled::Session* ,
00545 ulint )
00546 {
00547 return;
00548 }
00549
00550
00551
00552
00553 typedef struct {
00554 fil_system_t *system;
00555 fil_space_t *space;
00556 fil_node_t *node;
00557 ibool started;
00558 os_mutex_t mutex;
00559 } datafiles_iter_t;
00560
00561 static
00562 datafiles_iter_t *
00563 datafiles_iter_new(fil_system_t *f_system)
00564 {
00565 datafiles_iter_t *it;
00566
00567 it = (datafiles_iter_t*) ut_malloc(sizeof(datafiles_iter_t));
00568 it->mutex = OS_MUTEX_CREATE();
00569
00570 it->system = f_system;
00571 it->space = NULL;
00572 it->node = NULL;
00573 it->started = FALSE;
00574
00575 return it;
00576 }
00577
00578 static
00579 fil_node_t *
00580 datafiles_iter_next(datafiles_iter_t *it, ibool *space_changed)
00581 {
00582 os_mutex_enter(it->mutex);
00583
00584 *space_changed = FALSE;
00585
00586 if (it->node == NULL) {
00587 if (it->started)
00588 goto end;
00589 it->started = TRUE;
00590 } else {
00591 it->node = UT_LIST_GET_NEXT(chain, it->node);
00592 if (it->node != NULL)
00593 goto end;
00594 }
00595
00596 it->space = (it->space == NULL) ?
00597 UT_LIST_GET_FIRST(it->system->space_list) :
00598 UT_LIST_GET_NEXT(space_list, it->space);
00599
00600 while (it->space != NULL &&
00601 (it->space->purpose != FIL_TABLESPACE ||
00602 UT_LIST_GET_LEN(it->space->chain) == 0))
00603 it->space = UT_LIST_GET_NEXT(space_list, it->space);
00604 if (it->space == NULL)
00605 goto end;
00606 *space_changed = TRUE;
00607
00608 it->node = UT_LIST_GET_FIRST(it->space->chain);
00609
00610 end:
00611 os_mutex_exit(it->mutex);
00612
00613 return it->node;
00614 }
00615
00616 static
00617 void
00618 datafiles_iter_free(datafiles_iter_t *it)
00619 {
00620 os_mutex_free(it->mutex);
00621 ut_free(it);
00622 }
00623
00624
00625
00626 typedef struct {
00627 datafiles_iter_t *it;
00628 uint num;
00629 uint *count;
00630 os_mutex_t count_mutex;
00631 os_thread_id_t id;
00632 } data_thread_ctxt_t;
00633
00634 static void print_version(void)
00635 {
00636 printf("%s Ver %s Rev %s for %s %s (%s)\n" ,my_progname,
00637 XTRABACKUP_VERSION, XTRABACKUP_REVISION, "Drizzle7",
00638 TARGET_OS, TARGET_CPU);
00639 }
00640
00641 static void usage(void)
00642 {
00643 puts("Open source backup tool for InnoDB and XtraDB\n\
00644 \n\
00645 Copyright (C) 2009 Percona Inc.\n\
00646 \n\
00647 This program is free software; you can redistribute it and/or\n\
00648 modify it under the terms of the GNU General Public License\n\
00649 as published by the Free Software Foundation version 2\n\
00650 of the License.\n\
00651 \n\
00652 This program is distributed in the hope that it will be useful,\n\
00653 but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
00654 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
00655 GNU General Public License for more details.\n\
00656 \n\
00657 You can download full text of the license on http://www.gnu.org/licenses/gpl-2.0.txt\n");
00658
00659 printf("Usage: [%s [--defaults-file=#] --backup | %s [--defaults-file=#] --prepare] [OPTIONS]\n",my_progname,my_progname);
00660
00661 }
00662
00663
00664
00665 UNIV_INTERN
00666 ibool
00667 thd_is_replication_slave_thread(
00668
00669 drizzled::Session* )
00670 {
00671 fprintf(stderr, "xtrabackup: thd_is_replication_slave_thread() is called\n");
00672 return(FALSE);
00673 }
00674
00675 UNIV_INTERN
00676 ibool
00677 thd_has_edited_nontrans_tables(
00678
00679 drizzled::Session *)
00680 {
00681 fprintf(stderr, "xtrabackup: thd_has_edited_nontrans_tables() is called\n");
00682 return(FALSE);
00683 }
00684
00685 UNIV_INTERN
00686 ibool
00687 thd_is_select(
00688
00689 const drizzled::Session *)
00690 {
00691 fprintf(stderr, "xtrabackup: thd_is_select() is called\n");
00692 return(false);
00693 }
00694
00695 UNIV_INTERN
00696 void
00697 innobase_mysql_print_thd(
00698 FILE*,
00699 drizzled::Session*,
00700 uint)
00701 {
00702 fprintf(stderr, "xtrabackup: innobase_mysql_print_thd() is called\n");
00703 }
00704
00705 void
00706 innobase_get_cset_width(
00707 ulint cset,
00708 ulint* mbminlen,
00709 ulint* mbmaxlen)
00710 {
00711 CHARSET_INFO* cs;
00712 ut_ad(cset < 256);
00713 ut_ad(mbminlen);
00714 ut_ad(mbmaxlen);
00715
00716 cs = all_charsets[cset];
00717 if (cs) {
00718 *mbminlen = cs->mbminlen;
00719 *mbmaxlen = cs->mbmaxlen;
00720 } else {
00721 ut_a(cset == 0);
00722 *mbminlen = *mbmaxlen = 0;
00723 }
00724 }
00725
00726 UNIV_INTERN
00727 void
00728 innobase_convert_from_table_id(
00729
00730 const void*,
00731 char* ,
00732 const char* ,
00733 ulint )
00734 {
00735 fprintf(stderr, "xtrabackup: innobase_convert_from_table_id() is called\n");
00736 }
00737
00738 UNIV_INTERN
00739 void
00740 innobase_convert_from_id(
00741
00742 const void*,
00743 char* ,
00744 const char* ,
00745 ulint )
00746 {
00747 fprintf(stderr, "xtrabackup: innobase_convert_from_id() is called\n");
00748 }
00749
00750 int
00751 innobase_strcasecmp(
00752 const char* a,
00753 const char* b)
00754 {
00755 return my_charset_utf8_general_ci.strcasecmp(a, b);
00756 }
00757
00758 void
00759 innobase_casedn_str(
00760 char* a)
00761 {
00762 my_charset_utf8_general_ci.casedn_str(a);
00763 }
00764
00765 UNIV_INTERN
00766 const char*
00767 innobase_get_stmt(
00768
00769 drizzled::Session *,
00770 size_t* )
00771 {
00772 fprintf(stderr, "xtrabackup: innobase_get_stmt() is called\n");
00773 return("nothing");
00774 }
00775
00776 int
00777 innobase_mysql_tmpfile(void)
00778 {
00779 char filename[FN_REFLEN];
00780 int fd2 = -1;
00781 int fd = internal::create_temp_file(filename, opt_mysql_tmpdir,
00782 "ib",
00783 #ifdef __WIN__
00784 O_BINARY | O_TRUNC | O_SEQUENTIAL |
00785 O_TEMPORARY | O_SHORT_LIVED |
00786 #endif
00787 O_CREAT | O_EXCL | O_RDWR);
00788 if (fd >= 0) {
00789 #ifndef __WIN__
00790
00791
00792
00793 unlink(filename);
00794 #endif
00795
00796
00797
00798
00799
00800
00801
00802
00803 fd2 = dup(fd);
00804 if (fd2 < 0) {
00805 fprintf(stderr, "xtrabackup: Got error %d on dup\n",fd2);
00806 }
00807 close(fd);
00808 }
00809 return(fd2);
00810 }
00811
00812 void
00813 innobase_invalidate_query_cache(
00814 trx_t* ,
00815 const char* ,
00816 ulint )
00817 {
00818
00819 }
00820
00821
00825 static
00826 char*
00827 innobase_convert_identifier(
00828
00829 char* buf,
00830 ulint buflen,
00831 const char* id,
00832 ulint idlen,
00833 void* ,
00834 ibool )
00836 {
00837 const char* s = id;
00838 int q;
00839
00840
00841 q = '"';
00842
00843 if (q == EOF) {
00844 if (UNIV_UNLIKELY(idlen > buflen)) {
00845 idlen = buflen;
00846 }
00847 memcpy(buf, s, idlen);
00848 return(buf + idlen);
00849 }
00850
00851
00852 if (buflen < 2) {
00853 return(buf);
00854 }
00855
00856 *buf++ = q;
00857 buflen--;
00858
00859 for (; idlen; idlen--) {
00860 int c = *s++;
00861 if (UNIV_UNLIKELY(c == q)) {
00862 if (UNIV_UNLIKELY(buflen < 3)) {
00863 break;
00864 }
00865
00866 *buf++ = c;
00867 *buf++ = c;
00868 buflen -= 2;
00869 } else {
00870 if (UNIV_UNLIKELY(buflen < 2)) {
00871 break;
00872 }
00873
00874 *buf++ = c;
00875 buflen--;
00876 }
00877 }
00878
00879 *buf++ = q;
00880 return(buf);
00881 }
00882
00883
00887 UNIV_INTERN
00888 char*
00889 innobase_convert_name(
00890
00891 char* buf,
00892 ulint buflen,
00893 const char* id,
00894 ulint idlen,
00895 drizzled::Session *session,
00896 ibool table_id)
00898 {
00899 char* s = buf;
00900 const char* bufend = buf + buflen;
00901
00902 if (table_id) {
00903 const char* slash = (const char*) memchr(id, '/', idlen);
00904 if (!slash) {
00905
00906 goto no_db_name;
00907 }
00908
00909
00910 s = innobase_convert_identifier(s, bufend - s, id, slash - id,
00911 session, TRUE);
00912 if (UNIV_LIKELY(s < bufend)) {
00913 *s++ = '.';
00914 s = innobase_convert_identifier(s, bufend - s,
00915 slash + 1, idlen
00916 - (slash - id) - 1,
00917 session, TRUE);
00918 }
00919 } else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
00920
00921 const char temp_index_suffix[]= "--temporary--";
00922
00923 s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
00924 session, FALSE);
00925 if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
00926 memcpy(s, temp_index_suffix,
00927 sizeof temp_index_suffix - 1);
00928 s += sizeof temp_index_suffix - 1;
00929 }
00930 } else {
00931 no_db_name:
00932 s = innobase_convert_identifier(buf, buflen, id, idlen,
00933 session, table_id);
00934 }
00935
00936 return(s);
00937
00938 }
00939
00940 ibool
00941 trx_is_interrupted(
00942 trx_t* )
00943 {
00944
00945 return(FALSE);
00946 }
00947
00948 UNIV_INTERN int
00949 innobase_mysql_cmp(
00950
00951 int mysql_type,
00952 uint charset_number,
00953 const unsigned char* a,
00954 unsigned int a_length,
00956 const unsigned char* b,
00957 unsigned int b_length);
00958
00959
00960 int
00961 innobase_mysql_cmp(
00962
00963
00964 int mysql_type,
00965 uint charset_number,
00966 const unsigned char* a,
00967 unsigned int a_length,
00968 const unsigned char* b,
00969 unsigned int b_length)
00970 {
00971 const CHARSET_INFO* charset;
00972 enum_field_types mysql_tp;
00973 int ret;
00974
00975 assert(a_length != UNIV_SQL_NULL);
00976 assert(b_length != UNIV_SQL_NULL);
00977
00978 mysql_tp = (enum_field_types) mysql_type;
00979
00980 switch (mysql_tp) {
00981
00982 case DRIZZLE_TYPE_BLOB:
00983 case DRIZZLE_TYPE_VARCHAR:
00984
00985
00986
00987
00988
00989 if (charset_number == default_charset_info->number) {
00990 charset = default_charset_info;
00991 } else {
00992 charset = get_charset(charset_number);
00993
00994 if (charset == NULL) {
00995 fprintf(stderr, "xtrabackup needs charset %lu for doing "
00996 "a comparison, but MySQL cannot "
00997 "find that charset.",
00998 (ulong) charset_number);
00999 ut_a(0);
01000 }
01001 }
01002
01003
01004
01005
01006
01007
01008 ret = charset->coll->strnncollsp(charset,
01009 a, a_length,
01010 b, b_length, 0);
01011 if (ret < 0) {
01012 return(-1);
01013 } else if (ret > 0) {
01014 return(1);
01015 } else {
01016 return(0);
01017 }
01018 default:
01019 ut_error;
01020 }
01021
01022 return(0);
01023 }
01024
01025 ulint
01026 innobase_get_at_most_n_mbchars(
01027 ulint charset_id,
01028 ulint prefix_len,
01029 ulint data_len,
01030 const char* str)
01031 {
01032 ulint char_length;
01033 ulint n_chars;
01034 const CHARSET_INFO* charset;
01035
01036 charset = get_charset((uint) charset_id);
01037
01038 ut_ad(charset);
01039 ut_ad(charset->mbmaxlen);
01040
01041
01042
01043 n_chars = prefix_len / charset->mbmaxlen;
01044
01045
01046
01047
01048
01049
01050 if (charset->mbmaxlen > 1) {
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 char_length = my_charpos(charset, str,
01070 str + data_len, (int) n_chars);
01071 if (char_length > data_len) {
01072 char_length = data_len;
01073 }
01074 } else {
01075 if (data_len < prefix_len) {
01076 char_length = data_len;
01077 } else {
01078 char_length = prefix_len;
01079 }
01080 }
01081
01082 return(char_length);
01083 }
01084
01085 UNIV_INTERN
01086 ulint
01087 innobase_raw_format(
01088
01089 const char* ,
01090 ulint ,
01092 ulint ,
01093 char* ,
01094 ulint )
01096 {
01097 fprintf(stderr, "xtrabackup: innobase_raw_format() is called\n");
01098 return(0);
01099 }
01100
01101 UNIV_INTERN
01102 ulong
01103 thd_lock_wait_timeout(
01104
01105 drizzled::Session*)
01107 {
01108 return(innobase_lock_wait_timeout);
01109 }
01110
01111 UNIV_INTERN
01112 ibool
01113 thd_supports_xa(
01114
01115 drizzled::Session* )
01117 {
01118 return(FALSE);
01119 }
01120
01121 ibool
01122 trx_is_strict(
01123
01124 trx_t*)
01125 {
01126 return(FALSE);
01127 }
01128
01129 #ifdef XTRADB_BASED
01130 trx_t*
01131 innobase_get_trx()
01132 {
01133 return(NULL);
01134 }
01135
01136 ibool
01137 innobase_get_slow_log()
01138 {
01139 return(FALSE);
01140 }
01141 #endif
01142
01143
01144
01145
01146 UNIV_INLINE
01147 ulint
01148 get_bit_shift(ulint value)
01149 {
01150 ulint shift;
01151
01152 if (value == 0)
01153 return 0;
01154
01155 for (shift = 0; !(value & 1UL); shift++) {
01156 value >>= 1;
01157 }
01158 return (value >> 1) ? 0 : shift;
01159 }
01160
01161 static bool
01162 innodb_init_param(void)
01163 {
01164
01165 static char current_dir[3];
01166 bool ret;
01167 char *default_path;
01168
01169
01170 get_charset_name(0);
01171
01172 #ifdef XTRADB_BASED
01173 srv_page_size = 0;
01174 srv_page_size_shift = 0;
01175
01176 if (innobase_page_size != (1 << 14)) {
01177 int n_shift = get_bit_shift(innobase_page_size);
01178
01179 if (n_shift >= 12 && n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX) {
01180 fprintf(stderr,
01181 "InnoDB: Warning: innodb_page_size has been "
01182 "changed from default value 16384.\n");
01183 srv_page_size_shift = n_shift;
01184 srv_page_size = 1 << n_shift;
01185 fprintf(stderr,
01186 "InnoDB: The universal page size of the "
01187 "database is set to %lu.\n", srv_page_size);
01188 } else {
01189 fprintf(stderr, "InnoDB: Error: invalid value of "
01190 "innobase_page_size: %lu", innobase_page_size);
01191 exit(EXIT_FAILURE);
01192 }
01193 } else {
01194 srv_page_size_shift = 14;
01195 srv_page_size = (1 << srv_page_size_shift);
01196 }
01197
01198 srv_log_block_size = 0;
01199 if (innobase_log_block_size != 512) {
01200 uint n_shift = get_bit_shift(innobase_log_block_size);;
01201
01202 fprintf(stderr,
01203 "InnoDB: Warning: innodb_log_block_size has "
01204 "been changed from its default value. "
01205 "(###EXPERIMENTAL### operation)\n");
01206 if (n_shift > 0) {
01207 srv_log_block_size = (1 << n_shift);
01208 fprintf(stderr,
01209 "InnoDB: The log block size is set to %lu.\n",
01210 srv_log_block_size);
01211 }
01212 } else {
01213 srv_log_block_size = 512;
01214 }
01215
01216 if (!srv_log_block_size) {
01217 fprintf(stderr,
01218 "InnoDB: Error: %lu is not valid value for "
01219 "innodb_log_block_size.\n", innobase_log_block_size);
01220 goto error;
01221 }
01222
01223 srv_fast_checksum = (ibool) innobase_fast_checksum;
01224 #endif
01225
01226
01227 if (sizeof(ulint) == 4) {
01228 if (xtrabackup_use_memory > UINT32_MAX) {
01229 fprintf(stderr,
01230 "xtrabackup: use-memory can't be over 4GB"
01231 " on 32-bit systems\n");
01232 }
01233
01234 if (innobase_buffer_pool_size > UINT32_MAX) {
01235 fprintf(stderr,
01236 "xtrabackup: innobase_buffer_pool_size can't be over 4GB"
01237 " on 32-bit systems\n");
01238
01239 goto error;
01240 }
01241
01242 if (innobase_log_file_size > UINT32_MAX) {
01243 fprintf(stderr,
01244 "xtrabackup: innobase_log_file_size can't be over 4GB"
01245 " on 32-bit systemsi\n");
01246
01247 goto error;
01248 }
01249 }
01250
01251 os_innodb_umask = (ulint)0664;
01252
01253
01254
01255
01256
01257
01258
01259
01260 current_dir[0] = FN_CURLIB;
01261 current_dir[1] = FN_LIBCHAR;
01262 current_dir[2] = 0;
01263 default_path = current_dir;
01264
01265 ut_a(default_path);
01266
01267
01268
01269
01270 if (xtrabackup_backup || xtrabackup_stats) {
01271 fprintf(stderr, "xtrabackup: Target instance is assumed as followings.\n");
01272 } else {
01273 fprintf(stderr, "xtrabackup: Temporary instance for recovery is set as followings.\n");
01274 }
01275
01276
01277
01278
01279
01280 srv_data_home = ((xtrabackup_backup || xtrabackup_stats) && innobase_data_home_dir
01281 ? innobase_data_home_dir : default_path);
01282 fprintf(stderr, "xtrabackup: innodb_data_home_dir = %s\n", srv_data_home);
01283
01284
01285
01286
01287
01288 if (!innobase_data_file_path) {
01289 innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
01290 }
01291 fprintf(stderr, "xtrabackup: innodb_data_file_path = %s\n",
01292 innobase_data_file_path);
01293
01294
01295
01296
01297 internal_innobase_data_file_path = strdup(innobase_data_file_path);
01298
01299 ret = (bool) srv_parse_data_file_paths_and_sizes(
01300 internal_innobase_data_file_path);
01301 if (ret == FALSE) {
01302 fprintf(stderr,
01303 "xtrabackup: syntax error in innodb_data_file_path\n");
01304 mem_free_and_error:
01305 free(internal_innobase_data_file_path);
01306 goto error;
01307 }
01308
01309 if (xtrabackup_prepare) {
01310
01311 ulint i;
01312
01313 for (i=0; i < srv_n_data_files; i++) {
01314 char *p;
01315
01316 p = srv_data_file_names[i];
01317 while ((p = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
01318 {
01319 p++;
01320 srv_data_file_names[i] = p;
01321 }
01322 }
01323 }
01324
01325 #ifdef XTRADB_BASED
01326 srv_doublewrite_file = innobase_doublewrite_file;
01327 #ifndef XTRADB55
01328 srv_extra_undoslots = (ibool) innobase_extra_undoslots;
01329 #endif
01330 #endif
01331
01332
01333
01334
01335
01336 if (!((xtrabackup_backup || xtrabackup_stats) && innobase_log_group_home_dir)) {
01337 innobase_log_group_home_dir = default_path;
01338 }
01339 if (xtrabackup_prepare && xtrabackup_incremental_dir) {
01340 innobase_log_group_home_dir = xtrabackup_incremental_dir;
01341 }
01342 fprintf(stderr, "xtrabackup: innodb_log_group_home_dir = %s\n",
01343 innobase_log_group_home_dir);
01344
01345 #ifdef UNIV_LOG_ARCHIVE
01346
01347
01348
01349
01350 innobase_log_arch_dir = innobase_log_group_home_dir;
01351
01352 srv_arch_dir = innobase_log_arch_dir;
01353 #endif
01354
01355 ret = (bool)
01356 srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
01357
01358 if (ret == FALSE || innobase_mirrored_log_groups != 1) {
01359 fprintf(stderr, "xtrabackup: syntax error in innodb_log_group_home_dir, or a "
01360 "wrong number of mirrored log groups\n");
01361
01362 goto mem_free_and_error;
01363 }
01364
01365 srv_adaptive_flushing = FALSE;
01366 srv_use_sys_malloc = TRUE;
01367 srv_file_format = 1;
01368 srv_max_file_format_at_startup = DICT_TF_FORMAT_51;
01369
01370
01371
01372 srv_file_flush_method_str = innobase_unix_file_flush_method;
01373
01374 srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
01375 srv_n_log_files = (ulint) innobase_log_files_in_group;
01376 srv_log_file_size = (ulint) innobase_log_file_size;
01377 fprintf(stderr, "xtrabackup: innodb_log_files_in_group = %ld\n",
01378 srv_n_log_files);
01379 fprintf(stderr, "xtrabackup: innodb_log_file_size = %ld\n",
01380 srv_log_file_size);
01381
01382 #ifdef UNIV_LOG_ARCHIVE
01383 srv_log_archive_on = (ulint) innobase_log_archive;
01384 #endif
01385 srv_log_buffer_size = (ulint) innobase_log_buffer_size;
01386
01387
01388
01389
01390
01391 srv_buf_pool_size = (ulint) xtrabackup_use_memory;
01392
01393 srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
01394
01395 srv_n_file_io_threads = (ulint) innobase_file_io_threads;
01396
01397 srv_n_read_io_threads = (ulint) innobase_read_io_threads;
01398 srv_n_write_io_threads = (ulint) innobase_write_io_threads;
01399
01400 srv_force_recovery = (ulint) innobase_force_recovery;
01401
01402 srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
01403 srv_use_checksums = (ibool) innobase_use_checksums;
01404
01405 btr_search_enabled = innobase_adaptive_hash_index ? true : false;
01406
01407 os_use_large_pages = (ibool) innobase_use_large_pages;
01408 os_large_page_size = (ulint) innobase_large_page_size;
01409
01410 row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
01411
01412 srv_file_per_table = innobase_file_per_table ? true : false;
01413
01414 srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
01415
01416 srv_max_n_open_files = (ulint) innobase_open_files;
01417 srv_innodb_status = (ibool) innobase_create_status_file;
01418
01419 srv_print_verbose_log = 1;
01420
01421
01422
01423
01424
01425 data_mysql_default_charset_coll = (ulint)default_charset_info->number;
01426
01427 ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443 #ifdef __WIN__
01444 switch (os_get_os_version()) {
01445 case OS_WIN95:
01446 case OS_WIN31:
01447 case OS_WINNT:
01448
01449
01450
01451
01452
01453 srv_use_native_aio = FALSE;
01454 break;
01455
01456 case OS_WIN2000:
01457 case OS_WINXP:
01458
01459 srv_use_native_aio = TRUE;
01460 break;
01461
01462 default:
01463
01464 srv_use_native_aio = TRUE;
01465 srv_use_native_conditions = TRUE;
01466 break;
01467 }
01468
01469 #elif defined(LINUX_NATIVE_AIO)
01470
01471 if (srv_use_native_aio) {
01472 ut_print_timestamp(stderr);
01473 fprintf(stderr,
01474 " InnoDB: Using Linux native AIO\n");
01475 }
01476 #else
01477
01478
01479
01480 srv_use_native_aio = FALSE;
01481
01482 #endif
01483
01484 return(FALSE);
01485
01486 error:
01487 fprintf(stderr, "xtrabackup: innodb_init_param(): Error occured.\n");
01488 return(TRUE);
01489 }
01490
01491 static bool
01492 innodb_init(void)
01493 {
01494 int err;
01495
01496 err = innobase_start_or_create_for_mysql();
01497
01498 if (err != DB_SUCCESS) {
01499 free(internal_innobase_data_file_path);
01500 goto error;
01501 }
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512 innodb_inited= 1;
01513
01514 return(FALSE);
01515
01516 error:
01517 fprintf(stderr, "xtrabackup: innodb_init(): Error occured.\n");
01518 return(TRUE);
01519 }
01520
01521 static bool
01522 innodb_end(void)
01523 {
01524 srv_fast_shutdown = (ulint) innobase_fast_shutdown;
01525 innodb_inited = 0;
01526
01527 fprintf(stderr, "xtrabackup: starting shutdown with innodb_fast_shutdown = %lu\n",
01528 srv_fast_shutdown);
01529
01530 if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
01531 goto error;
01532 }
01533 free(internal_innobase_data_file_path);
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543 return(FALSE);
01544
01545 error:
01546 fprintf(stderr, "xtrabackup: innodb_end(): Error occured.\n");
01547 return(TRUE);
01548 }
01549
01550
01551 static bool
01552 xtrabackup_read_metadata(char *filename)
01553 {
01554 FILE *fp;
01555
01556 fp = fopen(filename,"r");
01557 if(!fp) {
01558 fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filename);
01559 return(TRUE);
01560 }
01561
01562 if (fscanf(fp, "backup_type = %29s\n", metadata_type)
01563 != 1)
01564 return(TRUE);
01565 if (fscanf(fp, "from_lsn = %"PRIu64"\n", &metadata_from_lsn)
01566 != 1)
01567 return(TRUE);
01568 if (fscanf(fp, "to_lsn = %"PRIu64"\n", &metadata_to_lsn)
01569 != 1)
01570 return(TRUE);
01571 if (fscanf(fp, "last_lsn = %"PRIu64"\n", &metadata_last_lsn)
01572 != 1) {
01573 metadata_last_lsn = 0;
01574 }
01575
01576 fclose(fp);
01577
01578 return(FALSE);
01579 }
01580
01581 static bool
01582 xtrabackup_write_metadata(char *filename)
01583 {
01584 FILE *fp;
01585
01586 fp = fopen(filename,"w");
01587 if(!fp) {
01588 fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filename);
01589 return(TRUE);
01590 }
01591
01592 if (fprintf(fp, "backup_type = %s\n", metadata_type)
01593 < 0)
01594 return(TRUE);
01595 if (fprintf(fp, "from_lsn = %"PRIu64"\n", metadata_from_lsn)
01596 < 0)
01597 return(TRUE);
01598 if (fprintf(fp, "to_lsn = %"PRIu64"\n", metadata_to_lsn)
01599 < 0)
01600 return(TRUE);
01601 if (fprintf(fp, "last_lsn = %"PRIu64"\n", metadata_last_lsn)
01602 < 0)
01603 return(TRUE);
01604
01605 fclose(fp);
01606
01607 return(FALSE);
01608 }
01609
01610
01611
01612
01613 static bool
01614 xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info)
01615 {
01616 FILE *fp;
01617
01618 memset(info, 0, sizeof(xb_delta_info_t));
01619
01620 fp = fopen(filepath, "r");
01621 if (!fp) {
01622
01623 return(TRUE);
01624 }
01625
01626 if (fscanf(fp, "page_size = %lu\n", &info->page_size) != 1)
01627 return(FALSE);
01628
01629 fclose(fp);
01630
01631 return(TRUE);
01632 }
01633
01634
01635
01636
01637 static bool
01638 xb_write_delta_metadata(const char *filepath, const xb_delta_info_t *info)
01639 {
01640 FILE *fp;
01641
01642 fp = fopen(filepath, "w");
01643 if (!fp) {
01644 fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filepath);
01645 return(FALSE);
01646 }
01647
01648 if (fprintf(fp, "page_size = %lu\n", info->page_size) < 0)
01649 return(FALSE);
01650
01651 fclose(fp);
01652
01653 return(TRUE);
01654 }
01655
01656
01657 static void
01658 xtrabackup_io_throttling(void)
01659 {
01660 if (xtrabackup_throttle && (io_ticket--) < 0) {
01661 os_event_reset(wait_throttle);
01662 os_event_wait(wait_throttle);
01663 }
01664 }
01665
01666
01667
01668 #define COPY_CHUNK 64
01669
01670 static bool
01671 xtrabackup_copy_datafile(fil_node_t* node, uint thread_n)
01672 {
01673 os_file_t src_file = -1;
01674 os_file_t dst_file = -1;
01675 char dst_path[FN_REFLEN];
01676 char meta_path[FN_REFLEN];
01677 ibool success;
01678 byte* page;
01679 byte* buf2 = NULL;
01680 IB_INT64 file_size;
01681 IB_INT64 offset;
01682 ulint page_in_buffer= 0;
01683 ulint incremental_buffers = 0;
01684 ulint page_size;
01685 ulint page_size_shift;
01686 ulint zip_size;
01687 xb_delta_info_t info;
01688
01689 info.page_size = 0;
01690
01691 #ifdef XTRADB_BASED
01692 if (xtrabackup_tables && (!trx_sys_sys_space(node->space->id)))
01693 #else
01694 if (xtrabackup_tables && (node->space->id != 0))
01695 #endif
01696 {
01697 char *p;
01698 int p_len, regres= 0;
01699 char *next, *prev;
01700 char tmp;
01701 int i;
01702
01703 p = node->name;
01704 prev = NULL;
01705 while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
01706 {
01707 prev = p;
01708 p = next + 1;
01709 }
01710 p_len = strlen(p) - strlen(".ibd");
01711
01712 if (p_len < 1) {
01713
01714 goto skip_filter;
01715 }
01716
01717
01718 tmp = p[p_len];
01719 p[p_len] = 0;
01720 *(p - 1) = '.';
01721
01722 for (i = 0; i < tables_regex_num; i++) {
01723 regres = regexec(&tables_regex[i], prev, 1, tables_regmatch, 0);
01724 if (regres != REG_NOMATCH)
01725 break;
01726 }
01727
01728 p[p_len] = tmp;
01729 *(p - 1) = SRV_PATH_SEPARATOR;
01730
01731 if ( regres == REG_NOMATCH ) {
01732 printf("[%02u] Copying %s is skipped.\n",
01733 thread_n, node->name);
01734 return(FALSE);
01735 }
01736 }
01737
01738 #ifdef XTRADB_BASED
01739 if (xtrabackup_tables_file && (!trx_sys_sys_space(node->space->id)))
01740 #else
01741 if (xtrabackup_tables_file && (node->space->id != 0))
01742 #endif
01743 {
01744 xtrabackup_tables_t* table;
01745 char *p;
01746 int p_len;
01747 char *next, *prev;
01748 char tmp;
01749
01750 p = node->name;
01751 prev = NULL;
01752 while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
01753 {
01754 prev = p;
01755 p = next + 1;
01756 }
01757 p_len = strlen(p) - strlen(".ibd");
01758
01759 if (p_len < 1) {
01760
01761 goto skip_filter;
01762 }
01763
01764
01765 tmp = p[p_len];
01766 p[p_len] = 0;
01767
01768 HASH_SEARCH(name_hash, tables_hash, ut_fold_string(prev),
01769 xtrabackup_tables_t*,
01770 table,
01771 ut_ad(table->name),
01772 !strcmp(table->name, prev));
01773
01774 p[p_len] = tmp;
01775
01776 if (!table) {
01777 printf("[%02u] Copying %s is skipped.\n",
01778 thread_n, node->name);
01779 return(FALSE);
01780 }
01781 }
01782
01783 skip_filter:
01784 zip_size = fil_space_get_zip_size(node->space->id);
01785 if (zip_size == ULINT_UNDEFINED) {
01786 fprintf(stderr, "[%02u] xtrabackup: Warning: "
01787 "Failed to determine page size for %s.\n"
01788 "[%02u] xtrabackup: Warning: We assume the table was "
01789 "dropped during xtrabackup execution and ignore the "
01790 "file.\n", thread_n, node->name, thread_n);
01791 goto skip;
01792 } else if (zip_size) {
01793 page_size = zip_size;
01794 page_size_shift = get_bit_shift(page_size);
01795 fprintf(stderr, "[%02u] %s is compressed with page size = "
01796 "%lu bytes\n", thread_n, node->name, page_size);
01797 if (page_size_shift < 10 || page_size_shift > 14) {
01798 fprintf(stderr, "[%02u] xtrabackup: Error: Invalid "
01799 "page size.\n", thread_n);
01800 ut_error;
01801 }
01802 } else {
01803 page_size = UNIV_PAGE_SIZE;
01804 page_size_shift = UNIV_PAGE_SIZE_SHIFT;
01805 }
01806
01807 #ifdef XTRADB_BASED
01808 if (trx_sys_sys_space(node->space->id))
01809 #else
01810 if (node->space->id == 0)
01811 #endif
01812 {
01813 char *next, *p;
01814
01815 p = node->name;
01816 while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
01817 {
01818 p = next + 1;
01819 }
01820 sprintf(dst_path, "%s/%s", xtrabackup_target_dir, p);
01821 } else {
01822
01823 sprintf(dst_path, "%s%s", xtrabackup_target_dir, strstr(node->name, SRV_PATH_SEPARATOR_STR));
01824 }
01825
01826 if (xtrabackup_incremental) {
01827 snprintf(meta_path, sizeof(meta_path),
01828 "%s%s", dst_path, XB_DELTA_INFO_SUFFIX);
01829 strcat(dst_path, ".delta");
01830
01831
01832 bzero(incremental_buffer, (page_size/4) * page_size);
01833 page_in_buffer = 0;
01834 mach_write_to_4(incremental_buffer, 0x78747261UL);
01835 page_in_buffer++;
01836
01837 info.page_size = page_size;
01838 }
01839
01840
01841 if (!node->open) {
01842 src_file = os_file_create_simple_no_error_handling(
01843 0 ,
01844 node->name, OS_FILE_OPEN,
01845 OS_FILE_READ_ONLY, &success);
01846 if (!success) {
01847
01848 os_file_get_last_error(TRUE);
01849
01850 fprintf(stderr,
01851 "[%02u] xtrabackup: Warning: cannot open %s\n"
01852 "[%02u] xtrabackup: Warning: We assume the "
01853 "table was dropped during xtrabackup execution "
01854 "and ignore the file.\n",
01855 thread_n, node->name, thread_n);
01856 goto skip;
01857 }
01858
01859 if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
01860 os_file_set_nocache(src_file, node->name, "OPEN");
01861 }
01862 } else {
01863 src_file = node->handle;
01864 }
01865
01866 #ifdef USE_POSIX_FADVISE
01867 posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
01868 posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
01869 #endif
01870
01871
01872
01873 dst_file = os_file_create(
01874 0 ,
01875 dst_path, OS_FILE_CREATE,
01876 OS_FILE_NORMAL, OS_DATA_FILE, &success);
01877 if (!success) {
01878
01879 os_file_get_last_error(TRUE);
01880
01881 fprintf(stderr,"[%02u] xtrabackup: error: "
01882 "cannot open %s\n", thread_n, dst_path);
01883 goto error;
01884 }
01885
01886 #ifdef USE_POSIX_FADVISE
01887 posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED);
01888 #endif
01889
01890
01891 printf("[%02u] Copying %s \n to %s\n", thread_n,
01892 node->name, dst_path);
01893
01894 buf2 = (unsigned char*) ut_malloc(COPY_CHUNK * page_size + UNIV_PAGE_SIZE);
01895 page = (unsigned char*) ut_align(buf2, UNIV_PAGE_SIZE);
01896
01897 success = os_file_read(src_file, page, 0, 0, UNIV_PAGE_SIZE);
01898 if (!success) {
01899 goto error;
01900 }
01901
01902 file_size = os_file_get_size_as_iblonglong(src_file);
01903
01904 for (offset = 0; offset < file_size; offset += COPY_CHUNK * page_size) {
01905 ulint chunk;
01906 ulint chunk_offset;
01907 ulint retry_count = 10;
01908
01909 if ((ulint)(file_size - offset) > COPY_CHUNK * page_size) {
01910 chunk = COPY_CHUNK * page_size;
01911 } else {
01912 chunk = (ulint)(file_size - offset);
01913 }
01914
01915 read_retry:
01916 xtrabackup_io_throttling();
01917
01918 success = os_file_read(src_file, page,
01919 (ulint)(offset & 0xFFFFFFFFUL),
01920 (ulint)(offset >> 32), chunk);
01921 if (!success) {
01922 goto error;
01923 }
01924
01925
01926 for (chunk_offset = 0; chunk_offset < chunk; chunk_offset += page_size) {
01927 if (buf_page_is_corrupted(page + chunk_offset, zip_size))
01928 {
01929 if (
01930 #ifdef XTRADB_BASED
01931 trx_sys_sys_space(node->space->id)
01932 #else
01933 node->space->id == 0
01934 #endif
01935 && ((offset + (IB_INT64)chunk_offset) >> page_size_shift)
01936 >= FSP_EXTENT_SIZE
01937 && ((offset + (IB_INT64)chunk_offset) >> page_size_shift)
01938 < FSP_EXTENT_SIZE * 3) {
01939
01940
01941
01942 ut_a(page_size == UNIV_PAGE_SIZE);
01943 fprintf(stderr, "[%02u] xtrabackup: "
01944 "Page %lu seems double write "
01945 "buffer. passing the check.\n",
01946 thread_n,
01947 (ulint)((offset +
01948 (IB_INT64)chunk_offset) >>
01949 page_size_shift));
01950 } else {
01951 retry_count--;
01952 if (retry_count == 0) {
01953 fprintf(stderr,
01954 "[%02u] xtrabackup: "
01955 "Error: 10 retries "
01956 "resulted in fail. This"
01957 "file seems to be "
01958 "corrupted.\n",
01959 thread_n);
01960 goto error;
01961 }
01962 fprintf(stderr, "[%02u] xtrabackup: "
01963 "Database page corruption "
01964 "detected at page %lu. "
01965 "retrying...\n",
01966 thread_n,
01967 (ulint)((offset +
01968 (IB_INT64)chunk_offset)
01969 >> page_size_shift));
01970 goto read_retry;
01971 }
01972 }
01973 }
01974
01975 if (xtrabackup_incremental) {
01976 for (chunk_offset = 0; chunk_offset < chunk; chunk_offset += page_size) {
01977
01978
01979 if (ut_dulint_cmp(incremental_lsn,
01980 MACH_READ_64(page + chunk_offset + FIL_PAGE_LSN)) < 0) {
01981
01982 IB_INT64 offset_on_page;
01983
01984 if (page_in_buffer == page_size/4) {
01985
01986 success = os_file_write(dst_path, dst_file, incremental_buffer,
01987 ((incremental_buffers * (page_size/4))
01988 << page_size_shift) & 0xFFFFFFFFUL,
01989 (incremental_buffers * (page_size/4))
01990 >> (32 - page_size_shift),
01991 page_in_buffer * page_size);
01992 if (!success) {
01993 goto error;
01994 }
01995
01996 incremental_buffers++;
01997
01998
01999 bzero(incremental_buffer, (page_size/4) * page_size);
02000 page_in_buffer = 0;
02001 mach_write_to_4(incremental_buffer, 0x78747261UL);
02002 page_in_buffer++;
02003 }
02004
02005 offset_on_page = ((offset + (IB_INT64)chunk_offset) >> page_size_shift);
02006 ut_a(offset_on_page >> 32 == 0);
02007
02008 mach_write_to_4(incremental_buffer + page_in_buffer * 4, (ulint)offset_on_page);
02009 memcpy(incremental_buffer + page_in_buffer * page_size,
02010 page + chunk_offset, page_size);
02011
02012 page_in_buffer++;
02013
02014 }
02015 }
02016 } else {
02017 success = os_file_write(dst_path, dst_file, page,
02018 (ulint)(offset & 0xFFFFFFFFUL),
02019 (ulint)(offset >> 32), chunk);
02020 if (!success) {
02021 goto error;
02022 }
02023 }
02024
02025 }
02026
02027 if (xtrabackup_incremental) {
02028
02029 if (page_in_buffer != page_size/4) {
02030 mach_write_to_4(incremental_buffer + page_in_buffer * 4, 0xFFFFFFFFUL);
02031 }
02032
02033 mach_write_to_4(incremental_buffer, 0x58545241UL);
02034
02035
02036 success = os_file_write(dst_path, dst_file, incremental_buffer,
02037 ((incremental_buffers * (page_size/4))
02038 << page_size_shift) & 0xFFFFFFFFUL,
02039 (incremental_buffers * (page_size/4))
02040 >> (32 - page_size_shift),
02041 page_in_buffer * page_size);
02042 if (!success) {
02043 goto error;
02044 }
02045 if (!xb_write_delta_metadata(meta_path, &info)) {
02046 fprintf(stderr, "[%02u] xtrabackup: Error: "
02047 "failed to write meta info for %s\n",
02048 thread_n, dst_path);
02049 goto error;
02050 }
02051 }
02052
02053 success = os_file_flush(dst_file);
02054 if (!success) {
02055 goto error;
02056 }
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072 printf("[%02u] ...done\n", thread_n);
02073 if (!node->open) {
02074 os_file_close(src_file);
02075 }
02076 os_file_close(dst_file);
02077 ut_free(buf2);
02078 return(FALSE);
02079 error:
02080 if (src_file != -1 && !node->open)
02081 os_file_close(src_file);
02082 if (dst_file != -1)
02083 os_file_close(dst_file);
02084 if (buf2)
02085 ut_free(buf2);
02086 fprintf(stderr, "[%02u] xtrabackup: Error: "
02087 "xtrabackup_copy_datafile() failed.\n", thread_n);
02088 return(TRUE);
02089
02090 skip:
02091 if (src_file != -1 && !node->open)
02092 os_file_close(src_file);
02093 if (dst_file != -1)
02094 os_file_close(dst_file);
02095 if (buf2)
02096 ut_free(buf2);
02097 fprintf(stderr, "[%02u] xtrabackup: Warning: skipping file %s.\n",
02098 thread_n, node->name);
02099 return(FALSE);
02100 }
02101
02102 static bool
02103 xtrabackup_copy_logfile(LSN64 from_lsn, bool is_last)
02104 {
02105
02106 log_group_t* group;
02107 LSN64 group_scanned_lsn;
02108 LSN64 contiguous_lsn;
02109
02110 ibool success;
02111
02112 if (!xtrabackup_stream)
02113 ut_a(dst_log != -1);
02114
02115
02116 contiguous_lsn = ut_dulint_align_down(from_lsn,
02117 OS_FILE_LOG_BLOCK_SIZE);
02118
02119
02120
02121 group = UT_LIST_GET_FIRST(log_sys->log_groups);
02122
02123 while (group) {
02124 ibool finished;
02125 LSN64 start_lsn;
02126 LSN64 end_lsn;
02127
02128
02129
02130 finished = FALSE;
02131
02132 start_lsn = contiguous_lsn;
02133
02134 while (!finished) {
02135 end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE);
02136
02137 xtrabackup_io_throttling();
02138
02139 log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
02140 group, start_lsn, end_lsn);
02141
02142
02143
02144
02145
02146 {
02147 byte* log_block;
02148 ulint no;
02149 LSN64 scanned_lsn;
02150 ulint data_len;
02151
02152 ulint scanned_checkpoint_no = 0;
02153
02154 finished = FALSE;
02155
02156 log_block = log_sys->buf;
02157 scanned_lsn = start_lsn;
02158
02159 while (log_block < log_sys->buf + RECV_SCAN_SIZE && !finished) {
02160
02161 no = log_block_get_hdr_no(log_block);
02162
02163 if (no != log_block_convert_lsn_to_no(scanned_lsn)
02164 || !log_block_checksum_is_ok_or_old_format(log_block)) {
02165
02166 if (no > log_block_convert_lsn_to_no(scanned_lsn)
02167 && log_block_checksum_is_ok_or_old_format(log_block)) {
02168 fprintf(stderr,
02169 ">> ###Warning###: The copying transaction log migh be overtaken already by the target.\n"
02170 ">> : Waiting log block no %lu, but the bumber is already %lu.\n"
02171 ">> : If the number equals %lu + n * %lu, it should be overtaken already.\n",
02172 (ulong) log_block_convert_lsn_to_no(scanned_lsn),
02173 (ulong) no,
02174 (ulong) log_block_convert_lsn_to_no(scanned_lsn),
02175 (ulong) (log_block_convert_lsn_to_no(
02176 log_group_get_capacity(group)
02177 ) - 1));
02178
02179 } else if (no == log_block_convert_lsn_to_no(scanned_lsn)
02180 && !log_block_checksum_is_ok_or_old_format(
02181 log_block)) {
02182 fprintf(stderr,
02183 "xtrabackup: Log block no %lu at lsn %"PRIu64" has\n"
02184 "xtrabackup: ok header, but checksum field contains %lu, should be %lu\n",
02185 (ulong) no,
02186 scanned_lsn,
02187 (ulong) log_block_get_checksum(log_block),
02188 (ulong) log_block_calc_checksum(log_block));
02189 }
02190
02191
02192
02193 finished = TRUE;
02194
02195 break;
02196 }
02197
02198 if (log_block_get_flush_bit(log_block)) {
02199
02200
02201
02202
02203
02204
02205
02206 if (ut_dulint_cmp(scanned_lsn, contiguous_lsn) > 0) {
02207 contiguous_lsn = scanned_lsn;
02208 }
02209 }
02210
02211 data_len = log_block_get_data_len(log_block);
02212
02213 if (
02214 (scanned_checkpoint_no > 0)
02215 && (log_block_get_checkpoint_no(log_block)
02216 < scanned_checkpoint_no)
02217 && (scanned_checkpoint_no
02218 - log_block_get_checkpoint_no(log_block)
02219 > 0x80000000UL)) {
02220
02221
02222
02223
02224 finished = TRUE;
02225 break;
02226 }
02227
02228 scanned_lsn = ut_dulint_add(scanned_lsn, data_len);
02229 scanned_checkpoint_no = log_block_get_checkpoint_no(log_block);
02230
02231 if (data_len < OS_FILE_LOG_BLOCK_SIZE) {
02232
02233
02234 finished = TRUE;
02235 } else {
02236 log_block += OS_FILE_LOG_BLOCK_SIZE;
02237 }
02238 }
02239
02240 group_scanned_lsn = scanned_lsn;
02241
02242
02243
02244 }
02245
02246
02247 {
02248 ulint write_size;
02249
02250 if (!finished) {
02251 write_size = RECV_SCAN_SIZE;
02252 } else {
02253 write_size = ut_dulint_minus(
02254 ut_dulint_align_up(group_scanned_lsn, OS_FILE_LOG_BLOCK_SIZE),
02255 start_lsn);
02256 }
02257
02258
02259
02260 if (!xtrabackup_stream) {
02261 success = os_file_write(dst_log_path, dst_log, log_sys->buf,
02262 (ulint)(log_copy_offset & 0xFFFFFFFFUL),
02263 (ulint)(log_copy_offset >> 32), write_size);
02264 } else {
02265 ulint ret;
02266 ulint stdout_write_size = write_size;
02267 if (finished && !is_last
02268 && group_scanned_lsn % OS_FILE_LOG_BLOCK_SIZE
02269 )
02270 stdout_write_size -= OS_FILE_LOG_BLOCK_SIZE;
02271 if (stdout_write_size) {
02272 ret = write(fileno(stdout), log_sys->buf, stdout_write_size);
02273 if (ret == stdout_write_size) {
02274 success = TRUE;
02275 } else {
02276 fprintf(stderr, "write: %lu > %lu\n", stdout_write_size, ret);
02277 success = FALSE;
02278 }
02279 } else {
02280 success = TRUE;
02281 }
02282 }
02283
02284 log_copy_offset += write_size;
02285
02286 if (finished && group_scanned_lsn % OS_FILE_LOG_BLOCK_SIZE)
02287 {
02288
02289 log_copy_offset -= OS_FILE_LOG_BLOCK_SIZE;
02290 }
02291
02292 if(!success) {
02293 if (!xtrabackup_stream) {
02294 fprintf(stderr, "xtrabackup: Error: os_file_write to %s\n", dst_log_path);
02295 } else {
02296 fprintf(stderr, "xtrabackup: Error: write to stdout\n");
02297 }
02298 goto error;
02299 }
02300
02301
02302 }
02303
02304
02305
02306
02307
02308 start_lsn = end_lsn;
02309 }
02310
02311
02312
02313 group->scanned_lsn = group_scanned_lsn;
02314
02315
02316 fprintf(stderr, ">> log scanned up to (%"PRIu64")\n",group->scanned_lsn);
02317
02318 group = UT_LIST_GET_NEXT(log_groups, group);
02319
02320
02321 log_copy_scanned_lsn = group_scanned_lsn;
02322
02323
02324 ut_a(group == NULL);
02325 }
02326
02327
02328 if (!xtrabackup_stream) {
02329 success = os_file_flush(dst_log);
02330 } else {
02331 fflush(stdout);
02332 success = TRUE;
02333 }
02334
02335 if(!success) {
02336 goto error;
02337 }
02338
02339 return(FALSE);
02340
02341 error:
02342 if (!xtrabackup_stream)
02343 os_file_close(dst_log);
02344 fprintf(stderr, "xtrabackup: Error: xtrabackup_copy_logfile() failed.\n");
02345 return(TRUE);
02346 }
02347
02348
02349 #define SLEEPING_PERIOD 5
02350
02351 static
02352 #ifndef __WIN__
02353 void*
02354 #else
02355 ulint
02356 #endif
02357 log_copying_thread(
02358 void* )
02359 {
02360 ulint counter = 0;
02361
02362 if (!xtrabackup_stream)
02363 ut_a(dst_log != -1);
02364
02365 log_copying_running = TRUE;
02366
02367 while(log_copying) {
02368 os_thread_sleep(200000);
02369
02370 counter++;
02371 if(counter >= SLEEPING_PERIOD * 5) {
02372 if(xtrabackup_copy_logfile(log_copy_scanned_lsn, FALSE))
02373 goto end;
02374 counter = 0;
02375 }
02376 }
02377
02378
02379 if(xtrabackup_copy_logfile(log_copy_scanned_lsn, TRUE))
02380 goto end;
02381
02382 log_copying_succeed = TRUE;
02383 end:
02384 log_copying_running = FALSE;
02385 os_thread_exit(NULL);
02386
02387 return(0);
02388 }
02389
02390
02391 static
02392 #ifndef __WIN__
02393 void*
02394 #else
02395 ulint
02396 #endif
02397 io_watching_thread(
02398 void* )
02399 {
02400
02401 ut_a(xtrabackup_backup);
02402
02403 while (log_copying) {
02404 os_thread_sleep(1000000);
02405
02406
02407
02408
02409
02410
02411 io_ticket = xtrabackup_throttle;
02412 os_event_set(wait_throttle);
02413 }
02414
02415
02416 xtrabackup_throttle = 0;
02417 os_event_set(wait_throttle);
02418
02419 os_thread_exit(NULL);
02420
02421 return(0);
02422 }
02423
02424
02425
02426 static
02427
02428 #ifndef __WIN__
02429 void*
02430 #else
02431 ulint
02432 #endif
02433 io_handler_thread(
02434
02435 void* arg)
02436 {
02437 ulint segment;
02438 ulint i;
02439
02440 segment = *((ulint*)arg);
02441
02442 for (i = 0;; i++) {
02443 fil_aio_wait(segment);
02444 }
02445
02446
02447
02448
02449
02450
02451 os_thread_exit(NULL);
02452
02453 #ifndef __WIN__
02454 return(NULL);
02455 #else
02456 return(0);
02457 #endif
02458 }
02459
02460
02461
02462 static
02463 int
02464 xtrabackup_create_output_dir(
02465
02466
02467 fil_space_t *space)
02468 {
02469 char path[FN_REFLEN];
02470 char *ptr1, *ptr2;
02471
02472
02473 ptr1 = strstr(space->name, SRV_PATH_SEPARATOR_STR);
02474 if (ptr1) {
02475 ptr2 = strstr(ptr1 + 1, SRV_PATH_SEPARATOR_STR);
02476 } else {
02477 ptr2 = NULL;
02478 }
02479 #ifdef XTRADB_BASED
02480 if(!trx_sys_sys_space(space->id) && ptr2)
02481 #else
02482 if(space->id && ptr2)
02483 #endif
02484 {
02485
02486 *ptr2 = 0;
02487 snprintf(path, sizeof(path), "%s%s", xtrabackup_target_dir,
02488 ptr1);
02489 *ptr2 = SRV_PATH_SEPARATOR;
02490
02491 if (mkdir(path, 0777) != 0 && errno != EEXIST) {
02492 fprintf(stderr,
02493 "xtrabackup: Error: cannot mkdir %d: %s\n",
02494 errno, path);
02495 return -1;
02496 }
02497 }
02498 return 0;
02499 }
02500
02501
02502
02503 static
02504 os_thread_ret_t
02505 data_copy_thread_func(
02506
02507 void *arg)
02508 {
02509 data_thread_ctxt_t *ctxt = (data_thread_ctxt_t *) arg;
02510 uint num = ctxt->num;
02511 fil_space_t* space;
02512 ibool space_changed;
02513 fil_node_t* node;
02514
02515 while ((node = datafiles_iter_next(ctxt->it, &space_changed)) != NULL) {
02516 space = node->space;
02517
02518 if (space_changed && xtrabackup_create_output_dir(space))
02519 exit(EXIT_FAILURE);
02520
02521
02522 if(xtrabackup_copy_datafile(node, num)) {
02523 fprintf(stderr, "[%02u] xtrabackup: Error: "
02524 "failed to copy datafile.\n",
02525 num);
02526 exit(EXIT_FAILURE);
02527 }
02528 }
02529
02530 os_mutex_enter(ctxt->count_mutex);
02531 (*ctxt->count)--;
02532 os_mutex_exit(ctxt->count_mutex);
02533
02534 os_thread_exit(NULL);
02535 OS_THREAD_DUMMY_RETURN;
02536 }
02537
02538
02539 static void
02540 xtrabackup_backup_func(void)
02541 {
02542 struct stat stat_info;
02543 LSN64 latest_cp;
02544
02545 #ifdef USE_POSIX_FADVISE
02546 fprintf(stderr, "xtrabackup: uses posix_fadvise().\n");
02547 #endif
02548
02549
02550
02551 if (chdir(mysql_real_data_home) != 0)
02552 {
02553 fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", mysql_real_data_home);
02554 exit(EXIT_FAILURE);
02555 }
02556 fprintf(stderr, "xtrabackup: cd to %s\n", mysql_real_data_home);
02557
02558 mysql_data_home= mysql_data_home_buff;
02559 mysql_data_home[0]=FN_CURLIB;
02560 mysql_data_home[1]=0;
02561
02562
02563 srv_read_only = TRUE;
02564
02565
02566 if(innodb_init_param())
02567 exit(EXIT_FAILURE);
02568
02569 if (srv_file_flush_method_str == NULL) {
02570
02571 srv_unix_file_flush_method = SRV_UNIX_FSYNC;
02572
02573 srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
02574 #ifndef __WIN__
02575 } else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) {
02576 srv_unix_file_flush_method = SRV_UNIX_FSYNC;
02577
02578 } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
02579 srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
02580
02581 } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) {
02582 srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
02583 fprintf(stderr,"xtrabackup: use O_DIRECT\n");
02584 } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) {
02585 srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
02586
02587 } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
02588 srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
02589 #else
02590 } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
02591 srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
02592 os_aio_use_native_aio = FALSE;
02593
02594 } else if (0 == ut_strcmp(srv_file_flush_method_str, "unbuffered")) {
02595 srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
02596 os_aio_use_native_aio = FALSE;
02597
02598 } else if (0 == ut_strcmp(srv_file_flush_method_str,
02599 "async_unbuffered")) {
02600 srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
02601 #endif
02602 } else {
02603 fprintf(stderr,
02604 "xtrabackup: Unrecognized value %s for innodb_flush_method\n",
02605 srv_file_flush_method_str);
02606 exit(EXIT_FAILURE);
02607 }
02608
02609 if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
02610
02611
02612
02613
02614
02615 srv_max_n_threads = 50000;
02616
02617
02618 } else if (srv_buf_pool_size >= 8 * 1024 * 1024) {
02619
02620 srv_max_n_threads = 10000;
02621 } else {
02622 srv_max_n_threads = 1000;
02623
02624
02625 }
02626
02627 {
02628 ulint nr;
02629 ulint i;
02630
02631 nr = srv_n_data_files;
02632
02633 for (i = 0; i < nr; i++) {
02634 srv_data_file_sizes[i] = srv_data_file_sizes[i]
02635 * ((1024 * 1024) / UNIV_PAGE_SIZE);
02636 }
02637
02638 srv_last_file_size_max = srv_last_file_size_max
02639 * ((1024 * 1024) / UNIV_PAGE_SIZE);
02640
02641 srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE;
02642
02643 srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
02644
02645 srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
02646 }
02647
02648 os_sync_mutex = NULL;
02649 srv_general_init();
02650
02651 {
02652 ibool create_new_db;
02653 #ifdef XTRADB_BASED
02654 ibool create_new_doublewrite_file;
02655 #endif
02656 ibool log_file_created;
02657 ibool log_created = FALSE;
02658 ibool log_opened = FALSE;
02659 LSN64 min_flushed_lsn;
02660 LSN64 max_flushed_lsn;
02661 ulint sum_of_new_sizes;
02662 ulint err;
02663 ulint i;
02664
02665
02666
02667
02668 #define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
02669 #define SRV_MAX_N_PENDING_SYNC_IOS 100
02670
02671 srv_n_file_io_threads = 2 + srv_n_read_io_threads + srv_n_write_io_threads;
02672
02673 os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD,
02674 srv_n_read_io_threads,
02675 srv_n_write_io_threads,
02676 SRV_MAX_N_PENDING_SYNC_IOS);
02677
02678 fil_init(srv_file_per_table ? 50000 : 5000,
02679 srv_max_n_open_files);
02680
02681 fsp_init();
02682 log_init();
02683
02684 lock_sys_create(srv_lock_table_size);
02685
02686 for (i = 0; i < srv_n_file_io_threads; i++) {
02687 thread_nr[i] = i;
02688
02689 os_thread_create(io_handler_thread, thread_nr + i, thread_ids + i);
02690 }
02691
02692 os_thread_sleep(200000);
02693
02694 err = open_or_create_data_files(&create_new_db,
02695 #ifdef XTRADB_BASED
02696 &create_new_doublewrite_file,
02697 #endif
02698 &min_flushed_lsn, &max_flushed_lsn,
02699 &sum_of_new_sizes);
02700 if (err != DB_SUCCESS) {
02701 fprintf(stderr,
02702 "xtrabackup: Could not open or create data files.\n"
02703 "xtrabackup: If you tried to add new data files, and it failed here,\n"
02704 "xtrabackup: you should now edit innodb_data_file_path in my.cnf back\n"
02705 "xtrabackup: to what it was, and remove the new ibdata files InnoDB created\n"
02706 "xtrabackup: in this failed attempt. InnoDB only wrote those files full of\n"
02707 "xtrabackup: zeros, but did not yet use them in any way. But be careful: do not\n"
02708 "xtrabackup: remove old data files which contain your precious data!\n");
02709
02710
02711 exit(EXIT_FAILURE);
02712 }
02713
02714
02715 if (create_new_db) {
02716 fprintf(stderr, "xtrabackup: Something wrong with source files...\n");
02717 exit(EXIT_FAILURE);
02718 }
02719
02720 for (i = 0; i < srv_n_log_files; i++) {
02721 err = open_or_create_log_file(create_new_db, &log_file_created,
02722 log_opened, 0, i);
02723 if (err != DB_SUCCESS) {
02724
02725
02726 exit(EXIT_FAILURE);
02727 }
02728
02729 if (log_file_created) {
02730 log_created = TRUE;
02731 } else {
02732 log_opened = TRUE;
02733 }
02734 if ((log_opened && create_new_db)
02735 || (log_opened && log_created)) {
02736 fprintf(stderr,
02737 "xtrabackup: Error: all log files must be created at the same time.\n"
02738 "xtrabackup: All log files must be created also in database creation.\n"
02739 "xtrabackup: If you want bigger or smaller log files, shut down the\n"
02740 "xtrabackup: database and make sure there were no errors in shutdown.\n"
02741 "xtrabackup: Then delete the existing log files. Edit the .cnf file\n"
02742 "xtrabackup: and start the database again.\n");
02743
02744
02745 exit(EXIT_FAILURE);
02746 }
02747 }
02748
02749
02750 if (log_file_created) {
02751 fprintf(stderr, "xtrabackup: Something wrong with source files...\n");
02752 exit(EXIT_FAILURE);
02753 }
02754
02755 fil_load_single_table_tablespaces();
02756
02757 }
02758
02759
02760 if (xtrabackup_extra_lsndir
02761 && (stat(xtrabackup_extra_lsndir,&stat_info) != 0)
02762 && (mkdir(xtrabackup_extra_lsndir,0777) != 0)){
02763 fprintf(stderr,"xtrabackup: Error: cannot mkdir %d: %s\n",errno,xtrabackup_extra_lsndir);
02764 exit(EXIT_FAILURE);
02765 }
02766
02767
02768 if (!xtrabackup_stream) {
02769
02770
02771 if (stat(xtrabackup_target_dir,&stat_info) != 0
02772 && (mkdir(xtrabackup_target_dir,0777) != 0)){
02773 fprintf(stderr,"xtrabackup: Error: cannot mkdir %d: %s\n",errno,xtrabackup_target_dir);
02774 exit(EXIT_FAILURE);
02775 }
02776
02777 } else {
02778 fprintf(stderr,"xtrabackup: Stream mode.\n");
02779
02780
02781 }
02782
02783 {
02784 fil_system_t* f_system = fil_system;
02785
02786
02787 log_group_t* max_cp_group;
02788 ulint max_cp_field;
02789 byte* buf;
02790 boost::scoped_array<byte> log_hdr_buf_(
02791 new byte[LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE]);
02792 byte* log_hdr_buf;
02793 ulint err;
02794
02795 ibool success;
02796
02797
02798 os_thread_id_t log_copying_thread_id;
02799 datafiles_iter_t *it;
02800
02801 log_hdr_buf = (byte*)ut_align(log_hdr_buf_.get(),
02802 OS_FILE_LOG_BLOCK_SIZE);
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812 err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
02813
02814 if (err != DB_SUCCESS) {
02815
02816 exit(EXIT_FAILURE);
02817 }
02818
02819 log_group_read_checkpoint_info(max_cp_group, max_cp_field);
02820 buf = log_sys->checkpoint_buf;
02821
02822 checkpoint_lsn_start = MACH_READ_64(buf + LOG_CHECKPOINT_LSN);
02823 checkpoint_no_start = MACH_READ_64(buf + LOG_CHECKPOINT_NO);
02824
02825 reread_log_header:
02826 fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, max_cp_group->space_id,
02827 0,
02828 0, 0, LOG_FILE_HDR_SIZE,
02829 log_hdr_buf, max_cp_group);
02830
02831
02832 err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
02833
02834 if (err != DB_SUCCESS) {
02835
02836 exit(EXIT_FAILURE);
02837 }
02838
02839 log_group_read_checkpoint_info(max_cp_group, max_cp_field);
02840 buf = log_sys->checkpoint_buf;
02841
02842 if(ut_dulint_cmp(checkpoint_no_start,
02843 MACH_READ_64(buf + LOG_CHECKPOINT_NO)) != 0) {
02844 checkpoint_lsn_start = MACH_READ_64(buf + LOG_CHECKPOINT_LSN);
02845 checkpoint_no_start = MACH_READ_64(buf + LOG_CHECKPOINT_NO);
02846 goto reread_log_header;
02847 }
02848
02849 if (!xtrabackup_stream) {
02850
02851
02852 sprintf(dst_log_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
02853 srv_normalize_path_for_win(dst_log_path);
02854
02855 dst_log = os_file_create(
02856 0 ,
02857 dst_log_path, OS_FILE_CREATE,
02858 OS_FILE_NORMAL, OS_DATA_FILE, &success);
02859
02860 if (!success) {
02861
02862 os_file_get_last_error(TRUE);
02863
02864 fprintf(stderr,
02865 "xtrabackup: error: cannot open %s\n",
02866 dst_log_path);
02867 exit(EXIT_FAILURE);
02868 }
02869
02870 #ifdef USE_POSIX_FADVISE
02871 posix_fadvise(dst_log, 0, 0, POSIX_FADV_DONTNEED);
02872 #endif
02873
02874 }
02875
02876
02877 strcpy((char*) log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
02878 "xtrabkup ");
02879 ut_sprintf_timestamp(
02880 (char*) log_hdr_buf + (LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
02881 + (sizeof "xtrabkup ") - 1));
02882
02883 if (!xtrabackup_stream) {
02884 success = os_file_write(dst_log_path, dst_log, log_hdr_buf,
02885 0, 0, LOG_FILE_HDR_SIZE);
02886 } else {
02887
02888 if ((write(fileno(stdout), log_hdr_buf, LOG_FILE_HDR_SIZE)
02889 - LOG_FILE_HDR_SIZE) == 0)
02890 {
02891 success = TRUE;
02892 } else {
02893 success = FALSE;
02894 }
02895 }
02896
02897 log_copy_offset += LOG_FILE_HDR_SIZE;
02898 if (!success) {
02899 if (dst_log != -1)
02900 os_file_close(dst_log);
02901 exit(EXIT_FAILURE);
02902 }
02903
02904
02905 log_copying = TRUE;
02906
02907
02908 if(xtrabackup_throttle) {
02909 os_thread_id_t io_watching_thread_id;
02910
02911 io_ticket = xtrabackup_throttle;
02912 wait_throttle = os_event_create(NULL);
02913
02914 os_thread_create(io_watching_thread, NULL, &io_watching_thread_id);
02915 }
02916
02917
02918
02919 if(xtrabackup_copy_logfile(checkpoint_lsn_start, FALSE))
02920 exit(EXIT_FAILURE);
02921
02922
02923 os_thread_create(log_copying_thread, NULL, &log_copying_thread_id);
02924
02925
02926
02927 if (!xtrabackup_stream) {
02928 uint i;
02929 uint count;
02930 os_mutex_t count_mutex;
02931 data_thread_ctxt_t *data_threads;
02932
02933 ut_a(parallel > 0);
02934
02935 if (parallel > 1)
02936 printf("xtrabackup: Starting %u threads for parallel "
02937 "data files transfer\n", parallel);
02938
02939 it = datafiles_iter_new(f_system);
02940 if (it == NULL) {
02941 fprintf(stderr,
02942 "xtrabackup: Error: "
02943 "datafiles_iter_new() failed.\n");
02944 exit(EXIT_FAILURE);
02945 }
02946
02947
02948 ut_a(parallel > 0);
02949
02950 data_threads = (data_thread_ctxt_t *)
02951 ut_malloc(sizeof(data_thread_ctxt_t) * parallel);
02952 count = parallel;
02953 count_mutex = OS_MUTEX_CREATE();
02954
02955 for (i = 0; i < parallel; i++) {
02956 data_threads[i].it = it;
02957 data_threads[i].num = i+1;
02958 data_threads[i].count = &count;
02959 data_threads[i].count_mutex = count_mutex;
02960 os_thread_create(data_copy_thread_func,
02961 data_threads + i,
02962 &data_threads[i].id);
02963 }
02964
02965
02966 while (1) {
02967 os_thread_sleep(1000000);
02968 os_mutex_enter(count_mutex);
02969 if (count == 0) {
02970 os_mutex_exit(count_mutex);
02971 break;
02972 }
02973 os_mutex_exit(count_mutex);
02974 }
02975
02976
02977
02978 os_mutex_free(count_mutex);
02979 datafiles_iter_free(it);
02980
02981 }
02982
02983
02984 }
02985
02986
02987
02988 if (xtrabackup_suspend_at_end) {
02989 os_file_t suspend_file = -1;
02990 char suspend_path[FN_REFLEN];
02991 ibool success, exists;
02992 os_file_type_t type;
02993
02994 sprintf(suspend_path, "%s%s", xtrabackup_target_dir,
02995 "/xtrabackup_suspended");
02996
02997 srv_normalize_path_for_win(suspend_path);
02998
02999 suspend_file = os_file_create(
03000 0 ,
03001 suspend_path, OS_FILE_OVERWRITE,
03002 OS_FILE_NORMAL, OS_DATA_FILE, &success);
03003
03004 if (!success) {
03005 fprintf(stderr, "xtrabackup: Error: failed to create file 'xtrabackup_suspended'\n");
03006 }
03007
03008 if (suspend_file != -1)
03009 os_file_close(suspend_file);
03010
03011 exists = TRUE;
03012 while (exists) {
03013 os_thread_sleep(200000);
03014 success = os_file_status(suspend_path, &exists, &type);
03015 if (!success)
03016 break;
03017 }
03018 xtrabackup_suspend_at_end = FALSE;
03019 }
03020
03021
03022 latest_cp = ut_dulint_zero;
03023 {
03024 log_group_t* max_cp_group;
03025 ulint max_cp_field;
03026 ulint err;
03027
03028 err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
03029
03030 if (err != DB_SUCCESS) {
03031 fprintf(stderr, "xtrabackup: Error: recv_find_max_checkpoint() failed.\n");
03032 goto skip_last_cp;
03033 }
03034
03035 log_group_read_checkpoint_info(max_cp_group, max_cp_field);
03036
03037 latest_cp = MACH_READ_64(log_sys->checkpoint_buf + LOG_CHECKPOINT_LSN);
03038
03039 if (!xtrabackup_stream) {
03040 printf("xtrabackup: The latest check point (for incremental): '%"PRIu64"'\n",
03041 latest_cp);
03042 } else {
03043 fprintf(stderr, "xtrabackup: The latest check point (for incremental): '%"PRIu64"'\n",
03044 latest_cp);
03045 }
03046 }
03047 skip_last_cp:
03048
03049 log_copying = FALSE;
03050 if (!xtrabackup_stream) {
03051 printf("xtrabackup: Stopping log copying thread");
03052 while (log_copying_running) {
03053 printf(".");
03054 os_thread_sleep(200000);
03055 }
03056 printf("\n");
03057 } else {
03058 while (log_copying_running)
03059 os_thread_sleep(200000);
03060 }
03061
03062
03063 {
03064 char filename[FN_REFLEN];
03065
03066 if(!xtrabackup_incremental) {
03067 strcpy(metadata_type, "full-backuped");
03068 metadata_from_lsn = ut_dulint_zero;
03069 } else {
03070 strcpy(metadata_type, "incremental");
03071 metadata_from_lsn = incremental_lsn;
03072 }
03073 metadata_to_lsn = latest_cp;
03074 metadata_last_lsn = log_copy_scanned_lsn;
03075
03076 sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
03077 if (xtrabackup_write_metadata(filename))
03078 fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_target_dir)\n");
03079
03080 if(xtrabackup_extra_lsndir) {
03081 sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
03082 if (xtrabackup_write_metadata(filename))
03083 fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
03084 }
03085 }
03086
03087 if (!log_copying_succeed) {
03088 fprintf(stderr, "xtrabackup: Error: log_copying_thread failed.\n");
03089 exit(EXIT_FAILURE);
03090 }
03091
03092 if (!xtrabackup_stream)
03093 os_file_close(dst_log);
03094
03095 if (wait_throttle)
03096 os_event_free(wait_throttle);
03097
03098 if (!xtrabackup_stream) {
03099 printf("xtrabackup: Transaction log of lsn (%"PRIu64") to (%"PRIu64") was copied.\n",
03100 checkpoint_lsn_start, log_copy_scanned_lsn);
03101 } else {
03102 fprintf(stderr, "xtrabackup: Transaction log of lsn (%"PRIu64") to (%"PRIu64") was copied.\n",
03103 checkpoint_lsn_start, log_copy_scanned_lsn);
03104 if(xtrabackup_extra_lsndir) {
03105 char filename[FN_REFLEN];
03106 sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
03107 if (xtrabackup_write_metadata(filename))
03108 fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
03109 }
03110 }
03111 }
03112
03113
03114 static bool
03115 xtrabackup_stats_level(
03116 dict_index_t* index,
03117 ulint level)
03118 {
03119 ulint space;
03120 page_t* page;
03121
03122 rec_t* node_ptr;
03123
03124 ulint right_page_no;
03125
03126 page_cur_t cursor;
03127
03128 mtr_t mtr;
03129 mem_heap_t* heap = mem_heap_create(256);
03130
03131 ulint* offsets = NULL;
03132
03133 uint64_t n_pages, n_pages_extern;
03134 uint64_t sum_data, sum_data_extern;
03135 uint64_t n_recs;
03136 ulint page_size;
03137
03138 n_pages = sum_data = n_recs = 0;
03139 n_pages_extern = sum_data_extern = 0;
03140
03141 buf_block_t* block;
03142 ulint zip_size;
03143
03144 if (level == 0)
03145 fprintf(stdout, " leaf pages: ");
03146 else
03147 fprintf(stdout, " level %lu pages: ", level);
03148
03149 mtr_start(&mtr);
03150
03151 mtr_x_lock(&(index->lock), &mtr);
03152 block = btr_root_block_get(index, &mtr);
03153 page = buf_block_get_frame(block);
03154
03155 space = page_get_space_id(page);
03156 zip_size = fil_space_get_zip_size(space);
03157
03158 while (level != btr_page_get_level(page, &mtr)) {
03159
03160 ut_a(space == buf_block_get_space(block));
03161 ut_a(space == page_get_space_id(page));
03162 ut_a(!page_is_leaf(page));
03163
03164 page_cur_set_before_first(block, &cursor);
03165 page_cur_move_to_next(&cursor);
03166
03167 node_ptr = page_cur_get_rec(&cursor);
03168 offsets = rec_get_offsets(node_ptr, index, offsets,
03169 ULINT_UNDEFINED, &heap);
03170
03171 block = btr_node_ptr_get_child(node_ptr, index, offsets, &mtr);
03172 page = buf_block_get_frame(block);
03173 }
03174
03175 loop:
03176 mem_heap_empty(heap);
03177 offsets = NULL;
03178 mtr_x_lock(&(index->lock), &mtr);
03179
03180 right_page_no = btr_page_get_next(page, &mtr);
03181
03182
03183
03184
03185
03186 n_pages++;
03187 sum_data += page_get_data_size(page);
03188 n_recs += page_get_n_recs(page);
03189
03190
03191 if (level == 0) {
03192 page_cur_t cur;
03193 ulint n_fields;
03194 ulint i;
03195 mem_heap_t* local_heap = NULL;
03196 ulint offsets_[REC_OFFS_NORMAL_SIZE];
03197 ulint* local_offsets = offsets_;
03198
03199 *offsets_ = (sizeof offsets_) / sizeof *offsets_;
03200
03201 page_cur_set_before_first(block, &cur);
03202
03203 page_cur_move_to_next(&cur);
03204
03205 for (;;) {
03206 if (page_cur_is_after_last(&cur)) {
03207 break;
03208 }
03209
03210 local_offsets = rec_get_offsets(cur.rec, index, local_offsets,
03211 ULINT_UNDEFINED, &local_heap);
03212 n_fields = rec_offs_n_fields(local_offsets);
03213
03214 for (i = 0; i < n_fields; i++) {
03215 if (rec_offs_nth_extern(local_offsets, i)) {
03216 page_t* local_page;
03217 ulint space_id;
03218 ulint page_no;
03219 ulint offset;
03220 byte* blob_header;
03221 ulint part_len;
03222 mtr_t local_mtr;
03223 ulint local_len;
03224 byte* data;
03225 buf_block_t* local_block;
03226
03227 data = rec_get_nth_field(cur.rec, local_offsets, i, &local_len);
03228
03229 ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
03230 local_len -= BTR_EXTERN_FIELD_REF_SIZE;
03231
03232 space_id = mach_read_from_4(data + local_len + BTR_EXTERN_SPACE_ID);
03233 page_no = mach_read_from_4(data + local_len + BTR_EXTERN_PAGE_NO);
03234 offset = mach_read_from_4(data + local_len + BTR_EXTERN_OFFSET);
03235
03236 if (offset != FIL_PAGE_DATA)
03237 fprintf(stderr, "\nWarning: several record may share same external page.\n");
03238
03239 for (;;) {
03240 mtr_start(&local_mtr);
03241
03242 local_block = btr_block_get(space_id, zip_size, page_no, RW_S_LATCH, &local_mtr);
03243 local_page = buf_block_get_frame(local_block);
03244
03245 blob_header = local_page + offset;
03246 #define BTR_BLOB_HDR_PART_LEN 0
03247 #define BTR_BLOB_HDR_NEXT_PAGE_NO 4
03248
03249 part_len = mach_read_from_4(blob_header + BTR_BLOB_HDR_PART_LEN);
03250
03251
03252 page_no = mach_read_from_4(blob_header + BTR_BLOB_HDR_NEXT_PAGE_NO);
03253
03254 offset = FIL_PAGE_DATA;
03255
03256
03257
03258
03259
03260
03261
03262 n_pages_extern++;
03263 sum_data_extern += part_len;
03264
03265
03266 mtr_commit(&local_mtr);
03267
03268 if (page_no == FIL_NULL)
03269 break;
03270 }
03271 }
03272 }
03273
03274 page_cur_move_to_next(&cur);
03275 }
03276 }
03277
03278
03279
03280
03281 mtr_commit(&mtr);
03282 if (right_page_no != FIL_NULL) {
03283 mtr_start(&mtr);
03284 block = btr_block_get(space, zip_size, right_page_no, RW_X_LATCH, &mtr);
03285 page = buf_block_get_frame(block);
03286 goto loop;
03287 }
03288 mem_heap_free(heap);
03289
03290 if (zip_size) {
03291 page_size = zip_size;
03292 } else {
03293 page_size = UNIV_PAGE_SIZE;
03294 }
03295
03296 if (level == 0)
03297 fprintf(stdout, "recs=%"PRIu64", ", n_recs);
03298
03299 fprintf(stdout, "pages=%"PRIu64", data=%"PRIu64" bytes, data/pages=%"PRIu64"%%",
03300 n_pages, sum_data,
03301 ((sum_data * 100)/ page_size)/n_pages);
03302
03303
03304 if (level == 0 && n_pages_extern) {
03305 putc('\n', stdout);
03306
03307 fprintf(stdout, " external pages: ");
03308
03309 fprintf(stdout, "pages=%"PRIu64", data=%"PRIu64" bytes, data/pages=%"PRIu64"%%",
03310 n_pages_extern, sum_data_extern,
03311 ((sum_data_extern * 100)/ page_size)/n_pages_extern);
03312 }
03313
03314 putc('\n', stdout);
03315
03316 if (level > 0) {
03317 xtrabackup_stats_level(index, level - 1);
03318 }
03319
03320 return(TRUE);
03321 }
03322
03323 static void
03324 xtrabackup_stats_func(void)
03325 {
03326 ulint n;
03327
03328
03329
03330 if (chdir(mysql_real_data_home) != 0)
03331 {
03332 fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", mysql_real_data_home);
03333 exit(EXIT_FAILURE);
03334 }
03335 fprintf(stderr, "xtrabackup: cd to %s\n", mysql_real_data_home);
03336
03337 mysql_data_home= mysql_data_home_buff;
03338 mysql_data_home[0]=FN_CURLIB;
03339 mysql_data_home[1]=0;
03340
03341
03342 srv_read_only = TRUE;
03343 srv_fake_write = TRUE;
03344
03345
03346 if(innodb_init_param())
03347 exit(EXIT_FAILURE);
03348
03349
03350
03351 for (n = 0; n < srv_n_log_files; n++) {
03352 char logname[FN_REFLEN];
03353 ibool exists;
03354 os_file_type_t type;
03355
03356 sprintf(logname, "ib_logfile%lu", (ulong) n);
03357 if (!os_file_status(logname, &exists, &type) || !exists ||
03358 type != OS_FILE_TYPE_FILE) {
03359 fprintf(stderr, "xtrabackup: Error: "
03360 "Cannot find log file %s.\n", logname);
03361 fprintf(stderr, "xtrabackup: Error: "
03362 "to use the statistics feature, you need a "
03363 "clean copy of the database including "
03364 "correctly sized log files, so you need to "
03365 "execute with --prepare twice to use this "
03366 "functionality on a backup.\n");
03367 exit(EXIT_FAILURE);
03368 }
03369 }
03370
03371 fprintf(stderr, "xtrabackup: Starting 'read-only' InnoDB instance to gather index statistics.\n"
03372 "xtrabackup: Using %"PRIu64" bytes for buffer pool (set by --use-memory parameter)\n",
03373 xtrabackup_use_memory);
03374
03375 if(innodb_init())
03376 exit(EXIT_FAILURE);
03377
03378 fprintf(stdout, "\n\n<INDEX STATISTICS>\n");
03379
03380
03381
03382 {
03383 dict_table_t* sys_tables;
03384 dict_index_t* sys_index;
03385 dict_table_t* table;
03386 btr_pcur_t pcur;
03387 rec_t* rec;
03388 byte* field;
03389 ulint len;
03390 mtr_t mtr;
03391
03392
03393
03394
03395 mutex_enter(&kernel_mutex);
03396 srv_fatal_semaphore_wait_threshold += 72000;
03397 mutex_exit(&kernel_mutex);
03398
03399 mutex_enter(&(dict_sys->mutex));
03400
03401 mtr_start(&mtr);
03402
03403 sys_tables = dict_table_get_low("SYS_TABLES");
03404 sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
03405
03406 btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
03407 TRUE, &mtr);
03408 loop:
03409 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
03410
03411 rec = btr_pcur_get_rec(&pcur);
03412
03413 if (!btr_pcur_is_on_user_rec(&pcur))
03414 {
03415
03416
03417 btr_pcur_close(&pcur);
03418 mtr_commit(&mtr);
03419
03420 mutex_exit(&(dict_sys->mutex));
03421
03422
03423
03424 mutex_enter(&kernel_mutex);
03425 srv_fatal_semaphore_wait_threshold -= 72000;
03426 mutex_exit(&kernel_mutex);
03427
03428 goto end;
03429 }
03430
03431 field = rec_get_nth_field_old(rec, 0, &len);
03432
03433 if (!rec_get_deleted_flag(rec, 0))
03434 {
03435
03436
03437
03438 char* table_name = mem_strdupl((char*) field, len);
03439
03440 btr_pcur_store_position(&pcur, &mtr);
03441
03442 mtr_commit(&mtr);
03443
03444 table = dict_table_get_low(table_name);
03445 mem_free(table_name);
03446
03447
03448 if (xtrabackup_tables) {
03449 char *p;
03450 int regres= 0;
03451 int i;
03452
03453 p = strstr(table->name, SRV_PATH_SEPARATOR_STR);
03454
03455 if (p)
03456 *p = '.';
03457
03458 for (i = 0; i < tables_regex_num; i++) {
03459 regres = regexec(&tables_regex[i], table->name, 1, tables_regmatch, 0);
03460 if (regres != REG_NOMATCH)
03461 break;
03462 }
03463
03464 if (p)
03465 *p = SRV_PATH_SEPARATOR;
03466
03467 if ( regres == REG_NOMATCH )
03468 goto skip;
03469 }
03470
03471 if (xtrabackup_tables_file) {
03472 xtrabackup_tables_t* xtable;
03473
03474 HASH_SEARCH(name_hash, tables_hash, ut_fold_string(table->name),
03475 xtrabackup_tables_t*,
03476 xtable,
03477 ut_ad(xtable->name),
03478 !strcmp(xtable->name, table->name));
03479
03480 if (!xtable)
03481 goto skip;
03482 }
03483
03484
03485 if (table == NULL) {
03486 fputs("InnoDB: Failed to load table ", stderr);
03487 ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
03488 putc('\n', stderr);
03489 } else {
03490 dict_index_t* index;
03491
03492
03493
03494
03495 if (dict_table_get_first_index(table)) {
03496 #ifdef XTRADB_BASED
03497 dict_update_statistics(table, TRUE, FALSE);
03498 #elif defined(INNODB_VERSION_SHORT)
03499 dict_update_statistics(table, TRUE);
03500 #else
03501 dict_update_statistics_low(table, TRUE);
03502 #endif
03503 }
03504
03505
03506
03507 index = UT_LIST_GET_FIRST(table->indexes);
03508 while (index != NULL) {
03509 {
03510 IB_INT64 n_vals;
03511
03512 if (index->n_user_defined_cols > 0) {
03513 n_vals = index->stat_n_diff_key_vals[
03514 index->n_user_defined_cols];
03515 } else {
03516 n_vals = index->stat_n_diff_key_vals[1];
03517 }
03518
03519 fprintf(stdout,
03520 " table: %s, index: %s, space id: %lu, root page: %lu"
03521 ", zip size: %lu"
03522 "\n estimated statistics in dictionary:\n"
03523 " key vals: %lu, leaf pages: %lu, size pages: %lu\n"
03524 " real statistics:\n",
03525 table->name, index->name,
03526 (ulong) index->space,
03527 (ulong) index->page,
03528 (ulong) fil_space_get_zip_size(index->space),
03529 (ulong) n_vals,
03530 (ulong) index->stat_n_leaf_pages,
03531 (ulong) index->stat_index_size);
03532
03533 {
03534 mtr_t local_mtr;
03535 page_t* root;
03536 ulint page_level;
03537
03538 mtr_start(&local_mtr);
03539
03540 mtr_x_lock(&(index->lock), &local_mtr);
03541 root = btr_root_get(index, &local_mtr);
03542
03543 page_level = btr_page_get_level(root, &local_mtr);
03544
03545 xtrabackup_stats_level(index, page_level);
03546
03547 mtr_commit(&local_mtr);
03548 }
03549
03550 putc('\n', stdout);
03551 }
03552 index = UT_LIST_GET_NEXT(indexes, index);
03553 }
03554 }
03555
03556 skip:
03557 mtr_start(&mtr);
03558
03559 btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
03560 }
03561
03562 goto loop;
03563 }
03564
03565 end:
03566 putc('\n', stdout);
03567
03568
03569 if(innodb_end())
03570 exit(EXIT_FAILURE);
03571 }
03572
03573
03574
03575 static bool
03576 xtrabackup_init_temp_log(void)
03577 {
03578 os_file_t src_file = -1;
03579 char src_path[FN_REFLEN];
03580 char dst_path[FN_REFLEN];
03581 ibool success;
03582
03583 ulint field;
03584 byte* log_buf;
03585 byte* log_buf_ = NULL;
03586
03587 IB_INT64 file_size;
03588
03589 LSN64 max_no;
03590 LSN64 max_lsn= 0;
03591 LSN64 checkpoint_no;
03592
03593 ulint fold;
03594
03595 max_no = ut_dulint_zero;
03596
03597 if(!xtrabackup_incremental_dir) {
03598 sprintf(dst_path, "%s%s", xtrabackup_target_dir, "/ib_logfile0");
03599 sprintf(src_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
03600 } else {
03601 sprintf(dst_path, "%s%s", xtrabackup_incremental_dir, "/ib_logfile0");
03602 sprintf(src_path, "%s%s", xtrabackup_incremental_dir, "/xtrabackup_logfile");
03603 }
03604
03605 srv_normalize_path_for_win(dst_path);
03606 srv_normalize_path_for_win(src_path);
03607 retry:
03608 src_file = os_file_create_simple_no_error_handling(
03609 0 ,
03610 src_path, OS_FILE_OPEN,
03611 OS_FILE_READ_WRITE , &success);
03612 if (!success) {
03613
03614 os_file_get_last_error(TRUE);
03615
03616 fprintf(stderr,
03617 "xtrabackup: Warning: cannot open %s. will try to find.\n",
03618 src_path);
03619
03620
03621 src_file = os_file_create_simple_no_error_handling(
03622 0 ,
03623 dst_path, OS_FILE_OPEN,
03624 OS_FILE_READ_WRITE , &success);
03625 if (!success) {
03626 os_file_get_last_error(TRUE);
03627 fprintf(stderr,
03628 " xtrabackup: Fatal error: cannot find %s.\n",
03629 src_path);
03630
03631 goto error;
03632 }
03633
03634 log_buf_ = (unsigned char*) ut_malloc(LOG_FILE_HDR_SIZE * 2);
03635 log_buf = (unsigned char*) ut_align(log_buf_, LOG_FILE_HDR_SIZE);
03636
03637 success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
03638 if (!success) {
03639 goto error;
03640 }
03641
03642 if ( ut_memcmp(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
03643 (byte*)"xtrabkup", (sizeof "xtrabkup") - 1) == 0) {
03644 fprintf(stderr,
03645 " xtrabackup: 'ib_logfile0' seems to be 'xtrabackup_logfile'. will retry.\n");
03646
03647 ut_free(log_buf_);
03648 log_buf_ = NULL;
03649
03650 os_file_close(src_file);
03651 src_file = -1;
03652
03653
03654 success = os_file_rename(
03655 0 ,
03656 dst_path, src_path);
03657 if (!success) {
03658 goto error;
03659 }
03660
03661 goto retry;
03662 }
03663
03664 fprintf(stderr,
03665 " xtrabackup: Fatal error: cannot find %s.\n",
03666 src_path);
03667
03668 ut_free(log_buf_);
03669 log_buf_ = NULL;
03670
03671 os_file_close(src_file);
03672 src_file = -1;
03673
03674 goto error;
03675 }
03676
03677 #ifdef USE_POSIX_FADVISE
03678 posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
03679 posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
03680 #endif
03681
03682 if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
03683 os_file_set_nocache(src_file, src_path, "OPEN");
03684 }
03685
03686 file_size = os_file_get_size_as_iblonglong(src_file);
03687
03688
03689
03690 log_buf_ = (unsigned char*) ut_malloc(UNIV_PAGE_SIZE * 129);
03691 log_buf = (unsigned char*) ut_align(log_buf_, UNIV_PAGE_SIZE);
03692
03693
03694 success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
03695 if (!success) {
03696 goto error;
03697 }
03698
03699 if ( ut_memcmp(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
03700 (byte*)"xtrabkup", (sizeof "xtrabkup") - 1) != 0 ) {
03701 printf("xtrabackup: notice: xtrabackup_logfile was already used to '--prepare'.\n");
03702 goto skip_modify;
03703 } else {
03704
03705
03706
03707 }
03708
03709
03710 for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2;
03711 field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) {
03712 if (!recv_check_cp_is_consistent(log_buf + field))
03713 goto not_consistent;
03714
03715 checkpoint_no = MACH_READ_64(log_buf + field + LOG_CHECKPOINT_NO);
03716
03717 if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) {
03718 max_no = checkpoint_no;
03719 max_lsn = MACH_READ_64(log_buf + field + LOG_CHECKPOINT_LSN);
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733 }
03734 not_consistent:
03735 ;
03736 }
03737
03738 if (ut_dulint_cmp(max_no, ut_dulint_zero) == 0) {
03739 fprintf(stderr, "xtrabackup: No valid checkpoint found.\n");
03740 goto error;
03741 }
03742
03743
03744
03745 MACH_WRITE_64(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN, max_lsn);
03746 mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_OFFSET,
03747 LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
03748 ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
03749 #ifdef XTRADB_BASED
03750 MACH_WRITE_64(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_ARCHIVED_LSN,
03751 (ib_uint64_t)(LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
03752 ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE))));
03753 #endif
03754 fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_1, LOG_CHECKPOINT_CHECKSUM_1);
03755 mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_CHECKSUM_1, fold);
03756
03757 fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN,
03758 LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
03759 mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_CHECKSUM_2, fold);
03760
03761 MACH_WRITE_64(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN, max_lsn);
03762 mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_OFFSET,
03763 LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
03764 ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
03765 #ifdef XTRADB_BASED
03766 MACH_WRITE_64(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_ARCHIVED_LSN,
03767 (ib_uint64_t)(LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
03768 ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE))));
03769 #endif
03770 fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_2, LOG_CHECKPOINT_CHECKSUM_1);
03771 mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_CHECKSUM_1, fold);
03772
03773 fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN,
03774 LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
03775 mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_CHECKSUM_2, fold);
03776
03777
03778 success = os_file_write(src_path, src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
03779 if (!success) {
03780 goto error;
03781 }
03782
03783
03784
03785 if (file_size % UNIV_PAGE_SIZE) {
03786 memset(log_buf, 0, UNIV_PAGE_SIZE);
03787 success = os_file_write(src_path, src_file, log_buf,
03788 (ulint)(file_size & 0xFFFFFFFFUL),
03789 (ulint)(file_size >> 32),
03790 UNIV_PAGE_SIZE - (file_size % UNIV_PAGE_SIZE));
03791 if (!success) {
03792 goto error;
03793 }
03794
03795 file_size = os_file_get_size_as_iblonglong(src_file);
03796 }
03797
03798
03799 {
03800 ulint expand;
03801
03802 memset(log_buf, 0, UNIV_PAGE_SIZE * 128);
03803 expand = file_size / UNIV_PAGE_SIZE / 8;
03804
03805 for (; expand > 128; expand -= 128) {
03806 success = os_file_write(src_path, src_file, log_buf,
03807 (ulint)(file_size & 0xFFFFFFFFUL),
03808 (ulint)(file_size >> 32),
03809 UNIV_PAGE_SIZE * 128);
03810 if (!success) {
03811 goto error;
03812 }
03813 file_size += UNIV_PAGE_SIZE * 128;
03814 }
03815
03816 if (expand) {
03817 success = os_file_write(src_path, src_file, log_buf,
03818 (ulint)(file_size & 0xFFFFFFFFUL),
03819 (ulint)(file_size >> 32),
03820 expand * UNIV_PAGE_SIZE);
03821 if (!success) {
03822 goto error;
03823 }
03824 file_size += UNIV_PAGE_SIZE * expand;
03825 }
03826 }
03827
03828
03829 if (file_size < 2*1024*1024L) {
03830 memset(log_buf, 0, UNIV_PAGE_SIZE);
03831 while (file_size < 2*1024*1024L) {
03832 success = os_file_write(src_path, src_file, log_buf,
03833 (ulint)(file_size & 0xFFFFFFFFUL),
03834 (ulint)(file_size >> 32),
03835 UNIV_PAGE_SIZE);
03836 if (!success) {
03837 goto error;
03838 }
03839 file_size += UNIV_PAGE_SIZE;
03840 }
03841 file_size = os_file_get_size_as_iblonglong(src_file);
03842 }
03843
03844 printf("xtrabackup: xtrabackup_logfile detected: size=%"PRIu64", start_lsn=(%"PRIu64")\n",
03845 file_size, max_lsn);
03846
03847 os_file_close(src_file);
03848 src_file = -1;
03849
03850
03851 innobase_log_group_home_dir_backup = innobase_log_group_home_dir;
03852 innobase_log_file_size_backup = innobase_log_file_size;
03853 innobase_log_files_in_group_backup = innobase_log_files_in_group;
03854
03855
03856 innobase_log_group_home_dir = NULL;
03857 innobase_log_file_size = file_size;
03858 innobase_log_files_in_group = 1;
03859
03860 srv_thread_concurrency = 0;
03861
03862
03863 success = os_file_rename(
03864 0 ,
03865 src_path, dst_path);
03866 if (!success) {
03867 goto error;
03868 }
03869 xtrabackup_logfile_is_renamed = TRUE;
03870
03871 ut_free(log_buf_);
03872
03873 return(FALSE);
03874
03875 skip_modify:
03876 os_file_close(src_file);
03877 src_file = -1;
03878 ut_free(log_buf_);
03879 return(FALSE);
03880
03881 error:
03882 if (src_file != -1)
03883 os_file_close(src_file);
03884 if (log_buf_)
03885 ut_free(log_buf_);
03886 fprintf(stderr, "xtrabackup: Error: xtrabackup_init_temp_log() failed.\n");
03887 return(TRUE);
03888 }
03889
03890
03891
03892
03893
03894
03895 static
03896 ibool
03897 get_meta_path(
03898 const char *delta_path,
03899 char *meta_path)
03900
03901 {
03902 size_t len = strlen(delta_path);
03903
03904 if (len <= 6 || strcmp(delta_path + len - 6, ".delta")) {
03905 return FALSE;
03906 }
03907 memcpy(meta_path, delta_path, len - 6);
03908 strcpy(meta_path + len - 6, XB_DELTA_INFO_SUFFIX);
03909
03910 return TRUE;
03911 }
03912
03913 static void
03914 xtrabackup_apply_delta(
03915 const char* dirname,
03916 const char* dbname,
03917 const char* filename,
03918
03919 bool )
03920 {
03921 os_file_t src_file = -1;
03922 os_file_t dst_file = -1;
03923 char src_path[FN_REFLEN];
03924 char dst_path[FN_REFLEN];
03925 char meta_path[FN_REFLEN];
03926 ibool success;
03927
03928 ibool last_buffer = FALSE;
03929 ulint page_in_buffer;
03930 ulint incremental_buffers = 0;
03931
03932 xb_delta_info_t info;
03933 ulint page_size;
03934 ulint page_size_shift;
03935
03936 ut_a(xtrabackup_incremental);
03937
03938 if (dbname) {
03939 snprintf(src_path, sizeof(src_path), "%s/%s/%s",
03940 dirname, dbname, filename);
03941 snprintf(dst_path, sizeof(dst_path), "%s/%s/%s",
03942 xtrabackup_real_target_dir, dbname, filename);
03943 } else {
03944 snprintf(src_path, sizeof(src_path), "%s/%s",
03945 dirname, filename);
03946 snprintf(dst_path, sizeof(dst_path), "%s/%s",
03947 xtrabackup_real_target_dir, filename);
03948 }
03949 dst_path[strlen(dst_path) - 6] = '\0';
03950
03951 if (!get_meta_path(src_path, meta_path)) {
03952 goto error;
03953 }
03954
03955 srv_normalize_path_for_win(dst_path);
03956 srv_normalize_path_for_win(src_path);
03957 srv_normalize_path_for_win(meta_path);
03958
03959 if (!xb_read_delta_metadata(meta_path, &info)) {
03960 goto error;
03961 }
03962
03963 page_size = info.page_size;
03964 page_size_shift = get_bit_shift(page_size);
03965 fprintf(stderr, "xtrabackup: page size for %s is %lu bytes\n",
03966 src_path, page_size);
03967 if (page_size_shift < 10 ||
03968 page_size_shift > UNIV_PAGE_SIZE_SHIFT_MAX) {
03969 fprintf(stderr,
03970 "xtrabackup: error: invalid value of page_size "
03971 "(%lu bytes) read from %s\n", page_size, meta_path);
03972 goto error;
03973 }
03974
03975 src_file = os_file_create_simple_no_error_handling(
03976 0 ,
03977 src_path, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
03978 if (!success) {
03979 os_file_get_last_error(TRUE);
03980 fprintf(stderr,
03981 "xtrabackup: error: cannot open %s\n",
03982 src_path);
03983 goto error;
03984 }
03985
03986 #ifdef USE_POSIX_FADVISE
03987 posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
03988 posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
03989 #endif
03990
03991 if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
03992 os_file_set_nocache(src_file, src_path, "OPEN");
03993 }
03994
03995 dst_file = os_file_create_simple_no_error_handling(
03996 0 ,
03997 dst_path, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
03998 if (!success) {
03999 os_file_get_last_error(TRUE);
04000 fprintf(stderr,
04001 "xtrabackup: error: cannot open %s\n",
04002 dst_path);
04003 goto error;
04004 }
04005
04006 #ifdef USE_POSIX_FADVISE
04007 posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED);
04008 #endif
04009
04010 if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
04011 os_file_set_nocache(dst_file, dst_path, "OPEN");
04012 }
04013
04014 printf("Applying %s ...\n", src_path);
04015
04016 while (!last_buffer) {
04017 ulint cluster_header;
04018
04019
04020
04021 success = os_file_read(src_file, incremental_buffer,
04022 ((incremental_buffers * (page_size / 4))
04023 << page_size_shift) & 0xFFFFFFFFUL,
04024 (incremental_buffers * (page_size / 4))
04025 >> (32 - page_size_shift),
04026 page_size);
04027 if (!success) {
04028 goto error;
04029 }
04030
04031 cluster_header = mach_read_from_4(incremental_buffer);
04032 switch(cluster_header) {
04033 case 0x78747261UL:
04034 break;
04035 case 0x58545241UL:
04036 last_buffer = TRUE;
04037 break;
04038 default:
04039 fprintf(stderr,
04040 "xtrabackup: error: %s seems not .delta file.\n",
04041 src_path);
04042 goto error;
04043 }
04044
04045 for (page_in_buffer = 1; page_in_buffer < page_size / 4;
04046 page_in_buffer++) {
04047 if (mach_read_from_4(incremental_buffer + page_in_buffer * 4)
04048 == 0xFFFFFFFFUL)
04049 break;
04050 }
04051
04052 ut_a(last_buffer || page_in_buffer == page_size / 4);
04053
04054
04055 success = os_file_read(src_file, incremental_buffer,
04056 ((incremental_buffers * (page_size / 4))
04057 << page_size_shift) & 0xFFFFFFFFUL,
04058 (incremental_buffers * (page_size / 4))
04059 >> (32 - page_size_shift),
04060 page_in_buffer * page_size);
04061 if (!success) {
04062 goto error;
04063 }
04064
04065 for (page_in_buffer = 1; page_in_buffer < page_size / 4;
04066 page_in_buffer++) {
04067 ulint offset_on_page;
04068
04069 offset_on_page = mach_read_from_4(incremental_buffer + page_in_buffer * 4);
04070
04071 if (offset_on_page == 0xFFFFFFFFUL)
04072 break;
04073
04074
04075
04076
04077
04078
04079
04080
04081 success = os_file_write(dst_path, dst_file,
04082 incremental_buffer +
04083 page_in_buffer * page_size,
04084 (offset_on_page << page_size_shift) &
04085 0xFFFFFFFFUL,
04086 offset_on_page >> (32 - page_size_shift),
04087 page_size);
04088 if (!success) {
04089 goto error;
04090 }
04091 }
04092
04093 incremental_buffers++;
04094 }
04095
04096 if (src_file != -1)
04097 os_file_close(src_file);
04098 if (dst_file != -1)
04099 os_file_close(dst_file);
04100 return;
04101
04102 error:
04103 if (src_file != -1)
04104 os_file_close(src_file);
04105 if (dst_file != -1)
04106 os_file_close(dst_file);
04107 fprintf(stderr, "xtrabackup: Error: xtrabackup_apply_delta() failed.\n");
04108 return;
04109 }
04110
04111 static void
04112 xtrabackup_apply_deltas(bool check_newer)
04113 {
04114 int ret;
04115 char dbpath[FN_REFLEN];
04116 os_file_dir_t dir;
04117 os_file_dir_t dbdir;
04118 os_file_stat_t dbinfo;
04119 os_file_stat_t fileinfo;
04120 ulint err = DB_SUCCESS;
04121 static char current_dir[2];
04122
04123 current_dir[0] = FN_CURLIB;
04124 current_dir[1] = 0;
04125 srv_data_home = current_dir;
04126
04127
04128 dbdir = os_file_opendir(xtrabackup_incremental_dir, FALSE);
04129
04130 if (dbdir != NULL) {
04131 ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dbdir,
04132 &fileinfo);
04133 while (ret == 0) {
04134 if (fileinfo.type == OS_FILE_TYPE_DIR) {
04135 goto next_file_item_1;
04136 }
04137
04138 if (strlen(fileinfo.name) > 6
04139 && 0 == strcmp(fileinfo.name +
04140 strlen(fileinfo.name) - 6,
04141 ".delta")) {
04142 xtrabackup_apply_delta(
04143 xtrabackup_incremental_dir, NULL,
04144 fileinfo.name, check_newer);
04145 }
04146 next_file_item_1:
04147 ret = fil_file_readdir_next_file(&err,
04148 xtrabackup_incremental_dir, dbdir,
04149 &fileinfo);
04150 }
04151
04152 os_file_closedir(dbdir);
04153 } else {
04154 fprintf(stderr, "xtrabackup: Cannot open dir %s\n", xtrabackup_incremental_dir);
04155 }
04156
04157
04158 dir = os_file_opendir(xtrabackup_incremental_dir, FALSE);
04159
04160 if (dir == NULL) {
04161 fprintf(stderr, "xtrabackup: Cannot open dir %s\n", xtrabackup_incremental_dir);
04162 }
04163
04164 ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dir,
04165 &dbinfo);
04166 while (ret == 0) {
04167 if (dbinfo.type == OS_FILE_TYPE_FILE
04168 || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
04169
04170 goto next_datadir_item;
04171 }
04172
04173 sprintf(dbpath, "%s/%s", xtrabackup_incremental_dir,
04174 dbinfo.name);
04175 srv_normalize_path_for_win(dbpath);
04176
04177 dbdir = os_file_opendir(dbpath, FALSE);
04178
04179 if (dbdir != NULL) {
04180
04181 ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
04182 &fileinfo);
04183 while (ret == 0) {
04184
04185 if (fileinfo.type == OS_FILE_TYPE_DIR) {
04186
04187 goto next_file_item_2;
04188 }
04189
04190 if (strlen(fileinfo.name) > 6
04191 && 0 == strcmp(fileinfo.name +
04192 strlen(fileinfo.name) - 6,
04193 ".delta")) {
04194
04195
04196 xtrabackup_apply_delta(
04197 xtrabackup_incremental_dir, dbinfo.name,
04198 fileinfo.name, check_newer);
04199 }
04200 next_file_item_2:
04201 ret = fil_file_readdir_next_file(&err,
04202 dbpath, dbdir,
04203 &fileinfo);
04204 }
04205
04206 os_file_closedir(dbdir);
04207 }
04208 next_datadir_item:
04209 ret = fil_file_readdir_next_file(&err,
04210 xtrabackup_incremental_dir,
04211 dir, &dbinfo);
04212 }
04213
04214 os_file_closedir(dir);
04215
04216 }
04217
04218 static bool
04219 xtrabackup_close_temp_log(bool clear_flag)
04220 {
04221 os_file_t src_file = -1;
04222 char src_path[FN_REFLEN];
04223 char dst_path[FN_REFLEN];
04224 ibool success;
04225
04226 byte* log_buf;
04227 byte* log_buf_ = NULL;
04228
04229
04230 if (!xtrabackup_logfile_is_renamed)
04231 return(FALSE);
04232
04233
04234 innobase_log_group_home_dir = innobase_log_group_home_dir_backup;
04235 innobase_log_file_size = innobase_log_file_size_backup;
04236 innobase_log_files_in_group = innobase_log_files_in_group_backup;
04237
04238
04239 if(!xtrabackup_incremental_dir) {
04240 sprintf(dst_path, "%s%s", xtrabackup_target_dir, "/ib_logfile0");
04241 sprintf(src_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
04242 } else {
04243 sprintf(dst_path, "%s%s", xtrabackup_incremental_dir, "/ib_logfile0");
04244 sprintf(src_path, "%s%s", xtrabackup_incremental_dir, "/xtrabackup_logfile");
04245 }
04246
04247 srv_normalize_path_for_win(dst_path);
04248 srv_normalize_path_for_win(src_path);
04249
04250 success = os_file_rename(
04251 0 ,
04252 dst_path, src_path);
04253 if (!success) {
04254 goto error;
04255 }
04256 xtrabackup_logfile_is_renamed = FALSE;
04257
04258 if (!clear_flag)
04259 return(FALSE);
04260
04261
04262 src_file = os_file_create_simple_no_error_handling(
04263 0 ,
04264 src_path, OS_FILE_OPEN,
04265 OS_FILE_READ_WRITE, &success);
04266 if (!success) {
04267 goto error;
04268 }
04269
04270 #ifdef USE_POSIX_FADVISE
04271 posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
04272 #endif
04273
04274 if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
04275 os_file_set_nocache(src_file, src_path, "OPEN");
04276 }
04277
04278 log_buf_ = (unsigned char*) ut_malloc(LOG_FILE_HDR_SIZE * 2);
04279 log_buf = (unsigned char*) ut_align(log_buf_, LOG_FILE_HDR_SIZE);
04280
04281 success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
04282 if (!success) {
04283 goto error;
04284 }
04285
04286 memset(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, ' ', 4);
04287
04288 success = os_file_write(src_path, src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
04289 if (!success) {
04290 goto error;
04291 }
04292
04293 os_file_close(src_file);
04294 src_file = -1;
04295
04296 return(FALSE);
04297 error:
04298 if (src_file != -1)
04299 os_file_close(src_file);
04300 if (log_buf_)
04301 ut_free(log_buf_);
04302 fprintf(stderr, "xtrabackup: Error: xtrabackup_close_temp_log() failed.\n");
04303 return(TRUE);
04304 }
04305
04306 static void
04307 xtrabackup_prepare_func(void)
04308 {
04309
04310
04311 if (chdir(xtrabackup_real_target_dir) != 0)
04312 {
04313 fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", xtrabackup_real_target_dir);
04314 exit(EXIT_FAILURE);
04315 }
04316 fprintf(stderr, "xtrabackup: cd to %s\n", xtrabackup_real_target_dir);
04317
04318 xtrabackup_target_dir= mysql_data_home_buff;
04319 mysql_data_home_buff[0]=FN_CURLIB;
04320 mysql_data_home_buff[1]=0;
04321
04322
04323 {
04324 char filename[FN_REFLEN];
04325
04326 sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
04327
04328 if (xtrabackup_read_metadata(filename))
04329 fprintf(stderr, "xtrabackup: error: xtrabackup_read_metadata()\n");
04330
04331 if (!strcmp(metadata_type, "full-backuped")) {
04332 fprintf(stderr, "xtrabackup: This target seems to be not prepared yet.\n");
04333 } else if (!strcmp(metadata_type, "full-prepared")) {
04334 fprintf(stderr, "xtrabackup: This target seems to be already prepared.\n");
04335 goto skip_check;
04336 } else {
04337 fprintf(stderr, "xtrabackup: This target seems not to have correct metadata...\n");
04338 }
04339
04340 if (xtrabackup_incremental) {
04341 fprintf(stderr,
04342 "xtrabackup: error: applying incremental backup needs target prepared.\n");
04343 exit(EXIT_FAILURE);
04344 }
04345 skip_check:
04346 if (xtrabackup_incremental
04347 && ut_dulint_cmp(metadata_to_lsn, incremental_lsn) != 0) {
04348 fprintf(stderr,
04349 "xtrabackup: error: This incremental backup seems not to be proper for the target.\n"
04350 "xtrabackup: Check 'to_lsn' of the target and 'from_lsn' of the incremental.\n");
04351 exit(EXIT_FAILURE);
04352 }
04353 }
04354
04355
04356 srv_max_n_threads = 1000;
04357 os_sync_mutex = NULL;
04358 ut_mem_init();
04359 #ifdef XTRADB_BASED
04360
04361 srv_page_size_shift = 14;
04362 srv_page_size = (1 << srv_page_size_shift);
04363 #endif
04364 os_sync_init();
04365 sync_init();
04366 os_io_init_simple();
04367 if(xtrabackup_init_temp_log())
04368 goto error;
04369
04370 if(xtrabackup_incremental)
04371 xtrabackup_apply_deltas(TRUE);
04372
04373 sync_close();
04374 sync_initialized = FALSE;
04375 os_sync_free();
04376 os_sync_mutex = NULL;
04377 ut_free_all_mem();
04378
04379
04380
04381
04382 if(innodb_init_param())
04383 goto error;
04384
04385 srv_apply_log_only = (ibool) xtrabackup_apply_log_only;
04386
04387
04388 if(srv_n_file_io_threads < 10) {
04389 srv_n_file_io_threads = 10;
04390 }
04391
04392 fprintf(stderr, "xtrabackup: Starting InnoDB instance for recovery.\n"
04393 "xtrabackup: Using %"PRIu64" bytes for buffer pool (set by --use-memory parameter)\n",
04394 xtrabackup_use_memory);
04395
04396 if(innodb_init())
04397 goto error;
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435
04436
04437 {
04438 fil_system_t* f_system = fil_system;
04439 fil_space_t* space;
04440
04441 mutex_enter(&(f_system->mutex));
04442 space = UT_LIST_GET_FIRST(f_system->space_list);
04443
04444 while (space != NULL) {
04445 byte* header;
04446 ulint size;
04447 ulint actual_size;
04448 mtr_t mtr;
04449 buf_block_t* block;
04450 ulint flags;
04451
04452 if (space->purpose == FIL_TABLESPACE) {
04453 mutex_exit(&(f_system->mutex));
04454
04455 mtr_start(&mtr);
04456
04457 mtr_s_lock(fil_space_get_latch(space->id, &flags), &mtr);
04458
04459 block = buf_page_get(space->id,
04460 dict_table_flags_to_zip_size(flags),
04461 0, RW_S_LATCH, &mtr);
04462 header = FIL_PAGE_DATA
04463 + buf_block_get_frame(block);
04464
04465 size = mtr_read_ulint(header + 8 , MLOG_4BYTES, &mtr);
04466
04467 mtr_commit(&mtr);
04468
04469
04470
04471 fil_extend_space_to_desired_size(&actual_size, space->id, size);
04472
04473 mutex_enter(&(f_system->mutex));
04474 }
04475
04476 space = UT_LIST_GET_NEXT(space_list, space);
04477 }
04478
04479 mutex_exit(&(f_system->mutex));
04480 }
04481
04482
04483
04484 if (xtrabackup_export) {
04485 printf("xtrabackup: export option is specified.\n");
04486 if (innobase_file_per_table) {
04487 fil_system_t* f_system = fil_system;
04488 fil_space_t* space;
04489 fil_node_t* node;
04490 os_file_t info_file = -1;
04491 char info_file_path[FN_REFLEN];
04492 ibool success;
04493 char table_name[FN_REFLEN];
04494
04495 byte* page;
04496 byte* buf = NULL;
04497
04498 buf = (byte*) ut_malloc(UNIV_PAGE_SIZE * 2);
04499 page = (byte*) ut_align(buf, UNIV_PAGE_SIZE);
04500
04501
04502 innobase_fast_shutdown = 0;
04503
04504 mutex_enter(&(f_system->mutex));
04505
04506 space = UT_LIST_GET_FIRST(f_system->space_list);
04507 while (space != NULL) {
04508
04509 if (space->purpose != FIL_TABLESPACE
04510 #ifdef XTRADB_BASED
04511 || trx_sys_sys_space(space->id)
04512 #else
04513 || space->id == 0
04514 #endif
04515 )
04516 {
04517 space = UT_LIST_GET_NEXT(space_list, space);
04518 continue;
04519 }
04520
04521 node = UT_LIST_GET_FIRST(space->chain);
04522 while (node != NULL) {
04523 int len;
04524 char *next, *prev, *p;
04525 dict_table_t* table;
04526 dict_index_t* index;
04527 ulint n_index;
04528
04529
04530 strncpy(info_file_path, node->name, FN_REFLEN);
04531 len = strlen(info_file_path);
04532 info_file_path[len - 3] = 'e';
04533 info_file_path[len - 2] = 'x';
04534 info_file_path[len - 1] = 'p';
04535
04536 p = info_file_path;
04537 prev = NULL;
04538 while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
04539 {
04540 prev = p;
04541 p = next + 1;
04542 }
04543 info_file_path[len - 4] = 0;
04544 strncpy(table_name, prev, FN_REFLEN);
04545
04546 info_file_path[len - 4] = '.';
04547
04548 mutex_exit(&(f_system->mutex));
04549 mutex_enter(&(dict_sys->mutex));
04550
04551 table = dict_table_get_low(table_name);
04552 if (!table) {
04553 fprintf(stderr,
04554 "xtrabackup: error: cannot find dictionary record of table %s\n", table_name);
04555 goto next_node;
04556 }
04557 index = dict_table_get_first_index(table);
04558 n_index = UT_LIST_GET_LEN(table->indexes);
04559 if (n_index > 31) {
04560 fprintf(stderr,
04561 "xtrabackup: error: sorry, cannot export over 31 indexes for now.\n");
04562 goto next_node;
04563 }
04564
04565
04566 bzero(page, UNIV_PAGE_SIZE);
04567 mach_write_to_4(page , 0x78706f72UL);
04568 mach_write_to_4(page + 4, 0x74696e66UL);
04569 mach_write_to_4(page + 8, n_index);
04570 strncpy((char*)page + 12, table_name, 500);
04571
04572 printf(
04573 "xtrabackup: export metadata of table '%s' to file `%s` (%lu indexes)\n",
04574 table_name, info_file_path, n_index);
04575
04576 n_index = 1;
04577 while (index) {
04578 mach_write_to_8(page + n_index * 512, index->id);
04579 mach_write_to_4(page + n_index * 512 + 8,
04580 index->page);
04581
04582 strncpy((char*)page + n_index * 512 + 12, index->name, 500);
04583
04584 printf(
04585 "xtrabackup: name=%s, id.low=%lu, page=%lu\n",
04586 index->name,
04587 (ulint)(index->id & 0xFFFFFFFFUL),
04588
04589 (ulint) index->page);
04590
04591 index = dict_table_get_next_index(index);
04592 n_index++;
04593 }
04594
04595 srv_normalize_path_for_win(info_file_path);
04596 info_file = os_file_create(
04597 0 ,
04598 info_file_path, OS_FILE_OVERWRITE,
04599 OS_FILE_NORMAL, OS_DATA_FILE, &success);
04600 if (!success) {
04601 os_file_get_last_error(TRUE);
04602 goto next_node;
04603 }
04604 success = os_file_write(info_file_path, info_file, page,
04605 0, 0, UNIV_PAGE_SIZE);
04606 if (!success) {
04607 os_file_get_last_error(TRUE);
04608 goto next_node;
04609 }
04610 success = os_file_flush(info_file);
04611 if (!success) {
04612 os_file_get_last_error(TRUE);
04613 goto next_node;
04614 }
04615 next_node:
04616 if (info_file != -1) {
04617 os_file_close(info_file);
04618 info_file = -1;
04619 }
04620 mutex_exit(&(dict_sys->mutex));
04621 mutex_enter(&(f_system->mutex));
04622
04623 node = UT_LIST_GET_NEXT(chain, node);
04624 }
04625
04626 space = UT_LIST_GET_NEXT(space_list, space);
04627 }
04628 mutex_exit(&(f_system->mutex));
04629
04630 ut_free(buf);
04631 } else {
04632 printf("xtrabackup: export option is for file_per_table only, disabled.\n");
04633 }
04634 }
04635
04636
04637 printf("\n[notice (again)]\n"
04638 " If you use binary log and don't use any hack of group commit,\n"
04639 " the binary log position seems to be:\n");
04640
04641 printf("\n");
04642
04643
04644 if (false) {
04645
04646 FILE *fp;
04647
04648 fp = fopen("xtrabackup_binlog_pos_innodb", "w");
04649 if (fp) {
04650 fprintf(fp, "%s\t%llu\n",
04651 "none", 0ULL);
04652
04653
04654
04655 fclose(fp);
04656 } else {
04657 printf("xtrabackup: failed to open 'xtrabackup_binlog_pos_innodb'\n");
04658 }
04659 }
04660
04661
04662 if ((xtrabackup_incremental
04663 && ut_dulint_cmp(srv_start_lsn, incremental_last_lsn) < 0)
04664 ||(!xtrabackup_incremental
04665 && ut_dulint_cmp(srv_start_lsn, metadata_last_lsn) < 0)) {
04666 printf( "xtrabackup: ########################################################\n"
04667 "xtrabackup: # !!WARNING!! #\n"
04668 "xtrabackup: # The transaction log file should be wrong or corrupt. #\n"
04669 "xtrabackup: # The log was not applied to the intended LSN! #\n"
04670 "xtrabackup: ########################################################\n");
04671 if (xtrabackup_incremental) {
04672 printf("xtrabackup: The intended lsn is %"PRIu64"\n",
04673 incremental_last_lsn);
04674 } else {
04675 printf("xtrabackup: The intended lsn is %"PRIu64"\n",
04676 metadata_last_lsn);
04677 }
04678 }
04679
04680 if(innodb_end())
04681 goto error;
04682
04683 sync_initialized = FALSE;
04684 os_sync_mutex = NULL;
04685
04686
04687 ut_mem_init();
04688
04689 os_sync_init();
04690 sync_init();
04691 os_io_init_simple();
04692
04693 if(xtrabackup_close_temp_log(TRUE))
04694 exit(EXIT_FAILURE);
04695
04696
04697 {
04698 char filename[FN_REFLEN];
04699
04700 strcpy(metadata_type, "full-prepared");
04701
04702 if(xtrabackup_incremental
04703 && ut_dulint_cmp(metadata_to_lsn, incremental_to_lsn) < 0)
04704 {
04705 metadata_to_lsn = incremental_to_lsn;
04706 metadata_last_lsn = incremental_last_lsn;
04707 }
04708
04709 sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
04710 if (xtrabackup_write_metadata(filename))
04711 fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_target_dir)\n");
04712
04713 if(xtrabackup_extra_lsndir) {
04714 sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
04715 if (xtrabackup_write_metadata(filename))
04716 fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
04717 }
04718 }
04719
04720 if(!xtrabackup_create_ib_logfile)
04721 return;
04722
04723
04724
04725 printf("\n[notice]\nWe cannot call InnoDB second time during the process lifetime.\n");
04726 printf("Please re-execte to create ib_logfile*. Sorry.\n");
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736
04737
04738
04739
04740 return;
04741
04742 error:
04743 xtrabackup_close_temp_log(FALSE);
04744
04745 exit(EXIT_FAILURE);
04746 }
04747
04748
04749
04750 int main(int argc, char **argv)
04751 {
04752 po::options_description commandline_options(_("Options used only in command line"));
04753 commandline_options.add_options()
04754 ("target-dir", po::value<std::string>(), _("destination directory"))
04755 ("backup", po::value<bool>(&xtrabackup_backup)->default_value(false)->zero_tokens(), _("take backup to target-dir"))
04756 ("stats", po::value<bool>(&xtrabackup_stats)->default_value(false)->zero_tokens(), _("calc statistic of datadir (offline mysqld is recommended)"))
04757 ("prepare", po::value<bool>(&xtrabackup_prepare)->default_value(false)->zero_tokens(), _("prepare a backup for starting mysql server on the backup."))
04758 ("export", po::value<bool>(&xtrabackup_export)->default_value(false)->zero_tokens(), _("create files to import to another database when prepare."))
04759 ("apply-log-only", po::value<bool>(&xtrabackup_apply_log_only)->default_value(false)->zero_tokens(), _("stop recovery process not to progress LSN after applying log when prepare."))
04760 ("print-param", po::value<bool>(&xtrabackup_print_param)->default_value(false)->zero_tokens(), _("print parameter of mysqld needed for copyback."))
04761 ("use-memory", po::value<uint64_t>(&xtrabackup_use_memory)->default_value(100*1024*1024), _("The value is used instead of buffer_pool_size"))
04762 ("suspend-at-end", po::value<bool>(&xtrabackup_suspend_at_end)->default_value(false)->zero_tokens(), _("creates a file 'xtrabackup_suspended' and waits until the user deletes that file at the end of '--backup'"))
04763 ("throttle", po::value<long>(&xtrabackup_throttle), _("limit count of IO operations (pairs of read&write) per second to IOS values (for '--backup')"))
04764 ("log-stream", po::value<bool>(&xtrabackup_stream)->default_value(false)->zero_tokens(), _("outputs the contents of 'xtrabackup_logfile' to stdout only until the file 'xtrabackup_suspended' deleted (for '--backup')."))
04765 ("extra-lsndir", po::value<std::string>(), _("(for --backup): save an extra copy of the xtrabackup_checkpoints file in this directory."))
04766 ("incremental-lsn", po::value<std::string>(), _("(for --backup): copy only .ibd pages newer than specified LSN 'high:low'. ##ATTENTION##: checkpoint lsn must be used. anyone can detect your mistake. be carefully!"))
04767 ("incremental-basedir", po::value<std::string>(), _("(for --backup): copy only .ibd pages newer than backup at specified directory."))
04768 ("incremental-dir", po::value<std::string>(), _("(for --prepare): apply .delta files and logfile in the specified directory."))
04769 ("tables", po::value<std::string>(), _("filtering by regexp for table names."))
04770 ("tables-file", po::value<std::string>(), _("filtering by list of the exact database.table name in the file."))
04771 ("create-ib-logfile", po::value<bool>(&xtrabackup_create_ib_logfile), _("** not work for now** creates ib_logfile* also after '--prepare'. ### If you want create ib_logfile*, only re-execute this command in same options. ###"))
04772 ("datadir,h", po::value<std::string>(), _("Path to the database root."))
04773 ("tmpdir,t", po::value<std::string>(), _("Path for temporary files. Several paths may be specified, separated by a colon (:), in this case they are used in a round-robin fashion."))
04774 ("parallel", po::value<uint32_t>(¶llel)->default_value(1), _("Number of threads to use for parallel datafiles transfer. Does not have any effect in the stream mode. The default value is 1."))
04775 ("innodb-adaptive-hash-index", po::value<bool>(&innobase_adaptive_hash_index)->default_value(true), _("Enable InnoDB adaptive hash index (enabled by default). Disable with --skip-innodb-adaptive-hash-index."))
04776 ("innodb-additional-mem-pool-size", po::value<long>(&innobase_additional_mem_pool_size)->default_value(1*1024*1024), _("Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures."))
04777 ("innodb-autoextend-increment", po::value<uint32_t>(&srv_auto_extend_increment)->default_value(8), _("Data file autoextend increment in megabytes"))
04778 ("innodb-buffer-pool-size", po::value<uint64_t>(&innobase_buffer_pool_size)->default_value(8*1024*1024), _("The size of the memory buffer InnoDB uses to cache data and indexes of its tables."))
04779 ("innodb-checksums", po::value<bool>(&innobase_use_checksums)->default_value(true), _("Enable InnoDB checksums validation (enabled by default). Disable with --skip-innodb-checksums."))
04780 ("innodb-data-file-path", po::value<std::string>(), _("Path to individual files and their sizes."))
04781 ("innodb-data-home-dir", po::value<std::string>(), _("The common part for InnoDB table spaces."))
04782 ("innodb-doublewrite", po::value<bool>(&innobase_use_doublewrite)->default_value(true), _("Enable InnoDB doublewrite buffer (enabled by default). Disable with --skip-innodb-doublewrite."))
04783 ("innodb-file-io-threads", po::value<long>(&innobase_file_io_threads)->default_value(4), _("Number of file I/O threads in InnoDB."))
04784 ("innodb-file-per-table", po::value<bool>(&innobase_file_per_table), _("Stores each InnoDB table to an .ibd file in the database dir."))
04785 ("innodb-flush-log-at-trx-commit", po::value<ulong>(&srv_flush_log_at_trx_commit)->default_value(1), _("Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second)."))
04786 ("innodb-flush-method", po::value<std::string>(), _("With which method to flush data."))
04787
04788 ("innodb-force-recovery", po::value<long>(&innobase_force_recovery)->default_value(0), _("Helps to save your data in case the disk image of the database becomes corrupt."))
04789 ("innodb-lock-wait-timeout", po::value<long>(&innobase_lock_wait_timeout)->default_value(50), _("Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back."))
04790 ("innodb-log-buffer-size", po::value<long>(&innobase_log_buffer_size)->default_value(1024*1024), _("The size of the buffer which InnoDB uses to write log to the log files on disk."))
04791 ("innodb-log-file-size", po::value<log_file_constraint>(&innobase_log_file_size)->default_value(20*1024*1024L), _("Size of each log file in a log group."))
04792 ("innodb-log-files-in-group", po::value<long>(&innobase_log_files_in_group)->default_value(2), _("Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here."))
04793 ("innodb-log-group-home-dir", po::value<std::string>(), _("Path to InnoDB log files."))
04794 ("innodb-max_dirty-pages-pct", po::value<ulong>(&srv_max_buf_pool_modified_pct)->default_value(90), _("Percentage of dirty pages allowed in bufferpool."))
04795 ("innodb-open-files", po::value<long>(&innobase_open_files)->default_value(300), _("How many files at the maximum InnoDB keeps open at the same time."))
04796 #ifdef XTRADB_BASED
04797 ("innodb-page-size", po::value<uint32_t>(&innobase_page_size)->default_value(1 << 14), _("The universal page size of the database."))
04798 ("innodb-log-block-size", po::value<uint32_t>(&innobase_log_block_size)->default_value(512), _("###EXPERIMENTAL###: The log block size of the transaction log file. Changing for created log file is not supported. Use on your own risk!"))
04799 ("innodb-fast-checksum", po::value<bool>(&innobase_fast_checksum), _("Change the algorithm of checksum for the whole of datapage to 4-bytes word based."))
04800 ("innodb-extra-undoslots", po::value<bool>(&innobase_extra_undoslots), _("Enable to use about 4000 undo slots instead of default 1024. Not recommended to use, Because it is not change back to disable, once it is used."))
04801 ("innodb-doublewrite-file", po::value<char *>(&innobase_doublewrite_file), _("Path to special datafile for doublewrite buffer. (default is "": not used)"))
04802 #endif
04803 ;
04804
04805 po::variables_map vm;
04806
04807 int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
04808 po::store(po::command_line_parser(argc, argv).options(commandline_options).style(style).run(), vm);
04809 po::notify(vm);
04810
04811 if (vm.count("target-dir"))
04812 xtrabackup_target_dir= vm["target-dir"].as<std::string>().c_str();
04813
04814 if (vm.count("extra-lsndir"))
04815 xtrabackup_extra_lsndir= vm["extra-lsndir"].as<std::string>().c_str();
04816
04817 if (vm.count("incremental-lsn"))
04818 xtrabackup_incremental= vm["incremental-lsn"].as<std::string>().c_str();
04819
04820 if (vm.count("incremental-basedir"))
04821 xtrabackup_incremental_basedir= vm["incremental-basedir"].as<std::string>().c_str();
04822
04823 boost::scoped_ptr<char> xtrabackup_tables_autoptr(new char[(vm.count("tables")) ? vm["tables"].as<std::string>().length() + 1: 0]);
04824 if (vm.count("tables"))
04825 {
04826 xtrabackup_tables= xtrabackup_tables_autoptr.get();
04827 strcpy(xtrabackup_tables, vm["tables"].as<std::string>().c_str());
04828 }
04829
04830 if (vm.count("tables-file"))
04831 xtrabackup_tables_file= vm["tables-file"].as<std::string>().c_str();
04832
04833 if (vm.count("tmpdir"))
04834 opt_mysql_tmpdir= vm["tmpdir"].as<std::string>().c_str();
04835
04836 if (vm.count("innodb-data-file-path"))
04837 innobase_data_file_path= vm["innodb-data-file-path"].as<std::string>().c_str();
04838
04839 boost::scoped_ptr<char> xtrabackup_incremental_dir_autoptr(new char[(vm.count("incremental-dir")) ? vm["incremental-dir"].as<std::string>().length() + 1: 0]);
04840 if (vm.count("incremental-dir"))
04841 {
04842 xtrabackup_incremental_dir= xtrabackup_incremental_dir_autoptr.get();
04843 strcpy(xtrabackup_incremental_dir, vm["incremental-dir"].as<std::string>().c_str());
04844 }
04845
04846 boost::scoped_ptr<char> innobase_data_home_dir_autoptr(new char[(vm.count("innodb-data-home-dir")) ? vm["innodb-data-home-dir"].as<std::string>().length() + 1 : 0]);
04847 if (vm.count("innodb-data-home-dir"))
04848 {
04849 innobase_data_home_dir= innobase_data_home_dir_autoptr.get();
04850 strcpy(innobase_data_home_dir, vm["innodb-data-home-dir"].as<std::string>().c_str());
04851 }
04852
04853 boost::scoped_ptr<char> innobase_flush_method_autoptr(new char[(vm.count("innodb-flush-method")) ? vm["innodb-flush-method"].as<std::string>().length() + 1 : 0]);
04854 if (vm.count("innodb-flush-method"))
04855 {
04856 innobase_unix_file_flush_method= innobase_flush_method_autoptr.get();
04857 strcpy(innobase_unix_file_flush_method, vm["innodb-flush-method"].as<std::string>().c_str());
04858 }
04859
04860 boost::scoped_ptr<char> innobase_log_group_home_dir_autoptr(new char[(vm.count("innodb-log-group-home-dir")) ? vm["innodb-log-group-home-dir"].as<std::string>().length() + 1: 0]);
04861
04862 if (vm.count("innodb-log-group-home-dir"))
04863 {
04864 innobase_log_group_home_dir= innobase_log_group_home_dir_autoptr.get();
04865 strcpy(innobase_log_group_home_dir, vm["innodb-log-group-home-dir"].as<std::string>().c_str());
04866 }
04867
04868 xtrabackup_use_memory-= xtrabackup_use_memory % (1024*1024);
04869 if (xtrabackup_use_memory < (1024*1024)) {
04870 fprintf(stderr, "xtrabackup: use-memory out of range\n");
04871 exit(EXIT_FAILURE);
04872 }
04873
04874 if (parallel < 1) {
04875 fprintf(stderr, "xtrabackup: parallel needs to be greater than 0\n");
04876 exit(EXIT_FAILURE);
04877 }
04878
04879 innobase_additional_mem_pool_size-= innobase_additional_mem_pool_size % 1024;
04880 if (innobase_additional_mem_pool_size < (512*1024)) {
04881 fprintf(stderr, "xtrabackup: innodb-additional-mem-pool-size out of range\n");
04882 exit(EXIT_FAILURE);
04883 }
04884
04885 if ((srv_auto_extend_increment < 1) || (srv_auto_extend_increment > 8)) {
04886 fprintf(stderr, "xtrabackup: innodb-auto-extend-increment out of range\n");
04887 exit(EXIT_FAILURE);
04888 }
04889
04890 innobase_buffer_pool_size-= innobase_buffer_pool_size % (1024*1024);
04891 if (innobase_buffer_pool_size < (1024*1024)) {
04892 fprintf(stderr, "xtrabackup: innodb-buffer-pool-size out of range\n");
04893 exit(EXIT_FAILURE);
04894 }
04895
04896 if ((innobase_file_io_threads < 4) || (innobase_file_io_threads > 64)) {
04897 fprintf(stderr, "xtrabackup: innodb-file-io-threads out of range\n");
04898 exit(EXIT_FAILURE);
04899 }
04900
04901 if (srv_flush_log_at_trx_commit > 2) {
04902 fprintf(stderr, "xtrabackup: innodb-flush-log-at-trx-commit out of range\n");
04903 exit(EXIT_FAILURE);
04904 }
04905
04906 if (innobase_force_recovery > 6) {
04907 fprintf(stderr, "xtrabackup: innodb-force-recovery out of range\n");
04908 exit(EXIT_FAILURE);
04909 }
04910
04911 if ((innobase_lock_wait_timeout < 1) || (innobase_lock_wait_timeout > (1024*1024*1024))) {
04912 fprintf(stderr, "xtrabackup: innodb-lock-wait-timeout out of range\n");
04913 exit(EXIT_FAILURE);
04914 }
04915
04916 innobase_log_buffer_size-= innobase_log_buffer_size % 1024;
04917 if (innobase_additional_mem_pool_size < (256*1024)) {
04918 fprintf(stderr, "xtrabackup: innodb-log-buffer-size out of range\n");
04919 exit(EXIT_FAILURE);
04920 }
04921
04922 if (innobase_additional_mem_pool_size < (1024*1024)) {
04923 fprintf(stderr, "xtrabackup: innodb-log-file-size out of range\n");
04924 exit(EXIT_FAILURE);
04925 }
04926
04927 if ((innobase_log_files_in_group < 2) || (innobase_log_files_in_group > (100))) {
04928 fprintf(stderr, "xtrabackup: innodb-log-files-in-group out of range\n");
04929 exit(EXIT_FAILURE);
04930 }
04931
04932 if (srv_max_buf_pool_modified_pct > 100) {
04933 fprintf(stderr, "xtrabackup: innodb-max-buf-pool-modified-pct out of range\n");
04934 exit(EXIT_FAILURE);
04935 }
04936
04937 if (innobase_open_files < 10) {
04938 fprintf(stderr, "xtrabackup: innodb-open-files out of range\n");
04939 exit(EXIT_FAILURE);
04940 }
04941
04942 if ((innobase_page_size < (1 << 12)) || (innobase_page_size > (1 << UNIV_PAGE_SIZE_SHIFT_MAX))) {
04943 fprintf(stderr, "xtrabackup: innodb-page-size out of range\n");
04944 exit(EXIT_FAILURE);
04945 }
04946
04947 if ((innobase_log_block_size < (512)) || (innobase_log_block_size > (1 << UNIV_PAGE_SIZE_SHIFT_MAX))) {
04948 fprintf(stderr, "xtrabackup: innodb-log-block-size out of range\n");
04949 exit(EXIT_FAILURE);
04950 }
04951
04952 if (vm.count("datadir"))
04953 {
04954 mysql_data_home_arg.assign(vm["datadir"].as<std::string>());
04955 }
04956 else
04957 {
04958 mysql_data_home_arg.assign(LOCALSTATEDIR);
04959 }
04960
04961 mysql_data_home= (char*)malloc(mysql_data_home_arg.length());
04962 strcpy(mysql_data_home, mysql_data_home_arg.c_str());
04963
04964 if ((!xtrabackup_prepare) && (strcmp(mysql_data_home, "./") == 0)) {
04965 if (!xtrabackup_print_param)
04966 usage();
04967 printf("\nxtrabackup: Error: Please set parameter 'datadir'\n");
04968 exit(EXIT_FAILURE);
04969 }
04970
04971 if (xtrabackup_tables) {
04972
04973 char *p, *next;
04974 int i;
04975 char errbuf[100];
04976
04977 tables_regex_num = 1;
04978
04979 p = xtrabackup_tables;
04980 while ((p = strchr(p, ',')) != NULL) {
04981 p++;
04982 tables_regex_num++;
04983 }
04984
04985 tables_regex = (regex_t*) ut_malloc(sizeof(regex_t) * tables_regex_num);
04986
04987 p = xtrabackup_tables;
04988 for (i=0; i < tables_regex_num; i++) {
04989 next = strchr(p, ',');
04990 ut_a(next || i == tables_regex_num - 1);
04991
04992 next++;
04993 if (i != tables_regex_num - 1)
04994 *(next - 1) = '\0';
04995
04996 regerror(regcomp(&tables_regex[i],p,REG_EXTENDED),
04997 &tables_regex[i],errbuf,sizeof(errbuf));
04998 fprintf(stderr, "xtrabackup: tables regcomp(%s): %s\n",p,errbuf);
04999
05000 if (i != tables_regex_num - 1)
05001 *(next - 1) = ',';
05002 p = next;
05003 }
05004 }
05005
05006 if (xtrabackup_tables_file) {
05007 char name_buf[NAME_LEN*2+2];
05008 FILE *fp;
05009
05010 if (xtrabackup_stream) {
05011 fprintf(stderr, "xtrabackup: Warning: --tables_file option doesn't affect with --stream.\n");
05012 xtrabackup_tables_file = NULL;
05013 goto skip_tables_file_register;
05014 }
05015
05016 name_buf[NAME_LEN*2+1] = '\0';
05017
05018
05019 tables_hash = hash_create(1000);
05020
05021
05022 fp = fopen(xtrabackup_tables_file,"r");
05023 if (!fp) {
05024 fprintf(stderr, "xtrabackup: cannot open %s\n", xtrabackup_tables_file);
05025 exit(EXIT_FAILURE);
05026 }
05027 for (;;) {
05028 xtrabackup_tables_t* table;
05029 char* p = name_buf;
05030
05031 if ( fgets(name_buf, NAME_LEN*2+1, fp) == 0 ) {
05032 break;
05033 }
05034
05035 while (*p != '\0') {
05036 if (*p == '.') {
05037 *p = '/';
05038 }
05039 p++;
05040 }
05041 p = strchr(name_buf, '\n');
05042 if (p)
05043 {
05044 *p = '\0';
05045 }
05046
05047 table = (xtrabackup_tables_t*) malloc(sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1);
05048 memset(table, '\0', sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1);
05049 table->name = ((char*)table) + sizeof(xtrabackup_tables_t);
05050 strcpy(table->name, name_buf);
05051
05052 HASH_INSERT(xtrabackup_tables_t, name_hash, tables_hash,
05053 ut_fold_string(table->name), table);
05054
05055 printf("xtrabackup: table '%s' is registered to the list.\n", table->name);
05056 }
05057 }
05058 skip_tables_file_register:
05059
05060 #ifdef XTRADB_BASED
05061
05062 srv_page_size_shift = UNIV_PAGE_SIZE_SHIFT_MAX;
05063 srv_page_size = UNIV_PAGE_SIZE_MAX;
05064 srv_log_block_size = 512;
05065 #endif
05066 if (xtrabackup_backup && xtrabackup_incremental) {
05067
05068
05069
05070 char* endchar;
05071 int error = 0;
05072
05073 incremental_lsn = strtoll(xtrabackup_incremental, &endchar, 10);
05074 if (*endchar != '\0')
05075 error = 1;
05076
05077 if (error) {
05078 fprintf(stderr, "xtrabackup: value '%s' may be wrong format for incremental option.\n",
05079 xtrabackup_incremental);
05080 exit(EXIT_FAILURE);
05081 }
05082
05083
05084 incremental_buffer_base = (byte*) malloc((UNIV_PAGE_SIZE_MAX / 4 + 1) *
05085 UNIV_PAGE_SIZE_MAX);
05086 incremental_buffer = (byte*) ut_align(incremental_buffer_base,
05087 UNIV_PAGE_SIZE_MAX);
05088 } else if (xtrabackup_backup && xtrabackup_incremental_basedir) {
05089 char filename[FN_REFLEN];
05090
05091 sprintf(filename, "%s/%s", xtrabackup_incremental_basedir, XTRABACKUP_METADATA_FILENAME);
05092
05093 if (xtrabackup_read_metadata(filename)) {
05094 fprintf(stderr,
05095 "xtrabackup: error: failed to read metadata from %s\n",
05096 filename);
05097 exit(EXIT_FAILURE);
05098 }
05099
05100 incremental_lsn = metadata_to_lsn;
05101 xtrabackup_incremental = xtrabackup_incremental_basedir;
05102
05103
05104 incremental_buffer_base = (byte*) malloc((UNIV_PAGE_SIZE_MAX / 4 + 1) *
05105 UNIV_PAGE_SIZE_MAX);
05106 incremental_buffer = (byte*) ut_align(incremental_buffer_base,
05107 UNIV_PAGE_SIZE_MAX);
05108 } else if (xtrabackup_prepare && xtrabackup_incremental_dir) {
05109 char filename[FN_REFLEN];
05110
05111 sprintf(filename, "%s/%s", xtrabackup_incremental_dir, XTRABACKUP_METADATA_FILENAME);
05112
05113 if (xtrabackup_read_metadata(filename)) {
05114 fprintf(stderr,
05115 "xtrabackup: error: failed to read metadata from %s\n",
05116 filename);
05117 exit(EXIT_FAILURE);
05118 }
05119
05120 incremental_lsn = metadata_from_lsn;
05121 incremental_to_lsn = metadata_to_lsn;
05122 incremental_last_lsn = metadata_last_lsn;
05123 xtrabackup_incremental = xtrabackup_incremental_dir;
05124
05125
05126 incremental_buffer_base = (byte*) malloc((UNIV_PAGE_SIZE / 4 + 1) *
05127 UNIV_PAGE_SIZE);
05128 incremental_buffer = (byte*) ut_align(incremental_buffer_base,
05129 UNIV_PAGE_SIZE);
05130 } else {
05131
05132 incremental_buffer_base = (byte*) malloc((1 + 1) * UNIV_PAGE_SIZE_MAX);
05133 incremental_buffer = (byte*) ut_align(incremental_buffer_base,
05134 UNIV_PAGE_SIZE_MAX);
05135
05136 xtrabackup_incremental = NULL;
05137 }
05138
05139
05140 if (xtrabackup_print_param) {
05141 printf("# This MySQL options file was generated by XtraBackup.\n");
05142 printf("[mysqld]\n");
05143 printf("datadir = \"%s\"\n", mysql_data_home);
05144 printf("tmpdir = \"%s\"\n", opt_mysql_tmpdir);
05145 printf("innodb_data_home_dir = \"%s\"\n",
05146 innobase_data_home_dir ? innobase_data_home_dir : mysql_data_home);
05147 printf("innodb_data_file_path = \"%s\"\n",
05148 innobase_data_file_path ? innobase_data_file_path : "ibdata1:10M:autoextend");
05149 printf("innodb_log_group_home_dir = \"%s\"\n",
05150 innobase_log_group_home_dir ? innobase_log_group_home_dir : mysql_data_home);
05151 printf("innodb_log_files_in_group = %ld\n", innobase_log_files_in_group);
05152 printf("innodb_log_file_size = %"PRIu64"\n", (uint64_t)innobase_log_file_size);
05153 printf("innodb_flush_method = \"%s\"\n",
05154 (innobase_unix_file_flush_method != NULL) ?
05155 innobase_unix_file_flush_method : "");
05156 exit(EXIT_SUCCESS);
05157 }
05158
05159 if (!xtrabackup_stream) {
05160 print_version();
05161 if (xtrabackup_incremental) {
05162 printf("incremental backup from %"PRIu64" is enabled.\n",
05163 incremental_lsn);
05164 }
05165 } else {
05166 if (xtrabackup_backup) {
05167 xtrabackup_suspend_at_end = TRUE;
05168 fprintf(stderr, "xtrabackup: suspend-at-end is enabled.\n");
05169 }
05170 }
05171
05172
05173 {
05174 int num = 0;
05175
05176 if (xtrabackup_backup) num++;
05177 if (xtrabackup_stats) num++;
05178 if (xtrabackup_prepare) num++;
05179 if (num != 1) {
05180 usage();
05181 exit(EXIT_FAILURE);
05182 }
05183 }
05184
05185
05186 if (xtrabackup_backup)
05187 xtrabackup_backup_func();
05188
05189
05190 if (xtrabackup_stats)
05191 xtrabackup_stats_func();
05192
05193
05194 if (xtrabackup_prepare)
05195 xtrabackup_prepare_func();
05196
05197 free(incremental_buffer_base);
05198
05199 if (xtrabackup_tables) {
05200
05201 int i;
05202
05203 for (i = 0; i < tables_regex_num; i++) {
05204 regfree(&tables_regex[i]);
05205 }
05206 ut_free(tables_regex);
05207 }
05208
05209 if (xtrabackup_tables_file) {
05210 ulint i;
05211
05212
05213 for (i = 0; i < hash_get_n_cells(tables_hash); i++) {
05214 xtrabackup_tables_t* table;
05215
05216 table = (xtrabackup_tables_t*)
05217 HASH_GET_FIRST(tables_hash, i);
05218
05219 while (table) {
05220 xtrabackup_tables_t* prev_table = table;
05221
05222 table = (xtrabackup_tables_t*)
05223 HASH_GET_NEXT(name_hash, prev_table);
05224
05225 HASH_DELETE(xtrabackup_tables_t, name_hash, tables_hash,
05226 ut_fold_string(prev_table->name), prev_table);
05227 free(prev_table);
05228 }
05229 }
05230
05231
05232 hash_table_free(tables_hash);
05233 }
05234
05235 exit(EXIT_SUCCESS);
05236 }