1 /******************************************************
2 XtraBackup: hot backup tool for InnoDB
3 (c) 2009-2020 Percona LLC and/or its affiliates
4 Originally Created 3/3/2009 Yasufumi Kinoshita
5 Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
6 Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; version 2 of the License.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20
21 *******************************************************
22
23 This file incorporates work covered by the following copyright and
24 permission notice:
25
26 Copyright (c) 2000, 2011, MySQL AB & Innobase Oy. All Rights Reserved.
27
28 This program is free software; you can redistribute it and/or modify it under
29 the terms of the GNU General Public License as published by the Free Software
30 Foundation; version 2 of the License.
31
32 This program is distributed in the hope that it will be useful, but WITHOUT
33 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
35
36 You should have received a copy of the GNU General Public License along with
37 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
38 Place, Suite 330, Boston, MA 02111-1307 USA
39
40 *******************************************************/
41
42 //#define XTRABACKUP_TARGET_IS_PLUGIN
43
44 #include <mysql_version.h>
45 #include <my_base.h>
46 #include <my_getopt.h>
47 #include <mysql_com.h>
48 #include <my_default.h>
49 #include <mysqld.h>
50 #include <sql_bitmap.h>
51
52 #include <signal.h>
53 #include <fcntl.h>
54 #include <string.h>
55
56 #ifdef __linux__
57 # include <sys/prctl.h>
58 #endif
59
60 #include <sys/resource.h>
61
62 #include <btr0sea.h>
63 #include <dict0priv.h>
64 #include <dict0stats.h>
65 #include <lock0lock.h>
66 #include <log0recv.h>
67 #include <row0mysql.h>
68 #include <row0quiesce.h>
69 #include <srv0start.h>
70 #include <buf0dblwr.h>
71 #include <my_aes.h>
72 #include <sql_locale.h>
73
74 #include <list>
75 #include <sstream>
76 #include <set>
77 #include <mysql.h>
78
79 #define G_PTR uchar*
80
81 #include "common.h"
82 #include "xtrabackup_version.h"
83 #include "datasink.h"
84
85 #include "xb_regex.h"
86 #include "fil_cur.h"
87 #include "write_filt.h"
88 #include "xtrabackup.h"
89 #include "ds_buffer.h"
90 #include "ds_tmpfile.h"
91 #include "xbstream.h"
92 #include "changed_page_bitmap.h"
93 #include "read_filt.h"
94 #include "wsrep.h"
95 #include "innobackupex.h"
96 #include "backup_mysql.h"
97 #include "backup_copy.h"
98 #include "backup_mysql.h"
99 #include "keyring_plugins.h"
100 #include "xb0xb.h"
101 #include "ds_encrypt.h"
102 #include "xbcrypt_common.h"
103 #include "crc_glue.h"
104 #include "xtrabackup_config.h"
105
106 /* TODO: replace with appropriate macros used in InnoDB 5.6 */
107 #define PAGE_ZIP_MIN_SIZE_SHIFT 10
108 #define DICT_TF_ZSSIZE_SHIFT 1
109 #define DICT_TF_FORMAT_ZIP 1
110 #define DICT_TF_FORMAT_SHIFT 5
111
112 int sys_var_init();
113
114 my_bool innodb_inited= 0;
115
116
117 /* This tablespace name is reserved by InnoDB for the system tablespace
118 which uses space_id 0 and stores extra types of system pages like UNDO
119 and doublewrite. */
120 const char reserved_system_space_name[] = "innodb_system";
121
122 /* This tablespace name is reserved by InnoDB for the predefined temporary
123 tablespace. */
124 const char reserved_temporary_space_name[] = "innodb_temporary";
125
126 /* === xtrabackup specific options === */
127 char xtrabackup_real_target_dir[FN_REFLEN] = "./xtrabackup_backupfiles/";
128 char *xtrabackup_target_dir= xtrabackup_real_target_dir;
129 my_bool xtrabackup_version = FALSE;
130 my_bool xtrabackup_backup = FALSE;
131 my_bool xtrabackup_stats = FALSE;
132 my_bool xtrabackup_prepare = FALSE;
133 my_bool xtrabackup_copy_back = FALSE;
134 my_bool xtrabackup_move_back = FALSE;
135 my_bool xtrabackup_decrypt_decompress = FALSE;
136 my_bool xtrabackup_print_param = FALSE;
137
138 my_bool xtrabackup_export = FALSE;
139 my_bool xtrabackup_apply_log_only = FALSE;
140
141 longlong xtrabackup_use_memory = 100*1024*1024L;
142 my_bool xtrabackup_create_ib_logfile = FALSE;
143
144 long xtrabackup_throttle = 0; /* 0:unlimited */
145 lint io_ticket;
146 os_event_t wait_throttle = NULL;
147 os_event_t log_copying_stop = NULL;
148
149 char *xtrabackup_incremental = NULL;
150 lsn_t incremental_lsn;
151 lsn_t incremental_to_lsn;
152 lsn_t incremental_last_lsn;
153 lsn_t incremental_flushed_lsn;
154 xb_page_bitmap *changed_page_bitmap = NULL;
155
156 char *xtrabackup_incremental_basedir = NULL; /* for --backup */
157 char *xtrabackup_extra_lsndir = NULL; /* for --backup with --extra-lsndir */
158 char *xtrabackup_incremental_dir = NULL; /* for --prepare */
159
160 char xtrabackup_real_incremental_basedir[FN_REFLEN];
161 char xtrabackup_real_extra_lsndir[FN_REFLEN];
162 char xtrabackup_real_incremental_dir[FN_REFLEN];
163
164 lsn_t xtrabackup_archived_to_lsn = 0; /* for --archived-to-lsn */
165
166 char *xtrabackup_tables = NULL;
167 char *xtrabackup_tables_file = NULL;
168 char *xtrabackup_tables_exclude = NULL;
169
170 typedef std::list<xb_regex_t> regex_list_t;
171 static regex_list_t regex_include_list;
172 static regex_list_t regex_exclude_list;
173
174 static hash_table_t* tables_include_hash = NULL;
175 static hash_table_t* tables_exclude_hash = NULL;
176
177 char *xtrabackup_databases = NULL;
178 char *xtrabackup_databases_file = NULL;
179 char *xtrabackup_databases_exclude = NULL;
180 static hash_table_t* databases_include_hash = NULL;
181 static hash_table_t* databases_exclude_hash = NULL;
182
183 static hash_table_t* inc_dir_tables_hash;
184
185 struct xb_filter_entry_struct{
186 char* name;
187 ibool has_tables;
188 hash_node_t name_hash;
189 };
190 typedef struct xb_filter_entry_struct xb_filter_entry_t;
191
192 static ulint thread_nr[SRV_MAX_N_IO_THREADS + 6];
193 static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6];
194
195 lsn_t checkpoint_lsn_start;
196 lsn_t checkpoint_no_start;
197 lsn_t log_copy_scanned_lsn;
198 ibool log_copying = TRUE;
199 ibool log_copying_running = FALSE;
200 ibool io_watching_thread_running = FALSE;
201
202 ibool xtrabackup_logfile_is_renamed = FALSE;
203
204 int xtrabackup_parallel;
205
206 char *xtrabackup_stream_str = NULL;
207 xb_stream_fmt_t xtrabackup_stream_fmt = XB_STREAM_FMT_NONE;
208 ibool xtrabackup_stream = FALSE;
209
210 const char *xtrabackup_compress_alg = NULL;
211 ibool xtrabackup_compress = FALSE;
212 uint xtrabackup_compress_threads;
213 ulonglong xtrabackup_compress_chunk_size = 0;
214
215 const char *xtrabackup_encrypt_algo_names[] =
216 { "NONE", "AES128", "AES192", "AES256", NullS};
217 TYPELIB xtrabackup_encrypt_algo_typelib=
218 {array_elements(xtrabackup_encrypt_algo_names)-1,"",
219 xtrabackup_encrypt_algo_names, NULL};
220
221 ibool xtrabackup_encrypt = FALSE;
222 ulong xtrabackup_encrypt_algo;
223 char *xtrabackup_encrypt_key = NULL;
224 char *xtrabackup_encrypt_key_file = NULL;
225 uint xtrabackup_encrypt_threads;
226 ulonglong xtrabackup_encrypt_chunk_size = 0;
227
228 ulint xtrabackup_rebuild_threads = 1;
229
230 /* sleep interval beetween log copy iterations in log copying thread
231 in milliseconds (default is 1 second) */
232 ulint xtrabackup_log_copy_interval = 1000;
233
234 /* Ignored option (--log) for MySQL option compatibility */
235 char* log_ignored_opt = NULL;
236
237 /* === metadata of backup === */
238 #define XTRABACKUP_METADATA_FILENAME "xtrabackup_checkpoints"
239 char metadata_type[30] = ""; /*[full-backuped|log-applied|
240 full-prepared|incremental]*/
241 lsn_t metadata_from_lsn = 0;
242 lsn_t metadata_to_lsn = 0;
243 lsn_t metadata_last_lsn = 0;
244
245 #define XB_LOG_FILENAME "xtrabackup_logfile"
246
247 ds_file_t *dst_log_file = NULL;
248
249 static char mysql_data_home_buff[2];
250
251 const char *defaults_group = "mysqld";
252
253 /* === static parameters in ha_innodb.cc */
254
255 #define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
256 #define HA_INNOBASE_RANGE_COUNT 100
257
258 ulong innobase_large_page_size = 0;
259
260 /* The default values for the following, type long or longlong, start-up
261 parameters are declared in mysqld.cc: */
262
263 long innobase_buffer_pool_awe_mem_mb = 0;
264 long innobase_file_io_threads = 4;
265 long innobase_read_io_threads = 4;
266 long innobase_write_io_threads = 4;
267 long innobase_force_recovery = 0;
268 long innobase_log_buffer_size = 16*1024*1024L;
269 long innobase_log_files_in_group = 2;
270 long innobase_open_files = 300L;
271
272 longlong innobase_page_size = (1LL << 14); /* 16KB */
273 static ulong innobase_log_block_size = 512;
274 my_bool innobase_fast_checksum = FALSE;
275 char* innobase_doublewrite_file = NULL;
276 char* innobase_buffer_pool_filename = NULL;
277
278 longlong innobase_buffer_pool_size = 8*1024*1024L;
279 longlong innobase_log_file_size = 48*1024*1024L;
280
281 /* The default values for the following char* start-up parameters
282 are determined in innobase_init below: */
283
284 char* innobase_ignored_opt = NULL;
285 char* innobase_data_home_dir = NULL;
286 char* innobase_data_file_path = NULL;
287 char* innobase_temp_data_file_path = NULL;
288 char* innobase_log_arch_dir = NULL;/* unused */
289 /* The following has a misleading name: starting from 4.0.5, this also
290 affects Windows: */
291 char* innobase_unix_file_flush_method = NULL;
292
293 /* Below we have boolean-valued start-up parameters, and their default
294 values */
295
296 ulong innobase_fast_shutdown = 1;
297 my_bool innobase_log_archive = FALSE;/* unused */
298 my_bool innobase_use_doublewrite = TRUE;
299 my_bool innobase_use_checksums = TRUE;
300 my_bool innobase_use_large_pages = FALSE;
301 my_bool innobase_file_per_table = FALSE;
302 my_bool innobase_locks_unsafe_for_binlog = FALSE;
303 my_bool innobase_rollback_on_timeout = FALSE;
304 my_bool innobase_create_status_file = FALSE;
305 my_bool innobase_adaptive_hash_index = TRUE;
306
307 static char *internal_innobase_data_file_path = NULL;
308
309 char* opt_transition_key = NULL;
310 char* opt_xtra_plugin_dir = NULL;
311
312 my_bool opt_generate_new_master_key = FALSE;
313 my_bool opt_generate_transition_key = FALSE;
314
315 bool use_dumped_tablespace_keys = false;
316
317 /* The following counter is used to convey information to InnoDB
318 about server activity: in selects it is not sensible to call
319 srv_active_wake_master_thread after each fetch or search, we only do
320 it every INNOBASE_WAKE_INTERVAL'th step. */
321
322 #define INNOBASE_WAKE_INTERVAL 32
323 ulong innobase_active_counter = 0;
324
325 ibool srv_compact_backup = FALSE;
326 ibool srv_rebuild_indexes = FALSE;
327
328 static char *xtrabackup_debug_sync = NULL;
329 static const char* dbug_setting = NULL;
330
331 my_bool xtrabackup_compact = FALSE;
332 my_bool xtrabackup_rebuild_indexes = FALSE;
333
334 my_bool xtrabackup_incremental_force_scan = FALSE;
335
336 /* The flushed lsn which is read from data files */
337 lsn_t min_flushed_lsn= 0;
338 lsn_t max_flushed_lsn= 0;
339
340 /* The size of archived log file */
341 size_t xtrabackup_arch_file_size = 0ULL;
342 /* The minimal LSN of found archived log files */
343 lsn_t xtrabackup_arch_first_file_lsn = 0ULL;
344 /* The maximum LSN of found archived log files */
345 lsn_t xtrabackup_arch_last_file_lsn = 0ULL;
346
347 ulong xb_open_files_limit= 0;
348 my_bool xb_close_files= FALSE;
349
350 /* Datasinks */
351 ds_ctxt_t *ds_data = NULL;
352 ds_ctxt_t *ds_meta = NULL;
353 ds_ctxt_t *ds_redo = NULL;
354
355 static bool innobackupex_mode = false;
356
357 static long innobase_log_files_in_group_save;
358 static char *srv_log_group_home_dir_save;
359 static longlong innobase_log_file_size_save;
360
361 /* set true if corresponding variable set as option config file or
362 command argument */
363 bool innodb_log_checksum_algorithm_specified = false;
364
365 /* set true if corresponding variable set as option config file or
366 command argument */
367 bool innodb_checksum_algorithm_specified = false;
368
369 /* String buffer used by --print-param to accumulate server options as they are
370 parsed from the defaults file */
371 static std::ostringstream print_param_str;
372 static std::ostringstream param_str;
373
374 /* Set of specified parameters */
375 std::set<std::string> param_set;
376
377 static ulonglong global_max_value;
378
379 extern "C" void handle_fatal_signal(int sig);
380
381 my_bool opt_galera_info = FALSE;
382 my_bool opt_slave_info = FALSE;
383 my_bool opt_no_lock = FALSE;
384 my_bool opt_safe_slave_backup = FALSE;
385 my_bool opt_rsync = FALSE;
386 my_bool opt_force_non_empty_dirs = FALSE;
387 #ifdef HAVE_VERSION_CHECK
388 my_bool opt_noversioncheck = FALSE;
389 #endif
390 my_bool opt_no_backup_locks = FALSE;
391 my_bool opt_decompress = FALSE;
392 my_bool opt_remove_original = FALSE;
393 my_bool opt_tables_compatibility_check = TRUE;
394 static my_bool opt_check_privileges = FALSE;
395
396 static const char *binlog_info_values[] = {"off", "lockless", "on", "auto",
397 NullS};
398 static TYPELIB binlog_info_typelib = {array_elements(binlog_info_values)-1, "",
399 binlog_info_values, NULL};
400 ulong opt_binlog_info;
401
402 char *opt_incremental_history_name = NULL;
403 char *opt_incremental_history_uuid = NULL;
404
405 char *opt_user = NULL;
406 char *opt_password = NULL;
407 char *opt_host = NULL;
408 char *opt_defaults_group = NULL;
409 char *opt_socket = NULL;
410 uint opt_port = 0;
411 char *opt_login_path = NULL;
412 char *opt_log_bin = NULL;
413
414 bool tty_password = false;
415 bool tty_transition_key = false;
416
417 const char *query_type_names[] = { "ALL", "UPDATE", "SELECT", NullS};
418
419 TYPELIB query_type_typelib= {array_elements(query_type_names) - 1, "",
420 query_type_names, NULL};
421
422 ulong opt_lock_wait_query_type;
423 ulong opt_kill_long_query_type;
424
425 ulong opt_decrypt_algo = 0;
426
427 uint opt_kill_long_queries_timeout = 0;
428 uint opt_lock_wait_timeout = 0;
429 uint opt_lock_wait_threshold = 0;
430 uint opt_debug_sleep_before_unlock = 0;
431 uint opt_safe_slave_backup_timeout = 0;
432 uint opt_dump_innodb_buffer_pool_timeout = 10;
433 uint opt_dump_innodb_buffer_pool_pct = 0;
434 my_bool opt_dump_innodb_buffer_pool = FALSE;
435
436 my_bool opt_lock_ddl = FALSE;
437 my_bool opt_lock_ddl_per_table = FALSE;
438 uint opt_lock_ddl_timeout = 0;
439 uint opt_backup_lock_timeout = 0;
440 uint opt_backup_lock_retry_count = 0;
441
442 const char *opt_history = NULL;
443 my_bool opt_decrypt = FALSE;
444 uint opt_read_buffer_size = 0;
445
446 const char *ssl_mode_names_lib[] =
447 {"DISABLED", "PREFERRED", "REQUIRED", "VERIFY_CA", "VERIFY_IDENTITY",
448 NullS };
449 TYPELIB ssl_mode_typelib = {array_elements(ssl_mode_names_lib) - 1, "",
450 ssl_mode_names_lib, NULL};
451
452 #if defined(HAVE_OPENSSL)
453 uint opt_ssl_mode = SSL_MODE_PREFERRED;
454 my_bool opt_use_ssl_arg= TRUE;
455 my_bool opt_ssl_verify_server_cert_arg = FALSE;
456 my_bool ssl_mode_set_explicitly= FALSE;
457 #if !defined(HAVE_YASSL)
458 char *opt_server_public_key = NULL;
459 #endif
460 #endif
461
462 static void
463 check_all_privileges();
464
465 std::vector<ulint> invalid_encrypted_tablespace_ids;
466
467 /* Whether xtrabackup_binlog_info should be created on recovery */
468 static bool recover_binlog_info;
469
470 /* Redo log format version */
471 ulint redo_log_version = REDO_LOG_V1;
472
473 /* New server-id to encrypt tablespace keys for */
474 ulint opt_encrypt_server_id = 0;
475 bool opt_encrypt_for_server_id_specified = false;
476
477 bool mdl_taken = false;
478 #define CLIENT_WARN_DEPRECATED(opt, new_opt) \
479 msg("WARNING: " opt \
480 " is deprecated and will be removed in a future version. " \
481 "Use " new_opt " instead.\n")
482
483 /* Simple datasink creation tracking...add datasinks in the reverse order you
484 want them destroyed. */
485 #define XTRABACKUP_MAX_DATASINKS 10
486 static ds_ctxt_t *datasinks[XTRABACKUP_MAX_DATASINKS];
487 static uint actual_datasinks = 0;
488 static inline
489 void
xtrabackup_add_datasink(ds_ctxt_t * ds)490 xtrabackup_add_datasink(ds_ctxt_t *ds)
491 {
492 xb_ad(actual_datasinks < XTRABACKUP_MAX_DATASINKS);
493 datasinks[actual_datasinks] = ds; actual_datasinks++;
494 }
495
496 /* ======== Datafiles iterator ======== */
497 datafiles_iter_t *
datafiles_iter_new(fil_system_t * f_system)498 datafiles_iter_new(fil_system_t *f_system)
499 {
500 datafiles_iter_t *it;
501
502 it = static_cast<datafiles_iter_t *>
503 (ut_malloc_nokey(sizeof(datafiles_iter_t)));
504 mutex_create(LATCH_ID_XTRA_DATAFILES_ITER_MUTEX, &it->mutex);
505
506 it->system = f_system;
507 it->space = NULL;
508 it->node = NULL;
509 it->started = FALSE;
510
511 return it;
512 }
513
514 fil_node_t *
datafiles_iter_next(datafiles_iter_t * it)515 datafiles_iter_next(datafiles_iter_t *it)
516 {
517 fil_node_t *new_node;
518
519 mutex_enter(&it->mutex);
520
521 if (it->node == NULL) {
522 if (it->started)
523 goto end;
524 it->started = TRUE;
525 } else {
526 it->node = UT_LIST_GET_NEXT(chain, it->node);
527 if (it->node != NULL)
528 goto end;
529 }
530
531 it->space = (it->space == NULL) ?
532 UT_LIST_GET_FIRST(it->system->space_list) :
533 UT_LIST_GET_NEXT(space_list, it->space);
534
535 while (it->space != NULL &&
536 (it->space->purpose != FIL_TYPE_TABLESPACE ||
537 UT_LIST_GET_LEN(it->space->chain) == 0))
538 it->space = UT_LIST_GET_NEXT(space_list, it->space);
539 if (it->space == NULL)
540 goto end;
541
542 it->node = UT_LIST_GET_FIRST(it->space->chain);
543 end:
544 new_node = it->node;
545 mutex_exit(&it->mutex);
546
547 return new_node;
548 }
549
550 void
datafiles_iter_free(datafiles_iter_t * it)551 datafiles_iter_free(datafiles_iter_t *it)
552 {
553 mutex_free(&it->mutex);
554 ut_free(it);
555 }
556
557 /* ======== Date copying thread context ======== */
558
559 typedef struct {
560 datafiles_iter_t *it;
561 uint num;
562 uint *count;
563 ib_mutex_t *count_mutex;
564 bool *error;
565 os_thread_id_t id;
566 } data_thread_ctxt_t;
567
568 /* ======== for option and variables ======== */
569
570 enum options_xtrabackup
571 {
572 OPT_XTRA_TARGET_DIR = 1000, /* make sure it is larger
573 than OPT_MAX_CLIENT_OPTION */
574 OPT_XTRA_BACKUP,
575 OPT_XTRA_STATS,
576 OPT_XTRA_PREPARE,
577 OPT_XTRA_EXPORT,
578 OPT_XTRA_APPLY_LOG_ONLY,
579 OPT_XTRA_PRINT_PARAM,
580 OPT_XTRA_USE_MEMORY,
581 OPT_XTRA_THROTTLE,
582 OPT_XTRA_LOG_COPY_INTERVAL,
583 OPT_XTRA_INCREMENTAL,
584 OPT_XTRA_INCREMENTAL_BASEDIR,
585 OPT_XTRA_EXTRA_LSNDIR,
586 OPT_XTRA_INCREMENTAL_DIR,
587 OPT_XTRA_ARCHIVED_TO_LSN,
588 OPT_XTRA_TABLES,
589 OPT_XTRA_TABLES_FILE,
590 OPT_XTRA_DATABASES,
591 OPT_XTRA_DATABASES_FILE,
592 OPT_XTRA_CREATE_IB_LOGFILE,
593 OPT_XTRA_PARALLEL,
594 OPT_XTRA_STREAM,
595 OPT_XTRA_COMPRESS,
596 OPT_XTRA_COMPRESS_THREADS,
597 OPT_XTRA_COMPRESS_CHUNK_SIZE,
598 OPT_XTRA_ENCRYPT,
599 OPT_XTRA_ENCRYPT_KEY,
600 OPT_XTRA_ENCRYPT_KEY_FILE,
601 OPT_XTRA_ENCRYPT_THREADS,
602 OPT_XTRA_ENCRYPT_CHUNK_SIZE,
603 OPT_XTRA_SERVER_ID,
604 OPT_XTRA_ENCRYPT_FOR_SERVER_ID,
605 OPT_LOG,
606 OPT_INNODB,
607 OPT_INNODB_CHECKSUMS,
608 OPT_INNODB_DATA_FILE_PATH,
609 OPT_INNODB_DATA_HOME_DIR,
610 OPT_INNODB_ADAPTIVE_HASH_INDEX,
611 OPT_INNODB_DOUBLEWRITE,
612 OPT_INNODB_FAST_SHUTDOWN,
613 OPT_INNODB_FILE_PER_TABLE,
614 OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
615 OPT_INNODB_FLUSH_METHOD,
616 OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
617 OPT_INNODB_LOG_ARCH_DIR,
618 OPT_INNODB_LOG_ARCHIVE,
619 OPT_INNODB_LOG_GROUP_HOME_DIR,
620 OPT_INNODB_MAX_DIRTY_PAGES_PCT,
621 OPT_INNODB_MAX_PURGE_LAG,
622 OPT_INNODB_ROLLBACK_ON_TIMEOUT,
623 OPT_INNODB_STATUS_FILE,
624 OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
625 OPT_INNODB_AUTOEXTEND_INCREMENT,
626 OPT_INNODB_BUFFER_POOL_SIZE,
627 OPT_INNODB_COMMIT_CONCURRENCY,
628 OPT_INNODB_CONCURRENCY_TICKETS,
629 OPT_INNODB_FILE_IO_THREADS,
630 OPT_INNODB_IO_CAPACITY,
631 OPT_INNODB_READ_IO_THREADS,
632 OPT_INNODB_WRITE_IO_THREADS,
633 OPT_INNODB_USE_NATIVE_AIO,
634 OPT_INNODB_PAGE_SIZE,
635 OPT_INNODB_LOG_BLOCK_SIZE,
636 OPT_INNODB_FAST_CHECKSUM,
637 OPT_INNODB_EXTRA_UNDOSLOTS,
638 OPT_INNODB_DOUBLEWRITE_FILE,
639 OPT_INNODB_BUFFER_POOL_FILENAME,
640 OPT_INNODB_FORCE_RECOVERY,
641 OPT_INNODB_LOCK_WAIT_TIMEOUT,
642 OPT_INNODB_LOG_BUFFER_SIZE,
643 OPT_INNODB_LOG_FILE_SIZE,
644 OPT_INNODB_LOG_FILES_IN_GROUP,
645 OPT_INNODB_MIRRORED_LOG_GROUPS,
646 OPT_INNODB_OPEN_FILES,
647 OPT_INNODB_SYNC_SPIN_LOOPS,
648 OPT_INNODB_THREAD_CONCURRENCY,
649 OPT_INNODB_THREAD_SLEEP_DELAY,
650 OPT_XTRA_DEBUG_SYNC,
651 OPT_XTRA_COMPACT,
652 OPT_XTRA_REBUILD_INDEXES,
653 OPT_XTRA_REBUILD_THREADS,
654 OPT_INNODB_CHECKSUM_ALGORITHM,
655 OPT_INNODB_UNDO_DIRECTORY,
656 OPT_INNODB_UNDO_TABLESPACES,
657 OPT_INNODB_LOG_CHECKSUM_ALGORITHM,
658 OPT_XTRA_INCREMENTAL_FORCE_SCAN,
659 OPT_DEFAULTS_GROUP,
660 OPT_OPEN_FILES_LIMIT,
661 OPT_CLOSE_FILES,
662 OPT_CORE_FILE,
663
664 OPT_COPY_BACK,
665 OPT_MOVE_BACK,
666 OPT_GALERA_INFO,
667 OPT_SLAVE_INFO,
668 OPT_NO_LOCK,
669 OPT_LOCK_DDL,
670 OPT_LOCK_DDL_TIMEOUT,
671 OPT_LOCK_DDL_PER_TABLE,
672 OPT_BACKUP_LOCK_TIMEOUT,
673 OPT_BACKUP_LOCK_RETRY,
674 OPT_DUMP_INNODB_BUFFER,
675 OPT_DUMP_INNODB_BUFFER_TIMEOUT,
676 OPT_DUMP_INNODB_BUFFER_PCT,
677 OPT_SAFE_SLAVE_BACKUP,
678 OPT_RSYNC,
679 OPT_FORCE_NON_EMPTY_DIRS,
680 #ifdef HAVE_VERSION_CHECK
681 OPT_NO_VERSION_CHECK,
682 #endif
683 OPT_NO_BACKUP_LOCKS,
684 OPT_DECOMPRESS,
685 OPT_INCREMENTAL_HISTORY_NAME,
686 OPT_INCREMENTAL_HISTORY_UUID,
687 OPT_DECRYPT,
688 OPT_REMOVE_ORIGINAL,
689 OPT_LOCK_WAIT_QUERY_TYPE,
690 OPT_KILL_LONG_QUERY_TYPE,
691 OPT_HISTORY,
692 OPT_KILL_LONG_QUERIES_TIMEOUT,
693 OPT_LOCK_WAIT_TIMEOUT,
694 OPT_LOCK_WAIT_THRESHOLD,
695 OPT_DEBUG_SLEEP_BEFORE_UNLOCK,
696 OPT_SAFE_SLAVE_BACKUP_TIMEOUT,
697 OPT_BINLOG_INFO,
698 OPT_REDO_LOG_VERSION,
699 OPT_XB_SECURE_AUTH,
700 OPT_TRANSITION_KEY,
701 OPT_GENERATE_TRANSITION_KEY,
702 OPT_XTRA_PLUGIN_DIR,
703 OPT_GENERATE_NEW_MASTER_KEY,
704
705 OPT_SSL_SSL,
706 OPT_SSL_MODE,
707 OPT_SSL_VERIFY_SERVER_CERT,
708 OPT_SERVER_PUBLIC_KEY,
709
710 OPT_XTRA_TABLES_EXCLUDE,
711 OPT_XTRA_DATABASES_EXCLUDE,
712
713 OPT_XTRA_TABLES_COMPATIBILITY_CHECK,
714 OPT_XTRA_CHECK_PRIVILEGES,
715 OPT_XTRA_READ_BUFFER_SIZE,
716 };
717
718 struct my_option xb_client_options[] =
719 {
720 {"version", 'v', "print xtrabackup version information",
721 (G_PTR *) &xtrabackup_version, (G_PTR *) &xtrabackup_version, 0, GET_BOOL,
722 NO_ARG, 0, 0, 0, 0, 0, 0},
723 {"target-dir", OPT_XTRA_TARGET_DIR, "destination directory", (G_PTR*) &xtrabackup_target_dir,
724 (G_PTR*) &xtrabackup_target_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
725 {"backup", OPT_XTRA_BACKUP, "take backup to target-dir",
726 (G_PTR*) &xtrabackup_backup, (G_PTR*) &xtrabackup_backup,
727 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
728 {"stats", OPT_XTRA_STATS, "calc statistic of datadir (offline mysqld is recommended)",
729 (G_PTR*) &xtrabackup_stats, (G_PTR*) &xtrabackup_stats,
730 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
731 {"prepare", OPT_XTRA_PREPARE, "prepare a backup for starting mysql server on the backup.",
732 (G_PTR*) &xtrabackup_prepare, (G_PTR*) &xtrabackup_prepare,
733 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
734 {"export", OPT_XTRA_EXPORT, "create files to import to another database when prepare.",
735 (G_PTR*) &xtrabackup_export, (G_PTR*) &xtrabackup_export,
736 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
737 {"apply-log-only", OPT_XTRA_APPLY_LOG_ONLY,
738 "stop recovery process not to progress LSN after applying log when prepare.",
739 (G_PTR*) &xtrabackup_apply_log_only, (G_PTR*) &xtrabackup_apply_log_only,
740 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
741 {"print-param", OPT_XTRA_PRINT_PARAM, "print parameter of mysqld needed for copyback.",
742 (G_PTR*) &xtrabackup_print_param, (G_PTR*) &xtrabackup_print_param,
743 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
744 {"use-memory", OPT_XTRA_USE_MEMORY, "The value is used instead of buffer_pool_size",
745 (G_PTR*) &xtrabackup_use_memory, (G_PTR*) &xtrabackup_use_memory,
746 0, GET_LL, REQUIRED_ARG, 100*1024*1024L, 1024*1024L, LLONG_MAX, 0,
747 1024*1024L, 0},
748 {"throttle", OPT_XTRA_THROTTLE, "limit count of IO operations (pairs of read&write) per second to IOS values (for '--backup')",
749 (G_PTR*) &xtrabackup_throttle, (G_PTR*) &xtrabackup_throttle,
750 0, GET_LONG, REQUIRED_ARG, 0, 0, LONG_MAX, 0, 1, 0},
751 {"log", OPT_LOG, "Ignored option for MySQL option compatibility",
752 (G_PTR*) &log_ignored_opt, (G_PTR*) &log_ignored_opt, 0,
753 GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
754 {"log-copy-interval", OPT_XTRA_LOG_COPY_INTERVAL, "time interval between checks done by log copying thread in milliseconds (default is 1 second).",
755 (G_PTR*) &xtrabackup_log_copy_interval, (G_PTR*) &xtrabackup_log_copy_interval,
756 0, GET_LONG, REQUIRED_ARG, 1000, 0, LONG_MAX, 0, 1, 0},
757 {"extra-lsndir", OPT_XTRA_EXTRA_LSNDIR, "(for --backup): save an extra copy of the xtrabackup_checkpoints file in this directory.",
758 (G_PTR*) &xtrabackup_extra_lsndir, (G_PTR*) &xtrabackup_extra_lsndir,
759 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
760 {"incremental-lsn", OPT_XTRA_INCREMENTAL, "(for --backup): copy only .ibd pages newer than specified LSN 'high:low'. ##ATTENTION##: If a wrong LSN value is specified, it is impossible to diagnose this, causing the backup to be unusable. Be careful!",
761 (G_PTR*) &xtrabackup_incremental, (G_PTR*) &xtrabackup_incremental,
762 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
763 {"incremental-basedir", OPT_XTRA_INCREMENTAL_BASEDIR, "(for --backup): copy only .ibd pages newer than backup at specified directory.",
764 (G_PTR*) &xtrabackup_incremental_basedir, (G_PTR*) &xtrabackup_incremental_basedir,
765 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
766 {"incremental-dir", OPT_XTRA_INCREMENTAL_DIR, "(for --prepare): apply .delta files and logfile in the specified directory.",
767 (G_PTR*) &xtrabackup_incremental_dir, (G_PTR*) &xtrabackup_incremental_dir,
768 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
769 {"to-archived-lsn", OPT_XTRA_ARCHIVED_TO_LSN,
770 "Don't apply archived logs with bigger log sequence number.",
771 (G_PTR*) &xtrabackup_archived_to_lsn, (G_PTR*) &xtrabackup_archived_to_lsn, 0,
772 GET_LL, REQUIRED_ARG, 0, 0, LLONG_MAX, 0, 0, 0},
773 {"tables", OPT_XTRA_TABLES, "filtering by regexp for table names.",
774 (G_PTR*) &xtrabackup_tables, (G_PTR*) &xtrabackup_tables,
775 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
776 {"tables_file", OPT_XTRA_TABLES_FILE, "filtering by list of the exact database.table name in the file.",
777 (G_PTR*) &xtrabackup_tables_file, (G_PTR*) &xtrabackup_tables_file,
778 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
779 {"databases", OPT_XTRA_DATABASES, "filtering by list of databases.",
780 (G_PTR*) &xtrabackup_databases, (G_PTR*) &xtrabackup_databases,
781 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
782 {"databases_file", OPT_XTRA_TABLES_FILE,
783 "filtering by list of databases in the file.",
784 (G_PTR*) &xtrabackup_databases_file, (G_PTR*) &xtrabackup_databases_file,
785 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
786 {"tables-exclude", OPT_XTRA_TABLES_EXCLUDE, "filtering by regexp for table names. "
787 "Operates the same way as --tables, but matched names are excluded from backup. "
788 "Note that this option has a higher priority than --tables.",
789 (G_PTR*) &xtrabackup_tables_exclude, (G_PTR*) &xtrabackup_tables_exclude,
790 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
791 {"databases-exclude", OPT_XTRA_DATABASES_EXCLUDE, "Excluding databases based on name, "
792 "Operates the same way as --databases, but matched names are excluded from backup. "
793 "Note that this option has a higher priority than --databases.",
794 (G_PTR*) &xtrabackup_databases_exclude, (G_PTR*) &xtrabackup_databases_exclude,
795 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
796 {"create-ib-logfile", OPT_XTRA_CREATE_IB_LOGFILE, "** not work for now** creates ib_logfile* also after '--prepare'. ### If you want create ib_logfile*, only re-execute this command in same options. ###",
797 (G_PTR*) &xtrabackup_create_ib_logfile, (G_PTR*) &xtrabackup_create_ib_logfile,
798 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
799
800 {"stream", OPT_XTRA_STREAM, "Stream all backup files to the standard output "
801 "in the specified format. Currently the only supported format is 'tar'.",
802 (G_PTR*) &xtrabackup_stream_str, (G_PTR*) &xtrabackup_stream_str, 0, GET_STR,
803 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
804
805 {"compress", OPT_XTRA_COMPRESS, "Compress individual backup files using the "
806 "specified compression algorithm. Currently the only supported algorithm "
807 "is 'quicklz'. It is also the default algorithm, i.e. the one used when "
808 "--compress is used without an argument.",
809 (G_PTR*) &xtrabackup_compress_alg, (G_PTR*) &xtrabackup_compress_alg, 0,
810 GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
811
812 {"compress-threads", OPT_XTRA_COMPRESS_THREADS,
813 "Number of threads for parallel data compression. The default value is 1.",
814 (G_PTR*) &xtrabackup_compress_threads, (G_PTR*) &xtrabackup_compress_threads,
815 0, GET_UINT, REQUIRED_ARG, 1, 1, UINT_MAX, 0, 0, 0},
816
817 {"compress-chunk-size", OPT_XTRA_COMPRESS_CHUNK_SIZE,
818 "Size of working buffer(s) for compression threads in bytes. The default value is 64K.",
819 (G_PTR*) &xtrabackup_compress_chunk_size, (G_PTR*) &xtrabackup_compress_chunk_size,
820 0, GET_ULL, REQUIRED_ARG, (1 << 16), 1024, ULLONG_MAX, 0, 0, 0},
821
822 {"encrypt", OPT_XTRA_ENCRYPT, "Encrypt individual backup files using the "
823 "specified encryption algorithm.",
824 &xtrabackup_encrypt_algo, &xtrabackup_encrypt_algo,
825 &xtrabackup_encrypt_algo_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
826
827 {"encrypt-key", OPT_XTRA_ENCRYPT_KEY, "Encryption key to use.",0, 0, 0,
828 GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
829
830 {"encrypt-key-file", OPT_XTRA_ENCRYPT_KEY_FILE, "File which contains encryption key to use.",
831 (G_PTR*) &xtrabackup_encrypt_key_file, (G_PTR*) &xtrabackup_encrypt_key_file, 0,
832 GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
833
834 {"encrypt-threads", OPT_XTRA_ENCRYPT_THREADS,
835 "Number of threads for parallel data encryption. The default value is 1.",
836 (G_PTR*) &xtrabackup_encrypt_threads, (G_PTR*) &xtrabackup_encrypt_threads,
837 0, GET_UINT, REQUIRED_ARG, 1, 1, UINT_MAX, 0, 0, 0},
838
839 {"encrypt-chunk-size", OPT_XTRA_ENCRYPT_CHUNK_SIZE,
840 "Size of working buffer(S) for encryption threads in bytes. The default value is 64K.",
841 (G_PTR*) &xtrabackup_encrypt_chunk_size, (G_PTR*) &xtrabackup_encrypt_chunk_size,
842 0, GET_ULL, REQUIRED_ARG, (1 << 16), 1024, ULLONG_MAX, 0, 0, 0},
843
844 {"compact", OPT_XTRA_COMPACT,
845 "Create a compact backup by skipping secondary index pages.",
846 (G_PTR*) &xtrabackup_compact, (G_PTR*) &xtrabackup_compact,
847 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
848
849 {"rebuild_indexes", OPT_XTRA_REBUILD_INDEXES,
850 "Rebuild secondary indexes in InnoDB tables after applying the log. "
851 "Only has effect with --prepare.",
852 (G_PTR*) &xtrabackup_rebuild_indexes, (G_PTR*) &xtrabackup_rebuild_indexes,
853 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
854
855 {"rebuild_threads", OPT_XTRA_REBUILD_THREADS,
856 "Use this number of threads to rebuild indexes in a compact backup. "
857 "Only has effect with --prepare and --rebuild-indexes.",
858 (G_PTR*) &xtrabackup_rebuild_threads, (G_PTR*) &xtrabackup_rebuild_threads,
859 0, GET_UINT, REQUIRED_ARG, 1, 1, UINT_MAX, 0, 0, 0},
860
861 {"incremental-force-scan", OPT_XTRA_INCREMENTAL_FORCE_SCAN,
862 "Perform a full-scan incremental backup even in the presence of changed "
863 "page bitmap data",
864 (G_PTR*)&xtrabackup_incremental_force_scan,
865 (G_PTR*)&xtrabackup_incremental_force_scan, 0, GET_BOOL, NO_ARG,
866 0, 0, 0, 0, 0, 0},
867
868
869 {"close_files", OPT_CLOSE_FILES, "do not keep files opened. Use at your own "
870 "risk.", (G_PTR*) &xb_close_files, (G_PTR*) &xb_close_files, 0, GET_BOOL,
871 NO_ARG, 0, 0, 0, 0, 0, 0},
872
873 {"core-file", OPT_CORE_FILE, "Write core on fatal signals", 0, 0, 0,
874 GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
875
876
877 {"copy-back", OPT_COPY_BACK, "Copy all the files in a previously made "
878 "backup from the backup directory to their original locations.",
879 (uchar *) &xtrabackup_copy_back, (uchar *) &xtrabackup_copy_back, 0,
880 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
881
882 {"move-back", OPT_MOVE_BACK, "Move all the files in a previously made "
883 "backup from the backup directory to the actual datadir location. "
884 "Use with caution, as it removes backup files.",
885 (uchar *) &xtrabackup_move_back, (uchar *) &xtrabackup_move_back, 0,
886 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
887
888 {"galera-info", OPT_GALERA_INFO, "This options creates the "
889 "xtrabackup_galera_info file which contains the local node state at "
890 "the time of the backup. Option should be used when performing the "
891 "backup of Percona-XtraDB-Cluster. Has no effect when backup locks "
892 "are used to create the backup.",
893 (uchar *) &opt_galera_info, (uchar *) &opt_galera_info, 0,
894 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
895
896 {"slave-info", OPT_SLAVE_INFO, "This option is useful when backing "
897 "up a replication slave server. It prints the binary log position "
898 "and name of the master server. It also writes this information to "
899 "the \"xtrabackup_slave_info\" file as a \"CHANGE MASTER\" command. "
900 "A new slave for this master can be set up by starting a slave server "
901 "on this backup and issuing a \"CHANGE MASTER\" command with the "
902 "binary log position saved in the \"xtrabackup_slave_info\" file.",
903 (uchar *) &opt_slave_info, (uchar *) &opt_slave_info, 0,
904 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
905
906 {"no-lock", OPT_NO_LOCK, "Use this option to disable table lock "
907 "with \"FLUSH TABLES WITH READ LOCK\". Use it only if ALL your "
908 "tables are InnoDB and you DO NOT CARE about the binary log "
909 "position of the backup. This option shouldn't be used if there "
910 "are any DDL statements being executed or if any updates are "
911 "happening on non-InnoDB tables (this includes the system MyISAM "
912 "tables in the mysql database), otherwise it could lead to an "
913 "inconsistent backup. If you are considering to use --no-lock "
914 "because your backups are failing to acquire the lock, this could "
915 "be because of incoming replication events preventing the lock "
916 "from succeeding. Please try using --safe-slave-backup to "
917 "momentarily stop the replication slave thread, this may help "
918 "the backup to succeed and you then don't need to resort to "
919 "using this option.",
920 (uchar *) &opt_no_lock, (uchar *) &opt_no_lock, 0,
921 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
922
923 {"lock-ddl", OPT_LOCK_DDL, "Issue LOCK TABLES FOR BACKUP if it is "
924 "supported by server at the beginning of the backup to block all DDL "
925 "operations.", (uchar*) &opt_lock_ddl, (uchar*) &opt_lock_ddl, 0,
926 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
927
928 {"lock-ddl-timeout", OPT_LOCK_DDL_TIMEOUT,
929 "If LOCK TABLES FOR BACKUP does not return within given timeout, abort "
930 "the backup.",
931 (uchar*) &opt_lock_ddl_timeout,
932 (uchar*) &opt_lock_ddl_timeout, 0, GET_UINT,
933 REQUIRED_ARG, 31536000, 1, 31536000, 0, 1, 0},
934
935 {"lock-ddl-per-table", OPT_LOCK_DDL_PER_TABLE, "Lock DDL for each table "
936 "before xtrabackup starts the copy phase and until the backup is completed.",
937 (uchar*) &opt_lock_ddl_per_table, (uchar*) &opt_lock_ddl_per_table, 0,
938 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
939
940 {"backup-lock-timeout", OPT_BACKUP_LOCK_TIMEOUT,
941 "Timeout in seconds for attempts to acquire metadata locks.",
942 (uchar *)&opt_backup_lock_timeout, (uchar *)&opt_backup_lock_timeout, 0,
943 GET_UINT, REQUIRED_ARG, 31536000, 1, 31536000, 0, 1, 0},
944
945 {"backup-lock-retry-count", OPT_BACKUP_LOCK_RETRY,
946 "Number of attempts to acquire metadata locks.",
947 (uchar *)&opt_backup_lock_retry_count,
948 (uchar *)&opt_backup_lock_retry_count, 0,
949 GET_UINT, REQUIRED_ARG, 0, 0, UINT_MAX, 0, 1, 0},
950
951 {"dump-innodb-buffer-pool", OPT_DUMP_INNODB_BUFFER,
952 "Instruct MySQL server to dump innodb buffer pool by issuing a "
953 "SET GLOBAL innodb_buffer_pool_dump_now=ON ",
954 (uchar*) &opt_dump_innodb_buffer_pool,
955 (uchar*) &opt_dump_innodb_buffer_pool, 0,
956 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
957
958 {"dump-innodb-buffer-pool-timeout", OPT_DUMP_INNODB_BUFFER_TIMEOUT,
959 "This option specifies the number of seconds xtrabackup waits "
960 "for innodb buffer pool dump to complete",
961 (uchar*) &opt_dump_innodb_buffer_pool_timeout,
962 (uchar*) &opt_dump_innodb_buffer_pool_timeout, 0, GET_UINT,
963 REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
964
965 {"dump-innodb-buffer-pool-pct", OPT_DUMP_INNODB_BUFFER_PCT,
966 "This option specifies the percentage of buffer pool "
967 "to be dumped ",
968 (uchar*) &opt_dump_innodb_buffer_pool_pct,
969 (uchar*) &opt_dump_innodb_buffer_pool_pct, 0, GET_UINT,
970 REQUIRED_ARG, 0, 0, 100, 0, 1, 0},
971
972 {"safe-slave-backup", OPT_SAFE_SLAVE_BACKUP, "Stop slave SQL thread "
973 "and wait to start backup until Slave_open_temp_tables in "
974 "\"SHOW STATUS\" is zero. If there are no open temporary tables, "
975 "the backup will take place, otherwise the SQL thread will be "
976 "started and stopped until there are no open temporary tables. "
977 "The backup will fail if Slave_open_temp_tables does not become "
978 "zero after --safe-slave-backup-timeout seconds. The slave SQL "
979 "thread will be restarted when the backup finishes.",
980 (uchar *) &opt_safe_slave_backup,
981 (uchar *) &opt_safe_slave_backup,
982 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
983
984 {"rsync", OPT_RSYNC, "Uses the rsync utility to optimize local file "
985 "transfers. When this option is specified, innobackupex uses rsync "
986 "to copy all non-InnoDB files instead of spawning a separate cp for "
987 "each file, which can be much faster for servers with a large number "
988 "of databases or tables. This option cannot be used together with "
989 "--stream.",
990 (uchar *) &opt_rsync, (uchar *) &opt_rsync,
991 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
992
993 {"force-non-empty-directories", OPT_FORCE_NON_EMPTY_DIRS, "This "
994 "option, when specified, makes --copy-back or --move-back transfer "
995 "files to non-empty directories. Note that no existing files will be "
996 "overwritten. If --copy-back or --nove-back has to copy a file from "
997 "the backup directory which already exists in the destination "
998 "directory, it will still fail with an error.",
999 (uchar *) &opt_force_non_empty_dirs,
1000 (uchar *) &opt_force_non_empty_dirs,
1001 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1002
1003 #ifdef HAVE_VERSION_CHECK
1004 {"no-version-check", OPT_NO_VERSION_CHECK, "This option disables the "
1005 "version check which is enabled by the --version-check option.",
1006 (uchar *) &opt_noversioncheck,
1007 (uchar *) &opt_noversioncheck,
1008 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1009 #endif
1010
1011 {"tables-compatibility-check", OPT_XTRA_TABLES_COMPATIBILITY_CHECK,
1012 "This option enables engine compatibility warning.",
1013 (uchar *) & opt_tables_compatibility_check,
1014 (uchar *) & opt_tables_compatibility_check,
1015 0, GET_BOOL, NO_ARG, TRUE, 0, 0, 0, 0, 0},
1016
1017
1018 {"no-backup-locks", OPT_NO_BACKUP_LOCKS, "This option controls if "
1019 "backup locks should be used instead of FLUSH TABLES WITH READ LOCK "
1020 "on the backup stage. The option has no effect when backup locks are "
1021 "not supported by the server. This option is enabled by default, "
1022 "disable with --no-backup-locks.",
1023 (uchar *) &opt_no_backup_locks,
1024 (uchar *) &opt_no_backup_locks,
1025 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1026
1027 {"decompress", OPT_DECOMPRESS, "Decompresses all files with the .qp "
1028 "extension in a backup previously made with the --compress option.",
1029 (uchar *) &opt_decompress,
1030 (uchar *) &opt_decompress,
1031 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1032
1033 {"user", 'u', "This option specifies the MySQL username used "
1034 "when connecting to the server, if that's not the current user. "
1035 "The option accepts a string argument. See mysql --help for details.",
1036 (uchar*) &opt_user, (uchar*) &opt_user, 0, GET_STR,
1037 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1038
1039 {"host", 'H', "This option specifies the host to use when "
1040 "connecting to the database server with TCP/IP. The option accepts "
1041 "a string argument. See mysql --help for details.",
1042 (uchar*) &opt_host, (uchar*) &opt_host, 0, GET_STR,
1043 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1044
1045 {"port", 'P', "This option specifies the port to use when "
1046 "connecting to the database server with TCP/IP. The option accepts "
1047 "a string argument. See mysql --help for details.",
1048 &opt_port, &opt_port, 0, GET_UINT, REQUIRED_ARG,
1049 0, 0, 0, 0, 0, 0},
1050
1051 {"password", 'p', "This option specifies the password to use "
1052 "when connecting to the database. It accepts a string argument. "
1053 "See mysql --help for details.",
1054 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1055
1056 {"socket", 'S', "This option specifies the socket to use when "
1057 "connecting to the local database server with a UNIX domain socket. "
1058 "The option accepts a string argument. See mysql --help for details.",
1059 (uchar*) &opt_socket, (uchar*) &opt_socket, 0, GET_STR,
1060 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1061
1062 {"incremental-history-name", OPT_INCREMENTAL_HISTORY_NAME,
1063 "This option specifies the name of the backup series stored in the "
1064 "PERCONA_SCHEMA.xtrabackup_history history record to base an "
1065 "incremental backup on. Xtrabackup will search the history table "
1066 "looking for the most recent (highest innodb_to_lsn), successful "
1067 "backup in the series and take the to_lsn value to use as the "
1068 "starting lsn for the incremental backup. This will be mutually "
1069 "exclusive with --incremental-history-uuid, --incremental-basedir "
1070 "and --incremental-lsn. If no valid lsn can be found (no series by "
1071 "that name, no successful backups by that name) xtrabackup will "
1072 "return with an error. It is used with the --incremental option.",
1073 (uchar*) &opt_incremental_history_name,
1074 (uchar*) &opt_incremental_history_name, 0, GET_STR,
1075 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1076
1077 {"incremental-history-uuid", OPT_INCREMENTAL_HISTORY_UUID,
1078 "This option specifies the UUID of the specific history record "
1079 "stored in the PERCONA_SCHEMA.xtrabackup_history to base an "
1080 "incremental backup on. --incremental-history-name, "
1081 "--incremental-basedir and --incremental-lsn. If no valid lsn can be "
1082 "found (no success record with that uuid) xtrabackup will return "
1083 "with an error. It is used with the --incremental option.",
1084 (uchar*) &opt_incremental_history_uuid,
1085 (uchar*) &opt_incremental_history_uuid, 0, GET_STR,
1086 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1087
1088 {"decrypt", OPT_DECRYPT, "Decrypts all files with the .xbcrypt "
1089 "extension in a backup previously made with --encrypt option.",
1090 &opt_decrypt_algo, &opt_decrypt_algo,
1091 &xtrabackup_encrypt_algo_typelib, GET_ENUM, REQUIRED_ARG,
1092 0, 0, 0, 0, 0, 0},
1093
1094 {"remove-original", OPT_REMOVE_ORIGINAL, "Remove .qp and .xbcrypt files "
1095 "after decryption and decompression.",
1096 (uchar *) &opt_remove_original,
1097 (uchar *) &opt_remove_original,
1098 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1099
1100 {"ftwrl-wait-query-type", OPT_LOCK_WAIT_QUERY_TYPE,
1101 "This option specifies which types of queries are allowed to complete "
1102 "before innobackupex will issue the global lock. Default is all.",
1103 (uchar*) &opt_lock_wait_query_type,
1104 (uchar*) &opt_lock_wait_query_type, &query_type_typelib,
1105 GET_ENUM, REQUIRED_ARG, QUERY_TYPE_ALL, 0, 0, 0, 0, 0},
1106
1107 {"kill-long-query-type", OPT_KILL_LONG_QUERY_TYPE,
1108 "This option specifies which types of queries should be killed to "
1109 "unblock the global lock. Default is \"all\".",
1110 (uchar*) &opt_kill_long_query_type,
1111 (uchar*) &opt_kill_long_query_type, &query_type_typelib,
1112 GET_ENUM, REQUIRED_ARG, QUERY_TYPE_SELECT, 0, 0, 0, 0, 0},
1113
1114 {"history", OPT_HISTORY,
1115 "This option enables the tracking of backup history in the "
1116 "PERCONA_SCHEMA.xtrabackup_history table. An optional history "
1117 "series name may be specified that will be placed with the history "
1118 "record for the current backup being taken.",
1119 NULL, NULL, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1120
1121 {"kill-long-queries-timeout", OPT_KILL_LONG_QUERIES_TIMEOUT,
1122 "This option specifies the number of seconds innobackupex waits "
1123 "between starting FLUSH TABLES WITH READ LOCK and killing those "
1124 "queries that block it. Default is 0 seconds, which means "
1125 "innobackupex will not attempt to kill any queries.",
1126 (uchar*) &opt_kill_long_queries_timeout,
1127 (uchar*) &opt_kill_long_queries_timeout, 0, GET_UINT,
1128 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1129
1130 {"ftwrl-wait-timeout", OPT_LOCK_WAIT_TIMEOUT,
1131 "This option specifies time in seconds that innobackupex should wait "
1132 "for queries that would block FTWRL before running it. If there are "
1133 "still such queries when the timeout expires, innobackupex terminates "
1134 "with an error. Default is 0, in which case innobackupex does not "
1135 "wait for queries to complete and starts FTWRL immediately.",
1136 (uchar*) &opt_lock_wait_timeout,
1137 (uchar*) &opt_lock_wait_timeout, 0, GET_UINT,
1138 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1139
1140 {"ftwrl-wait-threshold", OPT_LOCK_WAIT_THRESHOLD,
1141 "This option specifies the query run time threshold which is used by "
1142 "innobackupex to detect long-running queries with a non-zero value "
1143 "of --ftwrl-wait-timeout. FTWRL is not started until such "
1144 "long-running queries exist. This option has no effect if "
1145 "--ftwrl-wait-timeout is 0. Default value is 60 seconds.",
1146 (uchar*) &opt_lock_wait_threshold,
1147 (uchar*) &opt_lock_wait_threshold, 0, GET_UINT,
1148 REQUIRED_ARG, 60, 0, 0, 0, 0, 0},
1149
1150 {"debug-sleep-before-unlock", OPT_DEBUG_SLEEP_BEFORE_UNLOCK,
1151 "This is a debug-only option used by the XtraBackup test suite.",
1152 (uchar*) &opt_debug_sleep_before_unlock,
1153 (uchar*) &opt_debug_sleep_before_unlock, 0, GET_UINT,
1154 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1155
1156 {"safe-slave-backup-timeout", OPT_SAFE_SLAVE_BACKUP_TIMEOUT,
1157 "How many seconds --safe-slave-backup should wait for "
1158 "Slave_open_temp_tables to become zero. (default 300)",
1159 (uchar*) &opt_safe_slave_backup_timeout,
1160 (uchar*) &opt_safe_slave_backup_timeout, 0, GET_UINT,
1161 REQUIRED_ARG, 300, 0, 0, 0, 0, 0},
1162
1163 {"binlog-info", OPT_BINLOG_INFO,
1164 "This option controls how XtraBackup should retrieve server's binary log "
1165 "coordinates corresponding to the backup. Possible values are OFF, ON, "
1166 "LOCKLESS and AUTO. See the XtraBackup manual for more information",
1167 &opt_binlog_info, &opt_binlog_info,
1168 &binlog_info_typelib, GET_ENUM, OPT_ARG, BINLOG_INFO_AUTO, 0, 0, 0, 0, 0},
1169
1170 {"reencrypt-for-server-id", OPT_XTRA_ENCRYPT_FOR_SERVER_ID,
1171 "Re-encrypt tablespace keys for given server-id.",
1172 &opt_encrypt_server_id, &opt_encrypt_server_id, 0,
1173 GET_UINT, REQUIRED_ARG, 0, 0, UINT_MAX32,
1174 0, 0, 0},
1175
1176 {"check-privileges", OPT_XTRA_CHECK_PRIVILEGES, "Check database user "
1177 "privileges before performing any query.", &opt_check_privileges,
1178 &opt_check_privileges, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1179
1180 {"read_buffer_size",
1181 OPT_XTRA_READ_BUFFER_SIZE,
1182 "Set datafile read buffer size, given value is scaled up to page size."
1183 " Default is 10Mb.",
1184 &opt_read_buffer_size,
1185 &opt_read_buffer_size,
1186 0, GET_UINT, OPT_ARG, 10*1024*1024,
1187 UNIV_PAGE_SIZE_MAX, UINT_MAX, 0, UNIV_PAGE_SIZE_MAX, 0},
1188
1189 #include "sslopt-longopts.h"
1190
1191 #if !defined(HAVE_YASSL)
1192 {"server-public-key-path", OPT_SERVER_PUBLIC_KEY,
1193 "File path to the server public RSA key in PEM format.",
1194 &opt_server_public_key, &opt_server_public_key, 0,
1195 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1196 #endif
1197
1198 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1199 };
1200
1201 uint xb_client_options_count = array_elements(xb_client_options);
1202
1203 struct my_option xb_server_options[] =
1204 {
1205 {"datadir", 'h', "Path to the database root.", (G_PTR*) &mysql_data_home,
1206 (G_PTR*) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1207 {"tmpdir", 't',
1208 "Path for temporary files. Several paths may be specified, separated by a "
1209 #if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
1210 "semicolon (;)"
1211 #else
1212 "colon (:)"
1213 #endif
1214 ", in this case they are used in a round-robin fashion.",
1215 (G_PTR*) &opt_mysql_tmpdir,
1216 (G_PTR*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1217 {"parallel", OPT_XTRA_PARALLEL,
1218 "Number of threads to use for parallel datafiles transfer. "
1219 "The default value is 1.",
1220 (G_PTR*) &xtrabackup_parallel, (G_PTR*) &xtrabackup_parallel, 0, GET_INT,
1221 REQUIRED_ARG, 1, 1, INT_MAX, 0, 0, 0},
1222
1223 {"log", OPT_LOG, "Ignored option for MySQL option compatibility",
1224 (G_PTR*) &log_ignored_opt, (G_PTR*) &log_ignored_opt, 0,
1225 GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1226
1227 {"log_bin", OPT_LOG, "Base name for the log sequence",
1228 &opt_log_bin, &opt_log_bin, 0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0},
1229
1230 {"innodb", OPT_INNODB, "Ignored option for MySQL option compatibility",
1231 (G_PTR*) &innobase_ignored_opt, (G_PTR*) &innobase_ignored_opt, 0,
1232 GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1233
1234 {"innodb_adaptive_hash_index", OPT_INNODB_ADAPTIVE_HASH_INDEX,
1235 "Enable InnoDB adaptive hash index (enabled by default). "
1236 "Disable with --skip-innodb-adaptive-hash-index.",
1237 (G_PTR*) &innobase_adaptive_hash_index,
1238 (G_PTR*) &innobase_adaptive_hash_index,
1239 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
1240 {"innodb_autoextend_increment", OPT_INNODB_AUTOEXTEND_INCREMENT,
1241 "Data file autoextend increment in megabytes",
1242 (G_PTR*) &sys_tablespace_auto_extend_increment,
1243 (G_PTR*) &sys_tablespace_auto_extend_increment,
1244 0, GET_ULONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0},
1245 {"innodb_buffer_pool_size", OPT_INNODB_BUFFER_POOL_SIZE,
1246 "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
1247 (G_PTR*) &innobase_buffer_pool_size, (G_PTR*) &innobase_buffer_pool_size, 0,
1248 GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LLONG_MAX, 0,
1249 1024*1024L, 0},
1250 {"innodb_checksums", OPT_INNODB_CHECKSUMS, "Enable InnoDB checksums validation (enabled by default). \
1251 Disable with --skip-innodb-checksums.", (G_PTR*) &innobase_use_checksums,
1252 (G_PTR*) &innobase_use_checksums, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
1253 {"innodb_data_file_path", OPT_INNODB_DATA_FILE_PATH,
1254 "Path to individual files and their sizes.", &innobase_data_file_path,
1255 &innobase_data_file_path, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1256 {"innodb_data_home_dir", OPT_INNODB_DATA_HOME_DIR,
1257 "The common part for InnoDB table spaces.", &innobase_data_home_dir,
1258 &innobase_data_home_dir, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1259 {"innodb_doublewrite", OPT_INNODB_DOUBLEWRITE, "Enable InnoDB doublewrite buffer (enabled by default). \
1260 Disable with --skip-innodb-doublewrite.", (G_PTR*) &innobase_use_doublewrite,
1261 (G_PTR*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
1262 {"innodb_io_capacity", OPT_INNODB_IO_CAPACITY,
1263 "Number of IOPs the server can do. Tunes the background IO rate",
1264 (G_PTR*) &srv_io_capacity, (G_PTR*) &srv_io_capacity,
1265 0, GET_ULONG, OPT_ARG, 200, 100, ~0UL, 0, 0, 0},
1266 {"innodb_file_io_threads", OPT_INNODB_FILE_IO_THREADS,
1267 "Number of file I/O threads in InnoDB.", (G_PTR*) &innobase_file_io_threads,
1268 (G_PTR*) &innobase_file_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 4, 64, 0,
1269 1, 0},
1270 {"innodb_read_io_threads", OPT_INNODB_READ_IO_THREADS,
1271 "Number of background read I/O threads in InnoDB.", (G_PTR*) &innobase_read_io_threads,
1272 (G_PTR*) &innobase_read_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 1, 64, 0,
1273 1, 0},
1274 {"innodb_write_io_threads", OPT_INNODB_WRITE_IO_THREADS,
1275 "Number of background write I/O threads in InnoDB.", (G_PTR*) &innobase_write_io_threads,
1276 (G_PTR*) &innobase_write_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 1, 64, 0,
1277 1, 0},
1278 {"innodb_file_per_table", OPT_INNODB_FILE_PER_TABLE,
1279 "Stores each InnoDB table to an .ibd file in the database dir.",
1280 (G_PTR*) &innobase_file_per_table,
1281 (G_PTR*) &innobase_file_per_table, 0, GET_BOOL, NO_ARG,
1282 FALSE, 0, 0, 0, 0, 0},
1283 {"innodb_flush_log_at_trx_commit", OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
1284 "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).",
1285 (G_PTR*) &srv_flush_log_at_trx_commit,
1286 (G_PTR*) &srv_flush_log_at_trx_commit,
1287 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0},
1288 {"innodb_flush_method", OPT_INNODB_FLUSH_METHOD,
1289 "With which method to flush data.", (G_PTR*) &innobase_unix_file_flush_method,
1290 (G_PTR*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
1291 0, 0, 0},
1292
1293 /* ####### Should we use this option? ####### */
1294 {"innodb_force_recovery", OPT_INNODB_FORCE_RECOVERY,
1295 "Helps to save your data in case the disk image of the database becomes corrupt.",
1296 (G_PTR*) &innobase_force_recovery, (G_PTR*) &innobase_force_recovery, 0,
1297 GET_LONG, REQUIRED_ARG, 0, 0, 6, 0, 1, 0},
1298
1299 {"innodb_log_arch_dir", OPT_INNODB_LOG_ARCH_DIR,
1300 "Where full logs should be archived.", (G_PTR*) &innobase_log_arch_dir,
1301 (G_PTR*) &innobase_log_arch_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1302 {"innodb_log_buffer_size", OPT_INNODB_LOG_BUFFER_SIZE,
1303 "The size of the buffer which InnoDB uses to write log to the log files on disk.",
1304 (G_PTR*) &innobase_log_buffer_size, (G_PTR*) &innobase_log_buffer_size, 0,
1305 GET_LONG, REQUIRED_ARG, 16*1024*1024L, 256*1024L, LONG_MAX, 0, 1024, 0},
1306 {"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE,
1307 "Size of each log file in a log group.",
1308 (G_PTR*) &innobase_log_file_size, (G_PTR*) &innobase_log_file_size, 0,
1309 GET_LL, REQUIRED_ARG, 48*1024*1024L, 1*1024*1024L, LLONG_MAX, 0,
1310 1024*1024L, 0},
1311 {"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP,
1312 "Number of log files in the log group. InnoDB writes to the files in a "
1313 "circular fashion. Value 3 is recommended here.",
1314 &innobase_log_files_in_group, &innobase_log_files_in_group,
1315 0, GET_LONG, REQUIRED_ARG, 2, 2, 100, 0, 1, 0},
1316 {"innodb_log_group_home_dir", OPT_INNODB_LOG_GROUP_HOME_DIR,
1317 "Path to InnoDB log files.", &srv_log_group_home_dir,
1318 &srv_log_group_home_dir, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1319 {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT,
1320 "Percentage of dirty pages allowed in bufferpool.",
1321 (G_PTR*) &srv_max_buf_pool_modified_pct,
1322 (G_PTR*) &srv_max_buf_pool_modified_pct, 0, GET_DOUBLE, REQUIRED_ARG,
1323 (longlong)getopt_double2ulonglong(75), (longlong)getopt_double2ulonglong(0),
1324 getopt_double2ulonglong(100), 0, 0, 0},
1325 {"innodb_open_files", OPT_INNODB_OPEN_FILES,
1326 "How many files at the maximum InnoDB keeps open at the same time.",
1327 (G_PTR*) &innobase_open_files, (G_PTR*) &innobase_open_files, 0,
1328 GET_LONG, REQUIRED_ARG, 300L, 10L, LONG_MAX, 0, 1L, 0},
1329 {"innodb_use_native_aio", OPT_INNODB_USE_NATIVE_AIO,
1330 "Use native AIO if supported on this platform.",
1331 (G_PTR*) &srv_use_native_aio,
1332 (G_PTR*) &srv_use_native_aio, 0, GET_BOOL, NO_ARG,
1333 FALSE, 0, 0, 0, 0, 0},
1334 {"innodb_page_size", OPT_INNODB_PAGE_SIZE,
1335 "The universal page size of the database.",
1336 (G_PTR*) &innobase_page_size, (G_PTR*) &innobase_page_size, 0,
1337 /* Use GET_LL to support numeric suffixes in 5.6 */
1338 GET_LL, REQUIRED_ARG,
1339 (1LL << 14), (1LL << 12), (1LL << UNIV_PAGE_SIZE_SHIFT_MAX), 0, 1L, 0},
1340 {"innodb_log_block_size", OPT_INNODB_LOG_BLOCK_SIZE,
1341 "The log block size of the transaction log file. "
1342 "Changing for created log file is not supported. Use on your own risk!",
1343 (G_PTR*) &innobase_log_block_size, (G_PTR*) &innobase_log_block_size, 0,
1344 GET_ULONG, REQUIRED_ARG, 512, 512, 1 << UNIV_PAGE_SIZE_SHIFT_MAX, 0, 1L, 0},
1345 {"innodb_fast_checksum", OPT_INNODB_FAST_CHECKSUM,
1346 "Change the algorithm of checksum for the whole of datapage to 4-bytes word based.",
1347 (G_PTR*) &innobase_fast_checksum,
1348 (G_PTR*) &innobase_fast_checksum, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1349 {"innodb_doublewrite_file", OPT_INNODB_DOUBLEWRITE_FILE,
1350 "Path to special datafile for doublewrite buffer. (default is "": not used)",
1351 (G_PTR*) &innobase_doublewrite_file, (G_PTR*) &innobase_doublewrite_file,
1352 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1353 {"innodb_buffer_pool_filename", OPT_INNODB_BUFFER_POOL_FILENAME,
1354 "Filename to/from which to dump/load the InnoDB buffer pool",
1355 (G_PTR*) &innobase_buffer_pool_filename,
1356 (G_PTR*) &innobase_buffer_pool_filename,
1357 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1358
1359 #ifndef __WIN__
1360 {"debug-sync", OPT_XTRA_DEBUG_SYNC,
1361 "Debug sync point. This is only used by the xtrabackup test suite",
1362 (G_PTR*) &xtrabackup_debug_sync,
1363 (G_PTR*) &xtrabackup_debug_sync,
1364 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1365 #endif
1366
1367 #ifndef DBUG_OFF
1368 {"debug", '#', "Output debug log. Default all ib_log output to stderr."
1369 " To redirect all ib_log output to separate file, use "
1370 "--debug=d,ib_log:o,/tmp/xtrabackup.trace", &dbug_setting,
1371 &dbug_setting, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1372 #endif /* !DBUG_OFF */
1373
1374 {"innodb_checksum_algorithm", OPT_INNODB_CHECKSUM_ALGORITHM,
1375 "The algorithm InnoDB uses for page checksumming. [CRC32, STRICT_CRC32, "
1376 "INNODB, STRICT_INNODB, NONE, STRICT_NONE]", &srv_checksum_algorithm,
1377 &srv_checksum_algorithm, &innodb_checksum_algorithm_typelib, GET_ENUM,
1378 REQUIRED_ARG, SRV_CHECKSUM_ALGORITHM_INNODB, 0, 0, 0, 0, 0},
1379 {"innodb_log_checksum_algorithm", OPT_INNODB_LOG_CHECKSUM_ALGORITHM,
1380 "The algorithm InnoDB uses for log checksumming. [CRC32, STRICT_CRC32, "
1381 "INNODB, STRICT_INNODB, NONE, STRICT_NONE]", &srv_log_checksum_algorithm,
1382 &srv_log_checksum_algorithm, &innodb_checksum_algorithm_typelib, GET_ENUM,
1383 REQUIRED_ARG, SRV_CHECKSUM_ALGORITHM_INNODB, 0, 0, 0, 0, 0},
1384 {"innodb_undo_directory", OPT_INNODB_UNDO_DIRECTORY,
1385 "Directory where undo tablespace files live, this path can be absolute.",
1386 &srv_undo_dir, &srv_undo_dir, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0,
1387 0},
1388
1389 {"innodb_undo_tablespaces", OPT_INNODB_UNDO_TABLESPACES,
1390 "Number of undo tablespaces to use.",
1391 (G_PTR*)&srv_undo_tablespaces, (G_PTR*)&srv_undo_tablespaces,
1392 0, GET_ULONG, REQUIRED_ARG, 0, 0, 126, 0, 1, 0},
1393
1394 {"defaults_group", OPT_DEFAULTS_GROUP, "defaults group in config file (default \"mysqld\").",
1395 (G_PTR*) &defaults_group, (G_PTR*) &defaults_group,
1396 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1397
1398 {"open_files_limit", OPT_OPEN_FILES_LIMIT, "the maximum number of file "
1399 "descriptors to reserve with setrlimit().",
1400 (G_PTR*) &xb_open_files_limit, (G_PTR*) &xb_open_files_limit, 0, GET_ULONG,
1401 REQUIRED_ARG, 0, 0, UINT_MAX, 0, 1, 0},
1402
1403 {"redo-log-version", OPT_REDO_LOG_VERSION,
1404 "Redo log version of the backup. For --prepare only.",
1405 &redo_log_version, &redo_log_version, 0, GET_UINT,
1406 REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
1407
1408 {"server-id", OPT_XTRA_SERVER_ID, "The server instance being backed up",
1409 &server_id, &server_id, 0, GET_UINT, REQUIRED_ARG, 0, 0, UINT_MAX32,
1410 0, 0, 0},
1411
1412 {"transition-key", OPT_TRANSITION_KEY, "Transition key to encrypt "
1413 "tablespace keys with.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1414
1415 {"xtrabackup-plugin-dir", OPT_XTRA_PLUGIN_DIR,
1416 "Directory for xtrabackup plugins.",
1417 &opt_xtra_plugin_dir, &opt_xtra_plugin_dir,
1418 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1419
1420 {"generate-new-master-key", OPT_GENERATE_NEW_MASTER_KEY,
1421 "Generate new master key when doing copy-back.",
1422 &opt_generate_new_master_key, &opt_generate_new_master_key, 0, GET_BOOL,
1423 NO_ARG, 0, 0, 0, 0, 0, 0},
1424
1425 {"generate-transition-key", OPT_GENERATE_TRANSITION_KEY,
1426 "Generate transition key and store it into keyring.",
1427 &opt_generate_transition_key, &opt_generate_transition_key, 0, GET_BOOL,
1428 NO_ARG, 0, 0, 0, 0, 0, 0},
1429
1430 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1431 };
1432
1433 uint xb_server_options_count = array_elements(xb_server_options);
1434
1435 #ifndef __WIN__
1436 static int debug_sync_resumed;
1437
1438 static void sigcont_handler(int sig);
1439
sigcont_handler(int sig)1440 static void sigcont_handler(int sig __attribute__((unused)))
1441 {
1442 debug_sync_resumed= 1;
1443 }
1444 #endif
1445
1446 static inline
1447 void
debug_sync_point(const char * name)1448 debug_sync_point(const char *name)
1449 {
1450 #ifndef __WIN__
1451 FILE *fp;
1452 pid_t pid;
1453 char pid_path[FN_REFLEN];
1454
1455 if (xtrabackup_debug_sync == NULL) {
1456 return;
1457 }
1458
1459 if (strcmp(xtrabackup_debug_sync, name)) {
1460 return;
1461 }
1462
1463 pid = getpid();
1464
1465 snprintf(pid_path, sizeof(pid_path), "%s/xtrabackup_debug_sync",
1466 xtrabackup_target_dir);
1467 fp = fopen(pid_path, "w");
1468 if (fp == NULL) {
1469 msg("xtrabackup: Error: cannot open %s\n", pid_path);
1470 exit(EXIT_FAILURE);
1471 }
1472 fprintf(fp, "%u\n", (uint) pid);
1473 fclose(fp);
1474
1475 msg("xtrabackup: DEBUG: Suspending at debug sync point '%s'. "
1476 "Resume with 'kill -SIGCONT %u'.\n", name, (uint) pid);
1477
1478 debug_sync_resumed= 0;
1479 kill(pid, SIGSTOP);
1480 while (!debug_sync_resumed) {
1481 sleep(1);
1482 }
1483
1484 /* On resume */
1485 msg("xtrabackup: DEBUG: removing the pid file.\n");
1486 my_delete(pid_path, MYF(MY_WME));
1487 #endif
1488 }
1489
1490 static const char *xb_client_default_groups[]=
1491 { "xtrabackup", "client", 0, 0, 0 };
1492
1493 static const char *xb_server_default_groups[]=
1494 { "xtrabackup", "mysqld", 0, 0, 0 };
1495
print_version(void)1496 static void print_version(void)
1497 {
1498 msg("%s version %s based on MySQL server %s %s (%s) (revision id: %s)\n",
1499 my_progname, XTRABACKUP_VERSION, MYSQL_SERVER_VERSION, SYSTEM_TYPE,
1500 MACHINE_TYPE, XTRABACKUP_REVISION);
1501 }
1502
usage(void)1503 static void usage(void)
1504 {
1505 puts("Open source backup tool for InnoDB and XtraDB\n\
1506 \n\
1507 Copyright (C) 2009-2017 Percona LLC and/or its affiliates.\n\
1508 Portions Copyright (C) 2000, 2011, MySQL AB & Innobase Oy. All Rights Reserved.\n\
1509 \n\
1510 This program is free software; you can redistribute it and/or\n\
1511 modify it under the terms of the GNU General Public License\n\
1512 as published by the Free Software Foundation version 2\n\
1513 of the License.\n\
1514 \n\
1515 This program is distributed in the hope that it will be useful,\n\
1516 but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
1517 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
1518 GNU General Public License for more details.\n\
1519 \n\
1520 You can download full text of the license on http://www.gnu.org/licenses/gpl-2.0.txt\n");
1521
1522 printf("Usage: [%s [--defaults-file=#] --backup | %s [--defaults-file=#] --prepare] [OPTIONS]\n",my_progname,my_progname);
1523 print_defaults("my", xb_server_default_groups);
1524 my_print_help(xb_client_options);
1525 my_print_help(xb_server_options);
1526 my_print_variables(xb_server_options);
1527 my_print_variables(xb_client_options);
1528 }
1529
1530 #define ADD_PRINT_PARAM_OPT(value) \
1531 { \
1532 print_param_str << opt->name << "=" << value << "\n"; \
1533 param_set.insert(opt->name); \
1534 }
1535
1536 /************************************************************************
1537 Check if parameter is set in defaults file or via command line argument
1538 @return true if parameter is set. */
1539 bool
check_if_param_set(const char * param)1540 check_if_param_set(const char *param)
1541 {
1542 return param_set.find(param) != param_set.end();
1543 }
1544
1545 my_bool
xb_get_one_option(int optid,const struct my_option * opt,char * argument)1546 xb_get_one_option(int optid,
1547 const struct my_option *opt,
1548 char *argument)
1549 {
1550 static const char* hide_value[]=
1551 { "password", "encrypt-key", "transition-key" };
1552
1553 param_str << "--" << opt->name;
1554 if (argument) {
1555 bool param_handled = false;
1556 for (unsigned i=0; i<sizeof(hide_value)/sizeof(char*); ++i) {
1557 if (strcmp(opt->name, hide_value[i]) == 0) {
1558 param_handled = true;
1559 param_str << "=*";
1560 break;
1561 }
1562 }
1563 if(!param_handled) {
1564 param_str << "=" << argument;
1565 }
1566 }
1567 param_str << " ";
1568 switch(optid) {
1569 case '#':
1570 dbug_setting = argument ? argument : "d,ib_log";
1571 DBUG_SET_INITIAL(dbug_setting);
1572 break;
1573
1574 case 'h':
1575 strmake(mysql_real_data_home,argument, FN_REFLEN - 1);
1576 mysql_data_home= mysql_real_data_home;
1577
1578 ADD_PRINT_PARAM_OPT(mysql_real_data_home);
1579 break;
1580
1581 case 't':
1582
1583 ADD_PRINT_PARAM_OPT(opt_mysql_tmpdir);
1584 break;
1585
1586 case OPT_INNODB_DATA_HOME_DIR:
1587
1588 ADD_PRINT_PARAM_OPT(innobase_data_home_dir);
1589 break;
1590
1591 case OPT_INNODB_DATA_FILE_PATH:
1592
1593 ADD_PRINT_PARAM_OPT(innobase_data_file_path);
1594 break;
1595
1596 case OPT_INNODB_LOG_GROUP_HOME_DIR:
1597
1598 ADD_PRINT_PARAM_OPT(srv_log_group_home_dir);
1599 break;
1600
1601 case OPT_INNODB_LOG_FILES_IN_GROUP:
1602
1603 ADD_PRINT_PARAM_OPT(innobase_log_files_in_group);
1604 break;
1605
1606 case OPT_INNODB_LOG_FILE_SIZE:
1607
1608 ADD_PRINT_PARAM_OPT(innobase_log_file_size);
1609 break;
1610
1611 case OPT_INNODB_FLUSH_METHOD:
1612
1613 ADD_PRINT_PARAM_OPT(innobase_unix_file_flush_method);
1614 break;
1615
1616 case OPT_INNODB_PAGE_SIZE:
1617
1618 ADD_PRINT_PARAM_OPT(innobase_page_size);
1619 break;
1620
1621 case OPT_INNODB_FAST_CHECKSUM:
1622
1623 ADD_PRINT_PARAM_OPT(!!innobase_fast_checksum);
1624 break;
1625
1626 case OPT_INNODB_LOG_BLOCK_SIZE:
1627
1628 ADD_PRINT_PARAM_OPT(innobase_log_block_size);
1629 break;
1630
1631 case OPT_INNODB_DOUBLEWRITE_FILE:
1632
1633 ADD_PRINT_PARAM_OPT(innobase_doublewrite_file);
1634 break;
1635
1636 case OPT_INNODB_UNDO_DIRECTORY:
1637
1638 ADD_PRINT_PARAM_OPT(srv_undo_dir);
1639 break;
1640
1641 case OPT_INNODB_UNDO_TABLESPACES:
1642
1643 ADD_PRINT_PARAM_OPT(srv_undo_tablespaces);
1644 break;
1645
1646 case OPT_INNODB_CHECKSUM_ALGORITHM:
1647
1648 ut_a(srv_checksum_algorithm <= SRV_CHECKSUM_ALGORITHM_STRICT_NONE);
1649
1650 ADD_PRINT_PARAM_OPT(innodb_checksum_algorithm_names[srv_checksum_algorithm]);
1651 innodb_checksum_algorithm_specified = true;
1652 break;
1653
1654 case OPT_INNODB_LOG_CHECKSUM_ALGORITHM:
1655
1656 ut_a(srv_log_checksum_algorithm <= SRV_CHECKSUM_ALGORITHM_STRICT_NONE);
1657
1658 ADD_PRINT_PARAM_OPT(innodb_checksum_algorithm_names[srv_log_checksum_algorithm]);
1659 innodb_log_checksum_algorithm_specified = true;
1660 break;
1661
1662 case OPT_INNODB_BUFFER_POOL_FILENAME:
1663
1664 ADD_PRINT_PARAM_OPT(innobase_buffer_pool_filename);
1665 break;
1666
1667 case OPT_XTRA_TARGET_DIR:
1668 strmake(xtrabackup_real_target_dir,argument, sizeof(xtrabackup_real_target_dir)-1);
1669 xtrabackup_target_dir= xtrabackup_real_target_dir;
1670 break;
1671 case OPT_XTRA_STREAM:
1672 if (!strcasecmp(argument, "tar"))
1673 xtrabackup_stream_fmt = XB_STREAM_FMT_TAR;
1674 else if (!strcasecmp(argument, "xbstream"))
1675 xtrabackup_stream_fmt = XB_STREAM_FMT_XBSTREAM;
1676 else
1677 {
1678 msg("Invalid --stream argument: %s\n", argument);
1679 return 1;
1680 }
1681 xtrabackup_stream = TRUE;
1682 break;
1683 case OPT_XTRA_COMPRESS:
1684 if (argument == NULL)
1685 xtrabackup_compress_alg = "quicklz";
1686 else if (strcasecmp(argument, "quicklz"))
1687 {
1688 msg("Invalid --compress argument: %s\n", argument);
1689 return 1;
1690 }
1691 xtrabackup_compress = TRUE;
1692 break;
1693 case OPT_XTRA_ENCRYPT:
1694 if (argument == NULL)
1695 {
1696 msg("Missing --encrypt argument, must specify a valid encryption "
1697 " algorithm.\n");
1698 return 1;
1699 }
1700 xtrabackup_encrypt = TRUE;
1701 break;
1702 case OPT_DECRYPT:
1703 if (argument == NULL) {
1704 msg("Missing --decrypt argument, must specify a "
1705 "valid encryption algorithm.\n");
1706 return(1);
1707 }
1708 opt_decrypt = TRUE;
1709 xtrabackup_decrypt_decompress = true;
1710 break;
1711 case OPT_DECOMPRESS:
1712 opt_decompress = TRUE;
1713 xtrabackup_decrypt_decompress = true;
1714 break;
1715 case (int) OPT_CORE_FILE:
1716 test_flags |= TEST_CORE_ON_SIGNAL;
1717 break;
1718 case OPT_HISTORY:
1719 if (argument) {
1720 opt_history = argument;
1721 } else {
1722 opt_history = "";
1723 }
1724 break;
1725 case OPT_XTRA_ENCRYPT_FOR_SERVER_ID:
1726 opt_encrypt_for_server_id_specified = true;
1727 break;
1728 case 'p':
1729 if (argument == disabled_my_option)
1730 argument= (char*) ""; /* Don't require password */
1731 if (argument)
1732 {
1733 hide_option(argument, &opt_password);
1734 tty_password = false;
1735 }
1736 else
1737 tty_password = true;
1738 break;
1739 case OPT_TRANSITION_KEY:
1740 if (argument == disabled_my_option)
1741 argument = (char*) ""; /* Don't require password */
1742 if (argument)
1743 {
1744 hide_option(argument, &opt_transition_key);
1745 tty_transition_key = false;
1746 }
1747 else
1748 tty_transition_key = true;
1749 use_dumped_tablespace_keys = true;
1750 break;
1751 case OPT_GENERATE_TRANSITION_KEY:
1752 use_dumped_tablespace_keys = true;
1753 break;
1754 case OPT_XTRA_ENCRYPT_KEY:
1755 hide_option(argument, &xtrabackup_encrypt_key);
1756 break;
1757
1758 #include "sslopt-case.h"
1759
1760 case '?':
1761 usage();
1762 exit(EXIT_SUCCESS);
1763 break;
1764 case 'v':
1765 print_version();
1766 exit(EXIT_SUCCESS);
1767 break;
1768 default:
1769 break;
1770 }
1771 return 0;
1772 }
1773
1774 /***********************************************************************
1775 Initializes log_block_size */
1776 static
1777 ibool
xb_init_log_block_size(void)1778 xb_init_log_block_size(void)
1779 {
1780 srv_log_block_size = 0;
1781 if (innobase_log_block_size != 512) {
1782 uint n_shift = get_bit_shift(innobase_log_block_size);
1783
1784 if (n_shift > 0) {
1785 srv_log_block_size = (1 << n_shift);
1786 msg("InnoDB: The log block size is set to %lu.\n",
1787 srv_log_block_size);
1788 }
1789 } else {
1790 srv_log_block_size = 512;
1791 }
1792 if (!srv_log_block_size) {
1793 msg("InnoDB: Error: %lu is not valid value for "
1794 "innodb_log_block_size.\n", innobase_log_block_size);
1795 return FALSE;
1796 }
1797
1798 return TRUE;
1799 }
1800
1801 /** Check that a page_size is correct for InnoDB.
1802 If correct, set the associated page_size_shift which is the power of 2
1803 for this page size.
1804 @param[in] page_size Page Size to evaluate
1805 @return an associated page_size_shift if valid, 0 if invalid. */
1806 inline
1807 ulong
innodb_page_size_validate(ulong page_size)1808 innodb_page_size_validate(
1809 ulong page_size)
1810 {
1811 ulong n;
1812
1813 for (n = UNIV_PAGE_SIZE_SHIFT_MIN;
1814 n <= UNIV_PAGE_SIZE_SHIFT_MAX;
1815 n++) {
1816 if (page_size == static_cast<ulong>(1 << n)) {
1817 return(n);
1818 }
1819 }
1820
1821 return(0);
1822 }
1823
1824 static my_bool
innodb_init_param(void)1825 innodb_init_param(void)
1826 {
1827 /* innobase_init */
1828 static char current_dir[3]; /* Set if using current lib */
1829 char *default_path;
1830 ulint fsp_flags;
1831
1832 /* === some variables from mysqld === */
1833 memset((G_PTR) &mysql_tmpdir_list, 0, sizeof(mysql_tmpdir_list));
1834
1835 if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
1836 exit(EXIT_FAILURE);
1837
1838 /* dummy for initialize all_charsets[] */
1839 get_charset_name(0);
1840
1841 /* Check that the value of system variable innodb_page_size was
1842 set correctly. Its value was put into srv_page_size. If valid,
1843 return the associated srv_page_size_shift. */
1844 srv_page_size_shift = innodb_page_size_validate(innobase_page_size);
1845 if (!srv_page_size_shift) {
1846 msg("xtrabackup: Invalid page size=%llu.\n", innobase_page_size);
1847 goto error;
1848 }
1849 srv_page_size = innobase_page_size;
1850
1851 if (!xb_init_log_block_size()) {
1852 goto error;
1853 }
1854
1855 srv_fast_checksum = (ibool) innobase_fast_checksum;
1856
1857 /* Check that values don't overflow on 32-bit systems. */
1858 if (sizeof(ulint) == 4) {
1859 if (xtrabackup_use_memory > UINT_MAX32) {
1860 msg("xtrabackup: use-memory can't be over 4GB"
1861 " on 32-bit systems\n");
1862 }
1863
1864 if (innobase_buffer_pool_size > UINT_MAX32) {
1865 msg("xtrabackup: innobase_buffer_pool_size can't be "
1866 "over 4GB on 32-bit systems\n");
1867
1868 goto error;
1869 }
1870
1871 if (innobase_log_file_size > UINT_MAX32) {
1872 msg("xtrabackup: innobase_log_file_size can't be "
1873 "over 4GB on 32-bit systemsi\n");
1874
1875 goto error;
1876 }
1877 }
1878
1879 os_innodb_umask = (ulint)0664;
1880
1881 os_file_set_umask(my_umask);
1882
1883 /* Setup the memory alloc/free tracing mechanisms before calling
1884 any functions that could possibly allocate memory. */
1885 ut_new_boot();
1886
1887 /* First calculate the default path for innodb_data_home_dir etc.,
1888 in case the user has not given any value.
1889
1890 Note that when using the embedded server, the datadirectory is not
1891 necessarily the current directory of this program. */
1892
1893 /* It's better to use current lib, to keep paths short */
1894 current_dir[0] = FN_CURLIB;
1895 current_dir[1] = 0;
1896 default_path = current_dir;
1897
1898 ut_a(default_path);
1899
1900 fil_path_to_mysql_datadir = default_path;
1901 folder_mysql_datadir = fil_path_to_mysql_datadir;
1902
1903 /* Set InnoDB initialization parameters according to the values
1904 read from MySQL .cnf file */
1905
1906 if (xtrabackup_backup || xtrabackup_stats) {
1907 msg("xtrabackup: using the following InnoDB configuration:\n");
1908 } else {
1909 msg("xtrabackup: using the following InnoDB configuration "
1910 "for recovery:\n");
1911 }
1912
1913 /*--------------- Data files -------------------------*/
1914
1915 /* The default dir for data files is the datadir of MySQL */
1916
1917 srv_data_home = ((xtrabackup_backup || xtrabackup_stats) && innobase_data_home_dir
1918 ? innobase_data_home_dir : default_path);
1919 msg("xtrabackup: innodb_data_home_dir = %s\n", srv_data_home);
1920
1921 /*--------------- Shared tablespaces -------------------------*/
1922
1923 /* Set default InnoDB data file size to 10 MB and let it be
1924 auto-extending. Thus users can use InnoDB in >= 4.0 without having
1925 to specify any startup options. */
1926
1927 if (!innobase_data_file_path) {
1928 innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1929 }
1930 msg("xtrabackup: innodb_data_file_path = %s\n",
1931 innobase_data_file_path);
1932
1933 /* This is the first time univ_page_size is used.
1934 It was initialized to 16k pages before srv_page_size was set */
1935 univ_page_size.copy_from(
1936 page_size_t(srv_page_size, srv_page_size, false));
1937
1938 srv_sys_space.set_space_id(TRX_SYS_SPACE);
1939
1940 /* Create the filespace flags. */
1941 fsp_flags = fsp_flags_init(
1942 univ_page_size, false, false, false, false);
1943 srv_sys_space.set_flags(fsp_flags);
1944
1945 srv_sys_space.set_name(reserved_system_space_name);
1946 srv_sys_space.set_path(srv_data_home);
1947
1948 /* Supports raw devices */
1949 if (!srv_sys_space.parse_params(innobase_data_file_path,
1950 true, xtrabackup_prepare)) {
1951 goto error;
1952 }
1953
1954 /* Set default InnoDB temp data file size to 12 MB and let it be
1955 auto-extending. */
1956
1957 if (!innobase_temp_data_file_path) {
1958 innobase_temp_data_file_path = (char*) "ibtmp1:12M:autoextend";
1959 }
1960
1961 /* We set the temporary tablspace id later, after recovery.
1962 The temp tablespace doesn't support raw devices.
1963 Set the name and path. */
1964 srv_tmp_space.set_name(reserved_temporary_space_name);
1965 srv_tmp_space.set_path(srv_data_home);
1966
1967 /* Create the filespace flags with the temp flag set. */
1968 fsp_flags = fsp_flags_init(
1969 univ_page_size, false, false, false, true);
1970 srv_tmp_space.set_flags(fsp_flags);
1971
1972 if (!srv_tmp_space.parse_params(innobase_temp_data_file_path, false,
1973 xtrabackup_prepare)) {
1974 goto error;
1975 }
1976
1977 /* Perform all sanity check before we take action of deleting files*/
1978 if (srv_sys_space.intersection(&srv_tmp_space)) {
1979 msg("%s and %s file names seem to be the same.",
1980 srv_tmp_space.name(), srv_sys_space.name());
1981 goto error;
1982 }
1983
1984 /* -------------- Log files ---------------------------*/
1985
1986 /* The default dir for log files is the datadir of MySQL */
1987
1988 if (!((xtrabackup_backup || xtrabackup_stats) &&
1989 srv_log_group_home_dir)) {
1990 srv_log_group_home_dir = default_path;
1991 }
1992 if (xtrabackup_prepare && xtrabackup_incremental_dir) {
1993 srv_log_group_home_dir = xtrabackup_incremental_dir;
1994 }
1995 msg("xtrabackup: innodb_log_group_home_dir = %s\n",
1996 srv_log_group_home_dir);
1997
1998 os_normalize_path(srv_log_group_home_dir);
1999
2000 if (strchr(srv_log_group_home_dir, ';')) {
2001
2002 msg("syntax error in innodb_log_group_home_dir, ");
2003
2004 goto error;
2005 }
2006
2007 srv_adaptive_flushing = FALSE;
2008 srv_file_format = 1; /* Barracuda */
2009 srv_max_file_format_at_startup = UNIV_FORMAT_MIN; /* on */
2010 /* --------------------------------------------------*/
2011
2012 srv_file_flush_method_str = innobase_unix_file_flush_method;
2013
2014 srv_n_log_files = (ulint) innobase_log_files_in_group;
2015 srv_log_file_size = (ulint) innobase_log_file_size;
2016 msg("xtrabackup: innodb_log_files_in_group = %ld\n",
2017 srv_n_log_files);
2018 msg("xtrabackup: innodb_log_file_size = %lld\n",
2019 (long long int) srv_log_file_size);
2020
2021 srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2022
2023 /* We set srv_pool_size here in units of 1 kB. InnoDB internally
2024 changes the value so that it becomes the number of database pages. */
2025
2026 /* TDOD: add option */
2027 srv_buf_pool_chunk_unit = 134217728;
2028 srv_buf_pool_size = (ulint) xtrabackup_use_memory;
2029 srv_buf_pool_instances = 1;
2030
2031 srv_n_file_io_threads = (ulint) innobase_file_io_threads;
2032 srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2033 srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2034
2035 srv_force_recovery = (ulint) innobase_force_recovery;
2036
2037 srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
2038
2039 if (!innobase_use_checksums) {
2040
2041 srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_NONE;
2042 }
2043
2044 btr_search_enabled = (char) innobase_adaptive_hash_index;
2045
2046 os_use_large_pages = (ibool) innobase_use_large_pages;
2047 os_large_page_size = (ulint) innobase_large_page_size;
2048
2049 row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
2050
2051 srv_file_per_table = (my_bool) innobase_file_per_table;
2052
2053 srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
2054
2055 srv_max_n_open_files = (ulint) innobase_open_files;
2056 srv_innodb_status = (ibool) innobase_create_status_file;
2057
2058 srv_print_verbose_log = 1;
2059
2060 /* Store the default charset-collation number of this MySQL
2061 installation */
2062
2063 /* We cannot treat characterset here for now!! */
2064 data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2065
2066 //innobase_commit_concurrency_init_default();
2067
2068 /* Since we in this module access directly the fields of a trx
2069 struct, and due to different headers and flags it might happen that
2070 mutex_t has a different size in this module and in InnoDB
2071 modules, we check at run time that the size is the same in
2072 these compilation modules. */
2073
2074 /* On 5.5+ srv_use_native_aio is TRUE by default. It is later reset
2075 if it is not supported by the platform in
2076 innobase_start_or_create_for_mysql(). As we don't call it in xtrabackup,
2077 we have to duplicate checks from that function here. */
2078
2079 #ifdef __WIN__
2080 switch (os_get_os_version()) {
2081 case OS_WIN95:
2082 case OS_WIN31:
2083 case OS_WINNT:
2084 /* On Win 95, 98, ME, Win32 subsystem for Windows 3.1,
2085 and NT use simulated aio. In NT Windows provides async i/o,
2086 but when run in conjunction with InnoDB Hot Backup, it seemed
2087 to corrupt the data files. */
2088
2089 srv_use_native_aio = FALSE;
2090 break;
2091
2092 case OS_WIN2000:
2093 case OS_WINXP:
2094 /* On 2000 and XP, async IO is available. */
2095 srv_use_native_aio = TRUE;
2096 break;
2097
2098 default:
2099 /* Vista and later have both async IO and condition variables */
2100 srv_use_native_aio = TRUE;
2101 srv_use_native_conditions = TRUE;
2102 break;
2103 }
2104
2105 #elif defined(LINUX_NATIVE_AIO)
2106
2107 if (srv_use_native_aio) {
2108 ut_print_timestamp(stderr);
2109 msg(" InnoDB: Using Linux native AIO\n");
2110 }
2111 #else
2112 /* Currently native AIO is supported only on windows and linux
2113 and that also when the support is compiled in. In all other
2114 cases, we ignore the setting of innodb_use_native_aio. */
2115 srv_use_native_aio = FALSE;
2116
2117 #endif
2118
2119 /* Assign the default value to srv_undo_dir if it's not specified, as
2120 my_getopt does not support default values for string options. We also
2121 ignore the option and override innodb_undo_directory on --prepare,
2122 because separate undo tablespaces are copied to the root backup
2123 directory. */
2124
2125 if (!srv_undo_dir || !xtrabackup_backup) {
2126 my_free(srv_undo_dir);
2127 srv_undo_dir = my_strdup(PSI_NOT_INSTRUMENTED, ".", MYF(MY_FAE));
2128 }
2129
2130 innodb_log_checksum_func_update(srv_log_checksum_algorithm);
2131
2132 return(FALSE);
2133
2134 error:
2135 msg("xtrabackup: innodb_init_param(): Error occured.\n");
2136 return(TRUE);
2137 }
2138
2139 static my_bool
innodb_init(void)2140 innodb_init(void)
2141 {
2142 int err;
2143
2144 os_event_global_init();
2145 err = innobase_start_or_create_for_mysql();
2146
2147 if (err != DB_SUCCESS) {
2148 free(internal_innobase_data_file_path);
2149 internal_innobase_data_file_path = NULL;
2150 goto error;
2151 }
2152
2153 /* They may not be needed for now */
2154 // (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
2155 // (hash_get_key) innobase_get_key, 0, 0);
2156 // pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2157 // pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2158 // pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2159 // pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2160 // pthread_cond_init(&commit_cond, NULL);
2161
2162 innodb_inited= 1;
2163
2164 return(FALSE);
2165
2166 error:
2167 msg("xtrabackup: innodb_init(): Error occured.\n");
2168 return(TRUE);
2169 }
2170
2171 static my_bool
innodb_end(void)2172 innodb_end(void)
2173 {
2174 srv_fast_shutdown = (ulint) innobase_fast_shutdown;
2175 innodb_inited = 0;
2176
2177 msg("xtrabackup: starting shutdown with innodb_fast_shutdown = %lu\n",
2178 srv_fast_shutdown);
2179
2180 if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
2181 goto error;
2182 }
2183 free(internal_innobase_data_file_path);
2184 internal_innobase_data_file_path = NULL;
2185
2186 /* They may not be needed for now */
2187 // hash_free(&innobase_open_tables);
2188 // pthread_mutex_destroy(&innobase_share_mutex);
2189 // pthread_mutex_destroy(&prepare_commit_mutex);
2190 // pthread_mutex_destroy(&commit_threads_m);
2191 // pthread_mutex_destroy(&commit_cond_m);
2192 // pthread_cond_destroy(&commit_cond);
2193
2194 return(FALSE);
2195
2196 error:
2197 msg("xtrabackup: innodb_end(): Error occured.\n");
2198 return(TRUE);
2199 }
2200
2201 /* ================= common ================= */
2202
2203 /***********************************************************************
2204 Read backup meta info.
2205 @return TRUE on success, FALSE on failure. */
2206 static
2207 my_bool
xtrabackup_read_metadata(char * filename)2208 xtrabackup_read_metadata(char *filename)
2209 {
2210 FILE *fp;
2211 my_bool r = TRUE;
2212 int t;
2213
2214 fp = fopen(filename,"r");
2215 if(!fp) {
2216 msg("xtrabackup: Error: cannot open %s\n", filename);
2217 return(FALSE);
2218 }
2219
2220 if (fscanf(fp, "backup_type = %29s\n", metadata_type)
2221 != 1) {
2222 r = FALSE;
2223 goto end;
2224 }
2225 if (fscanf(fp, "from_lsn = " LSN_PF "\n", &metadata_from_lsn)
2226 != 1) {
2227 r = FALSE;
2228 goto end;
2229 }
2230 if (fscanf(fp, "to_lsn = " LSN_PF "\n", &metadata_to_lsn)
2231 != 1) {
2232 r = FALSE;
2233 goto end;
2234 }
2235 if (fscanf(fp, "last_lsn = " LSN_PF "\n", &metadata_last_lsn)
2236 != 1) {
2237 metadata_last_lsn = 0;
2238 }
2239 /* Optional fields */
2240
2241 if (fscanf(fp, "compact = %d\n", &t) == 1) {
2242 xtrabackup_compact = (t == 1);
2243 } else {
2244 xtrabackup_compact = 0;
2245 }
2246
2247 if (fscanf(fp, "recover_binlog_info = %d\n", &t) == 1) {
2248 recover_binlog_info = (t == 1);
2249 }
2250
2251 if (fscanf(fp, "flushed_lsn = " LSN_PF "\n",
2252 &backup_redo_log_flushed_lsn) != 1) {
2253 backup_redo_log_flushed_lsn = 0;
2254 }
2255 end:
2256 fclose(fp);
2257
2258 return(r);
2259 }
2260
2261 /***********************************************************************
2262 Print backup meta info to a specified buffer. */
2263 static
2264 void
xtrabackup_print_metadata(char * buf,size_t buf_len)2265 xtrabackup_print_metadata(char *buf, size_t buf_len)
2266 {
2267 snprintf(buf, buf_len,
2268 "backup_type = %s\n"
2269 "from_lsn = " LSN_PF "\n"
2270 "to_lsn = " LSN_PF "\n"
2271 "last_lsn = " LSN_PF "\n"
2272 "compact = %d\n"
2273 "recover_binlog_info = %d\n"
2274 "flushed_lsn = " LSN_PF "\n",
2275 metadata_type,
2276 metadata_from_lsn,
2277 metadata_to_lsn,
2278 metadata_last_lsn,
2279 MY_TEST(xtrabackup_compact == TRUE),
2280 MY_TEST((xtrabackup_backup &&
2281 (opt_binlog_info == BINLOG_INFO_LOCKLESS)) ||
2282 (xtrabackup_prepare && recover_binlog_info)),
2283 backup_redo_log_flushed_lsn);
2284 }
2285
2286 /***********************************************************************
2287 Stream backup meta info to a specified datasink.
2288 @return TRUE on success, FALSE on failure. */
2289 static
2290 my_bool
xtrabackup_stream_metadata(ds_ctxt_t * ds_ctxt)2291 xtrabackup_stream_metadata(ds_ctxt_t *ds_ctxt)
2292 {
2293 char buf[1024];
2294 size_t len;
2295 ds_file_t *stream;
2296 MY_STAT mystat;
2297 my_bool rc = TRUE;
2298
2299 xtrabackup_print_metadata(buf, sizeof(buf));
2300
2301 len = strlen(buf);
2302
2303 mystat.st_size = len;
2304 mystat.st_mtime = my_time(0);
2305
2306 stream = ds_open(ds_ctxt, XTRABACKUP_METADATA_FILENAME, &mystat);
2307 if (stream == NULL) {
2308 msg("xtrabackup: Error: cannot open output stream "
2309 "for %s\n", XTRABACKUP_METADATA_FILENAME);
2310 return(FALSE);
2311 }
2312
2313 if (ds_write(stream, buf, len)) {
2314 rc = FALSE;
2315 }
2316
2317 if (ds_close(stream)) {
2318 rc = FALSE;
2319 }
2320
2321 return(rc);
2322 }
2323
2324
2325 static
write_to_file(const char * filepath,const char * data)2326 my_bool write_to_file(const char *filepath, const char *data)
2327 {
2328 size_t len = strlen(data);
2329 FILE *fp = fopen(filepath, "w");
2330 if(!fp) {
2331 msg("xtrabackup: Error: cannot open %s\n", filepath);
2332 return(FALSE);
2333 }
2334 if (fwrite(data, len, 1, fp) < 1) {
2335 fclose(fp);
2336 return(FALSE);
2337 }
2338
2339 fclose(fp);
2340 return TRUE;
2341 }
2342
2343
2344 /***********************************************************************
2345 Write backup meta info to a specified file.
2346 @return TRUE on success, FALSE on failure. */
2347 static
2348 my_bool
xtrabackup_write_metadata(const char * filepath)2349 xtrabackup_write_metadata(const char *filepath)
2350 {
2351 char buf[1024];
2352
2353 xtrabackup_print_metadata(buf, sizeof(buf));
2354 return write_to_file(filepath, buf);
2355 }
2356
2357 /***********************************************************************
2358 Read meta info for an incremental delta.
2359 @return TRUE on success, FALSE on failure. */
2360 static my_bool
xb_read_delta_metadata(const char * filepath,xb_delta_info_t * info)2361 xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info)
2362 {
2363 FILE* fp;
2364 char key[51];
2365 char value[51];
2366 my_bool r = TRUE;
2367
2368 /* set defaults */
2369 info->page_size = ULINT_UNDEFINED;
2370 info->zip_size = ULINT_UNDEFINED;
2371 info->space_id = ULINT_UNDEFINED;
2372 info->space_flags = 0;
2373
2374 fp = fopen(filepath, "r");
2375 if (!fp) {
2376 /* Meta files for incremental deltas are optional */
2377 return(TRUE);
2378 }
2379
2380 while (!feof(fp)) {
2381 if (fscanf(fp, "%50s = %50s\n", key, value) == 2) {
2382 if (strcmp(key, "page_size") == 0) {
2383 info->page_size = strtoul(value, NULL, 10);
2384 } else if (strcmp(key, "zip_size") == 0) {
2385 info->zip_size = strtoul(value, NULL, 10);
2386 } else if (strcmp(key, "space_id") == 0) {
2387 info->space_id = strtoul(value, NULL, 10);
2388 } else if (strcmp(key, "space_flags") == 0) {
2389 info->space_flags = strtoul(value, NULL, 10);
2390 }
2391 }
2392 }
2393
2394 fclose(fp);
2395
2396 if (info->page_size == ULINT_UNDEFINED) {
2397 msg("xtrabackup: page_size is required in %s\n", filepath);
2398 r = FALSE;
2399 }
2400 if (info->space_id == ULINT_UNDEFINED) {
2401 msg("xtrabackup: Warning: This backup was taken with XtraBackup 2.0.1 "
2402 "or earlier, some DDL operations between full and incremental "
2403 "backups may be handled incorrectly\n");
2404 }
2405
2406 return(r);
2407 }
2408
2409 /***********************************************************************
2410 Write meta info for an incremental delta.
2411 @return TRUE on success, FALSE on failure. */
2412 my_bool
xb_write_delta_metadata(const char * filename,const xb_delta_info_t * info)2413 xb_write_delta_metadata(const char *filename, const xb_delta_info_t *info)
2414 {
2415 ds_file_t *f;
2416 char buf[200];
2417 my_bool ret;
2418 size_t len;
2419 MY_STAT mystat;
2420
2421 snprintf(buf, sizeof(buf),
2422 "page_size = %lu\n"
2423 "zip_size = %lu\n"
2424 "space_id = %lu\n"
2425 "space_flags = %lu\n",
2426 info->page_size, info->zip_size, info->space_id,
2427 info->space_flags);
2428 len = strlen(buf);
2429
2430 mystat.st_size = len;
2431 mystat.st_mtime = my_time(0);
2432
2433 f = ds_open(ds_meta, filename, &mystat);
2434 if (f == NULL) {
2435 msg("xtrabackup: Error: cannot open output stream for %s\n",
2436 filename);
2437 return(FALSE);
2438 }
2439
2440 ret = (ds_write(f, buf, len) == 0);
2441
2442 if (ds_close(f)) {
2443 ret = FALSE;
2444 }
2445
2446 return(ret);
2447 }
2448
2449 static my_bool
xtrabackup_write_info(const char * filepath)2450 xtrabackup_write_info(const char *filepath)
2451 {
2452 char *xtrabackup_info_data = get_xtrabackup_info(mysql_connection);
2453 if (!xtrabackup_info_data) {
2454 return FALSE;
2455 }
2456
2457 my_bool result = write_to_file(filepath, xtrabackup_info_data);
2458
2459 free(xtrabackup_info_data);
2460 return result;
2461 }
2462
2463 /* ================= backup ================= */
2464 void
xtrabackup_io_throttling(void)2465 xtrabackup_io_throttling(void)
2466 {
2467 if (xtrabackup_throttle && (--io_ticket) < 0) {
2468 os_event_reset(wait_throttle);
2469 os_event_wait(wait_throttle);
2470 }
2471 }
2472
2473 static
regex_list_check_match(const regex_list_t & list,const char * name)2474 my_bool regex_list_check_match(
2475 const regex_list_t& list,
2476 const char* name)
2477 {
2478 xb_regmatch_t tables_regmatch[1];
2479 for (regex_list_t::const_iterator i = list.begin(), end = list.end();
2480 i != end; ++i) {
2481 const xb_regex_t& regex = *i;
2482 int regres = xb_regexec(®ex, name, 1, tables_regmatch, 0);
2483
2484 if (regres != REG_NOMATCH) {
2485 return(TRUE);
2486 }
2487 }
2488 return(FALSE);
2489 }
2490
2491 static
2492 my_bool
find_filter_in_hashtable(const char * name,hash_table_t * table,xb_filter_entry_t ** result)2493 find_filter_in_hashtable(
2494 const char* name,
2495 hash_table_t* table,
2496 xb_filter_entry_t** result
2497 )
2498 {
2499 xb_filter_entry_t* found = NULL;
2500 HASH_SEARCH(name_hash, table, ut_fold_string(name),
2501 xb_filter_entry_t*,
2502 found, (void) 0,
2503 !strcmp(found->name, name));
2504
2505 if (found && result) {
2506 *result = found;
2507 }
2508 return (found != NULL);
2509 }
2510
2511 /************************************************************************
2512 Checks if a given table name matches any of specifications given in
2513 regex_list or tables_hash.
2514
2515 @return TRUE on match or both regex_list and tables_hash are empty.*/
2516 static my_bool
check_if_table_matches_filters(const char * name,const regex_list_t & regex_list,hash_table_t * tables_hash)2517 check_if_table_matches_filters(const char *name,
2518 const regex_list_t& regex_list,
2519 hash_table_t* tables_hash)
2520 {
2521 if (regex_list.empty() && !tables_hash) {
2522 return(FALSE);
2523 }
2524
2525 if (regex_list_check_match(regex_list, name)) {
2526 return(TRUE);
2527 }
2528
2529 if (tables_hash && find_filter_in_hashtable(name, tables_hash, NULL)) {
2530 return(TRUE);
2531 }
2532
2533 return FALSE;
2534 }
2535
2536 enum skip_database_check_result {
2537 DATABASE_SKIP,
2538 DATABASE_SKIP_SOME_TABLES,
2539 DATABASE_DONT_SKIP,
2540 DATABASE_DONT_SKIP_UNLESS_EXPLICITLY_EXCLUDED,
2541 };
2542
2543 /************************************************************************
2544 Checks if a database specified by name should be skipped from backup based on
2545 the --databases, --databases_file or --databases_exclude options.
2546
2547 @return TRUE if entire database should be skipped,
2548 FALSE otherwise.
2549 */
2550 static
2551 skip_database_check_result
check_if_skip_database(const char * name)2552 check_if_skip_database(
2553 const char* name /*!< in: path to the database */
2554 )
2555 {
2556 /* There are some filters for databases, check them */
2557 xb_filter_entry_t* database = NULL;
2558
2559 if (databases_exclude_hash &&
2560 find_filter_in_hashtable(name, databases_exclude_hash,
2561 &database) &&
2562 !database->has_tables) {
2563 /* Database is found and there are no tables specified,
2564 skip entire db. */
2565 return DATABASE_SKIP;
2566 }
2567
2568 if (databases_include_hash) {
2569 if (!find_filter_in_hashtable(name, databases_include_hash,
2570 &database)) {
2571 /* Database isn't found, skip the database */
2572 return DATABASE_SKIP;
2573 } else if (database->has_tables) {
2574 return DATABASE_SKIP_SOME_TABLES;
2575 } else {
2576 return DATABASE_DONT_SKIP_UNLESS_EXPLICITLY_EXCLUDED;
2577 }
2578 }
2579
2580 return DATABASE_DONT_SKIP;
2581 }
2582
2583 /************************************************************************
2584 Checks if a database specified by path should be skipped from backup based on
2585 the --databases, --databases_file or --databases_exclude options.
2586
2587 @return TRUE if the table should be skipped. */
2588 my_bool
check_if_skip_database_by_path(const char * path)2589 check_if_skip_database_by_path(
2590 const char* path /*!< in: path to the db directory. */
2591 )
2592 {
2593 if (databases_include_hash == NULL &&
2594 databases_exclude_hash == NULL) {
2595 return(FALSE);
2596 }
2597
2598 const char* db_name = strrchr(path, OS_PATH_SEPARATOR);
2599 if (db_name == NULL) {
2600 db_name = path;
2601 } else {
2602 ++db_name;
2603 }
2604
2605 return check_if_skip_database(db_name) == DATABASE_SKIP;
2606 }
2607
2608 /************************************************************************
2609 Checks if a table specified as a name in the form "database/name" (InnoDB 5.6)
2610 or "./database/name.ibd" (InnoDB 5.5-) should be skipped from backup based on
2611 the --tables or --tables-file options.
2612
2613 @return TRUE if the table should be skipped. */
2614 bool
check_if_skip_table(const char * name)2615 check_if_skip_table(
2616 /******************/
2617 const char* name) /*!< in: path to the table */
2618 {
2619 char buf[FN_REFLEN];
2620 const char *dbname, *tbname;
2621 const char *ptr;
2622 char *eptr;
2623
2624 if (regex_exclude_list.empty() &&
2625 regex_include_list.empty() &&
2626 tables_include_hash == NULL &&
2627 tables_exclude_hash == NULL &&
2628 databases_include_hash == NULL &&
2629 databases_exclude_hash == NULL) {
2630 return(false);
2631 }
2632
2633 dbname = NULL;
2634 tbname = name;
2635 while ((ptr = strchr(tbname, OS_PATH_SEPARATOR)) != NULL) {
2636 dbname = tbname;
2637 tbname = ptr + 1;
2638 }
2639
2640 if (dbname == NULL) {
2641 return(false);
2642 }
2643
2644 strncpy(buf, dbname, FN_REFLEN);
2645 buf[tbname - 1 - dbname] = 0;
2646
2647 const skip_database_check_result skip_database =
2648 check_if_skip_database(buf);
2649 if (skip_database == DATABASE_SKIP) {
2650 return(true);
2651 }
2652
2653 buf[FN_REFLEN - 1] = '\0';
2654 buf[tbname - 1 - dbname] = '.';
2655
2656 /* Check if there's a suffix in the table name. If so, truncate it. We
2657 rely on the fact that a dot cannot be a part of a table name (it is
2658 encoded by the server with the @NNNN syntax). */
2659 if ((eptr = strchr(&buf[tbname - dbname], '.')) != NULL) {
2660
2661 *eptr = '\0';
2662 }
2663
2664 /* For partitioned tables first try to match against the regexp
2665 without truncating the #P#... suffix so we can backup individual
2666 partitions with regexps like '^test[.]t#P#p5' */
2667 if (check_if_table_matches_filters(buf, regex_exclude_list,
2668 tables_exclude_hash)) {
2669 return(true);
2670 }
2671 if (check_if_table_matches_filters(buf, regex_include_list,
2672 tables_include_hash)) {
2673 return(false);
2674 }
2675 if ((eptr = strstr(buf, "#P#")) != NULL) {
2676 *eptr = 0;
2677
2678 if (check_if_table_matches_filters(buf, regex_exclude_list,
2679 tables_exclude_hash)) {
2680 return(true);
2681 }
2682 if (check_if_table_matches_filters(buf, regex_include_list,
2683 tables_include_hash)) {
2684 return(false);
2685 }
2686 }
2687
2688 if (skip_database == DATABASE_DONT_SKIP_UNLESS_EXPLICITLY_EXCLUDED) {
2689 /* Database is in include-list, and qualified name wasn't
2690 found in any of exclusion filters.*/
2691 return(false);
2692 }
2693
2694 if (skip_database == DATABASE_SKIP_SOME_TABLES ||
2695 !regex_include_list.empty() ||
2696 tables_include_hash) {
2697
2698 /* Include lists are present, but qualified name
2699 failed to match any.*/
2700 return(true);
2701 }
2702
2703 return(false);
2704 }
2705
2706 /***********************************************************************
2707 Reads the space flags from a given data file and returns the
2708 page size. */
2709 const page_size_t
xb_get_zip_size(pfs_os_file_t file,bool * success)2710 xb_get_zip_size(pfs_os_file_t file, bool *success)
2711 {
2712 byte *buf;
2713 byte *page;
2714 page_size_t page_size(0, 0, false);
2715 ibool ret;
2716 ulint space;
2717 IORequest read_request(IORequest::READ);
2718
2719 buf = static_cast<byte *>(ut_malloc_nokey(2 * UNIV_PAGE_SIZE_MAX));
2720 page = static_cast<byte *>(ut_align(buf, UNIV_PAGE_SIZE_MAX));
2721
2722 ret = os_file_read(read_request, file, page, 0, UNIV_PAGE_SIZE_MIN);
2723 if (!ret) {
2724 *success = false;
2725 goto end;
2726 }
2727
2728 space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
2729 if (space == 0) {
2730 page_size.copy_from(univ_page_size);
2731 } else {
2732 page_size.copy_from(page_size_t(fsp_header_get_flags(page)));
2733 }
2734 *success = true;
2735 end:
2736 ut_free(buf);
2737
2738 return(page_size);
2739 }
2740
2741 const char*
xb_get_copy_action(const char * dflt)2742 xb_get_copy_action(const char *dflt)
2743 {
2744 const char *action;
2745
2746 if (xtrabackup_stream) {
2747 if (xtrabackup_compress) {
2748 if (xtrabackup_encrypt) {
2749 action = "Compressing, encrypting and streaming";
2750 } else {
2751 action = "Compressing and streaming";
2752 }
2753 } else if (xtrabackup_encrypt) {
2754 action = "Encrypting and streaming";
2755 } else {
2756 action = "Streaming";
2757 }
2758 } else {
2759 if (xtrabackup_compress) {
2760 if (xtrabackup_encrypt) {
2761 action = "Compressing and encrypting";
2762 } else {
2763 action = "Compressing";
2764 }
2765 } else if (xtrabackup_encrypt) {
2766 action = "Encrypting";
2767 } else {
2768 action = dflt;
2769 }
2770 }
2771
2772 return(action);
2773 }
2774
2775 /* TODO: We may tune the behavior (e.g. by fil_aio)*/
2776
2777 static
2778 my_bool
xtrabackup_copy_datafile(fil_node_t * node,uint thread_n)2779 xtrabackup_copy_datafile(fil_node_t* node, uint thread_n)
2780 {
2781 char dst_name[FN_REFLEN];
2782 ds_file_t *dstfile = NULL;
2783 xb_fil_cur_t cursor;
2784 xb_fil_cur_result_t res;
2785 xb_write_filt_t *write_filter = NULL;
2786 xb_write_filt_ctxt_t write_filt_ctxt;
2787 const char *action;
2788 xb_read_filt_t *read_filter;
2789 ibool is_system;
2790 my_bool rc = FALSE;
2791
2792 /* Get the name and the path for the tablespace. node->name always
2793 contains the path (which may be absolute for remote tablespaces in
2794 5.6+). space->name contains the tablespace name in the form
2795 "./database/table.ibd" (in 5.5-) or "database/table" (in 5.6+). For a
2796 multi-node shared tablespace, space->name contains the name of the first
2797 node, but that's irrelevant, since we only need node_name to match them
2798 against filters, and the shared tablespace is always copied regardless
2799 of the filters value. */
2800
2801 const char* const node_name = node->space->name;
2802 const char* const node_path = node->name;
2803
2804 is_system = !fil_is_user_tablespace_id(node->space->id);
2805
2806 if (!is_system && check_if_skip_table(node_name)) {
2807 msg("[%02u] Skipping %s.\n", thread_n, node_name);
2808 return(FALSE);
2809 }
2810
2811 if (!changed_page_bitmap) {
2812 read_filter = &rf_pass_through;
2813 }
2814 else {
2815 read_filter = &rf_bitmap;
2816 }
2817 res = xb_fil_cur_open(&cursor, read_filter, node, thread_n);
2818 if (res == XB_FIL_CUR_SKIP) {
2819 goto skip;
2820 } else if (res == XB_FIL_CUR_ERROR) {
2821 goto error;
2822 }
2823
2824 if (!is_system) {
2825 snprintf(dst_name, sizeof(dst_name), "%s.ibd", node_name);
2826 } else {
2827 strncpy(dst_name, cursor.rel_path, sizeof(dst_name));
2828 }
2829
2830 /* Setup the page write filter */
2831 if (xtrabackup_incremental) {
2832 write_filter = &wf_incremental;
2833 } else if (xtrabackup_compact) {
2834 write_filter = &wf_compact;
2835 } else {
2836 write_filter = &wf_write_through;
2837 }
2838
2839 memset(&write_filt_ctxt, 0, sizeof(xb_write_filt_ctxt_t));
2840 ut_a(write_filter->process != NULL);
2841
2842 if (write_filter->init != NULL &&
2843 !write_filter->init(&write_filt_ctxt, dst_name, &cursor)) {
2844 msg("[%02u] xtrabackup: error: "
2845 "failed to initialize page write filter.\n", thread_n);
2846 goto error;
2847 }
2848
2849 dstfile = ds_open(ds_data, dst_name, &cursor.statinfo);
2850 if (dstfile == NULL) {
2851 msg("[%02u] xtrabackup: error: "
2852 "cannot open the destination stream for %s\n",
2853 thread_n, dst_name);
2854 goto error;
2855 }
2856
2857 action = xb_get_copy_action();
2858
2859 if (xtrabackup_stream) {
2860 msg_ts("[%02u] %s %s\n", thread_n, action, node_path);
2861 } else {
2862 msg_ts("[%02u] %s %s to %s\n", thread_n, action,
2863 node_path, dstfile->path);
2864 }
2865
2866 /* The main copy loop */
2867 while ((res = xb_fil_cur_read(&cursor)) == XB_FIL_CUR_SUCCESS) {
2868 if (!write_filter->process(&write_filt_ctxt, dstfile)) {
2869 goto error;
2870 }
2871 }
2872
2873 if (res == XB_FIL_CUR_ERROR) {
2874 goto error;
2875 }
2876
2877 if (write_filter->finalize
2878 && !write_filter->finalize(&write_filt_ctxt, dstfile)) {
2879 goto error;
2880 }
2881
2882 /* close */
2883 msg_ts("[%02u] ...done\n", thread_n);
2884 xb_fil_cur_close(&cursor);
2885 if (ds_close(dstfile)) {
2886 rc = TRUE;
2887 }
2888 if (write_filter && write_filter->deinit) {
2889 write_filter->deinit(&write_filt_ctxt);
2890 }
2891 return(rc);
2892
2893 error:
2894 xb_fil_cur_close(&cursor);
2895 if (dstfile != NULL) {
2896 ds_close(dstfile);
2897 }
2898 if (write_filter && write_filter->deinit) {
2899 write_filter->deinit(&write_filt_ctxt);
2900 }
2901 msg("[%02u] xtrabackup: Error: "
2902 "xtrabackup_copy_datafile() failed.\n", thread_n);
2903 return(TRUE); /*ERROR*/
2904
2905 skip:
2906
2907 if (dstfile != NULL) {
2908 ds_close(dstfile);
2909 }
2910 if (write_filter && write_filter->deinit) {
2911 write_filter->deinit(&write_filt_ctxt);
2912 }
2913 msg("[%02u] xtrabackup: Warning: We assume the "
2914 "table was dropped during xtrabackup execution "
2915 "and ignore the file.\n", thread_n);
2916 msg("[%02u] xtrabackup: Warning: skipping tablespace %s.\n",
2917 thread_n, node_name);
2918 return(FALSE);
2919 }
2920
2921 static
2922 void
xtrabackup_choose_lsn_offset(lsn_t start_lsn)2923 xtrabackup_choose_lsn_offset(lsn_t start_lsn)
2924 {
2925 ulint no, expected_no;
2926 ulint blocks_in_group;
2927 lsn_t end_lsn;
2928 log_group_t *group;
2929
2930 start_lsn = ut_uint64_align_down(start_lsn, OS_FILE_LOG_BLOCK_SIZE);
2931 end_lsn = start_lsn + RECV_SCAN_SIZE;
2932
2933 group = UT_LIST_GET_FIRST(log_sys->log_groups);
2934
2935 if (mysql_server_version < 50500) {
2936 /* server doesn't support log files larger than 4G */
2937 return;
2938 }
2939
2940 if (server_flavor == FLAVOR_PERCONA_SERVER &&
2941 (mysql_server_version > 50500 && mysql_server_version < 50600)) {
2942 /* it is Percona Server 5.5 */
2943 group->lsn_offset = group->lsn_offset_ps55;
2944 return;
2945 }
2946
2947 if (group->lsn_offset_ps55 == group->lsn_offset ||
2948 group->lsn_offset_ps55 == (lsn_t) -1) {
2949 /* we have only one option */
2950 return;
2951 }
2952
2953 no = (ulint) -1;
2954
2955 blocks_in_group = log_block_convert_lsn_to_no(
2956 log_group_get_capacity(group)) - 1;
2957
2958 lsn_t offsets[2] = {group->lsn_offset,
2959 group->lsn_offset_ps55};
2960
2961 expected_no = log_block_convert_lsn_to_no(start_lsn);
2962
2963 for (int i = 0; i < 2; i++) {
2964 group->lsn_offset = offsets[i];
2965
2966 /* read log block number */
2967 if (group->lsn_offset < group->file_size * group->n_files &&
2968 (log_group_calc_lsn_offset(start_lsn, group) %
2969 UNIV_PAGE_SIZE) % OS_MIN_LOG_BLOCK_SIZE == 0) {
2970 log_group_read_log_seg(log_sys->buf, group,
2971 start_lsn, end_lsn);
2972 no = log_block_get_hdr_no(log_sys->buf);
2973 }
2974
2975 if ((no <= expected_no &&
2976 ((expected_no - no) % blocks_in_group) == 0) ||
2977 ((expected_no | 0x40000000UL) - no) % blocks_in_group == 0) {
2978 /* offset looks ok */
2979 return;
2980 }
2981 }
2982 }
2983
2984 /*******************************************************//**
2985 Scans log from a buffer and writes new log data to the outpud datasinc.
2986 @return true if success */
2987 static
2988 bool
xtrabackup_scan_log_recs(log_group_t * group,bool is_last,lsn_t start_lsn,lsn_t * contiguous_lsn,lsn_t * group_scanned_lsn,lsn_t checkpoint_lsn,bool * finished)2989 xtrabackup_scan_log_recs(
2990 /*===============*/
2991 log_group_t* group, /*!< in: log group */
2992 bool is_last, /*!< in: whether it is last segment
2993 to copy */
2994 lsn_t start_lsn, /*!< in: buffer start lsn */
2995 lsn_t* contiguous_lsn, /*!< in/out: it is known that all log
2996 groups contain contiguous log data up
2997 to this lsn */
2998 lsn_t* group_scanned_lsn,/*!< out: scanning succeeded up to
2999 this lsn */
3000 lsn_t checkpoint_lsn, /*!< in: latest checkpoint LSN */
3001 bool* finished) /*!< out: false if is not able to scan
3002 any more in this log group */
3003 {
3004 lsn_t scanned_lsn;
3005 ulint data_len;
3006 ulint write_size;
3007 const byte* log_block;
3008 bool more_data = false;
3009
3010 ulint scanned_checkpoint_no = 0;
3011
3012 *finished = false;
3013 scanned_lsn = start_lsn;
3014 log_block = log_sys->buf;
3015
3016 while (log_block < log_sys->buf + RECV_SCAN_SIZE && !*finished) {
3017 ulint no = log_block_get_hdr_no(log_block);
3018 ulint scanned_no = log_block_convert_lsn_to_no(scanned_lsn);
3019 ibool checksum_is_ok = log_block_checksum_is_ok(log_block);
3020
3021 if (no != scanned_no && checksum_is_ok) {
3022 ulint blocks_in_group;
3023
3024 blocks_in_group = log_block_convert_lsn_to_no(
3025 log_group_get_capacity(group)) - 1;
3026
3027 if ((no < scanned_no &&
3028 ((scanned_no - no) % blocks_in_group) == 0) ||
3029 no == 0 ||
3030 /* Log block numbers wrap around at 0x3FFFFFFF */
3031 ((scanned_no | 0x40000000UL) - no) %
3032 blocks_in_group == 0) {
3033
3034 /* old log block, do nothing */
3035 *finished = true;
3036 break;
3037 }
3038
3039 msg("xtrabackup: error:"
3040 " log block numbers mismatch:\n"
3041 "xtrabackup: error: expected log block no. %lu,"
3042 " but got no. %lu from the log file.\n",
3043 (ulong) scanned_no, (ulong) no);
3044
3045 if ((no - scanned_no) % blocks_in_group == 0) {
3046 msg("xtrabackup: error:"
3047 " it looks like InnoDB log has wrapped"
3048 " around before xtrabackup could"
3049 " process all records due to either"
3050 " log copying being too slow, or "
3051 " log files being too small.\n");
3052 }
3053
3054 return(false);
3055 } else if (!checksum_is_ok) {
3056 /* Garbage or an incompletely written log block */
3057
3058 msg("xtrabackup: warning: Log block checksum mismatch"
3059 " (block no %lu at lsn " LSN_PF "): \n"
3060 "expected %lu, calculated checksum %lu\n",
3061 (ulong) no,
3062 scanned_lsn,
3063 (ulong) log_block_get_checksum(log_block),
3064 (ulong) log_block_calc_checksum(log_block));
3065 msg("xtrabackup: warning: this is possible when the "
3066 "log block has not been fully written by the "
3067 "server, will retry later.\n");
3068 *finished = true;
3069 break;
3070 }
3071
3072 if (log_block_get_flush_bit(log_block)) {
3073 /* This block was a start of a log flush operation:
3074 we know that the previous flush operation must have
3075 been completed for all log groups before this block
3076 can have been flushed to any of the groups. Therefore,
3077 we know that log data is contiguous up to scanned_lsn
3078 in all non-corrupt log groups. */
3079
3080 if (scanned_lsn > *contiguous_lsn) {
3081
3082 *contiguous_lsn = scanned_lsn;
3083 }
3084 }
3085
3086 data_len = log_block_get_data_len(log_block);
3087
3088 if (
3089 (scanned_checkpoint_no > 0)
3090 && (log_block_get_checkpoint_no(log_block)
3091 < scanned_checkpoint_no)
3092 && (scanned_checkpoint_no
3093 - log_block_get_checkpoint_no(log_block)
3094 > 0x80000000UL)) {
3095
3096 /* Garbage from a log buffer flush which was made
3097 before the most recent database recovery */
3098
3099 *finished = true;
3100 break;
3101 }
3102
3103 if (!recv_sys->parse_start_lsn
3104 && (log_block_get_first_rec_group(log_block) > 0)) {
3105
3106 /* We found a point from which to start the parsing
3107 of log records */
3108
3109 recv_sys->parse_start_lsn = scanned_lsn
3110 + log_block_get_first_rec_group(log_block);
3111 recv_sys->scanned_lsn = recv_sys->parse_start_lsn;
3112 recv_sys->recovered_lsn = recv_sys->parse_start_lsn;
3113 }
3114
3115 scanned_lsn = scanned_lsn + data_len;
3116 scanned_checkpoint_no = log_block_get_checkpoint_no(log_block);
3117
3118 if (scanned_lsn > recv_sys->scanned_lsn) {
3119
3120 /* We were able to find more log data: add it to the
3121 parsing buffer if parse_start_lsn is already
3122 non-zero */
3123
3124 if (recv_sys->len + 4 * OS_FILE_LOG_BLOCK_SIZE
3125 >= RECV_PARSING_BUF_SIZE) {
3126 ib::error() << "Log parsing buffer overflow."
3127 " Recovery may have failed!";
3128
3129 recv_sys->found_corrupt_log = true;
3130
3131 } else if (!recv_sys->found_corrupt_log) {
3132 more_data = recv_sys_add_to_parsing_buf(
3133 log_block, scanned_lsn);
3134 }
3135
3136 recv_sys->scanned_lsn = scanned_lsn;
3137 recv_sys->scanned_checkpoint_no
3138 = log_block_get_checkpoint_no(log_block);
3139 }
3140
3141 if (data_len < OS_FILE_LOG_BLOCK_SIZE) {
3142 /* Log data for this group ends here */
3143
3144 *finished = true;
3145 } else {
3146 log_block += OS_FILE_LOG_BLOCK_SIZE;
3147 }
3148 }
3149
3150 *group_scanned_lsn = scanned_lsn;
3151
3152 /* ===== write log to 'xtrabackup_logfile' ====== */
3153 if (!*finished) {
3154 write_size = RECV_SCAN_SIZE;
3155 } else {
3156 write_size = ut_uint64_align_up(scanned_lsn,
3157 OS_FILE_LOG_BLOCK_SIZE) - start_lsn;
3158 if (!is_last && scanned_lsn % OS_FILE_LOG_BLOCK_SIZE) {
3159 write_size -= OS_FILE_LOG_BLOCK_SIZE;
3160 }
3161 }
3162
3163 if (ds_write(dst_log_file, log_sys->buf, write_size)) {
3164 msg("xtrabackup: Error: "
3165 "write to logfile failed\n");
3166 return(false);
3167 }
3168
3169 if (more_data && !recv_sys->found_corrupt_log) {
3170 /* Try to parse more log records */
3171
3172 if (recv_parse_log_recs(checkpoint_lsn, /*!< in: latest checkpoint LSN */
3173 STORE_NO)) {
3174 ut_ad(recv_sys->found_corrupt_log
3175 || recv_sys->found_corrupt_fs
3176 || recv_sys->mlog_checkpoint_lsn
3177 == recv_sys->recovered_lsn);
3178 return(true);
3179 }
3180
3181 if (recv_sys->recovered_offset > RECV_PARSING_BUF_SIZE / 4) {
3182 /* Move parsing buffer data to the buffer start */
3183
3184 recv_sys_justify_left_parsing_buf();
3185 }
3186 }
3187
3188 return(true);
3189 }
3190
3191 static my_bool
xtrabackup_copy_logfile(lsn_t from_lsn,my_bool is_last)3192 xtrabackup_copy_logfile(lsn_t from_lsn, my_bool is_last)
3193 {
3194 /* definition from recv_recovery_from_checkpoint_start() */
3195 log_group_t* group;
3196 lsn_t group_scanned_lsn;
3197 lsn_t contiguous_lsn;
3198
3199 ut_a(dst_log_file != NULL);
3200
3201 /* read from checkpoint_lsn_start to current */
3202 contiguous_lsn = ut_uint64_align_down(from_lsn, OS_FILE_LOG_BLOCK_SIZE);
3203
3204 /* TODO: We must check the contiguous_lsn still exists in log file.. */
3205
3206 group = UT_LIST_GET_FIRST(log_sys->log_groups);
3207
3208 while (group) {
3209 bool finished;
3210 lsn_t start_lsn;
3211 lsn_t end_lsn;
3212
3213 /* reference recv_group_scan_log_recs() */
3214 finished = false;
3215
3216 start_lsn = contiguous_lsn;
3217
3218 while (!finished) {
3219
3220 end_lsn = start_lsn + RECV_SCAN_SIZE;
3221
3222 xtrabackup_io_throttling();
3223
3224 mutex_enter(&log_sys->mutex);
3225
3226 log_group_read_log_seg(log_sys->buf,
3227 group, start_lsn, end_lsn);
3228
3229 if (!xtrabackup_scan_log_recs(group, is_last,
3230 start_lsn, &contiguous_lsn, &group_scanned_lsn,
3231 from_lsn, &finished)) {
3232 goto error;
3233 }
3234
3235 mutex_exit(&log_sys->mutex);
3236
3237 start_lsn = end_lsn;
3238
3239 }
3240
3241 group->scanned_lsn = group_scanned_lsn;
3242
3243 msg_ts(">> log scanned up to (" LSN_PF ")\n",
3244 group->scanned_lsn);
3245
3246 group = UT_LIST_GET_NEXT(log_groups, group);
3247
3248 /* update global variable*/
3249 log_copy_scanned_lsn = group_scanned_lsn;
3250
3251 /* innodb_mirrored_log_groups must be 1, no other groups */
3252 ut_a(group == NULL);
3253
3254 debug_sync_point("xtrabackup_copy_logfile_pause");
3255
3256 }
3257
3258
3259 return(FALSE);
3260
3261 error:
3262 mutex_exit(&log_sys->mutex);
3263 ds_close(dst_log_file);
3264 msg("xtrabackup: Error: xtrabackup_copy_logfile() failed.\n");
3265 return(TRUE);
3266 }
3267
3268 static
3269 #ifndef __WIN__
3270 void*
3271 #else
3272 ulint
3273 #endif
log_copying_thread(void * arg)3274 log_copying_thread(
3275 void* arg __attribute__((unused)))
3276 {
3277 /*
3278 Initialize mysys thread-specific memory so we can
3279 use mysys functions in this thread.
3280 */
3281 my_thread_init();
3282
3283 ut_a(dst_log_file != NULL);
3284
3285 log_copying_running = TRUE;
3286
3287 while(log_copying) {
3288 os_event_reset(log_copying_stop);
3289 os_event_wait_time_low(log_copying_stop,
3290 xtrabackup_log_copy_interval * 1000ULL,
3291 0);
3292 if (log_copying) {
3293 if(xtrabackup_copy_logfile(log_copy_scanned_lsn,
3294 FALSE)) {
3295
3296 exit(EXIT_FAILURE);
3297 }
3298 }
3299 }
3300
3301 /* last copying */
3302 if(xtrabackup_copy_logfile(log_copy_scanned_lsn, TRUE)) {
3303
3304 exit(EXIT_FAILURE);
3305 }
3306
3307 log_copying_running = FALSE;
3308 my_thread_end();
3309 os_thread_exit();
3310
3311 return(0);
3312 }
3313
3314 /* io throttle watching (rough) */
3315 static
3316 #ifndef __WIN__
3317 void*
3318 #else
3319 ulint
3320 #endif
io_watching_thread(void * arg)3321 io_watching_thread(
3322 void* arg)
3323 {
3324 (void)arg;
3325 /* currently, for --backup only */
3326 ut_a(xtrabackup_backup);
3327
3328 io_watching_thread_running = TRUE;
3329
3330 while (log_copying) {
3331 os_thread_sleep(1000000); /*1 sec*/
3332 io_ticket = xtrabackup_throttle;
3333 os_event_set(wait_throttle);
3334 }
3335
3336 /* stop io throttle */
3337 xtrabackup_throttle = 0;
3338 os_event_set(wait_throttle);
3339
3340 io_watching_thread_running = FALSE;
3341
3342 os_thread_exit();
3343
3344 return(0);
3345 }
3346
3347 /************************************************************************
3348 I/o-handler thread function. */
3349 static
3350
3351 #ifndef __WIN__
3352 void*
3353 #else
3354 ulint
3355 #endif
io_handler_thread(void * arg)3356 io_handler_thread(
3357 /*==============*/
3358 void* arg)
3359 {
3360 ulint segment;
3361
3362
3363 segment = *((ulint*)arg);
3364
3365 while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
3366 fil_aio_wait(segment);
3367 }
3368
3369 /* We count the number of threads in os_thread_exit(). A created
3370 thread should always use that to exit and not use return() to exit.
3371 The thread actually never comes here because it is exited in an
3372 os_event_wait(). */
3373
3374 os_thread_exit();
3375
3376 #ifndef __WIN__
3377 return(NULL); /* Not reached */
3378 #else
3379 return(0);
3380 #endif
3381 }
3382
3383 /**************************************************************************
3384 Datafiles copying thread.*/
3385 static
3386 os_thread_ret_t
data_copy_thread_func(void * arg)3387 data_copy_thread_func(
3388 /*==================*/
3389 void *arg) /* thread context */
3390 {
3391 data_thread_ctxt_t *ctxt = (data_thread_ctxt_t *) arg;
3392 uint num = ctxt->num;
3393 fil_node_t* node;
3394
3395 /*
3396 Initialize mysys thread-specific memory so we can
3397 use mysys functions in this thread.
3398 */
3399 my_thread_init();
3400
3401 debug_sync_point("data_copy_thread_func");
3402
3403 while ((node = datafiles_iter_next(ctxt->it)) != NULL &&
3404 !*(ctxt->error)) {
3405
3406 /* copy the datafile */
3407 if(xtrabackup_copy_datafile(node, num)) {
3408 msg("[%02u] xtrabackup: Error: "
3409 "failed to copy datafile.\n", num);
3410 *(ctxt->error) = true;
3411 }
3412 }
3413
3414 mutex_enter(ctxt->count_mutex);
3415 (*ctxt->count)--;
3416 mutex_exit(ctxt->count_mutex);
3417
3418 my_thread_end();
3419 os_thread_exit();
3420 OS_THREAD_DUMMY_RETURN;
3421 }
3422
3423 /************************************************************************
3424 Initialize the appropriate datasink(s). Both local backups and streaming in the
3425 'xbstream' format allow parallel writes so we can write directly.
3426
3427 Otherwise (i.e. when streaming in the 'tar' format) we need 2 separate datasinks
3428 for the data stream (and don't allow parallel data copying) and for metainfo
3429 files (including xtrabackup_logfile). The second datasink writes to temporary
3430 files first, and then streams them in a serialized way when closed. */
3431 static void
xtrabackup_init_datasinks(void)3432 xtrabackup_init_datasinks(void)
3433 {
3434 if (xtrabackup_parallel > 1 && xtrabackup_stream &&
3435 xtrabackup_stream_fmt == XB_STREAM_FMT_TAR) {
3436 msg("xtrabackup: warning: the --parallel option does not have "
3437 "any effect when streaming in the 'tar' format. "
3438 "You can use the 'xbstream' format instead.\n");
3439 xtrabackup_parallel = 1;
3440 }
3441
3442 /* Start building out the pipelines from the terminus back */
3443 if (xtrabackup_stream) {
3444 /* All streaming goes to stdout */
3445 ds_data = ds_meta = ds_redo = ds_create(xtrabackup_target_dir,
3446 DS_TYPE_STDOUT);
3447 } else {
3448 /* Local filesystem */
3449 ds_data = ds_meta = ds_redo = ds_create(xtrabackup_target_dir,
3450 DS_TYPE_LOCAL);
3451 }
3452
3453 /* Track it for destruction */
3454 xtrabackup_add_datasink(ds_data);
3455
3456 /* Stream formatting */
3457 if (xtrabackup_stream) {
3458 ds_ctxt_t *ds;
3459 if (xtrabackup_stream_fmt == XB_STREAM_FMT_TAR) {
3460 ds = ds_create(xtrabackup_target_dir, DS_TYPE_ARCHIVE);
3461 } else if (xtrabackup_stream_fmt == XB_STREAM_FMT_XBSTREAM) {
3462 ds = ds_create(xtrabackup_target_dir, DS_TYPE_XBSTREAM);
3463 } else {
3464 /* bad juju... */
3465 ds = NULL;
3466 }
3467
3468 xtrabackup_add_datasink(ds);
3469
3470 ds_set_pipe(ds, ds_data);
3471 ds_data = ds;
3472
3473 if (xtrabackup_stream_fmt != XB_STREAM_FMT_XBSTREAM) {
3474
3475 /* 'tar' does not allow parallel streams */
3476 ds_redo = ds_meta = ds_create(xtrabackup_target_dir,
3477 DS_TYPE_TMPFILE);
3478 xtrabackup_add_datasink(ds_meta);
3479 ds_set_pipe(ds_meta, ds);
3480 } else {
3481 ds_redo = ds_meta = ds_data;
3482 }
3483 }
3484
3485 /* Encryption */
3486 if (xtrabackup_encrypt) {
3487 ds_ctxt_t *ds;
3488
3489 ds_encrypt_algo = xtrabackup_encrypt_algo;
3490 ds_encrypt_key = xtrabackup_encrypt_key;
3491 ds_encrypt_key_file = xtrabackup_encrypt_key_file;
3492 ds_encrypt_encrypt_threads = xtrabackup_encrypt_threads;
3493 ds_encrypt_encrypt_chunk_size = xtrabackup_encrypt_chunk_size;
3494
3495 ds = ds_create(xtrabackup_target_dir, DS_TYPE_ENCRYPT);
3496 xtrabackup_add_datasink(ds);
3497
3498 ds_set_pipe(ds, ds_data);
3499 if (ds_data != ds_meta) {
3500 ds_data = ds;
3501 ds = ds_create(xtrabackup_target_dir, DS_TYPE_ENCRYPT);
3502 xtrabackup_add_datasink(ds);
3503
3504 ds_set_pipe(ds, ds_redo);
3505 ds_redo = ds;
3506 } else {
3507 ds_redo = ds_data = ds;
3508 }
3509 }
3510
3511 /* Compression for ds_data and ds_redo */
3512 if (xtrabackup_compress) {
3513 ds_ctxt_t *ds;
3514
3515 /* Use a 1 MB buffer for compressed output stream */
3516 ds = ds_create(xtrabackup_target_dir, DS_TYPE_BUFFER);
3517 ds_buffer_set_size(ds, opt_read_buffer_size);
3518 xtrabackup_add_datasink(ds);
3519 ds_set_pipe(ds, ds_data);
3520 if (ds_data != ds_redo) {
3521 ds_data = ds;
3522 ds = ds_create(xtrabackup_target_dir, DS_TYPE_BUFFER);
3523 ds_buffer_set_size(ds, opt_read_buffer_size);
3524 xtrabackup_add_datasink(ds);
3525 ds_set_pipe(ds, ds_redo);
3526 ds_redo = ds;
3527 } else {
3528 ds_redo = ds_data = ds;
3529 }
3530
3531 ds = ds_create(xtrabackup_target_dir, DS_TYPE_COMPRESS);
3532 xtrabackup_add_datasink(ds);
3533 ds_set_pipe(ds, ds_data);
3534 if (ds_data != ds_redo) {
3535 ds_data = ds;
3536 ds = ds_create(xtrabackup_target_dir, DS_TYPE_COMPRESS);
3537 xtrabackup_add_datasink(ds);
3538 ds_set_pipe(ds, ds_redo);
3539 ds_redo = ds;
3540 } else {
3541 ds_redo = ds_data = ds;
3542 }
3543 }
3544 }
3545
3546 /************************************************************************
3547 Destroy datasinks.
3548
3549 Destruction is done in the specific order to not violate their order in the
3550 pipeline so that each datasink is able to flush data down the pipeline. */
xtrabackup_destroy_datasinks(void)3551 static void xtrabackup_destroy_datasinks(void)
3552 {
3553 for (uint i = actual_datasinks; i > 0; i--) {
3554 ds_destroy(datasinks[i-1]);
3555 datasinks[i-1] = NULL;
3556 }
3557 ds_data = NULL;
3558 ds_meta = NULL;
3559 ds_redo = NULL;
3560 }
3561
3562 #define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
3563 #define SRV_MAX_N_PENDING_SYNC_IOS 100
3564
3565 /************************************************************************
3566 @return TRUE if table should be opened. */
3567 static
3568 bool
xb_check_if_open_tablespace(const char * db,const char * table)3569 xb_check_if_open_tablespace(
3570 const char* db,
3571 const char* table)
3572 {
3573 char buf[FN_REFLEN];
3574
3575 snprintf(buf, sizeof(buf), "%s/%s", db, table);
3576
3577 return !check_if_skip_table(buf);
3578 }
3579
3580 /************************************************************************
3581 Initializes the I/O and tablespace cache subsystems. */
3582 static
3583 void
xb_fil_io_init(void)3584 xb_fil_io_init(void)
3585 /*================*/
3586 {
3587 srv_n_file_io_threads = srv_n_read_io_threads;
3588
3589 os_aio_init(srv_n_read_io_threads,
3590 srv_n_write_io_threads,
3591 SRV_MAX_N_PENDING_SYNC_IOS);
3592
3593 fil_init(srv_file_per_table ? 50000 : 5000, LONG_MAX);
3594
3595 fsp_init();
3596 }
3597
xb_new_datafile(const char * name,bool is_remote)3598 Datafile *xb_new_datafile(
3599 const char *name,
3600 bool is_remote)
3601 {
3602 if (is_remote) {
3603 RemoteDatafile *remote_file = new RemoteDatafile();
3604 remote_file->set_name(name);
3605 return(remote_file);
3606 } else {
3607 Datafile *file = new Datafile();
3608 file->set_name(name);
3609 file->make_filepath(".", name, IBD);
3610 return(file);
3611 }
3612 }
3613
3614 bool
validate_missing_encryption_tablespaces()3615 validate_missing_encryption_tablespaces()
3616 {
3617 bool ret=true;
3618 bool found = false;
3619 if (invalid_encrypted_tablespace_ids.size() > 0)
3620 {
3621 std::vector<ulint>::iterator it;
3622 for (it = invalid_encrypted_tablespace_ids.begin();
3623 it != invalid_encrypted_tablespace_ids.end();
3624 it++) {
3625 found = false;
3626 mutex_enter(&recv_sys->mutex);
3627 if (recv_sys->encryption_list != NULL) {
3628 encryption_list_t::iterator it_enc;
3629 for (it_enc = recv_sys->encryption_list->begin();
3630 it_enc != recv_sys->encryption_list->end();
3631 it_enc++) {
3632 if (it_enc->space_id == (*it)) {
3633 found = true;
3634 break;
3635 }
3636 }
3637 }
3638 mutex_exit(&recv_sys->mutex);
3639 if (!found)
3640 {
3641 msg_ts("xtrabackup: Error: Space ID %lu is missing encryption information.\n", (*it));
3642 ret=false;
3643 }
3644 }
3645 }
3646 return ret;
3647 }
3648
3649 void
xb_load_single_table_tablespace(const char * dirname,const char * filname,bool is_remote)3650 xb_load_single_table_tablespace(
3651 const char *dirname,
3652 const char *filname,
3653 bool is_remote)
3654 {
3655 /* Ignore .isl files on XtraBackup recovery. All tablespaces must be
3656 local. */
3657 if (is_remote && !srv_backup_mode) {
3658 return;
3659 }
3660
3661 /* The name ends in .ibd or .isl;
3662 try opening the file */
3663 char* name;
3664 size_t dirlen = dirname == NULL ? 0 : strlen(dirname);
3665 size_t namelen = strlen(filname);
3666 ulint pathlen = dirname == NULL ? namelen + 1: dirlen + namelen + 2;
3667 lsn_t flush_lsn;
3668 dberr_t err;
3669 fil_space_t *space;
3670
3671 name = static_cast<char*>(ut_malloc_nokey(pathlen));
3672
3673 if (dirname != NULL) {
3674 ut_snprintf(name, pathlen, "%s/%s", dirname, filname);
3675 name[pathlen - 5] = 0;
3676 } else {
3677 ut_snprintf(name, pathlen, "%s", filname);
3678 name[pathlen - 5] = 0;
3679 }
3680
3681 Datafile *file = xb_new_datafile(name, is_remote);
3682
3683 if (file->open_read_only(true) != DB_SUCCESS) {
3684 ut_free(name);
3685 exit(EXIT_FAILURE);
3686 }
3687
3688 err = file->validate_first_page(&flush_lsn, false);
3689
3690 if (err == DB_SUCCESS) {
3691
3692 os_offset_t node_size = os_file_get_size(file->handle());
3693 bool is_tmp = FSP_FLAGS_GET_TEMPORARY(file->flags());
3694 os_offset_t n_pages;
3695
3696 ut_a(node_size != (os_offset_t) -1);
3697
3698 n_pages = node_size / page_size_t(file->flags()).physical();
3699
3700 space = fil_space_create(
3701 name, file->space_id(), file->flags(),
3702 is_tmp ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE);
3703
3704 ut_a(space != NULL);
3705
3706 /* For encrypted tablespace, initialize encryption
3707 information.*/
3708 if (FSP_FLAGS_GET_ENCRYPTION(file->flags())) {
3709 if (srv_backup_mode || !use_dumped_tablespace_keys) {
3710 byte* key = file->m_encryption_key;
3711 byte* iv = file->m_encryption_iv;
3712
3713 if (key && iv) {
3714 err = fil_set_encryption(
3715 space->id,
3716 Encryption::AES, key, iv);
3717 }
3718 } else {
3719 byte key[ENCRYPTION_KEY_LEN];
3720 byte iv[ENCRYPTION_KEY_LEN];
3721
3722 xb_fetch_tablespace_key(space->id, key, iv);
3723
3724 err = fil_set_encryption(space->id,
3725 Encryption::AES, key, iv);
3726 }
3727
3728 ut_ad(err == DB_SUCCESS);
3729 }
3730
3731 if (!fil_node_create(file->filepath(), n_pages, space,
3732 false, false)) {
3733 ut_error;
3734 }
3735
3736 /* by opening the tablespace we forcing node and space objects
3737 in the cache to be populated with fields from space header */
3738 fil_space_open(space->name);
3739
3740 if (!srv_backup_mode || srv_close_files) {
3741 fil_space_close(space->name);
3742 }
3743 } else {
3744 /* allow corrupted first page for xtrabackup, it could be just
3745 zero-filled page, which we'll restore from redo log later */
3746
3747 if (xtrabackup_backup && err != DB_PAGE_IS_BLANK) {
3748 exit(EXIT_FAILURE);
3749 }
3750 if (xtrabackup_prepare) {
3751 exit(EXIT_FAILURE);
3752 }
3753 }
3754
3755 ut_free(name);
3756
3757 delete file;
3758 }
3759
3760 static
3761 bool
is_remote_tablespace_name(const char * path)3762 is_remote_tablespace_name(const char *path)
3763 {
3764 size_t len = strlen(path);
3765 return len > 4 && strcmp(path + len - 4, ".isl") == 0;
3766 }
3767
3768 static
3769 bool
is_local_tablespace_name(const char * path)3770 is_local_tablespace_name(const char *path)
3771 {
3772 size_t len = strlen(path);
3773 return len > 4 && strcmp(path + len - 4, ".ibd") == 0;
3774 }
3775
3776 static
3777 bool
is_tablespace_name(const char * path)3778 is_tablespace_name(const char *path)
3779 {
3780 return is_remote_tablespace_name(path)
3781 || is_local_tablespace_name(path);
3782 }
3783
3784 /********************************************************************//**
3785 At the server startup, if we need crash recovery, scans the database
3786 directories under the MySQL datadir, looking for .ibd files. Those files are
3787 single-table tablespaces. We need to know the space id in each of them so that
3788 we know into which file we should look to check the contents of a page stored
3789 in the doublewrite buffer, also to know where to apply log records where the
3790 space id is != 0.
3791 @return DB_SUCCESS or error number */
3792 UNIV_INTERN
3793 dberr_t
xb_load_single_table_tablespaces(bool (* pred)(const char *,const char *))3794 xb_load_single_table_tablespaces(bool (*pred)(const char*, const char*))
3795 /*===================================*/
3796 {
3797 int ret;
3798 char* dbpath = NULL;
3799 ulint dbpath_len = 100;
3800 os_file_dir_t dir;
3801 os_file_dir_t dbdir;
3802 os_file_stat_t dbinfo;
3803 os_file_stat_t fileinfo;
3804 dberr_t err = DB_SUCCESS;
3805
3806 /* The datadir of MySQL is always the default directory of mysqld */
3807
3808 dir = os_file_opendir(fil_path_to_mysql_datadir, true);
3809
3810 if (dir == NULL) {
3811
3812 return(DB_ERROR);
3813 }
3814
3815 dbpath = static_cast<char*>(ut_malloc_nokey(dbpath_len));
3816
3817 /* Scan all directories under the datadir. They are the database
3818 directories of MySQL. */
3819
3820 ret = fil_file_readdir_next_file(&err, fil_path_to_mysql_datadir, dir,
3821 &dbinfo);
3822 while (ret == 0) {
3823 ulint len;
3824 bool is_tablespace;
3825 bool is_remote;
3826
3827 is_tablespace = is_tablespace_name(dbinfo.name);
3828 is_remote = is_remote_tablespace_name(dbinfo.name);
3829
3830 /* General tablespaces are always at the first level of the
3831 data home dir */
3832 if (dbinfo.type == OS_FILE_TYPE_FILE && is_tablespace &&
3833 !(pred && !pred(".", dbinfo.name))) {
3834 xb_load_single_table_tablespace(
3835 NULL, dbinfo.name, is_remote);
3836 }
3837
3838 if (dbinfo.type == OS_FILE_TYPE_FILE
3839 || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
3840
3841 goto next_datadir_item;
3842 }
3843
3844 /* We found a symlink or a directory; try opening it to see
3845 if a symlink is a directory */
3846
3847 len = strlen(fil_path_to_mysql_datadir)
3848 + strlen (dbinfo.name) + 2;
3849 if (len > dbpath_len) {
3850 dbpath_len = len;
3851
3852 if (dbpath) {
3853 ut_free(dbpath);
3854 }
3855
3856 dbpath = static_cast<char*>(ut_malloc_nokey(dbpath_len));
3857 }
3858 ut_snprintf(dbpath, dbpath_len,
3859 "%s/%s", fil_path_to_mysql_datadir, dbinfo.name);
3860 os_normalize_path(dbpath);
3861
3862 if (check_if_skip_database_by_path(dbpath)) {
3863 fprintf(stderr, "Skipping db: %s\n", dbpath);
3864 goto next_datadir_item;
3865 }
3866
3867 /* We want wrong directory permissions to be a fatal error for
3868 XtraBackup. */
3869 dbdir = os_file_opendir(dbpath, true);
3870
3871 if (dbdir != NULL) {
3872
3873 /* We found a database directory; loop through it,
3874 looking for possible .ibd and .isl files in it */
3875
3876 ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
3877 &fileinfo);
3878 while (ret == 0) {
3879 if (fileinfo.type == OS_FILE_TYPE_DIR) {
3880 goto next_file_item;
3881 }
3882
3883 is_tablespace = is_tablespace_name(
3884 fileinfo.name);
3885 is_remote = is_remote_tablespace_name(
3886 fileinfo.name);
3887
3888 /* We found a symlink or a file */
3889 if (is_tablespace
3890 && (!pred
3891 || pred(dbinfo.name, fileinfo.name))) {
3892 xb_load_single_table_tablespace(
3893 dbinfo.name, fileinfo.name,
3894 is_remote);
3895 }
3896 next_file_item:
3897 ret = fil_file_readdir_next_file(&err,
3898 dbpath, dbdir,
3899 &fileinfo);
3900 }
3901
3902 if (0 != os_file_closedir(dbdir)) {
3903 fputs("InnoDB: Warning: could not"
3904 " close database directory ", stderr);
3905 fputs(dbpath, stderr);
3906 putc('\n', stderr);
3907
3908 err = DB_ERROR;
3909 }
3910
3911 } else {
3912
3913 err = DB_ERROR;
3914 break;
3915
3916 }
3917
3918 next_datadir_item:
3919 ret = fil_file_readdir_next_file(&err,
3920 fil_path_to_mysql_datadir,
3921 dir, &dbinfo);
3922 }
3923
3924 ut_free(dbpath);
3925
3926 if (0 != os_file_closedir(dir)) {
3927 fprintf(stderr,
3928 "InnoDB: Error: could not close MySQL datadir\n");
3929
3930 return(DB_ERROR);
3931 }
3932
3933 return(err);
3934 }
3935
3936 /****************************************************************************
3937 Populates the tablespace memory cache by scanning for and opening data files.
3938 @returns DB_SUCCESS or error code.*/
3939 static
3940 ulint
xb_load_tablespaces(void)3941 xb_load_tablespaces(void)
3942 /*=====================*/
3943 {
3944 ulint i;
3945 ulint err;
3946 ulint sum_of_new_sizes;
3947 lsn_t flush_lsn;
3948 bool create_new_db;
3949
3950 for (i = 0; i < srv_n_file_io_threads; i++) {
3951 thread_nr[i] = i;
3952
3953 os_thread_create(io_handler_thread, thread_nr + i,
3954 thread_ids + i);
3955 }
3956
3957 os_thread_sleep(200000); /*0.2 sec*/
3958
3959 err = srv_sys_space.check_file_spec(&create_new_db, 0);
3960
3961 /* create_new_db must not be true. */
3962 if (err != DB_SUCCESS || create_new_db) {
3963 msg("xtrabackup: could not find data files at the "
3964 "specified datadir\n");
3965 return(DB_ERROR);
3966 }
3967
3968 err = srv_sys_space.open_or_create(false, false, &sum_of_new_sizes,
3969 &flush_lsn);
3970
3971 if (err != DB_SUCCESS) {
3972 msg("xtrabackup: Could not open or create data files.\n"
3973 "xtrabackup: If you tried to add new data files, and it "
3974 "failed here,\n"
3975 "xtrabackup: you should now edit innodb_data_file_path in "
3976 "my.cnf back\n"
3977 "xtrabackup: to what it was, and remove the new ibdata "
3978 "files InnoDB created\n"
3979 "xtrabackup: in this failed attempt. InnoDB only wrote "
3980 "those files full of\n"
3981 "xtrabackup: zeros, but did not yet use them in any way. "
3982 "But be careful: do not\n"
3983 "xtrabackup: remove old data files which contain your "
3984 "precious data!\n");
3985 return(err);
3986 }
3987
3988 /* Add separate undo tablespaces to fil_system */
3989
3990 err = srv_undo_tablespaces_init(FALSE,
3991 TRUE,
3992 srv_undo_tablespaces,
3993 &srv_undo_tablespaces_open);
3994 if (err != DB_SUCCESS) {
3995 return(err);
3996 }
3997
3998 /* It is important to call fil_load_single_table_tablespace() after
3999 srv_undo_tablespaces_init(), because fil_is_user_tablespace_id() *
4000 relies on srv_undo_tablespaces_open to be properly initialized */
4001
4002 msg("xtrabackup: Generating a list of tablespaces\n");
4003
4004 err = xb_load_single_table_tablespaces(xb_check_if_open_tablespace);
4005 if (err != DB_SUCCESS) {
4006 return(err);
4007 }
4008
4009 debug_sync_point("xtrabackup_load_tablespaces_pause");
4010
4011 return(DB_SUCCESS);
4012 }
4013
4014 /************************************************************************
4015 Initialize the tablespace memory cache and populate it by scanning for and
4016 opening data files.
4017 @returns DB_SUCCESS or error code.*/
4018 ulint
xb_data_files_init(void)4019 xb_data_files_init(void)
4020 /*====================*/
4021 {
4022 xb_fil_io_init();
4023
4024 return(xb_load_tablespaces());
4025 }
4026
4027 /************************************************************************
4028 Destroy the tablespace memory cache. */
4029 void
xb_data_files_close(void)4030 xb_data_files_close(void)
4031 /*====================*/
4032 {
4033 ulint i;
4034
4035 srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
4036
4037 /* All threads end up waiting for certain events. Put those events
4038 to the signaled state. Then the threads will exit themselves after
4039 os_event_wait(). */
4040 for (i = 0; i < 1000; i++) {
4041
4042 if (!buf_page_cleaner_is_active
4043 && os_aio_all_slots_free()) {
4044 os_aio_wake_all_threads_at_shutdown();
4045 }
4046
4047 /* f. dict_stats_thread is signaled from
4048 logs_empty_and_mark_files_at_shutdown() and should have
4049 already quit or is quitting right now. */
4050
4051 bool active = os_thread_active();
4052
4053 os_thread_sleep(100000);
4054
4055 if (!active) {
4056 break;
4057 }
4058 }
4059
4060 if (i == 1000) {
4061 ib::warn() << os_thread_count << " threads created by InnoDB"
4062 " had not exited at shutdown!";
4063 }
4064
4065 os_aio_free();
4066
4067 fil_close_all_files();
4068
4069 fil_close();
4070
4071 /* Free the double write data structures. */
4072 if (buf_dblwr) {
4073 buf_dblwr_free();
4074 }
4075
4076 /* Reset srv_file_io_threads to its default value to avoid confusing
4077 warning on --prepare in innobase_start_or_create_for_mysql()*/
4078 srv_n_file_io_threads = 4;
4079
4080 srv_shutdown_state = SRV_SHUTDOWN_NONE;
4081 }
4082
4083 /***********************************************************************
4084 Allocate and initialize the entry for databases and tables filtering
4085 hash tables. If memory allocation is not successful, terminate program.
4086 @return pointer to the created entry. */
4087 static
4088 xb_filter_entry_t *
xb_new_filter_entry(const char * name)4089 xb_new_filter_entry(
4090 /*================*/
4091 const char* name) /*!< in: name of table/database */
4092 {
4093 xb_filter_entry_t *entry;
4094 ulint namelen = strlen(name);
4095
4096 ut_a(namelen <= NAME_LEN * 2 + 1);
4097
4098 entry = static_cast<xb_filter_entry_t *>
4099 (ut_zalloc_nokey(sizeof(xb_filter_entry_t) + namelen + 1));
4100 entry->name = ((char*)entry) + sizeof(xb_filter_entry_t);
4101 strcpy(entry->name, name);
4102 entry->has_tables = FALSE;
4103
4104 return entry;
4105 }
4106
4107 /***********************************************************************
4108 Add entry to hash table. If hash table is NULL, allocate and initialize
4109 new hash table */
4110 static
4111 xb_filter_entry_t*
xb_add_filter(const char * name,hash_table_t ** hash)4112 xb_add_filter(
4113 /*========================*/
4114 const char* name, /*!< in: name of table/database */
4115 hash_table_t** hash) /*!< in/out: hash to insert into */
4116 {
4117 xb_filter_entry_t* entry;
4118
4119 entry = xb_new_filter_entry(name);
4120
4121 if (UNIV_UNLIKELY(*hash == NULL)) {
4122 *hash = hash_create(1000);
4123 }
4124 HASH_INSERT(xb_filter_entry_t,
4125 name_hash, *hash,
4126 ut_fold_string(entry->name),
4127 entry);
4128
4129 return entry;
4130 }
4131
4132 /***********************************************************************
4133 Validate name of table or database. If name is invalid, program will
4134 be finished with error code */
4135 static
4136 void
xb_validate_name(const char * name,size_t len)4137 xb_validate_name(
4138 /*=============*/
4139 const char* name, /*!< in: name */
4140 size_t len) /*!< in: length of name */
4141 {
4142 const char* p;
4143
4144 /* perform only basic validation. validate length and
4145 path symbols */
4146 if (len > NAME_LEN) {
4147 msg("xtrabackup: name `%s` is too long.\n", name);
4148 exit(EXIT_FAILURE);
4149 }
4150 p = strpbrk(name, "/\\~");
4151 if (p && p - name < NAME_LEN) {
4152 msg("xtrabackup: name `%s` is not valid.\n", name);
4153 exit(EXIT_FAILURE);
4154 }
4155 }
4156
4157 /***********************************************************************
4158 Register new filter entry which can be either database
4159 or table name. */
4160 static
4161 void
xb_register_filter_entry(const char * name,hash_table_t ** databases_hash,hash_table_t ** tables_hash)4162 xb_register_filter_entry(
4163 /*=====================*/
4164 const char* name, /*!< in: name */
4165 hash_table_t** databases_hash,
4166 hash_table_t** tables_hash)
4167 {
4168 const char* p;
4169 size_t namelen;
4170 xb_filter_entry_t* db_entry = NULL;
4171
4172 namelen = strlen(name);
4173 if ((p = strchr(name, '.')) != NULL) {
4174 char dbname[NAME_LEN + 1];
4175
4176 xb_validate_name(name, p - name);
4177 xb_validate_name(p + 1, namelen - (p - name));
4178
4179 strncpy(dbname, name, p - name);
4180 dbname[p - name] = 0;
4181
4182 if (*databases_hash) {
4183 HASH_SEARCH(name_hash, (*databases_hash),
4184 ut_fold_string(dbname),
4185 xb_filter_entry_t*,
4186 db_entry, (void) 0,
4187 !strcmp(db_entry->name, dbname));
4188 }
4189 if (!db_entry) {
4190 db_entry = xb_add_filter(dbname, databases_hash);
4191 }
4192 db_entry->has_tables = TRUE;
4193 xb_add_filter(name, tables_hash);
4194 } else {
4195 xb_validate_name(name, namelen);
4196
4197 xb_add_filter(name, databases_hash);
4198 }
4199 }
4200
4201 static
4202 void
xb_register_include_filter_entry(const char * name)4203 xb_register_include_filter_entry(
4204 const char* name)
4205 {
4206 xb_register_filter_entry(name, &databases_include_hash,
4207 &tables_include_hash);
4208 }
4209
4210 static
4211 void
xb_register_exclude_filter_entry(const char * name)4212 xb_register_exclude_filter_entry(
4213 const char* name)
4214 {
4215 xb_register_filter_entry(name, &databases_exclude_hash,
4216 &tables_exclude_hash);
4217 }
4218
4219 /***********************************************************************
4220 Register new table for the filter. */
4221 static
4222 void
xb_register_table(const char * name)4223 xb_register_table(
4224 /*==============*/
4225 const char* name) /*!< in: name of table */
4226 {
4227 if (strchr(name, '.') == NULL) {
4228 msg("xtrabackup: `%s` is not fully qualified name.\n", name);
4229 exit(EXIT_FAILURE);
4230 }
4231
4232 xb_register_include_filter_entry(name);
4233 }
4234
compile_regex(const char * regex_string,const char * error_context,xb_regex_t * compiled_re)4235 bool compile_regex(
4236 const char* regex_string,
4237 const char* error_context,
4238 xb_regex_t* compiled_re)
4239 {
4240 char errbuf[100];
4241 int ret = xb_regcomp(compiled_re, regex_string, REG_EXTENDED);
4242 if (ret != 0) {
4243 xb_regerror(ret, compiled_re, errbuf, sizeof(errbuf));
4244 msg("xtrabackup: error: %s regcomp(%s): %s\n",
4245 error_context, regex_string, errbuf);
4246 return false;
4247 }
4248 return true;
4249 }
4250
4251 static
4252 void
xb_add_regex_to_list(const char * regex,const char * error_context,regex_list_t * list)4253 xb_add_regex_to_list(
4254 const char* regex, /*!< in: regex */
4255 const char* error_context, /*!< in: context to error message */
4256 regex_list_t* list) /*! in: list to put new regex to */
4257 {
4258 xb_regex_t compiled_regex;
4259 if (!compile_regex(regex, error_context, &compiled_regex)) {
4260 exit(EXIT_FAILURE);
4261 }
4262
4263 list->push_back(compiled_regex);
4264 }
4265
4266 /***********************************************************************
4267 Register new regex for the include filter. */
4268 static
4269 void
xb_register_include_regex(const char * regex)4270 xb_register_include_regex(
4271 /*==============*/
4272 const char* regex) /*!< in: regex */
4273 {
4274 xb_add_regex_to_list(regex, "tables", ®ex_include_list);
4275 }
4276
4277 /***********************************************************************
4278 Register new regex for the exclude filter. */
4279 static
4280 void
xb_register_exclude_regex(const char * regex)4281 xb_register_exclude_regex(
4282 /*==============*/
4283 const char* regex) /*!< in: regex */
4284 {
4285 xb_add_regex_to_list(regex, "tables-exclude", ®ex_exclude_list);
4286 }
4287
4288 typedef void (*insert_entry_func_t)(const char*);
4289
4290 /***********************************************************************
4291 Scan string and load filter entries from it. */
4292 static
4293 void
xb_load_list_string(char * list,const char * delimiters,insert_entry_func_t ins)4294 xb_load_list_string(
4295 /*================*/
4296 char* list, /*!< in: string representing a list */
4297 const char* delimiters, /*!< in: delimiters of entries */
4298 insert_entry_func_t ins) /*!< in: callback to add entry */
4299 {
4300 char* p;
4301 char* saveptr;
4302
4303 p = strtok_r(list, delimiters, &saveptr);
4304 while (p) {
4305
4306 ins(p);
4307
4308 p = strtok_r(NULL, delimiters, &saveptr);
4309 }
4310 }
4311
4312 /***********************************************************************
4313 Scan file and load filter entries from it. */
4314 static
4315 void
xb_load_list_file(const char * filename,insert_entry_func_t ins)4316 xb_load_list_file(
4317 /*==============*/
4318 const char* filename, /*!< in: name of file */
4319 insert_entry_func_t ins) /*!< in: callback to add entry */
4320 {
4321 char name_buf[NAME_LEN*2+2];
4322 FILE* fp;
4323
4324 /* read and store the filenames */
4325 fp = fopen(filename, "r");
4326 if (!fp) {
4327 msg("xtrabackup: cannot open %s\n",
4328 filename);
4329 exit(EXIT_FAILURE);
4330 }
4331 while (fgets(name_buf, sizeof(name_buf), fp) != NULL) {
4332 char* p = strchr(name_buf, '\n');
4333 if (p) {
4334 *p = '\0';
4335 } else {
4336 msg("xtrabackup: `%s...` name is too long", name_buf);
4337 exit(EXIT_FAILURE);
4338 }
4339
4340 ins(name_buf);
4341 }
4342
4343 fclose(fp);
4344 }
4345
4346
4347 static
4348 void
xb_filters_init()4349 xb_filters_init()
4350 {
4351 if (xtrabackup_databases) {
4352 xb_load_list_string(xtrabackup_databases, " \t",
4353 xb_register_include_filter_entry);
4354 }
4355
4356 if (xtrabackup_databases_file) {
4357 xb_load_list_file(xtrabackup_databases_file,
4358 xb_register_include_filter_entry);
4359 }
4360
4361 if (xtrabackup_databases_exclude) {
4362 xb_load_list_string(xtrabackup_databases_exclude, " \t",
4363 xb_register_exclude_filter_entry);
4364 }
4365
4366 if (xtrabackup_tables) {
4367 xb_load_list_string(xtrabackup_tables, ",",
4368 xb_register_include_regex);
4369 }
4370
4371 if (xtrabackup_tables_file) {
4372 xb_load_list_file(xtrabackup_tables_file, xb_register_table);
4373 }
4374
4375 if (xtrabackup_tables_exclude) {
4376 xb_load_list_string(xtrabackup_tables_exclude, ",",
4377 xb_register_exclude_regex);
4378 }
4379 }
4380
4381 static
4382 void
xb_filter_hash_free(hash_table_t * hash)4383 xb_filter_hash_free(hash_table_t* hash)
4384 {
4385 ulint i;
4386
4387 /* free the hash elements */
4388 for (i = 0; i < hash_get_n_cells(hash); i++) {
4389 xb_filter_entry_t* table;
4390
4391 table = static_cast<xb_filter_entry_t *>
4392 (HASH_GET_FIRST(hash, i));
4393
4394 while (table) {
4395 xb_filter_entry_t* prev_table = table;
4396
4397 table = static_cast<xb_filter_entry_t *>
4398 (HASH_GET_NEXT(name_hash, prev_table));
4399
4400 HASH_DELETE(xb_filter_entry_t, name_hash, hash,
4401 ut_fold_string(prev_table->name), prev_table);
4402 ut_free(prev_table);
4403 }
4404 }
4405
4406 /* free hash */
4407 hash_table_free(hash);
4408 }
4409
xb_regex_list_free(regex_list_t * list)4410 static void xb_regex_list_free(regex_list_t* list)
4411 {
4412 while (list->size() > 0) {
4413 xb_regfree(&list->front());
4414 list->pop_front();
4415 }
4416 }
4417
4418 /************************************************************************
4419 Destroy table filters for partial backup. */
4420 static
4421 void
xb_filters_free()4422 xb_filters_free()
4423 {
4424 xb_regex_list_free(®ex_include_list);
4425 xb_regex_list_free(®ex_exclude_list);
4426
4427 if (tables_include_hash) {
4428 xb_filter_hash_free(tables_include_hash);
4429 }
4430
4431 if (tables_exclude_hash) {
4432 xb_filter_hash_free(tables_exclude_hash);
4433 }
4434
4435 if (databases_include_hash) {
4436 xb_filter_hash_free(databases_include_hash);
4437 }
4438
4439 if (databases_exclude_hash) {
4440 xb_filter_hash_free(databases_exclude_hash);
4441 }
4442 }
4443
4444 /*********************************************************************//**
4445 Creates or opens the log files and closes them.
4446 @return DB_SUCCESS or error code */
4447 static
4448 ulint
open_or_create_log_file(ibool create_new_db,ibool * log_file_created,ibool log_file_has_been_opened,ulint k,ulint i,fil_space_t ** log_space)4449 open_or_create_log_file(
4450 /*====================*/
4451 ibool create_new_db, /*!< in: TRUE if we should create a
4452 new database */
4453 ibool* log_file_created, /*!< out: TRUE if new log file
4454 created */
4455 ibool log_file_has_been_opened,/*!< in: TRUE if a log file has been
4456 opened before: then it is an error
4457 to try to create another log file */
4458 ulint k, /*!< in: log group number */
4459 ulint i, /*!< in: log file number in group */
4460 fil_space_t** log_space) /*!< out: log space */
4461 {
4462 bool ret;
4463 os_offset_t size;
4464 char name[10000];
4465 ulint dirnamelen;
4466
4467 UT_NOT_USED(create_new_db);
4468 UT_NOT_USED(log_file_has_been_opened);
4469 UT_NOT_USED(k);
4470 ut_ad(k == 0);
4471
4472 *log_file_created = FALSE;
4473
4474 os_normalize_path(srv_log_group_home_dir);
4475
4476 dirnamelen = strlen(srv_log_group_home_dir);
4477 ut_a(dirnamelen < (sizeof name) - 10 - sizeof "ib_logfile");
4478 memcpy(name, srv_log_group_home_dir, dirnamelen);
4479
4480 /* Add a path separator if needed. */
4481 if (dirnamelen && name[dirnamelen - 1] != OS_PATH_SEPARATOR) {
4482 name[dirnamelen++] = OS_PATH_SEPARATOR;
4483 }
4484
4485 sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i);
4486
4487 files[i] = os_file_create(0, name,
4488 OS_FILE_OPEN, OS_FILE_NORMAL,
4489 OS_LOG_FILE, true, &ret);
4490 if (!ret) {
4491 fprintf(stderr, "InnoDB: Error in opening %s\n", name);
4492
4493 return(DB_ERROR);
4494 }
4495
4496 size = os_file_get_size(files[i]);
4497
4498 if (size != srv_log_file_size * UNIV_PAGE_SIZE) {
4499
4500 fprintf(stderr,
4501 "InnoDB: Error: log file %s is"
4502 " of different size " UINT64PF " bytes\n"
4503 "InnoDB: than specified in the .cnf"
4504 " file " UINT64PF " bytes!\n",
4505 name, size, srv_log_file_size * UNIV_PAGE_SIZE);
4506
4507 return(DB_ERROR);
4508 }
4509
4510 ret = os_file_close(files[i]);
4511 ut_a(ret);
4512
4513 if (i == 0) {
4514 /* Create in memory the file space object
4515 which is for this log group */
4516
4517 *log_space = fil_space_create(
4518 name, 2 * k + SRV_LOG_SPACE_FIRST_ID,
4519 fsp_flags_set_page_size(0, univ_page_size),
4520 FIL_TYPE_LOG);
4521 }
4522
4523 ut_a(*log_space != NULL);
4524 ut_a(fil_validate());
4525
4526 ut_a(fil_node_create(name, srv_log_file_size, *log_space,
4527 false, false) != NULL);
4528 if (i == 0) {
4529 ut_a(log_group_init(k, srv_n_log_files,
4530 srv_log_file_size * UNIV_PAGE_SIZE,
4531 2 * k + SRV_LOG_SPACE_FIRST_ID));
4532 }
4533
4534 return(DB_SUCCESS);
4535 }
4536
4537 /*********************************************************************//**
4538 Normalizes init parameter values to use units we use inside InnoDB.
4539 @return DB_SUCCESS or error code */
4540 static
4541 void
xb_normalize_init_values(void)4542 xb_normalize_init_values(void)
4543 /*==========================*/
4544 {
4545 srv_sys_space.normalize();
4546
4547 srv_tmp_space.normalize();
4548
4549 srv_log_file_size /= UNIV_PAGE_SIZE;
4550
4551 srv_log_buffer_size /= UNIV_PAGE_SIZE;
4552
4553 srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
4554 }
4555
4556 /***********************************************************************
4557 Set the open files limit. Based on set_max_open_files().
4558
4559 @return the resulting open files limit. May be less or more than the requested
4560 value. */
4561 static uint
xb_set_max_open_files(uint max_file_limit)4562 xb_set_max_open_files(
4563 /*==================*/
4564 uint max_file_limit) /*!<in: open files limit */
4565 {
4566 #if defined(RLIMIT_NOFILE)
4567 struct rlimit rlimit;
4568 uint old_cur;
4569
4570 if (getrlimit(RLIMIT_NOFILE, &rlimit)) {
4571
4572 goto end;
4573 }
4574
4575 old_cur = (uint) rlimit.rlim_cur;
4576
4577 if (rlimit.rlim_cur == RLIM_INFINITY) {
4578
4579 rlimit.rlim_cur = max_file_limit;
4580 }
4581
4582 if (rlimit.rlim_cur >= max_file_limit) {
4583
4584 max_file_limit = rlimit.rlim_cur;
4585 goto end;
4586 }
4587
4588 rlimit.rlim_cur = rlimit.rlim_max = max_file_limit;
4589
4590 if (setrlimit(RLIMIT_NOFILE, &rlimit)) {
4591
4592 max_file_limit = old_cur; /* Use original value */
4593 } else {
4594
4595 rlimit.rlim_cur = 0; /* Safety if next call fails */
4596
4597 (void) getrlimit(RLIMIT_NOFILE, &rlimit);
4598
4599 if (rlimit.rlim_cur) {
4600
4601 /* If call didn't fail */
4602 max_file_limit = (uint) rlimit.rlim_cur;
4603 }
4604 }
4605
4606 end:
4607 return(max_file_limit);
4608 #else
4609 return(0);
4610 #endif
4611 }
4612
4613 /**************************************************************************
4614 Prints a warning for every table that uses unsupported engine and
4615 hence will not be backed up. */
4616 static void
xb_tables_compatibility_check()4617 xb_tables_compatibility_check()
4618 {
4619 const char* query = "SELECT\n"
4620 " CONCAT(table_schema, '/', table_name), engine\n"
4621 "FROM information_schema.tables\n"
4622 "WHERE engine NOT IN (\n"
4623 " 'MyISAM', 'InnoDB', 'CSV', 'MRG_MYISAM'\n"
4624 ")\n"
4625 "AND table_schema NOT IN (\n"
4626 " 'performance_schema', 'information_schema',"
4627 " 'mysql'\n"
4628 ");";
4629
4630 MYSQL_RES* result = xb_mysql_query(mysql_connection, query, true, true);
4631 MYSQL_ROW row;
4632 if (!result) {
4633 return;
4634 }
4635
4636 ut_a(mysql_num_fields(result) == 2);
4637 while ((row = mysql_fetch_row(result))) {
4638 if (!check_if_skip_table(row[0])) {
4639 *strchr(row[0], '/') = '.';
4640 msg("Warning: \"%s\" uses engine \"%s\" "
4641 "and will not be backed up.\n", row[0], row[1]);
4642 }
4643 }
4644
4645 mysql_free_result(result);
4646 }
4647
4648 void
xtrabackup_backup_func(void)4649 xtrabackup_backup_func(void)
4650 {
4651 MY_STAT stat_info;
4652 lsn_t latest_cp;
4653 uint i;
4654 uint count;
4655 ib_mutex_t count_mutex;
4656 data_thread_ctxt_t *data_threads;
4657
4658 recv_is_making_a_backup = true;
4659
4660 #ifdef USE_POSIX_FADVISE
4661 msg("xtrabackup: uses posix_fadvise().\n");
4662 #endif
4663
4664 /* cd to datadir */
4665
4666 if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
4667 {
4668 msg("xtrabackup: cannot my_setwd %s\n", mysql_real_data_home);
4669 exit(EXIT_FAILURE);
4670 }
4671 msg("xtrabackup: cd to %s\n", mysql_real_data_home);
4672
4673 msg("xtrabackup: open files limit requested %u, set to %u\n",
4674 (uint) xb_open_files_limit,
4675 xb_set_max_open_files(xb_open_files_limit));
4676
4677 mysql_data_home= mysql_data_home_buff;
4678 mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
4679 mysql_data_home[1]=0;
4680
4681 srv_read_only_mode = TRUE;
4682
4683 srv_backup_mode = TRUE;
4684 /* We can safely close files if we don't allow DDL during the
4685 backup */
4686 srv_close_files = xb_close_files || opt_lock_ddl;
4687
4688 if (xb_close_files)
4689 msg("xtrabackup: warning: close-files specified. Use it "
4690 "at your own risk. If there are DDL operations like table DROP TABLE "
4691 "or RENAME TABLE during the backup, inconsistent backup will be "
4692 "produced.\n");
4693
4694 /* initialize components */
4695 if(innodb_init_param())
4696 exit(EXIT_FAILURE);
4697
4698 xb_normalize_init_values();
4699
4700 #ifndef __WIN__
4701 if (srv_file_flush_method_str == NULL) {
4702 /* These are the default options */
4703 srv_unix_file_flush_method = SRV_UNIX_FSYNC;
4704 } else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) {
4705 srv_unix_file_flush_method = SRV_UNIX_FSYNC;
4706 } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
4707 srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
4708
4709 } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) {
4710 srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
4711 msg("xtrabackup: using O_DIRECT\n");
4712 } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) {
4713 srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
4714
4715 } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
4716 srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
4717 } else if (0 == ut_strcmp(srv_file_flush_method_str, "ALL_O_DIRECT")) {
4718 srv_unix_file_flush_method = SRV_UNIX_ALL_O_DIRECT;
4719 msg("xtrabackup: using ALL_O_DIRECT\n");
4720 } else if (0 == ut_strcmp(srv_file_flush_method_str,
4721 "O_DIRECT_NO_FSYNC")) {
4722 srv_unix_file_flush_method = SRV_UNIX_O_DIRECT_NO_FSYNC;
4723 msg("xtrabackup: using O_DIRECT_NO_FSYNC\n");
4724 } else {
4725 msg("xtrabackup: Unrecognized value %s for "
4726 "innodb_flush_method\n", srv_file_flush_method_str);
4727 exit(EXIT_FAILURE);
4728 }
4729 #else /* __WIN__ */
4730 /* We can only use synchronous unbuffered IO on Windows for now */
4731 if (srv_file_flush_method_str != NULL) {
4732 msg("xtrabackupp: Warning: "
4733 "ignoring innodb_flush_method = %s on Windows.\n");
4734 }
4735
4736 srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
4737 srv_use_native_aio = FALSE;
4738 #endif
4739
4740 if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
4741 /* Here we still have srv_pool_size counted
4742 in kilobytes (in 4.0 this was in bytes)
4743 srv_boot() converts the value to
4744 pages; if buffer pool is less than 1000 MB,
4745 assume fewer threads. */
4746 srv_max_n_threads = 50000;
4747
4748 } else if (srv_buf_pool_size >= 8 * 1024 * 1024) {
4749
4750 srv_max_n_threads = 10000;
4751 } else {
4752 srv_max_n_threads = 1000; /* saves several MB of memory,
4753 especially in 64-bit
4754 computers */
4755 }
4756
4757 os_event_global_init();
4758 srv_general_init();
4759 ut_crc32_init();
4760 crc_init();
4761
4762 xb_filters_init();
4763
4764 if (!xb_keyring_init_for_backup(mysql_connection)) {
4765 msg("xtrabackup: Error: failed to init keyring plugin\n");
4766 exit(EXIT_FAILURE);
4767 }
4768
4769 if (opt_tables_compatibility_check) {
4770 xb_tables_compatibility_check();
4771 }
4772
4773 {
4774 ibool log_file_created;
4775 ibool log_created = FALSE;
4776 ibool log_opened = FALSE;
4777 ulint err;
4778 ulint i;
4779 fil_space_t *log_space;
4780
4781 xb_fil_io_init();
4782
4783 log_init();
4784
4785 recv_sys_create();
4786 recv_sys_init(buf_pool_get_curr_size());
4787
4788 lock_sys_create(srv_lock_table_size);
4789
4790 for (i = 0; i < srv_n_log_files; i++) {
4791 err = open_or_create_log_file(FALSE, &log_file_created,
4792 log_opened, 0, i, &log_space);
4793 if (err != DB_SUCCESS) {
4794
4795 //return((int) err);
4796 exit(EXIT_FAILURE);
4797 }
4798
4799 if (log_file_created) {
4800 log_created = TRUE;
4801 } else {
4802 log_opened = TRUE;
4803 }
4804 if ((log_opened && log_created)) {
4805 msg(
4806 "xtrabackup: Error: all log files must be created at the same time.\n"
4807 "xtrabackup: All log files must be created also in database creation.\n"
4808 "xtrabackup: If you want bigger or smaller log files, shut down the\n"
4809 "xtrabackup: database and make sure there were no errors in shutdown.\n"
4810 "xtrabackup: Then delete the existing log files. Edit the .cnf file\n"
4811 "xtrabackup: and start the database again.\n");
4812
4813 //return(DB_ERROR);
4814 exit(EXIT_FAILURE);
4815 }
4816 }
4817
4818 /* log_file_created must not be TRUE, if online */
4819 if (log_file_created) {
4820 msg("xtrabackup: Something wrong with source files...\n");
4821 exit(EXIT_FAILURE);
4822 }
4823
4824 }
4825
4826 /* create extra LSN dir if it does not exist. */
4827 if (xtrabackup_extra_lsndir
4828 &&!my_stat(xtrabackup_extra_lsndir,&stat_info,MYF(0))
4829 && (my_mkdir(xtrabackup_extra_lsndir,0777,MYF(0)) < 0)) {
4830 msg("xtrabackup: Error: cannot mkdir %d: %s\n",
4831 my_errno(), xtrabackup_extra_lsndir);
4832 exit(EXIT_FAILURE);
4833 }
4834
4835 /* create target dir if not exist */
4836 if (!my_stat(xtrabackup_target_dir,&stat_info,MYF(0))
4837 && (my_mkdir(xtrabackup_target_dir,0777,MYF(0)) < 0)){
4838 msg("xtrabackup: Error: cannot mkdir %d: %s\n",
4839 my_errno(), xtrabackup_target_dir);
4840 exit(EXIT_FAILURE);
4841 }
4842
4843
4844 if (opt_dump_innodb_buffer_pool) {
4845 dump_innodb_buffer_pool(mysql_connection);
4846 }
4847
4848 {
4849 fil_system_t* f_system = fil_system;
4850
4851 /* definition from recv_recovery_from_checkpoint_start() */
4852 log_group_t* max_cp_group;
4853 ulint max_cp_field;
4854 byte* buf;
4855 byte* log_hdr_buf_;
4856 byte* log_hdr_buf;
4857 ulint err;
4858 bool data_copying_error = false;
4859
4860 /* start back ground thread to copy newer log */
4861 os_thread_id_t log_copying_thread_id;
4862 datafiles_iter_t *it;
4863
4864 log_hdr_buf_ = static_cast<byte *>
4865 (ut_malloc_nokey(LOG_FILE_HDR_SIZE + UNIV_PAGE_SIZE_MAX));
4866 log_hdr_buf = static_cast<byte *>
4867 (ut_align(log_hdr_buf_, UNIV_PAGE_SIZE_MAX));
4868
4869 /* get current checkpoint_lsn */
4870 /* Look for the latest checkpoint from any of the log groups */
4871
4872 mutex_enter(&log_sys->mutex);
4873
4874 err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
4875
4876 if (err != DB_SUCCESS) {
4877
4878 ut_free(log_hdr_buf_);
4879 exit(EXIT_FAILURE);
4880 }
4881
4882 log_group_header_read(max_cp_group, max_cp_field);
4883 buf = log_sys->checkpoint_buf;
4884
4885 checkpoint_lsn_start = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
4886 checkpoint_no_start = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
4887
4888 mutex_exit(&log_sys->mutex);
4889
4890 reread_log_header:
4891 fil_io(IORequest(IORequest::READ), true,
4892 page_id_t(max_cp_group->space_id, 0),
4893 univ_page_size,
4894 0, LOG_FILE_HDR_SIZE,
4895 log_hdr_buf, max_cp_group);
4896
4897 /* check consistency of log file header to copy */
4898 mutex_enter(&log_sys->mutex);
4899
4900 err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
4901
4902 if (err != DB_SUCCESS) {
4903
4904 ut_free(log_hdr_buf_);
4905 exit(EXIT_FAILURE);
4906 }
4907
4908 log_group_header_read(max_cp_group, max_cp_field);
4909 buf = log_sys->checkpoint_buf;
4910
4911 if(checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) {
4912
4913 checkpoint_lsn_start = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
4914 checkpoint_no_start = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
4915 mutex_exit(&log_sys->mutex);
4916 goto reread_log_header;
4917 }
4918
4919 mutex_exit(&log_sys->mutex);
4920
4921 xtrabackup_init_datasinks();
4922
4923 if (!select_history()) {
4924 exit(EXIT_FAILURE);
4925 }
4926
4927 /* open the log file */
4928 memset(&stat_info, 0, sizeof(MY_STAT));
4929 dst_log_file = ds_open(ds_redo, XB_LOG_FILENAME, &stat_info);
4930 if (dst_log_file == NULL) {
4931 msg("xtrabackup: error: failed to open the target stream for "
4932 "'%s'.\n", XB_LOG_FILENAME);
4933 ut_free(log_hdr_buf_);
4934 exit(EXIT_FAILURE);
4935 }
4936
4937 /* label it */
4938 strcpy((char*) log_hdr_buf + LOG_HEADER_CREATOR, "xtrabkup ");
4939 ut_sprintf_timestamp(
4940 (char*) log_hdr_buf + (LOG_HEADER_CREATOR
4941 + (sizeof "xtrabkup ") - 1));
4942
4943 if (ds_write(dst_log_file, log_hdr_buf, LOG_FILE_HDR_SIZE)) {
4944 msg("xtrabackup: error: write to logfile failed\n");
4945 ut_free(log_hdr_buf_);
4946 exit(EXIT_FAILURE);
4947 }
4948
4949 ut_free(log_hdr_buf_);
4950
4951 /* start flag */
4952 log_copying = TRUE;
4953
4954 /* start io throttle */
4955 if(xtrabackup_throttle) {
4956 os_thread_id_t io_watching_thread_id;
4957
4958 io_ticket = xtrabackup_throttle;
4959 wait_throttle = os_event_create("wait_throttle");
4960
4961 os_thread_create(io_watching_thread, NULL,
4962 &io_watching_thread_id);
4963 }
4964
4965 mutex_enter(&log_sys->mutex);
4966 xtrabackup_choose_lsn_offset(checkpoint_lsn_start);
4967 mutex_exit(&log_sys->mutex);
4968
4969 if (opt_lock_ddl_per_table) {
4970 mdl_lock_tables();
4971 }
4972
4973 /* copy log file by current position */
4974 if(xtrabackup_copy_logfile(checkpoint_lsn_start, FALSE))
4975 exit(EXIT_FAILURE);
4976
4977 /*
4978 * From this point forward, recv_parse_or_apply_log_rec_body should fail if
4979 * MLOG_INDEX_LOAD event is parsed as its not safe to continue the backup
4980 * in any situation (with or without --lock-ddl-per-table).
4981 */
4982 mdl_taken = true;
4983
4984 log_copying_stop = os_event_create("log_copying_stop");
4985 debug_sync_point("xtrabackup_pause_after_redo_catchup");
4986 os_thread_create(log_copying_thread, NULL, &log_copying_thread_id);
4987
4988 /* Populate fil_system with tablespaces to copy */
4989 err = xb_load_tablespaces();
4990 if (err != DB_SUCCESS) {
4991 msg("xtrabackup: error: xb_load_tablespaces() failed with"
4992 "error code %lu\n", err);
4993 exit(EXIT_FAILURE);
4994 }
4995
4996 /* FLUSH CHANGED_PAGE_BITMAPS call */
4997 if (!flush_changed_page_bitmaps()) {
4998 exit(EXIT_FAILURE);
4999 }
5000 debug_sync_point("xtrabackup_suspend_at_start");
5001
5002 if (xtrabackup_incremental) {
5003 if (!xtrabackup_incremental_force_scan &&
5004 have_changed_page_bitmaps) {
5005 changed_page_bitmap = xb_page_bitmap_init();
5006 }
5007 if (!changed_page_bitmap) {
5008 msg("xtrabackup: using the full scan for incremental "
5009 "backup\n");
5010 } else if (incremental_lsn != checkpoint_lsn_start) {
5011 /* Do not print that bitmaps are used when dummy bitmap
5012 is build for an empty LSN range. */
5013 msg("xtrabackup: using the changed page bitmap\n");
5014 }
5015 }
5016
5017 ut_a(xtrabackup_parallel > 0);
5018
5019 if (xtrabackup_parallel > 1) {
5020 msg("xtrabackup: Starting %u threads for parallel data "
5021 "files transfer\n", xtrabackup_parallel);
5022 }
5023
5024 it = datafiles_iter_new(f_system);
5025 if (it == NULL) {
5026 msg("xtrabackup: Error: datafiles_iter_new() failed.\n");
5027 exit(EXIT_FAILURE);
5028 }
5029
5030 /* Create data copying threads */
5031 data_threads = (data_thread_ctxt_t *)
5032 ut_malloc_nokey(sizeof(data_thread_ctxt_t) *
5033 xtrabackup_parallel);
5034 count = xtrabackup_parallel;
5035 mutex_create(LATCH_ID_XTRA_COUNT_MUTEX, &count_mutex);
5036
5037 for (i = 0; i < (uint) xtrabackup_parallel; i++) {
5038 data_threads[i].it = it;
5039 data_threads[i].num = i+1;
5040 data_threads[i].count = &count;
5041 data_threads[i].count_mutex = &count_mutex;
5042 data_threads[i].error = &data_copying_error;
5043 os_thread_create(data_copy_thread_func, data_threads + i,
5044 &data_threads[i].id);
5045 }
5046
5047 /* Wait for threads to exit */
5048 while (1) {
5049 os_thread_sleep(1000000);
5050 mutex_enter(&count_mutex);
5051 if (count == 0) {
5052 mutex_exit(&count_mutex);
5053 break;
5054 }
5055 mutex_exit(&count_mutex);
5056 }
5057
5058 mutex_free(&count_mutex);
5059 ut_free(data_threads);
5060 datafiles_iter_free(it);
5061
5062 if (data_copying_error) {
5063 exit(EXIT_FAILURE);
5064 }
5065
5066 if (changed_page_bitmap) {
5067 xb_page_bitmap_deinit(changed_page_bitmap);
5068 }
5069 }
5070
5071 if (!backup_start()) {
5072 exit(EXIT_FAILURE);
5073 }
5074 if(opt_lock_ddl_per_table && opt_debug_sleep_before_unlock){
5075 msg_ts("Debug sleep for %u seconds\n",
5076 opt_debug_sleep_before_unlock);
5077 os_thread_sleep(opt_debug_sleep_before_unlock * 1000000);
5078 }
5079 /* read the latest checkpoint lsn */
5080 latest_cp = 0;
5081 {
5082 log_group_t* max_cp_group;
5083 ulint max_cp_field;
5084 ulint err;
5085
5086 mutex_enter(&log_sys->mutex);
5087
5088 err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
5089
5090 if (err != DB_SUCCESS) {
5091 msg("xtrabackup: Error: recv_find_max_checkpoint() failed.\n");
5092 mutex_exit(&log_sys->mutex);
5093 goto skip_last_cp;
5094 }
5095
5096 log_group_header_read(max_cp_group, max_cp_field);
5097
5098 xtrabackup_choose_lsn_offset(checkpoint_lsn_start);
5099
5100 latest_cp = mach_read_from_8(log_sys->checkpoint_buf +
5101 LOG_CHECKPOINT_LSN);
5102
5103 mutex_exit(&log_sys->mutex);
5104
5105 msg("xtrabackup: The latest check point (for incremental): "
5106 "'" LSN_PF "'\n", latest_cp);
5107 }
5108 skip_last_cp:
5109 /* stop log_copying_thread */
5110 log_copying = FALSE;
5111 os_event_set(log_copying_stop);
5112 msg("xtrabackup: Stopping log copying thread.\n");
5113 while (log_copying_running) {
5114 msg(".");
5115 os_thread_sleep(200000); /*0.2 sec*/
5116 }
5117 msg("\n");
5118
5119 os_event_destroy(log_copying_stop);
5120 if (ds_close(dst_log_file)) {
5121 exit(EXIT_FAILURE);
5122 }
5123
5124 if (!validate_missing_encryption_tablespaces()) {
5125 exit(EXIT_FAILURE);
5126 }
5127
5128
5129 if(!xtrabackup_incremental) {
5130 strcpy(metadata_type, "full-backuped");
5131 metadata_from_lsn = 0;
5132 } else {
5133 strcpy(metadata_type, "incremental");
5134 metadata_from_lsn = incremental_lsn;
5135 }
5136 metadata_to_lsn = latest_cp;
5137 metadata_last_lsn = log_copy_scanned_lsn;
5138
5139 if (!xtrabackup_stream_metadata(ds_meta)) {
5140 msg("xtrabackup: Error: failed to stream metadata.\n");
5141 exit(EXIT_FAILURE);
5142 }
5143
5144 if (!backup_finish()) {
5145 exit(EXIT_FAILURE);
5146 }
5147
5148 if (xtrabackup_extra_lsndir) {
5149 char filename[FN_REFLEN];
5150
5151 sprintf(filename, "%s/%s", xtrabackup_extra_lsndir,
5152 XTRABACKUP_METADATA_FILENAME);
5153 if (!xtrabackup_write_metadata(filename)) {
5154 msg("xtrabackup: Error: failed to write metadata "
5155 "to '%s'.\n", filename);
5156 exit(EXIT_FAILURE);
5157 }
5158
5159 sprintf(filename, "%s/%s", xtrabackup_extra_lsndir,
5160 XTRABACKUP_INFO);
5161 if (!xtrabackup_write_info(filename)) {
5162 msg("xtrabackup: Error: failed to write info "
5163 "to '%s'.\n", filename);
5164 exit(EXIT_FAILURE);
5165 }
5166
5167 }
5168
5169 if (opt_lock_ddl_per_table) {
5170 mdl_unlock_all();
5171 }
5172
5173 if (opt_transition_key != NULL || opt_generate_transition_key) {
5174 if (!xb_tablespace_keys_dump(ds_data, opt_transition_key,
5175 opt_transition_key != NULL ?
5176 strlen(opt_transition_key) : 0)) {
5177 msg("xtrabackup: Error: failed to dump "
5178 "tablespace keys.\n");
5179 exit(EXIT_FAILURE);
5180 }
5181 }
5182
5183 xtrabackup_destroy_datasinks();
5184
5185 if (wait_throttle) {
5186 /* wait for io_watching_thread completion */
5187 while (io_watching_thread_running) {
5188 os_thread_sleep(1000000);
5189 }
5190 os_event_destroy(wait_throttle);
5191 wait_throttle = NULL;
5192 }
5193
5194 msg("xtrabackup: Transaction log of lsn (" LSN_PF ") to (" LSN_PF
5195 ") was copied.\n", checkpoint_lsn_start, log_copy_scanned_lsn);
5196 xb_filters_free();
5197
5198 xb_data_files_close();
5199
5200 recv_sys_debug_free();
5201
5202 log_shutdown();
5203
5204 trx_pool_close();
5205
5206 lock_sys_close();
5207
5208 os_thread_free();
5209
5210 row_mysql_close();
5211
5212 sync_check_close();
5213
5214 xb_keyring_shutdown();
5215
5216 /* Make sure that the latest checkpoint made it to xtrabackup_logfile */
5217 if (latest_cp > log_copy_scanned_lsn) {
5218 msg("xtrabackup: error: last checkpoint LSN (" LSN_PF
5219 ") is larger than last copied LSN (" LSN_PF ").\n",
5220 latest_cp, log_copy_scanned_lsn);
5221 exit(EXIT_FAILURE);
5222 }
5223 }
5224
5225 /* ================= stats ================= */
5226 static my_bool
xtrabackup_stats_level(dict_index_t * index,ulint level)5227 xtrabackup_stats_level(
5228 dict_index_t* index,
5229 ulint level)
5230 {
5231 ulint space;
5232 page_t* page;
5233
5234 rec_t* node_ptr;
5235
5236 ulint right_page_no;
5237
5238 page_cur_t cursor;
5239
5240 mtr_t mtr;
5241 mem_heap_t* heap = mem_heap_create(256);
5242
5243 ulint* offsets = NULL;
5244
5245 ulonglong n_pages, n_pages_extern;
5246 ulonglong sum_data, sum_data_extern;
5247 ulonglong n_recs;
5248 buf_block_t* block;
5249 page_size_t page_size(0, 0, false);
5250 bool found;
5251
5252 n_pages = sum_data = n_recs = 0;
5253 n_pages_extern = sum_data_extern = 0;
5254
5255
5256 if (level == 0)
5257 fprintf(stdout, " leaf pages: ");
5258 else
5259 fprintf(stdout, " level %lu pages: ", level);
5260
5261 mtr_start(&mtr);
5262
5263 mtr_x_lock(&(index->lock), &mtr);
5264 block = btr_root_block_get(index, RW_X_LATCH, &mtr);
5265 page = buf_block_get_frame(block);
5266
5267 space = page_get_space_id(page);
5268 page_size.copy_from(fil_space_get_page_size(space, &found));
5269
5270 ut_a(found);
5271
5272 while (level != btr_page_get_level(page, &mtr)) {
5273
5274 ut_a(space == block->page.id.space());
5275 ut_a(space == page_get_space_id(page));
5276 ut_a(!page_is_leaf(page));
5277
5278 page_cur_set_before_first(block, &cursor);
5279 page_cur_move_to_next(&cursor);
5280
5281 node_ptr = page_cur_get_rec(&cursor);
5282 offsets = rec_get_offsets(node_ptr, index, offsets,
5283 ULINT_UNDEFINED, &heap);
5284 block = btr_node_ptr_get_child(node_ptr, index, offsets, &mtr);
5285 page = buf_block_get_frame(block);
5286 }
5287
5288 loop:
5289 mem_heap_empty(heap);
5290 offsets = NULL;
5291 mtr_x_lock(&(index->lock), &mtr);
5292
5293 right_page_no = btr_page_get_next(page, &mtr);
5294
5295
5296 /*=================================*/
5297 //fprintf(stdout, "%lu ", (ulint) buf_frame_get_page_no(page));
5298
5299 n_pages++;
5300 sum_data += page_get_data_size(page);
5301 n_recs += page_get_n_recs(page);
5302
5303
5304 if (level == 0) {
5305 page_cur_t cur;
5306 ulint n_fields;
5307 ulint i;
5308 mem_heap_t* local_heap = NULL;
5309 ulint offsets_[REC_OFFS_NORMAL_SIZE];
5310 ulint* local_offsets = offsets_;
5311
5312 *offsets_ = (sizeof offsets_) / sizeof *offsets_;
5313
5314 page_cur_set_before_first(block, &cur);
5315 page_cur_move_to_next(&cur);
5316
5317 for (;;) {
5318 if (page_cur_is_after_last(&cur)) {
5319 break;
5320 }
5321
5322 local_offsets = rec_get_offsets(cur.rec, index, local_offsets,
5323 ULINT_UNDEFINED, &local_heap);
5324 n_fields = rec_offs_n_fields(local_offsets);
5325
5326 for (i = 0; i < n_fields; i++) {
5327 if (rec_offs_nth_extern(local_offsets, i)) {
5328 page_t* local_page;
5329 ulint space_id;
5330 ulint page_no;
5331 ulint offset;
5332 byte* blob_header;
5333 ulint part_len;
5334 mtr_t local_mtr;
5335 ulint local_len;
5336 byte* data;
5337 buf_block_t* local_block;
5338
5339 data = rec_get_nth_field(cur.rec, local_offsets, i, &local_len);
5340
5341 ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
5342 local_len -= BTR_EXTERN_FIELD_REF_SIZE;
5343
5344 space_id = mach_read_from_4(data + local_len + BTR_EXTERN_SPACE_ID);
5345 page_no = mach_read_from_4(data + local_len + BTR_EXTERN_PAGE_NO);
5346 offset = mach_read_from_4(data + local_len + BTR_EXTERN_OFFSET);
5347
5348 if (offset != FIL_PAGE_DATA)
5349 msg("\nWarning: several record may share same external page.\n");
5350
5351 for (;;) {
5352 mtr_start(&local_mtr);
5353
5354 local_block = btr_block_get(page_id_t(space_id, page_no), page_size, RW_S_LATCH, index, &local_mtr);
5355 local_page = buf_block_get_frame(local_block);
5356 blob_header = local_page + offset;
5357 #define BTR_BLOB_HDR_PART_LEN 0
5358 #define BTR_BLOB_HDR_NEXT_PAGE_NO 4
5359 //part_len = btr_blob_get_part_len(blob_header);
5360 part_len = mach_read_from_4(blob_header + BTR_BLOB_HDR_PART_LEN);
5361
5362 //page_no = btr_blob_get_next_page_no(blob_header);
5363 page_no = mach_read_from_4(blob_header + BTR_BLOB_HDR_NEXT_PAGE_NO);
5364
5365 offset = FIL_PAGE_DATA;
5366
5367
5368
5369
5370 /*=================================*/
5371 //fprintf(stdout, "[%lu] ", (ulint) buf_frame_get_page_no(page));
5372
5373 n_pages_extern++;
5374 sum_data_extern += part_len;
5375
5376
5377 mtr_commit(&local_mtr);
5378
5379 if (page_no == FIL_NULL)
5380 break;
5381 }
5382 }
5383 }
5384
5385 page_cur_move_to_next(&cur);
5386 }
5387 }
5388
5389
5390
5391
5392 mtr_commit(&mtr);
5393 if (right_page_no != FIL_NULL) {
5394 mtr_start(&mtr);
5395 block = btr_block_get(page_id_t(space,
5396 dict_index_get_page(index)),
5397 page_size,
5398 RW_X_LATCH, index, &mtr);
5399 page = buf_block_get_frame(block);
5400 goto loop;
5401 }
5402 mem_heap_free(heap);
5403
5404 if (level == 0)
5405 fprintf(stdout, "recs=%llu, ", n_recs);
5406
5407 fprintf(stdout, "pages=%llu, data=%llu bytes, data/pages=%lld%%",
5408 n_pages, sum_data,
5409 ((sum_data * 100) / page_size.physical()) / n_pages);
5410
5411
5412 if (level == 0 && n_pages_extern) {
5413 putc('\n', stdout);
5414 /* also scan blob pages*/
5415 fprintf(stdout, " external pages: ");
5416
5417 fprintf(stdout, "pages=%llu, data=%llu bytes, data/pages=%lld%%",
5418 n_pages_extern, sum_data_extern,
5419 ((sum_data_extern * 100) / page_size.physical())
5420 / n_pages_extern);
5421 }
5422
5423 putc('\n', stdout);
5424
5425 if (level > 0) {
5426 xtrabackup_stats_level(index, level - 1);
5427 }
5428
5429 return(TRUE);
5430 }
5431
5432 static void
xtrabackup_stats_func(int argc,char ** argv)5433 xtrabackup_stats_func(int argc, char **argv)
5434 {
5435 ulint n;
5436
5437 /* cd to datadir */
5438
5439 if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
5440 {
5441 msg("xtrabackup: cannot my_setwd %s\n", mysql_real_data_home);
5442 exit(EXIT_FAILURE);
5443 }
5444 msg("xtrabackup: cd to %s\n", mysql_real_data_home);
5445
5446 mysql_data_home= mysql_data_home_buff;
5447 mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
5448 mysql_data_home[1]=0;
5449
5450 /* set read only */
5451 srv_read_only_mode = TRUE;
5452
5453 if (!xb_keyring_init_for_stats(argc, argv)) {
5454 msg("xtrabackup: error: failed to init keyring plugin.\n");
5455 exit(EXIT_FAILURE);
5456 }
5457
5458 /* initialize components */
5459 if(innodb_init_param()) {
5460 exit(EXIT_FAILURE);
5461 }
5462
5463 /* Check if the log files have been created, otherwise innodb_init()
5464 will crash when called with srv_read_only == TRUE */
5465 for (n = 0; n < srv_n_log_files; n++) {
5466 char logname[FN_REFLEN];
5467 bool exists;
5468 os_file_type_t type;
5469
5470 snprintf(logname, sizeof(logname), "%s%c%s%lu",
5471 srv_log_group_home_dir, OS_PATH_SEPARATOR,
5472 "ib_logfile", (ulong) n);
5473 os_normalize_path(logname);
5474
5475 if (!os_file_status(logname, &exists, &type) || !exists ||
5476 type != OS_FILE_TYPE_FILE) {
5477 msg("xtrabackup: Error: "
5478 "Cannot find log file %s.\n", logname);
5479 msg("xtrabackup: Error: "
5480 "to use the statistics feature, you need a "
5481 "clean copy of the database including "
5482 "correctly sized log files, so you need to "
5483 "execute with --prepare twice to use this "
5484 "functionality on a backup.\n");
5485 exit(EXIT_FAILURE);
5486 }
5487 }
5488
5489 msg("xtrabackup: Starting 'read-only' InnoDB instance to gather "
5490 "index statistics.\n"
5491 "xtrabackup: Using %lld bytes for buffer pool (set by "
5492 "--use-memory parameter)\n", xtrabackup_use_memory);
5493
5494 if(innodb_init())
5495 exit(EXIT_FAILURE);
5496
5497 xb_filters_init();
5498
5499 fprintf(stdout, "\n\n<INDEX STATISTICS>\n");
5500
5501 /* gather stats */
5502
5503 {
5504 dict_table_t* sys_tables;
5505 dict_index_t* sys_index;
5506 dict_table_t* table;
5507 btr_pcur_t pcur;
5508 rec_t* rec;
5509 byte* field;
5510 ulint len;
5511 mtr_t mtr;
5512
5513 /* Enlarge the fatal semaphore wait timeout during the InnoDB table
5514 monitor printout */
5515
5516 os_atomic_increment_ulint(
5517 &srv_fatal_semaphore_wait_threshold,
5518 72000);
5519
5520 mutex_enter(&(dict_sys->mutex));
5521
5522 mtr_start(&mtr);
5523
5524 sys_tables = dict_table_get_low("SYS_TABLES");
5525 sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
5526
5527 btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
5528 TRUE, 0, &mtr);
5529 loop:
5530 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
5531
5532 rec = btr_pcur_get_rec(&pcur);
5533
5534 if (!btr_pcur_is_on_user_rec(&pcur))
5535 {
5536 /* end of index */
5537
5538 btr_pcur_close(&pcur);
5539 mtr_commit(&mtr);
5540
5541 mutex_exit(&(dict_sys->mutex));
5542
5543 /* Restore the fatal semaphore wait timeout */
5544 os_atomic_increment_ulint(
5545 &srv_fatal_semaphore_wait_threshold,
5546 -72000);
5547
5548 goto end;
5549 }
5550
5551 field = rec_get_nth_field_old(rec, 0, &len);
5552
5553 if (!rec_get_deleted_flag(rec, 0)) {
5554
5555 /* We found one */
5556
5557 char* table_name = mem_strdupl((char*) field, len);
5558
5559 btr_pcur_store_position(&pcur, &mtr);
5560
5561 mtr_commit(&mtr);
5562
5563 table = dict_table_get_low(table_name);
5564 ut_free(table_name);
5565
5566 if (table && check_if_skip_table(table->name.m_name))
5567 goto skip;
5568
5569
5570 if (table == NULL) {
5571 fputs("InnoDB: Failed to load table ", stderr);
5572 ut_print_name(stderr, NULL, (char*) field);
5573 putc('\n', stderr);
5574 } else {
5575 dict_index_t* index;
5576
5577 /* The table definition was corrupt if there
5578 is no index */
5579
5580 if (dict_table_get_first_index(table)) {
5581 dict_stats_update_transient(table);
5582 }
5583
5584 //dict_table_print_low(table);
5585
5586 index = UT_LIST_GET_FIRST(table->indexes);
5587 while (index != NULL) {
5588 {
5589 ib_uint64_t n_vals;
5590 bool found;
5591
5592 if (index->n_user_defined_cols > 0) {
5593 n_vals = index->stat_n_diff_key_vals[
5594 index->n_user_defined_cols];
5595 } else {
5596 n_vals = index->stat_n_diff_key_vals[1];
5597 }
5598
5599 fprintf(stdout,
5600 " table: %s, index: %s, space id: %lu, root page: %lu"
5601 ", zip size: %lu"
5602 "\n estimated statistics in dictionary:\n"
5603 " key vals: %lu, leaf pages: %lu, size pages: %lu\n"
5604 " real statistics:\n",
5605 table->name.m_name, index->name(),
5606 (ulong) index->space,
5607 (ulong) index->page,
5608 (ulong) fil_space_get_page_size(index->space, &found).physical(),
5609 (ulong) n_vals,
5610 (ulong) index->stat_n_leaf_pages,
5611 (ulong) index->stat_index_size);
5612
5613 {
5614 mtr_t local_mtr;
5615 page_t* root;
5616 ulint page_level;
5617
5618 mtr_start(&local_mtr);
5619
5620 mtr_x_lock(&(index->lock), &local_mtr);
5621 root = btr_root_get(index, &local_mtr);
5622 page_level = btr_page_get_level(root, &local_mtr);
5623
5624 xtrabackup_stats_level(index, page_level);
5625
5626 mtr_commit(&local_mtr);
5627 }
5628
5629 putc('\n', stdout);
5630 }
5631 index = UT_LIST_GET_NEXT(indexes, index);
5632 }
5633 }
5634
5635 skip:
5636 mtr_start(&mtr);
5637
5638 btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
5639 }
5640
5641 goto loop;
5642 }
5643
5644 end:
5645 putc('\n', stdout);
5646
5647 fflush(stdout);
5648
5649 xb_filters_free();
5650
5651 /* shutdown InnoDB */
5652 if(innodb_end())
5653 exit(EXIT_FAILURE);
5654
5655 xb_keyring_shutdown();
5656 }
5657
5658 /* ================= prepare ================= */
5659
5660 static
5661 bool
check_log_header_checksum_0(const byte * buf)5662 check_log_header_checksum_0(
5663 /*========================*/
5664 const byte* buf) /*!< in: buffer containing checkpoint info */
5665 {
5666 /** Offset of the first checkpoint checksum */
5667 static const uint CHECKSUM_1 = 288;
5668 /** Offset of the second checkpoint checksum */
5669 static const uint CHECKSUM_2 = CHECKSUM_1 + 4;
5670
5671 if (static_cast<uint32_t>(ut_fold_binary(buf, CHECKSUM_1))
5672 != mach_read_from_4(buf + CHECKSUM_1)
5673 || static_cast<uint32_t>(
5674 ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
5675 CHECKSUM_2 - LOG_CHECKPOINT_LSN))
5676 != mach_read_from_4(buf + CHECKSUM_2)) {
5677 return(false);
5678 }
5679
5680 return(true);
5681 }
5682
5683 static
5684 void
update_log_temp_checkpoint_0(byte * buf,lsn_t lsn)5685 update_log_temp_checkpoint_0(
5686 byte* buf,
5687 lsn_t lsn)
5688 {
5689 /** Offset of the first checkpoint checksum */
5690 static const uint CHECKSUM_1 = 288;
5691 /** Offset of the second checkpoint checksum */
5692 static const uint CHECKSUM_2 = CHECKSUM_1 + 4;
5693 /** Most significant bits of the checkpoint offset */
5694 static const uint OFFSET_HIGH32 = CHECKSUM_2 + 12;
5695 /** Least significant bits of the checkpoint offset */
5696 static const uint OFFSET_LOW32 = 16;
5697
5698 ulint fold;
5699
5700 mach_write_to_8(buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN, lsn);
5701 mach_write_to_4(buf + LOG_CHECKPOINT_1 + OFFSET_LOW32,
5702 LOG_FILE_HDR_SIZE +
5703 (lsn -
5704 ut_uint64_align_down(lsn, OS_FILE_LOG_BLOCK_SIZE)));
5705 mach_write_to_4(buf + LOG_CHECKPOINT_1 + OFFSET_HIGH32, 0);
5706 fold = ut_fold_binary(buf + LOG_CHECKPOINT_1, CHECKSUM_1);
5707 mach_write_to_4(buf + LOG_CHECKPOINT_1 + CHECKSUM_1, fold);
5708
5709 fold = ut_fold_binary(buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN,
5710 CHECKSUM_2 - LOG_CHECKPOINT_LSN);
5711 mach_write_to_4(buf + LOG_CHECKPOINT_1 + CHECKSUM_2, fold);
5712
5713 mach_write_to_8(buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN, lsn);
5714 mach_write_to_4(buf + LOG_CHECKPOINT_2 + OFFSET_LOW32,
5715 LOG_FILE_HDR_SIZE +
5716 (lsn -
5717 ut_uint64_align_down(lsn,
5718 OS_FILE_LOG_BLOCK_SIZE)));
5719 mach_write_to_4(buf + LOG_CHECKPOINT_2
5720 + LOG_CHECKPOINT_OFFSET_HIGH32, 0);
5721 fold = ut_fold_binary(buf + LOG_CHECKPOINT_2, CHECKSUM_1);
5722 mach_write_to_4(buf + LOG_CHECKPOINT_2 + CHECKSUM_1, fold);
5723
5724 fold = ut_fold_binary(buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN,
5725 CHECKSUM_2 - LOG_CHECKPOINT_LSN);
5726 mach_write_to_4(buf + LOG_CHECKPOINT_2 + CHECKSUM_2, fold);
5727 }
5728
5729 static
5730 void
update_log_temp_checkpoint(byte * buf,lsn_t lsn)5731 update_log_temp_checkpoint(
5732 byte* buf,
5733 lsn_t lsn)
5734 {
5735 if (redo_log_version == REDO_LOG_V0) {
5736 update_log_temp_checkpoint_0(buf, lsn);
5737 return;
5738 }
5739
5740 /* Overwrite the both checkpoint area. */
5741
5742 lsn_t lsn_offset;
5743
5744 lsn_offset = LOG_FILE_HDR_SIZE + (lsn -
5745 ut_uint64_align_down(lsn, OS_FILE_LOG_BLOCK_SIZE));
5746
5747 mach_write_to_8(buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN,
5748 lsn);
5749 mach_write_to_8(buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_OFFSET,
5750 lsn_offset);
5751
5752 mach_write_to_8(buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN,
5753 lsn);
5754 mach_write_to_8(buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_OFFSET,
5755 lsn_offset);
5756
5757 log_block_set_checksum(buf, log_block_calc_checksum_crc32(buf));
5758 log_block_set_checksum(buf + LOG_CHECKPOINT_1,
5759 log_block_calc_checksum_crc32(buf + LOG_CHECKPOINT_1));
5760 log_block_set_checksum(buf + LOG_CHECKPOINT_2,
5761 log_block_calc_checksum_crc32(buf + LOG_CHECKPOINT_2));
5762 }
5763
5764 static my_bool
xtrabackup_init_temp_log(void)5765 xtrabackup_init_temp_log(void)
5766 {
5767 pfs_os_file_t src_file = XB_FILE_UNDEFINED;
5768 char src_path[FN_REFLEN];
5769 char dst_path[FN_REFLEN];
5770 bool success;
5771
5772 ulint field;
5773 byte *log_buf;
5774
5775 ib_uint64_t file_size;
5776
5777 lsn_t max_no;
5778 lsn_t max_lsn;
5779 lsn_t checkpoint_no;
5780
5781 bool checkpoint_found;
5782
5783 IORequest read_request(IORequest::READ);
5784 IORequest write_request(IORequest::WRITE);
5785
5786 max_no = 0;
5787
5788 log_buf = static_cast<byte*>(ut_malloc_nokey(UNIV_PAGE_SIZE_MAX * 128));
5789 if (log_buf == NULL) {
5790 goto error;
5791 }
5792
5793 if (!xb_init_log_block_size()) {
5794 goto error;
5795 }
5796
5797 if(!xtrabackup_incremental_dir) {
5798 sprintf(dst_path, "%s/ib_logfile0", xtrabackup_target_dir);
5799 sprintf(src_path, "%s/%s", xtrabackup_target_dir,
5800 XB_LOG_FILENAME);
5801 } else {
5802 sprintf(dst_path, "%s/ib_logfile0", xtrabackup_incremental_dir);
5803 sprintf(src_path, "%s/%s", xtrabackup_incremental_dir,
5804 XB_LOG_FILENAME);
5805 }
5806
5807 os_normalize_path(dst_path);
5808 os_normalize_path(src_path);
5809 retry:
5810 src_file = os_file_create_simple_no_error_handling(0, src_path,
5811 OS_FILE_OPEN,
5812 OS_FILE_READ_WRITE,
5813 srv_read_only_mode,
5814 &success);
5815 if (!success) {
5816 /* The following call prints an error message */
5817 os_file_get_last_error(TRUE);
5818
5819 msg("xtrabackup: Warning: cannot open %s. will try to find.\n",
5820 src_path);
5821
5822 /* check if ib_logfile0 may be xtrabackup_logfile */
5823 src_file = os_file_create_simple_no_error_handling(0, dst_path,
5824 OS_FILE_OPEN,
5825 OS_FILE_READ_WRITE,
5826 srv_read_only_mode,
5827 &success);
5828 if (!success) {
5829 os_file_get_last_error(TRUE);
5830 msg(" xtrabackup: Fatal error: cannot find %s.\n",
5831 src_path);
5832
5833 goto error;
5834 }
5835
5836 success = os_file_read(read_request, src_file, log_buf, 0,
5837 LOG_FILE_HDR_SIZE);
5838 if (!success) {
5839 goto error;
5840 }
5841
5842 if (ut_memcmp(log_buf + LOG_HEADER_CREATOR, (byte*)"xtrabkup",
5843 (sizeof "xtrabkup") - 1) == 0) {
5844 msg(" xtrabackup: 'ib_logfile0' seems to be "
5845 "'xtrabackup_logfile'. will retry.\n");
5846
5847 os_file_close(src_file);
5848 src_file = XB_FILE_UNDEFINED;
5849
5850 /* rename and try again */
5851 success = os_file_rename(0, dst_path, src_path);
5852 if (!success) {
5853 goto error;
5854 }
5855
5856 goto retry;
5857 }
5858
5859 msg(" xtrabackup: Fatal error: cannot find %s.\n",
5860 src_path);
5861
5862 os_file_close(src_file);
5863 src_file = XB_FILE_UNDEFINED;
5864
5865 goto error;
5866 }
5867
5868 file_size = os_file_get_size(src_file);
5869
5870
5871 /* TODO: We should skip the following modifies, if it is not the first time. */
5872
5873 /* read log file header */
5874 success = os_file_read(read_request, src_file, log_buf, 0,
5875 LOG_FILE_HDR_SIZE);
5876 if (!success) {
5877 goto error;
5878 }
5879
5880 if (ut_memcmp(log_buf + LOG_HEADER_CREATOR, (byte *)"xtrabkup",
5881 (sizeof "xtrabkup") - 1) != 0) {
5882 if (xtrabackup_incremental_dir) {
5883 msg("xtrabackup: error: xtrabackup_logfile was already used "
5884 "to '--prepare'.\n");
5885 goto error;
5886 }
5887 msg("xtrabackup: notice: xtrabackup_logfile was already used "
5888 "to '--prepare'.\n");
5889 goto skip_modify;
5890 }
5891
5892 checkpoint_found = false;
5893
5894 /* read last checkpoint lsn */
5895 for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2;
5896 field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) {
5897
5898 /* InnoDB using CRC32 by default since 5.7.9+ */
5899 if (log_block_get_checksum(log_buf + field)
5900 == log_block_calc_checksum_crc32(log_buf + field) &&
5901 mach_read_from_4(log_buf + LOG_HEADER_FORMAT)
5902 == LOG_HEADER_FORMAT_CURRENT) {
5903 redo_log_version = REDO_LOG_V1;
5904 if (!innodb_log_checksum_algorithm_specified) {
5905 srv_log_checksum_algorithm =
5906 SRV_CHECKSUM_ALGORITHM_CRC32;
5907 }
5908 if (!innodb_checksum_algorithm_specified) {
5909 srv_checksum_algorithm =
5910 SRV_CHECKSUM_ALGORITHM_CRC32;
5911 }
5912 } else if (check_log_header_checksum_0(log_buf + field)) {
5913 redo_log_version = REDO_LOG_V0;
5914 if (!innodb_log_checksum_algorithm_specified) {
5915 srv_log_checksum_algorithm =
5916 SRV_CHECKSUM_ALGORITHM_INNODB;
5917 }
5918 if (!innodb_checksum_algorithm_specified) {
5919 srv_checksum_algorithm =
5920 SRV_CHECKSUM_ALGORITHM_INNODB;
5921 }
5922 } else {
5923 goto not_consistent;
5924 }
5925
5926 checkpoint_no = mach_read_from_8(log_buf + field +
5927 LOG_CHECKPOINT_NO);
5928
5929 if (checkpoint_no >= max_no) {
5930
5931 max_no = checkpoint_no;
5932 max_lsn = mach_read_from_8(log_buf + field +
5933 LOG_CHECKPOINT_LSN);
5934 checkpoint_found = true;
5935 }
5936 not_consistent:
5937 ;
5938 }
5939
5940 if (!checkpoint_found) {
5941 msg("xtrabackup: No valid checkpoint found.\n");
5942 goto error;
5943 }
5944
5945 mach_write_to_4(log_buf + LOG_HEADER_FORMAT,
5946 redo_log_version == REDO_LOG_V0 ?
5947 0 : LOG_HEADER_FORMAT_CURRENT);
5948 update_log_temp_checkpoint(log_buf, max_lsn);
5949
5950 success = os_file_write(write_request, src_path, src_file, log_buf, 0,
5951 LOG_FILE_HDR_SIZE);
5952 if (!success) {
5953 goto error;
5954 }
5955
5956 /* expand file size (9/8) and align to UNIV_PAGE_SIZE_MAX */
5957
5958 if (file_size % UNIV_PAGE_SIZE_MAX) {
5959 ulint n = UNIV_PAGE_SIZE_MAX -
5960 (ulint) (file_size % UNIV_PAGE_SIZE_MAX);
5961 memset(log_buf, 0, UNIV_PAGE_SIZE_MAX);
5962 success = os_file_write(write_request, src_path, src_file,
5963 log_buf, file_size, n);
5964 if (!success) {
5965 goto error;
5966 }
5967
5968 file_size = os_file_get_size(src_file);
5969 }
5970
5971 /* TODO: We should judge whether the file is already expanded or not... */
5972 {
5973 ulint expand;
5974
5975 memset(log_buf, 0, UNIV_PAGE_SIZE_MAX * 128);
5976 expand = (ulint) (file_size / UNIV_PAGE_SIZE_MAX / 8);
5977
5978 for (; expand > 128; expand -= 128) {
5979 success = os_file_write(write_request, src_path,
5980 src_file, log_buf,
5981 file_size,
5982 UNIV_PAGE_SIZE_MAX * 128);
5983 if (!success) {
5984 goto error;
5985 }
5986 file_size += UNIV_PAGE_SIZE_MAX * 128;
5987 }
5988
5989 if (expand) {
5990 success = os_file_write(write_request, src_path,
5991 src_file, log_buf,
5992 file_size,
5993 expand * UNIV_PAGE_SIZE_MAX);
5994 if (!success) {
5995 goto error;
5996 }
5997 file_size += UNIV_PAGE_SIZE_MAX * expand;
5998 }
5999 }
6000
6001 /* make larger than 128 * UNIV_PAGE_SIZE_MAX */
6002 if (file_size < 128 * UNIV_PAGE_SIZE_MAX) {
6003 memset(log_buf, 0, UNIV_PAGE_SIZE_MAX);
6004 while (file_size < 128 * UNIV_PAGE_SIZE_MAX) {
6005 success = os_file_write(write_request, src_path,
6006 src_file, log_buf,
6007 file_size,
6008 UNIV_PAGE_SIZE_MAX);
6009 if (!success) {
6010 goto error;
6011 }
6012 file_size += UNIV_PAGE_SIZE_MAX;
6013 }
6014 file_size = os_file_get_size(src_file);
6015 }
6016
6017 msg("xtrabackup: xtrabackup_logfile detected: size=" UINT64PF ", "
6018 "start_lsn=(" LSN_PF ")\n", file_size, max_lsn);
6019
6020 os_file_close(src_file);
6021 src_file = XB_FILE_UNDEFINED;
6022
6023 /* fake InnoDB */
6024 innobase_log_files_in_group_save = innobase_log_files_in_group;
6025 srv_log_group_home_dir_save = srv_log_group_home_dir;
6026 innobase_log_file_size_save = innobase_log_file_size;
6027
6028 srv_log_group_home_dir = NULL;
6029 innobase_log_file_size = file_size;
6030 innobase_log_files_in_group = 1;
6031
6032 srv_thread_concurrency = 0;
6033
6034 /* rename 'xtrabackup_logfile' to 'ib_logfile0' */
6035 success = os_file_rename(0, src_path, dst_path);
6036 if (!success) {
6037 goto error;
6038 }
6039 xtrabackup_logfile_is_renamed = TRUE;
6040
6041 if (log_buf != NULL) {
6042 ut_free(log_buf);
6043 }
6044
6045 return(FALSE);
6046
6047 skip_modify:
6048 if (log_buf != NULL) {
6049 ut_free(log_buf);
6050 }
6051 os_file_close(src_file);
6052 src_file = XB_FILE_UNDEFINED;
6053 return(FALSE);
6054
6055 error:
6056 if (log_buf != NULL) {
6057 ut_free(log_buf);
6058 }
6059 if (src_file != XB_FILE_UNDEFINED)
6060 os_file_close(src_file);
6061 msg("xtrabackup: Error: xtrabackup_init_temp_log() failed.\n");
6062 return(TRUE); /*ERROR*/
6063 }
6064
6065 /***********************************************************************
6066 Generates path to the meta file path from a given path to an incremental .delta
6067 by replacing trailing ".delta" with ".meta", or returns error if 'delta_path'
6068 does not end with the ".delta" character sequence.
6069 @return TRUE on success, FALSE on error. */
6070 static
6071 ibool
get_meta_path(const char * delta_path,char * meta_path)6072 get_meta_path(
6073 const char *delta_path, /* in: path to a .delta file */
6074 char *meta_path) /* out: path to the corresponding .meta
6075 file */
6076 {
6077 size_t len = strlen(delta_path);
6078
6079 if (len <= 6 || strcmp(delta_path + len - 6, ".delta")) {
6080 return FALSE;
6081 }
6082 memcpy(meta_path, delta_path, len - 6);
6083 strcpy(meta_path + len - 6, XB_DELTA_INFO_SUFFIX);
6084
6085 return TRUE;
6086 }
6087
6088 /****************************************************************//**
6089 Create a new tablespace on disk and return the handle to its opened
6090 file. Code adopted from fiL_ibd_create with
6091 the main difference that only disk file is created without updating
6092 the InnoDB in-memory dictionary data structures.
6093
6094 @return TRUE on success, FALSE on error. */
6095 static
6096 bool
xb_space_create_file(const char * path,ulint space_id,ulint flags,pfs_os_file_t * file)6097 xb_space_create_file(
6098 /*==================*/
6099 const char* path, /*!<in: path to tablespace */
6100 ulint space_id, /*!<in: space id */
6101 ulint flags __attribute__((unused)),/*!<in: tablespace
6102 flags */
6103 pfs_os_file_t* file) /*!<out: file handle */
6104 {
6105 const ulint size = FIL_IBD_FILE_INITIAL_SIZE;
6106 dberr_t err;
6107 byte* buf2;
6108 byte* page;
6109 bool success;
6110
6111 IORequest write_request(IORequest::WRITE);
6112
6113 ut_ad(!is_system_tablespace(space_id));
6114 ut_ad(!srv_read_only_mode);
6115 ut_a(space_id < SRV_LOG_SPACE_FIRST_ID);
6116 ut_a(fsp_flags_is_valid(flags));
6117
6118 /* Create the subdirectories in the path, if they are
6119 not there already. */
6120 err = os_file_create_subdirs_if_needed(path);
6121 if (err != DB_SUCCESS) {
6122 return(false);
6123 }
6124
6125 *file = os_file_create(
6126 innodb_data_file_key, path,
6127 OS_FILE_CREATE | OS_FILE_ON_ERROR_NO_EXIT,
6128 OS_FILE_NORMAL,
6129 OS_DATA_FILE,
6130 srv_read_only_mode,
6131 &success);
6132
6133 if (!success) {
6134 /* The following call will print an error message */
6135 ulint error = os_file_get_last_error(true);
6136
6137 ib::error() << "Cannot create file '" << path << "'";
6138
6139 if (error == OS_FILE_ALREADY_EXISTS) {
6140 ib::error() << "The file '" << path << "'"
6141 " already exists though the"
6142 " corresponding table did not exist"
6143 " in the InnoDB data dictionary."
6144 " Have you moved InnoDB .ibd files"
6145 " around without using the SQL commands"
6146 " DISCARD TABLESPACE and IMPORT TABLESPACE,"
6147 " or did mysqld crash in the middle of"
6148 " CREATE TABLE?"
6149 " You can resolve the problem by removing"
6150 " the file '" << path
6151 << "' under the 'datadir' of MySQL.";
6152
6153 return(false);
6154 }
6155
6156 return(false);
6157 }
6158
6159
6160 #if !defined(NO_FALLOCATE) && defined(UNIV_LINUX)
6161 if (fil_fusionio_enable_atomic_write(*file)) {
6162
6163 /* This is required by FusionIO HW/Firmware */
6164 int ret = posix_fallocate(file->m_file, 0, size * UNIV_PAGE_SIZE);
6165
6166 if (ret != 0) {
6167
6168 ib::error() <<
6169 "posix_fallocate(): Failed to preallocate"
6170 " data for file " << path
6171 << ", desired size "
6172 << size * UNIV_PAGE_SIZE
6173 << " Operating system error number " << ret
6174 << ". Check"
6175 " that the disk is not full or a disk quota"
6176 " exceeded. Make sure the file system supports"
6177 " this function. Some operating system error"
6178 " numbers are described at " REFMAN
6179 " operating-system-error-codes.html";
6180
6181 success = false;
6182 } else {
6183 success = true;
6184 }
6185 } else {
6186
6187 success = os_file_set_size(
6188 path, *file, size * UNIV_PAGE_SIZE, srv_read_only_mode);
6189 }
6190 #else
6191 success = os_file_set_size(
6192 path, *file, size * UNIV_PAGE_SIZE, srv_read_only_mode);
6193 #endif /* !NO_FALLOCATE && UNIV_LINUX */
6194
6195 if (!success) {
6196 os_file_close(*file);
6197 os_file_delete(innodb_data_file_key, path);
6198 return(false);
6199 }
6200
6201 /* printf("Creating tablespace %s id %lu\n", path, space_id); */
6202
6203 /* We have to write the space id to the file immediately and flush the
6204 file to disk. This is because in crash recovery we must be aware what
6205 tablespaces exist and what are their space id's, so that we can apply
6206 the log records to the right file. It may take quite a while until
6207 buffer pool flush algorithms write anything to the file and flush it to
6208 disk. If we would not write here anything, the file would be filled
6209 with zeros from the call of os_file_set_size(), until a buffer pool
6210 flush would write to it. */
6211
6212 buf2 = static_cast<byte*>(ut_malloc_nokey(3 * UNIV_PAGE_SIZE));
6213 /* Align the memory for file i/o if we might have O_DIRECT set */
6214 page = static_cast<byte*>(ut_align(buf2, UNIV_PAGE_SIZE));
6215
6216 memset(page, '\0', UNIV_PAGE_SIZE);
6217
6218 /* Add the UNIV_PAGE_SIZE to the table flags and write them to the
6219 tablespace header. */
6220 flags = fsp_flags_set_page_size(flags, univ_page_size);
6221 fsp_header_init_fields(page, space_id, flags);
6222 mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
6223
6224 const page_size_t page_size(flags);
6225
6226 if (!page_size.is_compressed()) {
6227 buf_flush_init_for_writing(
6228 NULL, page, NULL, 0,
6229 fsp_is_checksum_disabled(space_id));
6230 success = os_file_write(write_request, path, *file, page, 0,
6231 page_size.physical());
6232 } else {
6233 page_zip_des_t page_zip;
6234
6235 page_zip_set_size(&page_zip, page_size.physical());
6236 page_zip.data = page + UNIV_PAGE_SIZE;
6237 #ifdef UNIV_DEBUG
6238 page_zip.m_start =
6239 #endif /* UNIV_DEBUG */
6240 page_zip.m_end = page_zip.m_nonempty =
6241 page_zip.n_blobs = 0;
6242
6243 buf_flush_init_for_writing(
6244 NULL, page, &page_zip, 0,
6245 fsp_is_checksum_disabled(space_id));
6246 success = os_file_write(write_request, path, *file,
6247 page_zip.data, 0,
6248 page_size.physical());
6249 }
6250
6251 ut_free(buf2);
6252
6253 if (!success) {
6254 ib::error() << "Could not write the first page to"
6255 << " tablespace '" << path << "'";
6256 os_file_close(*file);
6257 os_file_delete(innodb_data_file_key, path);
6258 return(false);
6259 }
6260
6261 success = os_file_flush(*file);
6262
6263 if (!success) {
6264 ib::error() << "File flush of tablespace '"
6265 << path << "' failed";
6266 os_file_close(*file);
6267 os_file_delete(innodb_data_file_key, path);
6268 return(false);
6269 }
6270
6271 return(true);
6272 }
6273
6274 /***********************************************************************
6275 Searches for matching tablespace file for given .delta file and space_id
6276 in given directory. When matching tablespace found, renames it to match the
6277 name of .delta file. If there was a tablespace with matching name and
6278 mismatching ID, renames it to xtrabackup_tmp_#ID.ibd. If there was no
6279 matching file, creates a new tablespace.
6280 @return file handle of matched or created file */
6281 static
6282 pfs_os_file_t
xb_delta_open_matching_space(const char * dbname,const char * name,ulint space_id,ulint space_flags,ulint zip_size,char * real_name,size_t real_name_len,bool * success)6283 xb_delta_open_matching_space(
6284 const char* dbname, /* in: path to destination database dir */
6285 const char* name, /* in: name of delta file (without .delta) */
6286 ulint space_id, /* in: space id of delta file */
6287 ulint space_flags, /* in: space flags of delta file */
6288 ulint zip_size, /* in: zip_size of tablespace */
6289 char* real_name, /* out: full path of destination file */
6290 size_t real_name_len, /* out: buffer size for real_name */
6291 bool* success) /* out: indicates error. TRUE = success */
6292 {
6293 char dest_dir[FN_REFLEN];
6294 char dest_space_name[FN_REFLEN];
6295 bool ok;
6296 fil_space_t* fil_space;
6297 pfs_os_file_t file = XB_FILE_UNDEFINED;
6298 xb_filter_entry_t* table;
6299
6300 *success = false;
6301
6302 if (dbname) {
6303 snprintf(dest_dir, FN_REFLEN, "%s/%s",
6304 xtrabackup_target_dir, dbname);
6305 os_normalize_path(dest_dir);
6306
6307 snprintf(dest_space_name, FN_REFLEN, "%s/%s", dbname, name);
6308 } else {
6309 snprintf(dest_dir, FN_REFLEN, "%s", xtrabackup_target_dir);
6310 os_normalize_path(dest_dir);
6311
6312 snprintf(dest_space_name, FN_REFLEN, "%s", name);
6313 }
6314
6315 snprintf(real_name, real_name_len,
6316 "%s/%s",
6317 xtrabackup_target_dir, dest_space_name);
6318 os_normalize_path(real_name);
6319 /* Truncate ".ibd" */
6320 dest_space_name[strlen(dest_space_name) - 4] = '\0';
6321
6322 /* Create the database directory if it doesn't exist yet */
6323 if (!os_file_create_directory(dest_dir, FALSE)) {
6324 msg("xtrabackup: error: cannot create dir %s\n", dest_dir);
6325 return file;
6326 }
6327
6328 if (space_id != ULINT_UNDEFINED
6329 && !fil_is_user_tablespace_id(space_id)) {
6330 goto found;
6331 }
6332
6333 /* remember space name for further reference */
6334 table = static_cast<xb_filter_entry_t *>
6335 (ut_malloc_nokey(sizeof(xb_filter_entry_t) +
6336 strlen(dest_space_name) + 1));
6337
6338 table->name = ((char*)table) + sizeof(xb_filter_entry_t);
6339 strcpy(table->name, dest_space_name);
6340 HASH_INSERT(xb_filter_entry_t, name_hash, inc_dir_tables_hash,
6341 ut_fold_string(table->name), table);
6342
6343 mutex_enter(&fil_system->mutex);
6344 fil_space = fil_space_get_by_name(dest_space_name);
6345 mutex_exit(&fil_system->mutex);
6346
6347 if (fil_space != NULL) {
6348 if (fil_space->id == space_id || space_id == ULINT_UNDEFINED) {
6349 /* we found matching space */
6350 goto found;
6351 } else {
6352
6353 char tmpname[FN_REFLEN];
6354 char *oldpath;
6355 bool exists;
6356 os_file_type_t type;
6357
6358 if (dbname != NULL) {
6359 snprintf(tmpname, FN_REFLEN,
6360 "%s/xtrabackup_tmp_#%lu",
6361 dbname, fil_space->id);
6362 } else {
6363 snprintf(tmpname, FN_REFLEN,
6364 "./xtrabackup_tmp_#%lu",
6365 fil_space->id);
6366 }
6367
6368 oldpath = mem_strdup(
6369 UT_LIST_GET_FIRST(fil_space->chain)->name);
6370
6371 msg("xtrabackup: Renaming %s to %s.ibd\n",
6372 fil_space->name, tmpname);
6373
6374
6375 ut_a(os_file_status(oldpath, &exists, &type));
6376
6377 if (exists && !fil_rename_tablespace(fil_space->id,
6378 oldpath, tmpname, NULL))
6379 {
6380 msg("xtrabackup: Cannot rename %s to %s\n",
6381 fil_space->name, tmpname);
6382 ut_free(oldpath);
6383 goto exit;
6384 }
6385 ut_free(oldpath);
6386 }
6387 }
6388
6389 if (space_id == ULINT_UNDEFINED)
6390 {
6391 msg("xtrabackup: Error: Cannot handle DDL operation on "
6392 "tablespace %s\n", dest_space_name);
6393 exit(EXIT_FAILURE);
6394 }
6395 mutex_enter(&fil_system->mutex);
6396 fil_space = fil_space_get_by_id(space_id);
6397 mutex_exit(&fil_system->mutex);
6398 if (fil_space != NULL) {
6399 char tmpname[FN_REFLEN];
6400 char *oldpath;
6401 bool exists;
6402 os_file_type_t type;
6403
6404 strncpy(tmpname, dest_space_name, FN_REFLEN);
6405
6406 oldpath = mem_strdup(UT_LIST_GET_FIRST(fil_space->chain)->name);
6407
6408 msg("xtrabackup: Renaming %s to %s\n",
6409 fil_space->name, dest_space_name);
6410
6411 ut_a(os_file_status(oldpath, &exists, &type));
6412
6413 if (exists && !fil_rename_tablespace(fil_space->id, oldpath,
6414 tmpname, NULL))
6415 {
6416 msg("xtrabackup: Cannot rename %s to %s\n",
6417 fil_space->name, dest_space_name);
6418 ut_free(oldpath);
6419 goto exit;
6420 }
6421 ut_free(oldpath);
6422
6423 goto found;
6424 }
6425
6426 /* No matching space found. create the new one. */
6427
6428 if (!fil_space_create(dest_space_name, space_id, space_flags,
6429 FIL_TYPE_TABLESPACE)) {
6430 msg("xtrabackup: Cannot create tablespace %s\n",
6431 dest_space_name);
6432 goto exit;
6433 }
6434
6435 /* Calculate correct tablespace flags for compressed tablespaces. */
6436 if (zip_size != 0 && zip_size != ULINT_UNDEFINED) {
6437 space_flags
6438 |= (get_bit_shift(zip_size >> PAGE_ZIP_MIN_SIZE_SHIFT
6439 << 1)
6440 << DICT_TF_ZSSIZE_SHIFT)
6441 | DICT_TF_COMPACT
6442 | (DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT);
6443 ut_a(page_size_t(space_flags).physical() == zip_size);
6444 }
6445 *success = xb_space_create_file(real_name, space_id, space_flags,
6446 &file);
6447 goto exit;
6448
6449 found:
6450 /* open the file and return it's handle */
6451
6452 file = os_file_create_simple_no_error_handling(0, real_name,
6453 OS_FILE_OPEN,
6454 OS_FILE_READ_WRITE,
6455 srv_read_only_mode,
6456 &ok);
6457
6458 if (ok) {
6459 *success = true;
6460 } else {
6461 msg("xtrabackup: Cannot open file %s\n", real_name);
6462 }
6463
6464 exit:
6465
6466 return file;
6467 }
6468
6469 /************************************************************************
6470 Applies a given .delta file to the corresponding data file.
6471 @return TRUE on success */
6472 static
6473 ibool
xtrabackup_apply_delta(const char * dirname,const char * dbname,const char * filename,void *)6474 xtrabackup_apply_delta(
6475 const char* dirname, /* in: dir name of incremental */
6476 const char* dbname, /* in: database name (ibdata: NULL) */
6477 const char* filename, /* in: file name (not a path),
6478 including the .delta extension */
6479 void* /*data*/)
6480 {
6481 pfs_os_file_t src_file = XB_FILE_UNDEFINED;
6482 pfs_os_file_t dst_file = XB_FILE_UNDEFINED;
6483 char src_path[FN_REFLEN * 2 + 2];
6484 char dst_path[FN_REFLEN * 2 + 2];
6485 char meta_path[FN_REFLEN];
6486 char space_name[FN_REFLEN];
6487 bool success;
6488
6489 ibool last_buffer = FALSE;
6490 ulint page_in_buffer;
6491 ulint incremental_buffers = 0;
6492
6493 xb_delta_info_t info;
6494 ulint page_size;
6495 ulint page_size_shift;
6496 byte* incremental_buffer_base = NULL;
6497 byte* incremental_buffer;
6498
6499 size_t offset;
6500
6501 IORequest read_request(IORequest::READ);
6502 IORequest write_request(IORequest::WRITE);
6503
6504 ut_a(xtrabackup_incremental);
6505
6506 if (dbname) {
6507 snprintf(src_path, sizeof(src_path), "%s/%s/%s",
6508 dirname, dbname, filename);
6509 snprintf(dst_path, sizeof(dst_path), "%s/%s/%s",
6510 xtrabackup_real_target_dir, dbname, filename);
6511 } else {
6512 snprintf(src_path, sizeof(src_path), "%s/%s",
6513 dirname, filename);
6514 snprintf(dst_path, sizeof(dst_path), "%s/%s",
6515 xtrabackup_real_target_dir, filename);
6516 }
6517 dst_path[strlen(dst_path) - 6] = '\0';
6518
6519 strncpy(space_name, filename, FN_REFLEN);
6520 space_name[strlen(space_name) - 6] = 0;
6521
6522 if (!get_meta_path(src_path, meta_path)) {
6523 goto error;
6524 }
6525
6526 os_normalize_path(dst_path);
6527 os_normalize_path(src_path);
6528 os_normalize_path(meta_path);
6529
6530 if (!xb_read_delta_metadata(meta_path, &info)) {
6531 goto error;
6532 }
6533
6534 page_size = info.page_size;
6535 page_size_shift = get_bit_shift(page_size);
6536 msg("xtrabackup: page size for %s is %lu bytes space id is %lu\n",
6537 src_path, page_size, info.space_id);
6538 if (page_size_shift < 10 ||
6539 page_size_shift > UNIV_PAGE_SIZE_SHIFT_MAX) {
6540 msg("xtrabackup: error: invalid value of page_size "
6541 "(%lu bytes) read from %s\n", page_size, meta_path);
6542 goto error;
6543 }
6544
6545 src_file = os_file_create_simple_no_error_handling(0, src_path,
6546 OS_FILE_OPEN,
6547 OS_FILE_READ_WRITE,
6548 srv_read_only_mode,
6549 &success);
6550 if (!success) {
6551 os_file_get_last_error(TRUE);
6552 msg("xtrabackup: error: cannot open %s\n", src_path);
6553 goto error;
6554 }
6555
6556 posix_fadvise(src_file.m_file, 0, 0, POSIX_FADV_SEQUENTIAL);
6557
6558 os_file_set_nocache(src_file.m_file, src_path, "OPEN");
6559
6560 dst_file = xb_delta_open_matching_space(dbname, space_name,
6561 info.space_id, info.space_flags,
6562 info.zip_size, dst_path,
6563 sizeof(dst_path), &success);
6564 if (!success) {
6565 msg("xtrabackup: error: cannot open %s\n", dst_path);
6566 goto error;
6567 }
6568
6569 posix_fadvise(dst_file.m_file, 0, 0, POSIX_FADV_DONTNEED);
6570
6571 os_file_set_nocache(dst_file.m_file, dst_path, "OPEN");
6572
6573 /* allocate buffer for incremental backup */
6574 incremental_buffer_base = static_cast<byte *>
6575 (ut_malloc_nokey((page_size / 4 + 1) * page_size +
6576 UNIV_PAGE_SIZE_MAX));
6577 incremental_buffer = static_cast<byte *>
6578 (ut_align(incremental_buffer_base, UNIV_PAGE_SIZE_MAX));
6579
6580 msg("Applying %s to %s...\n", src_path, dst_path);
6581
6582 while (!last_buffer) {
6583 ulint cluster_header;
6584
6585 /* read to buffer */
6586 /* first block of block cluster */
6587 offset = ((incremental_buffers * (page_size / 4))
6588 << page_size_shift);
6589 success = os_file_read(read_request, src_file,
6590 incremental_buffer, offset, page_size);
6591 if (!success) {
6592 goto error;
6593 }
6594
6595 cluster_header = mach_read_from_4(incremental_buffer);
6596 switch(cluster_header) {
6597 case 0x78747261UL: /*"xtra"*/
6598 break;
6599 case 0x58545241UL: /*"XTRA"*/
6600 last_buffer = TRUE;
6601 break;
6602 default:
6603 msg("xtrabackup: error: %s seems not "
6604 ".delta file.\n", src_path);
6605 goto error;
6606 }
6607
6608 for (page_in_buffer = 1; page_in_buffer < page_size / 4;
6609 page_in_buffer++) {
6610 if (mach_read_from_4(incremental_buffer +
6611 page_in_buffer * 4)
6612 == 0xFFFFFFFFUL)
6613 break;
6614 }
6615
6616 ut_a(last_buffer || page_in_buffer == page_size / 4);
6617
6618 /* read whole of the cluster */
6619 success = os_file_read(read_request, src_file,
6620 incremental_buffer, offset,
6621 page_in_buffer * page_size);
6622 if (!success) {
6623 goto error;
6624 }
6625
6626 posix_fadvise(src_file.m_file, offset,
6627 page_in_buffer * page_size,
6628 POSIX_FADV_DONTNEED);
6629
6630 for (page_in_buffer = 1; page_in_buffer < page_size / 4;
6631 page_in_buffer++) {
6632 ulint offset_on_page;
6633
6634 offset_on_page = mach_read_from_4(incremental_buffer +
6635 page_in_buffer * 4);
6636
6637 if (offset_on_page == 0xFFFFFFFFUL)
6638 break;
6639
6640 success = os_file_write(write_request, dst_path,
6641 dst_file,
6642 incremental_buffer +
6643 page_in_buffer * page_size,
6644 (offset_on_page <<
6645 page_size_shift),
6646 page_size);
6647 if (!success) {
6648 goto error;
6649 }
6650 }
6651
6652 incremental_buffers++;
6653 }
6654
6655 if (incremental_buffer_base)
6656 ut_free(incremental_buffer_base);
6657 if (src_file != XB_FILE_UNDEFINED)
6658 os_file_close(src_file);
6659 if (dst_file != XB_FILE_UNDEFINED)
6660 os_file_close(dst_file);
6661 return TRUE;
6662
6663 error:
6664 if (incremental_buffer_base)
6665 ut_free(incremental_buffer_base);
6666 if (src_file != XB_FILE_UNDEFINED)
6667 os_file_close(src_file);
6668 if (dst_file != XB_FILE_UNDEFINED)
6669 os_file_close(dst_file);
6670 msg("xtrabackup: Error: xtrabackup_apply_delta(): "
6671 "failed to apply %s to %s.\n", src_path, dst_path);
6672 return FALSE;
6673 }
6674
6675 /************************************************************************
6676 Callback to handle datadir entry. Function of this type will be called
6677 for each entry which matches the mask by xb_process_datadir.
6678 @return should return TRUE on success */
6679 typedef ibool (*handle_datadir_entry_func_t)(
6680 /*=========================================*/
6681 const char* data_home_dir, /*!<in: path to datadir */
6682 const char* db_name, /*!<in: database name */
6683 const char* file_name, /*!<in: file name with suffix */
6684 void* arg); /*!<in: caller-provided data */
6685
6686 /************************************************************************
6687 Callback to handle datadir entry. Deletes entry if it has no matching
6688 fil_space in fil_system directory.
6689 @return FALSE if delete attempt was unsuccessful */
6690 static
6691 ibool
rm_if_not_found(const char * data_home_dir,const char * db_name,const char * file_name,void * arg)6692 rm_if_not_found(
6693 const char* data_home_dir, /*!<in: path to datadir */
6694 const char* db_name, /*!<in: database name */
6695 const char* file_name, /*!<in: file name with suffix */
6696 void* arg __attribute__((unused)))
6697 {
6698 char name[FN_REFLEN];
6699 xb_filter_entry_t* table;
6700
6701 if (db_name != NULL) {
6702 snprintf(name, FN_REFLEN, "%s/%s", db_name, file_name);
6703 } else {
6704 snprintf(name, FN_REFLEN, "%s", file_name);
6705 }
6706 /* Truncate ".ibd" */
6707 name[strlen(name) - 4] = '\0';
6708
6709 HASH_SEARCH(name_hash, inc_dir_tables_hash, ut_fold_string(name),
6710 xb_filter_entry_t*,
6711 table, (void) 0,
6712 !strcmp(table->name, name));
6713
6714 if (!table) {
6715 if (db_name != NULL) {
6716 snprintf(name, FN_REFLEN, "%s/%s/%s", data_home_dir,
6717 db_name, file_name);
6718 } else {
6719 snprintf(name, FN_REFLEN, "%s/%s", data_home_dir,
6720 file_name);
6721 }
6722 return os_file_delete(0, name);
6723 }
6724
6725 return(TRUE);
6726 }
6727
6728 /************************************************************************
6729 Function enumerates files in datadir (provided by path) which are matched
6730 by provided suffix. For each entry callback is called.
6731 @return FALSE if callback for some entry returned FALSE */
6732 static
6733 ibool
xb_process_datadir(const char * path,const char * suffix,handle_datadir_entry_func_t func,void * data)6734 xb_process_datadir(
6735 const char* path, /*!<in: datadir path */
6736 const char* suffix, /*!<in: suffix to match
6737 against */
6738 handle_datadir_entry_func_t func, /*!<in: callback */
6739 void* data) /*!<in: additional argument for
6740 callback */
6741 {
6742 ulint ret;
6743 char dbpath[FN_REFLEN];
6744 os_file_dir_t dir;
6745 os_file_dir_t dbdir;
6746 os_file_stat_t dbinfo;
6747 os_file_stat_t fileinfo;
6748 ulint suffix_len;
6749 dberr_t err = DB_SUCCESS;
6750 static char current_dir[2];
6751
6752 current_dir[0] = FN_CURLIB;
6753 current_dir[1] = 0;
6754 srv_data_home = current_dir;
6755
6756 suffix_len = strlen(suffix);
6757
6758 /* datafile */
6759 dbdir = os_file_opendir(path, false);
6760
6761 if (dbdir != NULL) {
6762 ret = fil_file_readdir_next_file(&err, path, dbdir,
6763 &fileinfo);
6764 while (ret == 0) {
6765 if (fileinfo.type == OS_FILE_TYPE_DIR) {
6766 goto next_file_item_1;
6767 }
6768
6769 if (strlen(fileinfo.name) > suffix_len
6770 && 0 == strcmp(fileinfo.name +
6771 strlen(fileinfo.name) - suffix_len,
6772 suffix)) {
6773 if (!func(
6774 path, NULL,
6775 fileinfo.name, data))
6776 {
6777 return(FALSE);
6778 }
6779 }
6780 next_file_item_1:
6781 ret = fil_file_readdir_next_file(&err,
6782 path, dbdir,
6783 &fileinfo);
6784 }
6785
6786 os_file_closedir(dbdir);
6787 } else {
6788 msg("xtrabackup: Cannot open dir %s\n",
6789 path);
6790 }
6791
6792 /* single table tablespaces */
6793 dir = os_file_opendir(path, false);
6794
6795 if (dir == NULL) {
6796 msg("xtrabackup: Cannot open dir %s\n",
6797 path);
6798 }
6799
6800 ret = fil_file_readdir_next_file(&err, path, dir,
6801 &dbinfo);
6802 while (ret == 0) {
6803 if (dbinfo.type == OS_FILE_TYPE_FILE
6804 || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
6805
6806 goto next_datadir_item;
6807 }
6808
6809 fn_format(dbpath, dbinfo.name, path, "", MYF(0));
6810 os_normalize_path(dbpath);
6811
6812 dbdir = os_file_opendir(dbpath, false);
6813
6814 if (dbdir != NULL) {
6815
6816 ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
6817 &fileinfo);
6818 while (ret == 0) {
6819
6820 if (fileinfo.type == OS_FILE_TYPE_DIR) {
6821
6822 goto next_file_item_2;
6823 }
6824
6825 if (strlen(fileinfo.name) > suffix_len
6826 && 0 == strcmp(fileinfo.name +
6827 strlen(fileinfo.name) -
6828 suffix_len,
6829 suffix)) {
6830 /* The name ends in suffix; process
6831 the file */
6832 if (!func(
6833 path,
6834 dbinfo.name,
6835 fileinfo.name, data))
6836 {
6837 return(FALSE);
6838 }
6839 }
6840 next_file_item_2:
6841 ret = fil_file_readdir_next_file(&err,
6842 dbpath, dbdir,
6843 &fileinfo);
6844 }
6845
6846 os_file_closedir(dbdir);
6847 }
6848 next_datadir_item:
6849 ret = fil_file_readdir_next_file(&err,
6850 path,
6851 dir, &dbinfo);
6852 }
6853
6854 os_file_closedir(dir);
6855
6856 return(TRUE);
6857 }
6858
6859 /************************************************************************
6860 Applies all .delta files from incremental_dir to the full backup.
6861 @return TRUE on success. */
6862 static
6863 ibool
xtrabackup_apply_deltas()6864 xtrabackup_apply_deltas()
6865 {
6866 return xb_process_datadir(xtrabackup_incremental_dir, ".delta",
6867 xtrabackup_apply_delta, NULL);
6868 }
6869
6870 static my_bool
xtrabackup_close_temp_log(my_bool clear_flag)6871 xtrabackup_close_temp_log(my_bool clear_flag)
6872 {
6873 pfs_os_file_t src_file = XB_FILE_UNDEFINED;
6874 char src_path[FN_REFLEN];
6875 char dst_path[FN_REFLEN];
6876 bool success;
6877 byte log_buf[UNIV_PAGE_SIZE_MAX];
6878 IORequest read_request(IORequest::READ);
6879 IORequest write_request(IORequest::WRITE);
6880
6881 if (!xtrabackup_logfile_is_renamed)
6882 return(FALSE);
6883
6884 /* rename 'ib_logfile0' to 'xtrabackup_logfile' */
6885 if(!xtrabackup_incremental_dir) {
6886 sprintf(dst_path, "%s/ib_logfile0", xtrabackup_target_dir);
6887 sprintf(src_path, "%s/%s", xtrabackup_target_dir,
6888 XB_LOG_FILENAME);
6889 } else {
6890 sprintf(dst_path, "%s/ib_logfile0", xtrabackup_incremental_dir);
6891 sprintf(src_path, "%s/%s", xtrabackup_incremental_dir,
6892 XB_LOG_FILENAME);
6893 }
6894
6895 os_normalize_path(dst_path);
6896 os_normalize_path(src_path);
6897
6898 success = os_file_rename(0, dst_path, src_path);
6899 if (!success) {
6900 goto error;
6901 }
6902 xtrabackup_logfile_is_renamed = FALSE;
6903
6904 if (!clear_flag)
6905 return(FALSE);
6906
6907 /* clear LOG_HEADER_CREATOR field */
6908 src_file = os_file_create_simple_no_error_handling(0, src_path,
6909 OS_FILE_OPEN,
6910 OS_FILE_READ_WRITE,
6911 srv_read_only_mode,
6912 &success);
6913 if (!success) {
6914 goto error;
6915 }
6916
6917 success = os_file_read(read_request, src_file, log_buf, 0,
6918 LOG_FILE_HDR_SIZE);
6919 if (!success) {
6920 goto error;
6921 }
6922
6923 memset(log_buf + LOG_HEADER_CREATOR, ' ', 4);
6924
6925 success = os_file_write(write_request, src_path, src_file, log_buf, 0,
6926 LOG_FILE_HDR_SIZE);
6927 if (!success) {
6928 goto error;
6929 }
6930
6931 // os_file_close(src_file);
6932 src_file = XB_FILE_UNDEFINED;
6933
6934 innobase_log_files_in_group = innobase_log_files_in_group_save;
6935 srv_log_group_home_dir = srv_log_group_home_dir_save;
6936 innobase_log_file_size = innobase_log_file_size_save;
6937
6938 return(FALSE);
6939 error:
6940 if (src_file != XB_FILE_UNDEFINED)
6941 os_file_close(src_file);
6942 msg("xtrabackup: Error: xtrabackup_close_temp_log() failed.\n");
6943 return(TRUE); /*ERROR*/
6944 }
6945
6946
6947 /*********************************************************************//**
6948 Write the meta data (index user fields) config file.
6949 @return true in case of success otherwise false. */
6950 static
6951 bool
xb_export_cfg_write_index_fields(const dict_index_t * index,FILE * file)6952 xb_export_cfg_write_index_fields(
6953 /*===========================*/
6954 const dict_index_t* index, /*!< in: write the meta data for
6955 this index */
6956 FILE* file) /*!< in: file to write to */
6957 {
6958 byte row[sizeof(ib_uint32_t) * 2];
6959
6960 for (ulint i = 0; i < index->n_fields; ++i) {
6961 byte* ptr = row;
6962 const dict_field_t* field = &index->fields[i];
6963
6964 mach_write_to_4(ptr, field->prefix_len);
6965 ptr += sizeof(ib_uint32_t);
6966
6967 mach_write_to_4(ptr, field->fixed_len);
6968
6969 if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
6970
6971 msg("xtrabackup: Error: writing index fields.");
6972
6973 return(false);
6974 }
6975
6976 /* Include the NUL byte in the length. */
6977 ib_uint32_t len = strlen(field->name) + 1;
6978 ut_a(len > 1);
6979
6980 mach_write_to_4(row, len);
6981
6982 if (fwrite(row, 1, sizeof(len), file) != sizeof(len)
6983 || fwrite(field->name, 1, len, file) != len) {
6984
6985 msg("xtrabackup: Error: writing index column.");
6986
6987 return(false);
6988 }
6989 }
6990
6991 return(true);
6992 }
6993
6994 /*********************************************************************//**
6995 Write the meta data config file index information.
6996 @return true in case of success otherwise false. */
6997 static __attribute__((nonnull, warn_unused_result))
6998 bool
xb_export_cfg_write_indexes(const dict_table_t * table,FILE * file)6999 xb_export_cfg_write_indexes(
7000 /*======================*/
7001 const dict_table_t* table, /*!< in: write the meta data for
7002 this table */
7003 FILE* file) /*!< in: file to write to */
7004 {
7005 {
7006 byte row[sizeof(ib_uint32_t)];
7007
7008 /* Write the number of indexes in the table. */
7009 mach_write_to_4(row, UT_LIST_GET_LEN(table->indexes));
7010
7011 if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
7012 msg("xtrabackup: Error: writing index count.");
7013
7014 return(false);
7015 }
7016 }
7017
7018 bool ret = true;
7019
7020 /* Write the index meta data. */
7021 for (const dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
7022 index != 0 && ret;
7023 index = UT_LIST_GET_NEXT(indexes, index)) {
7024
7025 byte* ptr;
7026 byte row[sizeof(ib_uint64_t)
7027 + sizeof(ib_uint32_t) * 8];
7028
7029 ptr = row;
7030
7031 ut_ad(sizeof(ib_uint64_t) == 8);
7032 mach_write_to_8(ptr, index->id);
7033 ptr += sizeof(ib_uint64_t);
7034
7035 mach_write_to_4(ptr, index->space);
7036 ptr += sizeof(ib_uint32_t);
7037
7038 mach_write_to_4(ptr, index->page);
7039 ptr += sizeof(ib_uint32_t);
7040
7041 mach_write_to_4(ptr, index->type);
7042 ptr += sizeof(ib_uint32_t);
7043
7044 mach_write_to_4(ptr, index->trx_id_offset);
7045 ptr += sizeof(ib_uint32_t);
7046
7047 mach_write_to_4(ptr, index->n_user_defined_cols);
7048 ptr += sizeof(ib_uint32_t);
7049
7050 mach_write_to_4(ptr, index->n_uniq);
7051 ptr += sizeof(ib_uint32_t);
7052
7053 mach_write_to_4(ptr, index->n_nullable);
7054 ptr += sizeof(ib_uint32_t);
7055
7056 mach_write_to_4(ptr, index->n_fields);
7057
7058 if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
7059
7060 msg("xtrabackup: Error: writing index meta-data.");
7061
7062 return(false);
7063 }
7064
7065 /* Write the length of the index name.
7066 NUL byte is included in the length. */
7067 ib_uint32_t len = strlen(index->name) + 1;
7068 ut_a(len > 1);
7069
7070 mach_write_to_4(row, len);
7071
7072 if (fwrite(row, 1, sizeof(len), file) != sizeof(len)
7073 || fwrite(index->name, 1, len, file) != len) {
7074
7075 msg("xtrabackup: Error: writing index name.");
7076
7077 return(false);
7078 }
7079
7080 ret = xb_export_cfg_write_index_fields(index, file);
7081 }
7082
7083 return(ret);
7084 }
7085
7086 /*********************************************************************//**
7087 Write the meta data (table columns) config file. Serialise the contents of
7088 dict_col_t structure, along with the column name. All fields are serialized
7089 as ib_uint32_t.
7090 @return true in case of success otherwise false. */
7091 static __attribute__((nonnull, warn_unused_result))
7092 bool
xb_export_cfg_write_table(const dict_table_t * table,FILE * file)7093 xb_export_cfg_write_table(
7094 /*====================*/
7095 const dict_table_t* table, /*!< in: write the meta data for
7096 this table */
7097 FILE* file) /*!< in: file to write to */
7098 {
7099 dict_col_t* col;
7100 byte row[sizeof(ib_uint32_t) * 7];
7101
7102 col = table->cols;
7103
7104 for (ulint i = 0; i < table->n_cols; ++i, ++col) {
7105 byte* ptr = row;
7106
7107 mach_write_to_4(ptr, col->prtype);
7108 ptr += sizeof(ib_uint32_t);
7109
7110 mach_write_to_4(ptr, col->mtype);
7111 ptr += sizeof(ib_uint32_t);
7112
7113 mach_write_to_4(ptr, col->len);
7114 ptr += sizeof(ib_uint32_t);
7115
7116 mach_write_to_4(ptr, col->mbminmaxlen);
7117 ptr += sizeof(ib_uint32_t);
7118
7119 mach_write_to_4(ptr, col->ind);
7120 ptr += sizeof(ib_uint32_t);
7121
7122 mach_write_to_4(ptr, col->ord_part);
7123 ptr += sizeof(ib_uint32_t);
7124
7125 mach_write_to_4(ptr, col->max_prefix);
7126
7127 if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
7128 msg("xtrabackup: Error: writing table column data.");
7129
7130 return(false);
7131 }
7132
7133 /* Write out the column name as [len, byte array]. The len
7134 includes the NUL byte. */
7135 ib_uint32_t len;
7136 const char* col_name;
7137
7138 col_name = dict_table_get_col_name(table, dict_col_get_no(col));
7139
7140 /* Include the NUL byte in the length. */
7141 len = strlen(col_name) + 1;
7142 ut_a(len > 1);
7143
7144 mach_write_to_4(row, len);
7145
7146 if (fwrite(row, 1, sizeof(len), file) != sizeof(len)
7147 || fwrite(col_name, 1, len, file) != len) {
7148
7149 msg("xtrabackup: Error: writing column name.");
7150
7151 return(false);
7152 }
7153 }
7154
7155 return(true);
7156 }
7157
7158 /*********************************************************************//**
7159 Write the meta data config file header.
7160 @return true in case of success otherwise false. */
7161 static __attribute__((nonnull, warn_unused_result))
7162 bool
xb_export_cfg_write_header(const dict_table_t * table,FILE * file)7163 xb_export_cfg_write_header(
7164 /*=====================*/
7165 const dict_table_t* table, /*!< in: write the meta data for
7166 this table */
7167 FILE* file) /*!< in: file to write to */
7168 {
7169 byte value[sizeof(ib_uint32_t)];
7170
7171 /* Write the meta-data version number. */
7172 mach_write_to_4(value, IB_EXPORT_CFG_VERSION_V1);
7173
7174 if (fwrite(&value, 1, sizeof(value), file) != sizeof(value)) {
7175 msg("xtrabackup: Error: writing meta-data version number.");
7176
7177 return(false);
7178 }
7179
7180 /* Write the server hostname. */
7181 ib_uint32_t len;
7182 const char* hostname = "Hostname unknown";
7183
7184 /* The server hostname includes the NUL byte. */
7185 len = strlen(hostname) + 1;
7186 mach_write_to_4(value, len);
7187
7188 if (fwrite(&value, 1, sizeof(value), file) != sizeof(value)
7189 || fwrite(hostname, 1, len, file) != len) {
7190
7191 msg("xtrabackup: Error: writing hostname.");
7192
7193 return(false);
7194 }
7195
7196 /* The table name includes the NUL byte. */
7197 ut_a(table->name.m_name != NULL);
7198 len = strlen(table->name.m_name) + 1;
7199
7200 /* Write the table name. */
7201 mach_write_to_4(value, len);
7202
7203 if (fwrite(&value, 1, sizeof(value), file) != sizeof(value)
7204 || fwrite(table->name.m_name, 1, len, file) != len) {
7205
7206 msg("xtrabackup: Error: writing table name.");
7207
7208 return(false);
7209 }
7210
7211 byte row[sizeof(ib_uint32_t) * 3];
7212
7213 /* Write the next autoinc value. */
7214 mach_write_to_8(row, table->autoinc);
7215
7216 if (fwrite(row, 1, sizeof(ib_uint64_t), file) != sizeof(ib_uint64_t)) {
7217 msg("xtrabackup: Error: writing table autoinc value.");
7218
7219 return(false);
7220 }
7221
7222 byte* ptr = row;
7223
7224 /* Write the system page size. */
7225 mach_write_to_4(ptr, UNIV_PAGE_SIZE);
7226 ptr += sizeof(ib_uint32_t);
7227
7228 /* Write the table->flags. */
7229 mach_write_to_4(ptr, table->flags);
7230 ptr += sizeof(ib_uint32_t);
7231
7232 /* Write the number of columns in the table. */
7233 mach_write_to_4(ptr, table->n_cols);
7234
7235 if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
7236 msg("xtrabackup: Error: writing table meta-data.");
7237
7238 return(false);
7239 }
7240
7241 return(true);
7242 }
7243
7244 /*********************************************************************//**
7245 Write MySQL 5.6-style meta data config file.
7246 @return true in case of success otherwise false. */
7247 static
7248 bool
xb_export_cfg_write(const fil_node_t * node,const dict_table_t * table)7249 xb_export_cfg_write(
7250 const fil_node_t* node,
7251 const dict_table_t* table) /*!< in: write the meta data for
7252 this table */
7253 {
7254 char file_path[FN_REFLEN];
7255 FILE* file;
7256 bool success;
7257
7258 strcpy(file_path, node->name);
7259 strcpy(file_path + strlen(file_path) - 4, ".cfg");
7260
7261 file = fopen(file_path, "w+b");
7262
7263 if (file == NULL) {
7264 msg("xtrabackup: Error: cannot open %s\n", node->name);
7265
7266 success = false;
7267 } else {
7268
7269 success = xb_export_cfg_write_header(table, file);
7270
7271 if (success) {
7272 success = xb_export_cfg_write_table(table, file);
7273 }
7274
7275 if (success) {
7276 success = xb_export_cfg_write_indexes(table, file);
7277 }
7278
7279 if (fclose(file) != 0) {
7280 msg("xtrabackup: Error: cannot close %s\n", node->name);
7281 success = false;
7282 }
7283
7284 }
7285
7286 return(success);
7287
7288 }
7289
7290 /** Write the transfer key to CFP file.
7291 @param[in] table write the data for this table
7292 @param[in] file file to write to
7293 @return DB_SUCCESS or error code. */
7294 static __attribute__((nonnull, warn_unused_result))
7295 dberr_t
xb_export_write_transfer_key(const dict_table_t * table,FILE * file)7296 xb_export_write_transfer_key(
7297 const dict_table_t* table,
7298 FILE* file)
7299 {
7300 byte key_size[sizeof(ib_uint32_t)];
7301 byte row[ENCRYPTION_KEY_LEN * 3];
7302 byte* ptr = row;
7303 byte* transfer_key = ptr;
7304 lint elen;
7305
7306 ut_ad(table->encryption_key != NULL
7307 && table->encryption_iv != NULL);
7308
7309 /* Write the encryption key size. */
7310 mach_write_to_4(key_size, ENCRYPTION_KEY_LEN);
7311
7312 if (fwrite(&key_size, 1, sizeof(key_size), file)
7313 != sizeof(key_size)) {
7314 msg("IO Write error: (%d, %s) %s",
7315 errno, strerror(errno),
7316 "while writing key size.");
7317
7318 return(DB_IO_ERROR);
7319 }
7320
7321 /* Generate and write the transfer key. */
7322 Encryption::random_value(transfer_key);
7323 if (fwrite(transfer_key, 1, ENCRYPTION_KEY_LEN, file)
7324 != ENCRYPTION_KEY_LEN) {
7325 msg("IO Write error: (%d, %s) %s",
7326 errno, strerror(errno),
7327 "while writing transfer key.");
7328
7329 return(DB_IO_ERROR);
7330 }
7331
7332 ptr += ENCRYPTION_KEY_LEN;
7333
7334 /* Encrypt tablespace key. */
7335 elen = my_aes_encrypt(
7336 reinterpret_cast<unsigned char*>(table->encryption_key),
7337 ENCRYPTION_KEY_LEN,
7338 ptr,
7339 reinterpret_cast<unsigned char*>(transfer_key),
7340 ENCRYPTION_KEY_LEN,
7341 my_aes_256_ecb,
7342 NULL, false);
7343
7344 if (elen == MY_AES_BAD_DATA) {
7345 msg("IO Write error: (%d, %s) %s",
7346 errno, strerror(errno),
7347 "while encrypt tablespace key.");
7348 return(DB_ERROR);
7349 }
7350
7351 /* Write encrypted tablespace key */
7352 if (fwrite(ptr, 1, ENCRYPTION_KEY_LEN, file)
7353 != ENCRYPTION_KEY_LEN) {
7354 msg("IO Write error: (%d, %s) %s",
7355 errno, strerror(errno),
7356 "while writing encrypted tablespace key.");
7357
7358 return(DB_IO_ERROR);
7359 }
7360 ptr += ENCRYPTION_KEY_LEN;
7361
7362 /* Encrypt tablespace iv. */
7363 elen = my_aes_encrypt(
7364 reinterpret_cast<unsigned char*>(table->encryption_iv),
7365 ENCRYPTION_KEY_LEN,
7366 ptr,
7367 reinterpret_cast<unsigned char*>(transfer_key),
7368 ENCRYPTION_KEY_LEN,
7369 my_aes_256_ecb,
7370 NULL, false);
7371
7372 if (elen == MY_AES_BAD_DATA) {
7373 msg("IO Write error: (%d, %s) %s",
7374 errno, strerror(errno),
7375 "while encrypt tablespace iv.");
7376 return(DB_ERROR);
7377 }
7378
7379 /* Write encrypted tablespace iv */
7380 if (fwrite(ptr, 1, ENCRYPTION_KEY_LEN, file)
7381 != ENCRYPTION_KEY_LEN) {
7382 msg("IO Write error: (%d, %s) %s",
7383 errno, strerror(errno),
7384 "while writing encrypted tablespace iv.");
7385
7386 return(DB_IO_ERROR);
7387 }
7388
7389 return(DB_SUCCESS);
7390 }
7391
7392 /** Write the encryption data after quiesce.
7393 @param[in] table write the data for this table
7394 @return DB_SUCCESS or error code */
7395 static __attribute__((nonnull, warn_unused_result))
7396 dberr_t
xb_export_cfp_write(dict_table_t * table)7397 xb_export_cfp_write(
7398 dict_table_t* table)
7399 {
7400 dberr_t err;
7401 char name[OS_FILE_MAX_PATH];
7402
7403 /* If table is not encrypted, return. */
7404 if (!dict_table_is_encrypted(table)) {
7405 return(DB_SUCCESS);
7406 }
7407
7408 /* Get the encryption key and iv from space */
7409 /* For encrypted table, before we discard the tablespace,
7410 we need save the encryption information into table, otherwise,
7411 this information will be lost in fil_discard_tablespace along
7412 with fil_space_free(). */
7413 if (table->encryption_key == NULL) {
7414 table->encryption_key =
7415 static_cast<byte*>(mem_heap_alloc(table->heap,
7416 ENCRYPTION_KEY_LEN));
7417
7418 table->encryption_iv =
7419 static_cast<byte*>(mem_heap_alloc(table->heap,
7420 ENCRYPTION_KEY_LEN));
7421
7422 fil_space_t* space = fil_space_get(table->space);
7423 ut_ad(space != NULL && FSP_FLAGS_GET_ENCRYPTION(space->flags));
7424
7425 memcpy(table->encryption_key,
7426 space->encryption_key,
7427 ENCRYPTION_KEY_LEN);
7428 memcpy(table->encryption_iv,
7429 space->encryption_iv,
7430 ENCRYPTION_KEY_LEN);
7431 }
7432
7433 srv_get_encryption_data_filename(table, name, sizeof(name));
7434
7435 ib::info() << "Writing table encryption data to '" << name << "'";
7436
7437 FILE* file = fopen(name, "w+b");
7438
7439 if (file == NULL) {
7440 msg("Can't create file '%-.200s' (errno: %d - %s)",
7441 name, errno, strerror(errno));
7442
7443 err = DB_IO_ERROR;
7444 } else {
7445 err = xb_export_write_transfer_key(table, file);
7446
7447 if (fflush(file) != 0) {
7448
7449 char buf[BUFSIZ];
7450
7451 ut_snprintf(buf, sizeof(buf), "%s flush() failed",
7452 name);
7453
7454 msg("IO Write error: (%d, %s) %s",
7455 errno, strerror(errno), buf);
7456
7457 err = DB_IO_ERROR;
7458 }
7459
7460 if (fclose(file) != 0) {
7461 char buf[BUFSIZ];
7462
7463 ut_snprintf(buf, sizeof(buf), "%s flose() failed",
7464 name);
7465
7466 msg("IO Write error: (%d, %s) %s",
7467 errno, strerror(errno), buf);
7468 err = DB_IO_ERROR;
7469 }
7470 }
7471
7472 /* Clean the encryption information */
7473 table->encryption_key = NULL;
7474 table->encryption_iv = NULL;
7475
7476 return(err);
7477 }
7478
7479 /*********************************************************************//**
7480 Re-encrypt tablespace keys with newly generated master key having ID
7481 based on new server-id.
7482 @return true in case of success otherwise false. */
7483 static
7484 bool
reencrypt_tablespace_keys(ulint new_server_id)7485 reencrypt_tablespace_keys(
7486 ulint new_server_id)
7487 {
7488 byte* master_key = NULL;
7489 bool ret = false;
7490 Encryption::Version version;
7491
7492 /* Check if keyring loaded and the current master key
7493 can be fetched. */
7494 if (Encryption::master_key_id != 0) {
7495 ulint master_key_id;
7496
7497 Encryption::get_master_key(&master_key_id,
7498 &master_key,
7499 &version);
7500 if (master_key == NULL) {
7501 msg("xtrabackup: error: Can't find master key.\n");
7502 return(false);
7503 }
7504 msg("xtrabackup: found master key version %s.\n",
7505 version == Encryption::ENCRYPTION_VERSION_1 ?
7506 "= 5.7.11" : ">= 5.7.12");
7507 my_free(master_key);
7508
7509 if (version != Encryption::ENCRYPTION_VERSION_1) {
7510 msg("xtrabackup: reencryption is not needed.\n");
7511 return(true);
7512 }
7513 } else {
7514
7515 /* no encrypted tablespaces */
7516
7517 return(true);
7518 }
7519
7520 master_key = NULL;
7521
7522 /* Generate the new master key. */
7523 server_id = new_server_id;
7524 Encryption::create_master_key_v0(&master_key);
7525
7526 if (master_key == NULL) {
7527 msg("xtrabackup: error: Can't create master key.\n");
7528 return(false);
7529 }
7530
7531 ret = fil_encryption_rotate();
7532
7533 my_free(master_key);
7534
7535 /* If rotation failure, return error */
7536 if (!ret) {
7537 msg("xtrabackup: error: Can't rotate master key.\n");
7538 } else {
7539 msg("xtrabackup: Keys reencrypted for server-id %lu.\n",
7540 server_id);
7541 }
7542
7543 return(ret);
7544 }
7545
7546 #if 0
7547 /********************************************************************//**
7548 Searches archived log files in archived log directory. The min and max
7549 LSN's of found files as well as archived log file size are stored in
7550 xtrabackup_arch_first_file_lsn, xtrabackup_arch_last_file_lsn and
7551 xtrabackup_arch_file_size respectively.
7552 @return true on success
7553 */
7554 static
7555 bool
7556 xtrabackup_arch_search_files(
7557 /*=========================*/
7558 ib_uint64_t start_lsn) /*!< in: filter out log files
7559 witch does not contain data
7560 with lsn < start_lsn */
7561 {
7562 os_file_dir_t dir;
7563 os_file_stat_t fileinfo;
7564 ut_ad(innobase_log_arch_dir);
7565
7566 dir = os_file_opendir(innobase_log_arch_dir, FALSE);
7567 if (!dir) {
7568 msg("xtrabackup: error: cannot open archived log directory %s\n",
7569 innobase_log_arch_dir);
7570 return false;
7571 }
7572
7573 while(!os_file_readdir_next_file(innobase_log_arch_dir,
7574 dir,
7575 &fileinfo) ) {
7576 lsn_t log_file_lsn;
7577 char* log_str_end_lsn_ptr;
7578
7579 if (strncmp(fileinfo.name,
7580 IB_ARCHIVED_LOGS_PREFIX,
7581 sizeof(IB_ARCHIVED_LOGS_PREFIX) - 1)) {
7582 continue;
7583 }
7584
7585 log_file_lsn = strtoll(fileinfo.name +
7586 sizeof(IB_ARCHIVED_LOGS_PREFIX) - 1,
7587 &log_str_end_lsn_ptr, 10);
7588
7589 if (*log_str_end_lsn_ptr) {
7590 continue;
7591 }
7592
7593 if (log_file_lsn + (fileinfo.size - LOG_FILE_HDR_SIZE) < start_lsn) {
7594 continue;
7595 }
7596
7597 if (!xtrabackup_arch_first_file_lsn ||
7598 log_file_lsn < xtrabackup_arch_first_file_lsn) {
7599 xtrabackup_arch_first_file_lsn = log_file_lsn;
7600 }
7601 if (log_file_lsn > xtrabackup_arch_last_file_lsn) {
7602 xtrabackup_arch_last_file_lsn = log_file_lsn;
7603 }
7604
7605 //TODO: find the more suitable way to extract archived log file
7606 //size
7607 if (fileinfo.size > (int64_t)xtrabackup_arch_file_size) {
7608 xtrabackup_arch_file_size = fileinfo.size;
7609 }
7610 }
7611
7612 return xtrabackup_arch_first_file_lsn != 0;
7613 }
7614 #endif
7615
7616 static
7617 void
innodb_free_param()7618 innodb_free_param()
7619 {
7620 srv_sys_space.shutdown();
7621 srv_tmp_space.shutdown();
7622 free(internal_innobase_data_file_path);
7623 internal_innobase_data_file_path = NULL;
7624 free_tmpdir(&mysql_tmpdir_list);
7625 }
7626
7627
7628 /**************************************************************************
7629 Store the current binary log coordinates in a specified file.
7630 @return 'false' on error. */
7631 static bool
store_binlog_info(const char * filename)7632 store_binlog_info(
7633 /*==============*/
7634 const char *filename) /*!< in: output file name */
7635 {
7636 FILE *fp;
7637
7638 if (trx_sys_mysql_bin_log_name[0] == '\0') {
7639 return(true);
7640 }
7641
7642 fp = fopen(filename, "w");
7643
7644 if (!fp) {
7645 msg("xtrabackup: failed to open '%s'\n", filename);
7646 return(false);
7647 }
7648
7649 fprintf(fp, "%s\t" UINT64PF "\n",
7650 trx_sys_mysql_bin_log_name, trx_sys_mysql_bin_log_pos);
7651 fclose(fp);
7652
7653 return(true);
7654 }
7655
7656
7657 /**************************************************************************
7658 Store current master key ID.
7659 @return 'false' on error. */
7660 static bool
store_master_key_id(const char * filename)7661 store_master_key_id(
7662 /*==============*/
7663 const char *filename) /*!< in: output file name */
7664 {
7665 FILE *fp;
7666
7667 fp = fopen(filename, "w");
7668
7669 if (!fp) {
7670 msg("xtrabackup: failed to open '%s'\n", filename);
7671 return(false);
7672 }
7673
7674 fprintf(fp, "%lu", Encryption::master_key_id);
7675 fclose(fp);
7676
7677 return(true);
7678 }
7679
7680 static void
xtrabackup_prepare_func(int argc,char ** argv)7681 xtrabackup_prepare_func(int argc, char **argv)
7682 {
7683 ulint err;
7684 datafiles_iter_t *it;
7685 fil_node_t *node;
7686 fil_space_t *space;
7687 char metadata_path[FN_REFLEN];
7688 IORequest write_request(IORequest::WRITE);
7689
7690 mysql_mutex_init(key_LOCK_global_system_variables,
7691 &LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
7692
7693 /* cd to target-dir */
7694
7695 if (my_setwd(xtrabackup_real_target_dir,MYF(MY_WME)))
7696 {
7697 msg("xtrabackup: cannot my_setwd %s\n",
7698 xtrabackup_real_target_dir);
7699 exit(EXIT_FAILURE);
7700 }
7701 msg("xtrabackup: cd to %s\n", xtrabackup_real_target_dir);
7702
7703 xtrabackup_target_dir= mysql_data_home_buff;
7704 xtrabackup_target_dir[0]=FN_CURLIB; // all paths are relative from here
7705 xtrabackup_target_dir[1]=0;
7706
7707 /*
7708 read metadata of target, we don't need metadata reading in the case
7709 archived logs applying
7710 */
7711 sprintf(metadata_path, "%s/%s", xtrabackup_target_dir,
7712 XTRABACKUP_METADATA_FILENAME);
7713
7714 if (!xtrabackup_read_metadata(metadata_path)) {
7715 msg("xtrabackup: Error: failed to read metadata from '%s'\n",
7716 metadata_path);
7717 exit(EXIT_FAILURE);
7718 }
7719
7720 if (!innobase_log_arch_dir)
7721 {
7722 if (!strcmp(metadata_type, "full-backuped")) {
7723 msg("xtrabackup: This target seems to be not prepared "
7724 "yet.\n");
7725 } else if (!strcmp(metadata_type, "log-applied")) {
7726 msg("xtrabackup: This target seems to be already "
7727 "prepared with --apply-log-only.\n");
7728 goto skip_check;
7729 } else if (!strcmp(metadata_type, "full-prepared")) {
7730 msg("xtrabackup: This target seems to be already "
7731 "prepared.\n");
7732 } else {
7733 msg("xtrabackup: This target seems not to have correct "
7734 "metadata...\n");
7735 exit(EXIT_FAILURE);
7736 }
7737
7738 if (xtrabackup_incremental) {
7739 msg("xtrabackup: error: applying incremental backup "
7740 "needs target prepared with --apply-log-only.\n");
7741 exit(EXIT_FAILURE);
7742 }
7743 skip_check:
7744 if (xtrabackup_incremental
7745 && metadata_to_lsn != incremental_lsn) {
7746 msg("xtrabackup: error: This incremental backup seems "
7747 "not to be proper for the target.\n"
7748 "xtrabackup: Check 'to_lsn' of the target and "
7749 "'from_lsn' of the incremental.\n");
7750 exit(EXIT_FAILURE);
7751 }
7752 }
7753
7754 if (xtrabackup_incremental) {
7755 backup_redo_log_flushed_lsn = incremental_flushed_lsn;
7756 }
7757
7758 /* Create logfiles for recovery from 'xtrabackup_logfile', before start InnoDB */
7759 srv_max_n_threads = 1000;
7760 /* temporally dummy value to avoid crash */
7761 srv_page_size_shift = 14;
7762 srv_page_size = (1 << srv_page_size_shift);
7763 os_event_global_init();
7764 sync_check_init();
7765 #ifdef UNIV_DEBUG
7766 sync_check_enable();
7767 #endif
7768 os_thread_init();
7769 trx_pool_init();
7770 ut_crc32_init();
7771
7772 xb_filters_init();
7773
7774 if(!innobase_log_arch_dir && xtrabackup_init_temp_log())
7775 goto error_cleanup;
7776
7777 if(innodb_init_param()) {
7778 goto error_cleanup;
7779 }
7780
7781 if (opt_transition_key && !xb_tablespace_keys_exist()) {
7782 msg("xtrabackup: Error: --transition-key specified, but "
7783 "xtrabackup_keys is not found.\n");
7784 goto error_cleanup;
7785 }
7786
7787 if (opt_transition_key) {
7788 if (!xb_tablespace_keys_load(
7789 xtrabackup_incremental,
7790 opt_transition_key, strlen(opt_transition_key))) {
7791 msg("xtrabackup: Error: failed to load tablespace "
7792 "keys\n");
7793 goto error_cleanup;
7794 }
7795 } else {
7796 if (!xb_keyring_init_for_prepare(argc, argv)) {
7797 msg("xtrabackup: Error: failed to init keyring "
7798 "plugin\n");
7799 goto error_cleanup;
7800 }
7801 if (xb_tablespace_keys_exist()) {
7802 use_dumped_tablespace_keys = true;
7803 if (!xb_tablespace_keys_load(
7804 xtrabackup_incremental,
7805 NULL, 0)) {
7806 msg("xtrabackup: Error: failed to load "
7807 "tablespace keys\n");
7808 goto error_cleanup;
7809 }
7810 }
7811 }
7812
7813 /* Expand compacted datafiles */
7814
7815 if (xtrabackup_compact) {
7816 srv_compact_backup = TRUE;
7817
7818 if (!xb_expand_datafiles()) {
7819 goto error_cleanup;
7820 }
7821
7822 /* Reset the 'compact' flag in xtrabackup_checkpoints so we
7823 don't expand on subsequent invocations. */
7824 xtrabackup_compact = FALSE;
7825 if (!xtrabackup_write_metadata(metadata_path)) {
7826 msg("xtrabackup: error: xtrabackup_write_metadata() "
7827 "failed\n");
7828 goto error_cleanup;
7829 }
7830 }
7831
7832 xb_normalize_init_values();
7833
7834 if (xtrabackup_incremental || innobase_log_arch_dir) {
7835 err = xb_data_files_init();
7836 if (err != DB_SUCCESS) {
7837 msg("xtrabackup: error: xb_data_files_init() failed "
7838 "with error code %lu\n", err);
7839 goto error_cleanup;
7840 }
7841 }
7842 if (xtrabackup_incremental) {
7843 inc_dir_tables_hash = hash_create(1000);
7844
7845 if(!xtrabackup_apply_deltas()) {
7846 xb_data_files_close();
7847 xb_filter_hash_free(inc_dir_tables_hash);
7848 goto error_cleanup;
7849 }
7850 }
7851 if (xtrabackup_incremental || innobase_log_arch_dir) {
7852 xb_data_files_close();
7853 }
7854 if (xtrabackup_incremental) {
7855 /* Cleanup datadir from tablespaces deleted between full and
7856 incremental backups */
7857
7858 xb_process_datadir("./", ".ibd", rm_if_not_found, NULL);
7859
7860 xb_filter_hash_free(inc_dir_tables_hash);
7861 }
7862 if (fil_system) {
7863 fil_close();
7864 }
7865
7866 trx_pool_close();
7867
7868 os_thread_free();
7869
7870 sync_check_close();
7871
7872 innodb_free_param();
7873
7874 /* Reset the configuration as it might have been changed by
7875 xb_data_files_init(). */
7876 if(innodb_init_param()) {
7877 goto error_cleanup;
7878 }
7879
7880 srv_apply_log_only = (ibool) xtrabackup_apply_log_only;
7881 srv_rebuild_indexes = (ibool) xtrabackup_rebuild_indexes;
7882
7883 /* increase IO threads */
7884 if(srv_n_file_io_threads < 10) {
7885 srv_n_read_io_threads = 4;
7886 srv_n_write_io_threads = 4;
7887 }
7888
7889 msg("xtrabackup: Starting InnoDB instance for recovery.\n"
7890 "xtrabackup: Using %lld bytes for buffer pool "
7891 "(set by --use-memory parameter)\n", xtrabackup_use_memory);
7892
7893 if(innodb_init())
7894 goto error_cleanup;
7895
7896 it = datafiles_iter_new(fil_system);
7897 if (it == NULL) {
7898 msg("xtrabackup: Error: datafiles_iter_new() failed.\n");
7899 exit(EXIT_FAILURE);
7900 }
7901
7902 while ((node = datafiles_iter_next(it)) != NULL) {
7903 byte *header;
7904 ulint size;
7905 mtr_t mtr;
7906 buf_block_t *block;
7907 ulint flags;
7908
7909 space = node->space;
7910
7911 /* Align space sizes along with fsp header. We want to process
7912 each space once, so skip all nodes except the first one in a
7913 multi-node space. */
7914 if (UT_LIST_GET_PREV(chain, node) != NULL) {
7915 continue;
7916 }
7917
7918 mtr_start(&mtr);
7919
7920 mtr_s_lock(fil_space_get_latch(space->id, &flags), &mtr);
7921
7922 block = buf_page_get(page_id_t(space->id, 0),
7923 page_size_t(flags),
7924 RW_S_LATCH, &mtr);
7925 header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
7926
7927 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES,
7928 &mtr);
7929
7930 mtr_commit(&mtr);
7931
7932 fil_space_extend(space, size);
7933 }
7934
7935 datafiles_iter_free(it);
7936
7937 if (xtrabackup_export) {
7938 msg("xtrabackup: export option is specified.\n");
7939 pfs_os_file_t info_file = XB_FILE_UNDEFINED;
7940 char info_file_path[FN_REFLEN];
7941 bool success;
7942 char table_name[FN_REFLEN];
7943
7944 byte* page;
7945 byte* buf = NULL;
7946
7947 buf = static_cast<byte *>(ut_malloc_nokey(UNIV_PAGE_SIZE * 2));
7948 page = static_cast<byte *>(ut_align(buf, UNIV_PAGE_SIZE));
7949
7950 /* flush insert buffer at shutdwon */
7951 innobase_fast_shutdown = 0;
7952
7953 it = datafiles_iter_new(fil_system);
7954 if (it == NULL) {
7955 msg("xtrabackup: Error: datafiles_iter_new() "
7956 "failed.\n");
7957 exit(EXIT_FAILURE);
7958 }
7959 while ((node = datafiles_iter_next(it)) != NULL) {
7960 int len;
7961 char *next, *prev, *p;
7962 dict_table_t* table;
7963 dict_index_t* index;
7964 ulint n_index;
7965
7966 space = node->space;
7967
7968 /* treat file_per_table only */
7969 if (!fil_is_user_tablespace_id(space->id)) {
7970 continue;
7971 }
7972
7973 /* node exist == file exist, here */
7974 strcpy(info_file_path, node->name);
7975 strcpy(info_file_path +
7976 strlen(info_file_path) -
7977 4, ".exp");
7978
7979 len = strlen(info_file_path);
7980
7981 p = info_file_path;
7982 prev = NULL;
7983 while ((next = strchr(p, OS_PATH_SEPARATOR)) != NULL)
7984 {
7985 prev = p;
7986 p = next + 1;
7987 }
7988 info_file_path[len - 4] = 0;
7989 strncpy(table_name, prev, FN_REFLEN);
7990
7991 info_file_path[len - 4] = '.';
7992
7993 mutex_enter(&(dict_sys->mutex));
7994
7995 table = dict_table_get_low(table_name);
7996 if (!table) {
7997 msg("xtrabackup: error: "
7998 "cannot find dictionary "
7999 "record of table %s\n",
8000 table_name);
8001 goto next_node;
8002 }
8003
8004 /* Write MySQL 5.6 .cfg file */
8005 if (!xb_export_cfg_write(node, table)) {
8006 goto next_node;
8007 }
8008
8009 index = dict_table_get_first_index(table);
8010 n_index = UT_LIST_GET_LEN(table->indexes);
8011 if (n_index > 31) {
8012 msg("xtrabackup: warning: table '%s' has more "
8013 "than 31 indexes, .exp file was not "
8014 "generated. Table will fail to import "
8015 "on server version prior to 5.6.\n",
8016 table_name);
8017 goto next_node;
8018 }
8019
8020 /* Write transfer key for tablespace file */
8021 if (!xb_export_cfp_write(table)) {
8022 goto next_node;
8023 }
8024
8025 /* init exp file */
8026 memset(page, 0, UNIV_PAGE_SIZE);
8027 mach_write_to_4(page , 0x78706f72UL);
8028 mach_write_to_4(page + 4, 0x74696e66UL);/*"xportinf"*/
8029 mach_write_to_4(page + 8, n_index);
8030 strncpy((char *) page + 12,
8031 table_name, 500);
8032
8033 msg("xtrabackup: export metadata of "
8034 "table '%s' to file `%s` "
8035 "(%lu indexes)\n",
8036 table_name, info_file_path,
8037 n_index);
8038
8039 n_index = 1;
8040 while (index) {
8041 mach_write_to_8(page + n_index * 512, index->id);
8042 mach_write_to_4(page + n_index * 512 + 8,
8043 index->page);
8044 strncpy((char *) page + n_index * 512 +
8045 12, index->name, 500);
8046
8047 msg("xtrabackup: name=%s, "
8048 "id.low=%lu, page=%lu\n",
8049 index->name(),
8050 (ulint)(index->id &
8051 0xFFFFFFFFUL),
8052 (ulint) index->page);
8053 index = dict_table_get_next_index(index);
8054 n_index++;
8055 }
8056
8057 os_normalize_path(info_file_path);
8058 info_file = os_file_create(
8059 0,
8060 info_file_path,
8061 OS_FILE_OVERWRITE,
8062 OS_FILE_NORMAL, OS_DATA_FILE,
8063 false,
8064 &success);
8065 if (!success) {
8066 os_file_get_last_error(TRUE);
8067 goto next_node;
8068 }
8069 success = os_file_write(write_request, info_file_path,
8070 info_file, page,
8071 0, UNIV_PAGE_SIZE);
8072 if (!success) {
8073 os_file_get_last_error(TRUE);
8074 goto next_node;
8075 }
8076 success = os_file_flush(info_file);
8077 if (!success) {
8078 os_file_get_last_error(TRUE);
8079 goto next_node;
8080 }
8081 next_node:
8082 if (info_file != XB_FILE_UNDEFINED) {
8083 os_file_close(info_file);
8084 info_file = XB_FILE_UNDEFINED;
8085 }
8086 mutex_exit(&(dict_sys->mutex));
8087 }
8088
8089 ut_free(buf);
8090
8091 datafiles_iter_free(it);
8092 }
8093
8094 /* print the binary log position */
8095 trx_sys_print_mysql_binlog_offset();
8096 msg("\n");
8097
8098 /* output to xtrabackup_binlog_pos_innodb and (if
8099 backup_safe_binlog_info was available on the server) to
8100 xtrabackup_binlog_info. In the latter case xtrabackup_binlog_pos_innodb
8101 becomes redundant and is created only for compatibility. */
8102 if (!store_binlog_info("xtrabackup_binlog_pos_innodb") ||
8103 (recover_binlog_info &&
8104 !store_binlog_info(XTRABACKUP_BINLOG_INFO))) {
8105
8106 exit(EXIT_FAILURE);
8107 }
8108
8109 if (!store_master_key_id("xtrabackup_master_key_id")) {
8110 exit(EXIT_FAILURE);
8111 }
8112
8113 if (innobase_log_arch_dir)
8114 srv_start_lsn = log_sys->lsn = recv_sys->recovered_lsn;
8115
8116 /* Check whether the log is applied enough or not. */
8117 if ((xtrabackup_incremental
8118 && srv_start_lsn < incremental_to_lsn)
8119 ||(!xtrabackup_incremental
8120 && srv_start_lsn < metadata_to_lsn)) {
8121 msg("xtrabackup: error: "
8122 "The transaction log file is corrupted.\n"
8123 "xtrabackup: error: "
8124 "The log was not applied to the intended LSN!\n");
8125 msg("xtrabackup: Log applied to lsn " LSN_PF "\n",
8126 srv_start_lsn);
8127 if (xtrabackup_incremental) {
8128 msg("xtrabackup: The intended lsn is " LSN_PF "\n",
8129 incremental_to_lsn);
8130 } else {
8131 msg("xtrabackup: The intended lsn is " LSN_PF "\n",
8132 metadata_to_lsn);
8133 }
8134 exit(EXIT_FAILURE);
8135 }
8136
8137 xb_write_galera_info(xtrabackup_incremental);
8138
8139 if(innodb_end())
8140 goto error_cleanup;
8141
8142 innodb_free_param();
8143
8144 /* re-init necessary components */
8145 os_event_global_init();
8146 sync_check_init();
8147 #ifdef UNIV_DEBUG
8148 sync_check_enable();
8149 #endif
8150 /* Reset the system variables in the recovery module. */
8151 os_thread_init();
8152 trx_pool_init();
8153 que_init();
8154
8155 if(xtrabackup_close_temp_log(TRUE))
8156 exit(EXIT_FAILURE);
8157
8158 /* output to metadata file */
8159 {
8160 char filename[FN_REFLEN];
8161
8162 strcpy(metadata_type, srv_apply_log_only ?
8163 "log-applied" : "full-prepared");
8164
8165 if(xtrabackup_incremental
8166 && metadata_to_lsn < incremental_to_lsn)
8167 {
8168 metadata_to_lsn = incremental_to_lsn;
8169 metadata_last_lsn = incremental_last_lsn;
8170 }
8171
8172 sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
8173 if (!xtrabackup_write_metadata(filename)) {
8174
8175 msg("xtrabackup: Error: failed to write metadata "
8176 "to '%s'\n", filename);
8177 exit(EXIT_FAILURE);
8178 }
8179
8180 if(xtrabackup_extra_lsndir) {
8181 sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
8182 if (!xtrabackup_write_metadata(filename)) {
8183 msg("xtrabackup: Error: failed to write "
8184 "metadata to '%s'\n", filename);
8185 exit(EXIT_FAILURE);
8186 }
8187 }
8188 }
8189
8190 if (!apply_log_finish()) {
8191 exit(EXIT_FAILURE);
8192 }
8193
8194 trx_pool_close();
8195
8196 if (fil_system) {
8197 fil_close();
8198 }
8199
8200 os_thread_free();
8201
8202 sync_check_close();
8203
8204 /* start InnoDB once again to create log files */
8205
8206 if (!xtrabackup_apply_log_only) {
8207
8208 /* xtrabackup_incremental_dir is used to indicate that
8209 we are going to apply incremental backup. Here we already
8210 applied incremental backup and are about to do final prepare
8211 of the full backup */
8212 xtrabackup_incremental_dir = NULL;
8213
8214 if(innodb_init_param()) {
8215 goto error;
8216 }
8217
8218 srv_apply_log_only = FALSE;
8219 srv_rebuild_indexes = FALSE;
8220
8221 /* increase IO threads */
8222 if(srv_n_file_io_threads < 10) {
8223 srv_n_read_io_threads = 4;
8224 srv_n_write_io_threads = 4;
8225 }
8226
8227 srv_shutdown_state = SRV_SHUTDOWN_NONE;
8228
8229 if(innodb_init())
8230 goto error;
8231
8232 if (opt_encrypt_for_server_id_specified) {
8233 if (!reencrypt_tablespace_keys(opt_encrypt_server_id)) {
8234 msg("xtrabackup: error: "
8235 "Tablespace keys are not reencrypted.\n");
8236 goto error;
8237 }
8238 }
8239
8240 if(innodb_end())
8241 goto error;
8242
8243 innodb_free_param();
8244
8245 }
8246
8247 if (!use_dumped_tablespace_keys) {
8248 xb_keyring_shutdown();
8249 }
8250
8251 mysql_mutex_destroy(&LOCK_global_system_variables);
8252
8253 xb_filters_free();
8254
8255 return;
8256
8257 error_cleanup:
8258
8259 if (!use_dumped_tablespace_keys) {
8260 xb_keyring_shutdown();
8261 }
8262
8263 xtrabackup_close_temp_log(FALSE);
8264
8265 mysql_mutex_destroy(&LOCK_global_system_variables);
8266
8267 xb_filters_free();
8268
8269 error:
8270 exit(EXIT_FAILURE);
8271 }
8272
8273 /**************************************************************************
8274 Signals-related setup. */
8275 static
8276 void
setup_signals()8277 setup_signals()
8278 /*===========*/
8279 {
8280 struct sigaction sa;
8281
8282 /* Print a stacktrace on some signals */
8283 sa.sa_flags = SA_RESETHAND | SA_NODEFER;
8284 sigemptyset(&sa.sa_mask);
8285 sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
8286 #ifdef HAVE_STACKTRACE
8287 my_init_stacktrace();
8288 #endif
8289 sa.sa_handler = handle_fatal_signal;
8290 sigaction(SIGSEGV, &sa, NULL);
8291 sigaction(SIGABRT, &sa, NULL);
8292 sigaction(SIGBUS, &sa, NULL);
8293 sigaction(SIGILL, &sa, NULL);
8294 sigaction(SIGFPE, &sa, NULL);
8295
8296 #ifdef __linux__
8297 /* Ensure xtrabackup process is killed when the parent one
8298 (innobackupex) is terminated with an unhandled signal */
8299
8300 if (prctl(PR_SET_PDEATHSIG, SIGKILL)) {
8301 msg("prctl() failed with errno = %d\n", errno);
8302 exit(EXIT_FAILURE);
8303 }
8304 #endif
8305 }
8306
8307 /**************************************************************************
8308 Append group name to xb_load_default_groups list. */
8309 static
8310 void
append_defaults_group(const char * group,const char * default_groups[],size_t default_groups_size)8311 append_defaults_group(const char *group, const char *default_groups[],
8312 size_t default_groups_size)
8313 {
8314 uint i;
8315 bool appended = false;
8316 for (i = 0; i < default_groups_size - 1; i++) {
8317 if (default_groups[i] == NULL) {
8318 default_groups[i] = group;
8319 appended = true;
8320 break;
8321 }
8322 }
8323 ut_a(appended);
8324 }
8325
8326 bool
xb_init()8327 xb_init()
8328 {
8329 const char *mixed_options[4] = {NULL, NULL, NULL, NULL};
8330 int n_mixed_options;
8331
8332 /* sanity checks */
8333 if (opt_lock_ddl && opt_lock_ddl_per_table) {
8334 msg("Error: %s and %s are mutually exclusive\n",
8335 "--lock-ddl", "--lock-ddl-per-table");
8336 return(false);
8337 }
8338
8339 if (opt_slave_info
8340 && opt_no_lock
8341 && !opt_safe_slave_backup) {
8342 msg("Error: --slave-info is used with --no-lock but "
8343 "without --safe-slave-backup. The binlog position "
8344 "cannot be consistent with the backup data.\n");
8345 return(false);
8346 }
8347
8348 if (opt_rsync && xtrabackup_stream_fmt) {
8349 msg("Error: --rsync doesn't work with --stream\n");
8350 return(false);
8351 }
8352
8353 if (opt_transition_key && opt_generate_transition_key) {
8354 msg("Error: options --transition-key and "
8355 "--generate-transition-key are mutually exclusive.\n");
8356 return(false);
8357 }
8358
8359 n_mixed_options = 0;
8360
8361 if (opt_decompress) {
8362 mixed_options[n_mixed_options++] = "--decompress";
8363 } else if (opt_decrypt) {
8364 mixed_options[n_mixed_options++] = "--decrypt";
8365 }
8366
8367 if (xtrabackup_copy_back) {
8368 mixed_options[n_mixed_options++] = "--copy-back";
8369 }
8370
8371 if (xtrabackup_move_back) {
8372 mixed_options[n_mixed_options++] = "--move-back";
8373 }
8374
8375 if (xtrabackup_prepare) {
8376 mixed_options[n_mixed_options++] = "--apply-log";
8377 }
8378
8379 if (n_mixed_options > 1) {
8380 msg("Error: %s and %s are mutually exclusive\n",
8381 mixed_options[0], mixed_options[1]);
8382 return(false);
8383 }
8384
8385 if (xtrabackup_backup) {
8386
8387 #ifdef HAVE_VERSION_CHECK
8388 if (!opt_noversioncheck) {
8389 version_check();
8390 }
8391 #endif
8392
8393 if ((mysql_connection = xb_mysql_connect()) == NULL) {
8394 return(false);
8395 }
8396
8397 if (!get_mysql_vars(mysql_connection)) {
8398 return(false);
8399 }
8400
8401 if (opt_lock_ddl_per_table && have_backup_locks) {
8402 msg_ts("You are taking your backup with --lock-ddl-per-table."
8403 " Please consider moving to a more safe option --lock-ddl.\n");
8404 }
8405
8406 if (opt_check_privileges) {
8407 check_all_privileges();
8408 }
8409
8410 history_start_time = time(NULL);
8411
8412 if (opt_lock_ddl &&
8413 !lock_tables_for_backup(mysql_connection,
8414 opt_lock_ddl_timeout, 0)) {
8415 return (false);
8416 }
8417
8418 parse_show_engine_innodb_status(mysql_connection);
8419
8420 }
8421
8422 return(true);
8423 }
8424
8425 static const char*
normalize_privilege_target_name(const char * name)8426 normalize_privilege_target_name(const char* name)
8427 {
8428 if (strcmp(name, "*") == 0) {
8429 return "\\*";
8430 } else {
8431 /* should have no regex special characters. */
8432 ut_ad(strpbrk(name, ".()[]*+?") == 0);
8433 }
8434 return name;
8435 }
8436
8437 /******************************************************************//**
8438 Check if specific privilege is granted.
8439 Uses regexp magic to check if requested privilege is granted for given
8440 database.table or database.* or *.*
8441 or if user has 'ALL PRIVILEGES' granted.
8442 @return true if requested privilege is granted, false otherwise. */
8443 static bool
has_privilege(const std::list<std::string> & granted,const char * required,const char * db_name,const char * table_name)8444 has_privilege(const std::list<std::string> &granted,
8445 const char* required,
8446 const char* db_name,
8447 const char* table_name)
8448 {
8449 char buffer[1000];
8450 xb_regex_t priv_re;
8451 xb_regmatch_t tables_regmatch[1];
8452 bool result = false;
8453
8454 db_name = normalize_privilege_target_name(db_name);
8455 table_name = normalize_privilege_target_name(table_name);
8456
8457 int written = snprintf(buffer, sizeof(buffer),
8458 "GRANT .*(%s)|(ALL PRIVILEGES).* ON (\\*|`%s`)\\.(\\*|`%s`)",
8459 required, db_name, table_name);
8460 if (written < 0 || written == sizeof(buffer)
8461 || !compile_regex(buffer, "has_privilege", &priv_re)) {
8462 exit(EXIT_FAILURE);
8463 }
8464
8465 typedef std::list<std::string>::const_iterator string_iter;
8466 for (string_iter i = granted.begin(), e = granted.end(); i != e; ++i) {
8467 int res = xb_regexec(&priv_re, i->c_str(),
8468 1, tables_regmatch, 0);
8469
8470 if (res != REG_NOMATCH) {
8471 result = true;
8472 break;
8473 }
8474 }
8475
8476 xb_regfree(&priv_re);
8477 return result;
8478 }
8479
8480 enum {
8481 PRIVILEGE_OK = 0,
8482 PRIVILEGE_WARNING = 1,
8483 PRIVILEGE_ERROR = 2,
8484 };
8485
8486 /******************************************************************//**
8487 Check if specific privilege is granted.
8488 Prints error message if required privilege is missing.
8489 @return PRIVILEGE_OK if requested privilege is granted, error otherwise. */
8490 static
check_privilege(const std::list<std::string> & granted_priv,const char * required,const char * target_database,const char * target_table,int error=PRIVILEGE_ERROR)8491 int check_privilege(
8492 const std::list<std::string> &granted_priv, /* in: list of
8493 granted privileges*/
8494 const char* required, /* in: required privilege name */
8495 const char* target_database, /* in: required privilege target
8496 database name */
8497 const char* target_table, /* in: required privilege target
8498 table name */
8499 int error = PRIVILEGE_ERROR) /* in: return value if privilege
8500 is not granted */
8501 {
8502 if (!has_privilege(granted_priv,
8503 required, target_database, target_table)) {
8504 msg("xtrabackup: %s: missing required privilege %s on %s.%s\n",
8505 (error == PRIVILEGE_ERROR ? "Error" : "Warning"),
8506 required, target_database, target_table);
8507 return error;
8508 }
8509 return PRIVILEGE_OK;
8510 }
8511
8512 /******************************************************************//**
8513 Check DB user privileges according to the intended actions.
8514
8515 Fetches DB user privileges, determines intended actions based on
8516 command-line arguments and prints missing privileges.
8517 May terminate application with EXIT_FAILURE exit code.*/
8518 static void
check_all_privileges()8519 check_all_privileges()
8520 {
8521 if (!mysql_connection) {
8522 /* Not connected, no queries is going to be executed. */
8523 return;
8524 }
8525
8526 /* Fetch effective privileges. */
8527 std::list<std::string> granted_privileges;
8528 MYSQL_ROW row = 0;
8529 MYSQL_RES* result = xb_mysql_query(mysql_connection, "SHOW GRANTS",
8530 true);
8531 while((row = mysql_fetch_row(result))) {
8532 granted_privileges.push_back(*row);
8533 }
8534 mysql_free_result(result);
8535
8536 int check_result = PRIVILEGE_OK;
8537 bool reload_checked = false;
8538
8539 /* SHOW DATABASES */
8540 check_result |= check_privilege(granted_privileges,
8541 "SHOW DATABASES", "*", "*");
8542
8543 /* SELECT 'INNODB_CHANGED_PAGES', COUNT(*) FROM INFORMATION_SCHEMA.PLUGINS */
8544 check_result |= check_privilege(
8545 granted_privileges,
8546 "SELECT", "INFORMATION_SCHEMA", "PLUGINS");
8547
8548 /* SHOW ENGINE INNODB STATUS */
8549 /* SHOW FULL PROCESSLIST */
8550 check_result |= check_privilege(granted_privileges,
8551 "PROCESS", "*", "*");
8552
8553 if (xb_mysql_numrows(mysql_connection,
8554 "SHOW DATABASES LIKE 'PERCONA_SCHEMA';",
8555 false) == 0) {
8556 /* CREATE DATABASE IF NOT EXISTS PERCONA_SCHEMA */
8557 check_result |= check_privilege(
8558 granted_privileges,
8559 "CREATE", "*", "*");
8560 } else if (xb_mysql_numrows(mysql_connection,
8561 "SHOW TABLES IN PERCONA_SCHEMA "
8562 "LIKE 'xtrabackup_history';",
8563 false) == 0) {
8564 /* CREATE TABLE IF NOT EXISTS PERCONA_SCHEMA.xtrabackup_history */
8565 check_result |= check_privilege(
8566 granted_privileges,
8567 "CREATE", "PERCONA_SCHEMA", "*");
8568 }
8569
8570 /* FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS */
8571 if (have_flush_engine_logs
8572 /* FLUSH NO_WRITE_TO_BINLOG TABLES */
8573 || (opt_lock_wait_timeout && !opt_kill_long_queries_timeout
8574 && !opt_no_lock)
8575 /* FLUSH TABLES WITH READ LOCK */
8576 || !opt_no_lock
8577 /* LOCK BINLOG FOR BACKUP */
8578 /* UNLOCK BINLOG */
8579 || (have_backup_locks && !opt_no_lock)) {
8580 check_result |= check_privilege(
8581 granted_privileges,
8582 "RELOAD", "*", "*");
8583 reload_checked = true;
8584 }
8585
8586
8587 /* FLUSH TABLES WITH READ LOCK */
8588 if (!opt_no_lock
8589 /* LOCK TABLES FOR BACKUP */
8590 /* UNLOCK TABLES */
8591 && ((have_backup_locks && !opt_no_lock) || opt_slave_info
8592 || opt_binlog_info == BINLOG_INFO_ON)) {
8593 check_result |= check_privilege(
8594 granted_privileges,
8595 "LOCK TABLES", "*", "*");
8596 }
8597
8598 /* SELECT innodb_to_lsn FROM PERCONA_SCHEMA.xtrabackup_history ... */
8599 if (opt_incremental_history_name || opt_incremental_history_uuid) {
8600 check_result |= check_privilege(
8601 granted_privileges,
8602 "SELECT", "PERCONA_SCHEMA", "xtrabackup_history");
8603 }
8604
8605 if (!reload_checked
8606 /* FLUSH BINARY LOGS */
8607 && opt_galera_info) {
8608 check_result |= check_privilege(
8609 granted_privileges,
8610 "RELOAD", "*", "*",
8611 PRIVILEGE_WARNING);
8612 }
8613
8614 /* KILL ... */
8615 if (opt_kill_long_queries_timeout
8616 /* START SLAVE SQL_THREAD */
8617 /* STOP SLAVE SQL_THREAD */
8618 || opt_safe_slave_backup) {
8619 check_result |= check_privilege(
8620 granted_privileges,
8621 "SUPER", "*", "*",
8622 PRIVILEGE_WARNING);
8623 }
8624
8625 /* SHOW MASTER STATUS */
8626 /* SHOW SLAVE STATUS */
8627 if (opt_galera_info || opt_slave_info
8628 || (opt_no_lock && opt_safe_slave_backup)
8629 /* LOCK BINLOG FOR BACKUP */
8630 || (have_backup_locks && !opt_no_lock)) {
8631 check_result |= check_privilege(granted_privileges,
8632 "REPLICATION CLIENT", "*", "*",
8633 PRIVILEGE_WARNING);
8634 }
8635
8636 if (check_result & PRIVILEGE_ERROR) {
8637 exit(EXIT_FAILURE);
8638 }
8639 }
8640
8641 void
handle_options(int argc,char ** argv,int * argc_client,char *** argv_client,int * argc_server,char *** argv_server)8642 handle_options(int argc, char **argv, int *argc_client, char ***argv_client,
8643 int *argc_server, char ***argv_server)
8644 {
8645 int i;
8646 int ho_error;
8647 char conf_file[FN_REFLEN];
8648
8649 char* target_dir = NULL;
8650 bool prepare = false;
8651
8652 *argc_client = argc;
8653 *argc_server = argc;
8654 *argv_client = argv;
8655 *argv_server = argv;
8656
8657 /* scan options for group and config file to load defaults from */
8658 for (i = 1; i < argc; i++) {
8659
8660 char *optend = strcend(argv[i], '=');
8661
8662 if (strncmp(argv[i], "--defaults-group",
8663 optend - argv[i]) == 0) {
8664 defaults_group = optend + 1;
8665 append_defaults_group(defaults_group,
8666 xb_server_default_groups,
8667 array_elements(xb_server_default_groups));
8668 }
8669
8670 if (strncmp(argv[i], "--login-path",
8671 optend - argv[i]) == 0) {
8672 append_defaults_group(optend + 1,
8673 xb_client_default_groups,
8674 array_elements(xb_client_default_groups));
8675 }
8676
8677 if (!strncmp(argv[i], "--prepare",
8678 optend - argv[i])) {
8679 prepare = true;
8680 }
8681
8682 if (!strncmp(argv[i], "--apply-log",
8683 optend - argv[i])) {
8684 prepare = true;
8685 }
8686
8687 if (!strncmp(argv[i], "--target-dir",
8688 optend - argv[i]) && *optend) {
8689 target_dir = optend + 1;
8690 }
8691
8692 if (!*optend && argv[i][0] != '-') {
8693 target_dir = argv[i];
8694 }
8695 }
8696
8697 snprintf(conf_file, sizeof(conf_file), "my");
8698
8699 if (prepare && target_dir) {
8700 snprintf(conf_file, sizeof(conf_file),
8701 "%s/backup-my.cnf", target_dir);
8702 }
8703 if (load_defaults(conf_file, xb_server_default_groups,
8704 argc_server, argv_server)) {
8705 exit(EXIT_FAILURE);
8706 }
8707
8708 print_param_str <<
8709 "# This MySQL options file was generated by XtraBackup.\n"
8710 "[" << defaults_group << "]\n";
8711
8712 /* We want xtrabackup to ignore unknown options, because it only
8713 recognizes a small subset of server variables */
8714 my_getopt_skip_unknown = TRUE;
8715
8716 /* Reset u_max_value for all options, as we don't want the
8717 --maximum-... modifier to set the actual option values */
8718 for (my_option *optp= xb_server_options; optp->name; optp++) {
8719 optp->u_max_value = (G_PTR *) &global_max_value;
8720 }
8721
8722 /* Throw a descriptive error if --defaults-file or --defaults-extra-file
8723 is not the first command line argument */
8724 for (int i = 2 ; i < argc ; i++) {
8725 char *optend = strcend((argv)[i], '=');
8726
8727 if (optend - argv[i] == 15 &&
8728 !strncmp(argv[i], "--defaults-file", optend - argv[i])) {
8729
8730 msg("xtrabackup: Error: --defaults-file "
8731 "must be specified first on the command "
8732 "line\n");
8733 exit(EXIT_FAILURE);
8734 }
8735 if (optend - argv[i] == 21 &&
8736 !strncmp(argv[i], "--defaults-extra-file",
8737 optend - argv[i])) {
8738
8739 msg("xtrabackup: Error: --defaults-extra-file "
8740 "must be specified first on the command "
8741 "line\n");
8742 exit(EXIT_FAILURE);
8743 }
8744 }
8745
8746 if (*argc_server > 0
8747 && (ho_error=handle_options(argc_server, argv_server,
8748 xb_server_options, xb_get_one_option)))
8749 exit(ho_error);
8750
8751 msg("xtrabackup: recognized server arguments: %s\n",
8752 param_str.str().c_str());
8753 param_str.str("");
8754
8755 if (load_defaults(conf_file, xb_client_default_groups,
8756 argc_client, argv_client)) {
8757 exit(EXIT_FAILURE);
8758 }
8759
8760 if (strcmp(base_name(my_progname), INNOBACKUPEX_BIN_NAME) == 0 &&
8761 *argc_client > 0) {
8762 /* emulate innobackupex script */
8763 innobackupex_mode = true;
8764 if (!ibx_handle_options(argc_client, argv_client)) {
8765 exit(EXIT_FAILURE);
8766 }
8767 }
8768
8769 if (*argc_client > 0
8770 && (ho_error=handle_options(argc_client, argv_client,
8771 xb_client_options, xb_get_one_option)))
8772 exit(ho_error);
8773
8774 msg("xtrabackup: recognized client arguments: %s\n",
8775 param_str.str().c_str());
8776 param_str.clear();
8777
8778 /* Reject command line arguments that don't look like options, i.e. are
8779 not of the form '-X' (single-character options) or '--option' (long
8780 options) */
8781 for (int i = 0 ; i < *argc_client ; i++) {
8782 const char * const opt = (*argv_client)[i];
8783
8784 if (strncmp(opt, "--", 2) &&
8785 !(strlen(opt) == 2 && opt[0] == '-')) {
8786 bool server_option = true;
8787
8788 for (int j = 0; j < *argc_server; j++) {
8789 if (opt == (*argv_server)[j]) {
8790 server_option = false;
8791 break;
8792 }
8793 }
8794
8795 if (!server_option) {
8796 msg("xtrabackup: Error:"
8797 " unknown argument: '%s'\n", opt);
8798 exit(EXIT_FAILURE);
8799 }
8800 }
8801 }
8802
8803 if (tty_password) {
8804 opt_password = get_tty_password(NullS);
8805 }
8806
8807 if (tty_transition_key) {
8808 opt_transition_key = get_tty_password("Enter transition key: ");
8809 }
8810 }
8811
setup_error_messages()8812 void setup_error_messages()
8813 {
8814 static const char *all_msgs[4000];
8815 my_default_lc_messages = &my_locale_en_US;
8816 my_default_lc_messages->errmsgs->errmsgs = all_msgs;
8817
8818 struct {
8819 int id;
8820 const char *fmt;
8821 }
8822 xb_msgs[] = {
8823 { ER_DATABASE_NAME,"Database" },
8824 { ER_TABLE_NAME,"Table"},
8825 { ER_PARTITION_NAME, "Partition" },
8826 { ER_SUBPARTITION_NAME, "Subpartition" },
8827 { ER_TEMPORARY_NAME, "Temporary"},
8828 { ER_RENAMED_NAME, "Renamed"},
8829 { ER_CANT_FIND_DL_ENTRY, "Can't find symbol '%-.128s' in library"},
8830 { ER_CANT_OPEN_LIBRARY, "Can't open shared library '%-.192s' (errno: %d, %-.128s)" },
8831 { ER_OUTOFMEMORY, "Out of memory; restart server and try again (needed %d bytes)" },
8832 { ER_CANT_OPEN_LIBRARY, "Can't open shared library '%-.192s' (errno: %d, %-.128s)" },
8833 { ER_UDF_NO_PATHS, "No paths allowed for shared library" },
8834 { ER_CANT_INITIALIZE_UDF,"Can't initialize function '%-.192s'; %-.80s"},
8835 { ER_PLUGIN_IS_NOT_LOADED,"Plugin '%-.192s' is not loaded" }
8836 };
8837
8838 for (int i = 0; i < (int)array_elements(all_msgs); i++) {
8839 all_msgs[i] = "Unknown error";
8840 }
8841
8842 for (int i = 0; i < (int)array_elements(xb_msgs); i++) {
8843 all_msgs[xb_msgs[i].id - 1000] = xb_msgs[i].fmt;
8844 }
8845 }
8846
8847 /* ================= main =================== */
8848
main(int argc,char ** argv)8849 int main(int argc, char **argv)
8850 {
8851 char **client_defaults, **server_defaults;
8852 int client_argc, server_argc;
8853 char cwd[FN_REFLEN];
8854
8855 setup_signals();
8856
8857 MY_INIT(argv[0]);
8858
8859 if (my_create_thread_local_key(&THR_THD,NULL) ||
8860 my_create_thread_local_key(&THR_MALLOC,NULL))
8861 {
8862 exit(EXIT_FAILURE);
8863 }
8864 THR_THD_initialized = true;
8865 THR_MALLOC_initialized = true;
8866
8867 my_thread_set_THR_THD(NULL);
8868
8869 xb_regex_init();
8870
8871 capture_tool_command(argc, argv);
8872
8873 if (mysql_server_init(-1, NULL, NULL))
8874 {
8875 exit(EXIT_FAILURE);
8876 }
8877
8878 system_charset_info= &my_charset_utf8_general_ci;
8879 key_map_full.set_all();
8880
8881 handle_options(argc, argv, &client_argc, &client_defaults,
8882 &server_argc, &server_defaults);
8883
8884 xb_libgcrypt_init();
8885
8886 if (innobackupex_mode) {
8887 if (!ibx_init()) {
8888 exit(EXIT_FAILURE);
8889 }
8890 }
8891
8892 if ((!xtrabackup_print_param) && (!xtrabackup_prepare) && (strcmp(mysql_data_home, "./") == 0)) {
8893 if (!xtrabackup_print_param)
8894 usage();
8895 msg("\nxtrabackup: Error: Please set parameter 'datadir'\n");
8896 exit(EXIT_FAILURE);
8897 }
8898
8899 /* Expand target-dir, incremental-basedir, etc. */
8900
8901 my_getwd(cwd, sizeof(cwd), MYF(0));
8902
8903 my_load_path(xtrabackup_real_target_dir,
8904 xtrabackup_target_dir, cwd);
8905 unpack_dirname(xtrabackup_real_target_dir,
8906 xtrabackup_real_target_dir);
8907 xtrabackup_target_dir= xtrabackup_real_target_dir;
8908
8909 if (xtrabackup_incremental_basedir) {
8910 my_load_path(xtrabackup_real_incremental_basedir,
8911 xtrabackup_incremental_basedir, cwd);
8912 unpack_dirname(xtrabackup_real_incremental_basedir,
8913 xtrabackup_real_incremental_basedir);
8914 xtrabackup_incremental_basedir =
8915 xtrabackup_real_incremental_basedir;
8916 }
8917
8918 if (xtrabackup_incremental_dir) {
8919 my_load_path(xtrabackup_real_incremental_dir,
8920 xtrabackup_incremental_dir, cwd);
8921 unpack_dirname(xtrabackup_real_incremental_dir,
8922 xtrabackup_real_incremental_dir);
8923 xtrabackup_incremental_dir = xtrabackup_real_incremental_dir;
8924 }
8925
8926 if (xtrabackup_extra_lsndir) {
8927 my_load_path(xtrabackup_real_extra_lsndir,
8928 xtrabackup_extra_lsndir, cwd);
8929 unpack_dirname(xtrabackup_real_extra_lsndir,
8930 xtrabackup_real_extra_lsndir);
8931 xtrabackup_extra_lsndir = xtrabackup_real_extra_lsndir;
8932 }
8933
8934 /* get default temporary directory */
8935 if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0]) {
8936 opt_mysql_tmpdir = getenv("TMPDIR");
8937 #if defined(__WIN__)
8938 if (!opt_mysql_tmpdir) {
8939 opt_mysql_tmpdir = getenv("TEMP");
8940 }
8941 if (!opt_mysql_tmpdir) {
8942 opt_mysql_tmpdir = getenv("TMP");
8943 }
8944 #endif
8945 if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0]) {
8946 opt_mysql_tmpdir = const_cast<char*>(DEFAULT_TMPDIR);
8947 }
8948 }
8949
8950 /* temporary setting of enough size */
8951 srv_page_size_shift = UNIV_PAGE_SIZE_SHIFT_MAX;
8952 srv_page_size = UNIV_PAGE_SIZE_MAX;
8953 if (xtrabackup_backup && xtrabackup_incremental) {
8954 /* direct specification is only for --backup */
8955 /* and the lsn is prior to the other option */
8956
8957 char* endchar;
8958 int error = 0;
8959 incremental_lsn = strtoll(xtrabackup_incremental, &endchar, 10);
8960 if (*endchar != '\0')
8961 error = 1;
8962
8963 if (error) {
8964 msg("xtrabackup: value '%s' may be wrong format for "
8965 "incremental option.\n", xtrabackup_incremental);
8966 exit(EXIT_FAILURE);
8967 }
8968 } else if (xtrabackup_backup && xtrabackup_incremental_basedir) {
8969 char filename[FN_REFLEN];
8970
8971 sprintf(filename, "%s/%s", xtrabackup_incremental_basedir,
8972 XTRABACKUP_METADATA_FILENAME);
8973
8974 if (!xtrabackup_read_metadata(filename)) {
8975 msg("xtrabackup: error: failed to read metadata from "
8976 "%s\n", filename);
8977 exit(EXIT_FAILURE);
8978 }
8979
8980 incremental_lsn = metadata_to_lsn;
8981 xtrabackup_incremental = xtrabackup_incremental_basedir; //dummy
8982 } else if (xtrabackup_prepare && xtrabackup_incremental_dir) {
8983 char filename[FN_REFLEN];
8984
8985 sprintf(filename, "%s/%s", xtrabackup_incremental_dir,
8986 XTRABACKUP_METADATA_FILENAME);
8987
8988 if (!xtrabackup_read_metadata(filename)) {
8989 msg("xtrabackup: error: failed to read metadata from "
8990 "%s\n", filename);
8991 exit(EXIT_FAILURE);
8992 }
8993
8994 incremental_lsn = metadata_from_lsn;
8995 incremental_to_lsn = metadata_to_lsn;
8996 incremental_last_lsn = metadata_last_lsn;
8997 incremental_flushed_lsn = backup_redo_log_flushed_lsn;
8998 xtrabackup_incremental = xtrabackup_incremental_dir; //dummy
8999
9000 } else if (opt_incremental_history_name) {
9001 xtrabackup_incremental = opt_incremental_history_name;
9002 } else if (opt_incremental_history_uuid) {
9003 xtrabackup_incremental = opt_incremental_history_uuid;
9004 } else {
9005 xtrabackup_incremental = NULL;
9006 }
9007
9008 if (!xb_init()) {
9009 exit(EXIT_FAILURE);
9010 }
9011
9012 /* --print-param */
9013 if (xtrabackup_print_param) {
9014
9015 printf("%s", print_param_str.str().c_str());
9016
9017 exit(EXIT_SUCCESS);
9018 }
9019
9020 print_version();
9021 if (xtrabackup_incremental) {
9022 msg("incremental backup from " LSN_PF " is enabled.\n",
9023 incremental_lsn);
9024 }
9025
9026 if (xtrabackup_export && innobase_file_per_table == FALSE) {
9027 msg("xtrabackup: auto-enabling --innodb-file-per-table due to "
9028 "the --export option\n");
9029 innobase_file_per_table = TRUE;
9030 }
9031
9032 if (xtrabackup_incremental && xtrabackup_stream &&
9033 xtrabackup_stream_fmt == XB_STREAM_FMT_TAR) {
9034 msg("xtrabackup: error: "
9035 "streaming incremental backups are incompatible with the \n"
9036 "'tar' streaming format. Use --stream=xbstream instead.\n");
9037 exit(EXIT_FAILURE);
9038 }
9039
9040 if ((xtrabackup_compress || xtrabackup_encrypt) && xtrabackup_stream &&
9041 xtrabackup_stream_fmt == XB_STREAM_FMT_TAR) {
9042 msg("xtrabackup: error: "
9043 "compressed and encrypted backups are incompatible with the \n"
9044 "'tar' streaming format. Use --stream=xbstream instead.\n");
9045 exit(EXIT_FAILURE);
9046 }
9047
9048 if (!xtrabackup_prepare &&
9049 (innobase_log_arch_dir || xtrabackup_archived_to_lsn)) {
9050
9051 /* Default my.cnf can contain innobase_log_arch_dir option set
9052 for server, reset it to allow backup. */
9053 innobase_log_arch_dir= NULL;
9054 xtrabackup_archived_to_lsn= 0;
9055 msg("xtrabackup: warning: "
9056 "as --innodb-log-arch-dir and --to-archived-lsn can be used "
9057 "only with --prepare they will be reset\n");
9058 }
9059 if (xtrabackup_throttle && !xtrabackup_backup) {
9060 xtrabackup_throttle = 0;
9061 msg("xtrabackup: warning: --throttle has effect "
9062 "only with --backup\n");
9063 }
9064
9065 if (xtrabackup_backup && xtrabackup_compact) {
9066 msg("xtrabackup: error: compact backups are not supported "
9067 "by this version of xtrabackup\n");
9068 exit(EXIT_FAILURE);
9069 }
9070
9071 /* cannot execute both for now */
9072 {
9073 int num = 0;
9074
9075 if (xtrabackup_backup) num++;
9076 if (xtrabackup_stats) num++;
9077 if (xtrabackup_prepare) num++;
9078 if (xtrabackup_copy_back) num++;
9079 if (xtrabackup_move_back) num++;
9080 if (xtrabackup_decrypt_decompress) num++;
9081 if (num != 1) { /* !XOR (for now) */
9082 usage();
9083 exit(EXIT_FAILURE);
9084 }
9085 }
9086
9087 #ifndef __WIN__
9088 if (xtrabackup_debug_sync) {
9089 signal(SIGCONT, sigcont_handler);
9090 }
9091 #endif
9092
9093 system_charset_info= &my_charset_utf8_general_ci;
9094 files_charset_info= &my_charset_utf8_general_ci;
9095 national_charset_info= &my_charset_utf8_general_ci;
9096 table_alias_charset= &my_charset_bin;
9097 character_set_filesystem= &my_charset_bin;
9098
9099 sys_var_init();
9100 setup_error_messages();
9101
9102 /* --backup */
9103 if (xtrabackup_backup) {
9104 xtrabackup_backup_func();
9105 }
9106
9107 /* --stats */
9108 if (xtrabackup_stats) {
9109 xtrabackup_stats_func(server_argc, server_defaults);
9110 }
9111
9112 /* --prepare */
9113 if (xtrabackup_prepare) {
9114 xtrabackup_prepare_func(server_argc, server_defaults);
9115 }
9116
9117 if (xtrabackup_copy_back || xtrabackup_move_back) {
9118 if (!check_if_param_set("datadir")) {
9119 msg("Error: datadir must be specified.\n");
9120 exit(EXIT_FAILURE);
9121 }
9122 mysql_mutex_init(key_LOCK_keyring_operations,
9123 &LOCK_keyring_operations, MY_MUTEX_INIT_FAST);
9124 if (!copy_back(server_argc, server_defaults)) {
9125 exit(EXIT_FAILURE);
9126 }
9127 mysql_mutex_destroy(&LOCK_keyring_operations);
9128 }
9129
9130 if (xtrabackup_decrypt_decompress && !decrypt_decompress()) {
9131 exit(EXIT_FAILURE);
9132 }
9133
9134 backup_cleanup();
9135
9136 if (innobackupex_mode) {
9137 ibx_cleanup();
9138 }
9139
9140 xb_regex_end();
9141
9142 free_defaults(client_defaults);
9143 free_defaults(server_defaults);
9144
9145 if (THR_THD)
9146 (void) pthread_key_delete(THR_THD);
9147
9148 if (THR_THD_initialized) {
9149 THR_THD_initialized = false;
9150 (void) my_delete_thread_local_key(THR_THD);
9151 }
9152
9153 if (THR_MALLOC_initialized) {
9154 THR_MALLOC_initialized= false;
9155 (void) my_delete_thread_local_key(THR_MALLOC);
9156 }
9157 msg_ts("completed OK!\n");
9158
9159 exit(EXIT_SUCCESS);
9160 }
9161