1
/******************************************************
2
XtraBackup: The another hot backup tool for InnoDB
4
Created 3/3/2009 Yasufumi Kinoshita
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; version 2 of the License.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*******************************************************/
21
#ifndef XTRABACKUP_VERSION
22
#define XTRABACKUP_VERSION "undefined"
24
#ifndef XTRABACKUP_REVISION
25
#define XTRABACKUP_REVISION "undefined"
28
//#define XTRABACKUP_TARGET_IS_PLUGIN
31
#include <my_getopt.h>
32
#include <mysql_version.h>
33
#include <mysql_com.h>
35
#if (MYSQL_VERSION_ID < 50100)
37
#else /* MYSQL_VERSION_ID < 51000 */
43
#include <os0thread.h>
44
#include <srv0start.h>
51
#include <row0mysql.h>
56
#include <lock0lock.h>
57
#include <dict0crea.h>
62
#include <sync0sync.h>
66
#ifdef INNODB_VERSION_SHORT
67
#include <ibuf0ibuf.h>
70
#ifndef INNODB_VERSION_SHORT
71
#define IB_INT64 ib_longlong
73
#define MACH_READ_64 mach_read_from_8
74
#define MACH_WRITE_64 mach_write_to_8
75
#define OS_MUTEX_CREATE() os_mutex_create(NULL)
77
#define IB_INT64 ib_int64_t
78
#define LSN64 ib_uint64_t
79
#if (MYSQL_VERSION_ID < 50500)
80
#define MACH_READ_64 mach_read_ull
81
#define MACH_WRITE_64 mach_write_ull
82
#define OS_MUTEX_CREATE() os_mutex_create(NULL)
84
#define MACH_READ_64 mach_read_from_8
85
#define MACH_WRITE_64 mach_write_to_8
86
#define OS_MUTEX_CREATE() os_mutex_create()
88
#define ut_dulint_zero 0
89
#define ut_dulint_cmp(A, B) (A > B ? 1 : (A == B ? 0 : -1))
90
#define ut_dulint_add(A, B) (A + B)
91
#define ut_dulint_minus(A, B) (A - B)
92
#define ut_dulint_align_down(A, B) (A & ~((ib_int64_t)B - 1))
93
#define ut_dulint_align_up(A, B) ((A + B - 1) & ~((ib_int64_t)B - 1))
97
#define SRV_PATH_SEPARATOR '\\'
98
#define SRV_PATH_SEPARATOR_STR "\\"
100
#define SRV_PATH_SEPARATOR '/'
101
#define SRV_PATH_SEPARATOR_STR "/"
104
#ifndef UNIV_PAGE_SIZE_MAX
105
#define UNIV_PAGE_SIZE_MAX UNIV_PAGE_SIZE
107
#ifndef UNIV_PAGE_SIZE_SHIFT_MAX
108
#define UNIV_PAGE_SIZE_SHIFT_MAX UNIV_PAGE_SIZE_SHIFT
111
#if MYSQL_VERSION_ID >= 50507
113
As of MySQL 5.5.7, InnoDB uses thd_wait plugin service.
114
We have to provide mock functions to avoid linker errors.
116
#include <mysql/plugin.h>
117
#include <mysql/service_thd_wait.h>
119
void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type)
124
void thd_wait_end(MYSQL_THD thd)
129
#endif /* MYSQL_VERSION_ID >= 50507 */
131
/* prototypes for static functions in original */
132
#ifndef INNODB_VERSION_SHORT
134
btr_node_ptr_get_child(
135
/*===================*/
136
/* out: child page, x-latched */
137
rec_t* node_ptr,/* in: node pointer */
138
const ulint* offsets,/* in: array returned by rec_get_offsets() */
139
mtr_t* mtr); /* in: mtr */
142
btr_node_ptr_get_child(
143
/*===================*/
144
const rec_t* node_ptr,/*!< in: node pointer */
145
dict_index_t* index, /*!< in: index */
146
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
147
mtr_t* mtr); /*!< in: mtr */
152
dict_index_t* index, /*!< in: index tree */
153
mtr_t* mtr); /*!< in: mtr */
157
fil_file_readdir_next_file(
158
/*=======================*/
159
/* out: 0 if ok, -1 if error even after the
160
retries, 1 if at the end of the directory */
161
ulint* err, /* out: this is set to DB_ERROR if an error
162
was encountered, otherwise not changed */
163
const char* dirname,/* in: directory name or path */
164
os_file_dir_t dir, /* in: directory stream */
165
os_file_stat_t* info); /* in/out: buffer where the info is returned */
168
recv_check_cp_is_consistent(
169
/*========================*/
170
/* out: TRUE if ok */
171
byte* buf); /* in: buffer containing checkpoint info */
174
recv_find_max_checkpoint(
175
/*=====================*/
176
/* out: error code or DB_SUCCESS */
177
log_group_t** max_group, /* out: max group */
178
ulint* max_field); /* out: LOG_CHECKPOINT_1 or
182
log_block_checksum_is_ok_or_old_format(
183
/*===================================*/
184
/* out: TRUE if ok, or if the log block may be in the
185
format of InnoDB version < 3.23.52 */
186
byte* block); /* in: pointer to a log block */
189
open_or_create_log_file(
190
/*====================*/
191
/* out: DB_SUCCESS or error code */
192
ibool create_new_db, /* in: TRUE if we should create a
194
ibool* log_file_created, /* out: TRUE if new log file
196
ibool log_file_has_been_opened,/* in: TRUE if a log file has been
197
opened before: then it is an error
198
to try to create another log file */
199
ulint k, /* in: log group number */
200
ulint i); /* in: log file number in group */
203
open_or_create_data_files(
204
/*======================*/
205
/* out: DB_SUCCESS or error code */
206
ibool* create_new_db, /* out: TRUE if new database should be
209
ibool* create_new_doublewrite_file,
211
#ifdef UNIV_LOG_ARCHIVE
212
ulint* min_arch_log_no,/* out: min of archived log numbers in data
214
ulint* max_arch_log_no,/* out: */
215
#endif /* UNIV_LOG_ARCHIVE */
216
LSN64* min_flushed_lsn,/* out: min of flushed lsn values in data
218
LSN64* max_flushed_lsn,/* out: */
219
ulint* sum_of_new_sizes);/* out: sum of sizes of the new files added */
224
int fd, /* in: file descriptor to alter */
225
const char* file_name, /* in: used in the diagnostic message */
226
const char* operation_name); /* in: used in the diagnostic message,
227
we call os_file_set_nocache()
228
immediately after opening or creating
229
a file, so this is either "open" or
235
#ifdef POSIX_FADV_NORMAL
236
#define USE_POSIX_FADVISE
239
/* ==start === definition at fil0fil.c === */
240
// ##################################################################
241
// NOTE: We should check the following definitions fit to the source.
242
// ##################################################################
244
#ifndef INNODB_VERSION_SHORT
246
/* File node of a tablespace or the log data space */
247
struct fil_node_struct {
248
fil_space_t* space; /* backpointer to the space where this node
250
char* name; /* path to the file */
251
ibool open; /* TRUE if file open */
252
os_file_t handle; /* OS handle to the file, if file open */
253
ibool is_raw_disk;/* TRUE if the 'file' is actually a raw
254
device or a raw disk partition */
255
ulint size; /* size of the file in database pages, 0 if
256
not known yet; the possible last incomplete
257
megabyte may be ignored if space == 0 */
259
/* count of pending i/o's on this file;
260
closing of the file is not allowed if
262
ulint n_pending_flushes;
263
/* count of pending flushes on this file;
264
closing of the file is not allowed if
266
ib_longlong modification_counter;/* when we write to the file we
267
increment this by one */
268
ib_longlong flush_counter;/* up to what modification_counter value
269
we have flushed the modifications to disk */
270
UT_LIST_NODE_T(fil_node_t) chain;
271
/* link field for the file chain */
272
UT_LIST_NODE_T(fil_node_t) LRU;
273
/* link field for the LRU list */
277
struct fil_space_struct {
278
char* name; /* space name = the path to the first file in
280
ulint id; /* space id */
281
ib_longlong tablespace_version;
282
/* in DISCARD/IMPORT this timestamp is used to
283
check if we should ignore an insert buffer
284
merge request for a page because it actually
285
was for the previous incarnation of the
287
ibool mark; /* this is set to TRUE at database startup if
288
the space corresponds to a table in the InnoDB
289
data dictionary; so we can print a warning of
290
orphaned tablespaces */
291
ibool stop_ios;/* TRUE if we want to rename the .ibd file of
292
tablespace and want to stop temporarily
293
posting of new i/o requests on the file */
294
ibool stop_ibuf_merges;
295
/* we set this TRUE when we start deleting a
296
single-table tablespace */
297
ibool is_being_deleted;
298
/* this is set to TRUE when we start
299
deleting a single-table tablespace and its
300
file; when this flag is set no further i/o
301
or flush requests can be placed on this space,
302
though there may be such requests still being
303
processed on this space */
304
ulint purpose;/* FIL_TABLESPACE, FIL_LOG, or FIL_ARCH_LOG */
305
UT_LIST_BASE_NODE_T(fil_node_t) chain;
306
/* base node for the file chain */
307
ulint size; /* space size in pages; 0 if a single-table
308
tablespace whose size we do not know yet;
309
last incomplete megabytes in data files may be
310
ignored if space == 0 */
311
ulint n_reserved_extents;
312
/* number of reserved free extents for
313
ongoing operations like B-tree page split */
314
ulint n_pending_flushes; /* this is > 0 when flushing
315
the tablespace to disk; dropping of the
316
tablespace is forbidden if this is > 0 */
317
ulint n_pending_ibuf_merges;/* this is > 0 when merging
318
insert buffer entries to a page so that we
319
may need to access the ibuf bitmap page in the
320
tablespade: dropping of the tablespace is
321
forbidden if this is > 0 */
322
hash_node_t hash; /* hash chain node */
323
hash_node_t name_hash;/* hash chain the name_hash table */
324
rw_lock_t latch; /* latch protecting the file space storage
326
UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
327
/* list of spaces with at least one unflushed
328
file we have written to */
329
ibool is_in_unflushed_spaces; /* TRUE if this space is
330
currently in the list above */
331
UT_LIST_NODE_T(fil_space_t) space_list;
332
/* list of all spaces */
333
ibuf_data_t* ibuf_data;
334
/* insert buffer data */
337
typedef struct fil_system_struct fil_system_t;
338
struct fil_system_struct {
339
mutex_t mutex; /* The mutex protecting the cache */
340
hash_table_t* spaces; /* The hash table of spaces in the
341
system; they are hashed on the space
343
hash_table_t* name_hash; /* hash table based on the space
345
UT_LIST_BASE_NODE_T(fil_node_t) LRU;
346
/* base node for the LRU list of the
347
most recently used open files with no
348
pending i/o's; if we start an i/o on
349
the file, we first remove it from this
350
list, and return it to the start of
351
the list when the i/o ends;
352
log files and the system tablespace are
353
not put to this list: they are opened
354
after the startup, and kept open until
356
UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
357
/* base node for the list of those
358
tablespaces whose files contain
359
unflushed writes; those spaces have
360
at least one file node where
361
modification_counter > flush_counter */
362
ulint n_open; /* number of files currently open */
363
ulint max_n_open; /* n_open is not allowed to exceed
365
ib_longlong modification_counter;/* when we write to a file we
366
increment this by one */
367
ulint max_assigned_id;/* maximum space id in the existing
368
tables, or assigned during the time
369
mysqld has been up; at an InnoDB
370
startup we scan the data dictionary
371
and set here the maximum of the
372
space id's of the tables there */
373
ib_longlong tablespace_version;
374
/* a counter which is incremented for
375
every space object memory creation;
376
every space mem object gets a
377
'timestamp' from this; in DISCARD/
378
IMPORT this is used to check if we
379
should ignore an insert buffer merge
381
UT_LIST_BASE_NODE_T(fil_space_t) space_list;
382
/* list of all file spaces */
386
/** File node of a tablespace or the log data space */
387
struct fil_node_struct {
388
fil_space_t* space; /*!< backpointer to the space where this node
390
char* name; /*!< path to the file */
391
ibool open; /*!< TRUE if file open */
392
os_file_t handle; /*!< OS handle to the file, if file open */
393
ibool is_raw_disk;/*!< TRUE if the 'file' is actually a raw
394
device or a raw disk partition */
395
ulint size; /*!< size of the file in database pages, 0 if
396
not known yet; the possible last incomplete
397
megabyte may be ignored if space == 0 */
399
/*!< count of pending i/o's on this file;
400
closing of the file is not allowed if
402
ulint n_pending_flushes;
403
/*!< count of pending flushes on this file;
404
closing of the file is not allowed if
406
ib_int64_t modification_counter;/*!< when we write to the file we
407
increment this by one */
408
ib_int64_t flush_counter;/*!< up to what
409
modification_counter value we have
410
flushed the modifications to disk */
411
UT_LIST_NODE_T(fil_node_t) chain;
412
/*!< link field for the file chain */
413
UT_LIST_NODE_T(fil_node_t) LRU;
414
/*!< link field for the LRU list */
415
ulint magic_n;/*!< FIL_NODE_MAGIC_N */
418
struct fil_space_struct {
419
char* name; /*!< space name = the path to the first file in
421
ulint id; /*!< space id */
422
ib_int64_t tablespace_version;
423
/*!< in DISCARD/IMPORT this timestamp
424
is used to check if we should ignore
425
an insert buffer merge request for a
426
page because it actually was for the
427
previous incarnation of the space */
428
ibool mark; /*!< this is set to TRUE at database startup if
429
the space corresponds to a table in the InnoDB
430
data dictionary; so we can print a warning of
431
orphaned tablespaces */
432
ibool stop_ios;/*!< TRUE if we want to rename the
433
.ibd file of tablespace and want to
434
stop temporarily posting of new i/o
435
requests on the file */
436
ibool stop_ibuf_merges;
437
/*!< we set this TRUE when we start
438
deleting a single-table tablespace */
439
ibool is_being_deleted;
440
/*!< this is set to TRUE when we start
441
deleting a single-table tablespace and its
442
file; when this flag is set no further i/o
443
or flush requests can be placed on this space,
444
though there may be such requests still being
445
processed on this space */
446
ulint purpose;/*!< FIL_TABLESPACE, FIL_LOG, or
448
UT_LIST_BASE_NODE_T(fil_node_t) chain;
449
/*!< base node for the file chain */
450
ulint size; /*!< space size in pages; 0 if a single-table
451
tablespace whose size we do not know yet;
452
last incomplete megabytes in data files may be
453
ignored if space == 0 */
454
ulint flags; /*!< compressed page size and file format, or 0 */
455
ulint n_reserved_extents;
456
/*!< number of reserved free extents for
457
ongoing operations like B-tree page split */
458
ulint n_pending_flushes; /*!< this is positive when flushing
459
the tablespace to disk; dropping of the
460
tablespace is forbidden if this is positive */
461
ulint n_pending_ibuf_merges;/*!< this is positive
462
when merging insert buffer entries to
463
a page so that we may need to access
464
the ibuf bitmap page in the
465
tablespade: dropping of the tablespace
466
is forbidden if this is positive */
467
hash_node_t hash; /*!< hash chain node */
468
hash_node_t name_hash;/*!< hash chain the name_hash table */
469
#ifndef UNIV_HOTBACKUP
470
rw_lock_t latch; /*!< latch protecting the file space storage
472
#endif /* !UNIV_HOTBACKUP */
473
UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
474
/*!< list of spaces with at least one unflushed
475
file we have written to */
476
ibool is_in_unflushed_spaces; /*!< TRUE if this space is
477
currently in unflushed_spaces */
481
UT_LIST_NODE_T(fil_space_t) space_list;
482
/*!< list of all spaces */
483
ulint magic_n;/*!< FIL_SPACE_MAGIC_N */
486
typedef struct fil_system_struct fil_system_t;
488
struct fil_system_struct {
489
#ifndef UNIV_HOTBACKUP
490
mutex_t mutex; /*!< The mutex protecting the cache */
492
mutex_t file_extend_mutex;
494
#endif /* !UNIV_HOTBACKUP */
495
hash_table_t* spaces; /*!< The hash table of spaces in the
496
system; they are hashed on the space
498
hash_table_t* name_hash; /*!< hash table based on the space
500
UT_LIST_BASE_NODE_T(fil_node_t) LRU;
501
/*!< base node for the LRU list of the
502
most recently used open files with no
503
pending i/o's; if we start an i/o on
504
the file, we first remove it from this
505
list, and return it to the start of
506
the list when the i/o ends;
507
log files and the system tablespace are
508
not put to this list: they are opened
509
after the startup, and kept open until
511
UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
512
/*!< base node for the list of those
513
tablespaces whose files contain
514
unflushed writes; those spaces have
515
at least one file node where
516
modification_counter > flush_counter */
517
ulint n_open; /*!< number of files currently open */
518
ulint max_n_open; /*!< n_open is not allowed to exceed
520
ib_int64_t modification_counter;/*!< when we write to a file we
521
increment this by one */
522
ulint max_assigned_id;/*!< maximum space id in the existing
523
tables, or assigned during the time
524
mysqld has been up; at an InnoDB
525
startup we scan the data dictionary
526
and set here the maximum of the
527
space id's of the tables there */
528
ib_int64_t tablespace_version;
529
/*!< a counter which is incremented for
530
every space object memory creation;
531
every space mem object gets a
532
'timestamp' from this; in DISCARD/
533
IMPORT this is used to check if we
534
should ignore an insert buffer merge
536
UT_LIST_BASE_NODE_T(fil_space_t) space_list;
537
/*!< list of all file spaces */
540
#endif /* INNODB_VERSION_SHORT */
546
extern fil_system_t* fil_system;
548
/* ==end=== definition at fil0fil.c === */
551
my_bool innodb_inited= 0;
553
/* === xtrabackup specific options === */
554
char xtrabackup_real_target_dir[FN_REFLEN] = "./xtrabackup_backupfiles/";
555
char *xtrabackup_target_dir= xtrabackup_real_target_dir;
556
my_bool xtrabackup_backup = FALSE;
557
my_bool xtrabackup_stats = FALSE;
558
my_bool xtrabackup_prepare = FALSE;
559
my_bool xtrabackup_print_param = FALSE;
561
my_bool xtrabackup_export = FALSE;
562
my_bool xtrabackup_apply_log_only = FALSE;
564
my_bool xtrabackup_suspend_at_end = FALSE;
565
longlong xtrabackup_use_memory = 100*1024*1024L;
566
my_bool xtrabackup_create_ib_logfile = FALSE;
568
long xtrabackup_throttle = 0; /* 0:unlimited */
570
os_event_t wait_throttle = NULL;
572
my_bool xtrabackup_stream = FALSE;
573
char *xtrabackup_incremental = NULL;
574
LSN64 incremental_lsn;
575
LSN64 incremental_to_lsn;
576
LSN64 incremental_last_lsn;
577
byte* incremental_buffer = NULL;
578
byte* incremental_buffer_base = NULL;
580
char *xtrabackup_incremental_basedir = NULL; /* for --backup */
581
char *xtrabackup_extra_lsndir = NULL; /* for --backup with --extra-lsndir */
582
char *xtrabackup_incremental_dir = NULL; /* for --prepare */
584
char *xtrabackup_tables = NULL;
585
int tables_regex_num;
586
regex_t *tables_regex;
587
regmatch_t tables_regmatch[1];
589
char *xtrabackup_tables_file = NULL;
590
hash_table_t* tables_hash;
592
struct xtrabackup_tables_struct{
594
hash_node_t name_hash;
596
typedef struct xtrabackup_tables_struct xtrabackup_tables_t;
599
static ulint n[SRV_MAX_N_IO_THREADS + 6 + 64];
600
static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6 + 64];
602
static ulint n[SRV_MAX_N_IO_THREADS + 6];
603
static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6];
606
LSN64 checkpoint_lsn_start;
607
LSN64 checkpoint_no_start;
608
LSN64 log_copy_scanned_lsn;
609
IB_INT64 log_copy_offset = 0;
610
ibool log_copying = TRUE;
611
ibool log_copying_running = FALSE;
612
ibool log_copying_succeed = FALSE;
614
ibool xtrabackup_logfile_is_renamed = FALSE;
618
/* === metadata of backup === */
619
#define XTRABACKUP_METADATA_FILENAME "xtrabackup_checkpoints"
620
char metadata_type[30] = ""; /*[full-backuped|full-prepared|incremental]*/
621
#ifndef INNODB_VERSION_SHORT
622
dulint metadata_from_lsn = {0, 0};
623
dulint metadata_to_lsn = {0, 0};
624
dulint metadata_last_lsn = {0, 0};
626
ib_uint64_t metadata_from_lsn = 0;
627
ib_uint64_t metadata_to_lsn = 0;
628
ib_uint64_t metadata_last_lsn = 0;
631
#define XB_DELTA_INFO_SUFFIX ".meta"
633
/* === sharing with thread === */
634
os_file_t dst_log = -1;
635
char dst_log_path[FN_REFLEN];
637
/* === some variables from mysqld === */
638
char mysql_real_data_home[FN_REFLEN] = "./";
639
char *mysql_data_home= mysql_real_data_home;
640
static char mysql_data_home_buff[2];
642
char *opt_mysql_tmpdir = NULL;
643
MY_TMPDIR mysql_tmpdir_list;
645
/* === static parameters in ha_innodb.cc */
647
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
648
#define HA_INNOBASE_RANGE_COUNT 100
650
ulong innobase_large_page_size = 0;
652
/* The default values for the following, type long or longlong, start-up
653
parameters are declared in mysqld.cc: */
655
long innobase_additional_mem_pool_size = 1*1024*1024L;
656
long innobase_buffer_pool_awe_mem_mb = 0;
657
long innobase_file_io_threads = 4;
658
long innobase_read_io_threads = 4;
659
long innobase_write_io_threads = 4;
660
long innobase_force_recovery = 0;
661
long innobase_lock_wait_timeout = 50;
662
long innobase_log_buffer_size = 1024*1024L;
663
long innobase_log_files_in_group = 2;
664
long innobase_log_files_in_group_backup;
665
long innobase_mirrored_log_groups = 1;
666
long innobase_open_files = 300L;
668
long innobase_page_size = (1 << 14); /* 16KB */
669
static ulong innobase_log_block_size = 512;
670
my_bool innobase_fast_checksum = FALSE;
671
my_bool innobase_extra_undoslots = FALSE;
672
char* innobase_doublewrite_file = NULL;
674
longlong innobase_buffer_pool_size = 8*1024*1024L;
675
longlong innobase_log_file_size = 5*1024*1024L;
676
longlong innobase_log_file_size_backup;
678
/* The default values for the following char* start-up parameters
679
are determined in innobase_init below: */
681
char* innobase_data_home_dir = NULL;
682
char* innobase_data_file_path = NULL;
683
char* innobase_log_group_home_dir = NULL;
684
char* innobase_log_group_home_dir_backup = NULL;
685
char* innobase_log_arch_dir = NULL;/* unused */
686
/* The following has a misleading name: starting from 4.0.5, this also
688
char* innobase_unix_file_flush_method = NULL;
690
/* Below we have boolean-valued start-up parameters, and their default
693
ulong innobase_fast_shutdown = 1;
694
my_bool innobase_log_archive = FALSE;/* unused */
695
my_bool innobase_use_doublewrite = TRUE;
696
my_bool innobase_use_checksums = TRUE;
697
my_bool innobase_use_large_pages = FALSE;
698
my_bool innobase_file_per_table = FALSE;
699
my_bool innobase_locks_unsafe_for_binlog = FALSE;
700
my_bool innobase_rollback_on_timeout = FALSE;
701
my_bool innobase_create_status_file = FALSE;
702
my_bool innobase_adaptive_hash_index = TRUE;
704
static char *internal_innobase_data_file_path = NULL;
706
/* The following counter is used to convey information to InnoDB
707
about server activity: in selects it is not sensible to call
708
srv_active_wake_master_thread after each fetch or search, we only do
709
it every INNOBASE_WAKE_INTERVAL'th step. */
711
#define INNOBASE_WAKE_INTERVAL 32
712
ulong innobase_active_counter = 0;
714
/* ======== Datafiles iterator ======== */
716
fil_system_t *system;
725
datafiles_iter_new(fil_system_t *system)
727
datafiles_iter_t *it;
729
it = ut_malloc(sizeof(datafiles_iter_t));
730
it->mutex = OS_MUTEX_CREATE();
742
datafiles_iter_next(datafiles_iter_t *it, ibool *space_changed)
744
os_mutex_enter(it->mutex);
746
*space_changed = FALSE;
748
if (it->node == NULL) {
753
it->node = UT_LIST_GET_NEXT(chain, it->node);
754
if (it->node != NULL)
758
it->space = (it->space == NULL) ?
759
UT_LIST_GET_FIRST(it->system->space_list) :
760
UT_LIST_GET_NEXT(space_list, it->space);
762
while (it->space != NULL &&
763
(it->space->purpose != FIL_TABLESPACE ||
764
UT_LIST_GET_LEN(it->space->chain) == 0))
765
it->space = UT_LIST_GET_NEXT(space_list, it->space);
766
if (it->space == NULL)
768
*space_changed = TRUE;
770
it->node = UT_LIST_GET_FIRST(it->space->chain);
773
os_mutex_exit(it->mutex);
780
datafiles_iter_free(datafiles_iter_t *it)
782
os_mutex_free(it->mutex);
786
/* ======== Date copying thread context ======== */
789
datafiles_iter_t *it;
792
os_mutex_t count_mutex;
794
} data_thread_ctxt_t;
796
/* ======== for option and variables ======== */
798
enum options_xtrabackup
800
OPT_XTRA_TARGET_DIR=256,
805
OPT_XTRA_APPLY_LOG_ONLY,
806
OPT_XTRA_PRINT_PARAM,
807
OPT_XTRA_SUSPEND_AT_END,
811
OPT_XTRA_INCREMENTAL,
812
OPT_XTRA_INCREMENTAL_BASEDIR,
813
OPT_XTRA_EXTRA_LSNDIR,
814
OPT_XTRA_INCREMENTAL_DIR,
816
OPT_XTRA_TABLES_FILE,
817
OPT_XTRA_CREATE_IB_LOGFILE,
819
OPT_INNODB_CHECKSUMS,
820
OPT_INNODB_DATA_FILE_PATH,
821
OPT_INNODB_DATA_HOME_DIR,
822
OPT_INNODB_ADAPTIVE_HASH_INDEX,
823
OPT_INNODB_DOUBLEWRITE,
824
OPT_INNODB_FAST_SHUTDOWN,
825
OPT_INNODB_FILE_PER_TABLE,
826
OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
827
OPT_INNODB_FLUSH_METHOD,
828
OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
829
OPT_INNODB_LOG_ARCH_DIR,
830
OPT_INNODB_LOG_ARCHIVE,
831
OPT_INNODB_LOG_GROUP_HOME_DIR,
832
OPT_INNODB_MAX_DIRTY_PAGES_PCT,
833
OPT_INNODB_MAX_PURGE_LAG,
834
OPT_INNODB_ROLLBACK_ON_TIMEOUT,
835
OPT_INNODB_STATUS_FILE,
836
OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
837
OPT_INNODB_AUTOEXTEND_INCREMENT,
838
OPT_INNODB_BUFFER_POOL_SIZE,
839
OPT_INNODB_COMMIT_CONCURRENCY,
840
OPT_INNODB_CONCURRENCY_TICKETS,
841
OPT_INNODB_FILE_IO_THREADS,
842
#ifdef INNODB_VERSION_SHORT
843
OPT_INNODB_IO_CAPACITY,
844
OPT_INNODB_READ_IO_THREADS,
845
OPT_INNODB_WRITE_IO_THREADS,
848
OPT_INNODB_PAGE_SIZE,
849
OPT_INNODB_LOG_BLOCK_SIZE,
850
OPT_INNODB_FAST_CHECKSUM,
851
OPT_INNODB_EXTRA_UNDOSLOTS,
852
OPT_INNODB_DOUBLEWRITE_FILE,
854
OPT_INNODB_FORCE_RECOVERY,
855
OPT_INNODB_LOCK_WAIT_TIMEOUT,
856
OPT_INNODB_LOG_BUFFER_SIZE,
857
OPT_INNODB_LOG_FILE_SIZE,
858
OPT_INNODB_LOG_FILES_IN_GROUP,
859
OPT_INNODB_MIRRORED_LOG_GROUPS,
860
OPT_INNODB_OPEN_FILES,
861
OPT_INNODB_SYNC_SPIN_LOOPS,
862
OPT_INNODB_THREAD_CONCURRENCY,
863
OPT_INNODB_THREAD_SLEEP_DELAY
866
static struct my_option my_long_options[] =
868
{"target-dir", OPT_XTRA_TARGET_DIR, "destination directory", (G_PTR*) &xtrabackup_target_dir,
869
(G_PTR*) &xtrabackup_target_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
870
{"backup", OPT_XTRA_BACKUP, "take backup to target-dir",
871
(G_PTR*) &xtrabackup_backup, (G_PTR*) &xtrabackup_backup,
872
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
873
{"stats", OPT_XTRA_STATS, "calc statistic of datadir (offline mysqld is recommended)",
874
(G_PTR*) &xtrabackup_stats, (G_PTR*) &xtrabackup_stats,
875
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
876
{"prepare", OPT_XTRA_PREPARE, "prepare a backup for starting mysql server on the backup.",
877
(G_PTR*) &xtrabackup_prepare, (G_PTR*) &xtrabackup_prepare,
878
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
879
{"export", OPT_XTRA_EXPORT, "create files to import to another database when prepare.",
880
(G_PTR*) &xtrabackup_export, (G_PTR*) &xtrabackup_export,
881
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
882
{"apply-log-only", OPT_XTRA_APPLY_LOG_ONLY,
883
"stop recovery process not to progress LSN after applying log when prepare.",
884
(G_PTR*) &xtrabackup_apply_log_only, (G_PTR*) &xtrabackup_apply_log_only,
885
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
886
{"print-param", OPT_XTRA_PRINT_PARAM, "print parameter of mysqld needed for copyback.",
887
(G_PTR*) &xtrabackup_print_param, (G_PTR*) &xtrabackup_print_param,
888
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
889
{"use-memory", OPT_XTRA_USE_MEMORY, "The value is used instead of buffer_pool_size",
890
(G_PTR*) &xtrabackup_use_memory, (G_PTR*) &xtrabackup_use_memory,
891
0, GET_LL, REQUIRED_ARG, 100*1024*1024L, 1024*1024L, LONGLONG_MAX, 0,
893
{"suspend-at-end", OPT_XTRA_SUSPEND_AT_END, "creates a file 'xtrabackup_suspended' and waits until the user deletes that file at the end of '--backup'",
894
(G_PTR*) &xtrabackup_suspend_at_end, (G_PTR*) &xtrabackup_suspend_at_end,
895
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
896
{"throttle", OPT_XTRA_THROTTLE, "limit count of IO operations (pairs of read&write) per second to IOS values (for '--backup')",
897
(G_PTR*) &xtrabackup_throttle, (G_PTR*) &xtrabackup_throttle,
898
0, GET_LONG, REQUIRED_ARG, 0, 0, LONG_MAX, 0, 1, 0},
899
{"log-stream", OPT_XTRA_STREAM, "outputs the contents of 'xtrabackup_logfile' to stdout only until the file 'xtrabackup_suspended' deleted (for '--backup').",
900
(G_PTR*) &xtrabackup_stream, (G_PTR*) &xtrabackup_stream,
901
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
902
{"extra-lsndir", OPT_XTRA_EXTRA_LSNDIR, "(for --backup): save an extra copy of the xtrabackup_checkpoints file in this directory.",
903
(G_PTR*) &xtrabackup_extra_lsndir, (G_PTR*) &xtrabackup_extra_lsndir,
904
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
905
{"incremental-lsn", OPT_XTRA_INCREMENTAL, "(for --backup): copy only .ibd pages newer than specified LSN 'high:low'. ##ATTENTION##: checkpoint lsn must be used. anyone can detect your mistake. be carefully!",
906
(G_PTR*) &xtrabackup_incremental, (G_PTR*) &xtrabackup_incremental,
907
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
908
{"incremental-basedir", OPT_XTRA_INCREMENTAL_BASEDIR, "(for --backup): copy only .ibd pages newer than backup at specified directory.",
909
(G_PTR*) &xtrabackup_incremental_basedir, (G_PTR*) &xtrabackup_incremental_basedir,
910
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
911
{"incremental-dir", OPT_XTRA_INCREMENTAL_DIR, "(for --prepare): apply .delta files and logfile in the specified directory.",
912
(G_PTR*) &xtrabackup_incremental_dir, (G_PTR*) &xtrabackup_incremental_dir,
913
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
914
{"tables", OPT_XTRA_TABLES, "filtering by regexp for table names.",
915
(G_PTR*) &xtrabackup_tables, (G_PTR*) &xtrabackup_tables,
916
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
917
{"tables_file", OPT_XTRA_TABLES_FILE, "filtering by list of the exact database.table name in the file.",
918
(G_PTR*) &xtrabackup_tables_file, (G_PTR*) &xtrabackup_tables_file,
919
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
920
{"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. ###",
921
(G_PTR*) &xtrabackup_create_ib_logfile, (G_PTR*) &xtrabackup_create_ib_logfile,
922
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
924
{"datadir", 'h', "Path to the database root.", (G_PTR*) &mysql_data_home,
925
(G_PTR*) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
927
"Path for temporary files. Several paths may be specified, separated by a "
928
#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
933
", in this case they are used in a round-robin fashion.",
934
(G_PTR*) &opt_mysql_tmpdir,
935
(G_PTR*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
936
{"parallel", OPT_XTRA_PARALLEL,
937
"Number of threads to use for parallel datafiles transfer. Does not have "
938
"any effect in the stream mode. The default value is 1.",
939
(G_PTR*) ¶llel, (G_PTR*) ¶llel, 0, GET_UINT, REQUIRED_ARG,
940
1, 1, UINT_MAX, 0, 0, 0},
942
{"innodb_adaptive_hash_index", OPT_INNODB_ADAPTIVE_HASH_INDEX,
943
"Enable InnoDB adaptive hash index (enabled by default). "
944
"Disable with --skip-innodb-adaptive-hash-index.",
945
(G_PTR*) &innobase_adaptive_hash_index,
946
(G_PTR*) &innobase_adaptive_hash_index,
947
0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
948
{"innodb_additional_mem_pool_size", OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
949
"Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
950
(G_PTR*) &innobase_additional_mem_pool_size,
951
(G_PTR*) &innobase_additional_mem_pool_size, 0, GET_LONG, REQUIRED_ARG,
952
1*1024*1024L, 512*1024L, LONG_MAX, 0, 1024, 0},
953
{"innodb_autoextend_increment", OPT_INNODB_AUTOEXTEND_INCREMENT,
954
"Data file autoextend increment in megabytes",
955
(G_PTR*) &srv_auto_extend_increment,
956
(G_PTR*) &srv_auto_extend_increment,
957
0, GET_ULONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0},
958
{"innodb_buffer_pool_size", OPT_INNODB_BUFFER_POOL_SIZE,
959
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
960
(G_PTR*) &innobase_buffer_pool_size, (G_PTR*) &innobase_buffer_pool_size, 0,
961
GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 0,
963
{"innodb_checksums", OPT_INNODB_CHECKSUMS, "Enable InnoDB checksums validation (enabled by default). \
964
Disable with --skip-innodb-checksums.", (G_PTR*) &innobase_use_checksums,
965
(G_PTR*) &innobase_use_checksums, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
967
{"innodb_commit_concurrency", OPT_INNODB_COMMIT_CONCURRENCY,
968
"Helps in performance tuning in heavily concurrent environments.",
969
(G_PTR*) &srv_commit_concurrency, (G_PTR*) &srv_commit_concurrency,
970
0, GET_ULONG, REQUIRED_ARG, 0, 0, 1000, 0, 1, 0},
973
{"innodb_concurrency_tickets", OPT_INNODB_CONCURRENCY_TICKETS,
974
"Number of times a thread is allowed to enter InnoDB within the same \
975
SQL query after it has once got the ticket",
976
(G_PTR*) &srv_n_free_tickets_to_enter,
977
(G_PTR*) &srv_n_free_tickets_to_enter,
978
0, GET_ULONG, REQUIRED_ARG, 500L, 1L, ULONG_MAX, 0, 1L, 0},
980
{"innodb_data_file_path", OPT_INNODB_DATA_FILE_PATH,
981
"Path to individual files and their sizes.", (G_PTR*) &innobase_data_file_path,
982
(G_PTR*) &innobase_data_file_path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
983
{"innodb_data_home_dir", OPT_INNODB_DATA_HOME_DIR,
984
"The common part for InnoDB table spaces.", (G_PTR*) &innobase_data_home_dir,
985
(G_PTR*) &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0,
987
{"innodb_doublewrite", OPT_INNODB_DOUBLEWRITE, "Enable InnoDB doublewrite buffer (enabled by default). \
988
Disable with --skip-innodb-doublewrite.", (G_PTR*) &innobase_use_doublewrite,
989
(G_PTR*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
990
#ifdef INNODB_VERSION_SHORT
991
{"innodb_io_capacity", OPT_INNODB_IO_CAPACITY,
992
"Number of IOPs the server can do. Tunes the background IO rate",
993
(G_PTR*) &srv_io_capacity, (G_PTR*) &srv_io_capacity,
994
0, GET_ULONG, OPT_ARG, 200, 100, ~0L, 0, 0, 0},
997
{"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN,
998
"Speeds up the shutdown process of the InnoDB storage engine. Possible "
999
"values are 0, 1 (faster)"
1000
" or 2 (fastest - crash-like)"
1002
(G_PTR*) &innobase_fast_shutdown,
1003
(G_PTR*) &innobase_fast_shutdown, 0, GET_ULONG, OPT_ARG, 1, 0,
1006
{"innodb_file_io_threads", OPT_INNODB_FILE_IO_THREADS,
1007
"Number of file I/O threads in InnoDB.", (G_PTR*) &innobase_file_io_threads,
1008
(G_PTR*) &innobase_file_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 4, 64, 0,
1010
#ifdef INNODB_VERSION_SHORT
1011
{"innodb_read_io_threads", OPT_INNODB_READ_IO_THREADS,
1012
"Number of background read I/O threads in InnoDB.", (G_PTR*) &innobase_read_io_threads,
1013
(G_PTR*) &innobase_read_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 1, 64, 0,
1015
{"innodb_write_io_threads", OPT_INNODB_WRITE_IO_THREADS,
1016
"Number of background write I/O threads in InnoDB.", (G_PTR*) &innobase_write_io_threads,
1017
(G_PTR*) &innobase_write_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 1, 64, 0,
1020
{"innodb_file_per_table", OPT_INNODB_FILE_PER_TABLE,
1021
"Stores each InnoDB table to an .ibd file in the database dir.",
1022
(G_PTR*) &innobase_file_per_table,
1023
(G_PTR*) &innobase_file_per_table, 0, GET_BOOL, NO_ARG,
1024
#if (MYSQL_VERSION_ID < 50500)
1030
{"innodb_flush_log_at_trx_commit", OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
1031
"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).",
1032
(G_PTR*) &srv_flush_log_at_trx_commit,
1033
(G_PTR*) &srv_flush_log_at_trx_commit,
1034
0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0},
1035
{"innodb_flush_method", OPT_INNODB_FLUSH_METHOD,
1036
"With which method to flush data.", (G_PTR*) &innobase_unix_file_flush_method,
1037
(G_PTR*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
1040
/* ####### Should we use this option? ####### */
1041
{"innodb_force_recovery", OPT_INNODB_FORCE_RECOVERY,
1042
"Helps to save your data in case the disk image of the database becomes corrupt.",
1043
(G_PTR*) &innobase_force_recovery, (G_PTR*) &innobase_force_recovery, 0,
1044
GET_LONG, REQUIRED_ARG, 0, 0, 6, 0, 1, 0},
1046
{"innodb_lock_wait_timeout", OPT_INNODB_LOCK_WAIT_TIMEOUT,
1047
"Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back.",
1048
(G_PTR*) &innobase_lock_wait_timeout, (G_PTR*) &innobase_lock_wait_timeout,
1049
0, GET_LONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
1051
{"innodb_locks_unsafe_for_binlog", OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
1052
"Force InnoDB not to use next-key locking. Instead use only row-level locking",
1053
(G_PTR*) &innobase_locks_unsafe_for_binlog,
1054
(G_PTR*) &innobase_locks_unsafe_for_binlog, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1057
{"innodb_log_arch_dir", OPT_INNODB_LOG_ARCH_DIR,
1058
"Where full logs should be archived.", (G_PTR*) &innobase_log_arch_dir,
1059
(G_PTR*) &innobase_log_arch_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1061
{"innodb_log_buffer_size", OPT_INNODB_LOG_BUFFER_SIZE,
1062
"The size of the buffer which InnoDB uses to write log to the log files on disk.",
1063
(G_PTR*) &innobase_log_buffer_size, (G_PTR*) &innobase_log_buffer_size, 0,
1064
GET_LONG, REQUIRED_ARG, 1024*1024L, 256*1024L, LONG_MAX, 0, 1024, 0},
1065
{"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE,
1066
"Size of each log file in a log group.",
1067
(G_PTR*) &innobase_log_file_size, (G_PTR*) &innobase_log_file_size, 0,
1068
GET_LL, REQUIRED_ARG, 5*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 0,
1070
{"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP,
1071
"Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
1072
(G_PTR*) &innobase_log_files_in_group, (G_PTR*) &innobase_log_files_in_group,
1073
0, GET_LONG, REQUIRED_ARG, 2, 2, 100, 0, 1, 0},
1074
{"innodb_log_group_home_dir", OPT_INNODB_LOG_GROUP_HOME_DIR,
1075
"Path to InnoDB log files.", (G_PTR*) &innobase_log_group_home_dir,
1076
(G_PTR*) &innobase_log_group_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
1078
{"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT,
1079
"Percentage of dirty pages allowed in bufferpool.", (G_PTR*) &srv_max_buf_pool_modified_pct,
1080
(G_PTR*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0},
1082
{"innodb_max_purge_lag", OPT_INNODB_MAX_PURGE_LAG,
1083
"Desired maximum length of the purge queue (0 = no limit)",
1084
(G_PTR*) &srv_max_purge_lag,
1085
(G_PTR*) &srv_max_purge_lag, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ULONG_MAX,
1089
{"innodb_mirrored_log_groups", OPT_INNODB_MIRRORED_LOG_GROUPS,
1090
"Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
1091
(G_PTR*) &innobase_mirrored_log_groups,
1092
(G_PTR*) &innobase_mirrored_log_groups, 0, GET_LONG, REQUIRED_ARG, 1, 1, 10,
1095
{"innodb_open_files", OPT_INNODB_OPEN_FILES,
1096
"How many files at the maximum InnoDB keeps open at the same time.",
1097
(G_PTR*) &innobase_open_files, (G_PTR*) &innobase_open_files, 0,
1098
GET_LONG, REQUIRED_ARG, 300L, 10L, LONG_MAX, 0, 1L, 0},
1100
{"innodb_page_size", OPT_INNODB_PAGE_SIZE,
1101
"The universal page size of the database.",
1102
(G_PTR*) &innobase_page_size, (G_PTR*) &innobase_page_size, 0,
1103
GET_LONG, REQUIRED_ARG, (1 << 14), (1 << 12), (1 << UNIV_PAGE_SIZE_SHIFT_MAX), 0, 1L, 0},
1104
{"innodb_log_block_size", OPT_INNODB_LOG_BLOCK_SIZE,
1105
"###EXPERIMENTAL###: The log block size of the transaction log file. "
1106
"Changing for created log file is not supported. Use on your own risk!",
1107
(G_PTR*) &innobase_log_block_size, (G_PTR*) &innobase_log_block_size, 0,
1108
GET_ULONG, REQUIRED_ARG, 512, 512, 1 << UNIV_PAGE_SIZE_SHIFT_MAX, 0, 1L, 0},
1109
{"innodb_fast_checksum", OPT_INNODB_FAST_CHECKSUM,
1110
"Change the algorithm of checksum for the whole of datapage to 4-bytes word based.",
1111
(G_PTR*) &innobase_fast_checksum,
1112
(G_PTR*) &innobase_fast_checksum, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1113
{"innodb_extra_undoslots", OPT_INNODB_EXTRA_UNDOSLOTS,
1114
"Enable to use about 4000 undo slots instead of default 1024. Not recommended to use, "
1115
"Because it is not change back to disable, once it is used.",
1116
(G_PTR*) &innobase_extra_undoslots, (G_PTR*) &innobase_extra_undoslots,
1117
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1118
{"innodb_doublewrite_file", OPT_INNODB_DOUBLEWRITE_FILE,
1119
"Path to special datafile for doublewrite buffer. (default is "": not used)",
1120
(G_PTR*) &innobase_doublewrite_file, (G_PTR*) &innobase_doublewrite_file,
1121
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1124
{"innodb_rollback_on_timeout", OPT_INNODB_ROLLBACK_ON_TIMEOUT,
1125
"Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
1126
(G_PTR*) &innobase_rollback_on_timeout, (G_PTR*) &innobase_rollback_on_timeout,
1127
0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
1130
{"innodb_status_file", OPT_INNODB_STATUS_FILE,
1131
"Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
1132
(G_PTR*) &innobase_create_status_file, (G_PTR*) &innobase_create_status_file,
1133
0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
1136
{"innodb_sync_spin_loops", OPT_INNODB_SYNC_SPIN_LOOPS,
1137
"Count of spin-loop rounds in InnoDB mutexes",
1138
(G_PTR*) &srv_n_spin_wait_rounds,
1139
(G_PTR*) &srv_n_spin_wait_rounds,
1140
0, GET_ULONG, REQUIRED_ARG, 20L, 0L, ULONG_MAX, 0, 1L, 0},
1143
{"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY,
1144
"Helps in performance tuning in heavily concurrent environments. "
1145
"Sets the maximum number of threads allowed inside InnoDB. Value 0"
1146
" will disable the thread throttling.",
1147
(G_PTR*) &srv_thread_concurrency, (G_PTR*) &srv_thread_concurrency,
1148
0, GET_ULONG, REQUIRED_ARG, 8, 0, 1000, 0, 1, 0},
1151
{"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY,
1152
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0"
1154
(G_PTR*) &srv_thread_sleep_delay,
1155
(G_PTR*) &srv_thread_sleep_delay,
1156
0, GET_ULONG, REQUIRED_ARG, 10000L, 0L, ULONG_MAX, 0, 1L, 0},
1159
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1162
static const char *load_default_groups[]= { "mysqld","xtrabackup",0 };
1164
static void print_version(void)
1166
printf("%s Ver %s Rev %s for %s %s (%s)\n" ,my_progname,
1167
XTRABACKUP_VERSION, XTRABACKUP_REVISION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
1170
static void usage(void)
1172
puts("Open source backup tool for InnoDB and XtraDB\n\
1174
Copyright (C) 2009 Percona Inc.\n\
1176
This program is free software; you can redistribute it and/or\n\
1177
modify it under the terms of the GNU General Public License\n\
1178
as published by the Free Software Foundation version 2\n\
1181
This program is distributed in the hope that it will be useful,\n\
1182
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
1183
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
1184
GNU General Public License for more details.\n\
1186
You can download full text of the license on http://www.gnu.org/licenses/gpl-2.0.txt\n");
1188
printf("Usage: [%s [--defaults-file=#] --backup | %s [--defaults-file=#] --prepare] [OPTIONS]\n",my_progname,my_progname);
1189
print_defaults("my",load_default_groups);
1190
my_print_help(my_long_options);
1191
my_print_variables(my_long_options);
1195
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1200
strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
1201
mysql_data_home= mysql_real_data_home;
1203
case OPT_XTRA_TARGET_DIR:
1204
strmake(xtrabackup_real_target_dir,argument, sizeof(xtrabackup_real_target_dir)-1);
1205
xtrabackup_target_dir= xtrabackup_real_target_dir;
1217
/* ================ Dummys =================== */
1220
thd_is_replication_slave_thread(
1223
fprintf(stderr, "xtrabackup: thd_is_replication_slave_thread() is called\n");
1228
thd_has_edited_nontrans_tables(
1231
fprintf(stderr, "xtrabackup: thd_has_edited_nontrans_tables() is called\n");
1239
fprintf(stderr, "xtrabackup: thd_is_select() is called\n");
1244
innobase_mysql_prepare_print_arbitrary_thd(void)
1250
innobase_mysql_end_print_arbitrary_thd(void)
1256
innobase_mysql_print_thd(
1261
fprintf(stderr, "xtrabackup: innobase_mysql_print_thd() is called\n");
1265
innobase_get_cset_width(
1275
cs = all_charsets[cset];
1277
*mbminlen = cs->mbminlen;
1278
*mbmaxlen = cs->mbmaxlen;
1281
*mbminlen = *mbmaxlen = 0;
1286
innobase_convert_from_table_id(
1287
#ifdef INNODB_VERSION_SHORT
1288
struct charset_info_st* cs,
1294
fprintf(stderr, "xtrabackup: innobase_convert_from_table_id() is called\n");
1298
innobase_convert_from_id(
1299
#ifdef INNODB_VERSION_SHORT
1300
struct charset_info_st* cs,
1306
fprintf(stderr, "xtrabackup: innobase_convert_from_id() is called\n");
1310
innobase_strcasecmp(
1314
return(my_strcasecmp(&my_charset_utf8_general_ci, a, b));
1318
innobase_casedn_str(
1321
my_casedn_str(&my_charset_utf8_general_ci, a);
1324
struct charset_info_st*
1325
innobase_get_charset(
1328
fprintf(stderr, "xtrabackup: innobase_get_charset() is called\n");
1337
fprintf(stderr, "xtrabackup: innobase_get_stmt() is called\n");
1342
innobase_mysql_tmpfile(void)
1344
char filename[FN_REFLEN];
1346
File fd = create_temp_file(filename, my_tmpdir(&mysql_tmpdir_list), "ib",
1348
O_BINARY | O_TRUNC | O_SEQUENTIAL |
1349
O_TEMPORARY | O_SHORT_LIVED |
1350
#endif /* __WIN__ */
1351
O_CREAT | O_EXCL | O_RDWR,
1355
/* On Windows, open files cannot be removed, but files can be
1356
created with the O_TEMPORARY flag to the same effect
1357
("delete on close"). */
1359
#endif /* !__WIN__ */
1360
/* Copy the file descriptor, so that the additional resources
1361
allocated by create_temp_file() can be freed by invoking
1364
Because the file descriptor returned by this function
1365
will be passed to fdopen(), it will be closed by invoking
1366
fclose(), which in turn will invoke close() instead of
1370
fprintf(stderr, "xtrabackup: Got error %d on dup\n",fd2);
1372
my_close(fd, MYF(MY_WME));
1378
innobase_invalidate_query_cache(
1380
#ifndef INNODB_VERSION_SHORT
1383
const char* full_name,
1385
ulint full_name_len)
1391
mysql_get_identifier_quote_char(
1400
innobase_print_identifier(
1407
const char* s = name;
1408
const char* e = s + namelen;
1424
/*****************************************************************//**
1425
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1426
and quote it if needed.
1427
@return pointer to the end of buf */
1430
innobase_convert_identifier(
1431
/*========================*/
1432
char* buf, /*!< out: buffer for converted identifier */
1433
ulint buflen, /*!< in: length of buf, in bytes */
1434
const char* id, /*!< in: identifier to convert */
1435
ulint idlen, /*!< in: length of id, in bytes */
1436
void* thd, /*!< in: MySQL connection thread, or NULL */
1437
ibool file_id)/*!< in: TRUE=id is a table or database name;
1438
FALSE=id is an UTF-8 string */
1443
/* See if the identifier needs to be quoted. */
1447
if (UNIV_UNLIKELY(idlen > buflen)) {
1450
memcpy(buf, s, idlen);
1451
return(buf + idlen);
1454
/* Quote the identifier. */
1462
for (; idlen; idlen--) {
1464
if (UNIV_UNLIKELY(c == q)) {
1465
if (UNIV_UNLIKELY(buflen < 3)) {
1473
if (UNIV_UNLIKELY(buflen < 2)) {
1486
/*****************************************************************//**
1487
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1488
and quote it if needed.
1489
@return pointer to the end of buf */
1491
innobase_convert_name(
1492
/*==================*/
1493
char* buf, /*!< out: buffer for converted identifier */
1494
ulint buflen, /*!< in: length of buf, in bytes */
1495
const char* id, /*!< in: identifier to convert */
1496
ulint idlen, /*!< in: length of id, in bytes */
1497
void* thd, /*!< in: MySQL connection thread, or NULL */
1498
ibool table_id)/*!< in: TRUE=id is a table or database name;
1499
FALSE=id is an index name */
1502
const char* bufend = buf + buflen;
1505
const char* slash = (const char*) memchr(id, '/', idlen);
1511
/* Print the database name and table name separately. */
1512
s = innobase_convert_identifier(s, bufend - s, id, slash - id,
1514
if (UNIV_LIKELY(s < bufend)) {
1516
s = innobase_convert_identifier(s, bufend - s,
1521
#ifdef INNODB_VERSION_SHORT
1522
} else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
1523
/* Temporary index name (smart ALTER TABLE) */
1524
const char temp_index_suffix[]= "--temporary--";
1526
s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
1528
if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
1529
memcpy(s, temp_index_suffix,
1530
sizeof temp_index_suffix - 1);
1531
s += sizeof temp_index_suffix - 1;
1536
s = innobase_convert_identifier(buf, buflen, id, idlen,
1548
/* There are no mysql_thd */
1555
uint charset_number,
1557
unsigned int a_length,
1559
unsigned int b_length)
1561
CHARSET_INFO* charset;
1562
enum enum_field_types mysql_tp;
1565
DBUG_ASSERT(a_length != UNIV_SQL_NULL);
1566
DBUG_ASSERT(b_length != UNIV_SQL_NULL);
1568
mysql_tp = (enum enum_field_types) mysql_type;
1572
case MYSQL_TYPE_BIT:
1573
case MYSQL_TYPE_STRING:
1574
case MYSQL_TYPE_VAR_STRING:
1575
case FIELD_TYPE_TINY_BLOB:
1576
case FIELD_TYPE_MEDIUM_BLOB:
1577
case FIELD_TYPE_BLOB:
1578
case FIELD_TYPE_LONG_BLOB:
1579
case MYSQL_TYPE_VARCHAR:
1580
/* Use the charset number to pick the right charset struct for
1581
the comparison. Since the MySQL function get_charset may be
1582
slow before Bar removes the mutex operation there, we first
1583
look at 2 common charsets directly. */
1585
if (charset_number == default_charset_info->number) {
1586
charset = default_charset_info;
1587
} else if (charset_number == my_charset_latin1.number) {
1588
charset = &my_charset_latin1;
1590
charset = get_charset(charset_number, MYF(MY_WME));
1592
if (charset == NULL) {
1593
fprintf(stderr, "xtrabackup: InnoDB needs charset %lu for doing "
1594
"a comparison, but MySQL cannot "
1595
"find that charset.\n",
1596
(ulong) charset_number);
1601
/* Starting from 4.1.3, we use strnncollsp() in comparisons of
1602
non-latin1_swedish_ci strings. NOTE that the collation order
1603
changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
1604
having indexes on such data need to rebuild their tables! */
1606
ret = charset->coll->strnncollsp(charset,
1611
} else if (ret > 0) {
1624
innobase_get_at_most_n_mbchars(
1630
ulint char_length; /* character length in bytes */
1631
ulint n_chars; /* number of characters in prefix */
1632
CHARSET_INFO* charset; /* charset used in the field */
1634
charset = get_charset((uint) charset_id, MYF(MY_WME));
1637
ut_ad(charset->mbmaxlen);
1639
/* Calculate how many characters at most the prefix index contains */
1641
n_chars = prefix_len / charset->mbmaxlen;
1643
/* If the charset is multi-byte, then we must find the length of the
1644
first at most n chars in the string. If the string contains less
1645
characters than n, then we return the length to the end of the last
1648
if (charset->mbmaxlen > 1) {
1649
/* my_charpos() returns the byte length of the first n_chars
1650
characters, or a value bigger than the length of str, if
1651
there were not enough full characters in str.
1653
Why does the code below work:
1654
Suppose that we are looking for n UTF-8 characters.
1656
1) If the string is long enough, then the prefix contains at
1657
least n complete UTF-8 characters + maybe some extra
1658
characters + an incomplete UTF-8 character. No problem in
1659
this case. The function returns the pointer to the
1660
end of the nth character.
1662
2) If the string is not long enough, then the string contains
1663
the complete value of a column, that is, only complete UTF-8
1664
characters, and we can store in the column prefix index the
1667
char_length = my_charpos(charset, str,
1668
str + data_len, (int) n_chars);
1669
if (char_length > data_len) {
1670
char_length = data_len;
1673
if (data_len < prefix_len) {
1674
char_length = data_len;
1676
char_length = prefix_len;
1680
return(char_length);
1684
innobase_query_is_update(void)
1686
fprintf(stderr, "xtrabackup: innobase_query_is_update() is called\n");
1690
#ifdef INNODB_VERSION_SHORT
1692
innobase_raw_format(
1693
/*================*/
1694
const char* data, /*!< in: raw data */
1695
ulint data_len, /*!< in: raw data length
1697
ulint charset_coll, /*!< in: charset collation */
1698
char* buf, /*!< out: output buffer */
1699
ulint buf_size) /*!< in: output buffer size
1702
fprintf(stderr, "xtrabackup: innobase_raw_format() is called\n");
1707
thd_lock_wait_timeout(
1708
/*==================*/
1709
void* thd) /*!< in: thread handle (THD*), or NULL to query
1710
the global innodb_lock_wait_timeout */
1712
return(innobase_lock_wait_timeout);
1718
void* thd) /*!< in: thread handle (THD*), or NULL to query
1719
the global innodb_supports_xa */
1727
trx_t* trx) /*!< in: transaction */
1740
innobase_get_slow_log()
1747
/***********************************************************************
1748
Computes bit shift for a given value. If the argument is not a power
1752
get_bit_shift(ulint value)
1759
for (shift = 0; !(value & 1UL); shift++) {
1762
return (value >> 1) ? 0 : shift;
1766
innodb_init_param(void)
1769
static char current_dir[3]; /* Set if using current lib */
1773
/* === some variables from mysqld === */
1774
bzero((G_PTR) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
1776
if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
1779
/* dummy for initialize all_charsets[] */
1780
get_charset_name(0);
1784
srv_page_size_shift = 0;
1786
if (innobase_page_size != (1 << 14)) {
1787
int n_shift = get_bit_shift(innobase_page_size);
1789
if (n_shift >= 12 && n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX) {
1791
"InnoDB: Warning: innodb_page_size has been "
1792
"changed from default value 16384.\n",
1793
innobase_page_size);
1794
srv_page_size_shift = n_shift;
1795
srv_page_size = 1 << n_shift;
1797
"InnoDB: The universal page size of the "
1798
"database is set to %lu.\n", srv_page_size);
1800
fprintf(stderr, "InnoDB: Error: invalid value of "
1801
"innobase_page_size: %lu", innobase_page_size);
1805
srv_page_size_shift = 14;
1806
srv_page_size = (1 << srv_page_size_shift);
1809
srv_log_block_size = 0;
1810
if (innobase_log_block_size != 512) {
1811
uint n_shift = get_bit_shift(innobase_log_block_size);;
1814
"InnoDB: Warning: innodb_log_block_size has "
1815
"been changed from its default value. "
1816
"(###EXPERIMENTAL### operation)\n");
1818
srv_log_block_size = (1 << n_shift);
1820
"InnoDB: The log block size is set to %lu.\n",
1821
srv_log_block_size);
1824
srv_log_block_size = 512;
1827
if (!srv_log_block_size) {
1829
"InnoDB: Error: %lu is not valid value for "
1830
"innodb_log_block_size.\n", innobase_log_block_size);
1834
srv_fast_checksum = (ibool) innobase_fast_checksum;
1837
/* Check that values don't overflow on 32-bit systems. */
1838
if (sizeof(ulint) == 4) {
1839
if (xtrabackup_use_memory > UINT_MAX32) {
1841
"xtrabackup: use-memory can't be over 4GB"
1842
" on 32-bit systems\n");
1845
if (innobase_buffer_pool_size > UINT_MAX32) {
1847
"xtrabackup: innobase_buffer_pool_size can't be over 4GB"
1848
" on 32-bit systems\n");
1853
if (innobase_log_file_size > UINT_MAX32) {
1855
"xtrabackup: innobase_log_file_size can't be over 4GB"
1856
" on 32-bit systemsi\n");
1862
os_innodb_umask = (ulint)0664;
1864
/* First calculate the default path for innodb_data_home_dir etc.,
1865
in case the user has not given any value.
1867
Note that when using the embedded server, the datadirectory is not
1868
necessarily the current directory of this program. */
1870
/* It's better to use current lib, to keep paths short */
1871
current_dir[0] = FN_CURLIB;
1872
current_dir[1] = FN_LIBCHAR;
1874
default_path = current_dir;
1878
#if (MYSQL_VERSION_ID < 50500)
1879
// if (specialflag & SPECIAL_NO_PRIOR) {
1880
srv_set_thread_priorities = FALSE;
1882
// srv_set_thread_priorities = TRUE;
1883
// srv_query_thread_priority = QUERY_PRIOR;
1887
/* Set InnoDB initialization parameters according to the values
1888
read from MySQL .cnf file */
1890
if (xtrabackup_backup || xtrabackup_stats) {
1891
fprintf(stderr, "xtrabackup: Target instance is assumed as followings.\n");
1893
fprintf(stderr, "xtrabackup: Temporary instance for recovery is set as followings.\n");
1896
/*--------------- Data files -------------------------*/
1898
/* The default dir for data files is the datadir of MySQL */
1900
srv_data_home = ((xtrabackup_backup || xtrabackup_stats) && innobase_data_home_dir
1901
? innobase_data_home_dir : default_path);
1902
fprintf(stderr, "xtrabackup: innodb_data_home_dir = %s\n", srv_data_home);
1904
/* Set default InnoDB data file size to 10 MB and let it be
1905
auto-extending. Thus users can use InnoDB in >= 4.0 without having
1906
to specify any startup options. */
1908
if (!innobase_data_file_path) {
1909
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1911
fprintf(stderr, "xtrabackup: innodb_data_file_path = %s\n",
1912
innobase_data_file_path);
1914
/* Since InnoDB edits the argument in the next call, we make another
1917
internal_innobase_data_file_path = strdup(innobase_data_file_path);
1919
ret = (my_bool) srv_parse_data_file_paths_and_sizes(
1920
#ifndef INNODB_VERSION_SHORT
1921
internal_innobase_data_file_path,
1922
&srv_data_file_names,
1923
&srv_data_file_sizes,
1924
&srv_data_file_is_raw_partition,
1926
&srv_auto_extend_last_data_file,
1927
&srv_last_file_size_max);
1929
internal_innobase_data_file_path);
1933
"xtrabackup: syntax error in innodb_data_file_path\n");
1935
free(internal_innobase_data_file_path);
1939
if (xtrabackup_prepare) {
1940
/* "--prepare" needs filenames only */
1943
for (i=0; i < srv_n_data_files; i++) {
1946
p = srv_data_file_names[i];
1947
while ((p = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
1950
srv_data_file_names[i] = p;
1956
srv_doublewrite_file = innobase_doublewrite_file;
1958
srv_extra_undoslots = (ibool) innobase_extra_undoslots;
1962
/* -------------- Log files ---------------------------*/
1964
/* The default dir for log files is the datadir of MySQL */
1966
if (!((xtrabackup_backup || xtrabackup_stats) && innobase_log_group_home_dir)) {
1967
innobase_log_group_home_dir = default_path;
1969
if (xtrabackup_prepare && xtrabackup_incremental_dir) {
1970
innobase_log_group_home_dir = xtrabackup_incremental_dir;
1972
fprintf(stderr, "xtrabackup: innodb_log_group_home_dir = %s\n",
1973
innobase_log_group_home_dir);
1975
#ifdef UNIV_LOG_ARCHIVE
1976
/* Since innodb_log_arch_dir has no relevance under MySQL,
1977
starting from 4.0.6 we always set it the same as
1978
innodb_log_group_home_dir: */
1980
innobase_log_arch_dir = innobase_log_group_home_dir;
1982
srv_arch_dir = innobase_log_arch_dir;
1983
#endif /* UNIG_LOG_ARCHIVE */
1986
#ifndef INNODB_VERSION_SHORT
1987
srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
1988
&srv_log_group_home_dirs);
1990
srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
1993
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1994
fprintf(stderr, "xtrabackup: syntax error in innodb_log_group_home_dir, or a "
1995
"wrong number of mirrored log groups\n");
1997
goto mem_free_and_error;
2000
#ifdef INNODB_VERSION_SHORT
2001
srv_adaptive_flushing = FALSE;
2002
srv_use_sys_malloc = TRUE;
2003
srv_file_format = 1; /* Barracuda */
2004
#if (MYSQL_VERSION_ID < 50500)
2005
srv_check_file_format_at_startup = DICT_TF_FORMAT_51; /* on */
2007
srv_max_file_format_at_startup = DICT_TF_FORMAT_51; /* on */
2010
/* --------------------------------------------------*/
2012
srv_file_flush_method_str = innobase_unix_file_flush_method;
2014
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2015
srv_n_log_files = (ulint) innobase_log_files_in_group;
2016
srv_log_file_size = (ulint) innobase_log_file_size;
2017
fprintf(stderr, "xtrabackup: innodb_log_files_in_group = %ld\n",
2019
fprintf(stderr, "xtrabackup: innodb_log_file_size = %ld\n",
2022
#ifdef UNIV_LOG_ARCHIVE
2023
srv_log_archive_on = (ulint) innobase_log_archive;
2024
#endif /* UNIV_LOG_ARCHIVE */
2025
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2027
/* We set srv_pool_size here in units of 1 kB. InnoDB internally
2028
changes the value so that it becomes the number of database pages. */
2030
#ifndef INNODB_VERSION_SHORT
2031
if (innobase_buffer_pool_awe_mem_mb == 0) {
2032
/* Careful here: we first convert the signed long int to ulint
2033
and only after that divide */
2035
//srv_pool_size = ((ulint) innobase_buffer_pool_size) / 1024;
2036
srv_pool_size = ((ulint) xtrabackup_use_memory) / 1024;
2039
srv_pool_size = (ulint)
2040
(1024 * innobase_buffer_pool_awe_mem_mb);
2041
//srv_awe_window_size = (ulint) innobase_buffer_pool_size;
2042
srv_awe_window_size = (ulint) xtrabackup_use_memory;
2044
/* Note that what the user specified as
2045
innodb_buffer_pool_size is actually the AWE memory window
2046
size in this case, and the real buffer pool size is
2047
determined by .._awe_mem_mb. */
2050
//srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2051
srv_buf_pool_size = (ulint) xtrabackup_use_memory;
2054
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2056
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
2057
#ifdef INNODB_VERSION_SHORT
2058
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2059
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2062
#ifndef INNODB_VERSION_SHORT
2063
srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
2065
srv_force_recovery = (ulint) innobase_force_recovery;
2067
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
2068
srv_use_checksums = (ibool) innobase_use_checksums;
2070
#ifndef INNODB_VERSION_SHORT
2071
srv_use_adaptive_hash_indexes = (ibool) innobase_adaptive_hash_index;
2073
btr_search_enabled = (ibool) innobase_adaptive_hash_index;
2076
os_use_large_pages = (ibool) innobase_use_large_pages;
2077
os_large_page_size = (ulint) innobase_large_page_size;
2079
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
2081
srv_file_per_table = (ibool) innobase_file_per_table;
2083
srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
2085
srv_max_n_open_files = (ulint) innobase_open_files;
2086
srv_innodb_status = (ibool) innobase_create_status_file;
2088
srv_print_verbose_log = 1;
2090
/* Store the default charset-collation number of this MySQL
2093
/* We cannot treat characterset here for now!! */
2094
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2096
ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
2097
my_charset_latin1.number);
2098
ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
2100
/* Store the latin1_swedish_ci character ordering table to InnoDB. For
2101
non-latin1_swedish_ci charsets we use the MySQL comparison functions,
2102
and consequently we do not need to know the ordering internally in
2105
#ifndef INNODB_VERSION_SHORT
2106
ut_a(0 == strcmp((char*)my_charset_latin1.name,
2107
(char*)"latin1_swedish_ci"));
2108
memcpy(srv_latin1_ordering, my_charset_latin1.sort_order, 256);
2110
ut_a(0 == strcmp(my_charset_latin1.name, "latin1_swedish_ci"));
2111
srv_latin1_ordering = my_charset_latin1.sort_order;
2113
//innobase_commit_concurrency_init_default();
2116
/* Since we in this module access directly the fields of a trx
2117
struct, and due to different headers and flags it might happen that
2118
mutex_t has a different size in this module and in InnoDB
2119
modules, we check at run time that the size is the same in
2120
these compilation modules. */
2122
#ifndef INNODB_VERSION_SHORT
2123
srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
2126
#if MYSQL_VERSION_ID >= 50500
2127
/* On 5.5 srv_use_native_aio is TRUE by default. It is later reset
2128
if it is not supported by the platform in
2129
innobase_start_or_create_for_mysql(). As we don't call it in xtrabackup,
2130
we have to duplicate checks from that function here. */
2133
switch (os_get_os_version()) {
2137
/* On Win 95, 98, ME, Win32 subsystem for Windows 3.1,
2138
and NT use simulated aio. In NT Windows provides async i/o,
2139
but when run in conjunction with InnoDB Hot Backup, it seemed
2140
to corrupt the data files. */
2142
srv_use_native_aio = FALSE;
2147
/* On 2000 and XP, async IO is available. */
2148
srv_use_native_aio = TRUE;
2152
/* Vista and later have both async IO and condition variables */
2153
srv_use_native_aio = TRUE;
2154
srv_use_native_conditions = TRUE;
2158
#elif defined(LINUX_NATIVE_AIO)
2160
if (srv_use_native_aio) {
2161
ut_print_timestamp(stderr);
2163
" InnoDB: Using Linux native AIO\n");
2166
/* Currently native AIO is supported only on windows and linux
2167
and that also when the support is compiled in. In all other
2168
cases, we ignore the setting of innodb_use_native_aio. */
2169
srv_use_native_aio = FALSE;
2172
#endif /* MYSQL_VERSION_ID */
2177
fprintf(stderr, "xtrabackup: innodb_init_param(): Error occured.\n");
2186
err = innobase_start_or_create_for_mysql();
2188
if (err != DB_SUCCESS) {
2189
free(internal_innobase_data_file_path);
2193
/* They may not be needed for now */
2194
// (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
2195
// (hash_get_key) innobase_get_key, 0, 0);
2196
// pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2197
// pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2198
// pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2199
// pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2200
// pthread_cond_init(&commit_cond, NULL);
2207
fprintf(stderr, "xtrabackup: innodb_init(): Error occured.\n");
2214
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
2217
fprintf(stderr, "xtrabackup: starting shutdown with innodb_fast_shutdown = %lu\n",
2220
if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
2223
free(internal_innobase_data_file_path);
2225
/* They may not be needed for now */
2226
// hash_free(&innobase_open_tables);
2227
// pthread_mutex_destroy(&innobase_share_mutex);
2228
// pthread_mutex_destroy(&prepare_commit_mutex);
2229
// pthread_mutex_destroy(&commit_threads_m);
2230
// pthread_mutex_destroy(&commit_cond_m);
2231
// pthread_cond_destroy(&commit_cond);
2236
fprintf(stderr, "xtrabackup: innodb_end(): Error occured.\n");
2240
/* ================= common ================= */
2242
xtrabackup_read_metadata(char *filename)
2246
fp = fopen(filename,"r");
2248
fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filename);
2252
if (fscanf(fp, "backup_type = %29s\n", metadata_type)
2255
#ifndef INNODB_VERSION_SHORT
2256
if (fscanf(fp, "from_lsn = %lu:%lu\n", &metadata_from_lsn.high, &metadata_from_lsn.low)
2259
if (fscanf(fp, "to_lsn = %lu:%lu\n", &metadata_to_lsn.high, &metadata_to_lsn.low)
2262
if (fscanf(fp, "last_lsn = %lu:%lu\n", &metadata_last_lsn.high, &metadata_last_lsn.low)
2264
metadata_last_lsn.high = metadata_last_lsn.low = 0;
2267
if (fscanf(fp, "from_lsn = %llu\n", &metadata_from_lsn)
2270
if (fscanf(fp, "to_lsn = %llu\n", &metadata_to_lsn)
2273
if (fscanf(fp, "last_lsn = %llu\n", &metadata_last_lsn)
2275
metadata_last_lsn = 0;
2285
xtrabackup_write_metadata(char *filename)
2289
fp = fopen(filename,"w");
2291
fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filename);
2295
if (fprintf(fp, "backup_type = %s\n", metadata_type)
2298
#ifndef INNODB_VERSION_SHORT
2299
if (fprintf(fp, "from_lsn = %lu:%lu\n", metadata_from_lsn.high, metadata_from_lsn.low)
2302
if (fprintf(fp, "to_lsn = %lu:%lu\n", metadata_to_lsn.high, metadata_to_lsn.low)
2305
if (fprintf(fp, "last_lsn = %lu:%lu\n", metadata_last_lsn.high, metadata_last_lsn.low)
2309
if (fprintf(fp, "from_lsn = %llu\n", metadata_from_lsn)
2312
if (fprintf(fp, "to_lsn = %llu\n", metadata_to_lsn)
2315
if (fprintf(fp, "last_lsn = %llu\n", metadata_last_lsn)
2325
/***********************************************************************
2326
Read meta info for an incremental delta.
2327
@return TRUE on success, FALSE on failure. */
2329
xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info)
2333
memset(info, 0, sizeof(xb_delta_info_t));
2335
fp = fopen(filepath, "r");
2337
/* Meta files for incremental deltas are optional */
2341
if (fscanf(fp, "page_size = %lu\n", &info->page_size) != 1)
2349
/***********************************************************************
2350
Write meta info for an incremental delta.
2351
@return TRUE on success, FALSE on failure. */
2353
xb_write_delta_metadata(const char *filepath, const xb_delta_info_t *info)
2357
fp = fopen(filepath, "w");
2359
fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filepath);
2363
if (fprintf(fp, "page_size = %lu\n", info->page_size) < 0)
2371
/* ================= backup ================= */
2373
xtrabackup_io_throttling(void)
2375
if (xtrabackup_throttle && (io_ticket--) < 0) {
2376
os_event_reset(wait_throttle);
2377
os_event_wait(wait_throttle);
2382
/* TODO: We may tune the behavior (e.g. by fil_aio)*/
2383
#define COPY_CHUNK 64
2386
xtrabackup_copy_datafile(fil_node_t* node, uint thread_n)
2388
os_file_t src_file = -1;
2389
os_file_t dst_file = -1;
2390
char dst_path[FN_REFLEN];
2391
char meta_path[FN_REFLEN];
2398
ulint page_in_buffer;
2399
ulint incremental_buffers = 0;
2401
ulint page_size_shift;
2402
#ifdef INNODB_VERSION_SHORT
2405
xb_delta_info_t info;
2408
if (xtrabackup_tables && (!trx_sys_sys_space(node->space->id)))
2410
if (xtrabackup_tables && (node->space->id != 0))
2412
{ /* must backup id==0 */
2421
while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
2426
p_len = strlen(p) - strlen(".ibd");
2429
/* unknown situation: skip filtering */
2433
/* TODO: Fix this lazy implementation... */
2438
for (i = 0; i < tables_regex_num; i++) {
2439
regres = regexec(&tables_regex[i], prev, 1, tables_regmatch, 0);
2440
if (regres != REG_NOMATCH)
2445
*(p - 1) = SRV_PATH_SEPARATOR;
2447
if ( regres == REG_NOMATCH ) {
2448
printf("[%02u] Copying %s is skipped.\n",
2449
thread_n, node->name);
2455
if (xtrabackup_tables_file && (!trx_sys_sys_space(node->space->id)))
2457
if (xtrabackup_tables_file && (node->space->id != 0))
2459
{ /* must backup id==0 */
2460
xtrabackup_tables_t* table;
2469
while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
2474
p_len = strlen(p) - strlen(".ibd");
2477
/* unknown situation: skip filtering */
2481
/* TODO: Fix this lazy implementation... */
2485
HASH_SEARCH(name_hash, tables_hash, ut_fold_string(prev),
2486
#ifdef INNODB_VERSION_SHORT
2487
xtrabackup_tables_t*,
2490
#ifdef INNODB_VERSION_SHORT
2493
!strcmp(table->name, prev));
2498
printf("[%02u] Copying %s is skipped.\n",
2499
thread_n, node->name);
2505
#ifndef INNODB_VERSION_SHORT
2506
page_size = UNIV_PAGE_SIZE;
2507
page_size_shift = UNIV_PAGE_SIZE_SHIFT;
2509
zip_size = fil_space_get_zip_size(node->space->id);
2510
if (zip_size == ULINT_UNDEFINED) {
2511
fprintf(stderr, "[%02u] xtrabackup: Warning: "
2512
"Failed to determine page size for %s.\n"
2513
"[%02u] xtrabackup: Warning: We assume the table was "
2514
"dropped during xtrabackup execution and ignore the "
2515
"file.\n", thread_n, node->name, thread_n);
2517
} else if (zip_size) {
2518
page_size = zip_size;
2519
page_size_shift = get_bit_shift(page_size);
2520
fprintf(stderr, "[%02u] %s is compressed with page size = "
2521
"%lu bytes\n", thread_n, node->name, page_size);
2522
if (page_size_shift < 10 || page_size_shift > 14) {
2523
fprintf(stderr, "[%02u] xtrabackup: Error: Invalid "
2524
"page size.\n", thread_n);
2528
page_size = UNIV_PAGE_SIZE;
2529
page_size_shift = UNIV_PAGE_SIZE_SHIFT;
2534
if (trx_sys_sys_space(node->space->id))
2536
if (node->space->id == 0)
2540
/* system datafile "/fullpath/datafilename.ibd" or "./datafilename.ibd" */
2542
while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
2546
sprintf(dst_path, "%s/%s", xtrabackup_target_dir, p);
2548
/* file per table style "./database/table.ibd" */
2549
sprintf(dst_path, "%s%s", xtrabackup_target_dir, strstr(node->name, SRV_PATH_SEPARATOR_STR));
2552
if (xtrabackup_incremental) {
2553
snprintf(meta_path, sizeof(meta_path),
2554
"%s%s", dst_path, XB_DELTA_INFO_SUFFIX);
2555
strcat(dst_path, ".delta");
2558
bzero(incremental_buffer, (page_size/4) * page_size);
2560
mach_write_to_4(incremental_buffer, 0x78747261UL);/*"xtra"*/
2563
info.page_size = page_size;
2568
src_file = os_file_create_simple_no_error_handling(
2569
#if (MYSQL_VERSION_ID > 50500)
2570
0 /* dummy of innodb_file_data_key */,
2572
node->name, OS_FILE_OPEN,
2573
OS_FILE_READ_ONLY, &success);
2575
/* The following call prints an error message */
2576
os_file_get_last_error(TRUE);
2579
"[%02u] xtrabackup: Warning: cannot open %s\n"
2580
"[%02u] xtrabackup: Warning: We assume the "
2581
"table was dropped during xtrabackup execution "
2582
"and ignore the file.\n",
2583
thread_n, node->name, thread_n);
2587
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
2588
os_file_set_nocache(src_file, node->name, "OPEN");
2591
src_file = node->handle;
2594
#ifdef USE_POSIX_FADVISE
2595
posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
2596
posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
2600
/* os_file_create reads srv_unix_file_flush_method */
2601
dst_file = os_file_create(
2602
#if (MYSQL_VERSION_ID > 50500)
2603
0 /* dummy of innodb_file_data_key */,
2605
dst_path, OS_FILE_CREATE,
2606
OS_FILE_NORMAL, OS_DATA_FILE, &success);
2608
/* The following call prints an error message */
2609
os_file_get_last_error(TRUE);
2611
fprintf(stderr,"[%02u] xtrabackup: error: "
2612
"cannot open %s\n", thread_n, dst_path);
2616
#ifdef USE_POSIX_FADVISE
2617
posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED);
2620
/* copy : TODO: tune later */
2621
printf("[%02u] Copying %s \n to %s\n", thread_n,
2622
node->name, dst_path);
2624
buf2 = ut_malloc(COPY_CHUNK * page_size + UNIV_PAGE_SIZE);
2625
page = ut_align(buf2, UNIV_PAGE_SIZE);
2627
success = os_file_read(src_file, page, 0, 0, UNIV_PAGE_SIZE);
2631
flush_lsn = MACH_READ_64(page + FIL_PAGE_FILE_FLUSH_LSN);
2632
/* check current flush lsn newer than checkpoint@start */
2633
// if (ut_dulint_cmp(backup_start_checkpoint, flush_lsn) >= 0) {
2637
file_size = os_file_get_size_as_iblonglong(src_file);
2639
for (offset = 0; offset < file_size; offset += COPY_CHUNK * page_size) {
2642
ulint retry_count = 10;
2644
if (file_size - offset > COPY_CHUNK * page_size) {
2645
chunk = COPY_CHUNK * page_size;
2647
chunk = (ulint)(file_size - offset);
2651
xtrabackup_io_throttling();
2653
success = os_file_read(src_file, page,
2654
(ulint)(offset & 0xFFFFFFFFUL),
2655
(ulint)(offset >> 32), chunk);
2660
/* check corruption and retry */
2661
for (chunk_offset = 0; chunk_offset < chunk; chunk_offset += page_size) {
2662
#ifndef INNODB_VERSION_SHORT
2663
if (buf_page_is_corrupted(page + chunk_offset))
2665
if (buf_page_is_corrupted(page + chunk_offset, zip_size))
2670
trx_sys_sys_space(node->space->id)
2672
node->space->id == 0
2674
&& ((offset + (IB_INT64)chunk_offset) >> page_size_shift)
2676
&& ((offset + (IB_INT64)chunk_offset) >> page_size_shift)
2677
< FSP_EXTENT_SIZE * 3) {
2678
/* double write buffer may have old data in the end
2679
or it may contain the other format page like COMPRESSED.
2680
So, we can pass the check of double write buffer.*/
2681
ut_a(page_size == UNIV_PAGE_SIZE);
2682
fprintf(stderr, "[%02u] xtrabackup: "
2683
"Page %lu seems double write "
2684
"buffer. passing the check.\n",
2687
(IB_INT64)chunk_offset) >>
2691
if (retry_count == 0) {
2693
"[%02u] xtrabackup: "
2694
"Error: 10 retries "
2695
"resulted in fail. This"
2701
fprintf(stderr, "[%02u] xtrabackup: "
2702
"Database page corruption "
2703
"detected at page %lu. "
2707
(IB_INT64)chunk_offset)
2708
>> page_size_shift));
2714
if (xtrabackup_incremental) {
2715
for (chunk_offset = 0; chunk_offset < chunk; chunk_offset += page_size) {
2717
/* This condition may be OK for header, ibuf and fsp */
2718
if (ut_dulint_cmp(incremental_lsn,
2719
MACH_READ_64(page + chunk_offset + FIL_PAGE_LSN)) < 0) {
2720
/* ========================================= */
2721
IB_INT64 page_offset;
2723
if (page_in_buffer == page_size/4) {
2725
success = os_file_write(dst_path, dst_file, incremental_buffer,
2726
((incremental_buffers * (page_size/4))
2727
<< page_size_shift) & 0xFFFFFFFFUL,
2728
(incremental_buffers * (page_size/4))
2729
>> (32 - page_size_shift),
2730
page_in_buffer * page_size);
2735
incremental_buffers++;
2738
bzero(incremental_buffer, (page_size/4) * page_size);
2740
mach_write_to_4(incremental_buffer, 0x78747261UL);/*"xtra"*/
2744
page_offset = ((offset + (IB_INT64)chunk_offset) >> page_size_shift);
2745
ut_a(page_offset >> 32 == 0);
2747
mach_write_to_4(incremental_buffer + page_in_buffer * 4, (ulint)page_offset);
2748
memcpy(incremental_buffer + page_in_buffer * page_size,
2749
page + chunk_offset, page_size);
2752
/* ========================================= */
2756
success = os_file_write(dst_path, dst_file, page,
2757
(ulint)(offset & 0xFFFFFFFFUL),
2758
(ulint)(offset >> 32), chunk);
2766
if (xtrabackup_incremental) {
2768
if (page_in_buffer != page_size/4) {
2769
mach_write_to_4(incremental_buffer + page_in_buffer * 4, 0xFFFFFFFFUL);
2772
mach_write_to_4(incremental_buffer, 0x58545241UL);/*"XTRA"*/
2775
success = os_file_write(dst_path, dst_file, incremental_buffer,
2776
((incremental_buffers * (page_size/4))
2777
<< page_size_shift) & 0xFFFFFFFFUL,
2778
(incremental_buffers * (page_size/4))
2779
>> (32 - page_size_shift),
2780
page_in_buffer * page_size);
2784
if (!xb_write_delta_metadata(meta_path, &info)) {
2785
fprintf(stderr, "[%02u] xtrabackup: Error: "
2786
"failed to write meta info for %s\n",
2787
thread_n, dst_path);
2792
success = os_file_flush(dst_file);
2798
/* check size again */
2799
/* TODO: but is it needed ?? */
2800
// if (file_size < os_file_get_size_as_iblonglong(src_file)) {
2801
// offset -= COPY_CHUNK * page_size;
2802
// file_size = os_file_get_size_as_iblonglong(src_file);
2806
/* TODO: How should we treat double_write_buffer here? */
2807
/* (currently, don't care about. Because,
2808
the blocks is newer than the last checkpoint anyway.) */
2811
printf("[%02u] ...done\n", thread_n);
2813
os_file_close(src_file);
2815
os_file_close(dst_file);
2819
if (src_file != -1 && !node->open)
2820
os_file_close(src_file);
2822
os_file_close(dst_file);
2825
fprintf(stderr, "[%02u] xtrabackup: Error: "
2826
"xtrabackup_copy_datafile() failed.\n", thread_n);
2827
return(TRUE); /*ERROR*/
2830
if (src_file != -1 && !node->open)
2831
os_file_close(src_file);
2833
os_file_close(dst_file);
2836
fprintf(stderr, "[%02u] xtrabackup: Warning: skipping file %s.\n",
2837
thread_n, node->name);
2842
xtrabackup_copy_logfile(LSN64 from_lsn, my_bool is_last)
2844
/* definition from recv_recovery_from_checkpoint_start() */
2846
log_group_t* up_to_date_group;
2847
LSN64 old_scanned_lsn;
2848
LSN64 group_scanned_lsn;
2849
LSN64 contiguous_lsn;
2853
if (!xtrabackup_stream)
2854
ut_a(dst_log != -1);
2856
/* read from checkpoint_lsn_start to current */
2857
contiguous_lsn = ut_dulint_align_down(from_lsn,
2858
OS_FILE_LOG_BLOCK_SIZE);
2860
/* TODO: We must check the contiguous_lsn still exists in log file.. */
2862
group = UT_LIST_GET_FIRST(log_sys->log_groups);
2870
old_scanned_lsn = from_lsn;
2872
/* reference recv_group_scan_log_recs() */
2875
start_lsn = contiguous_lsn;
2878
end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE);
2880
xtrabackup_io_throttling();
2882
log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
2883
group, start_lsn, end_lsn);
2885
//printf("log read from (%lu %lu) to (%lu %lu)\n",
2886
// start_lsn.high, start_lsn.low, end_lsn.high, end_lsn.low);
2888
/* reference recv_scan_log_recs() */
2896
ulint scanned_checkpoint_no = 0;
2900
log_block = log_sys->buf;
2901
scanned_lsn = start_lsn;
2904
while (log_block < log_sys->buf + RECV_SCAN_SIZE && !finished) {
2906
no = log_block_get_hdr_no(log_block);
2908
if (no != log_block_convert_lsn_to_no(scanned_lsn)
2909
|| !log_block_checksum_is_ok_or_old_format(log_block)) {
2911
if (no > log_block_convert_lsn_to_no(scanned_lsn)
2912
&& log_block_checksum_is_ok_or_old_format(log_block)) {
2914
">> ###Warning###: The copying transaction log migh be overtaken already by the target.\n"
2915
">> : Waiting log block no %lu, but the bumber is already %lu.\n"
2916
">> : If the number equals %lu + n * %lu, it should be overtaken already.\n",
2917
(ulong) log_block_convert_lsn_to_no(scanned_lsn),
2919
(ulong) log_block_convert_lsn_to_no(scanned_lsn),
2920
(ulong) (log_block_convert_lsn_to_no(
2921
#ifndef INNODB_VERSION_SHORT
2922
ut_dulint_create(0, log_group_get_capacity(group))
2924
log_group_get_capacity(group)
2928
} else if (no == log_block_convert_lsn_to_no(scanned_lsn)
2929
&& !log_block_checksum_is_ok_or_old_format(
2932
#ifndef INNODB_VERSION_SHORT
2933
"xtrabackup: Log block no %lu at lsn %lu %lu has\n"
2935
"xtrabackup: Log block no %lu at lsn %llu has\n"
2937
"xtrabackup: ok header, but checksum field contains %lu, should be %lu\n",
2939
#ifndef INNODB_VERSION_SHORT
2940
(ulong) ut_dulint_get_high(scanned_lsn),
2941
(ulong) ut_dulint_get_low(scanned_lsn),
2945
(ulong) log_block_get_checksum(log_block),
2946
(ulong) log_block_calc_checksum(log_block));
2949
/* Garbage or an incompletely written log block */
2956
if (log_block_get_flush_bit(log_block)) {
2957
/* This block was a start of a log flush operation:
2958
we know that the previous flush operation must have
2959
been completed for all log groups before this block
2960
can have been flushed to any of the groups. Therefore,
2961
we know that log data is contiguous up to scanned_lsn
2962
in all non-corrupt log groups. */
2964
if (ut_dulint_cmp(scanned_lsn, contiguous_lsn) > 0) {
2965
contiguous_lsn = scanned_lsn;
2969
data_len = log_block_get_data_len(log_block);
2972
(scanned_checkpoint_no > 0)
2973
&& (log_block_get_checkpoint_no(log_block)
2974
< scanned_checkpoint_no)
2975
&& (scanned_checkpoint_no
2976
- log_block_get_checkpoint_no(log_block)
2979
/* Garbage from a log buffer flush which was made
2980
before the most recent database recovery */
2986
scanned_lsn = ut_dulint_add(scanned_lsn, data_len);
2987
scanned_checkpoint_no = log_block_get_checkpoint_no(log_block);
2989
if (data_len < OS_FILE_LOG_BLOCK_SIZE) {
2990
/* Log data for this group ends here */
2994
log_block += OS_FILE_LOG_BLOCK_SIZE;
2996
} /* while (log_block < log_sys->buf + RECV_SCAN_SIZE && !finished) */
2998
group_scanned_lsn = scanned_lsn;
3004
/* ===== write log to 'xtrabackup_logfile' ====== */
3009
write_size = RECV_SCAN_SIZE;
3011
write_size = ut_dulint_minus(
3012
ut_dulint_align_up(group_scanned_lsn, OS_FILE_LOG_BLOCK_SIZE),
3016
//printf("Wrinting offset= %lld, size= %lu\n", log_copy_offset, write_size);
3018
if (!xtrabackup_stream) {
3019
success = os_file_write(dst_log_path, dst_log, log_sys->buf,
3020
(ulint)(log_copy_offset & 0xFFFFFFFFUL),
3021
(ulint)(log_copy_offset >> 32), write_size);
3024
ulint stdout_write_size = write_size;
3025
if (finished && !is_last
3026
#ifndef INNODB_VERSION_SHORT
3027
&& group_scanned_lsn.low % OS_FILE_LOG_BLOCK_SIZE
3029
&& group_scanned_lsn % OS_FILE_LOG_BLOCK_SIZE
3032
stdout_write_size -= OS_FILE_LOG_BLOCK_SIZE;
3033
if (stdout_write_size) {
3034
ret = write(fileno(stdout), log_sys->buf, stdout_write_size);
3035
if (ret == stdout_write_size) {
3038
fprintf(stderr, "write: %lu > %lu\n", stdout_write_size, ret);
3042
success = TRUE; /* do nothing */
3046
log_copy_offset += write_size;
3048
#ifndef INNODB_VERSION_SHORT
3049
if (finished && group_scanned_lsn.low % OS_FILE_LOG_BLOCK_SIZE)
3051
if (finished && group_scanned_lsn % OS_FILE_LOG_BLOCK_SIZE)
3054
/* if continue, it will start from align_down(group_scanned_lsn) */
3055
log_copy_offset -= OS_FILE_LOG_BLOCK_SIZE;
3059
if (!xtrabackup_stream) {
3060
fprintf(stderr, "xtrabackup: Error: os_file_write to %s\n", dst_log_path);
3062
fprintf(stderr, "xtrabackup: Error: write to stdout\n");
3074
start_lsn = end_lsn;
3079
group->scanned_lsn = group_scanned_lsn;
3081
if (ut_dulint_cmp(old_scanned_lsn, group_scanned_lsn) < 0) {
3082
/* We found a more up-to-date group */
3084
up_to_date_group = group;
3087
#ifndef INNODB_VERSION_SHORT
3088
fprintf(stderr, ">> log scanned up to (%lu %lu)\n",group->scanned_lsn.high,group->scanned_lsn.low);
3090
fprintf(stderr, ">> log scanned up to (%llu)\n",group->scanned_lsn);
3093
group = UT_LIST_GET_NEXT(log_groups, group);
3095
/* update global variable*/
3096
log_copy_scanned_lsn = group_scanned_lsn;
3098
/* innodb_mirrored_log_groups must be 1, no other groups */
3099
ut_a(group == NULL);
3103
if (!xtrabackup_stream) {
3104
success = os_file_flush(dst_log);
3117
if (!xtrabackup_stream)
3118
os_file_close(dst_log);
3119
fprintf(stderr, "xtrabackup: Error: xtrabackup_copy_logfile() failed.\n");
3123
/* copying logfile in background */
3124
#define SLEEPING_PERIOD 5
3137
if (!xtrabackup_stream)
3138
ut_a(dst_log != -1);
3140
log_copying_running = TRUE;
3142
while(log_copying) {
3143
os_thread_sleep(200000); /*0.2 sec*/
3146
if(counter >= SLEEPING_PERIOD * 5) {
3147
if(xtrabackup_copy_logfile(log_copy_scanned_lsn, FALSE))
3154
if(xtrabackup_copy_logfile(log_copy_scanned_lsn, TRUE))
3157
log_copying_succeed = TRUE;
3159
log_copying_running = FALSE;
3160
os_thread_exit(NULL);
3165
/* io throttle watching (rough) */
3175
/* currently, for --backup only */
3176
ut_a(xtrabackup_backup);
3178
while (log_copying) {
3179
os_thread_sleep(1000000); /*1 sec*/
3182
//if (io_ticket == xtrabackup_throttle) {
3183
// fprintf(stderr, "There seem to be no IO...?\n");
3186
io_ticket = xtrabackup_throttle;
3187
os_event_set(wait_throttle);
3190
/* stop io throttle */
3191
xtrabackup_throttle = 0;
3192
os_event_set(wait_throttle);
3194
os_thread_exit(NULL);
3199
/************************************************************************
3200
I/o-handler thread function. */
3215
segment = *((ulint*)arg);
3218
fil_aio_wait(segment);
3221
/* We count the number of threads in os_thread_exit(). A created
3222
thread should always use that to exit and not use return() to exit.
3223
The thread actually never comes here because it is exited in an
3226
os_thread_exit(NULL);
3229
return(NULL); /* Not reached */
3235
/***************************************************************************
3236
Creates an output directory for a given tablespace, if it does not exist */
3239
xtrabackup_create_output_dir(
3240
/*==========================*/
3241
/* out: 0 if succes, -1 if failure */
3242
fil_space_t *space) /* in: tablespace */
3244
char path[FN_REFLEN];
3248
/* mkdir if not exist */
3249
ptr1 = strstr(space->name, SRV_PATH_SEPARATOR_STR);
3251
ptr2 = strstr(ptr1 + 1, SRV_PATH_SEPARATOR_STR);
3256
if(!trx_sys_sys_space(space->id) && ptr2)
3258
if(space->id && ptr2)
3261
/* single table space */
3262
*ptr2 = 0; /* temporary (it's my lazy..)*/
3263
snprintf(path, sizeof(path), "%s%s", xtrabackup_target_dir,
3265
*ptr2 = SRV_PATH_SEPARATOR;
3267
if (my_mkdir(path, 0777, MYF(0)) < 0 && my_errno != EEXIST) {
3269
"xtrabackup: Error: cannot mkdir %d: %s\n",
3277
/**************************************************************************
3278
Datafiles copying thread.*/
3281
data_copy_thread_func(
3282
/*==================*/
3283
void *arg) /* thread context */
3285
data_thread_ctxt_t *ctxt = (data_thread_ctxt_t *) arg;
3286
uint num = ctxt->num;
3288
ibool space_changed;
3292
We have to initialize mysys thread-specific memory because
3293
of the my_stat() call in xtrabackup_create_output_dir().
3297
while ((node = datafiles_iter_next(ctxt->it, &space_changed)) != NULL) {
3298
space = node->space;
3300
if (space_changed && xtrabackup_create_output_dir(space))
3303
/* copy the datafile */
3304
if(xtrabackup_copy_datafile(node, num)) {
3305
fprintf(stderr, "[%02u] xtrabackup: Error: "
3306
"failed to copy datafile.\n",
3312
os_mutex_enter(ctxt->count_mutex);
3314
os_mutex_exit(ctxt->count_mutex);
3317
os_thread_exit(NULL);
3318
OS_THREAD_DUMMY_RETURN;
3321
/* CAUTION(?): Don't rename file_per_table during backup */
3323
xtrabackup_backup_func(void)
3328
#ifdef USE_POSIX_FADVISE
3329
fprintf(stderr, "xtrabackup: uses posix_fadvise().\n");
3334
if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
3336
fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", mysql_real_data_home);
3339
fprintf(stderr, "xtrabackup: cd to %s\n", mysql_real_data_home);
3341
mysql_data_home= mysql_data_home_buff;
3342
mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
3343
mysql_data_home[1]=0;
3346
srv_read_only = TRUE;
3348
/* initialize components */
3349
if(innodb_init_param())
3352
if (srv_file_flush_method_str == NULL) {
3353
/* These are the default options */
3354
#if (MYSQL_VERSION_ID < 50100)
3355
srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
3356
#else /* MYSQL_VERSION_ID < 51000 */
3357
srv_unix_file_flush_method = SRV_UNIX_FSYNC;
3359
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
3361
#if (MYSQL_VERSION_ID < 50100)
3362
} else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) {
3363
srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
3364
#else /* MYSQL_VERSION_ID < 51000 */
3365
} else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) {
3366
srv_unix_file_flush_method = SRV_UNIX_FSYNC;
3369
} else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
3370
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
3372
} else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) {
3373
srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
3374
fprintf(stderr,"xtrabackup: use O_DIRECT\n");
3375
} else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) {
3376
srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
3378
} else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
3379
srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
3381
} else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
3382
srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
3383
os_aio_use_native_aio = FALSE;
3385
} else if (0 == ut_strcmp(srv_file_flush_method_str, "unbuffered")) {
3386
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
3387
os_aio_use_native_aio = FALSE;
3389
} else if (0 == ut_strcmp(srv_file_flush_method_str,
3390
"async_unbuffered")) {
3391
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
3395
"xtrabackup: Unrecognized value %s for innodb_flush_method\n",
3396
srv_file_flush_method_str);
3400
#ifndef INNODB_VERSION_SHORT
3401
if (srv_pool_size >= 1000 * 1024) {
3403
if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
3405
/* Here we still have srv_pool_size counted
3406
in kilobytes (in 4.0 this was in bytes)
3407
srv_boot() converts the value to
3408
pages; if buffer pool is less than 1000 MB,
3409
assume fewer threads. */
3410
srv_max_n_threads = 50000;
3412
#ifndef INNODB_VERSION_SHORT
3413
} else if (srv_pool_size >= 8 * 1024) {
3415
} else if (srv_buf_pool_size >= 8 * 1024 * 1024) {
3418
srv_max_n_threads = 10000;
3420
srv_max_n_threads = 1000; /* saves several MB of memory,
3421
especially in 64-bit
3429
n = srv_n_data_files;
3431
for (i = 0; i < n; i++) {
3432
srv_data_file_sizes[i] = srv_data_file_sizes[i]
3433
* ((1024 * 1024) / UNIV_PAGE_SIZE);
3436
srv_last_file_size_max = srv_last_file_size_max
3437
* ((1024 * 1024) / UNIV_PAGE_SIZE);
3439
srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE;
3441
srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
3443
#ifndef INNODB_VERSION_SHORT
3444
srv_pool_size = srv_pool_size / (UNIV_PAGE_SIZE / 1024);
3446
srv_awe_window_size = srv_awe_window_size / UNIV_PAGE_SIZE;
3449
/* If we are using AWE we must save memory in the 32-bit
3450
address space of the process, and cannot bind the lock
3451
table size to the real buffer pool size. */
3453
srv_lock_table_size = 20 * srv_awe_window_size;
3455
srv_lock_table_size = 5 * srv_pool_size;
3458
srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
3462
os_sync_mutex = NULL;
3466
ibool create_new_db;
3468
ibool create_new_doublewrite_file;
3470
ibool log_file_created;
3471
ibool log_created = FALSE;
3472
ibool log_opened = FALSE;
3473
LSN64 min_flushed_lsn;
3474
LSN64 max_flushed_lsn;
3475
ulint sum_of_new_sizes;
3482
#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
3483
#define SRV_MAX_N_PENDING_SYNC_IOS 100
3485
#ifndef INNODB_VERSION_SHORT
3486
os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
3487
* srv_n_file_io_threads,
3488
srv_n_file_io_threads,
3489
SRV_MAX_N_PENDING_SYNC_IOS);
3491
fil_init(srv_max_n_open_files);
3493
srv_n_file_io_threads = 2 + srv_n_read_io_threads + srv_n_write_io_threads;
3495
os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD,
3496
srv_n_read_io_threads,
3497
srv_n_write_io_threads,
3498
SRV_MAX_N_PENDING_SYNC_IOS);
3500
fil_init(srv_file_per_table ? 50000 : 5000,
3501
srv_max_n_open_files);
3507
lock_sys_create(srv_lock_table_size);
3509
for (i = 0; i < srv_n_file_io_threads; i++) {
3512
os_thread_create(io_handler_thread, n + i, thread_ids + i);
3515
os_thread_sleep(200000); /*0.2 sec*/
3517
err = open_or_create_data_files(&create_new_db,
3519
&create_new_doublewrite_file,
3521
&min_flushed_lsn, &max_flushed_lsn,
3523
if (err != DB_SUCCESS) {
3525
"xtrabackup: Could not open or create data files.\n"
3526
"xtrabackup: If you tried to add new data files, and it failed here,\n"
3527
"xtrabackup: you should now edit innodb_data_file_path in my.cnf back\n"
3528
"xtrabackup: to what it was, and remove the new ibdata files InnoDB created\n"
3529
"xtrabackup: in this failed attempt. InnoDB only wrote those files full of\n"
3530
"xtrabackup: zeros, but did not yet use them in any way. But be careful: do not\n"
3531
"xtrabackup: remove old data files which contain your precious data!\n");
3533
//return((int) err);
3537
/* create_new_db must not be TRUE.. */
3538
if (create_new_db) {
3539
fprintf(stderr, "xtrabackup: Something wrong with source files...\n");
3543
for (i = 0; i < srv_n_log_files; i++) {
3544
err = open_or_create_log_file(create_new_db, &log_file_created,
3546
if (err != DB_SUCCESS) {
3548
//return((int) err);
3552
if (log_file_created) {
3557
if ((log_opened && create_new_db)
3558
|| (log_opened && log_created)) {
3560
"xtrabackup: Error: all log files must be created at the same time.\n"
3561
"xtrabackup: All log files must be created also in database creation.\n"
3562
"xtrabackup: If you want bigger or smaller log files, shut down the\n"
3563
"xtrabackup: database and make sure there were no errors in shutdown.\n"
3564
"xtrabackup: Then delete the existing log files. Edit the .cnf file\n"
3565
"xtrabackup: and start the database again.\n");
3572
/* log_file_created must not be TRUE, if online */
3573
if (log_file_created) {
3574
fprintf(stderr, "xtrabackup: Something wrong with source files...\n");
3578
fil_load_single_table_tablespaces();
3582
/* create extra LSN dir if it does not exist. */
3583
if (xtrabackup_extra_lsndir
3584
&&!my_stat(xtrabackup_extra_lsndir,&stat_info,MYF(0))
3585
&& (my_mkdir(xtrabackup_extra_lsndir,0777,MYF(0)) < 0)){
3586
fprintf(stderr,"xtrabackup: Error: cannot mkdir %d: %s\n",my_errno,xtrabackup_extra_lsndir);
3591
if (!xtrabackup_stream) {
3593
/* create target dir if not exist */
3594
if (!my_stat(xtrabackup_target_dir,&stat_info,MYF(0))
3595
&& (my_mkdir(xtrabackup_target_dir,0777,MYF(0)) < 0)){
3596
fprintf(stderr,"xtrabackup: Error: cannot mkdir %d: %s\n",my_errno,xtrabackup_target_dir);
3601
fprintf(stderr,"xtrabackup: Stream mode.\n");
3602
/* stdout can treat binary at Linux */
3603
//setmode(fileno(stdout), O_BINARY);
3607
fil_system_t* system = fil_system;
3609
/* definition from recv_recovery_from_checkpoint_start() */
3610
log_group_t* max_cp_group;
3613
byte log_hdr_buf_[LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE];
3619
/* start back ground thread to copy newer log */
3620
os_thread_id_t log_copying_thread_id;
3621
datafiles_iter_t *it;
3623
log_hdr_buf = ut_align(log_hdr_buf_, OS_FILE_LOG_BLOCK_SIZE);
3626
//space = UT_LIST_GET_NEXT(space_list, UT_LIST_GET_FIRST(system->space_list));
3627
//printf("space: name=%s, id=%d, purpose=%d, size=%d\n",
3628
// space->name, space->id, space->purpose, space->size);
3630
/* get current checkpoint_lsn */
3631
/* Look for the latest checkpoint from any of the log groups */
3633
err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
3635
if (err != DB_SUCCESS) {
3640
log_group_read_checkpoint_info(max_cp_group, max_cp_field);
3641
buf = log_sys->checkpoint_buf;
3643
checkpoint_lsn_start = MACH_READ_64(buf + LOG_CHECKPOINT_LSN);
3644
checkpoint_no_start = MACH_READ_64(buf + LOG_CHECKPOINT_NO);
3647
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, max_cp_group->space_id,
3648
#ifdef INNODB_VERSION_SHORT
3651
0, 0, LOG_FILE_HDR_SIZE,
3652
log_hdr_buf, max_cp_group);
3654
/* check consistency of log file header to copy */
3655
err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
3657
if (err != DB_SUCCESS) {
3662
log_group_read_checkpoint_info(max_cp_group, max_cp_field);
3663
buf = log_sys->checkpoint_buf;
3665
if(ut_dulint_cmp(checkpoint_no_start,
3666
MACH_READ_64(buf + LOG_CHECKPOINT_NO)) != 0) {
3667
checkpoint_lsn_start = MACH_READ_64(buf + LOG_CHECKPOINT_LSN);
3668
checkpoint_no_start = MACH_READ_64(buf + LOG_CHECKPOINT_NO);
3669
goto reread_log_header;
3672
if (!xtrabackup_stream) {
3674
/* open 'xtrabackup_logfile' */
3675
sprintf(dst_log_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
3676
srv_normalize_path_for_win(dst_log_path);
3677
/* os_file_create reads srv_unix_file_flush_method for OS_DATA_FILE*/
3678
dst_log = os_file_create(
3679
#if (MYSQL_VERSION_ID > 50500)
3680
0 /* dummy of innodb_file_data_key */,
3682
dst_log_path, OS_FILE_CREATE,
3683
OS_FILE_NORMAL, OS_DATA_FILE, &success);
3686
/* The following call prints an error message */
3687
os_file_get_last_error(TRUE);
3690
"xtrabackup: error: cannot open %s\n",
3695
#ifdef USE_POSIX_FADVISE
3696
posix_fadvise(dst_log, 0, 0, POSIX_FADV_DONTNEED);
3702
strcpy((char*) log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
3704
ut_sprintf_timestamp(
3705
(char*) log_hdr_buf + (LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
3706
+ (sizeof "xtrabkup ") - 1));
3708
if (!xtrabackup_stream) {
3709
success = os_file_write(dst_log_path, dst_log, log_hdr_buf,
3710
0, 0, LOG_FILE_HDR_SIZE);
3713
if (write(fileno(stdout), log_hdr_buf, LOG_FILE_HDR_SIZE)
3714
== LOG_FILE_HDR_SIZE) {
3721
log_copy_offset += LOG_FILE_HDR_SIZE;
3724
os_file_close(dst_log);
3731
/* start io throttle */
3732
if(xtrabackup_throttle) {
3733
os_thread_id_t io_watching_thread_id;
3735
io_ticket = xtrabackup_throttle;
3736
wait_throttle = os_event_create(NULL);
3738
os_thread_create(io_watching_thread, NULL, &io_watching_thread_id);
3742
/* copy log file by current position */
3743
if(xtrabackup_copy_logfile(checkpoint_lsn_start, FALSE))
3747
os_thread_create(log_copying_thread, NULL, &log_copying_thread_id);
3751
if (!xtrabackup_stream) { /* stream mode is transaction log only */
3754
os_mutex_t count_mutex;
3755
data_thread_ctxt_t *data_threads;
3760
printf("xtrabackup: Starting %u threads for parallel "
3761
"data files transfer\n", parallel);
3763
it = datafiles_iter_new(system);
3766
"xtrabackup: Error: "
3767
"datafiles_iter_new() failed.\n");
3771
/* Create data copying threads */
3774
data_threads = (data_thread_ctxt_t *)
3775
ut_malloc(sizeof(data_thread_ctxt_t) * parallel);
3777
count_mutex = OS_MUTEX_CREATE();
3779
for (i = 0; i < parallel; i++) {
3780
data_threads[i].it = it;
3781
data_threads[i].num = i+1;
3782
data_threads[i].count = &count;
3783
data_threads[i].count_mutex = count_mutex;
3784
os_thread_create(data_copy_thread_func,
3786
&data_threads[i].id);
3789
/* Wait for threads to exit */
3791
os_thread_sleep(1000000);
3792
os_mutex_enter(count_mutex);
3794
os_mutex_exit(count_mutex);
3797
os_mutex_exit(count_mutex);
3799
/* NOTE: It may not needed at "--backup" for now */
3800
/* mutex_enter(&(system->mutex)); */
3802
os_mutex_free(count_mutex);
3803
datafiles_iter_free(it);
3805
} //if (!xtrabackup_stream)
3807
//mutex_exit(&(system->mutex));
3811
/* suspend-at-end */
3812
if (xtrabackup_suspend_at_end) {
3813
os_file_t suspend_file = -1;
3814
char suspend_path[FN_REFLEN];
3815
ibool success, exists;
3816
os_file_type_t type;
3818
sprintf(suspend_path, "%s%s", xtrabackup_target_dir,
3819
"/xtrabackup_suspended");
3821
srv_normalize_path_for_win(suspend_path);
3822
/* os_file_create reads srv_unix_file_flush_method */
3823
suspend_file = os_file_create(
3824
#if (MYSQL_VERSION_ID > 50500)
3825
0 /* dummy of innodb_file_data_key */,
3827
suspend_path, OS_FILE_OVERWRITE,
3828
OS_FILE_NORMAL, OS_DATA_FILE, &success);
3831
fprintf(stderr, "xtrabackup: Error: failed to create file 'xtrabackup_suspended'\n");
3834
if (suspend_file != -1)
3835
os_file_close(suspend_file);
3839
os_thread_sleep(200000); /*0.2 sec*/
3840
success = os_file_status(suspend_path, &exists, &type);
3844
xtrabackup_suspend_at_end = FALSE; /* suspend is 1 time */
3847
/* read the latest checkpoint lsn */
3848
latest_cp = ut_dulint_zero;
3850
log_group_t* max_cp_group;
3854
err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
3856
if (err != DB_SUCCESS) {
3857
fprintf(stderr, "xtrabackup: Error: recv_find_max_checkpoint() failed.\n");
3861
log_group_read_checkpoint_info(max_cp_group, max_cp_field);
3863
latest_cp = MACH_READ_64(log_sys->checkpoint_buf + LOG_CHECKPOINT_LSN);
3865
if (!xtrabackup_stream) {
3866
#ifndef INNODB_VERSION_SHORT
3867
printf("xtrabackup: The latest check point (for incremental): '%lu:%lu'\n",
3868
latest_cp.high, latest_cp.low);
3870
printf("xtrabackup: The latest check point (for incremental): '%llu'\n",
3874
#ifndef INNODB_VERSION_SHORT
3875
fprintf(stderr, "xtrabackup: The latest check point (for incremental): '%lu:%lu'\n",
3876
latest_cp.high, latest_cp.low);
3878
fprintf(stderr, "xtrabackup: The latest check point (for incremental): '%llu'\n",
3884
/* stop log_copying_thread */
3885
log_copying = FALSE;
3886
if (!xtrabackup_stream) {
3887
printf("xtrabackup: Stopping log copying thread");
3888
while (log_copying_running) {
3890
os_thread_sleep(200000); /*0.2 sec*/
3894
while (log_copying_running)
3895
os_thread_sleep(200000); /*0.2 sec*/
3898
/* output to metadata file */
3900
char filename[FN_REFLEN];
3902
if(!xtrabackup_incremental) {
3903
strcpy(metadata_type, "full-backuped");
3904
metadata_from_lsn = ut_dulint_zero;
3906
strcpy(metadata_type, "incremental");
3907
metadata_from_lsn = incremental_lsn;
3909
metadata_to_lsn = latest_cp;
3910
metadata_last_lsn = log_copy_scanned_lsn;
3912
sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
3913
if (xtrabackup_write_metadata(filename))
3914
fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_target_dir)\n");
3916
if(xtrabackup_extra_lsndir) {
3917
sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
3918
if (xtrabackup_write_metadata(filename))
3919
fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
3923
if (!log_copying_succeed) {
3924
fprintf(stderr, "xtrabackup: Error: log_copying_thread failed.\n");
3928
if (!xtrabackup_stream)
3929
os_file_close(dst_log);
3932
os_event_free(wait_throttle);
3934
if (!xtrabackup_stream) {
3935
#ifndef INNODB_VERSION_SHORT
3936
printf("xtrabackup: Transaction log of lsn (%lu %lu) to (%lu %lu) was copied.\n",
3937
checkpoint_lsn_start.high, checkpoint_lsn_start.low,
3938
log_copy_scanned_lsn.high, log_copy_scanned_lsn.low);
3940
printf("xtrabackup: Transaction log of lsn (%llu) to (%llu) was copied.\n",
3941
checkpoint_lsn_start, log_copy_scanned_lsn);
3944
#ifndef INNODB_VERSION_SHORT
3945
fprintf(stderr, "xtrabackup: Transaction log of lsn (%lu %lu) to (%lu %lu) was copied.\n",
3946
checkpoint_lsn_start.high, checkpoint_lsn_start.low,
3947
log_copy_scanned_lsn.high, log_copy_scanned_lsn.low);
3949
fprintf(stderr, "xtrabackup: Transaction log of lsn (%llu) to (%llu) was copied.\n",
3950
checkpoint_lsn_start, log_copy_scanned_lsn);
3952
if(xtrabackup_extra_lsndir) {
3953
char filename[FN_REFLEN];
3954
sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
3955
if (xtrabackup_write_metadata(filename))
3956
fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
3961
/* ================= stats ================= */
3963
xtrabackup_stats_level(
3964
dict_index_t* index,
3972
ulint right_page_no;
3977
mem_heap_t* heap = mem_heap_create(256);
3979
ulint* offsets = NULL;
3981
ulonglong n_pages, n_pages_extern;
3982
ulonglong sum_data, sum_data_extern;
3986
n_pages = sum_data = n_recs = 0;
3987
n_pages_extern = sum_data_extern = 0;
3989
#ifdef INNODB_VERSION_SHORT
3995
fprintf(stdout, " leaf pages: ");
3997
fprintf(stdout, " level %lu pages: ", level);
4001
#ifndef INNODB_VERSION_SHORT
4002
#if (MYSQL_VERSION_ID < 50100)
4003
mtr_x_lock(&(index->tree->lock), &mtr);
4004
page = btr_root_get(index->tree, &mtr);
4005
#else /* MYSQL_VERSION_ID < 51000 */
4006
mtr_x_lock(&(index->lock), &mtr);
4007
page = btr_root_get(index, &mtr);
4010
mtr_x_lock(&(index->lock), &mtr);
4011
block = btr_root_block_get(index, &mtr);
4012
page = buf_block_get_frame(block);
4015
#ifndef INNODB_VERSION_SHORT
4016
space = buf_frame_get_space_id(page);
4018
space = page_get_space_id(page);
4019
zip_size = fil_space_get_zip_size(space);
4022
while (level != btr_page_get_level(page, &mtr)) {
4024
#ifndef INNODB_VERSION_SHORT
4025
ut_a(btr_page_get_level(page, &mtr) > 0);
4027
ut_a(space == buf_block_get_space(block));
4028
ut_a(space == page_get_space_id(page));
4029
ut_a(!page_is_leaf(page));
4032
#ifndef INNODB_VERSION_SHORT
4033
page_cur_set_before_first(page, &cursor);
4035
page_cur_set_before_first(block, &cursor);
4037
page_cur_move_to_next(&cursor);
4039
node_ptr = page_cur_get_rec(&cursor);
4040
offsets = rec_get_offsets(node_ptr, index, offsets,
4041
ULINT_UNDEFINED, &heap);
4042
#ifndef INNODB_VERSION_SHORT
4043
page = btr_node_ptr_get_child(node_ptr, offsets, &mtr);
4045
block = btr_node_ptr_get_child(node_ptr, index, offsets, &mtr);
4046
page = buf_block_get_frame(block);
4051
mem_heap_empty(heap);
4053
#if (MYSQL_VERSION_ID < 50100)
4054
mtr_x_lock(&(index->tree->lock), &mtr);
4055
#else /* MYSQL_VERSION_ID < 51000 */
4056
mtr_x_lock(&(index->lock), &mtr);
4059
right_page_no = btr_page_get_next(page, &mtr);
4062
/*=================================*/
4063
//fprintf(stdout, "%lu ", (ulint) buf_frame_get_page_no(page));
4066
sum_data += page_get_data_size(page);
4067
n_recs += page_get_n_recs(page);
4074
mem_heap_t* heap = NULL;
4075
ulint offsets_[REC_OFFS_NORMAL_SIZE];
4076
ulint* offsets = offsets_;
4078
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
4080
#ifndef INNODB_VERSION_SHORT
4081
page_cur_set_before_first(page, &cur);
4083
page_cur_set_before_first(block, &cur);
4085
page_cur_move_to_next(&cur);
4088
if (page_cur_is_after_last(&cur)) {
4092
offsets = rec_get_offsets(cur.rec, index, offsets,
4093
ULINT_UNDEFINED, &heap);
4094
n_fields = rec_offs_n_fields(offsets);
4096
for (i = 0; i < n_fields; i++) {
4097
if (rec_offs_nth_extern(offsets, i)) {
4108
#ifdef INNODB_VERSION_SHORT
4112
data = rec_get_nth_field(cur.rec, offsets, i, &local_len);
4114
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
4115
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
4117
space_id = mach_read_from_4(data + local_len + BTR_EXTERN_SPACE_ID);
4118
page_no = mach_read_from_4(data + local_len + BTR_EXTERN_PAGE_NO);
4119
offset = mach_read_from_4(data + local_len + BTR_EXTERN_OFFSET);
4120
extern_len = mach_read_from_4(data + local_len + BTR_EXTERN_LEN + 4);
4122
if (offset != FIL_PAGE_DATA)
4123
fprintf(stderr, "\nWarning: several record may share same external page.\n");
4128
#ifndef INNODB_VERSION_SHORT
4129
page = buf_page_get(space_id, page_no, RW_S_LATCH, &mtr);
4131
block = btr_block_get(space_id, zip_size, page_no, RW_S_LATCH, &mtr);
4132
page = buf_block_get_frame(block);
4134
blob_header = page + offset;
4135
#define BTR_BLOB_HDR_PART_LEN 0
4136
#define BTR_BLOB_HDR_NEXT_PAGE_NO 4
4137
//part_len = btr_blob_get_part_len(blob_header);
4138
part_len = mach_read_from_4(blob_header + BTR_BLOB_HDR_PART_LEN);
4140
//page_no = btr_blob_get_next_page_no(blob_header);
4141
page_no = mach_read_from_4(blob_header + BTR_BLOB_HDR_NEXT_PAGE_NO);
4143
offset = FIL_PAGE_DATA;
4148
/*=================================*/
4149
//fprintf(stdout, "[%lu] ", (ulint) buf_frame_get_page_no(page));
4152
sum_data_extern += part_len;
4157
if (page_no == FIL_NULL)
4163
page_cur_move_to_next(&cur);
4171
if (right_page_no != FIL_NULL) {
4173
#ifndef INNODB_VERSION_SHORT
4174
page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr);
4176
block = btr_block_get(space, zip_size, right_page_no, RW_X_LATCH, &mtr);
4177
page = buf_block_get_frame(block);
4181
mem_heap_free(heap);
4183
#ifndef INNODB_VERSION_SHORT
4184
page_size = UNIV_PAGE_SIZE;
4187
page_size = zip_size;
4189
page_size = UNIV_PAGE_SIZE;
4194
fprintf(stdout, "recs=%lld, ", n_recs);
4196
fprintf(stdout, "pages=%lld, data=%lld bytes, data/pages=%lld%%",
4198
((sum_data * 100)/ page_size)/n_pages);
4201
if (level == 0 && n_pages_extern) {
4203
/* also scan blob pages*/
4204
fprintf(stdout, " external pages: ");
4206
fprintf(stdout, "pages=%lld, data=%lld bytes, data/pages=%lld%%",
4207
n_pages_extern, sum_data_extern,
4208
((sum_data_extern * 100)/ page_size)/n_pages_extern);
4214
xtrabackup_stats_level(index, level - 1);
4221
xtrabackup_stats_func(void)
4225
if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
4227
fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", mysql_real_data_home);
4230
fprintf(stderr, "xtrabackup: cd to %s\n", mysql_real_data_home);
4232
mysql_data_home= mysql_data_home_buff;
4233
mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
4234
mysql_data_home[1]=0;
4237
srv_read_only = TRUE;
4238
srv_fake_write = TRUE;
4240
/* initialize components */
4241
if(innodb_init_param())
4244
fprintf(stderr, "xtrabackup: Starting 'read-only' InnoDB instance to gather index statistics.\n"
4245
"xtrabackup: Using %lld bytes for buffer pool (set by --use-memory parameter)\n",
4246
xtrabackup_use_memory);
4251
fprintf(stdout, "\n\n<INDEX STATISTICS>\n");
4256
dict_table_t* sys_tables;
4257
dict_index_t* sys_index;
4258
dict_table_t* table;
4265
/* Enlarge the fatal semaphore wait timeout during the InnoDB table
4268
mutex_enter(&kernel_mutex);
4269
srv_fatal_semaphore_wait_threshold += 72000; /* 20 hours */
4270
mutex_exit(&kernel_mutex);
4272
mutex_enter(&(dict_sys->mutex));
4276
sys_tables = dict_table_get_low("SYS_TABLES");
4277
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
4279
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
4282
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
4284
rec = btr_pcur_get_rec(&pcur);
4286
#ifndef INNODB_VERSION_SHORT
4287
if (!btr_pcur_is_on_user_rec(&pcur, &mtr))
4289
if (!btr_pcur_is_on_user_rec(&pcur))
4294
btr_pcur_close(&pcur);
4297
mutex_exit(&(dict_sys->mutex));
4299
/* Restore the fatal semaphore wait timeout */
4301
mutex_enter(&kernel_mutex);
4302
srv_fatal_semaphore_wait_threshold -= 72000; /* 20 hours */
4303
mutex_exit(&kernel_mutex);
4308
field = rec_get_nth_field_old(rec, 0, &len);
4310
#if (MYSQL_VERSION_ID < 50100)
4311
if (!rec_get_deleted_flag(rec, sys_tables->comp))
4312
#else /* MYSQL_VERSION_ID < 51000 */
4313
if (!rec_get_deleted_flag(rec, 0))
4319
char* table_name = mem_strdupl((char*) field, len);
4321
btr_pcur_store_position(&pcur, &mtr);
4325
table = dict_table_get_low(table_name);
4326
mem_free(table_name);
4329
if (xtrabackup_tables) {
4334
p = strstr(table->name, SRV_PATH_SEPARATOR_STR);
4339
for (i = 0; i < tables_regex_num; i++) {
4340
regres = regexec(&tables_regex[i], table->name, 1, tables_regmatch, 0);
4341
if (regres != REG_NOMATCH)
4346
*p = SRV_PATH_SEPARATOR;
4348
if ( regres == REG_NOMATCH )
4352
if (xtrabackup_tables_file) {
4353
xtrabackup_tables_t* xtable;
4355
HASH_SEARCH(name_hash, tables_hash, ut_fold_string(table->name),
4356
#ifdef INNODB_VERSION_SHORT
4357
xtrabackup_tables_t*,
4360
#ifdef INNODB_VERSION_SHORT
4361
ut_ad(xtable->name),
4363
!strcmp(xtable->name, table->name));
4370
if (table == NULL) {
4371
fputs("InnoDB: Failed to load table ", stderr);
4372
#if (MYSQL_VERSION_ID < 50100)
4373
ut_print_namel(stderr, NULL, (char*) field, len);
4374
#else /* MYSQL_VERSION_ID < 51000 */
4375
ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
4379
dict_index_t* index;
4381
/* The table definition was corrupt if there
4384
if (dict_table_get_first_index(table)) {
4386
dict_update_statistics(table, TRUE, FALSE);
4387
#elif defined(INNODB_VERSION_SHORT)
4388
dict_update_statistics(table, TRUE);
4390
dict_update_statistics_low(table, TRUE);
4394
//dict_table_print_low(table);
4396
index = UT_LIST_GET_FIRST(table->indexes);
4397
while (index != NULL) {
4401
if (index->n_user_defined_cols > 0) {
4402
n_vals = index->stat_n_diff_key_vals[
4403
index->n_user_defined_cols];
4405
n_vals = index->stat_n_diff_key_vals[1];
4409
" table: %s, index: %s, space id: %lu, root page: %lu"
4410
#ifdef INNODB_VERSION_SHORT
4413
"\n estimated statistics in dictionary:\n"
4414
" key vals: %lu, leaf pages: %lu, size pages: %lu\n"
4415
" real statistics:\n",
4416
table->name, index->name,
4417
(ulong) index->space,
4418
#if (MYSQL_VERSION_ID < 50100)
4419
(ulong) index->tree->page,
4420
#else /* MYSQL_VERSION_ID < 51000 */
4421
(ulong) index->page,
4423
#ifdef INNODB_VERSION_SHORT
4424
(ulong) fil_space_get_zip_size(index->space),
4427
(ulong) index->stat_n_leaf_pages,
4428
(ulong) index->stat_index_size);
4437
#if (MYSQL_VERSION_ID < 50100)
4438
mtr_x_lock(&(index->tree->lock), &mtr);
4439
root = btr_root_get(index->tree, &mtr);
4440
#else /* MYSQL_VERSION_ID < 51000 */
4441
mtr_x_lock(&(index->lock), &mtr);
4442
root = btr_root_get(index, &mtr);
4444
n = btr_page_get_level(root, &mtr);
4446
xtrabackup_stats_level(index, n);
4453
index = UT_LIST_GET_NEXT(indexes, index);
4460
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
4469
/* shutdown InnoDB */
4474
/* ================= prepare ================= */
4477
xtrabackup_init_temp_log(void)
4479
os_file_t src_file = -1;
4480
char src_path[FN_REFLEN];
4481
char dst_path[FN_REFLEN];
4486
byte* log_buf_ = NULL;
4493
LSN64 checkpoint_no;
4497
max_no = ut_dulint_zero;
4499
if(!xtrabackup_incremental_dir) {
4500
sprintf(dst_path, "%s%s", xtrabackup_target_dir, "/ib_logfile0");
4501
sprintf(src_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
4503
sprintf(dst_path, "%s%s", xtrabackup_incremental_dir, "/ib_logfile0");
4504
sprintf(src_path, "%s%s", xtrabackup_incremental_dir, "/xtrabackup_logfile");
4507
srv_normalize_path_for_win(dst_path);
4508
srv_normalize_path_for_win(src_path);
4510
src_file = os_file_create_simple_no_error_handling(
4511
#if (MYSQL_VERSION_ID > 50500)
4512
0 /* dummy of innodb_file_data_key */,
4514
src_path, OS_FILE_OPEN,
4515
OS_FILE_READ_WRITE /* OS_FILE_READ_ONLY */, &success);
4517
/* The following call prints an error message */
4518
os_file_get_last_error(TRUE);
4521
"xtrabackup: Warning: cannot open %s. will try to find.\n",
4524
/* check if ib_logfile0 may be xtrabackup_logfile */
4525
src_file = os_file_create_simple_no_error_handling(
4526
#if (MYSQL_VERSION_ID > 50500)
4527
0 /* dummy of innodb_file_data_key */,
4529
dst_path, OS_FILE_OPEN,
4530
OS_FILE_READ_WRITE /* OS_FILE_READ_ONLY */, &success);
4532
os_file_get_last_error(TRUE);
4534
" xtrabackup: Fatal error: cannot find %s.\n",
4540
log_buf_ = ut_malloc(LOG_FILE_HDR_SIZE * 2);
4541
log_buf = ut_align(log_buf_, LOG_FILE_HDR_SIZE);
4543
success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
4548
if ( ut_memcmp(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
4549
(byte*)"xtrabkup", (sizeof "xtrabkup") - 1) == 0) {
4551
" xtrabackup: 'ib_logfile0' seems to be 'xtrabackup_logfile'. will retry.\n");
4556
os_file_close(src_file);
4559
/* rename and try again */
4560
success = os_file_rename(
4561
#if (MYSQL_VERSION_ID > 50500)
4562
0 /* dummy of innodb_file_data_key */,
4564
dst_path, src_path);
4573
" xtrabackup: Fatal error: cannot find %s.\n",
4579
os_file_close(src_file);
4585
#ifdef USE_POSIX_FADVISE
4586
posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
4587
posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
4590
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
4591
os_file_set_nocache(src_file, src_path, "OPEN");
4594
file_size = os_file_get_size_as_iblonglong(src_file);
4597
/* TODO: We should skip the following modifies, if it is not the first time. */
4598
log_buf_ = ut_malloc(UNIV_PAGE_SIZE * 129);
4599
log_buf = ut_align(log_buf_, UNIV_PAGE_SIZE);
4601
/* read log file header */
4602
success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
4607
if ( ut_memcmp(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
4608
(byte*)"xtrabkup", (sizeof "xtrabkup") - 1) != 0 ) {
4609
printf("xtrabackup: notice: xtrabackup_logfile was already used to '--prepare'.\n");
4612
/* clear it later */
4613
//memset(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
4617
/* read last checkpoint lsn */
4618
for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2;
4619
field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) {
4620
if (!recv_check_cp_is_consistent(log_buf + field))
4621
goto not_consistent;
4623
checkpoint_no = MACH_READ_64(log_buf + field + LOG_CHECKPOINT_NO);
4625
if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) {
4626
max_no = checkpoint_no;
4627
max_lsn = MACH_READ_64(log_buf + field + LOG_CHECKPOINT_LSN);
4630
mach_write_to_4(log_buf + field + LOG_CHECKPOINT_OFFSET,
4631
LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
4632
ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
4635
fold = ut_fold_binary(log_buf + field, LOG_CHECKPOINT_CHECKSUM_1);
4636
mach_write_to_4(log_buf + field + LOG_CHECKPOINT_CHECKSUM_1, fold);
4638
fold = ut_fold_binary(log_buf + field + LOG_CHECKPOINT_LSN,
4639
LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
4640
mach_write_to_4(log_buf + field + LOG_CHECKPOINT_CHECKSUM_2, fold);
4647
if (ut_dulint_cmp(max_no, ut_dulint_zero) == 0) {
4648
fprintf(stderr, "xtrabackup: No valid checkpoint found.\n");
4653
/* It seems to be needed to overwrite the both checkpoint area. */
4654
MACH_WRITE_64(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN, max_lsn);
4655
mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_OFFSET,
4656
LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
4657
ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
4659
MACH_WRITE_64(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_ARCHIVED_LSN,
4660
(ib_uint64_t)(LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
4661
ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE))));
4663
fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_1, LOG_CHECKPOINT_CHECKSUM_1);
4664
mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_CHECKSUM_1, fold);
4666
fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN,
4667
LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
4668
mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_CHECKSUM_2, fold);
4670
MACH_WRITE_64(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN, max_lsn);
4671
mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_OFFSET,
4672
LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
4673
ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
4675
MACH_WRITE_64(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_ARCHIVED_LSN,
4676
(ib_uint64_t)(LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
4677
ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE))));
4679
fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_2, LOG_CHECKPOINT_CHECKSUM_1);
4680
mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_CHECKSUM_1, fold);
4682
fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN,
4683
LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
4684
mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_CHECKSUM_2, fold);
4687
success = os_file_write(src_path, src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
4692
/* expand file size (9/8) and align to UNIV_PAGE_SIZE */
4694
if (file_size % UNIV_PAGE_SIZE) {
4695
memset(log_buf, 0, UNIV_PAGE_SIZE);
4696
success = os_file_write(src_path, src_file, log_buf,
4697
(ulint)(file_size & 0xFFFFFFFFUL),
4698
(ulint)(file_size >> 32),
4699
UNIV_PAGE_SIZE - (file_size % UNIV_PAGE_SIZE));
4704
file_size = os_file_get_size_as_iblonglong(src_file);
4707
/* TODO: We should judge whether the file is already expanded or not... */
4711
memset(log_buf, 0, UNIV_PAGE_SIZE * 128);
4712
expand = file_size / UNIV_PAGE_SIZE / 8;
4714
for (; expand > 128; expand -= 128) {
4715
success = os_file_write(src_path, src_file, log_buf,
4716
(ulint)(file_size & 0xFFFFFFFFUL),
4717
(ulint)(file_size >> 32),
4718
UNIV_PAGE_SIZE * 128);
4722
file_size += UNIV_PAGE_SIZE * 128;
4726
success = os_file_write(src_path, src_file, log_buf,
4727
(ulint)(file_size & 0xFFFFFFFFUL),
4728
(ulint)(file_size >> 32),
4729
expand * UNIV_PAGE_SIZE);
4733
file_size += UNIV_PAGE_SIZE * expand;
4737
/* make larger than 2MB */
4738
if (file_size < 2*1024*1024L) {
4739
memset(log_buf, 0, UNIV_PAGE_SIZE);
4740
while (file_size < 2*1024*1024L) {
4741
success = os_file_write(src_path, src_file, log_buf,
4742
(ulint)(file_size & 0xFFFFFFFFUL),
4743
(ulint)(file_size >> 32),
4748
file_size += UNIV_PAGE_SIZE;
4750
file_size = os_file_get_size_as_iblonglong(src_file);
4753
#ifndef INNODB_VERSION_SHORT
4754
printf("xtrabackup: xtrabackup_logfile detected: size=%lld, start_lsn=(%lu %lu)\n",
4755
file_size, max_lsn.high, max_lsn.low);
4757
printf("xtrabackup: xtrabackup_logfile detected: size=%lld, start_lsn=(%llu)\n",
4758
file_size, max_lsn);
4761
os_file_close(src_file);
4764
/* Backup log parameters */
4765
innobase_log_group_home_dir_backup = innobase_log_group_home_dir;
4766
innobase_log_file_size_backup = innobase_log_file_size;
4767
innobase_log_files_in_group_backup = innobase_log_files_in_group;
4770
innobase_log_group_home_dir = NULL;
4771
innobase_log_file_size = file_size;
4772
innobase_log_files_in_group = 1;
4774
srv_thread_concurrency = 0;
4776
/* rename 'xtrabackup_logfile' to 'ib_logfile0' */
4777
success = os_file_rename(
4778
#if (MYSQL_VERSION_ID > 50500)
4779
0 /* dummy of innodb_file_data_key */,
4781
src_path, dst_path);
4785
xtrabackup_logfile_is_renamed = TRUE;
4792
os_file_close(src_file);
4799
os_file_close(src_file);
4802
fprintf(stderr, "xtrabackup: Error: xtrabackup_init_temp_log() failed.\n");
4803
return(TRUE); /*ERROR*/
4806
/***********************************************************************
4807
Generates path to the meta file path from a given path to an incremental .delta
4808
by replacing trailing ".delta" with ".meta", or returns error if 'delta_path'
4809
does not end with the ".delta" character sequence.
4810
@return TRUE on success, FALSE on error. */
4814
const char *delta_path, /* in: path to a .delta file */
4815
char *meta_path) /* out: path to the corresponding .meta
4818
size_t len = strlen(delta_path);
4820
if (len <= 6 || strcmp(delta_path + len - 6, ".delta")) {
4823
memcpy(meta_path, delta_path, len - 6);
4824
strcpy(meta_path + len - 6, XB_DELTA_INFO_SUFFIX);
4830
xtrabackup_apply_delta(
4831
const char* dirname, /* in: dir name of incremental */
4832
const char* dbname, /* in: database name (ibdata: NULL) */
4833
const char* filename, /* in: file name (not a path),
4834
including the .delta extension */
4835
my_bool check_newer)
4837
os_file_t src_file = -1;
4838
os_file_t dst_file = -1;
4839
char src_path[FN_REFLEN];
4840
char dst_path[FN_REFLEN];
4841
char meta_path[FN_REFLEN];
4844
ibool last_buffer = FALSE;
4845
ulint page_in_buffer;
4846
ulint incremental_buffers = 0;
4848
xb_delta_info_t info;
4850
ulint page_size_shift;
4852
ut_a(xtrabackup_incremental);
4855
snprintf(src_path, sizeof(src_path), "%s/%s/%s",
4856
dirname, dbname, filename);
4857
snprintf(dst_path, sizeof(dst_path), "%s/%s/%s",
4858
xtrabackup_real_target_dir, dbname, filename);
4860
snprintf(src_path, sizeof(src_path), "%s/%s",
4862
snprintf(dst_path, sizeof(dst_path), "%s/%s",
4863
xtrabackup_real_target_dir, filename);
4865
dst_path[strlen(dst_path) - 6] = '\0';
4867
if (!get_meta_path(src_path, meta_path)) {
4871
srv_normalize_path_for_win(dst_path);
4872
srv_normalize_path_for_win(src_path);
4873
srv_normalize_path_for_win(meta_path);
4875
if (!xb_read_delta_metadata(meta_path, &info)) {
4879
page_size = info.page_size;
4880
page_size_shift = get_bit_shift(page_size);
4881
fprintf(stderr, "xtrabackup: page size for %s is %lu bytes\n",
4882
src_path, page_size);
4883
if (page_size_shift < 10 ||
4884
page_size_shift > UNIV_PAGE_SIZE_SHIFT_MAX) {
4886
"xtrabackup: error: invalid value of page_size "
4887
"(%lu bytes) read from %s\n", page_size, meta_path);
4891
src_file = os_file_create_simple_no_error_handling(
4892
#if (MYSQL_VERSION_ID > 50500)
4893
0 /* dummy of innodb_file_data_key */,
4895
src_path, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
4897
os_file_get_last_error(TRUE);
4899
"xtrabackup: error: cannot open %s\n",
4904
#ifdef USE_POSIX_FADVISE
4905
posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
4906
posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
4909
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
4910
os_file_set_nocache(src_file, src_path, "OPEN");
4913
dst_file = os_file_create_simple_no_error_handling(
4914
#if (MYSQL_VERSION_ID > 50500)
4915
0 /* dummy of innodb_file_data_key */,
4917
dst_path, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
4919
os_file_get_last_error(TRUE);
4921
"xtrabackup: error: cannot open %s\n",
4926
#ifdef USE_POSIX_FADVISE
4927
posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED);
4930
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
4931
os_file_set_nocache(dst_file, dst_path, "OPEN");
4934
printf("Applying %s ...\n", src_path);
4936
while (!last_buffer) {
4937
ulint cluster_header;
4939
/* read to buffer */
4940
/* first block of block cluster */
4941
success = os_file_read(src_file, incremental_buffer,
4942
((incremental_buffers * (page_size / 4))
4943
<< page_size_shift) & 0xFFFFFFFFUL,
4944
(incremental_buffers * (page_size / 4))
4945
>> (32 - page_size_shift),
4951
cluster_header = mach_read_from_4(incremental_buffer);
4952
switch(cluster_header) {
4953
case 0x78747261UL: /*"xtra"*/
4955
case 0x58545241UL: /*"XTRA"*/
4960
"xtrabackup: error: %s seems not .delta file.\n",
4965
for (page_in_buffer = 1; page_in_buffer < page_size / 4;
4967
if (mach_read_from_4(incremental_buffer + page_in_buffer * 4)
4972
ut_a(last_buffer || page_in_buffer == page_size / 4);
4974
/* read whole of the cluster */
4975
success = os_file_read(src_file, incremental_buffer,
4976
((incremental_buffers * (page_size / 4))
4977
<< page_size_shift) & 0xFFFFFFFFUL,
4978
(incremental_buffers * (page_size / 4))
4979
>> (32 - page_size_shift),
4980
page_in_buffer * page_size);
4985
for (page_in_buffer = 1; page_in_buffer < page_size / 4;
4989
page_offset = mach_read_from_4(incremental_buffer + page_in_buffer * 4);
4991
if (page_offset == 0xFFFFFFFFUL)
4994
/* apply blocks in the cluster */
4995
// if (ut_dulint_cmp(incremental_lsn,
4996
// MACH_READ_64(incremental_buffer
4997
// + page_in_buffer * page_size
4998
// + FIL_PAGE_LSN)) >= 0)
5001
success = os_file_write(dst_path, dst_file,
5002
incremental_buffer +
5003
page_in_buffer * page_size,
5004
(page_offset << page_size_shift) &
5006
page_offset >> (32 - page_size_shift),
5013
incremental_buffers++;
5017
os_file_close(src_file);
5019
os_file_close(dst_file);
5024
os_file_close(src_file);
5026
os_file_close(dst_file);
5027
fprintf(stderr, "xtrabackup: Error: xtrabackup_apply_delta() failed.\n");
5032
xtrabackup_apply_deltas(my_bool check_newer)
5035
char dbpath[FN_REFLEN];
5037
os_file_dir_t dbdir;
5038
os_file_stat_t dbinfo;
5039
os_file_stat_t fileinfo;
5040
ulint err = DB_SUCCESS;
5041
static char current_dir[2];
5043
current_dir[0] = FN_CURLIB;
5045
srv_data_home = current_dir;
5048
dbdir = os_file_opendir(xtrabackup_incremental_dir, FALSE);
5050
if (dbdir != NULL) {
5051
ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dbdir,
5054
if (fileinfo.type == OS_FILE_TYPE_DIR) {
5055
goto next_file_item_1;
5058
if (strlen(fileinfo.name) > 6
5059
&& 0 == strcmp(fileinfo.name +
5060
strlen(fileinfo.name) - 6,
5062
xtrabackup_apply_delta(
5063
xtrabackup_incremental_dir, NULL,
5064
fileinfo.name, check_newer);
5067
ret = fil_file_readdir_next_file(&err,
5068
xtrabackup_incremental_dir, dbdir,
5072
os_file_closedir(dbdir);
5074
fprintf(stderr, "xtrabackup: Cannot open dir %s\n", xtrabackup_incremental_dir);
5077
/* single table tablespaces */
5078
dir = os_file_opendir(xtrabackup_incremental_dir, FALSE);
5081
fprintf(stderr, "xtrabackup: Cannot open dir %s\n", xtrabackup_incremental_dir);
5084
ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dir,
5087
if (dbinfo.type == OS_FILE_TYPE_FILE
5088
|| dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
5090
goto next_datadir_item;
5093
sprintf(dbpath, "%s/%s", xtrabackup_incremental_dir,
5095
srv_normalize_path_for_win(dbpath);
5097
dbdir = os_file_opendir(dbpath, FALSE);
5099
if (dbdir != NULL) {
5101
ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
5105
if (fileinfo.type == OS_FILE_TYPE_DIR) {
5107
goto next_file_item_2;
5110
if (strlen(fileinfo.name) > 6
5111
&& 0 == strcmp(fileinfo.name +
5112
strlen(fileinfo.name) - 6,
5114
/* The name ends in .delta; try opening
5116
xtrabackup_apply_delta(
5117
xtrabackup_incremental_dir, dbinfo.name,
5118
fileinfo.name, check_newer);
5121
ret = fil_file_readdir_next_file(&err,
5126
os_file_closedir(dbdir);
5129
ret = fil_file_readdir_next_file(&err,
5130
xtrabackup_incremental_dir,
5134
os_file_closedir(dir);
5139
xtrabackup_close_temp_log(my_bool clear_flag)
5141
os_file_t src_file = -1;
5142
char src_path[FN_REFLEN];
5143
char dst_path[FN_REFLEN];
5147
byte* log_buf_ = NULL;
5150
if (!xtrabackup_logfile_is_renamed)
5153
/* Restore log parameters */
5154
innobase_log_group_home_dir = innobase_log_group_home_dir_backup;
5155
innobase_log_file_size = innobase_log_file_size_backup;
5156
innobase_log_files_in_group = innobase_log_files_in_group_backup;
5158
/* rename 'ib_logfile0' to 'xtrabackup_logfile' */
5159
if(!xtrabackup_incremental_dir) {
5160
sprintf(dst_path, "%s%s", xtrabackup_target_dir, "/ib_logfile0");
5161
sprintf(src_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
5163
sprintf(dst_path, "%s%s", xtrabackup_incremental_dir, "/ib_logfile0");
5164
sprintf(src_path, "%s%s", xtrabackup_incremental_dir, "/xtrabackup_logfile");
5167
srv_normalize_path_for_win(dst_path);
5168
srv_normalize_path_for_win(src_path);
5170
success = os_file_rename(
5171
#if (MYSQL_VERSION_ID > 50500)
5172
0 /* dummy of innodb_file_data_key */,
5174
dst_path, src_path);
5178
xtrabackup_logfile_is_renamed = FALSE;
5183
/* clear LOG_FILE_WAS_CREATED_BY_HOT_BACKUP field */
5184
src_file = os_file_create_simple_no_error_handling(
5185
#if (MYSQL_VERSION_ID > 50500)
5186
0 /* dummy of innodb_file_data_key */,
5188
src_path, OS_FILE_OPEN,
5189
OS_FILE_READ_WRITE, &success);
5194
#ifdef USE_POSIX_FADVISE
5195
posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
5198
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
5199
os_file_set_nocache(src_file, src_path, "OPEN");
5202
log_buf_ = ut_malloc(LOG_FILE_HDR_SIZE * 2);
5203
log_buf = ut_align(log_buf_, LOG_FILE_HDR_SIZE);
5205
success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
5210
memset(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, ' ', 4);
5212
success = os_file_write(src_path, src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
5217
os_file_close(src_file);
5223
os_file_close(src_file);
5226
fprintf(stderr, "xtrabackup: Error: xtrabackup_close_temp_log() failed.\n");
5227
return(TRUE); /*ERROR*/
5231
xtrabackup_prepare_func(void)
5233
/* cd to target-dir */
5235
if (my_setwd(xtrabackup_real_target_dir,MYF(MY_WME)))
5237
fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", xtrabackup_real_target_dir);
5240
fprintf(stderr, "xtrabackup: cd to %s\n", xtrabackup_real_target_dir);
5242
xtrabackup_target_dir= mysql_data_home_buff;
5243
xtrabackup_target_dir[0]=FN_CURLIB; // all paths are relative from here
5244
xtrabackup_target_dir[1]=0;
5246
/* read metadata of target */
5248
char filename[FN_REFLEN];
5250
sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
5252
if (xtrabackup_read_metadata(filename))
5253
fprintf(stderr, "xtrabackup: error: xtrabackup_read_metadata()\n");
5255
if (!strcmp(metadata_type, "full-backuped")) {
5256
fprintf(stderr, "xtrabackup: This target seems to be not prepared yet.\n");
5257
} else if (!strcmp(metadata_type, "full-prepared")) {
5258
fprintf(stderr, "xtrabackup: This target seems to be already prepared.\n");
5261
fprintf(stderr, "xtrabackup: This target seems not to have correct metadata...\n");
5264
if (xtrabackup_incremental) {
5266
"xtrabackup: error: applying incremental backup needs target prepared.\n");
5270
if (xtrabackup_incremental
5271
&& ut_dulint_cmp(metadata_to_lsn, incremental_lsn) != 0) {
5273
"xtrabackup: error: This incremental backup seems not to be proper for the target.\n"
5274
"xtrabackup: Check 'to_lsn' of the target and 'from_lsn' of the incremental.\n");
5279
/* Create logfiles for recovery from 'xtrabackup_logfile', before start InnoDB */
5280
srv_max_n_threads = 1000;
5281
os_sync_mutex = NULL;
5282
#ifdef INNODB_VERSION_SHORT
5285
/* temporally dummy value to avoid crash */
5286
srv_page_size_shift = 14;
5287
srv_page_size = (1 << srv_page_size_shift);
5292
os_io_init_simple();
5293
if(xtrabackup_init_temp_log())
5296
if(xtrabackup_incremental)
5297
xtrabackup_apply_deltas(TRUE);
5300
sync_initialized = FALSE;
5302
os_sync_mutex = NULL;
5305
/* check the accessibility of target-dir */
5306
/* ############# TODO ##################### */
5308
if(innodb_init_param())
5311
srv_apply_log_only = (ibool) xtrabackup_apply_log_only;
5313
/* increase IO threads */
5314
if(srv_n_file_io_threads < 10) {
5315
srv_n_file_io_threads = 10;
5318
fprintf(stderr, "xtrabackup: Starting InnoDB instance for recovery.\n"
5319
"xtrabackup: Using %lld bytes for buffer pool (set by --use-memory parameter)\n",
5320
xtrabackup_use_memory);
5325
//printf("Hello InnoDB world!\n");
5327
/* TEST: innodb status*/
5329
ulint trx_list_start = ULINT_UNDEFINED;
5330
ulint trx_list_end = ULINT_UNDEFINED;
5331
srv_printf_innodb_monitor(stdout, &trx_list_start, &trx_list_end);
5333
/* TEST: list of datafiles and transaction log files and LSN*/
5336
fil_system_t* system = fil_system;
5340
mutex_enter(&(system->mutex));
5342
space = UT_LIST_GET_FIRST(system->space_list);
5344
while (space != NULL) {
5345
printf("space: name=%s, id=%d, purpose=%d, size=%d\n",
5346
space->name, space->id, space->purpose, space->size);
5348
node = UT_LIST_GET_FIRST(space->chain);
5350
while (node != NULL) {
5351
printf("node: name=%s, open=%d, size=%d\n",
5352
node->name, node->open, node->size);
5354
node = UT_LIST_GET_NEXT(chain, node);
5356
space = UT_LIST_GET_NEXT(space_list, space);
5359
mutex_exit(&(system->mutex));
5362
/* align space sizes along with fsp header */
5364
fil_system_t* system = fil_system;
5368
mutex_enter(&(system->mutex));
5369
space = UT_LIST_GET_FIRST(system->space_list);
5371
while (space != NULL) {
5376
#ifdef INNODB_VERSION_SHORT
5381
if (space->purpose == FIL_TABLESPACE) {
5382
mutex_exit(&(system->mutex));
5386
#ifndef INNODB_VERSION_SHORT
5387
mtr_s_lock(fil_space_get_latch(space->id), &mtr);
5389
header = FIL_PAGE_DATA + buf_page_get(space->id, 0, RW_S_LATCH, &mtr);
5391
mtr_s_lock(fil_space_get_latch(space->id, &flags), &mtr);
5393
block = buf_page_get(space->id,
5394
dict_table_flags_to_zip_size(flags),
5395
0, RW_S_LATCH, &mtr);
5396
header = FIL_PAGE_DATA /*FSP_HEADER_OFFSET*/
5397
+ buf_block_get_frame(block);
5400
size = mtr_read_ulint(header + 8 /* FSP_SIZE */, MLOG_4BYTES, &mtr);
5404
//printf("%d, %d\n", space->id, size);
5406
fil_extend_space_to_desired_size(&actual_size, space->id, size);
5408
mutex_enter(&(system->mutex));
5411
space = UT_LIST_GET_NEXT(space_list, space);
5414
mutex_exit(&(system->mutex));
5419
if (xtrabackup_export) {
5420
printf("xtrabackup: export option is specified.\n");
5421
if (innobase_file_per_table) {
5422
fil_system_t* system = fil_system;
5425
os_file_t info_file = -1;
5426
char info_file_path[FN_REFLEN];
5428
char table_name[FN_REFLEN];
5433
buf = ut_malloc(UNIV_PAGE_SIZE * 2);
5434
page = ut_align(buf, UNIV_PAGE_SIZE);
5436
/* flush insert buffer at shutdwon */
5437
innobase_fast_shutdown = 0;
5439
mutex_enter(&(system->mutex));
5441
space = UT_LIST_GET_FIRST(system->space_list);
5442
while (space != NULL) {
5443
/* treat file_per_table only */
5444
if (space->purpose != FIL_TABLESPACE
5446
|| trx_sys_sys_space(space->id)
5452
space = UT_LIST_GET_NEXT(space_list, space);
5456
node = UT_LIST_GET_FIRST(space->chain);
5457
while (node != NULL) {
5459
char *next, *prev, *p;
5460
dict_table_t* table;
5461
dict_index_t* index;
5464
/* node exist == file exist, here */
5465
strncpy(info_file_path, node->name, FN_REFLEN);
5466
len = strlen(info_file_path);
5467
info_file_path[len - 3] = 'e';
5468
info_file_path[len - 2] = 'x';
5469
info_file_path[len - 1] = 'p';
5473
while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
5478
info_file_path[len - 4] = 0;
5479
strncpy(table_name, prev, FN_REFLEN);
5481
info_file_path[len - 4] = '.';
5483
mutex_exit(&(system->mutex));
5484
mutex_enter(&(dict_sys->mutex));
5486
table = dict_table_get_low(table_name);
5489
"xtrabackup: error: cannot find dictionary record of table %s\n", table_name);
5492
index = dict_table_get_first_index(table);
5493
n_index = UT_LIST_GET_LEN(table->indexes);
5496
"xtrabackup: error: sorry, cannot export over 31 indexes for now.\n");
5501
bzero(page, UNIV_PAGE_SIZE);
5502
mach_write_to_4(page , 0x78706f72UL);
5503
mach_write_to_4(page + 4, 0x74696e66UL);/*"xportinf"*/
5504
mach_write_to_4(page + 8, n_index);
5505
strncpy(page + 12, table_name, 500);
5508
"xtrabackup: export metadata of table '%s' to file `%s` (%lu indexes)\n",
5509
table_name, info_file_path, n_index);
5513
mach_write_to_8(page + n_index * 512, index->id);
5514
mach_write_to_4(page + n_index * 512 + 8,
5515
#if (MYSQL_VERSION_ID < 50100)
5517
#else /* MYSQL_VERSION_ID < 51000 */
5520
strncpy(page + n_index * 512 + 12, index->name, 500);
5523
"xtrabackup: name=%s, id.low=%lu, page=%lu\n",
5525
#if (MYSQL_VERSION_ID < 50500)
5528
(ulint)(index->id & 0xFFFFFFFFUL),
5530
#if (MYSQL_VERSION_ID < 50100)
5532
#else /* MYSQL_VERSION_ID < 51000 */
5533
(ulint) index->page);
5536
index = dict_table_get_next_index(index);
5540
srv_normalize_path_for_win(info_file_path);
5541
info_file = os_file_create(
5542
#if (MYSQL_VERSION_ID > 50500)
5543
0 /* dummy of innodb_file_data_key */,
5545
info_file_path, OS_FILE_OVERWRITE,
5546
OS_FILE_NORMAL, OS_DATA_FILE, &success);
5548
os_file_get_last_error(TRUE);
5551
success = os_file_write(info_file_path, info_file, page,
5552
0, 0, UNIV_PAGE_SIZE);
5554
os_file_get_last_error(TRUE);
5557
success = os_file_flush(info_file);
5559
os_file_get_last_error(TRUE);
5563
if (info_file != -1) {
5564
os_file_close(info_file);
5567
mutex_exit(&(dict_sys->mutex));
5568
mutex_enter(&(system->mutex));
5570
node = UT_LIST_GET_NEXT(chain, node);
5573
space = UT_LIST_GET_NEXT(space_list, space);
5575
mutex_exit(&(system->mutex));
5579
printf("xtrabackup: export option is for file_per_table only, disabled.\n");
5583
/* print binlog position (again?) */
5584
printf("\n[notice (again)]\n"
5585
" If you use binary log and don't use any hack of group commit,\n"
5586
" the binary log position seems to be:\n");
5587
trx_sys_print_mysql_binlog_offset();
5590
/* output to xtrabackup_binlog_pos_innodb */
5591
if (*trx_sys_mysql_bin_log_name != '\0') {
5594
fp = fopen("xtrabackup_binlog_pos_innodb", "w");
5596
fprintf(fp, "%s\t%llu\n",
5597
trx_sys_mysql_bin_log_name,
5598
trx_sys_mysql_bin_log_pos);
5601
printf("xtrabackup: failed to open 'xtrabackup_binlog_pos_innodb'\n");
5605
/* Check whether the log is applied enough or not. */
5606
if ((xtrabackup_incremental
5607
&& ut_dulint_cmp(srv_start_lsn, incremental_last_lsn) < 0)
5608
||(!xtrabackup_incremental
5609
&& ut_dulint_cmp(srv_start_lsn, metadata_last_lsn) < 0)) {
5610
printf( "xtrabackup: ########################################################\n"
5611
"xtrabackup: # !!WARNING!! #\n"
5612
"xtrabackup: # The transaction log file should be wrong or corrupt. #\n"
5613
"xtrabackup: # The log was not applied to the intended LSN! #\n"
5614
"xtrabackup: ########################################################\n");
5615
if (xtrabackup_incremental) {
5616
#ifndef INNODB_VERSION_SHORT
5617
printf("xtrabackup: The intended lsn is %lu:%lu\n",
5618
incremental_last_lsn.high, incremental_last_lsn.low);
5620
printf("xtrabackup: The intended lsn is %llu\n",
5621
incremental_last_lsn);
5624
#ifndef INNODB_VERSION_SHORT
5625
printf("xtrabackup: The intended lsn is %lu:%lu\n",
5626
metadata_last_lsn.high, metadata_last_lsn.low);
5628
printf("xtrabackup: The intended lsn is %llu\n",
5637
sync_initialized = FALSE;
5638
os_sync_mutex = NULL;
5640
/* re-init necessary components */
5641
#ifdef INNODB_VERSION_SHORT
5646
os_io_init_simple();
5648
if(xtrabackup_close_temp_log(TRUE))
5651
/* output to metadata file */
5653
char filename[FN_REFLEN];
5655
strcpy(metadata_type, "full-prepared");
5657
if(xtrabackup_incremental
5658
&& ut_dulint_cmp(metadata_to_lsn, incremental_to_lsn) < 0)
5660
metadata_to_lsn = incremental_to_lsn;
5661
metadata_last_lsn = incremental_last_lsn;
5664
sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
5665
if (xtrabackup_write_metadata(filename))
5666
fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_target_dir)\n");
5668
if(xtrabackup_extra_lsndir) {
5669
sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
5670
if (xtrabackup_write_metadata(filename))
5671
fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
5675
if(!xtrabackup_create_ib_logfile)
5678
/* TODO: make more smart */
5680
printf("\n[notice]\nWe cannot call InnoDB second time during the process lifetime.\n");
5681
printf("Please re-execte to create ib_logfile*. Sorry.\n");
5683
printf("Restart InnoDB to create ib_logfile*.\n");
5685
if(innodb_init_param())
5698
xtrabackup_close_temp_log(FALSE);
5703
/* ================= main =================== */
5705
int main(int argc, char **argv)
5711
load_defaults("my",load_default_groups,&argc,&argv);
5713
/* ignore unsupported options */
5715
int i,j,argc_new,find;
5716
char *optend, *prev_found;
5720
for (i=1 ; i < argc ; i++) {
5722
struct my_option *opt= (struct my_option *) my_long_options;
5723
optend= strcend((argv)[i], '=');
5724
for (count= 0; opt->name; opt++) {
5725
if (!getopt_compare_strings(opt->name, (argv)[i] + 2,
5726
(uint)(optend - (argv)[i] - 2))) /* match found */
5728
if (!opt->name[(uint)(optend - (argv)[i] - 2)]) {
5734
prev_found= (char *) opt->name;
5736
else if (strcmp(prev_found, opt->name)) {
5746
(argv)[j]=(argv)[i];
5754
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
5757
if (strcmp(mysql_data_home, "./") == 0) {
5758
if (!xtrabackup_print_param)
5760
printf("\nxtrabackup: Error: Please set parameter 'datadir'\n");
5764
if (xtrabackup_tables) {
5770
tables_regex_num = 1;
5772
p = xtrabackup_tables;
5773
while ((p = strchr(p, ',')) != NULL) {
5778
tables_regex = ut_malloc(sizeof(regex_t) * tables_regex_num);
5780
p = xtrabackup_tables;
5781
for (i=0; i < tables_regex_num; i++) {
5782
next = strchr(p, ',');
5783
ut_a(next || i == tables_regex_num - 1);
5786
if (i != tables_regex_num - 1)
5789
regerror(regcomp(&tables_regex[i],p,REG_EXTENDED),
5790
&tables_regex[i],errbuf,sizeof(errbuf));
5791
fprintf(stderr, "xtrabackup: tables regcomp(%s): %s\n",p,errbuf);
5793
if (i != tables_regex_num - 1)
5799
if (xtrabackup_tables_file) {
5800
char name_buf[NAME_LEN*2+2];
5803
if (xtrabackup_stream) {
5804
fprintf(stderr, "xtrabackup: Warning: --tables_file option doesn't affect with --stream.\n", xtrabackup_tables_file);
5805
xtrabackup_tables_file = NULL;
5806
goto skip_tables_file_register;
5809
name_buf[NAME_LEN*2+1] = '\0';
5811
/* init tables_hash */
5812
tables_hash = hash_create(1000);
5814
/* read and store the filenames */
5815
fp = fopen(xtrabackup_tables_file,"r");
5817
fprintf(stderr, "xtrabackup: cannot open %s\n", xtrabackup_tables_file);
5821
xtrabackup_tables_t* table;
5824
if ( fgets(name_buf, NAME_LEN*2+1, fp) == 0 ) {
5828
while (*p != '\0') {
5834
p = strchr(name_buf, '\n');
5840
table = malloc(sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1);
5841
memset(table, '\0', sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1);
5842
table->name = ((char*)table) + sizeof(xtrabackup_tables_t);
5843
strcpy(table->name, name_buf);
5845
HASH_INSERT(xtrabackup_tables_t, name_hash, tables_hash,
5846
ut_fold_string(table->name), table);
5848
printf("xtrabackup: table '%s' is registerd to the list.\n", table->name);
5851
skip_tables_file_register:
5854
/* temporary setting of enough size */
5855
srv_page_size_shift = UNIV_PAGE_SIZE_SHIFT_MAX;
5856
srv_page_size = UNIV_PAGE_SIZE_MAX;
5857
srv_log_block_size = 512;
5859
if (xtrabackup_backup && xtrabackup_incremental) {
5860
/* direct specification is only for --backup */
5861
/* and the lsn is prior to the other option */
5863
char* incremental_low;
5865
long long lsn_high, lsn_low;
5868
#ifndef INNODB_VERSION_SHORT
5869
incremental_low = strstr(xtrabackup_incremental, ":");
5870
if (incremental_low) {
5871
*incremental_low = '\0';
5873
lsn_high = strtoll(xtrabackup_incremental, &endchar, 10);
5874
if (*endchar != '\0' || (lsn_high >> 32))
5877
*incremental_low = ':';
5880
lsn_low = strtoll(incremental_low, &endchar, 10);
5882
if (*endchar != '\0' || (lsn_low >> 32))
5885
incremental_lsn = ut_dulint_create((ulint)lsn_high, (ulint)lsn_low);
5890
incremental_lsn = strtoll(xtrabackup_incremental, &endchar, 10);
5891
if (*endchar != '\0')
5896
fprintf(stderr, "xtrabackup: value '%s' may be wrong format for incremental option.\n",
5897
xtrabackup_incremental);
5901
/* allocate buffer for incremental backup (4096 pages) */
5902
incremental_buffer_base = malloc((UNIV_PAGE_SIZE_MAX / 4 + 1) *
5903
UNIV_PAGE_SIZE_MAX);
5904
incremental_buffer = ut_align(incremental_buffer_base,
5905
UNIV_PAGE_SIZE_MAX);
5906
} else if (xtrabackup_backup && xtrabackup_incremental_basedir) {
5907
char filename[FN_REFLEN];
5909
sprintf(filename, "%s/%s", xtrabackup_incremental_basedir, XTRABACKUP_METADATA_FILENAME);
5911
if (xtrabackup_read_metadata(filename)) {
5913
"xtrabackup: error: failed to read metadata from %s\n",
5918
incremental_lsn = metadata_to_lsn;
5919
xtrabackup_incremental = xtrabackup_incremental_basedir; //dummy
5921
/* allocate buffer for incremental backup (4096 pages) */
5922
incremental_buffer_base = malloc((UNIV_PAGE_SIZE_MAX / 4 + 1) *
5923
UNIV_PAGE_SIZE_MAX);
5924
incremental_buffer = ut_align(incremental_buffer_base,
5925
UNIV_PAGE_SIZE_MAX);
5926
} else if (xtrabackup_prepare && xtrabackup_incremental_dir) {
5927
char filename[FN_REFLEN];
5929
sprintf(filename, "%s/%s", xtrabackup_incremental_dir, XTRABACKUP_METADATA_FILENAME);
5931
if (xtrabackup_read_metadata(filename)) {
5933
"xtrabackup: error: failed to read metadata from %s\n",
5938
incremental_lsn = metadata_from_lsn;
5939
incremental_to_lsn = metadata_to_lsn;
5940
incremental_last_lsn = metadata_last_lsn;
5941
xtrabackup_incremental = xtrabackup_incremental_dir; //dummy
5943
/* allocate buffer for incremental backup (4096 pages) */
5944
incremental_buffer_base = malloc((UNIV_PAGE_SIZE / 4 + 1) *
5946
incremental_buffer = ut_align(incremental_buffer_base,
5949
/* allocate buffer for applying incremental (for header page only) */
5950
incremental_buffer_base = malloc((1 + 1) * UNIV_PAGE_SIZE_MAX);
5951
incremental_buffer = ut_align(incremental_buffer_base,
5952
UNIV_PAGE_SIZE_MAX);
5954
xtrabackup_incremental = NULL;
5958
if (xtrabackup_print_param) {
5959
/* === some variables from mysqld === */
5960
bzero((G_PTR) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
5962
if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
5965
printf("# This MySQL options file was generated by XtraBackup.\n");
5966
printf("[mysqld]\n");
5967
printf("datadir = \"%s\"\n", mysql_data_home);
5968
printf("tmpdir = \"%s\"\n", mysql_tmpdir_list.list[0]);
5969
printf("innodb_data_home_dir = \"%s\"\n",
5970
innobase_data_home_dir ? innobase_data_home_dir : mysql_data_home);
5971
printf("innodb_data_file_path = \"%s\"\n",
5972
innobase_data_file_path ? innobase_data_file_path : "ibdata1:10M:autoextend");
5973
printf("innodb_log_group_home_dir = \"%s\"\n",
5974
innobase_log_group_home_dir ? innobase_log_group_home_dir : mysql_data_home);
5975
printf("innodb_log_files_in_group = %ld\n", innobase_log_files_in_group);
5976
printf("innodb_log_file_size = %lld\n", innobase_log_file_size);
5977
printf("innodb_flush_method = \"%s\"\n",
5978
(innobase_unix_file_flush_method != NULL) ?
5979
innobase_unix_file_flush_method : "");
5983
if (!xtrabackup_stream) {
5985
if (xtrabackup_incremental) {
5986
#ifndef INNODB_VERSION_SHORT
5987
printf("incremental backup from %lu:%lu is enabled.\n",
5988
incremental_lsn.high, incremental_lsn.low);
5990
printf("incremental backup from %llu is enabled.\n",
5995
if (xtrabackup_backup) {
5996
xtrabackup_suspend_at_end = TRUE;
5997
fprintf(stderr, "xtrabackup: suspend-at-end is enabled.\n");
6001
/* cannot execute both for now */
6005
if (xtrabackup_backup) num++;
6006
if (xtrabackup_stats) num++;
6007
if (xtrabackup_prepare) num++;
6008
if (num != 1) { /* !XOR (for now) */
6015
if (xtrabackup_backup)
6016
xtrabackup_backup_func();
6019
if (xtrabackup_stats)
6020
xtrabackup_stats_func();
6023
if (xtrabackup_prepare)
6024
xtrabackup_prepare_func();
6026
free(incremental_buffer_base);
6028
if (xtrabackup_tables) {
6032
for (i = 0; i < tables_regex_num; i++) {
6033
regfree(&tables_regex[i]);
6035
ut_free(tables_regex);
6038
if (xtrabackup_tables_file) {
6041
/* free the hash elements */
6042
for (i = 0; i < hash_get_n_cells(tables_hash); i++) {
6043
xtrabackup_tables_t* table;
6045
table = HASH_GET_FIRST(tables_hash, i);
6048
xtrabackup_tables_t* prev_table = table;
6050
table = HASH_GET_NEXT(name_hash, prev_table);
6052
HASH_DELETE(xtrabackup_tables_t, name_hash, tables_hash,
6053
ut_fold_string(prev_table->name), prev_table);
6058
/* free tables_hash */
6059
hash_table_free(tables_hash);