1
/******************************************************
2
XtraBackup: The another hot backup tool for InnoDB
5
Created 3/3/2009 Yasufumi Kinoshita
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; version 2 of the License.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
*******************************************************/
22
#ifndef XTRABACKUP_VERSION
23
#define XTRABACKUP_VERSION "undefined"
25
#ifndef XTRABACKUP_REVISION
26
#define XTRABACKUP_REVISION "undefined"
31
#include <drizzled/internal/my_sys.h>
32
#include <drizzled/charset_info.h>
33
#include <drizzled/charset.h>
34
#include <drizzled/global_charset_info.h> // for default_charset_info
35
#include <drizzled/gettext.h>
36
#include <drizzled/constrained_value.h>
37
#include <drizzled/configmake.h>
38
#include <drizzled/error/level_t.h>
40
#include "ha_prototypes.h"
41
//#define XTRABACKUP_TARGET_IS_PLUGIN
42
#include <boost/program_options.hpp>
43
#include <boost/scoped_ptr.hpp>
45
typedef drizzled::charset_info_st CHARSET_INFO;
47
#define my_progname "xtrabackup"
49
#define MYSQL_VERSION_ID 50507 /* Drizzle is much greater */
53
#include <os0thread.h>
54
#include <srv0start.h>
61
#include <row0mysql.h>
66
#include <lock0lock.h>
67
#include <dict0crea.h>
72
#include <sync0sync.h>
76
#ifdef INNODB_VERSION_SHORT
77
#include <ibuf0ibuf.h>
82
#define IB_INT64 ib_int64_t
83
#define LSN64 ib_uint64_t
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()
87
#define ut_dulint_zero 0
88
#define ut_dulint_cmp(A, B) (A > B ? 1 : (A == B ? 0 : -1))
89
#define ut_dulint_add(A, B) (A + B)
90
#define ut_dulint_minus(A, B) (A - B)
91
#define ut_dulint_align_down(A, B) (A & ~((ib_int64_t)B - 1))
92
#define ut_dulint_align_up(A, B) ((A + B - 1) & ~((ib_int64_t)B - 1))
95
#define SRV_PATH_SEPARATOR '\\'
96
#define SRV_PATH_SEPARATOR_STR "\\"
98
#define SRV_PATH_SEPARATOR '/'
99
#define SRV_PATH_SEPARATOR_STR "/"
102
#ifndef UNIV_PAGE_SIZE_MAX
103
#define UNIV_PAGE_SIZE_MAX UNIV_PAGE_SIZE
105
#ifndef UNIV_PAGE_SIZE_SHIFT_MAX
106
#define UNIV_PAGE_SIZE_SHIFT_MAX UNIV_PAGE_SIZE_SHIFT
109
using namespace drizzled;
110
namespace po=boost::program_options;
113
bool errmsg_printf (error::level_t, char const *format, ...);
115
bool errmsg_printf (error::level_t, char const *format, ...)
119
va_start(args, format);
120
rv= vfprintf(stderr, format, args);
122
fprintf(stderr, "\n");
128
#include "xtrabackup_api.h"
130
/* prototypes for static functions in original */
133
recv_find_max_checkpoint(
134
/*=====================*/
135
/* out: error code or DB_SUCCESS */
136
log_group_t** max_group, /* out: max group */
137
ulint* max_field); /* out: LOG_CHECKPOINT_1 or
144
int fd, /* in: file descriptor to alter */
145
const char* file_name, /* in: used in the diagnostic message */
146
const char* operation_name); /* in: used in the diagnostic message,
147
we call os_file_set_nocache()
148
immediately after opening or creating
149
a file, so this is either "open" or
155
#ifdef POSIX_FADV_NORMAL
156
#define USE_POSIX_FADVISE
159
/* ==start === definition at fil0fil.c === */
160
// ##################################################################
161
// NOTE: We should check the following definitions fit to the source.
162
// ##################################################################
165
/** File node of a tablespace or the log data space */
166
struct fil_node_struct {
167
fil_space_t* space; /*!< backpointer to the space where this node
169
char* name; /*!< path to the file */
170
ibool open; /*!< TRUE if file open */
171
os_file_t handle; /*!< OS handle to the file, if file open */
172
ibool is_raw_disk;/*!< TRUE if the 'file' is actually a raw
173
device or a raw disk partition */
174
ulint size; /*!< size of the file in database pages, 0 if
175
not known yet; the possible last incomplete
176
megabyte may be ignored if space == 0 */
178
/*!< count of pending i/o's on this file;
179
closing of the file is not allowed if
181
ulint n_pending_flushes;
182
/*!< count of pending flushes on this file;
183
closing of the file is not allowed if
185
ib_int64_t modification_counter;/*!< when we write to the file we
186
increment this by one */
187
ib_int64_t flush_counter;/*!< up to what
188
modification_counter value we have
189
flushed the modifications to disk */
190
UT_LIST_NODE_T(fil_node_t) chain;
191
/*!< link field for the file chain */
192
UT_LIST_NODE_T(fil_node_t) LRU;
193
/*!< link field for the LRU list */
194
ulint magic_n;/*!< FIL_NODE_MAGIC_N */
197
struct fil_space_struct {
198
char* name; /*!< space name = the path to the first file in
200
ulint id; /*!< space id */
201
ib_int64_t tablespace_version;
202
/*!< in DISCARD/IMPORT this timestamp
203
is used to check if we should ignore
204
an insert buffer merge request for a
205
page because it actually was for the
206
previous incarnation of the space */
207
ibool mark; /*!< this is set to TRUE at database startup if
208
the space corresponds to a table in the InnoDB
209
data dictionary; so we can print a warning of
210
orphaned tablespaces */
211
ibool stop_ios;/*!< TRUE if we want to rename the
212
.ibd file of tablespace and want to
213
stop temporarily posting of new i/o
214
requests on the file */
215
ibool stop_ibuf_merges;
216
/*!< we set this TRUE when we start
217
deleting a single-table tablespace */
218
ibool is_being_deleted;
219
/*!< this is set to TRUE when we start
220
deleting a single-table tablespace and its
221
file; when this flag is set no further i/o
222
or flush requests can be placed on this space,
223
though there may be such requests still being
224
processed on this space */
225
ulint purpose;/*!< FIL_TABLESPACE, FIL_LOG, or
227
UT_LIST_BASE_NODE_T(fil_node_t) chain;
228
/*!< base node for the file chain */
229
ulint size; /*!< space size in pages; 0 if a single-table
230
tablespace whose size we do not know yet;
231
last incomplete megabytes in data files may be
232
ignored if space == 0 */
233
ulint flags; /*!< compressed page size and file format, or 0 */
234
ulint n_reserved_extents;
235
/*!< number of reserved free extents for
236
ongoing operations like B-tree page split */
237
ulint n_pending_flushes; /*!< this is positive when flushing
238
the tablespace to disk; dropping of the
239
tablespace is forbidden if this is positive */
240
ulint n_pending_ibuf_merges;/*!< this is positive
241
when merging insert buffer entries to
242
a page so that we may need to access
243
the ibuf bitmap page in the
244
tablespade: dropping of the tablespace
245
is forbidden if this is positive */
246
hash_node_t hash; /*!< hash chain node */
247
hash_node_t name_hash;/*!< hash chain the name_hash table */
248
#ifndef UNIV_HOTBACKUP
249
rw_lock_t latch; /*!< latch protecting the file space storage
251
#endif /* !UNIV_HOTBACKUP */
252
UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
253
/*!< list of spaces with at least one unflushed
254
file we have written to */
255
ibool is_in_unflushed_spaces; /*!< TRUE if this space is
256
currently in unflushed_spaces */
260
UT_LIST_NODE_T(fil_space_t) space_list;
261
/*!< list of all spaces */
262
ulint magic_n;/*!< FIL_SPACE_MAGIC_N */
265
typedef struct fil_system_struct fil_system_t;
267
struct fil_system_struct {
268
#ifndef UNIV_HOTBACKUP
269
mutex_t mutex; /*!< The mutex protecting the cache */
271
mutex_t file_extend_mutex;
273
#endif /* !UNIV_HOTBACKUP */
274
hash_table_t* spaces; /*!< The hash table of spaces in the
275
system; they are hashed on the space
277
hash_table_t* name_hash; /*!< hash table based on the space
279
UT_LIST_BASE_NODE_T(fil_node_t) LRU;
280
/*!< base node for the LRU list of the
281
most recently used open files with no
282
pending i/o's; if we start an i/o on
283
the file, we first remove it from this
284
list, and return it to the start of
285
the list when the i/o ends;
286
log files and the system tablespace are
287
not put to this list: they are opened
288
after the startup, and kept open until
290
UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
291
/*!< base node for the list of those
292
tablespaces whose files contain
293
unflushed writes; those spaces have
294
at least one file node where
295
modification_counter > flush_counter */
296
ulint n_open; /*!< number of files currently open */
297
ulint max_n_open; /*!< n_open is not allowed to exceed
299
ib_int64_t modification_counter;/*!< when we write to a file we
300
increment this by one */
301
ulint max_assigned_id;/*!< maximum space id in the existing
302
tables, or assigned during the time
303
mysqld has been up; at an InnoDB
304
startup we scan the data dictionary
305
and set here the maximum of the
306
space id's of the tables there */
307
ib_int64_t tablespace_version;
308
/*!< a counter which is incremented for
309
every space object memory creation;
310
every space mem object gets a
311
'timestamp' from this; in DISCARD/
312
IMPORT this is used to check if we
313
should ignore an insert buffer merge
315
UT_LIST_BASE_NODE_T(fil_space_t) space_list;
316
/*!< list of all file spaces */
323
extern fil_system_t* fil_system;
325
/* ==end=== definition at fil0fil.c === */
328
bool innodb_inited= 0;
330
/* === xtrabackup specific options === */
331
char xtrabackup_real_target_dir[FN_REFLEN] = "./xtrabackup_backupfiles/";
332
const char *xtrabackup_target_dir= xtrabackup_real_target_dir;
333
bool xtrabackup_backup = false;
334
bool xtrabackup_stats = false;
335
bool xtrabackup_prepare = false;
336
bool xtrabackup_print_param = false;
338
bool xtrabackup_export = false;
339
bool xtrabackup_apply_log_only = false;
341
bool xtrabackup_suspend_at_end = false;
342
uint64_t xtrabackup_use_memory = 100*1024*1024L;
343
bool xtrabackup_create_ib_logfile = false;
345
long xtrabackup_throttle = 0; /* 0:unlimited */
347
os_event_t wait_throttle = NULL;
349
bool xtrabackup_stream = false;
350
const char *xtrabackup_incremental = NULL;
351
LSN64 incremental_lsn;
352
LSN64 incremental_to_lsn;
353
LSN64 incremental_last_lsn;
354
byte* incremental_buffer = NULL;
355
byte* incremental_buffer_base = NULL;
357
const char *xtrabackup_incremental_basedir = NULL; /* for --backup */
358
const char *xtrabackup_extra_lsndir = NULL; /* for --backup with --extra-lsndir */
359
char *xtrabackup_incremental_dir = NULL; /* for --prepare */
361
char *xtrabackup_tables = NULL;
362
int tables_regex_num;
363
regex_t *tables_regex;
364
regmatch_t tables_regmatch[1];
366
const char *xtrabackup_tables_file = NULL;
367
hash_table_t* tables_hash;
369
struct xtrabackup_tables_struct{
371
hash_node_t name_hash;
373
typedef struct xtrabackup_tables_struct xtrabackup_tables_t;
376
static ulint thread_nr[SRV_MAX_N_IO_THREADS + 6 + 64];
377
static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6 + 64];
379
static ulint thread_nr[SRV_MAX_N_IO_THREADS + 6];
380
static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6];
383
LSN64 checkpoint_lsn_start;
384
LSN64 checkpoint_no_start;
385
LSN64 log_copy_scanned_lsn;
386
IB_INT64 log_copy_offset = 0;
387
ibool log_copying = TRUE;
388
ibool log_copying_running = FALSE;
389
ibool log_copying_succeed = FALSE;
391
ibool xtrabackup_logfile_is_renamed = FALSE;
395
/* === metadata of backup === */
396
#define XTRABACKUP_METADATA_FILENAME "xtrabackup_checkpoints"
397
char metadata_type[30] = ""; /*[full-backuped|full-prepared|incremental]*/
399
ib_uint64_t metadata_from_lsn = 0;
400
ib_uint64_t metadata_to_lsn = 0;
401
ib_uint64_t metadata_last_lsn = 0;
403
#define XB_DELTA_INFO_SUFFIX ".meta"
405
/* === sharing with thread === */
406
os_file_t dst_log = -1;
407
char dst_log_path[FN_REFLEN];
409
/* === some variables from mysqld === */
410
char mysql_real_data_home[FN_REFLEN] = "./";
411
char *mysql_data_home= mysql_real_data_home;
412
std::string mysql_data_home_arg;
413
static char mysql_data_home_buff[2];
415
const char *opt_mysql_tmpdir = NULL;
417
/* === static parameters in ha_innodb.cc */
419
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
420
#define HA_INNOBASE_RANGE_COUNT 100
422
ulong innobase_large_page_size = 0;
424
/* The default values for the following, type long or longlong, start-up
425
parameters are declared in mysqld.cc: */
427
long innobase_additional_mem_pool_size = 1*1024*1024L;
428
long innobase_buffer_pool_awe_mem_mb = 0;
429
long innobase_file_io_threads = 4;
430
long innobase_read_io_threads = 4;
431
long innobase_write_io_threads = 4;
432
long innobase_force_recovery = 0;
433
long innobase_lock_wait_timeout = 50;
434
long innobase_log_buffer_size = 1024*1024L;
435
long innobase_log_files_in_group = 2;
436
long innobase_log_files_in_group_backup;
437
long innobase_mirrored_log_groups = 1;
438
long innobase_open_files = 300L;
440
long innobase_page_size = (1 << 14); /* 16KB */
441
static ulong innobase_log_block_size = 512;
442
bool innobase_fast_checksum = false;
443
bool innobase_extra_undoslots = false;
444
char* innobase_doublewrite_file = NULL;
446
uint64_t innobase_buffer_pool_size = 8*1024*1024L;
448
typedef constrained_check<int64_t, INT64_MAX, 1024*1024, 1024*1024> log_file_constraint;
449
static log_file_constraint innobase_log_file_size;
451
uint64_t innobase_log_file_size_backup;
453
/* The default values for the following char* start-up parameters
454
are determined in innobase_init below: */
456
char* innobase_data_home_dir = NULL;
457
const char* innobase_data_file_path = NULL;
458
char* innobase_log_group_home_dir = NULL;
459
char* innobase_log_group_home_dir_backup = NULL;
460
char* innobase_log_arch_dir = NULL;/* unused */
461
/* The following has a misleading name: starting from 4.0.5, this also
463
char* innobase_unix_file_flush_method = NULL;
465
/* Below we have boolean-valued start-up parameters, and their default
468
ulong innobase_fast_shutdown = 1;
469
bool innobase_log_archive = FALSE;/* unused */
470
bool innobase_use_doublewrite = TRUE;
471
bool innobase_use_checksums = TRUE;
472
bool innobase_use_large_pages = FALSE;
473
bool innobase_file_per_table = FALSE;
474
bool innobase_locks_unsafe_for_binlog = FALSE;
475
bool innobase_rollback_on_timeout = FALSE;
476
bool innobase_create_status_file = FALSE;
477
bool innobase_adaptive_hash_index = TRUE;
479
static char *internal_innobase_data_file_path = NULL;
481
/* The following counter is used to convey information to InnoDB
482
about server activity: in selects it is not sensible to call
483
srv_active_wake_master_thread after each fetch or search, we only do
484
it every INNOBASE_WAKE_INTERVAL'th step. */
486
#define INNOBASE_WAKE_INTERVAL 32
487
ulong innobase_active_counter = 0;
495
return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
500
innobase_rec_to_mysql(
503
const dict_index_t* ,
508
innobase_rec_to_mysql(
509
/*==================*/
510
Table* , /*!< in/out: MySQL table */
511
const rec_t* , /*!< in: record */
512
const dict_index_t* , /*!< in: index */
513
const ulint* ) /*!< in: rec_get_offsets(
516
fprintf(stderr, "ERROR: innobase_rec_to_mysql called\n");
522
innobase_rec_reset(Table*);
528
Table* ) /*!< in/out: MySQL table */
530
fprintf(stderr, "ERROR: innobase_rec_reset called\n");
536
thd_set_lock_wait_time(
537
/*===================*/
538
drizzled::Session* , /*!< in: thread handle (THD*) */
539
ulint ); /*!< in: time waited for the lock */
543
thd_set_lock_wait_time(
544
/*===================*/
545
drizzled::Session* , /*!< in: thread handle (THD*) */
546
ulint ) /*!< in: time waited for the lock */
553
/* ======== Datafiles iterator ======== */
555
fil_system_t *system;
564
datafiles_iter_new(fil_system_t *f_system)
566
datafiles_iter_t *it;
568
it = (datafiles_iter_t*) ut_malloc(sizeof(datafiles_iter_t));
569
it->mutex = OS_MUTEX_CREATE();
571
it->system = f_system;
581
datafiles_iter_next(datafiles_iter_t *it, ibool *space_changed)
583
os_mutex_enter(it->mutex);
585
*space_changed = FALSE;
587
if (it->node == NULL) {
592
it->node = UT_LIST_GET_NEXT(chain, it->node);
593
if (it->node != NULL)
597
it->space = (it->space == NULL) ?
598
UT_LIST_GET_FIRST(it->system->space_list) :
599
UT_LIST_GET_NEXT(space_list, it->space);
601
while (it->space != NULL &&
602
(it->space->purpose != FIL_TABLESPACE ||
603
UT_LIST_GET_LEN(it->space->chain) == 0))
604
it->space = UT_LIST_GET_NEXT(space_list, it->space);
605
if (it->space == NULL)
607
*space_changed = TRUE;
609
it->node = UT_LIST_GET_FIRST(it->space->chain);
612
os_mutex_exit(it->mutex);
619
datafiles_iter_free(datafiles_iter_t *it)
621
os_mutex_free(it->mutex);
625
/* ======== Date copying thread context ======== */
628
datafiles_iter_t *it;
631
os_mutex_t count_mutex;
633
} data_thread_ctxt_t;
635
static void print_version(void)
637
printf("%s Ver %s Rev %s for %s %s (%s)\n" ,my_progname,
638
XTRABACKUP_VERSION, XTRABACKUP_REVISION, "Drizzle7",
639
TARGET_OS, TARGET_CPU);
642
static void usage(void)
644
puts("Open source backup tool for InnoDB and XtraDB\n\
646
Copyright (C) 2009 Percona Inc.\n\
648
This program is free software; you can redistribute it and/or\n\
649
modify it under the terms of the GNU General Public License\n\
650
as published by the Free Software Foundation version 2\n\
653
This program is distributed in the hope that it will be useful,\n\
654
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
655
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
656
GNU General Public License for more details.\n\
658
You can download full text of the license on http://www.gnu.org/licenses/gpl-2.0.txt\n");
660
printf("Usage: [%s [--defaults-file=#] --backup | %s [--defaults-file=#] --prepare] [OPTIONS]\n",my_progname,my_progname);
661
// FIXME: print what variables we have
664
/* ================ Dummys =================== */
668
thd_is_replication_slave_thread(
669
/*============================*/
670
drizzled::Session* ) /*!< in: thread handle (Session*) */
672
fprintf(stderr, "xtrabackup: thd_is_replication_slave_thread() is called\n");
678
thd_has_edited_nontrans_tables(
679
/*===========================*/
680
drizzled::Session *) /*!< in: thread handle (Session*) */
682
fprintf(stderr, "xtrabackup: thd_has_edited_nontrans_tables() is called\n");
690
const drizzled::Session *) /*!< in: thread handle (Session*) */
692
fprintf(stderr, "xtrabackup: thd_is_select() is called\n");
698
innobase_mysql_print_thd(
703
fprintf(stderr, "xtrabackup: innobase_mysql_print_thd() is called\n");
707
innobase_get_cset_width(
717
cs = all_charsets[cset];
719
*mbminlen = cs->mbminlen;
720
*mbmaxlen = cs->mbmaxlen;
723
*mbminlen = *mbmaxlen = 0;
729
innobase_convert_from_table_id(
730
/*===========================*/
731
const void*, /*!< in: the 'from' character set */
732
char* , /*!< out: converted identifier */
733
const char* , /*!< in: identifier to convert */
734
ulint ) /*!< in: length of 'to', in bytes */
736
fprintf(stderr, "xtrabackup: innobase_convert_from_table_id() is called\n");
741
innobase_convert_from_id(
742
/*=====================*/
743
const void*, /*!< in: the 'from' character set */
744
char* , /*!< out: converted identifier */
745
const char* , /*!< in: identifier to convert */
746
ulint ) /*!< in: length of 'to', in bytes */
748
fprintf(stderr, "xtrabackup: innobase_convert_from_id() is called\n");
756
return(my_strcasecmp(&my_charset_utf8_general_ci, a, b));
763
my_casedn_str(&my_charset_utf8_general_ci, a);
770
drizzled::Session *, /*!< in: MySQL thread handle */
771
size_t* ) /*!< out: length of the SQL statement */
773
fprintf(stderr, "xtrabackup: innobase_get_stmt() is called\n");
778
innobase_mysql_tmpfile(void)
780
char filename[FN_REFLEN];
782
int fd = internal::create_temp_file(filename, opt_mysql_tmpdir,
785
O_BINARY | O_TRUNC | O_SEQUENTIAL |
786
O_TEMPORARY | O_SHORT_LIVED |
788
O_CREAT | O_EXCL | O_RDWR);
791
/* On Windows, open files cannot be removed, but files can be
792
created with the O_TEMPORARY flag to the same effect
793
("delete on close"). */
795
#endif /* !__WIN__ */
796
/* Copy the file descriptor, so that the additional resources
797
allocated by create_temp_file() can be freed by invoking
800
Because the file descriptor returned by this function
801
will be passed to fdopen(), it will be closed by invoking
802
fclose(), which in turn will invoke close() instead of
806
fprintf(stderr, "xtrabackup: Got error %d on dup\n",fd2);
814
innobase_invalidate_query_cache(
822
/*****************************************************************//**
823
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
824
and quote it if needed.
825
@return pointer to the end of buf */
828
innobase_convert_identifier(
829
/*========================*/
830
char* buf, /*!< out: buffer for converted identifier */
831
ulint buflen, /*!< in: length of buf, in bytes */
832
const char* id, /*!< in: identifier to convert */
833
ulint idlen, /*!< in: length of id, in bytes */
834
void* , /*!< in: MySQL connection thread, or NULL */
835
ibool )/*!< in: TRUE=id is a table or database name;
836
FALSE=id is an UTF-8 string */
841
/* See if the identifier needs to be quoted. */
845
if (UNIV_UNLIKELY(idlen > buflen)) {
848
memcpy(buf, s, idlen);
852
/* Quote the identifier. */
860
for (; idlen; idlen--) {
862
if (UNIV_UNLIKELY(c == q)) {
863
if (UNIV_UNLIKELY(buflen < 3)) {
871
if (UNIV_UNLIKELY(buflen < 2)) {
884
/*****************************************************************//**
885
Convert a table or index name to the MySQL system_charset_info (UTF-8)
886
and quote it if needed.
887
@return pointer to the end of buf */
890
innobase_convert_name(
891
/*==================*/
892
char* buf, /*!< out: buffer for converted identifier */
893
ulint buflen, /*!< in: length of buf, in bytes */
894
const char* id, /*!< in: identifier to convert */
895
ulint idlen, /*!< in: length of id, in bytes */
896
drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
897
ibool table_id)/*!< in: TRUE=id is a table or database name;
898
FALSE=id is an index name */
901
const char* bufend = buf + buflen;
904
const char* slash = (const char*) memchr(id, '/', idlen);
910
/* Print the database name and table name separately. */
911
s = innobase_convert_identifier(s, bufend - s, id, slash - id,
913
if (UNIV_LIKELY(s < bufend)) {
915
s = innobase_convert_identifier(s, bufend - s,
920
} else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
921
/* Temporary index name (smart ALTER TABLE) */
922
const char temp_index_suffix[]= "--temporary--";
924
s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
926
if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
927
memcpy(s, temp_index_suffix,
928
sizeof temp_index_suffix - 1);
929
s += sizeof temp_index_suffix - 1;
933
s = innobase_convert_identifier(buf, buflen, id, idlen,
945
/* There are no mysql_thd */
952
int mysql_type, /*!< in: MySQL type */
953
uint charset_number, /*!< in: number of the charset */
954
const unsigned char* a, /*!< in: data field */
955
unsigned int a_length, /*!< in: data field length,
957
const unsigned char* b, /* in: data field */
958
unsigned int b_length); /* in: data field length,
964
/* out: 1, 0, -1, if a is greater, equal, less than b, respectively */
965
int mysql_type, /* in: MySQL type */
966
uint charset_number, /* in: number of the charset */
967
const unsigned char* a, /* in: data field */
968
unsigned int a_length, /* in: data field length, not UNIV_SQL_NULL */
969
const unsigned char* b, /* in: data field */
970
unsigned int b_length) /* in: data field length, not UNIV_SQL_NULL */
972
const CHARSET_INFO* charset;
973
enum_field_types mysql_tp;
976
assert(a_length != UNIV_SQL_NULL);
977
assert(b_length != UNIV_SQL_NULL);
979
mysql_tp = (enum_field_types) mysql_type;
983
case DRIZZLE_TYPE_BLOB:
984
case DRIZZLE_TYPE_VARCHAR:
985
/* Use the charset number to pick the right charset struct for
986
the comparison. Since the MySQL function get_charset may be
987
slow before Bar removes the mutex operation there, we first
988
look at 2 common charsets directly. */
990
if (charset_number == default_charset_info->number) {
991
charset = default_charset_info;
993
charset = get_charset(charset_number);
995
if (charset == NULL) {
996
fprintf(stderr, "xtrabackup needs charset %lu for doing "
997
"a comparison, but MySQL cannot "
998
"find that charset.",
999
(ulong) charset_number);
1004
/* Starting from 4.1.3, we use strnncollsp() in comparisons of
1005
non-latin1_swedish_ci strings. NOTE that the collation order
1006
changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
1007
having indexes on such data need to rebuild their tables! */
1009
ret = charset->coll->strnncollsp(charset,
1014
} else if (ret > 0) {
1027
innobase_get_at_most_n_mbchars(
1033
ulint char_length; /* character length in bytes */
1034
ulint n_chars; /* number of characters in prefix */
1035
const CHARSET_INFO* charset; /* charset used in the field */
1037
charset = get_charset((uint) charset_id);
1040
ut_ad(charset->mbmaxlen);
1042
/* Calculate how many characters at most the prefix index contains */
1044
n_chars = prefix_len / charset->mbmaxlen;
1046
/* If the charset is multi-byte, then we must find the length of the
1047
first at most n chars in the string. If the string contains less
1048
characters than n, then we return the length to the end of the last
1051
if (charset->mbmaxlen > 1) {
1052
/* my_charpos() returns the byte length of the first n_chars
1053
characters, or a value bigger than the length of str, if
1054
there were not enough full characters in str.
1056
Why does the code below work:
1057
Suppose that we are looking for n UTF-8 characters.
1059
1) If the string is long enough, then the prefix contains at
1060
least n complete UTF-8 characters + maybe some extra
1061
characters + an incomplete UTF-8 character. No problem in
1062
this case. The function returns the pointer to the
1063
end of the nth character.
1065
2) If the string is not long enough, then the string contains
1066
the complete value of a column, that is, only complete UTF-8
1067
characters, and we can store in the column prefix index the
1070
char_length = my_charpos(charset, str,
1071
str + data_len, (int) n_chars);
1072
if (char_length > data_len) {
1073
char_length = data_len;
1076
if (data_len < prefix_len) {
1077
char_length = data_len;
1079
char_length = prefix_len;
1083
return(char_length);
1088
innobase_raw_format(
1089
/*================*/
1090
const char* , /*!< in: raw data */
1091
ulint , /*!< in: raw data length
1093
ulint , /*!< in: charset collation */
1094
char* , /*!< out: output buffer */
1095
ulint ) /*!< in: output buffer size
1098
fprintf(stderr, "xtrabackup: innobase_raw_format() is called\n");
1104
thd_lock_wait_timeout(
1105
/*==================*/
1106
drizzled::Session*) /*!< in: thread handle (Session*), or NULL to query
1107
the global innodb_lock_wait_timeout */
1109
return(innobase_lock_wait_timeout);
1116
drizzled::Session* ) /*!< in: thread handle (Session*), or NULL to query
1117
the global innodb_supports_xa */
1125
trx_t*) /*!< in: transaction */
1138
innobase_get_slow_log()
1144
/***********************************************************************
1145
Computes bit shift for a given value. If the argument is not a power
1149
get_bit_shift(ulint value)
1156
for (shift = 0; !(value & 1UL); shift++) {
1159
return (value >> 1) ? 0 : shift;
1163
innodb_init_param(void)
1166
static char current_dir[3]; /* Set if using current lib */
1170
/* dummy for initialize all_charsets[] */
1171
get_charset_name(0);
1175
srv_page_size_shift = 0;
1177
if (innobase_page_size != (1 << 14)) {
1178
int n_shift = get_bit_shift(innobase_page_size);
1180
if (n_shift >= 12 && n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX) {
1182
"InnoDB: Warning: innodb_page_size has been "
1183
"changed from default value 16384.\n");
1184
srv_page_size_shift = n_shift;
1185
srv_page_size = 1 << n_shift;
1187
"InnoDB: The universal page size of the "
1188
"database is set to %lu.\n", srv_page_size);
1190
fprintf(stderr, "InnoDB: Error: invalid value of "
1191
"innobase_page_size: %lu", innobase_page_size);
1195
srv_page_size_shift = 14;
1196
srv_page_size = (1 << srv_page_size_shift);
1199
srv_log_block_size = 0;
1200
if (innobase_log_block_size != 512) {
1201
uint n_shift = get_bit_shift(innobase_log_block_size);;
1204
"InnoDB: Warning: innodb_log_block_size has "
1205
"been changed from its default value. "
1206
"(###EXPERIMENTAL### operation)\n");
1208
srv_log_block_size = (1 << n_shift);
1210
"InnoDB: The log block size is set to %lu.\n",
1211
srv_log_block_size);
1214
srv_log_block_size = 512;
1217
if (!srv_log_block_size) {
1219
"InnoDB: Error: %lu is not valid value for "
1220
"innodb_log_block_size.\n", innobase_log_block_size);
1224
srv_fast_checksum = (ibool) innobase_fast_checksum;
1227
/* Check that values don't overflow on 32-bit systems. */
1228
if (sizeof(ulint) == 4) {
1229
if (xtrabackup_use_memory > UINT32_MAX) {
1231
"xtrabackup: use-memory can't be over 4GB"
1232
" on 32-bit systems\n");
1235
if (innobase_buffer_pool_size > UINT32_MAX) {
1237
"xtrabackup: innobase_buffer_pool_size can't be over 4GB"
1238
" on 32-bit systems\n");
1243
if (innobase_log_file_size > UINT32_MAX) {
1245
"xtrabackup: innobase_log_file_size can't be over 4GB"
1246
" on 32-bit systemsi\n");
1252
os_innodb_umask = (ulint)0664;
1254
/* First calculate the default path for innodb_data_home_dir etc.,
1255
in case the user has not given any value.
1257
Note that when using the embedded server, the datadirectory is not
1258
necessarily the current directory of this program. */
1260
/* It's better to use current lib, to keep paths short */
1261
current_dir[0] = FN_CURLIB;
1262
current_dir[1] = FN_LIBCHAR;
1264
default_path = current_dir;
1268
/* Set InnoDB initialization parameters according to the values
1269
read from MySQL .cnf file */
1271
if (xtrabackup_backup || xtrabackup_stats) {
1272
fprintf(stderr, "xtrabackup: Target instance is assumed as followings.\n");
1274
fprintf(stderr, "xtrabackup: Temporary instance for recovery is set as followings.\n");
1277
/*--------------- Data files -------------------------*/
1279
/* The default dir for data files is the datadir of MySQL */
1281
srv_data_home = ((xtrabackup_backup || xtrabackup_stats) && innobase_data_home_dir
1282
? innobase_data_home_dir : default_path);
1283
fprintf(stderr, "xtrabackup: innodb_data_home_dir = %s\n", srv_data_home);
1285
/* Set default InnoDB data file size to 10 MB and let it be
1286
auto-extending. Thus users can use InnoDB in >= 4.0 without having
1287
to specify any startup options. */
1289
if (!innobase_data_file_path) {
1290
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1292
fprintf(stderr, "xtrabackup: innodb_data_file_path = %s\n",
1293
innobase_data_file_path);
1295
/* Since InnoDB edits the argument in the next call, we make another
1298
internal_innobase_data_file_path = strdup(innobase_data_file_path);
1300
ret = (bool) srv_parse_data_file_paths_and_sizes(
1301
internal_innobase_data_file_path);
1304
"xtrabackup: syntax error in innodb_data_file_path\n");
1306
free(internal_innobase_data_file_path);
1310
if (xtrabackup_prepare) {
1311
/* "--prepare" needs filenames only */
1314
for (i=0; i < srv_n_data_files; i++) {
1317
p = srv_data_file_names[i];
1318
while ((p = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
1321
srv_data_file_names[i] = p;
1327
srv_doublewrite_file = innobase_doublewrite_file;
1329
srv_extra_undoslots = (ibool) innobase_extra_undoslots;
1333
/* -------------- Log files ---------------------------*/
1335
/* The default dir for log files is the datadir of MySQL */
1337
if (!((xtrabackup_backup || xtrabackup_stats) && innobase_log_group_home_dir)) {
1338
innobase_log_group_home_dir = default_path;
1340
if (xtrabackup_prepare && xtrabackup_incremental_dir) {
1341
innobase_log_group_home_dir = xtrabackup_incremental_dir;
1343
fprintf(stderr, "xtrabackup: innodb_log_group_home_dir = %s\n",
1344
innobase_log_group_home_dir);
1346
#ifdef UNIV_LOG_ARCHIVE
1347
/* Since innodb_log_arch_dir has no relevance under MySQL,
1348
starting from 4.0.6 we always set it the same as
1349
innodb_log_group_home_dir: */
1351
innobase_log_arch_dir = innobase_log_group_home_dir;
1353
srv_arch_dir = innobase_log_arch_dir;
1354
#endif /* UNIG_LOG_ARCHIVE */
1357
srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
1359
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1360
fprintf(stderr, "xtrabackup: syntax error in innodb_log_group_home_dir, or a "
1361
"wrong number of mirrored log groups\n");
1363
goto mem_free_and_error;
1366
srv_adaptive_flushing = FALSE;
1367
srv_use_sys_malloc = TRUE;
1368
srv_file_format = 1; /* Barracuda */
1369
srv_max_file_format_at_startup = DICT_TF_FORMAT_51; /* on */
1371
/* --------------------------------------------------*/
1373
srv_file_flush_method_str = innobase_unix_file_flush_method;
1375
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
1376
srv_n_log_files = (ulint) innobase_log_files_in_group;
1377
srv_log_file_size = (ulint) innobase_log_file_size;
1378
fprintf(stderr, "xtrabackup: innodb_log_files_in_group = %ld\n",
1380
fprintf(stderr, "xtrabackup: innodb_log_file_size = %ld\n",
1383
#ifdef UNIV_LOG_ARCHIVE
1384
srv_log_archive_on = (ulint) innobase_log_archive;
1385
#endif /* UNIV_LOG_ARCHIVE */
1386
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
1388
/* We set srv_pool_size here in units of 1 kB. InnoDB internally
1389
changes the value so that it becomes the number of database pages. */
1391
//srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
1392
srv_buf_pool_size = (ulint) xtrabackup_use_memory;
1394
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
1396
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
1398
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
1399
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
1401
srv_force_recovery = (ulint) innobase_force_recovery;
1403
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
1404
srv_use_checksums = (ibool) innobase_use_checksums;
1406
btr_search_enabled = innobase_adaptive_hash_index ? true : false;
1408
os_use_large_pages = (ibool) innobase_use_large_pages;
1409
os_large_page_size = (ulint) innobase_large_page_size;
1411
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
1413
srv_file_per_table = innobase_file_per_table ? true : false;
1415
srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
1417
srv_max_n_open_files = (ulint) innobase_open_files;
1418
srv_innodb_status = (ibool) innobase_create_status_file;
1420
srv_print_verbose_log = 1;
1422
/* Store the default charset-collation number of this MySQL
1425
/* We cannot treat characterset here for now!! */
1426
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
1428
ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
1430
//innobase_commit_concurrency_init_default();
1432
/* Since we in this module access directly the fields of a trx
1433
struct, and due to different headers and flags it might happen that
1434
mutex_t has a different size in this module and in InnoDB
1435
modules, we check at run time that the size is the same in
1436
these compilation modules. */
1439
/* On 5.5 srv_use_native_aio is TRUE by default. It is later reset
1440
if it is not supported by the platform in
1441
innobase_start_or_create_for_mysql(). As we don't call it in xtrabackup,
1442
we have to duplicate checks from that function here. */
1445
switch (os_get_os_version()) {
1449
/* On Win 95, 98, ME, Win32 subsystem for Windows 3.1,
1450
and NT use simulated aio. In NT Windows provides async i/o,
1451
but when run in conjunction with InnoDB Hot Backup, it seemed
1452
to corrupt the data files. */
1454
srv_use_native_aio = FALSE;
1459
/* On 2000 and XP, async IO is available. */
1460
srv_use_native_aio = TRUE;
1464
/* Vista and later have both async IO and condition variables */
1465
srv_use_native_aio = TRUE;
1466
srv_use_native_conditions = TRUE;
1470
#elif defined(LINUX_NATIVE_AIO)
1472
if (srv_use_native_aio) {
1473
ut_print_timestamp(stderr);
1475
" InnoDB: Using Linux native AIO\n");
1478
/* Currently native AIO is supported only on windows and linux
1479
and that also when the support is compiled in. In all other
1480
cases, we ignore the setting of innodb_use_native_aio. */
1481
srv_use_native_aio = FALSE;
1488
fprintf(stderr, "xtrabackup: innodb_init_param(): Error occured.\n");
1497
err = innobase_start_or_create_for_mysql();
1499
if (err != DB_SUCCESS) {
1500
free(internal_innobase_data_file_path);
1504
/* They may not be needed for now */
1505
// (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
1506
// (hash_get_key) innobase_get_key, 0, 0);
1507
// pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
1508
// pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
1509
// pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
1510
// pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
1511
// pthread_cond_init(&commit_cond, NULL);
1518
fprintf(stderr, "xtrabackup: innodb_init(): Error occured.\n");
1525
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
1528
fprintf(stderr, "xtrabackup: starting shutdown with innodb_fast_shutdown = %lu\n",
1531
if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
1534
free(internal_innobase_data_file_path);
1536
/* They may not be needed for now */
1537
// hash_free(&innobase_open_tables);
1538
// pthread_mutex_destroy(&innobase_share_mutex);
1539
// pthread_mutex_destroy(&prepare_commit_mutex);
1540
// pthread_mutex_destroy(&commit_threads_m);
1541
// pthread_mutex_destroy(&commit_cond_m);
1542
// pthread_cond_destroy(&commit_cond);
1547
fprintf(stderr, "xtrabackup: innodb_end(): Error occured.\n");
1551
/* ================= common ================= */
1553
xtrabackup_read_metadata(char *filename)
1557
fp = fopen(filename,"r");
1559
fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filename);
1563
if (fscanf(fp, "backup_type = %29s\n", metadata_type)
1566
if (fscanf(fp, "from_lsn = %"PRIu64"\n", &metadata_from_lsn)
1569
if (fscanf(fp, "to_lsn = %"PRIu64"\n", &metadata_to_lsn)
1572
if (fscanf(fp, "last_lsn = %"PRIu64"\n", &metadata_last_lsn)
1574
metadata_last_lsn = 0;
1583
xtrabackup_write_metadata(char *filename)
1587
fp = fopen(filename,"w");
1589
fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filename);
1593
if (fprintf(fp, "backup_type = %s\n", metadata_type)
1596
if (fprintf(fp, "from_lsn = %"PRIu64"\n", metadata_from_lsn)
1599
if (fprintf(fp, "to_lsn = %"PRIu64"\n", metadata_to_lsn)
1602
if (fprintf(fp, "last_lsn = %"PRIu64"\n", metadata_last_lsn)
1611
/***********************************************************************
1612
Read meta info for an incremental delta.
1613
@return TRUE on success, FALSE on failure. */
1615
xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info)
1619
memset(info, 0, sizeof(xb_delta_info_t));
1621
fp = fopen(filepath, "r");
1623
/* Meta files for incremental deltas are optional */
1627
if (fscanf(fp, "page_size = %lu\n", &info->page_size) != 1)
1635
/***********************************************************************
1636
Write meta info for an incremental delta.
1637
@return TRUE on success, FALSE on failure. */
1639
xb_write_delta_metadata(const char *filepath, const xb_delta_info_t *info)
1643
fp = fopen(filepath, "w");
1645
fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filepath);
1649
if (fprintf(fp, "page_size = %lu\n", info->page_size) < 0)
1657
/* ================= backup ================= */
1659
xtrabackup_io_throttling(void)
1661
if (xtrabackup_throttle && (io_ticket--) < 0) {
1662
os_event_reset(wait_throttle);
1663
os_event_wait(wait_throttle);
1668
/* TODO: We may tune the behavior (e.g. by fil_aio)*/
1669
#define COPY_CHUNK 64
1672
xtrabackup_copy_datafile(fil_node_t* node, uint thread_n)
1674
os_file_t src_file = -1;
1675
os_file_t dst_file = -1;
1676
char dst_path[FN_REFLEN];
1677
char meta_path[FN_REFLEN];
1684
ulint page_in_buffer= 0;
1685
ulint incremental_buffers = 0;
1687
ulint page_size_shift;
1689
xb_delta_info_t info;
1694
if (xtrabackup_tables && (!trx_sys_sys_space(node->space->id)))
1696
if (xtrabackup_tables && (node->space->id != 0))
1698
{ /* must backup id==0 */
1700
int p_len, regres= 0;
1707
while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
1712
p_len = strlen(p) - strlen(".ibd");
1715
/* unknown situation: skip filtering */
1719
/* TODO: Fix this lazy implementation... */
1724
for (i = 0; i < tables_regex_num; i++) {
1725
regres = regexec(&tables_regex[i], prev, 1, tables_regmatch, 0);
1726
if (regres != REG_NOMATCH)
1731
*(p - 1) = SRV_PATH_SEPARATOR;
1733
if ( regres == REG_NOMATCH ) {
1734
printf("[%02u] Copying %s is skipped.\n",
1735
thread_n, node->name);
1741
if (xtrabackup_tables_file && (!trx_sys_sys_space(node->space->id)))
1743
if (xtrabackup_tables_file && (node->space->id != 0))
1745
{ /* must backup id==0 */
1746
xtrabackup_tables_t* table;
1754
while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
1759
p_len = strlen(p) - strlen(".ibd");
1762
/* unknown situation: skip filtering */
1766
/* TODO: Fix this lazy implementation... */
1770
HASH_SEARCH(name_hash, tables_hash, ut_fold_string(prev),
1771
xtrabackup_tables_t*,
1774
!strcmp(table->name, prev));
1779
printf("[%02u] Copying %s is skipped.\n",
1780
thread_n, node->name);
1786
zip_size = fil_space_get_zip_size(node->space->id);
1787
if (zip_size == ULINT_UNDEFINED) {
1788
fprintf(stderr, "[%02u] xtrabackup: Warning: "
1789
"Failed to determine page size for %s.\n"
1790
"[%02u] xtrabackup: Warning: We assume the table was "
1791
"dropped during xtrabackup execution and ignore the "
1792
"file.\n", thread_n, node->name, thread_n);
1794
} else if (zip_size) {
1795
page_size = zip_size;
1796
page_size_shift = get_bit_shift(page_size);
1797
fprintf(stderr, "[%02u] %s is compressed with page size = "
1798
"%lu bytes\n", thread_n, node->name, page_size);
1799
if (page_size_shift < 10 || page_size_shift > 14) {
1800
fprintf(stderr, "[%02u] xtrabackup: Error: Invalid "
1801
"page size.\n", thread_n);
1805
page_size = UNIV_PAGE_SIZE;
1806
page_size_shift = UNIV_PAGE_SIZE_SHIFT;
1810
if (trx_sys_sys_space(node->space->id))
1812
if (node->space->id == 0)
1816
/* system datafile "/fullpath/datafilename.ibd" or "./datafilename.ibd" */
1818
while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
1822
sprintf(dst_path, "%s/%s", xtrabackup_target_dir, p);
1824
/* file per table style "./database/table.ibd" */
1825
sprintf(dst_path, "%s%s", xtrabackup_target_dir, strstr(node->name, SRV_PATH_SEPARATOR_STR));
1828
if (xtrabackup_incremental) {
1829
snprintf(meta_path, sizeof(meta_path),
1830
"%s%s", dst_path, XB_DELTA_INFO_SUFFIX);
1831
strcat(dst_path, ".delta");
1834
bzero(incremental_buffer, (page_size/4) * page_size);
1836
mach_write_to_4(incremental_buffer, 0x78747261UL);/*"xtra"*/
1839
info.page_size = page_size;
1844
src_file = os_file_create_simple_no_error_handling(
1845
0 /* dummy of innodb_file_data_key */,
1846
node->name, OS_FILE_OPEN,
1847
OS_FILE_READ_ONLY, &success);
1849
/* The following call prints an error message */
1850
os_file_get_last_error(TRUE);
1853
"[%02u] xtrabackup: Warning: cannot open %s\n"
1854
"[%02u] xtrabackup: Warning: We assume the "
1855
"table was dropped during xtrabackup execution "
1856
"and ignore the file.\n",
1857
thread_n, node->name, thread_n);
1861
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
1862
os_file_set_nocache(src_file, node->name, "OPEN");
1865
src_file = node->handle;
1868
#ifdef USE_POSIX_FADVISE
1869
posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
1870
posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
1874
/* os_file_create reads srv_unix_file_flush_method */
1875
dst_file = os_file_create(
1876
0 /* dummy of innodb_file_data_key */,
1877
dst_path, OS_FILE_CREATE,
1878
OS_FILE_NORMAL, OS_DATA_FILE, &success);
1880
/* The following call prints an error message */
1881
os_file_get_last_error(TRUE);
1883
fprintf(stderr,"[%02u] xtrabackup: error: "
1884
"cannot open %s\n", thread_n, dst_path);
1888
#ifdef USE_POSIX_FADVISE
1889
posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED);
1892
/* copy : TODO: tune later */
1893
printf("[%02u] Copying %s \n to %s\n", thread_n,
1894
node->name, dst_path);
1896
buf2 = (unsigned char*) ut_malloc(COPY_CHUNK * page_size + UNIV_PAGE_SIZE);
1897
page = (unsigned char*) ut_align(buf2, UNIV_PAGE_SIZE);
1899
success = os_file_read(src_file, page, 0, 0, UNIV_PAGE_SIZE);
1903
flush_lsn = MACH_READ_64(page + FIL_PAGE_FILE_FLUSH_LSN);
1904
/* check current flush lsn newer than checkpoint@start */
1905
// if (ut_dulint_cmp(backup_start_checkpoint, flush_lsn) >= 0) {
1909
file_size = os_file_get_size_as_iblonglong(src_file);
1911
for (offset = 0; offset < file_size; offset += COPY_CHUNK * page_size) {
1914
ulint retry_count = 10;
1916
if ((ulint)(file_size - offset) > COPY_CHUNK * page_size) {
1917
chunk = COPY_CHUNK * page_size;
1919
chunk = (ulint)(file_size - offset);
1923
xtrabackup_io_throttling();
1925
success = os_file_read(src_file, page,
1926
(ulint)(offset & 0xFFFFFFFFUL),
1927
(ulint)(offset >> 32), chunk);
1932
/* check corruption and retry */
1933
for (chunk_offset = 0; chunk_offset < chunk; chunk_offset += page_size) {
1934
if (buf_page_is_corrupted(page + chunk_offset, zip_size))
1938
trx_sys_sys_space(node->space->id)
1940
node->space->id == 0
1942
&& ((offset + (IB_INT64)chunk_offset) >> page_size_shift)
1944
&& ((offset + (IB_INT64)chunk_offset) >> page_size_shift)
1945
< FSP_EXTENT_SIZE * 3) {
1946
/* double write buffer may have old data in the end
1947
or it may contain the other format page like COMPRESSED.
1948
So, we can pass the check of double write buffer.*/
1949
ut_a(page_size == UNIV_PAGE_SIZE);
1950
fprintf(stderr, "[%02u] xtrabackup: "
1951
"Page %lu seems double write "
1952
"buffer. passing the check.\n",
1955
(IB_INT64)chunk_offset) >>
1959
if (retry_count == 0) {
1961
"[%02u] xtrabackup: "
1962
"Error: 10 retries "
1963
"resulted in fail. This"
1969
fprintf(stderr, "[%02u] xtrabackup: "
1970
"Database page corruption "
1971
"detected at page %lu. "
1975
(IB_INT64)chunk_offset)
1976
>> page_size_shift));
1982
if (xtrabackup_incremental) {
1983
for (chunk_offset = 0; chunk_offset < chunk; chunk_offset += page_size) {
1985
/* This condition may be OK for header, ibuf and fsp */
1986
if (ut_dulint_cmp(incremental_lsn,
1987
MACH_READ_64(page + chunk_offset + FIL_PAGE_LSN)) < 0) {
1988
/* ========================================= */
1989
IB_INT64 offset_on_page;
1991
if (page_in_buffer == page_size/4) {
1993
success = os_file_write(dst_path, dst_file, incremental_buffer,
1994
((incremental_buffers * (page_size/4))
1995
<< page_size_shift) & 0xFFFFFFFFUL,
1996
(incremental_buffers * (page_size/4))
1997
>> (32 - page_size_shift),
1998
page_in_buffer * page_size);
2003
incremental_buffers++;
2006
bzero(incremental_buffer, (page_size/4) * page_size);
2008
mach_write_to_4(incremental_buffer, 0x78747261UL);/*"xtra"*/
2012
offset_on_page = ((offset + (IB_INT64)chunk_offset) >> page_size_shift);
2013
ut_a(offset_on_page >> 32 == 0);
2015
mach_write_to_4(incremental_buffer + page_in_buffer * 4, (ulint)offset_on_page);
2016
memcpy(incremental_buffer + page_in_buffer * page_size,
2017
page + chunk_offset, page_size);
2020
/* ========================================= */
2024
success = os_file_write(dst_path, dst_file, page,
2025
(ulint)(offset & 0xFFFFFFFFUL),
2026
(ulint)(offset >> 32), chunk);
2034
if (xtrabackup_incremental) {
2036
if (page_in_buffer != page_size/4) {
2037
mach_write_to_4(incremental_buffer + page_in_buffer * 4, 0xFFFFFFFFUL);
2040
mach_write_to_4(incremental_buffer, 0x58545241UL);/*"XTRA"*/
2043
success = os_file_write(dst_path, dst_file, incremental_buffer,
2044
((incremental_buffers * (page_size/4))
2045
<< page_size_shift) & 0xFFFFFFFFUL,
2046
(incremental_buffers * (page_size/4))
2047
>> (32 - page_size_shift),
2048
page_in_buffer * page_size);
2052
if (!xb_write_delta_metadata(meta_path, &info)) {
2053
fprintf(stderr, "[%02u] xtrabackup: Error: "
2054
"failed to write meta info for %s\n",
2055
thread_n, dst_path);
2060
success = os_file_flush(dst_file);
2066
/* check size again */
2067
/* TODO: but is it needed ?? */
2068
// if (file_size < os_file_get_size_as_iblonglong(src_file)) {
2069
// offset -= COPY_CHUNK * page_size;
2070
// file_size = os_file_get_size_as_iblonglong(src_file);
2074
/* TODO: How should we treat double_write_buffer here? */
2075
/* (currently, don't care about. Because,
2076
the blocks is newer than the last checkpoint anyway.) */
2079
printf("[%02u] ...done\n", thread_n);
2081
os_file_close(src_file);
2083
os_file_close(dst_file);
2087
if (src_file != -1 && !node->open)
2088
os_file_close(src_file);
2090
os_file_close(dst_file);
2093
fprintf(stderr, "[%02u] xtrabackup: Error: "
2094
"xtrabackup_copy_datafile() failed.\n", thread_n);
2095
return(TRUE); /*ERROR*/
2098
if (src_file != -1 && !node->open)
2099
os_file_close(src_file);
2101
os_file_close(dst_file);
2104
fprintf(stderr, "[%02u] xtrabackup: Warning: skipping file %s.\n",
2105
thread_n, node->name);
2110
xtrabackup_copy_logfile(LSN64 from_lsn, bool is_last)
2112
/* definition from recv_recovery_from_checkpoint_start() */
2114
log_group_t* up_to_date_group;
2115
LSN64 old_scanned_lsn;
2116
LSN64 group_scanned_lsn;
2117
LSN64 contiguous_lsn;
2121
if (!xtrabackup_stream)
2122
ut_a(dst_log != -1);
2124
/* read from checkpoint_lsn_start to current */
2125
contiguous_lsn = ut_dulint_align_down(from_lsn,
2126
OS_FILE_LOG_BLOCK_SIZE);
2128
/* TODO: We must check the contiguous_lsn still exists in log file.. */
2130
group = UT_LIST_GET_FIRST(log_sys->log_groups);
2138
old_scanned_lsn = from_lsn;
2140
/* reference recv_group_scan_log_recs() */
2143
start_lsn = contiguous_lsn;
2146
end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE);
2148
xtrabackup_io_throttling();
2150
log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
2151
group, start_lsn, end_lsn);
2153
//printf("log read from (%lu %lu) to (%lu %lu)\n",
2154
// start_lsn.high, start_lsn.low, end_lsn.high, end_lsn.low);
2156
/* reference recv_scan_log_recs() */
2164
ulint scanned_checkpoint_no = 0;
2168
log_block = log_sys->buf;
2169
scanned_lsn = start_lsn;
2172
while (log_block < log_sys->buf + RECV_SCAN_SIZE && !finished) {
2174
no = log_block_get_hdr_no(log_block);
2176
if (no != log_block_convert_lsn_to_no(scanned_lsn)
2177
|| !log_block_checksum_is_ok_or_old_format(log_block)) {
2179
if (no > log_block_convert_lsn_to_no(scanned_lsn)
2180
&& log_block_checksum_is_ok_or_old_format(log_block)) {
2182
">> ###Warning###: The copying transaction log migh be overtaken already by the target.\n"
2183
">> : Waiting log block no %lu, but the bumber is already %lu.\n"
2184
">> : If the number equals %lu + n * %lu, it should be overtaken already.\n",
2185
(ulong) log_block_convert_lsn_to_no(scanned_lsn),
2187
(ulong) log_block_convert_lsn_to_no(scanned_lsn),
2188
(ulong) (log_block_convert_lsn_to_no(
2189
log_group_get_capacity(group)
2192
} else if (no == log_block_convert_lsn_to_no(scanned_lsn)
2193
&& !log_block_checksum_is_ok_or_old_format(
2196
"xtrabackup: Log block no %lu at lsn %"PRIu64" has\n"
2197
"xtrabackup: ok header, but checksum field contains %lu, should be %lu\n",
2200
(ulong) log_block_get_checksum(log_block),
2201
(ulong) log_block_calc_checksum(log_block));
2204
/* Garbage or an incompletely written log block */
2211
if (log_block_get_flush_bit(log_block)) {
2212
/* This block was a start of a log flush operation:
2213
we know that the previous flush operation must have
2214
been completed for all log groups before this block
2215
can have been flushed to any of the groups. Therefore,
2216
we know that log data is contiguous up to scanned_lsn
2217
in all non-corrupt log groups. */
2219
if (ut_dulint_cmp(scanned_lsn, contiguous_lsn) > 0) {
2220
contiguous_lsn = scanned_lsn;
2224
data_len = log_block_get_data_len(log_block);
2227
(scanned_checkpoint_no > 0)
2228
&& (log_block_get_checkpoint_no(log_block)
2229
< scanned_checkpoint_no)
2230
&& (scanned_checkpoint_no
2231
- log_block_get_checkpoint_no(log_block)
2234
/* Garbage from a log buffer flush which was made
2235
before the most recent database recovery */
2241
scanned_lsn = ut_dulint_add(scanned_lsn, data_len);
2242
scanned_checkpoint_no = log_block_get_checkpoint_no(log_block);
2244
if (data_len < OS_FILE_LOG_BLOCK_SIZE) {
2245
/* Log data for this group ends here */
2249
log_block += OS_FILE_LOG_BLOCK_SIZE;
2251
} /* while (log_block < log_sys->buf + RECV_SCAN_SIZE && !finished) */
2253
group_scanned_lsn = scanned_lsn;
2259
/* ===== write log to 'xtrabackup_logfile' ====== */
2264
write_size = RECV_SCAN_SIZE;
2266
write_size = ut_dulint_minus(
2267
ut_dulint_align_up(group_scanned_lsn, OS_FILE_LOG_BLOCK_SIZE),
2271
//printf("Wrinting offset= %lld, size= %lu\n", log_copy_offset, write_size);
2273
if (!xtrabackup_stream) {
2274
success = os_file_write(dst_log_path, dst_log, log_sys->buf,
2275
(ulint)(log_copy_offset & 0xFFFFFFFFUL),
2276
(ulint)(log_copy_offset >> 32), write_size);
2279
ulint stdout_write_size = write_size;
2280
if (finished && !is_last
2281
&& group_scanned_lsn % OS_FILE_LOG_BLOCK_SIZE
2283
stdout_write_size -= OS_FILE_LOG_BLOCK_SIZE;
2284
if (stdout_write_size) {
2285
ret = write(fileno(stdout), log_sys->buf, stdout_write_size);
2286
if (ret == stdout_write_size) {
2289
fprintf(stderr, "write: %lu > %lu\n", stdout_write_size, ret);
2293
success = TRUE; /* do nothing */
2297
log_copy_offset += write_size;
2299
if (finished && group_scanned_lsn % OS_FILE_LOG_BLOCK_SIZE)
2301
/* if continue, it will start from align_down(group_scanned_lsn) */
2302
log_copy_offset -= OS_FILE_LOG_BLOCK_SIZE;
2306
if (!xtrabackup_stream) {
2307
fprintf(stderr, "xtrabackup: Error: os_file_write to %s\n", dst_log_path);
2309
fprintf(stderr, "xtrabackup: Error: write to stdout\n");
2321
start_lsn = end_lsn;
2326
group->scanned_lsn = group_scanned_lsn;
2328
if (ut_dulint_cmp(old_scanned_lsn, group_scanned_lsn) < 0) {
2329
/* We found a more up-to-date group */
2331
up_to_date_group = group;
2334
fprintf(stderr, ">> log scanned up to (%"PRIu64")\n",group->scanned_lsn);
2336
group = UT_LIST_GET_NEXT(log_groups, group);
2338
/* update global variable*/
2339
log_copy_scanned_lsn = group_scanned_lsn;
2341
/* innodb_mirrored_log_groups must be 1, no other groups */
2342
ut_a(group == NULL);
2346
if (!xtrabackup_stream) {
2347
success = os_file_flush(dst_log);
2360
if (!xtrabackup_stream)
2361
os_file_close(dst_log);
2362
fprintf(stderr, "xtrabackup: Error: xtrabackup_copy_logfile() failed.\n");
2366
/* copying logfile in background */
2367
#define SLEEPING_PERIOD 5
2380
if (!xtrabackup_stream)
2381
ut_a(dst_log != -1);
2383
log_copying_running = TRUE;
2385
while(log_copying) {
2386
os_thread_sleep(200000); /*0.2 sec*/
2389
if(counter >= SLEEPING_PERIOD * 5) {
2390
if(xtrabackup_copy_logfile(log_copy_scanned_lsn, FALSE))
2397
if(xtrabackup_copy_logfile(log_copy_scanned_lsn, TRUE))
2400
log_copying_succeed = TRUE;
2402
log_copying_running = FALSE;
2403
os_thread_exit(NULL);
2408
/* io throttle watching (rough) */
2418
/* currently, for --backup only */
2419
ut_a(xtrabackup_backup);
2421
while (log_copying) {
2422
os_thread_sleep(1000000); /*1 sec*/
2425
//if (io_ticket == xtrabackup_throttle) {
2426
// fprintf(stderr, "There seem to be no IO...?\n");
2429
io_ticket = xtrabackup_throttle;
2430
os_event_set(wait_throttle);
2433
/* stop io throttle */
2434
xtrabackup_throttle = 0;
2435
os_event_set(wait_throttle);
2437
os_thread_exit(NULL);
2442
/************************************************************************
2443
I/o-handler thread function. */
2458
segment = *((ulint*)arg);
2461
fil_aio_wait(segment);
2464
/* We count the number of threads in os_thread_exit(). A created
2465
thread should always use that to exit and not use return() to exit.
2466
The thread actually never comes here because it is exited in an
2469
os_thread_exit(NULL);
2472
return(NULL); /* Not reached */
2478
/***************************************************************************
2479
Creates an output directory for a given tablespace, if it does not exist */
2482
xtrabackup_create_output_dir(
2483
/*==========================*/
2484
/* out: 0 if succes, -1 if failure */
2485
fil_space_t *space) /* in: tablespace */
2487
char path[FN_REFLEN];
2490
/* mkdir if not exist */
2491
ptr1 = strstr(space->name, SRV_PATH_SEPARATOR_STR);
2493
ptr2 = strstr(ptr1 + 1, SRV_PATH_SEPARATOR_STR);
2498
if(!trx_sys_sys_space(space->id) && ptr2)
2500
if(space->id && ptr2)
2503
/* single table space */
2504
*ptr2 = 0; /* temporary (it's my lazy..)*/
2505
snprintf(path, sizeof(path), "%s%s", xtrabackup_target_dir,
2507
*ptr2 = SRV_PATH_SEPARATOR;
2509
if (mkdir(path, 0777) != 0 && errno != EEXIST) {
2511
"xtrabackup: Error: cannot mkdir %d: %s\n",
2519
/**************************************************************************
2520
Datafiles copying thread.*/
2523
data_copy_thread_func(
2524
/*==================*/
2525
void *arg) /* thread context */
2527
data_thread_ctxt_t *ctxt = (data_thread_ctxt_t *) arg;
2528
uint num = ctxt->num;
2530
ibool space_changed;
2533
while ((node = datafiles_iter_next(ctxt->it, &space_changed)) != NULL) {
2534
space = node->space;
2536
if (space_changed && xtrabackup_create_output_dir(space))
2539
/* copy the datafile */
2540
if(xtrabackup_copy_datafile(node, num)) {
2541
fprintf(stderr, "[%02u] xtrabackup: Error: "
2542
"failed to copy datafile.\n",
2548
os_mutex_enter(ctxt->count_mutex);
2550
os_mutex_exit(ctxt->count_mutex);
2552
os_thread_exit(NULL);
2553
OS_THREAD_DUMMY_RETURN;
2556
/* CAUTION(?): Don't rename file_per_table during backup */
2558
xtrabackup_backup_func(void)
2560
struct stat stat_info;
2563
#ifdef USE_POSIX_FADVISE
2564
fprintf(stderr, "xtrabackup: uses posix_fadvise().\n");
2569
if (chdir(mysql_real_data_home) != 0)
2571
fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", mysql_real_data_home);
2574
fprintf(stderr, "xtrabackup: cd to %s\n", mysql_real_data_home);
2576
mysql_data_home= mysql_data_home_buff;
2577
mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
2578
mysql_data_home[1]=0;
2581
srv_read_only = TRUE;
2583
/* initialize components */
2584
if(innodb_init_param())
2587
if (srv_file_flush_method_str == NULL) {
2588
/* These are the default options */
2589
srv_unix_file_flush_method = SRV_UNIX_FSYNC;
2591
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
2593
} else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) {
2594
srv_unix_file_flush_method = SRV_UNIX_FSYNC;
2596
} else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
2597
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
2599
} else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) {
2600
srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
2601
fprintf(stderr,"xtrabackup: use O_DIRECT\n");
2602
} else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) {
2603
srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
2605
} else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
2606
srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
2608
} else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
2609
srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
2610
os_aio_use_native_aio = FALSE;
2612
} else if (0 == ut_strcmp(srv_file_flush_method_str, "unbuffered")) {
2613
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
2614
os_aio_use_native_aio = FALSE;
2616
} else if (0 == ut_strcmp(srv_file_flush_method_str,
2617
"async_unbuffered")) {
2618
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
2622
"xtrabackup: Unrecognized value %s for innodb_flush_method\n",
2623
srv_file_flush_method_str);
2627
if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
2628
/* Here we still have srv_pool_size counted
2629
in kilobytes (in 4.0 this was in bytes)
2630
srv_boot() converts the value to
2631
pages; if buffer pool is less than 1000 MB,
2632
assume fewer threads. */
2633
srv_max_n_threads = 50000;
2636
} else if (srv_buf_pool_size >= 8 * 1024 * 1024) {
2638
srv_max_n_threads = 10000;
2640
srv_max_n_threads = 1000; /* saves several MB of memory,
2641
especially in 64-bit
2649
nr = srv_n_data_files;
2651
for (i = 0; i < nr; i++) {
2652
srv_data_file_sizes[i] = srv_data_file_sizes[i]
2653
* ((1024 * 1024) / UNIV_PAGE_SIZE);
2656
srv_last_file_size_max = srv_last_file_size_max
2657
* ((1024 * 1024) / UNIV_PAGE_SIZE);
2659
srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE;
2661
srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
2663
srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
2666
os_sync_mutex = NULL;
2670
ibool create_new_db;
2672
ibool create_new_doublewrite_file;
2674
ibool log_file_created;
2675
ibool log_created = FALSE;
2676
ibool log_opened = FALSE;
2677
LSN64 min_flushed_lsn;
2678
LSN64 max_flushed_lsn;
2679
ulint sum_of_new_sizes;
2686
#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
2687
#define SRV_MAX_N_PENDING_SYNC_IOS 100
2689
srv_n_file_io_threads = 2 + srv_n_read_io_threads + srv_n_write_io_threads;
2691
os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD,
2692
srv_n_read_io_threads,
2693
srv_n_write_io_threads,
2694
SRV_MAX_N_PENDING_SYNC_IOS);
2696
fil_init(srv_file_per_table ? 50000 : 5000,
2697
srv_max_n_open_files);
2702
lock_sys_create(srv_lock_table_size);
2704
for (i = 0; i < srv_n_file_io_threads; i++) {
2707
os_thread_create(io_handler_thread, thread_nr + i, thread_ids + i);
2710
os_thread_sleep(200000); /*0.2 sec*/
2712
err = open_or_create_data_files(&create_new_db,
2714
&create_new_doublewrite_file,
2716
&min_flushed_lsn, &max_flushed_lsn,
2718
if (err != DB_SUCCESS) {
2720
"xtrabackup: Could not open or create data files.\n"
2721
"xtrabackup: If you tried to add new data files, and it failed here,\n"
2722
"xtrabackup: you should now edit innodb_data_file_path in my.cnf back\n"
2723
"xtrabackup: to what it was, and remove the new ibdata files InnoDB created\n"
2724
"xtrabackup: in this failed attempt. InnoDB only wrote those files full of\n"
2725
"xtrabackup: zeros, but did not yet use them in any way. But be careful: do not\n"
2726
"xtrabackup: remove old data files which contain your precious data!\n");
2728
//return((int) err);
2732
/* create_new_db must not be TRUE.. */
2733
if (create_new_db) {
2734
fprintf(stderr, "xtrabackup: Something wrong with source files...\n");
2738
for (i = 0; i < srv_n_log_files; i++) {
2739
err = open_or_create_log_file(create_new_db, &log_file_created,
2741
if (err != DB_SUCCESS) {
2743
//return((int) err);
2747
if (log_file_created) {
2752
if ((log_opened && create_new_db)
2753
|| (log_opened && log_created)) {
2755
"xtrabackup: Error: all log files must be created at the same time.\n"
2756
"xtrabackup: All log files must be created also in database creation.\n"
2757
"xtrabackup: If you want bigger or smaller log files, shut down the\n"
2758
"xtrabackup: database and make sure there were no errors in shutdown.\n"
2759
"xtrabackup: Then delete the existing log files. Edit the .cnf file\n"
2760
"xtrabackup: and start the database again.\n");
2767
/* log_file_created must not be TRUE, if online */
2768
if (log_file_created) {
2769
fprintf(stderr, "xtrabackup: Something wrong with source files...\n");
2773
fil_load_single_table_tablespaces();
2777
/* create extra LSN dir if it does not exist. */
2778
if (xtrabackup_extra_lsndir
2779
&& (stat(xtrabackup_extra_lsndir,&stat_info) != 0)
2780
&& (mkdir(xtrabackup_extra_lsndir,0777) != 0)){
2781
fprintf(stderr,"xtrabackup: Error: cannot mkdir %d: %s\n",errno,xtrabackup_extra_lsndir);
2786
if (!xtrabackup_stream) {
2788
/* create target dir if not exist */
2789
if (stat(xtrabackup_target_dir,&stat_info) != 0
2790
&& (mkdir(xtrabackup_target_dir,0777) != 0)){
2791
fprintf(stderr,"xtrabackup: Error: cannot mkdir %d: %s\n",errno,xtrabackup_target_dir);
2796
fprintf(stderr,"xtrabackup: Stream mode.\n");
2797
/* stdout can treat binary at Linux */
2798
//setmode(fileno(stdout), O_BINARY);
2802
fil_system_t* f_system = fil_system;
2804
/* definition from recv_recovery_from_checkpoint_start() */
2805
log_group_t* max_cp_group;
2808
byte log_hdr_buf_[LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE];
2814
/* start back ground thread to copy newer log */
2815
os_thread_id_t log_copying_thread_id;
2816
datafiles_iter_t *it;
2818
log_hdr_buf = (unsigned char*)ut_align(log_hdr_buf_, OS_FILE_LOG_BLOCK_SIZE);
2821
//space = UT_LIST_GET_NEXT(space_list, UT_LIST_GET_FIRST(f_system->space_list));
2822
//printf("space: name=%s, id=%d, purpose=%d, size=%d\n",
2823
// space->name, space->id, space->purpose, space->size);
2825
/* get current checkpoint_lsn */
2826
/* Look for the latest checkpoint from any of the log groups */
2828
err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
2830
if (err != DB_SUCCESS) {
2835
log_group_read_checkpoint_info(max_cp_group, max_cp_field);
2836
buf = log_sys->checkpoint_buf;
2838
checkpoint_lsn_start = MACH_READ_64(buf + LOG_CHECKPOINT_LSN);
2839
checkpoint_no_start = MACH_READ_64(buf + LOG_CHECKPOINT_NO);
2842
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, max_cp_group->space_id,
2844
0, 0, LOG_FILE_HDR_SIZE,
2845
log_hdr_buf, max_cp_group);
2847
/* check consistency of log file header to copy */
2848
err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
2850
if (err != DB_SUCCESS) {
2855
log_group_read_checkpoint_info(max_cp_group, max_cp_field);
2856
buf = log_sys->checkpoint_buf;
2858
if(ut_dulint_cmp(checkpoint_no_start,
2859
MACH_READ_64(buf + LOG_CHECKPOINT_NO)) != 0) {
2860
checkpoint_lsn_start = MACH_READ_64(buf + LOG_CHECKPOINT_LSN);
2861
checkpoint_no_start = MACH_READ_64(buf + LOG_CHECKPOINT_NO);
2862
goto reread_log_header;
2865
if (!xtrabackup_stream) {
2867
/* open 'xtrabackup_logfile' */
2868
sprintf(dst_log_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
2869
srv_normalize_path_for_win(dst_log_path);
2870
/* os_file_create reads srv_unix_file_flush_method for OS_DATA_FILE*/
2871
dst_log = os_file_create(
2872
0 /* dummy of innodb_file_data_key */,
2873
dst_log_path, OS_FILE_CREATE,
2874
OS_FILE_NORMAL, OS_DATA_FILE, &success);
2877
/* The following call prints an error message */
2878
os_file_get_last_error(TRUE);
2881
"xtrabackup: error: cannot open %s\n",
2886
#ifdef USE_POSIX_FADVISE
2887
posix_fadvise(dst_log, 0, 0, POSIX_FADV_DONTNEED);
2893
strcpy((char*) log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
2895
ut_sprintf_timestamp(
2896
(char*) log_hdr_buf + (LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
2897
+ (sizeof "xtrabkup ") - 1));
2899
if (!xtrabackup_stream) {
2900
success = os_file_write(dst_log_path, dst_log, log_hdr_buf,
2901
0, 0, LOG_FILE_HDR_SIZE);
2904
if (write(fileno(stdout), log_hdr_buf, LOG_FILE_HDR_SIZE)
2905
== LOG_FILE_HDR_SIZE) {
2912
log_copy_offset += LOG_FILE_HDR_SIZE;
2915
os_file_close(dst_log);
2922
/* start io throttle */
2923
if(xtrabackup_throttle) {
2924
os_thread_id_t io_watching_thread_id;
2926
io_ticket = xtrabackup_throttle;
2927
wait_throttle = os_event_create(NULL);
2929
os_thread_create(io_watching_thread, NULL, &io_watching_thread_id);
2933
/* copy log file by current position */
2934
if(xtrabackup_copy_logfile(checkpoint_lsn_start, FALSE))
2938
os_thread_create(log_copying_thread, NULL, &log_copying_thread_id);
2942
if (!xtrabackup_stream) { /* stream mode is transaction log only */
2945
os_mutex_t count_mutex;
2946
data_thread_ctxt_t *data_threads;
2951
printf("xtrabackup: Starting %u threads for parallel "
2952
"data files transfer\n", parallel);
2954
it = datafiles_iter_new(f_system);
2957
"xtrabackup: Error: "
2958
"datafiles_iter_new() failed.\n");
2962
/* Create data copying threads */
2965
data_threads = (data_thread_ctxt_t *)
2966
ut_malloc(sizeof(data_thread_ctxt_t) * parallel);
2968
count_mutex = OS_MUTEX_CREATE();
2970
for (i = 0; i < parallel; i++) {
2971
data_threads[i].it = it;
2972
data_threads[i].num = i+1;
2973
data_threads[i].count = &count;
2974
data_threads[i].count_mutex = count_mutex;
2975
os_thread_create(data_copy_thread_func,
2977
&data_threads[i].id);
2980
/* Wait for threads to exit */
2982
os_thread_sleep(1000000);
2983
os_mutex_enter(count_mutex);
2985
os_mutex_exit(count_mutex);
2988
os_mutex_exit(count_mutex);
2990
/* NOTE: It may not needed at "--backup" for now */
2991
/* mutex_enter(&(f_system->mutex)); */
2993
os_mutex_free(count_mutex);
2994
datafiles_iter_free(it);
2996
} //if (!xtrabackup_stream)
2998
//mutex_exit(&(f_system->mutex));
3002
/* suspend-at-end */
3003
if (xtrabackup_suspend_at_end) {
3004
os_file_t suspend_file = -1;
3005
char suspend_path[FN_REFLEN];
3006
ibool success, exists;
3007
os_file_type_t type;
3009
sprintf(suspend_path, "%s%s", xtrabackup_target_dir,
3010
"/xtrabackup_suspended");
3012
srv_normalize_path_for_win(suspend_path);
3013
/* os_file_create reads srv_unix_file_flush_method */
3014
suspend_file = os_file_create(
3015
0 /* dummy of innodb_file_data_key */,
3016
suspend_path, OS_FILE_OVERWRITE,
3017
OS_FILE_NORMAL, OS_DATA_FILE, &success);
3020
fprintf(stderr, "xtrabackup: Error: failed to create file 'xtrabackup_suspended'\n");
3023
if (suspend_file != -1)
3024
os_file_close(suspend_file);
3028
os_thread_sleep(200000); /*0.2 sec*/
3029
success = os_file_status(suspend_path, &exists, &type);
3033
xtrabackup_suspend_at_end = FALSE; /* suspend is 1 time */
3036
/* read the latest checkpoint lsn */
3037
latest_cp = ut_dulint_zero;
3039
log_group_t* max_cp_group;
3043
err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
3045
if (err != DB_SUCCESS) {
3046
fprintf(stderr, "xtrabackup: Error: recv_find_max_checkpoint() failed.\n");
3050
log_group_read_checkpoint_info(max_cp_group, max_cp_field);
3052
latest_cp = MACH_READ_64(log_sys->checkpoint_buf + LOG_CHECKPOINT_LSN);
3054
if (!xtrabackup_stream) {
3055
printf("xtrabackup: The latest check point (for incremental): '%"PRIu64"'\n",
3058
fprintf(stderr, "xtrabackup: The latest check point (for incremental): '%"PRIu64"'\n",
3063
/* stop log_copying_thread */
3064
log_copying = FALSE;
3065
if (!xtrabackup_stream) {
3066
printf("xtrabackup: Stopping log copying thread");
3067
while (log_copying_running) {
3069
os_thread_sleep(200000); /*0.2 sec*/
3073
while (log_copying_running)
3074
os_thread_sleep(200000); /*0.2 sec*/
3077
/* output to metadata file */
3079
char filename[FN_REFLEN];
3081
if(!xtrabackup_incremental) {
3082
strcpy(metadata_type, "full-backuped");
3083
metadata_from_lsn = ut_dulint_zero;
3085
strcpy(metadata_type, "incremental");
3086
metadata_from_lsn = incremental_lsn;
3088
metadata_to_lsn = latest_cp;
3089
metadata_last_lsn = log_copy_scanned_lsn;
3091
sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
3092
if (xtrabackup_write_metadata(filename))
3093
fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_target_dir)\n");
3095
if(xtrabackup_extra_lsndir) {
3096
sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
3097
if (xtrabackup_write_metadata(filename))
3098
fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
3102
if (!log_copying_succeed) {
3103
fprintf(stderr, "xtrabackup: Error: log_copying_thread failed.\n");
3107
if (!xtrabackup_stream)
3108
os_file_close(dst_log);
3111
os_event_free(wait_throttle);
3113
if (!xtrabackup_stream) {
3114
printf("xtrabackup: Transaction log of lsn (%"PRIu64") to (%"PRIu64") was copied.\n",
3115
checkpoint_lsn_start, log_copy_scanned_lsn);
3117
fprintf(stderr, "xtrabackup: Transaction log of lsn (%"PRIu64") to (%"PRIu64") was copied.\n",
3118
checkpoint_lsn_start, log_copy_scanned_lsn);
3119
if(xtrabackup_extra_lsndir) {
3120
char filename[FN_REFLEN];
3121
sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
3122
if (xtrabackup_write_metadata(filename))
3123
fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
3128
/* ================= stats ================= */
3130
xtrabackup_stats_level(
3131
dict_index_t* index,
3139
ulint right_page_no;
3144
mem_heap_t* heap = mem_heap_create(256);
3146
ulint* offsets = NULL;
3148
uint64_t n_pages, n_pages_extern;
3149
uint64_t sum_data, sum_data_extern;
3153
n_pages = sum_data = n_recs = 0;
3154
n_pages_extern = sum_data_extern = 0;
3160
fprintf(stdout, " leaf pages: ");
3162
fprintf(stdout, " level %lu pages: ", level);
3166
mtr_x_lock(&(index->lock), &mtr);
3167
block = btr_root_block_get(index, &mtr);
3168
page = buf_block_get_frame(block);
3170
space = page_get_space_id(page);
3171
zip_size = fil_space_get_zip_size(space);
3173
while (level != btr_page_get_level(page, &mtr)) {
3175
ut_a(space == buf_block_get_space(block));
3176
ut_a(space == page_get_space_id(page));
3177
ut_a(!page_is_leaf(page));
3179
page_cur_set_before_first(block, &cursor);
3180
page_cur_move_to_next(&cursor);
3182
node_ptr = page_cur_get_rec(&cursor);
3183
offsets = rec_get_offsets(node_ptr, index, offsets,
3184
ULINT_UNDEFINED, &heap);
3186
block = btr_node_ptr_get_child(node_ptr, index, offsets, &mtr);
3187
page = buf_block_get_frame(block);
3191
mem_heap_empty(heap);
3193
mtr_x_lock(&(index->lock), &mtr);
3195
right_page_no = btr_page_get_next(page, &mtr);
3198
/*=================================*/
3199
//fprintf(stdout, "%lu ", (ulint) buf_frame_get_page_no(page));
3202
sum_data += page_get_data_size(page);
3203
n_recs += page_get_n_recs(page);
3210
mem_heap_t* local_heap = NULL;
3211
ulint offsets_[REC_OFFS_NORMAL_SIZE];
3212
ulint* local_offsets = offsets_;
3214
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
3216
page_cur_set_before_first(block, &cur);
3218
page_cur_move_to_next(&cur);
3221
if (page_cur_is_after_last(&cur)) {
3225
local_offsets = rec_get_offsets(cur.rec, index, local_offsets,
3226
ULINT_UNDEFINED, &local_heap);
3227
n_fields = rec_offs_n_fields(local_offsets);
3229
for (i = 0; i < n_fields; i++) {
3230
if (rec_offs_nth_extern(local_offsets, i)) {
3241
buf_block_t* local_block;
3243
data = rec_get_nth_field(cur.rec, local_offsets, i, &local_len);
3245
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
3246
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
3248
space_id = mach_read_from_4(data + local_len + BTR_EXTERN_SPACE_ID);
3249
page_no = mach_read_from_4(data + local_len + BTR_EXTERN_PAGE_NO);
3250
offset = mach_read_from_4(data + local_len + BTR_EXTERN_OFFSET);
3251
extern_len = mach_read_from_4(data + local_len + BTR_EXTERN_LEN + 4);
3253
if (offset != FIL_PAGE_DATA)
3254
fprintf(stderr, "\nWarning: several record may share same external page.\n");
3257
mtr_start(&local_mtr);
3259
local_block = btr_block_get(space_id, zip_size, page_no, RW_S_LATCH, &local_mtr);
3260
local_page = buf_block_get_frame(local_block);
3262
blob_header = local_page + offset;
3263
#define BTR_BLOB_HDR_PART_LEN 0
3264
#define BTR_BLOB_HDR_NEXT_PAGE_NO 4
3265
//part_len = btr_blob_get_part_len(blob_header);
3266
part_len = mach_read_from_4(blob_header + BTR_BLOB_HDR_PART_LEN);
3268
//page_no = btr_blob_get_next_page_no(blob_header);
3269
page_no = mach_read_from_4(blob_header + BTR_BLOB_HDR_NEXT_PAGE_NO);
3271
offset = FIL_PAGE_DATA;
3276
/*=================================*/
3277
//fprintf(stdout, "[%lu] ", (ulint) buf_frame_get_page_no(page));
3280
sum_data_extern += part_len;
3283
mtr_commit(&local_mtr);
3285
if (page_no == FIL_NULL)
3291
page_cur_move_to_next(&cur);
3299
if (right_page_no != FIL_NULL) {
3301
block = btr_block_get(space, zip_size, right_page_no, RW_X_LATCH, &mtr);
3302
page = buf_block_get_frame(block);
3305
mem_heap_free(heap);
3308
page_size = zip_size;
3310
page_size = UNIV_PAGE_SIZE;
3314
fprintf(stdout, "recs=%"PRIu64", ", n_recs);
3316
fprintf(stdout, "pages=%"PRIu64", data=%"PRIu64" bytes, data/pages=%"PRIu64"%%",
3318
((sum_data * 100)/ page_size)/n_pages);
3321
if (level == 0 && n_pages_extern) {
3323
/* also scan blob pages*/
3324
fprintf(stdout, " external pages: ");
3326
fprintf(stdout, "pages=%"PRIu64", data=%"PRIu64" bytes, data/pages=%"PRIu64"%%",
3327
n_pages_extern, sum_data_extern,
3328
((sum_data_extern * 100)/ page_size)/n_pages_extern);
3334
xtrabackup_stats_level(index, level - 1);
3341
xtrabackup_stats_func(void)
3347
if (chdir(mysql_real_data_home) != 0)
3349
fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", mysql_real_data_home);
3352
fprintf(stderr, "xtrabackup: cd to %s\n", mysql_real_data_home);
3354
mysql_data_home= mysql_data_home_buff;
3355
mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
3356
mysql_data_home[1]=0;
3359
srv_read_only = TRUE;
3360
srv_fake_write = TRUE;
3362
/* initialize components */
3363
if(innodb_init_param())
3366
/* Check if the log files have been created, otherwise innodb_init()
3367
will crash when called with srv_read_only == TRUE */
3368
for (n = 0; n < srv_n_log_files; n++) {
3369
char logname[FN_REFLEN];
3371
os_file_type_t type;
3373
sprintf(logname, "ib_logfile%lu", (ulong) n);
3374
if (!os_file_status(logname, &exists, &type) || !exists ||
3375
type != OS_FILE_TYPE_FILE) {
3376
fprintf(stderr, "xtrabackup: Error: "
3377
"Cannot find log file %s.\n", logname);
3378
fprintf(stderr, "xtrabackup: Error: "
3379
"to use the statistics feature, you need a "
3380
"clean copy of the database including "
3381
"correctly sized log files, so you need to "
3382
"execute with --prepare twice to use this "
3383
"functionality on a backup.\n");
3388
fprintf(stderr, "xtrabackup: Starting 'read-only' InnoDB instance to gather index statistics.\n"
3389
"xtrabackup: Using %"PRIu64" bytes for buffer pool (set by --use-memory parameter)\n",
3390
xtrabackup_use_memory);
3395
fprintf(stdout, "\n\n<INDEX STATISTICS>\n");
3400
dict_table_t* sys_tables;
3401
dict_index_t* sys_index;
3402
dict_table_t* table;
3409
/* Enlarge the fatal semaphore wait timeout during the InnoDB table
3412
mutex_enter(&kernel_mutex);
3413
srv_fatal_semaphore_wait_threshold += 72000; /* 20 hours */
3414
mutex_exit(&kernel_mutex);
3416
mutex_enter(&(dict_sys->mutex));
3420
sys_tables = dict_table_get_low("SYS_TABLES");
3421
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
3423
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
3426
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
3428
rec = btr_pcur_get_rec(&pcur);
3430
if (!btr_pcur_is_on_user_rec(&pcur))
3434
btr_pcur_close(&pcur);
3437
mutex_exit(&(dict_sys->mutex));
3439
/* Restore the fatal semaphore wait timeout */
3441
mutex_enter(&kernel_mutex);
3442
srv_fatal_semaphore_wait_threshold -= 72000; /* 20 hours */
3443
mutex_exit(&kernel_mutex);
3448
field = rec_get_nth_field_old(rec, 0, &len);
3450
if (!rec_get_deleted_flag(rec, 0))
3455
char* table_name = mem_strdupl((char*) field, len);
3457
btr_pcur_store_position(&pcur, &mtr);
3461
table = dict_table_get_low(table_name);
3462
mem_free(table_name);
3465
if (xtrabackup_tables) {
3470
p = strstr(table->name, SRV_PATH_SEPARATOR_STR);
3475
for (i = 0; i < tables_regex_num; i++) {
3476
regres = regexec(&tables_regex[i], table->name, 1, tables_regmatch, 0);
3477
if (regres != REG_NOMATCH)
3482
*p = SRV_PATH_SEPARATOR;
3484
if ( regres == REG_NOMATCH )
3488
if (xtrabackup_tables_file) {
3489
xtrabackup_tables_t* xtable;
3491
HASH_SEARCH(name_hash, tables_hash, ut_fold_string(table->name),
3492
xtrabackup_tables_t*,
3494
ut_ad(xtable->name),
3495
!strcmp(xtable->name, table->name));
3502
if (table == NULL) {
3503
fputs("InnoDB: Failed to load table ", stderr);
3504
ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
3507
dict_index_t* index;
3509
/* The table definition was corrupt if there
3512
if (dict_table_get_first_index(table)) {
3514
dict_update_statistics(table, TRUE, FALSE);
3515
#elif defined(INNODB_VERSION_SHORT)
3516
dict_update_statistics(table, TRUE);
3518
dict_update_statistics_low(table, TRUE);
3522
//dict_table_print_low(table);
3524
index = UT_LIST_GET_FIRST(table->indexes);
3525
while (index != NULL) {
3529
if (index->n_user_defined_cols > 0) {
3530
n_vals = index->stat_n_diff_key_vals[
3531
index->n_user_defined_cols];
3533
n_vals = index->stat_n_diff_key_vals[1];
3537
" table: %s, index: %s, space id: %lu, root page: %lu"
3539
"\n estimated statistics in dictionary:\n"
3540
" key vals: %lu, leaf pages: %lu, size pages: %lu\n"
3541
" real statistics:\n",
3542
table->name, index->name,
3543
(ulong) index->space,
3544
(ulong) index->page,
3545
(ulong) fil_space_get_zip_size(index->space),
3547
(ulong) index->stat_n_leaf_pages,
3548
(ulong) index->stat_index_size);
3555
mtr_start(&local_mtr);
3557
mtr_x_lock(&(index->lock), &local_mtr);
3558
root = btr_root_get(index, &local_mtr);
3560
page_level = btr_page_get_level(root, &local_mtr);
3562
xtrabackup_stats_level(index, page_level);
3564
mtr_commit(&local_mtr);
3569
index = UT_LIST_GET_NEXT(indexes, index);
3576
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
3585
/* shutdown InnoDB */
3590
/* ================= prepare ================= */
3593
xtrabackup_init_temp_log(void)
3595
os_file_t src_file = -1;
3596
char src_path[FN_REFLEN];
3597
char dst_path[FN_REFLEN];
3602
byte* log_buf_ = NULL;
3609
LSN64 checkpoint_no;
3613
max_no = ut_dulint_zero;
3615
if(!xtrabackup_incremental_dir) {
3616
sprintf(dst_path, "%s%s", xtrabackup_target_dir, "/ib_logfile0");
3617
sprintf(src_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
3619
sprintf(dst_path, "%s%s", xtrabackup_incremental_dir, "/ib_logfile0");
3620
sprintf(src_path, "%s%s", xtrabackup_incremental_dir, "/xtrabackup_logfile");
3623
srv_normalize_path_for_win(dst_path);
3624
srv_normalize_path_for_win(src_path);
3626
src_file = os_file_create_simple_no_error_handling(
3627
0 /* dummy of innodb_file_data_key */,
3628
src_path, OS_FILE_OPEN,
3629
OS_FILE_READ_WRITE /* OS_FILE_READ_ONLY */, &success);
3631
/* The following call prints an error message */
3632
os_file_get_last_error(TRUE);
3635
"xtrabackup: Warning: cannot open %s. will try to find.\n",
3638
/* check if ib_logfile0 may be xtrabackup_logfile */
3639
src_file = os_file_create_simple_no_error_handling(
3640
0 /* dummy of innodb_file_data_key */,
3641
dst_path, OS_FILE_OPEN,
3642
OS_FILE_READ_WRITE /* OS_FILE_READ_ONLY */, &success);
3644
os_file_get_last_error(TRUE);
3646
" xtrabackup: Fatal error: cannot find %s.\n",
3652
log_buf_ = (unsigned char*) ut_malloc(LOG_FILE_HDR_SIZE * 2);
3653
log_buf = (unsigned char*) ut_align(log_buf_, LOG_FILE_HDR_SIZE);
3655
success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
3660
if ( ut_memcmp(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
3661
(byte*)"xtrabkup", (sizeof "xtrabkup") - 1) == 0) {
3663
" xtrabackup: 'ib_logfile0' seems to be 'xtrabackup_logfile'. will retry.\n");
3668
os_file_close(src_file);
3671
/* rename and try again */
3672
success = os_file_rename(
3673
0 /* dummy of innodb_file_data_key */,
3674
dst_path, src_path);
3683
" xtrabackup: Fatal error: cannot find %s.\n",
3689
os_file_close(src_file);
3695
#ifdef USE_POSIX_FADVISE
3696
posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
3697
posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
3700
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
3701
os_file_set_nocache(src_file, src_path, "OPEN");
3704
file_size = os_file_get_size_as_iblonglong(src_file);
3707
/* TODO: We should skip the following modifies, if it is not the first time. */
3708
log_buf_ = (unsigned char*) ut_malloc(UNIV_PAGE_SIZE * 129);
3709
log_buf = (unsigned char*) ut_align(log_buf_, UNIV_PAGE_SIZE);
3711
/* read log file header */
3712
success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
3717
if ( ut_memcmp(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
3718
(byte*)"xtrabkup", (sizeof "xtrabkup") - 1) != 0 ) {
3719
printf("xtrabackup: notice: xtrabackup_logfile was already used to '--prepare'.\n");
3722
/* clear it later */
3723
//memset(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
3727
/* read last checkpoint lsn */
3728
for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2;
3729
field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) {
3730
if (!recv_check_cp_is_consistent(log_buf + field))
3731
goto not_consistent;
3733
checkpoint_no = MACH_READ_64(log_buf + field + LOG_CHECKPOINT_NO);
3735
if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) {
3736
max_no = checkpoint_no;
3737
max_lsn = MACH_READ_64(log_buf + field + LOG_CHECKPOINT_LSN);
3740
mach_write_to_4(log_buf + field + LOG_CHECKPOINT_OFFSET,
3741
LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
3742
ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
3745
fold = ut_fold_binary(log_buf + field, LOG_CHECKPOINT_CHECKSUM_1);
3746
mach_write_to_4(log_buf + field + LOG_CHECKPOINT_CHECKSUM_1, fold);
3748
fold = ut_fold_binary(log_buf + field + LOG_CHECKPOINT_LSN,
3749
LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
3750
mach_write_to_4(log_buf + field + LOG_CHECKPOINT_CHECKSUM_2, fold);
3757
if (ut_dulint_cmp(max_no, ut_dulint_zero) == 0) {
3758
fprintf(stderr, "xtrabackup: No valid checkpoint found.\n");
3763
/* It seems to be needed to overwrite the both checkpoint area. */
3764
MACH_WRITE_64(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN, max_lsn);
3765
mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_OFFSET,
3766
LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
3767
ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
3769
MACH_WRITE_64(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_ARCHIVED_LSN,
3770
(ib_uint64_t)(LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
3771
ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE))));
3773
fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_1, LOG_CHECKPOINT_CHECKSUM_1);
3774
mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_CHECKSUM_1, fold);
3776
fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN,
3777
LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
3778
mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_CHECKSUM_2, fold);
3780
MACH_WRITE_64(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN, max_lsn);
3781
mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_OFFSET,
3782
LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
3783
ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
3785
MACH_WRITE_64(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_ARCHIVED_LSN,
3786
(ib_uint64_t)(LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
3787
ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE))));
3789
fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_2, LOG_CHECKPOINT_CHECKSUM_1);
3790
mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_CHECKSUM_1, fold);
3792
fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN,
3793
LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
3794
mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_CHECKSUM_2, fold);
3797
success = os_file_write(src_path, src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
3802
/* expand file size (9/8) and align to UNIV_PAGE_SIZE */
3804
if (file_size % UNIV_PAGE_SIZE) {
3805
memset(log_buf, 0, UNIV_PAGE_SIZE);
3806
success = os_file_write(src_path, src_file, log_buf,
3807
(ulint)(file_size & 0xFFFFFFFFUL),
3808
(ulint)(file_size >> 32),
3809
UNIV_PAGE_SIZE - (file_size % UNIV_PAGE_SIZE));
3814
file_size = os_file_get_size_as_iblonglong(src_file);
3817
/* TODO: We should judge whether the file is already expanded or not... */
3821
memset(log_buf, 0, UNIV_PAGE_SIZE * 128);
3822
expand = file_size / UNIV_PAGE_SIZE / 8;
3824
for (; expand > 128; expand -= 128) {
3825
success = os_file_write(src_path, src_file, log_buf,
3826
(ulint)(file_size & 0xFFFFFFFFUL),
3827
(ulint)(file_size >> 32),
3828
UNIV_PAGE_SIZE * 128);
3832
file_size += UNIV_PAGE_SIZE * 128;
3836
success = os_file_write(src_path, src_file, log_buf,
3837
(ulint)(file_size & 0xFFFFFFFFUL),
3838
(ulint)(file_size >> 32),
3839
expand * UNIV_PAGE_SIZE);
3843
file_size += UNIV_PAGE_SIZE * expand;
3847
/* make larger than 2MB */
3848
if (file_size < 2*1024*1024L) {
3849
memset(log_buf, 0, UNIV_PAGE_SIZE);
3850
while (file_size < 2*1024*1024L) {
3851
success = os_file_write(src_path, src_file, log_buf,
3852
(ulint)(file_size & 0xFFFFFFFFUL),
3853
(ulint)(file_size >> 32),
3858
file_size += UNIV_PAGE_SIZE;
3860
file_size = os_file_get_size_as_iblonglong(src_file);
3863
printf("xtrabackup: xtrabackup_logfile detected: size=%"PRIu64", start_lsn=(%"PRIu64")\n",
3864
file_size, max_lsn);
3866
os_file_close(src_file);
3869
/* Backup log parameters */
3870
innobase_log_group_home_dir_backup = innobase_log_group_home_dir;
3871
innobase_log_file_size_backup = innobase_log_file_size;
3872
innobase_log_files_in_group_backup = innobase_log_files_in_group;
3875
innobase_log_group_home_dir = NULL;
3876
innobase_log_file_size = file_size;
3877
innobase_log_files_in_group = 1;
3879
srv_thread_concurrency = 0;
3881
/* rename 'xtrabackup_logfile' to 'ib_logfile0' */
3882
success = os_file_rename(
3883
0 /* dummy of innodb_file_data_key */,
3884
src_path, dst_path);
3888
xtrabackup_logfile_is_renamed = TRUE;
3895
os_file_close(src_file);
3902
os_file_close(src_file);
3905
fprintf(stderr, "xtrabackup: Error: xtrabackup_init_temp_log() failed.\n");
3906
return(TRUE); /*ERROR*/
3909
/***********************************************************************
3910
Generates path to the meta file path from a given path to an incremental .delta
3911
by replacing trailing ".delta" with ".meta", or returns error if 'delta_path'
3912
does not end with the ".delta" character sequence.
3913
@return TRUE on success, FALSE on error. */
3917
const char *delta_path, /* in: path to a .delta file */
3918
char *meta_path) /* out: path to the corresponding .meta
3921
size_t len = strlen(delta_path);
3923
if (len <= 6 || strcmp(delta_path + len - 6, ".delta")) {
3926
memcpy(meta_path, delta_path, len - 6);
3927
strcpy(meta_path + len - 6, XB_DELTA_INFO_SUFFIX);
3933
xtrabackup_apply_delta(
3934
const char* dirname, /* in: dir name of incremental */
3935
const char* dbname, /* in: database name (ibdata: NULL) */
3936
const char* filename, /* in: file name (not a path),
3937
including the .delta extension */
3940
os_file_t src_file = -1;
3941
os_file_t dst_file = -1;
3942
char src_path[FN_REFLEN];
3943
char dst_path[FN_REFLEN];
3944
char meta_path[FN_REFLEN];
3947
ibool last_buffer = FALSE;
3948
ulint page_in_buffer;
3949
ulint incremental_buffers = 0;
3951
xb_delta_info_t info;
3953
ulint page_size_shift;
3955
ut_a(xtrabackup_incremental);
3958
snprintf(src_path, sizeof(src_path), "%s/%s/%s",
3959
dirname, dbname, filename);
3960
snprintf(dst_path, sizeof(dst_path), "%s/%s/%s",
3961
xtrabackup_real_target_dir, dbname, filename);
3963
snprintf(src_path, sizeof(src_path), "%s/%s",
3965
snprintf(dst_path, sizeof(dst_path), "%s/%s",
3966
xtrabackup_real_target_dir, filename);
3968
dst_path[strlen(dst_path) - 6] = '\0';
3970
if (!get_meta_path(src_path, meta_path)) {
3974
srv_normalize_path_for_win(dst_path);
3975
srv_normalize_path_for_win(src_path);
3976
srv_normalize_path_for_win(meta_path);
3978
if (!xb_read_delta_metadata(meta_path, &info)) {
3982
page_size = info.page_size;
3983
page_size_shift = get_bit_shift(page_size);
3984
fprintf(stderr, "xtrabackup: page size for %s is %lu bytes\n",
3985
src_path, page_size);
3986
if (page_size_shift < 10 ||
3987
page_size_shift > UNIV_PAGE_SIZE_SHIFT_MAX) {
3989
"xtrabackup: error: invalid value of page_size "
3990
"(%lu bytes) read from %s\n", page_size, meta_path);
3994
src_file = os_file_create_simple_no_error_handling(
3995
0 /* dummy of innodb_file_data_key */,
3996
src_path, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
3998
os_file_get_last_error(TRUE);
4000
"xtrabackup: error: cannot open %s\n",
4005
#ifdef USE_POSIX_FADVISE
4006
posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
4007
posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
4010
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
4011
os_file_set_nocache(src_file, src_path, "OPEN");
4014
dst_file = os_file_create_simple_no_error_handling(
4015
0 /* dummy of innodb_file_data_key */,
4016
dst_path, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
4018
os_file_get_last_error(TRUE);
4020
"xtrabackup: error: cannot open %s\n",
4025
#ifdef USE_POSIX_FADVISE
4026
posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED);
4029
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
4030
os_file_set_nocache(dst_file, dst_path, "OPEN");
4033
printf("Applying %s ...\n", src_path);
4035
while (!last_buffer) {
4036
ulint cluster_header;
4038
/* read to buffer */
4039
/* first block of block cluster */
4040
success = os_file_read(src_file, incremental_buffer,
4041
((incremental_buffers * (page_size / 4))
4042
<< page_size_shift) & 0xFFFFFFFFUL,
4043
(incremental_buffers * (page_size / 4))
4044
>> (32 - page_size_shift),
4050
cluster_header = mach_read_from_4(incremental_buffer);
4051
switch(cluster_header) {
4052
case 0x78747261UL: /*"xtra"*/
4054
case 0x58545241UL: /*"XTRA"*/
4059
"xtrabackup: error: %s seems not .delta file.\n",
4064
for (page_in_buffer = 1; page_in_buffer < page_size / 4;
4066
if (mach_read_from_4(incremental_buffer + page_in_buffer * 4)
4071
ut_a(last_buffer || page_in_buffer == page_size / 4);
4073
/* read whole of the cluster */
4074
success = os_file_read(src_file, incremental_buffer,
4075
((incremental_buffers * (page_size / 4))
4076
<< page_size_shift) & 0xFFFFFFFFUL,
4077
(incremental_buffers * (page_size / 4))
4078
>> (32 - page_size_shift),
4079
page_in_buffer * page_size);
4084
for (page_in_buffer = 1; page_in_buffer < page_size / 4;
4086
ulint offset_on_page;
4088
offset_on_page = mach_read_from_4(incremental_buffer + page_in_buffer * 4);
4090
if (offset_on_page == 0xFFFFFFFFUL)
4093
/* apply blocks in the cluster */
4094
// if (ut_dulint_cmp(incremental_lsn,
4095
// MACH_READ_64(incremental_buffer
4096
// + page_in_buffer * page_size
4097
// + FIL_PAGE_LSN)) >= 0)
4100
success = os_file_write(dst_path, dst_file,
4101
incremental_buffer +
4102
page_in_buffer * page_size,
4103
(offset_on_page << page_size_shift) &
4105
offset_on_page >> (32 - page_size_shift),
4112
incremental_buffers++;
4116
os_file_close(src_file);
4118
os_file_close(dst_file);
4123
os_file_close(src_file);
4125
os_file_close(dst_file);
4126
fprintf(stderr, "xtrabackup: Error: xtrabackup_apply_delta() failed.\n");
4131
xtrabackup_apply_deltas(bool check_newer)
4134
char dbpath[FN_REFLEN];
4136
os_file_dir_t dbdir;
4137
os_file_stat_t dbinfo;
4138
os_file_stat_t fileinfo;
4139
ulint err = DB_SUCCESS;
4140
static char current_dir[2];
4142
current_dir[0] = FN_CURLIB;
4144
srv_data_home = current_dir;
4147
dbdir = os_file_opendir(xtrabackup_incremental_dir, FALSE);
4149
if (dbdir != NULL) {
4150
ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dbdir,
4153
if (fileinfo.type == OS_FILE_TYPE_DIR) {
4154
goto next_file_item_1;
4157
if (strlen(fileinfo.name) > 6
4158
&& 0 == strcmp(fileinfo.name +
4159
strlen(fileinfo.name) - 6,
4161
xtrabackup_apply_delta(
4162
xtrabackup_incremental_dir, NULL,
4163
fileinfo.name, check_newer);
4166
ret = fil_file_readdir_next_file(&err,
4167
xtrabackup_incremental_dir, dbdir,
4171
os_file_closedir(dbdir);
4173
fprintf(stderr, "xtrabackup: Cannot open dir %s\n", xtrabackup_incremental_dir);
4176
/* single table tablespaces */
4177
dir = os_file_opendir(xtrabackup_incremental_dir, FALSE);
4180
fprintf(stderr, "xtrabackup: Cannot open dir %s\n", xtrabackup_incremental_dir);
4183
ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dir,
4186
if (dbinfo.type == OS_FILE_TYPE_FILE
4187
|| dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
4189
goto next_datadir_item;
4192
sprintf(dbpath, "%s/%s", xtrabackup_incremental_dir,
4194
srv_normalize_path_for_win(dbpath);
4196
dbdir = os_file_opendir(dbpath, FALSE);
4198
if (dbdir != NULL) {
4200
ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
4204
if (fileinfo.type == OS_FILE_TYPE_DIR) {
4206
goto next_file_item_2;
4209
if (strlen(fileinfo.name) > 6
4210
&& 0 == strcmp(fileinfo.name +
4211
strlen(fileinfo.name) - 6,
4213
/* The name ends in .delta; try opening
4215
xtrabackup_apply_delta(
4216
xtrabackup_incremental_dir, dbinfo.name,
4217
fileinfo.name, check_newer);
4220
ret = fil_file_readdir_next_file(&err,
4225
os_file_closedir(dbdir);
4228
ret = fil_file_readdir_next_file(&err,
4229
xtrabackup_incremental_dir,
4233
os_file_closedir(dir);
4238
xtrabackup_close_temp_log(bool clear_flag)
4240
os_file_t src_file = -1;
4241
char src_path[FN_REFLEN];
4242
char dst_path[FN_REFLEN];
4246
byte* log_buf_ = NULL;
4249
if (!xtrabackup_logfile_is_renamed)
4252
/* Restore log parameters */
4253
innobase_log_group_home_dir = innobase_log_group_home_dir_backup;
4254
innobase_log_file_size = innobase_log_file_size_backup;
4255
innobase_log_files_in_group = innobase_log_files_in_group_backup;
4257
/* rename 'ib_logfile0' to 'xtrabackup_logfile' */
4258
if(!xtrabackup_incremental_dir) {
4259
sprintf(dst_path, "%s%s", xtrabackup_target_dir, "/ib_logfile0");
4260
sprintf(src_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
4262
sprintf(dst_path, "%s%s", xtrabackup_incremental_dir, "/ib_logfile0");
4263
sprintf(src_path, "%s%s", xtrabackup_incremental_dir, "/xtrabackup_logfile");
4266
srv_normalize_path_for_win(dst_path);
4267
srv_normalize_path_for_win(src_path);
4269
success = os_file_rename(
4270
0 /* dummy of innodb_file_data_key */,
4271
dst_path, src_path);
4275
xtrabackup_logfile_is_renamed = FALSE;
4280
/* clear LOG_FILE_WAS_CREATED_BY_HOT_BACKUP field */
4281
src_file = os_file_create_simple_no_error_handling(
4282
0 /* dummy of innodb_file_data_key */,
4283
src_path, OS_FILE_OPEN,
4284
OS_FILE_READ_WRITE, &success);
4289
#ifdef USE_POSIX_FADVISE
4290
posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
4293
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
4294
os_file_set_nocache(src_file, src_path, "OPEN");
4297
log_buf_ = (unsigned char*) ut_malloc(LOG_FILE_HDR_SIZE * 2);
4298
log_buf = (unsigned char*) ut_align(log_buf_, LOG_FILE_HDR_SIZE);
4300
success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
4305
memset(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, ' ', 4);
4307
success = os_file_write(src_path, src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
4312
os_file_close(src_file);
4318
os_file_close(src_file);
4321
fprintf(stderr, "xtrabackup: Error: xtrabackup_close_temp_log() failed.\n");
4322
return(TRUE); /*ERROR*/
4326
xtrabackup_prepare_func(void)
4328
/* cd to target-dir */
4330
if (chdir(xtrabackup_real_target_dir) != 0)
4332
fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", xtrabackup_real_target_dir);
4335
fprintf(stderr, "xtrabackup: cd to %s\n", xtrabackup_real_target_dir);
4337
xtrabackup_target_dir= mysql_data_home_buff;
4338
mysql_data_home_buff[0]=FN_CURLIB; // all paths are relative from here
4339
mysql_data_home_buff[1]=0;
4341
/* read metadata of target */
4343
char filename[FN_REFLEN];
4345
sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
4347
if (xtrabackup_read_metadata(filename))
4348
fprintf(stderr, "xtrabackup: error: xtrabackup_read_metadata()\n");
4350
if (!strcmp(metadata_type, "full-backuped")) {
4351
fprintf(stderr, "xtrabackup: This target seems to be not prepared yet.\n");
4352
} else if (!strcmp(metadata_type, "full-prepared")) {
4353
fprintf(stderr, "xtrabackup: This target seems to be already prepared.\n");
4356
fprintf(stderr, "xtrabackup: This target seems not to have correct metadata...\n");
4359
if (xtrabackup_incremental) {
4361
"xtrabackup: error: applying incremental backup needs target prepared.\n");
4365
if (xtrabackup_incremental
4366
&& ut_dulint_cmp(metadata_to_lsn, incremental_lsn) != 0) {
4368
"xtrabackup: error: This incremental backup seems not to be proper for the target.\n"
4369
"xtrabackup: Check 'to_lsn' of the target and 'from_lsn' of the incremental.\n");
4374
/* Create logfiles for recovery from 'xtrabackup_logfile', before start InnoDB */
4375
srv_max_n_threads = 1000;
4376
os_sync_mutex = NULL;
4379
/* temporally dummy value to avoid crash */
4380
srv_page_size_shift = 14;
4381
srv_page_size = (1 << srv_page_size_shift);
4385
os_io_init_simple();
4386
if(xtrabackup_init_temp_log())
4389
if(xtrabackup_incremental)
4390
xtrabackup_apply_deltas(TRUE);
4393
sync_initialized = FALSE;
4395
os_sync_mutex = NULL;
4398
/* check the accessibility of target-dir */
4399
/* ############# TODO ##################### */
4401
if(innodb_init_param())
4404
srv_apply_log_only = (ibool) xtrabackup_apply_log_only;
4406
/* increase IO threads */
4407
if(srv_n_file_io_threads < 10) {
4408
srv_n_file_io_threads = 10;
4411
fprintf(stderr, "xtrabackup: Starting InnoDB instance for recovery.\n"
4412
"xtrabackup: Using %"PRIu64" bytes for buffer pool (set by --use-memory parameter)\n",
4413
xtrabackup_use_memory);
4418
//printf("Hello InnoDB world!\n");
4420
/* TEST: innodb status*/
4422
ulint trx_list_start = ULINT_UNDEFINED;
4423
ulint trx_list_end = ULINT_UNDEFINED;
4424
srv_printf_innodb_monitor(stdout, &trx_list_start, &trx_list_end);
4426
/* TEST: list of datafiles and transaction log files and LSN*/
4429
fil_system_t* f_system = fil_system;
4433
mutex_enter(&(f_system->mutex));
4435
space = UT_LIST_GET_FIRST(f_system->space_list);
4437
while (space != NULL) {
4438
printf("space: name=%s, id=%d, purpose=%d, size=%d\n",
4439
space->name, space->id, space->purpose, space->size);
4441
node = UT_LIST_GET_FIRST(space->chain);
4443
while (node != NULL) {
4444
printf("node: name=%s, open=%d, size=%d\n",
4445
node->name, node->open, node->size);
4447
node = UT_LIST_GET_NEXT(chain, node);
4449
space = UT_LIST_GET_NEXT(space_list, space);
4452
mutex_exit(&(f_system->mutex));
4455
/* align space sizes along with fsp header */
4457
fil_system_t* f_system = fil_system;
4460
mutex_enter(&(f_system->mutex));
4461
space = UT_LIST_GET_FIRST(f_system->space_list);
4463
while (space != NULL) {
4471
if (space->purpose == FIL_TABLESPACE) {
4472
mutex_exit(&(f_system->mutex));
4476
mtr_s_lock(fil_space_get_latch(space->id, &flags), &mtr);
4478
block = buf_page_get(space->id,
4479
dict_table_flags_to_zip_size(flags),
4480
0, RW_S_LATCH, &mtr);
4481
header = FIL_PAGE_DATA /*FSP_HEADER_OFFSET*/
4482
+ buf_block_get_frame(block);
4484
size = mtr_read_ulint(header + 8 /* FSP_SIZE */, MLOG_4BYTES, &mtr);
4488
//printf("%d, %d\n", space->id, size);
4490
fil_extend_space_to_desired_size(&actual_size, space->id, size);
4492
mutex_enter(&(f_system->mutex));
4495
space = UT_LIST_GET_NEXT(space_list, space);
4498
mutex_exit(&(f_system->mutex));
4503
if (xtrabackup_export) {
4504
printf("xtrabackup: export option is specified.\n");
4505
if (innobase_file_per_table) {
4506
fil_system_t* f_system = fil_system;
4509
os_file_t info_file = -1;
4510
char info_file_path[FN_REFLEN];
4512
char table_name[FN_REFLEN];
4517
buf = (byte*) ut_malloc(UNIV_PAGE_SIZE * 2);
4518
page = (byte*) ut_align(buf, UNIV_PAGE_SIZE);
4520
/* flush insert buffer at shutdwon */
4521
innobase_fast_shutdown = 0;
4523
mutex_enter(&(f_system->mutex));
4525
space = UT_LIST_GET_FIRST(f_system->space_list);
4526
while (space != NULL) {
4527
/* treat file_per_table only */
4528
if (space->purpose != FIL_TABLESPACE
4530
|| trx_sys_sys_space(space->id)
4536
space = UT_LIST_GET_NEXT(space_list, space);
4540
node = UT_LIST_GET_FIRST(space->chain);
4541
while (node != NULL) {
4543
char *next, *prev, *p;
4544
dict_table_t* table;
4545
dict_index_t* index;
4548
/* node exist == file exist, here */
4549
strncpy(info_file_path, node->name, FN_REFLEN);
4550
len = strlen(info_file_path);
4551
info_file_path[len - 3] = 'e';
4552
info_file_path[len - 2] = 'x';
4553
info_file_path[len - 1] = 'p';
4557
while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
4562
info_file_path[len - 4] = 0;
4563
strncpy(table_name, prev, FN_REFLEN);
4565
info_file_path[len - 4] = '.';
4567
mutex_exit(&(f_system->mutex));
4568
mutex_enter(&(dict_sys->mutex));
4570
table = dict_table_get_low(table_name);
4573
"xtrabackup: error: cannot find dictionary record of table %s\n", table_name);
4576
index = dict_table_get_first_index(table);
4577
n_index = UT_LIST_GET_LEN(table->indexes);
4580
"xtrabackup: error: sorry, cannot export over 31 indexes for now.\n");
4585
bzero(page, UNIV_PAGE_SIZE);
4586
mach_write_to_4(page , 0x78706f72UL);
4587
mach_write_to_4(page + 4, 0x74696e66UL);/*"xportinf"*/
4588
mach_write_to_4(page + 8, n_index);
4589
strncpy((char*)page + 12, table_name, 500);
4592
"xtrabackup: export metadata of table '%s' to file `%s` (%lu indexes)\n",
4593
table_name, info_file_path, n_index);
4597
mach_write_to_8(page + n_index * 512, index->id);
4598
mach_write_to_4(page + n_index * 512 + 8,
4601
strncpy((char*)page + n_index * 512 + 12, index->name, 500);
4604
"xtrabackup: name=%s, id.low=%lu, page=%lu\n",
4606
(ulint)(index->id & 0xFFFFFFFFUL),
4608
(ulint) index->page);
4610
index = dict_table_get_next_index(index);
4614
srv_normalize_path_for_win(info_file_path);
4615
info_file = os_file_create(
4616
0 /* dummy of innodb_file_data_key */,
4617
info_file_path, OS_FILE_OVERWRITE,
4618
OS_FILE_NORMAL, OS_DATA_FILE, &success);
4620
os_file_get_last_error(TRUE);
4623
success = os_file_write(info_file_path, info_file, page,
4624
0, 0, UNIV_PAGE_SIZE);
4626
os_file_get_last_error(TRUE);
4629
success = os_file_flush(info_file);
4631
os_file_get_last_error(TRUE);
4635
if (info_file != -1) {
4636
os_file_close(info_file);
4639
mutex_exit(&(dict_sys->mutex));
4640
mutex_enter(&(f_system->mutex));
4642
node = UT_LIST_GET_NEXT(chain, node);
4645
space = UT_LIST_GET_NEXT(space_list, space);
4647
mutex_exit(&(f_system->mutex));
4651
printf("xtrabackup: export option is for file_per_table only, disabled.\n");
4655
/* print binlog position (again?) */
4656
printf("\n[notice (again)]\n"
4657
" If you use binary log and don't use any hack of group commit,\n"
4658
" the binary log position seems to be:\n");
4659
// FIXME: trx_sys_print_mysql_binlog_offset();
4662
/* output to xtrabackup_binlog_pos_innodb */
4664
//FIXME if (*trx_sys_mysql_bin_log_name != '\0') {
4667
fp = fopen("xtrabackup_binlog_pos_innodb", "w");
4669
fprintf(fp, "%s\t%llu\n",
4672
trx_sys_mysql_bin_log_name,
4673
trx_sys_mysql_bin_log_pos);*/
4676
printf("xtrabackup: failed to open 'xtrabackup_binlog_pos_innodb'\n");
4680
/* Check whether the log is applied enough or not. */
4681
if ((xtrabackup_incremental
4682
&& ut_dulint_cmp(srv_start_lsn, incremental_last_lsn) < 0)
4683
||(!xtrabackup_incremental
4684
&& ut_dulint_cmp(srv_start_lsn, metadata_last_lsn) < 0)) {
4685
printf( "xtrabackup: ########################################################\n"
4686
"xtrabackup: # !!WARNING!! #\n"
4687
"xtrabackup: # The transaction log file should be wrong or corrupt. #\n"
4688
"xtrabackup: # The log was not applied to the intended LSN! #\n"
4689
"xtrabackup: ########################################################\n");
4690
if (xtrabackup_incremental) {
4691
printf("xtrabackup: The intended lsn is %"PRIu64"\n",
4692
incremental_last_lsn);
4694
printf("xtrabackup: The intended lsn is %"PRIu64"\n",
4702
sync_initialized = FALSE;
4703
os_sync_mutex = NULL;
4705
/* re-init necessary components */
4710
os_io_init_simple();
4712
if(xtrabackup_close_temp_log(TRUE))
4715
/* output to metadata file */
4717
char filename[FN_REFLEN];
4719
strcpy(metadata_type, "full-prepared");
4721
if(xtrabackup_incremental
4722
&& ut_dulint_cmp(metadata_to_lsn, incremental_to_lsn) < 0)
4724
metadata_to_lsn = incremental_to_lsn;
4725
metadata_last_lsn = incremental_last_lsn;
4728
sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
4729
if (xtrabackup_write_metadata(filename))
4730
fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_target_dir)\n");
4732
if(xtrabackup_extra_lsndir) {
4733
sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
4734
if (xtrabackup_write_metadata(filename))
4735
fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
4739
if(!xtrabackup_create_ib_logfile)
4742
/* TODO: make more smart */
4744
printf("\n[notice]\nWe cannot call InnoDB second time during the process lifetime.\n");
4745
printf("Please re-execte to create ib_logfile*. Sorry.\n");
4747
printf("Restart InnoDB to create ib_logfile*.\n");
4749
if(innodb_init_param())
4762
xtrabackup_close_temp_log(FALSE);
4767
/* ================= main =================== */
4769
int main(int argc, char **argv)
4771
po::options_description commandline_options(_("Options used only in command line"));
4772
commandline_options.add_options()
4773
("target-dir", po::value<std::string>(), _("destination directory"))
4774
("backup", po::value<bool>(&xtrabackup_backup)->default_value(false)->zero_tokens(), _("take backup to target-dir"))
4775
("stats", po::value<bool>(&xtrabackup_stats)->default_value(false)->zero_tokens(), _("calc statistic of datadir (offline mysqld is recommended)"))
4776
("prepare", po::value<bool>(&xtrabackup_prepare)->default_value(false)->zero_tokens(), _("prepare a backup for starting mysql server on the backup."))
4777
("export", po::value<bool>(&xtrabackup_export)->default_value(false)->zero_tokens(), _("create files to import to another database when prepare."))
4778
("apply-log-only", po::value<bool>(&xtrabackup_apply_log_only)->default_value(false)->zero_tokens(), _("stop recovery process not to progress LSN after applying log when prepare."))
4779
("print-param", po::value<bool>(&xtrabackup_print_param)->default_value(false)->zero_tokens(), _("print parameter of mysqld needed for copyback."))
4780
("use-memory", po::value<uint64_t>(&xtrabackup_use_memory)->default_value(100*1024*1024), _("The value is used instead of buffer_pool_size"))
4781
("suspend-at-end", po::value<bool>(&xtrabackup_suspend_at_end)->default_value(false)->zero_tokens(), _("creates a file 'xtrabackup_suspended' and waits until the user deletes that file at the end of '--backup'"))
4782
("throttle", po::value<long>(&xtrabackup_throttle), _("limit count of IO operations (pairs of read&write) per second to IOS values (for '--backup')"))
4783
("log-stream", po::value<bool>(&xtrabackup_stream)->default_value(false)->zero_tokens(), _("outputs the contents of 'xtrabackup_logfile' to stdout only until the file 'xtrabackup_suspended' deleted (for '--backup')."))
4784
("extra-lsndir", po::value<std::string>(), _("(for --backup): save an extra copy of the xtrabackup_checkpoints file in this directory."))
4785
("incremental-lsn", po::value<std::string>(), _("(for --backup): copy only .ibd pages newer than specified LSN 'high:low'. ##ATTENTION##: checkpoint lsn must be used. anyone can detect your mistake. be carefully!"))
4786
("incremental-basedir", po::value<std::string>(), _("(for --backup): copy only .ibd pages newer than backup at specified directory."))
4787
("incremental-dir", po::value<std::string>(), _("(for --prepare): apply .delta files and logfile in the specified directory."))
4788
("tables", po::value<std::string>(), _("filtering by regexp for table names."))
4789
("tables-file", po::value<std::string>(), _("filtering by list of the exact database.table name in the file."))
4790
("create-ib-logfile", po::value<bool>(&xtrabackup_create_ib_logfile), _("** not work for now** creates ib_logfile* also after '--prepare'. ### If you want create ib_logfile*, only re-execute this command in same options. ###"))
4791
("datadir,h", po::value<std::string>(), _("Path to the database root."))
4792
("tmpdir,t", po::value<std::string>(), _("Path for temporary files. Several paths may be specified, separated by a colon (:), in this case they are used in a round-robin fashion."))
4793
("parallel", po::value<uint32_t>(¶llel)->default_value(1), _("Number of threads to use for parallel datafiles transfer. Does not have any effect in the stream mode. The default value is 1."))
4794
("innodb-adaptive-hash-index", po::value<bool>(&innobase_adaptive_hash_index)->default_value(true), _("Enable InnoDB adaptive hash index (enabled by default). Disable with --skip-innodb-adaptive-hash-index."))
4795
("innodb-additional-mem-pool-size", po::value<long>(&innobase_additional_mem_pool_size)->default_value(1*1024*1024), _("Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures."))
4796
("innodb-autoextend-increment", po::value<uint32_t>(&srv_auto_extend_increment)->default_value(8), _("Data file autoextend increment in megabytes"))
4797
("innodb-buffer-pool-size", po::value<uint64_t>(&innobase_buffer_pool_size)->default_value(8*1024*1024), _("The size of the memory buffer InnoDB uses to cache data and indexes of its tables."))
4798
("innodb-checksums", po::value<bool>(&innobase_use_checksums)->default_value(true), _("Enable InnoDB checksums validation (enabled by default). Disable with --skip-innodb-checksums."))
4799
("innodb-data-file-path", po::value<std::string>(), _("Path to individual files and their sizes."))
4800
("innodb-data-home-dir", po::value<std::string>(), _("The common part for InnoDB table spaces."))
4801
("innodb-doublewrite", po::value<bool>(&innobase_use_doublewrite)->default_value(true), _("Enable InnoDB doublewrite buffer (enabled by default). Disable with --skip-innodb-doublewrite."))
4802
("innodb-file-io-threads", po::value<long>(&innobase_file_io_threads)->default_value(4), _("Number of file I/O threads in InnoDB."))
4803
("innodb-file-per-table", po::value<bool>(&innobase_file_per_table), _("Stores each InnoDB table to an .ibd file in the database dir."))
4804
("innodb-flush-log-at-trx-commit", po::value<ulong>(&srv_flush_log_at_trx_commit)->default_value(1), _("Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second)."))
4805
("innodb-flush-method", po::value<std::string>(), _("With which method to flush data."))
4806
/* ####### Should we use this option? ####### */
4807
("innodb-force-recovery", po::value<long>(&innobase_force_recovery)->default_value(0), _("Helps to save your data in case the disk image of the database becomes corrupt."))
4808
("innodb-lock-wait-timeout", po::value<long>(&innobase_lock_wait_timeout)->default_value(50), _("Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back."))
4809
("innodb-log-buffer-size", po::value<long>(&innobase_log_buffer_size)->default_value(1024*1024), _("The size of the buffer which InnoDB uses to write log to the log files on disk."))
4810
("innodb-log-file-size", po::value<log_file_constraint>(&innobase_log_file_size)->default_value(20*1024*1024L), _("Size of each log file in a log group."))
4811
("innodb-log-files-in-group", po::value<long>(&innobase_log_files_in_group)->default_value(2), _("Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here."))
4812
("innodb-log-group-home-dir", po::value<std::string>(), _("Path to InnoDB log files."))
4813
("innodb-max_dirty-pages-pct", po::value<ulong>(&srv_max_buf_pool_modified_pct)->default_value(90), _("Percentage of dirty pages allowed in bufferpool."))
4814
("innodb-open-files", po::value<long>(&innobase_open_files)->default_value(300), _("How many files at the maximum InnoDB keeps open at the same time."))
4816
("innodb-page-size", po::value<uint32_t>(&innobase_page_size)->default_value(1 << 14), _("The universal page size of the database."))
4817
("innodb-log-block-size", po::value<uint32_t>(&innobase_log_block_size)->default_value(512), _("###EXPERIMENTAL###: The log block size of the transaction log file. Changing for created log file is not supported. Use on your own risk!"))
4818
("innodb-fast-checksum", po::value<bool>(&innobase_fast_checksum), _("Change the algorithm of checksum for the whole of datapage to 4-bytes word based."))
4819
("innodb-extra-undoslots", po::value<bool>(&innobase_extra_undoslots), _("Enable to use about 4000 undo slots instead of default 1024. Not recommended to use, Because it is not change back to disable, once it is used."))
4820
("innodb-doublewrite-file", po::value<char *>(&innobase_doublewrite_file), _("Path to special datafile for doublewrite buffer. (default is "": not used)"))
4824
po::variables_map vm;
4825
// Disable allow_guessing, it is evil and broken
4826
int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
4827
po::store(po::command_line_parser(argc, argv).options(commandline_options).style(style).run(), vm);
4830
if (vm.count("target-dir"))
4831
xtrabackup_target_dir= vm["target-dir"].as<std::string>().c_str();
4833
if (vm.count("extra-lsndir"))
4834
xtrabackup_extra_lsndir= vm["extra-lsndir"].as<std::string>().c_str();
4836
if (vm.count("incremental-lsn"))
4837
xtrabackup_incremental= vm["incremental-lsn"].as<std::string>().c_str();
4839
if (vm.count("incremental-basedir"))
4840
xtrabackup_incremental_basedir= vm["incremental-basedir"].as<std::string>().c_str();
4842
boost::scoped_ptr<char> xtrabackup_tables_autoptr(new char[(vm.count("tables")) ? vm["tables"].as<std::string>().length() + 1: 0]);
4843
if (vm.count("tables"))
4845
xtrabackup_tables= xtrabackup_tables_autoptr.get();
4846
strcpy(xtrabackup_tables, vm["tables"].as<std::string>().c_str());
4849
if (vm.count("tables-file"))
4850
xtrabackup_tables_file= vm["tables-file"].as<std::string>().c_str();
4852
if (vm.count("tmpdir"))
4853
opt_mysql_tmpdir= vm["tmpdir"].as<std::string>().c_str();
4855
if (vm.count("innodb-data-file-path"))
4856
innobase_data_file_path= vm["innodb-data-file-path"].as<std::string>().c_str();
4858
boost::scoped_ptr<char> xtrabackup_incremental_dir_autoptr(new char[(vm.count("incremental-dir")) ? vm["incremental-dir"].as<std::string>().length() + 1: 0]);
4859
if (vm.count("incremental-dir"))
4861
xtrabackup_incremental_dir= xtrabackup_incremental_dir_autoptr.get();
4862
strcpy(xtrabackup_incremental_dir, vm["incremental-dir"].as<std::string>().c_str());
4865
boost::scoped_ptr<char> innobase_data_home_dir_autoptr(new char[(vm.count("innodb-data-home-dir")) ? vm["innodb-data-home-dir"].as<std::string>().length() + 1 : 0]);
4866
if (vm.count("innodb-data-home-dir"))
4868
innobase_data_home_dir= innobase_data_home_dir_autoptr.get();
4869
strcpy(innobase_data_home_dir, vm["innodb-data-home-dir"].as<std::string>().c_str());
4872
boost::scoped_ptr<char> innobase_flush_method_autoptr(new char[(vm.count("innodb-flush-method")) ? vm["innodb-flush-method"].as<std::string>().length() + 1 : 0]);
4873
if (vm.count("innodb-flush-method"))
4875
innobase_unix_file_flush_method= innobase_flush_method_autoptr.get();
4876
strcpy(innobase_unix_file_flush_method, vm["innodb-flush-method"].as<std::string>().c_str());
4879
boost::scoped_ptr<char> innobase_log_group_home_dir_autoptr(new char[(vm.count("innodb-log-group-home-dir")) ? vm["innodb-log-group-home-dir"].as<std::string>().length() + 1: 0]);
4881
if (vm.count("innodb-log-group-home-dir"))
4883
innobase_log_group_home_dir= innobase_log_group_home_dir_autoptr.get();
4884
strcpy(innobase_log_group_home_dir, vm["innodb-log-group-home-dir"].as<std::string>().c_str());
4887
xtrabackup_use_memory-= xtrabackup_use_memory % (1024*1024);
4888
if (xtrabackup_use_memory < (1024*1024)) {
4889
fprintf(stderr, "xtrabackup: use-memory out of range\n");
4894
fprintf(stderr, "xtrabackup: parallel needs to be greater than 0\n");
4898
innobase_additional_mem_pool_size-= innobase_additional_mem_pool_size % 1024;
4899
if (innobase_additional_mem_pool_size < (512*1024)) {
4900
fprintf(stderr, "xtrabackup: innodb-additional-mem-pool-size out of range\n");
4904
if ((srv_auto_extend_increment < 1) || (srv_auto_extend_increment > 8)) {
4905
fprintf(stderr, "xtrabackup: innodb-auto-extend-increment out of range\n");
4909
innobase_buffer_pool_size-= innobase_buffer_pool_size % (1024*1024);
4910
if (innobase_buffer_pool_size < (1024*1024)) {
4911
fprintf(stderr, "xtrabackup: innodb-buffer-pool-size out of range\n");
4915
if ((innobase_file_io_threads < 4) || (innobase_file_io_threads > 64)) {
4916
fprintf(stderr, "xtrabackup: innodb-file-io-threads out of range\n");
4920
if (srv_flush_log_at_trx_commit > 2) {
4921
fprintf(stderr, "xtrabackup: innodb-flush-log-at-trx-commit out of range\n");
4925
if (innobase_force_recovery > 6) {
4926
fprintf(stderr, "xtrabackup: innodb-force-recovery out of range\n");
4930
if ((innobase_lock_wait_timeout < 1) || (innobase_lock_wait_timeout > (1024*1024*1024))) {
4931
fprintf(stderr, "xtrabackup: innodb-lock-wait-timeout out of range\n");
4935
innobase_log_buffer_size-= innobase_log_buffer_size % 1024;
4936
if (innobase_additional_mem_pool_size < (256*1024)) {
4937
fprintf(stderr, "xtrabackup: innodb-log-buffer-size out of range\n");
4941
if (innobase_additional_mem_pool_size < (1024*1024)) {
4942
fprintf(stderr, "xtrabackup: innodb-log-file-size out of range\n");
4946
if ((innobase_log_files_in_group < 2) || (innobase_log_files_in_group > (100))) {
4947
fprintf(stderr, "xtrabackup: innodb-log-files-in-group out of range\n");
4951
if (srv_max_buf_pool_modified_pct > 100) {
4952
fprintf(stderr, "xtrabackup: innodb-max-buf-pool-modified-pct out of range\n");
4956
if (innobase_open_files < 10) {
4957
fprintf(stderr, "xtrabackup: innodb-open-files out of range\n");
4961
if ((innobase_page_size < (1 << 12)) || (innobase_page_size > (1 << UNIV_PAGE_SIZE_SHIFT_MAX))) {
4962
fprintf(stderr, "xtrabackup: innodb-page-size out of range\n");
4966
if ((innobase_log_block_size < (512)) || (innobase_log_block_size > (1 << UNIV_PAGE_SIZE_SHIFT_MAX))) {
4967
fprintf(stderr, "xtrabackup: innodb-log-block-size out of range\n");
4971
if (vm.count("datadir"))
4973
mysql_data_home_arg.assign(vm["datadir"].as<std::string>());
4977
mysql_data_home_arg.assign(LOCALSTATEDIR);
4980
mysql_data_home= (char*)malloc(mysql_data_home_arg.length());
4981
strcpy(mysql_data_home, mysql_data_home_arg.c_str());
4983
if ((!xtrabackup_prepare) && (strcmp(mysql_data_home, "./") == 0)) {
4984
if (!xtrabackup_print_param)
4986
printf("\nxtrabackup: Error: Please set parameter 'datadir'\n");
4990
if (xtrabackup_tables) {
4996
tables_regex_num = 1;
4998
p = xtrabackup_tables;
4999
while ((p = strchr(p, ',')) != NULL) {
5004
tables_regex = (regex_t*) ut_malloc(sizeof(regex_t) * tables_regex_num);
5006
p = xtrabackup_tables;
5007
for (i=0; i < tables_regex_num; i++) {
5008
next = strchr(p, ',');
5009
ut_a(next || i == tables_regex_num - 1);
5012
if (i != tables_regex_num - 1)
5015
regerror(regcomp(&tables_regex[i],p,REG_EXTENDED),
5016
&tables_regex[i],errbuf,sizeof(errbuf));
5017
fprintf(stderr, "xtrabackup: tables regcomp(%s): %s\n",p,errbuf);
5019
if (i != tables_regex_num - 1)
5025
if (xtrabackup_tables_file) {
5026
char name_buf[NAME_LEN*2+2];
5029
if (xtrabackup_stream) {
5030
fprintf(stderr, "xtrabackup: Warning: --tables_file option doesn't affect with --stream.\n");
5031
xtrabackup_tables_file = NULL;
5032
goto skip_tables_file_register;
5035
name_buf[NAME_LEN*2+1] = '\0';
5037
/* init tables_hash */
5038
tables_hash = hash_create(1000);
5040
/* read and store the filenames */
5041
fp = fopen(xtrabackup_tables_file,"r");
5043
fprintf(stderr, "xtrabackup: cannot open %s\n", xtrabackup_tables_file);
5047
xtrabackup_tables_t* table;
5050
if ( fgets(name_buf, NAME_LEN*2+1, fp) == 0 ) {
5054
while (*p != '\0') {
5060
p = strchr(name_buf, '\n');
5066
table = (xtrabackup_tables_t*) malloc(sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1);
5067
memset(table, '\0', sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1);
5068
table->name = ((char*)table) + sizeof(xtrabackup_tables_t);
5069
strcpy(table->name, name_buf);
5071
HASH_INSERT(xtrabackup_tables_t, name_hash, tables_hash,
5072
ut_fold_string(table->name), table);
5074
printf("xtrabackup: table '%s' is registerd to the list.\n", table->name);
5077
skip_tables_file_register:
5080
/* temporary setting of enough size */
5081
srv_page_size_shift = UNIV_PAGE_SIZE_SHIFT_MAX;
5082
srv_page_size = UNIV_PAGE_SIZE_MAX;
5083
srv_log_block_size = 512;
5085
if (xtrabackup_backup && xtrabackup_incremental) {
5086
/* direct specification is only for --backup */
5087
/* and the lsn is prior to the other option */
5092
incremental_lsn = strtoll(xtrabackup_incremental, &endchar, 10);
5093
if (*endchar != '\0')
5097
fprintf(stderr, "xtrabackup: value '%s' may be wrong format for incremental option.\n",
5098
xtrabackup_incremental);
5102
/* allocate buffer for incremental backup (4096 pages) */
5103
incremental_buffer_base = (byte*) malloc((UNIV_PAGE_SIZE_MAX / 4 + 1) *
5104
UNIV_PAGE_SIZE_MAX);
5105
incremental_buffer = (byte*) ut_align(incremental_buffer_base,
5106
UNIV_PAGE_SIZE_MAX);
5107
} else if (xtrabackup_backup && xtrabackup_incremental_basedir) {
5108
char filename[FN_REFLEN];
5110
sprintf(filename, "%s/%s", xtrabackup_incremental_basedir, XTRABACKUP_METADATA_FILENAME);
5112
if (xtrabackup_read_metadata(filename)) {
5114
"xtrabackup: error: failed to read metadata from %s\n",
5119
incremental_lsn = metadata_to_lsn;
5120
xtrabackup_incremental = xtrabackup_incremental_basedir; //dummy
5122
/* allocate buffer for incremental backup (4096 pages) */
5123
incremental_buffer_base = (byte*) malloc((UNIV_PAGE_SIZE_MAX / 4 + 1) *
5124
UNIV_PAGE_SIZE_MAX);
5125
incremental_buffer = (byte*) ut_align(incremental_buffer_base,
5126
UNIV_PAGE_SIZE_MAX);
5127
} else if (xtrabackup_prepare && xtrabackup_incremental_dir) {
5128
char filename[FN_REFLEN];
5130
sprintf(filename, "%s/%s", xtrabackup_incremental_dir, XTRABACKUP_METADATA_FILENAME);
5132
if (xtrabackup_read_metadata(filename)) {
5134
"xtrabackup: error: failed to read metadata from %s\n",
5139
incremental_lsn = metadata_from_lsn;
5140
incremental_to_lsn = metadata_to_lsn;
5141
incremental_last_lsn = metadata_last_lsn;
5142
xtrabackup_incremental = xtrabackup_incremental_dir; //dummy
5144
/* allocate buffer for incremental backup (4096 pages) */
5145
incremental_buffer_base = (byte*) malloc((UNIV_PAGE_SIZE / 4 + 1) *
5147
incremental_buffer = (byte*) ut_align(incremental_buffer_base,
5150
/* allocate buffer for applying incremental (for header page only) */
5151
incremental_buffer_base = (byte*) malloc((1 + 1) * UNIV_PAGE_SIZE_MAX);
5152
incremental_buffer = (byte*) ut_align(incremental_buffer_base,
5153
UNIV_PAGE_SIZE_MAX);
5155
xtrabackup_incremental = NULL;
5159
if (xtrabackup_print_param) {
5160
printf("# This MySQL options file was generated by XtraBackup.\n");
5161
printf("[mysqld]\n");
5162
printf("datadir = \"%s\"\n", mysql_data_home);
5163
printf("tmpdir = \"%s\"\n", opt_mysql_tmpdir);
5164
printf("innodb_data_home_dir = \"%s\"\n",
5165
innobase_data_home_dir ? innobase_data_home_dir : mysql_data_home);
5166
printf("innodb_data_file_path = \"%s\"\n",
5167
innobase_data_file_path ? innobase_data_file_path : "ibdata1:10M:autoextend");
5168
printf("innodb_log_group_home_dir = \"%s\"\n",
5169
innobase_log_group_home_dir ? innobase_log_group_home_dir : mysql_data_home);
5170
printf("innodb_log_files_in_group = %ld\n", innobase_log_files_in_group);
5171
printf("innodb_log_file_size = %"PRIu64"\n", (uint64_t)innobase_log_file_size);
5172
printf("innodb_flush_method = \"%s\"\n",
5173
(innobase_unix_file_flush_method != NULL) ?
5174
innobase_unix_file_flush_method : "");
5178
if (!xtrabackup_stream) {
5180
if (xtrabackup_incremental) {
5181
printf("incremental backup from %"PRIu64" is enabled.\n",
5185
if (xtrabackup_backup) {
5186
xtrabackup_suspend_at_end = TRUE;
5187
fprintf(stderr, "xtrabackup: suspend-at-end is enabled.\n");
5191
/* cannot execute both for now */
5195
if (xtrabackup_backup) num++;
5196
if (xtrabackup_stats) num++;
5197
if (xtrabackup_prepare) num++;
5198
if (num != 1) { /* !XOR (for now) */
5205
if (xtrabackup_backup)
5206
xtrabackup_backup_func();
5209
if (xtrabackup_stats)
5210
xtrabackup_stats_func();
5213
if (xtrabackup_prepare)
5214
xtrabackup_prepare_func();
5216
free(incremental_buffer_base);
5218
if (xtrabackup_tables) {
5222
for (i = 0; i < tables_regex_num; i++) {
5223
regfree(&tables_regex[i]);
5225
ut_free(tables_regex);
5228
if (xtrabackup_tables_file) {
5231
/* free the hash elements */
5232
for (i = 0; i < hash_get_n_cells(tables_hash); i++) {
5233
xtrabackup_tables_t* table;
5235
table = (xtrabackup_tables_t*)
5236
HASH_GET_FIRST(tables_hash, i);
5239
xtrabackup_tables_t* prev_table = table;
5241
table = (xtrabackup_tables_t*)
5242
HASH_GET_NEXT(name_hash, prev_table);
5244
HASH_DELETE(xtrabackup_tables_t, name_hash, tables_hash,
5245
ut_fold_string(prev_table->name), prev_table);
5250
/* free tables_hash */
5251
hash_table_free(tables_hash);