~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/xtrabackup/xtrabackup.cc

  • Committer: pcrews
  • Date: 2011-05-24 17:36:24 UTC
  • mfrom: (1099.4.232 drizzle)
  • Revision ID: pcrews@lucid32-20110524173624-mwr1bvq6fa1r01ao
Updated translations + 2011.05.18 tarball tag

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
XtraBackup: The another hot backup tool for InnoDB
 
3
(c) 2009 Percona Inc.
 
4
(C) 2011 Stewart Smith
 
5
Created 3/3/2009 Yasufumi Kinoshita
 
6
 
 
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.
 
10
 
 
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.
 
15
 
 
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
 
19
 
 
20
*******************************************************/
 
21
 
 
22
#ifndef XTRABACKUP_VERSION
 
23
#define XTRABACKUP_VERSION "undefined"
 
24
#endif
 
25
#ifndef XTRABACKUP_REVISION
 
26
#define XTRABACKUP_REVISION "undefined"
 
27
#endif
 
28
 
 
29
#include <config.h>
 
30
#include <string>
 
31
#include <drizzled/internal/my_sys.h>
 
32
#include <drizzled/charset.h>
 
33
#include <drizzled/gettext.h>
 
34
#include <drizzled/constrained_value.h>
 
35
#include <drizzled/configmake.h>
 
36
#include <drizzled/error/level_t.h>
 
37
 
 
38
#include "ha_prototypes.h"
 
39
 //#define XTRABACKUP_TARGET_IS_PLUGIN
 
40
#include <boost/program_options.hpp>
 
41
#include <boost/scoped_ptr.hpp>
 
42
 
 
43
typedef drizzled::charset_info_st CHARSET_INFO;
 
44
 
 
45
#define my_progname "xtrabackup"
 
46
 
 
47
#define MYSQL_VERSION_ID 50507 /* Drizzle is much greater */
 
48
 
 
49
#include <univ.i>
 
50
#include <os0file.h>
 
51
#include <os0thread.h>
 
52
#include <srv0start.h>
 
53
#include <srv0srv.h>
 
54
#include <trx0roll.h>
 
55
#include <trx0trx.h>
 
56
#include <trx0sys.h>
 
57
#include <mtr0mtr.h>
 
58
#include <row0ins.h>
 
59
#include <row0mysql.h>
 
60
#include <row0sel.h>
 
61
#include <row0upd.h>
 
62
#include <log0log.h>
 
63
#include <log0recv.h>
 
64
#include <lock0lock.h>
 
65
#include <dict0crea.h>
 
66
#include <btr0cur.h>
 
67
#include <btr0btr.h>
 
68
#include <btr0sea.h>
 
69
#include <fsp0fsp.h>
 
70
#include <sync0sync.h>
 
71
#include <fil0fil.h>
 
72
#include <trx0xa.h>
 
73
 
 
74
#ifdef INNODB_VERSION_SHORT
 
75
#include <ibuf0ibuf.h>
 
76
#else
 
77
#error ENOCOOL
 
78
#endif
 
79
 
 
80
#define IB_INT64 ib_int64_t
 
81
#define LSN64 ib_uint64_t
 
82
#define MACH_READ_64 mach_read_from_8
 
83
#define MACH_WRITE_64 mach_write_to_8
 
84
#define OS_MUTEX_CREATE() os_mutex_create()
 
85
#define ut_dulint_zero 0
 
86
#define ut_dulint_cmp(A, B) (A > B ? 1 : (A == B ? 0 : -1))
 
87
#define ut_dulint_add(A, B) (A + B)
 
88
#define ut_dulint_minus(A, B) (A - B)
 
89
#define ut_dulint_align_down(A, B) (A & ~((ib_int64_t)B - 1))
 
90
#define ut_dulint_align_up(A, B) ((A + B - 1) & ~((ib_int64_t)B - 1))
 
91
 
 
92
#ifdef __WIN__
 
93
#define SRV_PATH_SEPARATOR      '\\'
 
94
#define SRV_PATH_SEPARATOR_STR  "\\"    
 
95
#else
 
96
#define SRV_PATH_SEPARATOR      '/'
 
97
#define SRV_PATH_SEPARATOR_STR  "/"
 
98
#endif
 
99
 
 
100
#ifndef UNIV_PAGE_SIZE_MAX
 
101
#define UNIV_PAGE_SIZE_MAX UNIV_PAGE_SIZE
 
102
#endif
 
103
#ifndef UNIV_PAGE_SIZE_SHIFT_MAX
 
104
#define UNIV_PAGE_SIZE_SHIFT_MAX UNIV_PAGE_SIZE_SHIFT
 
105
#endif
 
106
 
 
107
using namespace drizzled;
 
108
namespace po=boost::program_options;
 
109
 
 
110
namespace drizzled {
 
111
  bool errmsg_printf (error::level_t, char const *format, ...);
 
112
 
 
113
  bool errmsg_printf (error::level_t, char const *format, ...)
 
114
  {
 
115
    bool rv;
 
116
    va_list args;
 
117
    va_start(args, format);
 
118
    rv= vfprintf(stderr, format, args);
 
119
    va_end(args);
 
120
    fprintf(stderr, "\n");
 
121
    return rv;
 
122
  }
 
123
 
 
124
}
 
125
 
 
126
#include "xtrabackup_api.h"
 
127
 
 
128
 /* prototypes for static functions in original */
 
129
 
 
130
 ulint
 
131
 recv_find_max_checkpoint(
 
132
 /*=====================*/
 
133
                                         /* out: error code or DB_SUCCESS */
 
134
         log_group_t**  max_group,      /* out: max group */
 
135
         ulint*         max_field);     /* out: LOG_CHECKPOINT_1 or
 
136
                                         LOG_CHECKPOINT_2 */
 
137
 
 
138
 
 
139
 void
 
140
 os_file_set_nocache(
 
141
 /*================*/
 
142
         int            fd,             /* in: file descriptor to alter */
 
143
         const char*    file_name,      /* in: used in the diagnostic message */
 
144
         const char*    operation_name);        /* in: used in the diagnostic message,
 
145
                                         we call os_file_set_nocache()
 
146
                                         immediately after opening or creating
 
147
                                         a file, so this is either "open" or
 
148
                                         "create" */
 
149
 
 
150
 #include <fcntl.h>
 
151
 #include <regex.h>
 
152
 
 
153
 #ifdef POSIX_FADV_NORMAL
 
154
 #define USE_POSIX_FADVISE
 
155
 #endif
 
156
 
 
157
 /* ==start === definition at fil0fil.c === */
 
158
 // ##################################################################
 
159
 // NOTE: We should check the following definitions fit to the source.
 
160
 // ##################################################################
 
161
 
 
162
 //Plugin ?
 
163
 /** File node of a tablespace or the log data space */
 
164
 struct fil_node_struct {
 
165
         fil_space_t*   space;  /*!< backpointer to the space where this node
 
166
                                 belongs */
 
167
         char*          name;   /*!< path to the file */
 
168
         ibool          open;   /*!< TRUE if file open */
 
169
         os_file_t      handle; /*!< OS handle to the file, if file open */
 
170
         ibool          is_raw_disk;/*!< TRUE if the 'file' is actually a raw
 
171
                                 device or a raw disk partition */
 
172
         ulint          size;   /*!< size of the file in database pages, 0 if
 
173
                                 not known yet; the possible last incomplete
 
174
                                 megabyte may be ignored if space == 0 */
 
175
         ulint          n_pending;
 
176
                                 /*!< count of pending i/o's on this file;
 
177
                                 closing of the file is not allowed if
 
178
                                 this is > 0 */
 
179
         ulint          n_pending_flushes;
 
180
                                 /*!< count of pending flushes on this file;
 
181
                                 closing of the file is not allowed if
 
182
                                 this is > 0 */
 
183
         ib_int64_t     modification_counter;/*!< when we write to the file we
 
184
                                 increment this by one */
 
185
         ib_int64_t     flush_counter;/*!< up to what
 
186
                                 modification_counter value we have
 
187
                                 flushed the modifications to disk */
 
188
         UT_LIST_NODE_T(fil_node_t) chain;
 
189
                                 /*!< link field for the file chain */
 
190
         UT_LIST_NODE_T(fil_node_t) LRU;
 
191
                                 /*!< link field for the LRU list */
 
192
         ulint          magic_n;/*!< FIL_NODE_MAGIC_N */
 
193
 };
 
194
 
 
195
 struct fil_space_struct {
 
196
         char*          name;   /*!< space name = the path to the first file in
 
197
                                 it */
 
198
         ulint          id;     /*!< space id */
 
199
         ib_int64_t     tablespace_version;
 
200
                                 /*!< in DISCARD/IMPORT this timestamp
 
201
                                 is used to check if we should ignore
 
202
                                 an insert buffer merge request for a
 
203
                                 page because it actually was for the
 
204
                                 previous incarnation of the space */
 
205
         ibool          mark;   /*!< this is set to TRUE at database startup if
 
206
                                 the space corresponds to a table in the InnoDB
 
207
                                 data dictionary; so we can print a warning of
 
208
                                 orphaned tablespaces */
 
209
         ibool          stop_ios;/*!< TRUE if we want to rename the
 
210
                                 .ibd file of tablespace and want to
 
211
                                 stop temporarily posting of new i/o
 
212
                                 requests on the file */
 
213
         ibool          stop_ibuf_merges;
 
214
                                 /*!< we set this TRUE when we start
 
215
                                 deleting a single-table tablespace */
 
216
         ibool          is_being_deleted;
 
217
                                 /*!< this is set to TRUE when we start
 
218
                                 deleting a single-table tablespace and its
 
219
                                 file; when this flag is set no further i/o
 
220
                                 or flush requests can be placed on this space,
 
221
                                 though there may be such requests still being
 
222
                                 processed on this space */
 
223
         ulint          purpose;/*!< FIL_TABLESPACE, FIL_LOG, or
 
224
                                 FIL_ARCH_LOG */
 
225
         UT_LIST_BASE_NODE_T(fil_node_t) chain;
 
226
                                 /*!< base node for the file chain */
 
227
         ulint          size;   /*!< space size in pages; 0 if a single-table
 
228
                                 tablespace whose size we do not know yet;
 
229
                                 last incomplete megabytes in data files may be
 
230
                                 ignored if space == 0 */
 
231
         ulint          flags;  /*!< compressed page size and file format, or 0 */
 
232
         ulint          n_reserved_extents;
 
233
                                 /*!< number of reserved free extents for
 
234
                                 ongoing operations like B-tree page split */
 
235
         ulint          n_pending_flushes; /*!< this is positive when flushing
 
236
                                 the tablespace to disk; dropping of the
 
237
                                 tablespace is forbidden if this is positive */
 
238
         ulint          n_pending_ibuf_merges;/*!< this is positive
 
239
                                 when merging insert buffer entries to
 
240
                                 a page so that we may need to access
 
241
                                 the ibuf bitmap page in the
 
242
                                 tablespade: dropping of the tablespace
 
243
                                 is forbidden if this is positive */
 
244
         hash_node_t    hash;   /*!< hash chain node */
 
245
         hash_node_t    name_hash;/*!< hash chain the name_hash table */
 
246
 #ifndef UNIV_HOTBACKUP
 
247
         rw_lock_t      latch;  /*!< latch protecting the file space storage
 
248
                                 allocation */
 
249
 #endif /* !UNIV_HOTBACKUP */
 
250
         UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
 
251
                                 /*!< list of spaces with at least one unflushed
 
252
                                 file we have written to */
 
253
         ibool          is_in_unflushed_spaces; /*!< TRUE if this space is
 
254
                                 currently in unflushed_spaces */
 
255
 #ifdef XTRADB_BASED
 
256
         ibool          is_corrupt;
 
257
 #endif
 
258
         UT_LIST_NODE_T(fil_space_t) space_list;
 
259
                                 /*!< list of all spaces */
 
260
         ulint          magic_n;/*!< FIL_SPACE_MAGIC_N */
 
261
 };
 
262
 
 
263
 typedef        struct fil_system_struct        fil_system_t;
 
264
 
 
265
 struct fil_system_struct {
 
266
 #ifndef UNIV_HOTBACKUP
 
267
         mutex_t                mutex;          /*!< The mutex protecting the cache */
 
268
 #ifdef XTRADB55
 
269
         mutex_t                file_extend_mutex;
 
270
 #endif
 
271
 #endif /* !UNIV_HOTBACKUP */
 
272
         hash_table_t*  spaces;         /*!< The hash table of spaces in the
 
273
                                         system; they are hashed on the space
 
274
                                         id */
 
275
         hash_table_t*  name_hash;      /*!< hash table based on the space
 
276
                                         name */
 
277
         UT_LIST_BASE_NODE_T(fil_node_t) LRU;
 
278
                                         /*!< base node for the LRU list of the
 
279
                                         most recently used open files with no
 
280
                                         pending i/o's; if we start an i/o on
 
281
                                         the file, we first remove it from this
 
282
                                         list, and return it to the start of
 
283
                                         the list when the i/o ends;
 
284
                                         log files and the system tablespace are
 
285
                                         not put to this list: they are opened
 
286
                                         after the startup, and kept open until
 
287
                                         shutdown */
 
288
         UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
 
289
                                         /*!< base node for the list of those
 
290
                                         tablespaces whose files contain
 
291
                                         unflushed writes; those spaces have
 
292
                                         at least one file node where
 
293
                                         modification_counter > flush_counter */
 
294
         ulint          n_open;         /*!< number of files currently open */
 
295
         ulint          max_n_open;     /*!< n_open is not allowed to exceed
 
296
                                         this */
 
297
         ib_int64_t     modification_counter;/*!< when we write to a file we
 
298
                                         increment this by one */
 
299
         ulint          max_assigned_id;/*!< maximum space id in the existing
 
300
                                         tables, or assigned during the time
 
301
                                         mysqld has been up; at an InnoDB
 
302
                                         startup we scan the data dictionary
 
303
                                         and set here the maximum of the
 
304
                                         space id's of the tables there */
 
305
         ib_int64_t     tablespace_version;
 
306
                                         /*!< a counter which is incremented for
 
307
                                         every space object memory creation;
 
308
                                         every space mem object gets a
 
309
                                         'timestamp' from this; in DISCARD/
 
310
                                         IMPORT this is used to check if we
 
311
                                         should ignore an insert buffer merge
 
312
                                         request */
 
313
         UT_LIST_BASE_NODE_T(fil_space_t) space_list;
 
314
                                         /*!< list of all file spaces */
 
315
 };
 
316
 
 
317
 typedef struct {
 
318
         ulint  page_size;
 
319
 } xb_delta_info_t;
 
320
 
 
321
 extern fil_system_t*   fil_system;
 
322
 
 
323
 /* ==end=== definition  at fil0fil.c === */
 
324
 
 
325
 
 
326
 bool innodb_inited= 0;
 
327
 
 
328
 /* === xtrabackup specific options === */
 
329
 char xtrabackup_real_target_dir[FN_REFLEN] = "./xtrabackup_backupfiles/";
 
330
 const char *xtrabackup_target_dir= xtrabackup_real_target_dir;
 
331
 bool xtrabackup_backup = false;
 
332
 bool xtrabackup_stats = false;
 
333
 bool xtrabackup_prepare = false;
 
334
 bool xtrabackup_print_param = false;
 
335
 
 
336
 bool xtrabackup_export = false;
 
337
 bool xtrabackup_apply_log_only = false;
 
338
 
 
339
 bool xtrabackup_suspend_at_end = false;
 
340
 uint64_t xtrabackup_use_memory = 100*1024*1024L;
 
341
 bool xtrabackup_create_ib_logfile = false;
 
342
 
 
343
 long xtrabackup_throttle = 0; /* 0:unlimited */
 
344
 lint io_ticket;
 
345
 os_event_t wait_throttle = NULL;
 
346
 
 
347
 bool xtrabackup_stream = false;
 
348
const char *xtrabackup_incremental = NULL;
 
349
 LSN64 incremental_lsn;
 
350
 LSN64 incremental_to_lsn;
 
351
 LSN64 incremental_last_lsn;
 
352
 byte* incremental_buffer = NULL;
 
353
 byte* incremental_buffer_base = NULL;
 
354
 
 
355
const char *xtrabackup_incremental_basedir = NULL; /* for --backup */
 
356
const char *xtrabackup_extra_lsndir = NULL; /* for --backup with --extra-lsndir */
 
357
char *xtrabackup_incremental_dir = NULL; /* for --prepare */
 
358
 
 
359
 char *xtrabackup_tables = NULL;
 
360
 int tables_regex_num;
 
361
 regex_t *tables_regex;
 
362
 regmatch_t tables_regmatch[1];
 
363
 
 
364
const char *xtrabackup_tables_file = NULL;
 
365
 hash_table_t* tables_hash;
 
366
 
 
367
 struct xtrabackup_tables_struct{
 
368
         char*          name;
 
369
         hash_node_t    name_hash;
 
370
 };
 
371
 typedef struct xtrabackup_tables_struct        xtrabackup_tables_t;
 
372
 
 
373
 #ifdef XTRADB_BASED
 
374
 static ulint           thread_nr[SRV_MAX_N_IO_THREADS + 6 + 64];
 
375
 static os_thread_id_t  thread_ids[SRV_MAX_N_IO_THREADS + 6 + 64];
 
376
 #else
 
377
 static ulint           thread_nr[SRV_MAX_N_IO_THREADS + 6];
 
378
 static os_thread_id_t  thread_ids[SRV_MAX_N_IO_THREADS + 6];
 
379
 #endif
 
380
 
 
381
 LSN64 checkpoint_lsn_start;
 
382
 LSN64 checkpoint_no_start;
 
383
 LSN64 log_copy_scanned_lsn;
 
384
 IB_INT64 log_copy_offset = 0;
 
385
 ibool log_copying = TRUE;
 
386
 ibool log_copying_running = FALSE;
 
387
 ibool log_copying_succeed = FALSE;
 
388
 
 
389
 ibool xtrabackup_logfile_is_renamed = FALSE;
 
390
 
 
391
 uint parallel;
 
392
 
 
393
 /* === metadata of backup === */
 
394
 #define XTRABACKUP_METADATA_FILENAME "xtrabackup_checkpoints"
 
395
 char metadata_type[30] = ""; /*[full-backuped|full-prepared|incremental]*/
 
396
 
 
397
 ib_uint64_t metadata_from_lsn = 0;
 
398
 ib_uint64_t metadata_to_lsn = 0;
 
399
 ib_uint64_t metadata_last_lsn = 0;
 
400
 
 
401
 #define XB_DELTA_INFO_SUFFIX ".meta"
 
402
 
 
403
 /* === sharing with thread === */
 
404
 os_file_t       dst_log = -1;
 
405
 char            dst_log_path[FN_REFLEN];
 
406
 
 
407
 /* === some variables from mysqld === */
 
408
 char mysql_real_data_home[FN_REFLEN] = "./";
 
409
 char *mysql_data_home= mysql_real_data_home;
 
410
std::string mysql_data_home_arg;
 
411
 static char mysql_data_home_buff[2];
 
412
 
 
413
const char *opt_mysql_tmpdir = NULL;
 
414
 
 
415
/* === static parameters in ha_innodb.cc */
 
416
 
 
417
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
 
418
#define HA_INNOBASE_RANGE_COUNT   100
 
419
 
 
420
ulong   innobase_large_page_size = 0;
 
421
 
 
422
/* The default values for the following, type long or longlong, start-up
 
423
parameters are declared in mysqld.cc: */
 
424
 
 
425
long innobase_additional_mem_pool_size = 1*1024*1024L;
 
426
long innobase_buffer_pool_awe_mem_mb = 0;
 
427
long innobase_file_io_threads = 4;
 
428
long innobase_read_io_threads = 4;
 
429
long innobase_write_io_threads = 4;
 
430
long innobase_force_recovery = 0;
 
431
long innobase_lock_wait_timeout = 50;
 
432
long innobase_log_buffer_size = 1024*1024L;
 
433
long innobase_log_files_in_group = 2;
 
434
long innobase_log_files_in_group_backup;
 
435
long innobase_mirrored_log_groups = 1;
 
436
long innobase_open_files = 300L;
 
437
 
 
438
long innobase_page_size = (1 << 14); /* 16KB */
 
439
static ulong innobase_log_block_size = 512;
 
440
bool innobase_fast_checksum = false;
 
441
bool    innobase_extra_undoslots = false;
 
442
char*   innobase_doublewrite_file = NULL;
 
443
 
 
444
uint64_t innobase_buffer_pool_size = 8*1024*1024L;
 
445
 
 
446
typedef constrained_check<int64_t, INT64_MAX, 1024*1024, 1024*1024> log_file_constraint;
 
447
static log_file_constraint innobase_log_file_size;
 
448
 
 
449
uint64_t innobase_log_file_size_backup;
 
450
 
 
451
/* The default values for the following char* start-up parameters
 
452
are determined in innobase_init below: */
 
453
 
 
454
char*   innobase_data_home_dir                  = NULL;
 
455
const char* innobase_data_file_path             = NULL;
 
456
char*   innobase_log_group_home_dir             = NULL;
 
457
char*   innobase_log_group_home_dir_backup      = NULL;
 
458
char*   innobase_log_arch_dir                   = NULL;/* unused */
 
459
/* The following has a misleading name: starting from 4.0.5, this also
 
460
affects Windows: */
 
461
char*   innobase_unix_file_flush_method         = NULL;
 
462
 
 
463
/* Below we have boolean-valued start-up parameters, and their default
 
464
values */
 
465
 
 
466
ulong   innobase_fast_shutdown                  = 1;
 
467
bool innobase_log_archive                       = FALSE;/* unused */
 
468
bool innobase_use_doublewrite    = TRUE;
 
469
bool innobase_use_checksums      = TRUE;
 
470
bool innobase_use_large_pages    = FALSE;
 
471
bool    innobase_file_per_table                 = FALSE;
 
472
bool innobase_locks_unsafe_for_binlog        = FALSE;
 
473
bool innobase_rollback_on_timeout               = FALSE;
 
474
bool innobase_create_status_file                = FALSE;
 
475
bool innobase_adaptive_hash_index               = TRUE;
 
476
 
 
477
static char *internal_innobase_data_file_path   = NULL;
 
478
 
 
479
/* The following counter is used to convey information to InnoDB
 
480
about server activity: in selects it is not sensible to call
 
481
srv_active_wake_master_thread after each fetch or search, we only do
 
482
it every INNOBASE_WAKE_INTERVAL'th step. */
 
483
 
 
484
#define INNOBASE_WAKE_INTERVAL  32
 
485
ulong   innobase_active_counter = 0;
 
486
 
 
487
UNIV_INTERN
 
488
bool
 
489
innobase_isspace(
 
490
  const void *cs,
 
491
  char char_to_test)
 
492
{
 
493
  return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
 
494
}
 
495
 
 
496
UNIV_INTERN
 
497
void
 
498
innobase_rec_to_mysql(
 
499
        Table*                  ,
 
500
        const rec_t*            ,
 
501
        const dict_index_t*     ,
 
502
        const ulint*            );
 
503
 
 
504
UNIV_INTERN
 
505
void
 
506
innobase_rec_to_mysql(
 
507
/*==================*/
 
508
        Table*                  ,               /*!< in/out: MySQL table */
 
509
        const rec_t*            ,               /*!< in: record */
 
510
        const dict_index_t*     ,               /*!< in: index */
 
511
        const ulint*            )       /*!< in: rec_get_offsets(
 
512
                                                rec, index, ...) */
 
513
{
 
514
  fprintf(stderr, "ERROR: innobase_rec_to_mysql called\n");
 
515
  return;
 
516
}
 
517
 
 
518
UNIV_INTERN
 
519
void
 
520
innobase_rec_reset(Table*);
 
521
 
 
522
UNIV_INTERN
 
523
void
 
524
innobase_rec_reset(
 
525
/*===============*/
 
526
        Table*                  )               /*!< in/out: MySQL table */
 
527
{
 
528
  fprintf(stderr, "ERROR: innobase_rec_reset called\n");
 
529
  return;
 
530
}
 
531
 
 
532
UNIV_INTERN
 
533
void
 
534
thd_set_lock_wait_time(
 
535
/*===================*/
 
536
        drizzled::Session*      ,       /*!< in: thread handle (THD*) */
 
537
        ulint   );      /*!< in: time waited for the lock */
 
538
 
 
539
UNIV_INTERN
 
540
void
 
541
thd_set_lock_wait_time(
 
542
/*===================*/
 
543
        drizzled::Session*      ,       /*!< in: thread handle (THD*) */
 
544
        ulint   )       /*!< in: time waited for the lock */
 
545
{
 
546
  return;
 
547
}
 
548
 
 
549
 
 
550
 
 
551
/* ======== Datafiles iterator ======== */
 
552
typedef struct {
 
553
        fil_system_t *system;
 
554
        fil_space_t  *space;
 
555
        fil_node_t   *node;
 
556
        ibool        started;
 
557
        os_mutex_t   mutex;
 
558
} datafiles_iter_t;
 
559
 
 
560
static
 
561
datafiles_iter_t *
 
562
datafiles_iter_new(fil_system_t *f_system)
 
563
{
 
564
        datafiles_iter_t *it;
 
565
 
 
566
        it = (datafiles_iter_t*) ut_malloc(sizeof(datafiles_iter_t));
 
567
        it->mutex = OS_MUTEX_CREATE();
 
568
 
 
569
        it->system = f_system;
 
570
        it->space = NULL;
 
571
        it->node = NULL;
 
572
        it->started = FALSE;
 
573
 
 
574
        return it;
 
575
}
 
576
 
 
577
static
 
578
fil_node_t *
 
579
datafiles_iter_next(datafiles_iter_t *it, ibool *space_changed)
 
580
{
 
581
        os_mutex_enter(it->mutex);
 
582
 
 
583
        *space_changed = FALSE;
 
584
 
 
585
        if (it->node == NULL) {
 
586
                if (it->started)
 
587
                        goto end;
 
588
                it->started = TRUE;
 
589
        } else {
 
590
                it->node = UT_LIST_GET_NEXT(chain, it->node);
 
591
                if (it->node != NULL)
 
592
                        goto end;
 
593
        }
 
594
 
 
595
        it->space = (it->space == NULL) ?
 
596
                UT_LIST_GET_FIRST(it->system->space_list) :
 
597
                UT_LIST_GET_NEXT(space_list, it->space);
 
598
 
 
599
        while (it->space != NULL &&
 
600
               (it->space->purpose != FIL_TABLESPACE ||
 
601
                UT_LIST_GET_LEN(it->space->chain) == 0))
 
602
                it->space = UT_LIST_GET_NEXT(space_list, it->space);
 
603
        if (it->space == NULL)
 
604
                goto end;
 
605
        *space_changed = TRUE;
 
606
 
 
607
        it->node = UT_LIST_GET_FIRST(it->space->chain);
 
608
 
 
609
end:
 
610
        os_mutex_exit(it->mutex);
 
611
 
 
612
        return it->node;
 
613
}
 
614
 
 
615
static
 
616
void
 
617
datafiles_iter_free(datafiles_iter_t *it)
 
618
{
 
619
        os_mutex_free(it->mutex);
 
620
        ut_free(it);
 
621
}
 
622
 
 
623
/* ======== Date copying thread context ======== */
 
624
 
 
625
typedef struct {
 
626
        datafiles_iter_t        *it;
 
627
        uint                    num;
 
628
        uint                    *count;
 
629
        os_mutex_t              count_mutex;
 
630
        os_thread_id_t          id;
 
631
} data_thread_ctxt_t;
 
632
 
 
633
static void print_version(void)
 
634
{
 
635
  printf("%s  Ver %s Rev %s for %s %s (%s)\n" ,my_progname,
 
636
          XTRABACKUP_VERSION, XTRABACKUP_REVISION, "Drizzle7",
 
637
         TARGET_OS, TARGET_CPU);
 
638
}
 
639
 
 
640
static void usage(void)
 
641
{
 
642
  puts("Open source backup tool for InnoDB and XtraDB\n\
 
643
\n\
 
644
Copyright (C) 2009 Percona Inc.\n\
 
645
\n\
 
646
This program is free software; you can redistribute it and/or\n\
 
647
modify it under the terms of the GNU General Public License\n\
 
648
as published by the Free Software Foundation version 2\n\
 
649
of the License.\n\
 
650
\n\
 
651
This program is distributed in the hope that it will be useful,\n\
 
652
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
 
653
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
 
654
GNU General Public License for more details.\n\
 
655
\n\
 
656
You can download full text of the license on http://www.gnu.org/licenses/gpl-2.0.txt\n");
 
657
 
 
658
  printf("Usage: [%s [--defaults-file=#] --backup | %s [--defaults-file=#] --prepare] [OPTIONS]\n",my_progname,my_progname);
 
659
  // FIXME: print what variables we have
 
660
}
 
661
 
 
662
/* ================ Dummys =================== */
 
663
 
 
664
UNIV_INTERN
 
665
ibool
 
666
thd_is_replication_slave_thread(
 
667
/*============================*/
 
668
  drizzled::Session* ) /*!< in: thread handle (Session*) */
 
669
{
 
670
        fprintf(stderr, "xtrabackup: thd_is_replication_slave_thread() is called\n");
 
671
        return(FALSE);
 
672
}
 
673
 
 
674
UNIV_INTERN
 
675
ibool
 
676
thd_has_edited_nontrans_tables(
 
677
/*===========================*/
 
678
  drizzled::Session *)  /*!< in: thread handle (Session*) */
 
679
{
 
680
        fprintf(stderr, "xtrabackup: thd_has_edited_nontrans_tables() is called\n");
 
681
        return(FALSE);
 
682
}
 
683
 
 
684
UNIV_INTERN
 
685
ibool
 
686
thd_is_select(
 
687
/*==========*/
 
688
  const drizzled::Session *)  /*!< in: thread handle (Session*) */
 
689
{
 
690
        fprintf(stderr, "xtrabackup: thd_is_select() is called\n");
 
691
        return(false);
 
692
}
 
693
 
 
694
UNIV_INTERN
 
695
void
 
696
innobase_mysql_print_thd(
 
697
        FILE*,
 
698
        drizzled::Session*,
 
699
        uint)
 
700
{
 
701
        fprintf(stderr, "xtrabackup: innobase_mysql_print_thd() is called\n");
 
702
}
 
703
 
 
704
void
 
705
innobase_get_cset_width(
 
706
        ulint   cset,
 
707
        ulint*  mbminlen,
 
708
        ulint*  mbmaxlen)
 
709
{
 
710
        CHARSET_INFO*   cs;
 
711
        ut_ad(cset < 256);
 
712
        ut_ad(mbminlen);
 
713
        ut_ad(mbmaxlen);
 
714
 
 
715
        cs = all_charsets[cset];
 
716
        if (cs) {
 
717
                *mbminlen = cs->mbminlen;
 
718
                *mbmaxlen = cs->mbmaxlen;
 
719
        } else {
 
720
                ut_a(cset == 0);
 
721
                *mbminlen = *mbmaxlen = 0;
 
722
        }
 
723
}
 
724
 
 
725
UNIV_INTERN
 
726
void
 
727
innobase_convert_from_table_id(
 
728
/*===========================*/
 
729
  const void*,      /*!< in: the 'from' character set */
 
730
  char*     , /*!< out: converted identifier */
 
731
  const char* , /*!< in: identifier to convert */
 
732
  ulint     )  /*!< in: length of 'to', in bytes */
 
733
{
 
734
        fprintf(stderr, "xtrabackup: innobase_convert_from_table_id() is called\n");
 
735
}
 
736
 
 
737
UNIV_INTERN
 
738
void
 
739
innobase_convert_from_id(
 
740
/*=====================*/
 
741
  const void*,      /*!< in: the 'from' character set */
 
742
  char*     , /*!< out: converted identifier */
 
743
  const char*   , /*!< in: identifier to convert */
 
744
  ulint     )  /*!< in: length of 'to', in bytes */
 
745
{
 
746
        fprintf(stderr, "xtrabackup: innobase_convert_from_id() is called\n");
 
747
}
 
748
 
 
749
int
 
750
innobase_strcasecmp(
 
751
        const char*     a,
 
752
        const char*     b)
 
753
{
 
754
        return(my_strcasecmp(&my_charset_utf8_general_ci, a, b));
 
755
}
 
756
 
 
757
void
 
758
innobase_casedn_str(
 
759
        char*   a)
 
760
{
 
761
        my_casedn_str(&my_charset_utf8_general_ci, a);
 
762
}
 
763
 
 
764
UNIV_INTERN
 
765
const char*
 
766
innobase_get_stmt(
 
767
/*==============*/
 
768
       drizzled::Session *,      /*!< in: MySQL thread handle */
 
769
       size_t* )         /*!< out: length of the SQL statement */
 
770
{
 
771
        fprintf(stderr, "xtrabackup: innobase_get_stmt() is called\n");
 
772
        return("nothing");
 
773
}
 
774
 
 
775
int
 
776
innobase_mysql_tmpfile(void)
 
777
{
 
778
        char    filename[FN_REFLEN];
 
779
        int     fd2 = -1;
 
780
        int     fd = internal::create_temp_file(filename, opt_mysql_tmpdir,
 
781
                                                "ib",
 
782
#ifdef __WIN__
 
783
                                O_BINARY | O_TRUNC | O_SEQUENTIAL |
 
784
                                O_TEMPORARY | O_SHORT_LIVED |
 
785
#endif /* __WIN__ */
 
786
                                O_CREAT | O_EXCL | O_RDWR);
 
787
        if (fd >= 0) {
 
788
#ifndef __WIN__
 
789
                /* On Windows, open files cannot be removed, but files can be
 
790
                created with the O_TEMPORARY flag to the same effect
 
791
                ("delete on close"). */
 
792
                unlink(filename);
 
793
#endif /* !__WIN__ */
 
794
                /* Copy the file descriptor, so that the additional resources
 
795
                allocated by create_temp_file() can be freed by invoking
 
796
                my_close().
 
797
 
 
798
                Because the file descriptor returned by this function
 
799
                will be passed to fdopen(), it will be closed by invoking
 
800
                fclose(), which in turn will invoke close() instead of
 
801
                my_close(). */
 
802
                fd2 = dup(fd);
 
803
                if (fd2 < 0) {
 
804
                        fprintf(stderr, "xtrabackup: Got error %d on dup\n",fd2);
 
805
                }
 
806
                close(fd);
 
807
        }
 
808
        return(fd2);
 
809
}
 
810
 
 
811
void
 
812
innobase_invalidate_query_cache(
 
813
        trx_t*  ,
 
814
        const char*     ,
 
815
        ulint   )
 
816
{
 
817
        /* do nothing */
 
818
}
 
819
 
 
820
/*****************************************************************//**
 
821
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
 
822
and quote it if needed.
 
823
@return pointer to the end of buf */
 
824
static
 
825
char*
 
826
innobase_convert_identifier(
 
827
/*========================*/
 
828
        char*           buf,    /*!< out: buffer for converted identifier */
 
829
        ulint           buflen, /*!< in: length of buf, in bytes */
 
830
        const char*     id,     /*!< in: identifier to convert */
 
831
        ulint           idlen,  /*!< in: length of id, in bytes */
 
832
        void*           ,       /*!< in: MySQL connection thread, or NULL */
 
833
        ibool           )/*!< in: TRUE=id is a table or database name;
 
834
                                FALSE=id is an UTF-8 string */
 
835
{
 
836
        const char*     s       = id;
 
837
        int             q;
 
838
 
 
839
        /* See if the identifier needs to be quoted. */
 
840
        q = '"';
 
841
 
 
842
        if (q == EOF) {
 
843
                if (UNIV_UNLIKELY(idlen > buflen)) {
 
844
                        idlen = buflen;
 
845
                }
 
846
                memcpy(buf, s, idlen);
 
847
                return(buf + idlen);
 
848
        }
 
849
 
 
850
        /* Quote the identifier. */
 
851
        if (buflen < 2) {
 
852
                return(buf);
 
853
        }
 
854
 
 
855
        *buf++ = q;
 
856
        buflen--;
 
857
 
 
858
        for (; idlen; idlen--) {
 
859
                int     c = *s++;
 
860
                if (UNIV_UNLIKELY(c == q)) {
 
861
                        if (UNIV_UNLIKELY(buflen < 3)) {
 
862
                                break;
 
863
                        }
 
864
 
 
865
                        *buf++ = c;
 
866
                        *buf++ = c;
 
867
                        buflen -= 2;
 
868
                } else {
 
869
                        if (UNIV_UNLIKELY(buflen < 2)) {
 
870
                                break;
 
871
                        }
 
872
 
 
873
                        *buf++ = c;
 
874
                        buflen--;
 
875
                }
 
876
        }
 
877
 
 
878
        *buf++ = q;
 
879
        return(buf);
 
880
}
 
881
 
 
882
/*****************************************************************//**
 
883
Convert a table or index name to the MySQL system_charset_info (UTF-8)
 
884
and quote it if needed.
 
885
@return pointer to the end of buf */
 
886
UNIV_INTERN
 
887
char*
 
888
innobase_convert_name(
 
889
/*==================*/
 
890
  char*   buf,  /*!< out: buffer for converted identifier */
 
891
  ulint   buflen, /*!< in: length of buf, in bytes */
 
892
  const char* id, /*!< in: identifier to convert */
 
893
  ulint   idlen,  /*!< in: length of id, in bytes */
 
894
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
 
895
  ibool   table_id)/*!< in: TRUE=id is a table or database name;
 
896
        FALSE=id is an index name */
 
897
{
 
898
        char*           s       = buf;
 
899
        const char*     bufend  = buf + buflen;
 
900
 
 
901
        if (table_id) {
 
902
                const char*     slash = (const char*) memchr(id, '/', idlen);
 
903
                if (!slash) {
 
904
 
 
905
                        goto no_db_name;
 
906
                }
 
907
 
 
908
                /* Print the database name and table name separately. */
 
909
                s = innobase_convert_identifier(s, bufend - s, id, slash - id,
 
910
                                                session, TRUE);
 
911
                if (UNIV_LIKELY(s < bufend)) {
 
912
                        *s++ = '.';
 
913
                        s = innobase_convert_identifier(s, bufend - s,
 
914
                                                        slash + 1, idlen
 
915
                                                        - (slash - id) - 1,
 
916
                                                        session, TRUE);
 
917
                }
 
918
        } else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
 
919
                /* Temporary index name (smart ALTER TABLE) */
 
920
                const char temp_index_suffix[]= "--temporary--";
 
921
 
 
922
                s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
 
923
                                                session, FALSE);
 
924
                if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
 
925
                        memcpy(s, temp_index_suffix,
 
926
                               sizeof temp_index_suffix - 1);
 
927
                        s += sizeof temp_index_suffix - 1;
 
928
                }
 
929
        } else {
 
930
no_db_name:
 
931
                s = innobase_convert_identifier(buf, buflen, id, idlen,
 
932
                                                session, table_id);
 
933
        }
 
934
 
 
935
        return(s);
 
936
 
 
937
}
 
938
 
 
939
ibool
 
940
trx_is_interrupted(
 
941
        trx_t*  )
 
942
{
 
943
        /* There are no mysql_thd */
 
944
        return(FALSE);
 
945
}
 
946
 
 
947
UNIV_INTERN int
 
948
innobase_mysql_cmp(
 
949
/*===============*/
 
950
  int   mysql_type, /*!< in: MySQL type */
 
951
  uint    charset_number, /*!< in: number of the charset */
 
952
  const unsigned char* a,   /*!< in: data field */
 
953
  unsigned int  a_length, /*!< in: data field length,
 
954
          not UNIV_SQL_NULL */
 
955
  const unsigned char* b,   /* in: data field */
 
956
  unsigned int  b_length);  /* in: data field length,
 
957
          not UNIV_SQL_NULL */
 
958
 
 
959
int
 
960
innobase_mysql_cmp(
 
961
/*===============*/
 
962
          /* out: 1, 0, -1, if a is greater, equal, less than b, respectively */
 
963
  int   mysql_type, /* in: MySQL type */
 
964
  uint    charset_number, /* in: number of the charset */
 
965
  const unsigned char* a,   /* in: data field */
 
966
  unsigned int  a_length, /* in: data field length, not UNIV_SQL_NULL */
 
967
  const unsigned char* b,   /* in: data field */
 
968
  unsigned int  b_length) /* in: data field length, not UNIV_SQL_NULL */
 
969
{
 
970
  const CHARSET_INFO* charset;
 
971
  enum_field_types  mysql_tp;
 
972
  int     ret;
 
973
 
 
974
  assert(a_length != UNIV_SQL_NULL);
 
975
  assert(b_length != UNIV_SQL_NULL);
 
976
 
 
977
  mysql_tp = (enum_field_types) mysql_type;
 
978
 
 
979
  switch (mysql_tp) {
 
980
 
 
981
  case DRIZZLE_TYPE_BLOB:
 
982
  case DRIZZLE_TYPE_VARCHAR:
 
983
    /* Use the charset number to pick the right charset struct for
 
984
      the comparison. Since the MySQL function get_charset may be
 
985
      slow before Bar removes the mutex operation there, we first
 
986
      look at 2 common charsets directly. */
 
987
 
 
988
    if (charset_number == default_charset_info->number) {
 
989
      charset = default_charset_info;
 
990
    } else {
 
991
      charset = get_charset(charset_number);
 
992
 
 
993
      if (charset == NULL) {
 
994
        fprintf(stderr, "xtrabackup needs charset %lu for doing "
 
995
                "a comparison, but MySQL cannot "
 
996
                "find that charset.",
 
997
                (ulong) charset_number);
 
998
        ut_a(0);
 
999
      }
 
1000
    }
 
1001
 
 
1002
    /* Starting from 4.1.3, we use strnncollsp() in comparisons of
 
1003
      non-latin1_swedish_ci strings. NOTE that the collation order
 
1004
      changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
 
1005
      having indexes on such data need to rebuild their tables! */
 
1006
 
 
1007
    ret = charset->coll->strnncollsp(charset,
 
1008
                                     a, a_length,
 
1009
                                     b, b_length, 0);
 
1010
    if (ret < 0) {
 
1011
      return(-1);
 
1012
    } else if (ret > 0) {
 
1013
      return(1);
 
1014
    } else {
 
1015
      return(0);
 
1016
    }
 
1017
  default:
 
1018
    ut_error;
 
1019
  }
 
1020
 
 
1021
  return(0);
 
1022
}
 
1023
 
 
1024
ulint
 
1025
innobase_get_at_most_n_mbchars(
 
1026
        ulint charset_id,
 
1027
        ulint prefix_len,
 
1028
        ulint data_len,
 
1029
        const char* str)
 
1030
{
 
1031
        ulint char_length;      /* character length in bytes */
 
1032
        ulint n_chars;          /* number of characters in prefix */
 
1033
        const CHARSET_INFO* charset;    /* charset used in the field */
 
1034
 
 
1035
        charset = get_charset((uint) charset_id);
 
1036
 
 
1037
        ut_ad(charset);
 
1038
        ut_ad(charset->mbmaxlen);
 
1039
 
 
1040
        /* Calculate how many characters at most the prefix index contains */
 
1041
 
 
1042
        n_chars = prefix_len / charset->mbmaxlen;
 
1043
 
 
1044
        /* If the charset is multi-byte, then we must find the length of the
 
1045
        first at most n chars in the string. If the string contains less
 
1046
        characters than n, then we return the length to the end of the last
 
1047
        character. */
 
1048
 
 
1049
        if (charset->mbmaxlen > 1) {
 
1050
                /* my_charpos() returns the byte length of the first n_chars
 
1051
                characters, or a value bigger than the length of str, if
 
1052
                there were not enough full characters in str.
 
1053
 
 
1054
                Why does the code below work:
 
1055
                Suppose that we are looking for n UTF-8 characters.
 
1056
 
 
1057
                1) If the string is long enough, then the prefix contains at
 
1058
                least n complete UTF-8 characters + maybe some extra
 
1059
                characters + an incomplete UTF-8 character. No problem in
 
1060
                this case. The function returns the pointer to the
 
1061
                end of the nth character.
 
1062
 
 
1063
                2) If the string is not long enough, then the string contains
 
1064
                the complete value of a column, that is, only complete UTF-8
 
1065
                characters, and we can store in the column prefix index the
 
1066
                whole string. */
 
1067
 
 
1068
                char_length = my_charpos(charset, str,
 
1069
                                                str + data_len, (int) n_chars);
 
1070
                if (char_length > data_len) {
 
1071
                        char_length = data_len;
 
1072
                }
 
1073
        } else {
 
1074
                if (data_len < prefix_len) {
 
1075
                        char_length = data_len;
 
1076
                } else {
 
1077
                        char_length = prefix_len;
 
1078
                }
 
1079
        }
 
1080
 
 
1081
        return(char_length);
 
1082
}
 
1083
 
 
1084
UNIV_INTERN
 
1085
ulint
 
1086
innobase_raw_format(
 
1087
/*================*/
 
1088
  const char* ,   /*!< in: raw data */
 
1089
  ulint   , /*!< in: raw data length
 
1090
          in bytes */
 
1091
  ulint   ,   /*!< in: charset collation */
 
1092
  char*   ,    /*!< out: output buffer */
 
1093
  ulint   ) /*!< in: output buffer size
 
1094
          in bytes */
 
1095
{
 
1096
        fprintf(stderr, "xtrabackup: innobase_raw_format() is called\n");
 
1097
        return(0);
 
1098
}
 
1099
 
 
1100
UNIV_INTERN
 
1101
ulong
 
1102
thd_lock_wait_timeout(
 
1103
/*==================*/
 
1104
  drizzled::Session*)  /*!< in: thread handle (Session*), or NULL to query
 
1105
      the global innodb_lock_wait_timeout */
 
1106
{
 
1107
        return(innobase_lock_wait_timeout);
 
1108
}
 
1109
 
 
1110
UNIV_INTERN
 
1111
ibool
 
1112
thd_supports_xa(
 
1113
/*============*/
 
1114
  drizzled::Session* )  /*!< in: thread handle (Session*), or NULL to query
 
1115
        the global innodb_supports_xa */
 
1116
{
 
1117
        return(FALSE);
 
1118
}
 
1119
 
 
1120
ibool
 
1121
trx_is_strict(
 
1122
/*==========*/
 
1123
        trx_t*) /*!< in: transaction */
 
1124
{
 
1125
        return(FALSE);
 
1126
}
 
1127
 
 
1128
#ifdef XTRADB_BASED
 
1129
trx_t*
 
1130
innobase_get_trx()
 
1131
{
 
1132
        return(NULL);
 
1133
}
 
1134
 
 
1135
ibool
 
1136
innobase_get_slow_log()
 
1137
{
 
1138
        return(FALSE);
 
1139
}
 
1140
#endif
 
1141
 
 
1142
/***********************************************************************
 
1143
Computes bit shift for a given value. If the argument is not a power
 
1144
of 2, returns 0.*/
 
1145
UNIV_INLINE
 
1146
ulint
 
1147
get_bit_shift(ulint value)
 
1148
{
 
1149
        ulint shift;
 
1150
 
 
1151
        if (value == 0)
 
1152
                return 0;
 
1153
 
 
1154
        for (shift = 0; !(value & 1UL); shift++) {
 
1155
                value >>= 1;
 
1156
        }
 
1157
        return (value >> 1) ? 0 : shift;
 
1158
}
 
1159
 
 
1160
static bool
 
1161
innodb_init_param(void)
 
1162
{
 
1163
        /* innobase_init */
 
1164
        static char     current_dir[3];         /* Set if using current lib */
 
1165
        bool            ret;
 
1166
        char            *default_path;
 
1167
 
 
1168
        /* dummy for initialize all_charsets[] */
 
1169
        get_charset_name(0);
 
1170
 
 
1171
#ifdef XTRADB_BASED
 
1172
        srv_page_size = 0;
 
1173
        srv_page_size_shift = 0;
 
1174
 
 
1175
        if (innobase_page_size != (1 << 14)) {
 
1176
                int n_shift = get_bit_shift(innobase_page_size);
 
1177
 
 
1178
                if (n_shift >= 12 && n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX) {
 
1179
                        fprintf(stderr,
 
1180
                                "InnoDB: Warning: innodb_page_size has been "
 
1181
                                "changed from default value 16384.\n");
 
1182
                        srv_page_size_shift = n_shift;
 
1183
                        srv_page_size = 1 << n_shift;
 
1184
                        fprintf(stderr,
 
1185
                                "InnoDB: The universal page size of the "
 
1186
                                "database is set to %lu.\n", srv_page_size);
 
1187
                } else {
 
1188
                        fprintf(stderr, "InnoDB: Error: invalid value of "
 
1189
                               "innobase_page_size: %lu", innobase_page_size);
 
1190
                        exit(EXIT_FAILURE);
 
1191
                }
 
1192
        } else {
 
1193
                srv_page_size_shift = 14;
 
1194
                srv_page_size = (1 << srv_page_size_shift);
 
1195
        }
 
1196
 
 
1197
        srv_log_block_size = 0;
 
1198
        if (innobase_log_block_size != 512) {
 
1199
                uint    n_shift = get_bit_shift(innobase_log_block_size);;
 
1200
 
 
1201
                fprintf(stderr,
 
1202
                        "InnoDB: Warning: innodb_log_block_size has "
 
1203
                        "been changed from its default value. "
 
1204
                        "(###EXPERIMENTAL### operation)\n");
 
1205
                if (n_shift > 0) {
 
1206
                        srv_log_block_size = (1 << n_shift);
 
1207
                        fprintf(stderr,
 
1208
                                "InnoDB: The log block size is set to %lu.\n",
 
1209
                                srv_log_block_size);
 
1210
                }
 
1211
        } else {
 
1212
                srv_log_block_size = 512;
 
1213
        }
 
1214
 
 
1215
        if (!srv_log_block_size) {
 
1216
                fprintf(stderr,
 
1217
                        "InnoDB: Error: %lu is not valid value for "
 
1218
                        "innodb_log_block_size.\n", innobase_log_block_size);
 
1219
                goto error;
 
1220
        }
 
1221
 
 
1222
        srv_fast_checksum = (ibool) innobase_fast_checksum;
 
1223
#endif
 
1224
 
 
1225
        /* Check that values don't overflow on 32-bit systems. */
 
1226
        if (sizeof(ulint) == 4) {
 
1227
                if (xtrabackup_use_memory > UINT32_MAX) {
 
1228
                        fprintf(stderr,
 
1229
                                "xtrabackup: use-memory can't be over 4GB"
 
1230
                                " on 32-bit systems\n");
 
1231
                }
 
1232
 
 
1233
                if (innobase_buffer_pool_size > UINT32_MAX) {
 
1234
                        fprintf(stderr,
 
1235
                                "xtrabackup: innobase_buffer_pool_size can't be over 4GB"
 
1236
                                " on 32-bit systems\n");
 
1237
 
 
1238
                        goto error;
 
1239
                }
 
1240
 
 
1241
                if (innobase_log_file_size > UINT32_MAX) {
 
1242
                        fprintf(stderr,
 
1243
                                "xtrabackup: innobase_log_file_size can't be over 4GB"
 
1244
                                " on 32-bit systemsi\n");
 
1245
 
 
1246
                        goto error;
 
1247
                }
 
1248
        }
 
1249
 
 
1250
        os_innodb_umask = (ulint)0664;
 
1251
 
 
1252
        /* First calculate the default path for innodb_data_home_dir etc.,
 
1253
        in case the user has not given any value.
 
1254
 
 
1255
        Note that when using the embedded server, the datadirectory is not
 
1256
        necessarily the current directory of this program. */
 
1257
 
 
1258
                /* It's better to use current lib, to keep paths short */
 
1259
                current_dir[0] = FN_CURLIB;
 
1260
                current_dir[1] = FN_LIBCHAR;
 
1261
                current_dir[2] = 0;
 
1262
                default_path = current_dir;
 
1263
 
 
1264
        ut_a(default_path);
 
1265
 
 
1266
        /* Set InnoDB initialization parameters according to the values
 
1267
        read from MySQL .cnf file */
 
1268
 
 
1269
        if (xtrabackup_backup || xtrabackup_stats) {
 
1270
                fprintf(stderr, "xtrabackup: Target instance is assumed as followings.\n");
 
1271
        } else {
 
1272
                fprintf(stderr, "xtrabackup: Temporary instance for recovery is set as followings.\n");
 
1273
        }
 
1274
 
 
1275
        /*--------------- Data files -------------------------*/
 
1276
 
 
1277
        /* The default dir for data files is the datadir of MySQL */
 
1278
 
 
1279
        srv_data_home = ((xtrabackup_backup || xtrabackup_stats) && innobase_data_home_dir
 
1280
                         ? innobase_data_home_dir : default_path);
 
1281
        fprintf(stderr, "xtrabackup:   innodb_data_home_dir = %s\n", srv_data_home);
 
1282
 
 
1283
        /* Set default InnoDB data file size to 10 MB and let it be
 
1284
        auto-extending. Thus users can use InnoDB in >= 4.0 without having
 
1285
        to specify any startup options. */
 
1286
 
 
1287
        if (!innobase_data_file_path) {
 
1288
                innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
 
1289
        }
 
1290
        fprintf(stderr, "xtrabackup:   innodb_data_file_path = %s\n",
 
1291
                innobase_data_file_path);
 
1292
 
 
1293
        /* Since InnoDB edits the argument in the next call, we make another
 
1294
        copy of it: */
 
1295
 
 
1296
        internal_innobase_data_file_path = strdup(innobase_data_file_path);
 
1297
 
 
1298
        ret = (bool) srv_parse_data_file_paths_and_sizes(
 
1299
                        internal_innobase_data_file_path);
 
1300
        if (ret == FALSE) {
 
1301
                fprintf(stderr,
 
1302
                        "xtrabackup: syntax error in innodb_data_file_path\n");
 
1303
mem_free_and_error:
 
1304
                free(internal_innobase_data_file_path);
 
1305
                goto error;
 
1306
        }
 
1307
 
 
1308
        if (xtrabackup_prepare) {
 
1309
                /* "--prepare" needs filenames only */
 
1310
                ulint i;
 
1311
 
 
1312
                for (i=0; i < srv_n_data_files; i++) {
 
1313
                        char *p;
 
1314
 
 
1315
                        p = srv_data_file_names[i];
 
1316
                        while ((p = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
 
1317
                        {
 
1318
                                p++;
 
1319
                                srv_data_file_names[i] = p;
 
1320
                        }
 
1321
                }
 
1322
        }
 
1323
 
 
1324
#ifdef XTRADB_BASED
 
1325
        srv_doublewrite_file = innobase_doublewrite_file;
 
1326
#ifndef XTRADB55
 
1327
        srv_extra_undoslots = (ibool) innobase_extra_undoslots;
 
1328
#endif
 
1329
#endif
 
1330
 
 
1331
        /* -------------- Log files ---------------------------*/
 
1332
 
 
1333
        /* The default dir for log files is the datadir of MySQL */
 
1334
 
 
1335
        if (!((xtrabackup_backup || xtrabackup_stats) && innobase_log_group_home_dir)) {
 
1336
                innobase_log_group_home_dir = default_path;
 
1337
        }
 
1338
        if (xtrabackup_prepare && xtrabackup_incremental_dir) {
 
1339
                innobase_log_group_home_dir = xtrabackup_incremental_dir;
 
1340
        }
 
1341
        fprintf(stderr, "xtrabackup:   innodb_log_group_home_dir = %s\n",
 
1342
                innobase_log_group_home_dir);
 
1343
 
 
1344
#ifdef UNIV_LOG_ARCHIVE
 
1345
        /* Since innodb_log_arch_dir has no relevance under MySQL,
 
1346
        starting from 4.0.6 we always set it the same as
 
1347
        innodb_log_group_home_dir: */
 
1348
 
 
1349
        innobase_log_arch_dir = innobase_log_group_home_dir;
 
1350
 
 
1351
        srv_arch_dir = innobase_log_arch_dir;
 
1352
#endif /* UNIG_LOG_ARCHIVE */
 
1353
 
 
1354
        ret = (bool)
 
1355
                srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
 
1356
 
 
1357
        if (ret == FALSE || innobase_mirrored_log_groups != 1) {
 
1358
          fprintf(stderr, "xtrabackup: syntax error in innodb_log_group_home_dir, or a "
 
1359
                          "wrong number of mirrored log groups\n");
 
1360
 
 
1361
                goto mem_free_and_error;
 
1362
        }
 
1363
 
 
1364
        srv_adaptive_flushing = FALSE;
 
1365
        srv_use_sys_malloc = TRUE;
 
1366
        srv_file_format = 1; /* Barracuda */
 
1367
        srv_max_file_format_at_startup = DICT_TF_FORMAT_51; /* on */
 
1368
 
 
1369
        /* --------------------------------------------------*/
 
1370
 
 
1371
        srv_file_flush_method_str = innobase_unix_file_flush_method;
 
1372
 
 
1373
        srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
 
1374
        srv_n_log_files = (ulint) innobase_log_files_in_group;
 
1375
        srv_log_file_size = (ulint) innobase_log_file_size;
 
1376
        fprintf(stderr, "xtrabackup:   innodb_log_files_in_group = %ld\n",
 
1377
                srv_n_log_files);
 
1378
        fprintf(stderr, "xtrabackup:   innodb_log_file_size = %ld\n",
 
1379
                srv_log_file_size);
 
1380
 
 
1381
#ifdef UNIV_LOG_ARCHIVE
 
1382
        srv_log_archive_on = (ulint) innobase_log_archive;
 
1383
#endif /* UNIV_LOG_ARCHIVE */
 
1384
        srv_log_buffer_size = (ulint) innobase_log_buffer_size;
 
1385
 
 
1386
        /* We set srv_pool_size here in units of 1 kB. InnoDB internally
 
1387
        changes the value so that it becomes the number of database pages. */
 
1388
 
 
1389
        //srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
 
1390
        srv_buf_pool_size = (ulint) xtrabackup_use_memory;
 
1391
 
 
1392
        srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
 
1393
 
 
1394
        srv_n_file_io_threads = (ulint) innobase_file_io_threads;
 
1395
 
 
1396
        srv_n_read_io_threads = (ulint) innobase_read_io_threads;
 
1397
        srv_n_write_io_threads = (ulint) innobase_write_io_threads;
 
1398
 
 
1399
        srv_force_recovery = (ulint) innobase_force_recovery;
 
1400
 
 
1401
        srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
 
1402
        srv_use_checksums = (ibool) innobase_use_checksums;
 
1403
 
 
1404
        btr_search_enabled = innobase_adaptive_hash_index ? true : false;
 
1405
 
 
1406
        os_use_large_pages = (ibool) innobase_use_large_pages;
 
1407
        os_large_page_size = (ulint) innobase_large_page_size;
 
1408
 
 
1409
        row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
 
1410
 
 
1411
        srv_file_per_table = innobase_file_per_table ? true : false;
 
1412
 
 
1413
        srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
 
1414
 
 
1415
        srv_max_n_open_files = (ulint) innobase_open_files;
 
1416
        srv_innodb_status = (ibool) innobase_create_status_file;
 
1417
 
 
1418
        srv_print_verbose_log = 1;
 
1419
 
 
1420
        /* Store the default charset-collation number of this MySQL
 
1421
        installation */
 
1422
 
 
1423
        /* We cannot treat characterset here for now!! */
 
1424
        data_mysql_default_charset_coll = (ulint)default_charset_info->number;
 
1425
 
 
1426
        ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
 
1427
 
 
1428
        //innobase_commit_concurrency_init_default();
 
1429
 
 
1430
        /* Since we in this module access directly the fields of a trx
 
1431
        struct, and due to different headers and flags it might happen that
 
1432
        mutex_t has a different size in this module and in InnoDB
 
1433
        modules, we check at run time that the size is the same in
 
1434
        these compilation modules. */
 
1435
 
 
1436
 
 
1437
        /* On 5.5 srv_use_native_aio is TRUE by default. It is later reset
 
1438
        if it is not supported by the platform in
 
1439
        innobase_start_or_create_for_mysql(). As we don't call it in xtrabackup,
 
1440
        we have to duplicate checks from that function here. */
 
1441
 
 
1442
#ifdef __WIN__
 
1443
        switch (os_get_os_version()) {
 
1444
        case OS_WIN95:
 
1445
        case OS_WIN31:
 
1446
        case OS_WINNT:
 
1447
                /* On Win 95, 98, ME, Win32 subsystem for Windows 3.1,
 
1448
                and NT use simulated aio. In NT Windows provides async i/o,
 
1449
                but when run in conjunction with InnoDB Hot Backup, it seemed
 
1450
                to corrupt the data files. */
 
1451
 
 
1452
                srv_use_native_aio = FALSE;
 
1453
                break;
 
1454
 
 
1455
        case OS_WIN2000:
 
1456
        case OS_WINXP:
 
1457
                /* On 2000 and XP, async IO is available. */
 
1458
                srv_use_native_aio = TRUE;
 
1459
                break;
 
1460
 
 
1461
        default:
 
1462
                /* Vista and later have both async IO and condition variables */
 
1463
                srv_use_native_aio = TRUE;
 
1464
                srv_use_native_conditions = TRUE;
 
1465
                break;
 
1466
        }
 
1467
 
 
1468
#elif defined(LINUX_NATIVE_AIO)
 
1469
 
 
1470
        if (srv_use_native_aio) {
 
1471
                ut_print_timestamp(stderr);
 
1472
                fprintf(stderr,
 
1473
                        " InnoDB: Using Linux native AIO\n");
 
1474
        }
 
1475
#else
 
1476
        /* Currently native AIO is supported only on windows and linux
 
1477
        and that also when the support is compiled in. In all other
 
1478
        cases, we ignore the setting of innodb_use_native_aio. */
 
1479
        srv_use_native_aio = FALSE;
 
1480
 
 
1481
#endif
 
1482
 
 
1483
        return(FALSE);
 
1484
 
 
1485
error:
 
1486
        fprintf(stderr, "xtrabackup: innodb_init_param(): Error occured.\n");
 
1487
        return(TRUE);
 
1488
}
 
1489
 
 
1490
static bool
 
1491
innodb_init(void)
 
1492
{
 
1493
        int     err;
 
1494
 
 
1495
        err = innobase_start_or_create_for_mysql();
 
1496
 
 
1497
        if (err != DB_SUCCESS) {
 
1498
                free(internal_innobase_data_file_path);
 
1499
                goto error;
 
1500
        }
 
1501
 
 
1502
        /* They may not be needed for now */
 
1503
//      (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
 
1504
//                                      (hash_get_key) innobase_get_key, 0, 0);
 
1505
//        pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
 
1506
//        pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
 
1507
//        pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
 
1508
//        pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
 
1509
//        pthread_cond_init(&commit_cond, NULL);
 
1510
 
 
1511
        innodb_inited= 1;
 
1512
 
 
1513
        return(FALSE);
 
1514
 
 
1515
error:
 
1516
        fprintf(stderr, "xtrabackup: innodb_init(): Error occured.\n");
 
1517
        return(TRUE);
 
1518
}
 
1519
 
 
1520
static bool
 
1521
innodb_end(void)
 
1522
{
 
1523
        srv_fast_shutdown = (ulint) innobase_fast_shutdown;
 
1524
        innodb_inited = 0;
 
1525
 
 
1526
        fprintf(stderr, "xtrabackup: starting shutdown with innodb_fast_shutdown = %lu\n",
 
1527
                srv_fast_shutdown);
 
1528
 
 
1529
        if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
 
1530
                goto error;
 
1531
        }
 
1532
        free(internal_innobase_data_file_path);
 
1533
 
 
1534
        /* They may not be needed for now */
 
1535
//      hash_free(&innobase_open_tables);
 
1536
//      pthread_mutex_destroy(&innobase_share_mutex);
 
1537
//      pthread_mutex_destroy(&prepare_commit_mutex);
 
1538
//      pthread_mutex_destroy(&commit_threads_m);
 
1539
//      pthread_mutex_destroy(&commit_cond_m);
 
1540
//      pthread_cond_destroy(&commit_cond);
 
1541
 
 
1542
        return(FALSE);
 
1543
 
 
1544
error:
 
1545
        fprintf(stderr, "xtrabackup: innodb_end(): Error occured.\n");
 
1546
        return(TRUE);
 
1547
}
 
1548
 
 
1549
/* ================= common ================= */
 
1550
static bool
 
1551
xtrabackup_read_metadata(char *filename)
 
1552
{
 
1553
        FILE *fp;
 
1554
 
 
1555
        fp = fopen(filename,"r");
 
1556
        if(!fp) {
 
1557
                fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filename);
 
1558
                return(TRUE);
 
1559
        }
 
1560
 
 
1561
        if (fscanf(fp, "backup_type = %29s\n", metadata_type)
 
1562
                        != 1)
 
1563
                return(TRUE);
 
1564
        if (fscanf(fp, "from_lsn = %"PRIu64"\n", &metadata_from_lsn)
 
1565
                        != 1)
 
1566
                return(TRUE);
 
1567
        if (fscanf(fp, "to_lsn = %"PRIu64"\n", &metadata_to_lsn)
 
1568
                        != 1)
 
1569
                return(TRUE);
 
1570
        if (fscanf(fp, "last_lsn = %"PRIu64"\n", &metadata_last_lsn)
 
1571
                        != 1) {
 
1572
                metadata_last_lsn = 0;
 
1573
        }
 
1574
 
 
1575
        fclose(fp);
 
1576
 
 
1577
        return(FALSE);
 
1578
}
 
1579
 
 
1580
static bool
 
1581
xtrabackup_write_metadata(char *filename)
 
1582
{
 
1583
        FILE *fp;
 
1584
 
 
1585
        fp = fopen(filename,"w");
 
1586
        if(!fp) {
 
1587
                fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filename);
 
1588
                return(TRUE);
 
1589
        }
 
1590
 
 
1591
        if (fprintf(fp, "backup_type = %s\n", metadata_type)
 
1592
                        < 0)
 
1593
                return(TRUE);
 
1594
        if (fprintf(fp, "from_lsn = %"PRIu64"\n", metadata_from_lsn)
 
1595
                        < 0)
 
1596
                return(TRUE);
 
1597
        if (fprintf(fp, "to_lsn = %"PRIu64"\n", metadata_to_lsn)
 
1598
                        < 0)
 
1599
                return(TRUE);
 
1600
        if (fprintf(fp, "last_lsn = %"PRIu64"\n", metadata_last_lsn)
 
1601
                        < 0)
 
1602
                return(TRUE);
 
1603
 
 
1604
        fclose(fp);
 
1605
 
 
1606
        return(FALSE);
 
1607
}
 
1608
 
 
1609
/***********************************************************************
 
1610
Read meta info for an incremental delta.
 
1611
@return TRUE on success, FALSE on failure. */
 
1612
static bool
 
1613
xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info)
 
1614
{
 
1615
        FILE *fp;
 
1616
 
 
1617
        memset(info, 0, sizeof(xb_delta_info_t));
 
1618
 
 
1619
        fp = fopen(filepath, "r");
 
1620
        if (!fp) {
 
1621
                /* Meta files for incremental deltas are optional */
 
1622
                return(TRUE);
 
1623
        }
 
1624
 
 
1625
        if (fscanf(fp, "page_size = %lu\n", &info->page_size) != 1)
 
1626
                return(FALSE);
 
1627
 
 
1628
        fclose(fp);
 
1629
 
 
1630
        return(TRUE);
 
1631
}
 
1632
 
 
1633
/***********************************************************************
 
1634
Write meta info for an incremental delta.
 
1635
@return TRUE on success, FALSE on failure. */
 
1636
static bool
 
1637
xb_write_delta_metadata(const char *filepath, const xb_delta_info_t *info)
 
1638
{
 
1639
        FILE *fp;
 
1640
 
 
1641
        fp = fopen(filepath, "w");
 
1642
        if (!fp) {
 
1643
                fprintf(stderr, "xtrabackup: Error: cannot open %s\n", filepath);
 
1644
                return(FALSE);
 
1645
        }
 
1646
 
 
1647
        if (fprintf(fp, "page_size = %lu\n", info->page_size) < 0)
 
1648
                return(FALSE);
 
1649
 
 
1650
        fclose(fp);
 
1651
 
 
1652
        return(TRUE);
 
1653
}
 
1654
 
 
1655
/* ================= backup ================= */
 
1656
static void
 
1657
xtrabackup_io_throttling(void)
 
1658
{
 
1659
        if (xtrabackup_throttle && (io_ticket--) < 0) {
 
1660
                os_event_reset(wait_throttle);
 
1661
                os_event_wait(wait_throttle);
 
1662
        }
 
1663
}
 
1664
 
 
1665
 
 
1666
/* TODO: We may tune the behavior (e.g. by fil_aio)*/
 
1667
#define COPY_CHUNK 64
 
1668
 
 
1669
static bool
 
1670
xtrabackup_copy_datafile(fil_node_t* node, uint thread_n)
 
1671
{
 
1672
        os_file_t       src_file = -1;
 
1673
        os_file_t       dst_file = -1;
 
1674
        char            dst_path[FN_REFLEN];
 
1675
        char            meta_path[FN_REFLEN];
 
1676
        ibool           success;
 
1677
        byte*           page;
 
1678
        byte*           buf2 = NULL;
 
1679
        IB_INT64        file_size;
 
1680
        IB_INT64        offset;
 
1681
        ulint           page_in_buffer= 0;
 
1682
        ulint           incremental_buffers = 0;
 
1683
        ulint           page_size;
 
1684
        ulint           page_size_shift;
 
1685
        ulint           zip_size;
 
1686
        xb_delta_info_t info;
 
1687
 
 
1688
        info.page_size = 0;
 
1689
 
 
1690
#ifdef XTRADB_BASED
 
1691
        if (xtrabackup_tables && (!trx_sys_sys_space(node->space->id)))
 
1692
#else
 
1693
        if (xtrabackup_tables && (node->space->id != 0))
 
1694
#endif
 
1695
        { /* must backup id==0 */
 
1696
                char *p;
 
1697
                int p_len, regres= 0;
 
1698
                char *next, *prev;
 
1699
                char tmp;
 
1700
                int i;
 
1701
 
 
1702
                p = node->name;
 
1703
                prev = NULL;
 
1704
                while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
 
1705
                {
 
1706
                        prev = p;
 
1707
                        p = next + 1;
 
1708
                }
 
1709
                p_len = strlen(p) - strlen(".ibd");
 
1710
 
 
1711
                if (p_len < 1) {
 
1712
                        /* unknown situation: skip filtering */
 
1713
                        goto skip_filter;
 
1714
                }
 
1715
 
 
1716
                /* TODO: Fix this lazy implementation... */
 
1717
                tmp = p[p_len];
 
1718
                p[p_len] = 0;
 
1719
                *(p - 1) = '.';
 
1720
 
 
1721
                for (i = 0; i < tables_regex_num; i++) {
 
1722
                        regres = regexec(&tables_regex[i], prev, 1, tables_regmatch, 0);
 
1723
                        if (regres != REG_NOMATCH)
 
1724
                                break;
 
1725
                }
 
1726
 
 
1727
                p[p_len] = tmp;
 
1728
                *(p - 1) = SRV_PATH_SEPARATOR;
 
1729
 
 
1730
                if ( regres == REG_NOMATCH ) {
 
1731
                        printf("[%02u] Copying %s is skipped.\n",
 
1732
                               thread_n, node->name);
 
1733
                        return(FALSE);
 
1734
                }
 
1735
        }
 
1736
 
 
1737
#ifdef XTRADB_BASED
 
1738
        if (xtrabackup_tables_file && (!trx_sys_sys_space(node->space->id)))
 
1739
#else
 
1740
        if (xtrabackup_tables_file && (node->space->id != 0))
 
1741
#endif
 
1742
        { /* must backup id==0 */
 
1743
                xtrabackup_tables_t* table;
 
1744
                char *p;
 
1745
                int p_len;
 
1746
                char *next, *prev;
 
1747
                char tmp;
 
1748
 
 
1749
                p = node->name;
 
1750
                prev = NULL;
 
1751
                while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
 
1752
                {
 
1753
                        prev = p;
 
1754
                        p = next + 1;
 
1755
                }
 
1756
                p_len = strlen(p) - strlen(".ibd");
 
1757
 
 
1758
                if (p_len < 1) {
 
1759
                        /* unknown situation: skip filtering */
 
1760
                        goto skip_filter;
 
1761
                }
 
1762
 
 
1763
                /* TODO: Fix this lazy implementation... */
 
1764
                tmp = p[p_len];
 
1765
                p[p_len] = 0;
 
1766
 
 
1767
                HASH_SEARCH(name_hash, tables_hash, ut_fold_string(prev),
 
1768
                            xtrabackup_tables_t*,
 
1769
                            table,
 
1770
                            ut_ad(table->name),
 
1771
                            !strcmp(table->name, prev));
 
1772
 
 
1773
                p[p_len] = tmp;
 
1774
 
 
1775
                if (!table) {
 
1776
                        printf("[%02u] Copying %s is skipped.\n",
 
1777
                               thread_n, node->name);
 
1778
                        return(FALSE);
 
1779
                }
 
1780
        }
 
1781
 
 
1782
skip_filter:
 
1783
        zip_size = fil_space_get_zip_size(node->space->id);
 
1784
        if (zip_size == ULINT_UNDEFINED) {
 
1785
                fprintf(stderr, "[%02u] xtrabackup: Warning: "
 
1786
                        "Failed to determine page size for %s.\n"
 
1787
                        "[%02u] xtrabackup: Warning: We assume the table was "
 
1788
                        "dropped during xtrabackup execution and ignore the "
 
1789
                        "file.\n", thread_n, node->name, thread_n);
 
1790
                goto skip;
 
1791
        } else if (zip_size) {
 
1792
                page_size = zip_size;
 
1793
                page_size_shift = get_bit_shift(page_size);
 
1794
                fprintf(stderr, "[%02u] %s is compressed with page size = "
 
1795
                        "%lu bytes\n", thread_n, node->name, page_size);
 
1796
                if (page_size_shift < 10 || page_size_shift > 14) {
 
1797
                        fprintf(stderr, "[%02u] xtrabackup: Error: Invalid "
 
1798
                                "page size.\n", thread_n);
 
1799
                        ut_error;
 
1800
                }
 
1801
        } else {
 
1802
                page_size = UNIV_PAGE_SIZE;
 
1803
                page_size_shift = UNIV_PAGE_SIZE_SHIFT;
 
1804
        }
 
1805
 
 
1806
#ifdef XTRADB_BASED
 
1807
        if (trx_sys_sys_space(node->space->id))
 
1808
#else
 
1809
        if (node->space->id == 0)
 
1810
#endif
 
1811
        {
 
1812
                char *next, *p;
 
1813
                /* system datafile "/fullpath/datafilename.ibd" or "./datafilename.ibd" */
 
1814
                p = node->name;
 
1815
                while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
 
1816
                {
 
1817
                        p = next + 1;
 
1818
                }
 
1819
                sprintf(dst_path, "%s/%s", xtrabackup_target_dir, p);
 
1820
        } else {
 
1821
                /* file per table style "./database/table.ibd" */
 
1822
                sprintf(dst_path, "%s%s", xtrabackup_target_dir, strstr(node->name, SRV_PATH_SEPARATOR_STR));
 
1823
        }
 
1824
 
 
1825
        if (xtrabackup_incremental) {
 
1826
                snprintf(meta_path, sizeof(meta_path),
 
1827
                         "%s%s", dst_path, XB_DELTA_INFO_SUFFIX);
 
1828
                strcat(dst_path, ".delta");
 
1829
 
 
1830
                /* clear buffer */
 
1831
                bzero(incremental_buffer, (page_size/4) * page_size);
 
1832
                page_in_buffer = 0;
 
1833
                mach_write_to_4(incremental_buffer, 0x78747261UL);/*"xtra"*/
 
1834
                page_in_buffer++;
 
1835
 
 
1836
                info.page_size = page_size;
 
1837
        }
 
1838
 
 
1839
        /* open src_file*/
 
1840
        if (!node->open) {
 
1841
                src_file = os_file_create_simple_no_error_handling(
 
1842
                                                0 /* dummy of innodb_file_data_key */,
 
1843
                                                node->name, OS_FILE_OPEN,
 
1844
                                                OS_FILE_READ_ONLY, &success);
 
1845
                if (!success) {
 
1846
                        /* The following call prints an error message */
 
1847
                        os_file_get_last_error(TRUE);
 
1848
 
 
1849
                        fprintf(stderr,
 
1850
                                "[%02u] xtrabackup: Warning: cannot open %s\n"
 
1851
                                "[%02u] xtrabackup: Warning: We assume the "
 
1852
                                "table was dropped during xtrabackup execution "
 
1853
                                "and ignore the file.\n",
 
1854
                                thread_n, node->name, thread_n);
 
1855
                        goto skip;
 
1856
                }
 
1857
 
 
1858
                if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
 
1859
                        os_file_set_nocache(src_file, node->name, "OPEN");
 
1860
                }
 
1861
        } else {
 
1862
                src_file = node->handle;
 
1863
        }
 
1864
 
 
1865
#ifdef USE_POSIX_FADVISE
 
1866
        posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
 
1867
        posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
 
1868
#endif
 
1869
 
 
1870
        /* open dst_file */
 
1871
        /* os_file_create reads srv_unix_file_flush_method */
 
1872
        dst_file = os_file_create(
 
1873
                        0 /* dummy of innodb_file_data_key */,
 
1874
                        dst_path, OS_FILE_CREATE,
 
1875
                        OS_FILE_NORMAL, OS_DATA_FILE, &success);
 
1876
                if (!success) {
 
1877
                        /* The following call prints an error message */
 
1878
                        os_file_get_last_error(TRUE);
 
1879
 
 
1880
                        fprintf(stderr,"[%02u] xtrabackup: error: "
 
1881
                                "cannot open %s\n", thread_n, dst_path);
 
1882
                        goto error;
 
1883
                }
 
1884
 
 
1885
#ifdef USE_POSIX_FADVISE
 
1886
        posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED);
 
1887
#endif
 
1888
 
 
1889
        /* copy : TODO: tune later */
 
1890
        printf("[%02u] Copying %s \n     to %s\n", thread_n,
 
1891
               node->name, dst_path);
 
1892
 
 
1893
        buf2 = (unsigned char*) ut_malloc(COPY_CHUNK * page_size + UNIV_PAGE_SIZE);
 
1894
        page = (unsigned char*) ut_align(buf2, UNIV_PAGE_SIZE);
 
1895
 
 
1896
        success = os_file_read(src_file, page, 0, 0, UNIV_PAGE_SIZE);
 
1897
        if (!success) {
 
1898
                goto error;
 
1899
        }
 
1900
 
 
1901
        file_size = os_file_get_size_as_iblonglong(src_file);
 
1902
 
 
1903
        for (offset = 0; offset < file_size; offset += COPY_CHUNK * page_size) {
 
1904
                ulint chunk;
 
1905
                ulint chunk_offset;
 
1906
                ulint retry_count = 10;
 
1907
//copy_loop:
 
1908
                if ((ulint)(file_size - offset) > COPY_CHUNK * page_size) {
 
1909
                        chunk = COPY_CHUNK * page_size;
 
1910
                } else {
 
1911
                        chunk = (ulint)(file_size - offset);
 
1912
                }
 
1913
 
 
1914
read_retry:
 
1915
                xtrabackup_io_throttling();
 
1916
 
 
1917
                success = os_file_read(src_file, page,
 
1918
                                (ulint)(offset & 0xFFFFFFFFUL),
 
1919
                                (ulint)(offset >> 32), chunk);
 
1920
                if (!success) {
 
1921
                        goto error;
 
1922
                }
 
1923
 
 
1924
                /* check corruption and retry */
 
1925
                for (chunk_offset = 0; chunk_offset < chunk; chunk_offset += page_size) {
 
1926
                        if (buf_page_is_corrupted(page + chunk_offset, zip_size))
 
1927
                        {
 
1928
                                if (
 
1929
#ifdef XTRADB_BASED
 
1930
                                    trx_sys_sys_space(node->space->id)
 
1931
#else
 
1932
                                    node->space->id == 0
 
1933
#endif
 
1934
                                    && ((offset + (IB_INT64)chunk_offset) >> page_size_shift)
 
1935
                                       >= FSP_EXTENT_SIZE
 
1936
                                    && ((offset + (IB_INT64)chunk_offset) >> page_size_shift)
 
1937
                                       < FSP_EXTENT_SIZE * 3) {
 
1938
                                        /* double write buffer may have old data in the end
 
1939
                                           or it may contain the other format page like COMPRESSED.
 
1940
                                           So, we can pass the check of double write buffer.*/
 
1941
                                        ut_a(page_size == UNIV_PAGE_SIZE);
 
1942
                                        fprintf(stderr, "[%02u] xtrabackup: "
 
1943
                                                "Page %lu seems double write "
 
1944
                                                "buffer. passing the check.\n",
 
1945
                                                thread_n,
 
1946
                                                (ulint)((offset +
 
1947
                                                         (IB_INT64)chunk_offset) >>
 
1948
                                                        page_size_shift));
 
1949
                                } else {
 
1950
                                        retry_count--;
 
1951
                                        if (retry_count == 0) {
 
1952
                                                fprintf(stderr,
 
1953
                                                        "[%02u] xtrabackup: "
 
1954
                                                        "Error: 10 retries "
 
1955
                                                        "resulted in fail. This"
 
1956
                                                        "file seems to be "
 
1957
                                                        "corrupted.\n",
 
1958
                                                        thread_n);
 
1959
                                                goto error;
 
1960
                                        }
 
1961
                                        fprintf(stderr, "[%02u] xtrabackup: "
 
1962
                                                "Database page corruption "
 
1963
                                                "detected at page %lu. "
 
1964
                                                "retrying...\n",
 
1965
                                                thread_n,
 
1966
                                                (ulint)((offset +
 
1967
                                                         (IB_INT64)chunk_offset)
 
1968
                                                        >> page_size_shift));
 
1969
                                        goto read_retry;
 
1970
                                }
 
1971
                        }
 
1972
                }
 
1973
 
 
1974
                if (xtrabackup_incremental) {
 
1975
                        for (chunk_offset = 0; chunk_offset < chunk; chunk_offset += page_size) {
 
1976
                                /* newer page */
 
1977
                                /* This condition may be OK for header, ibuf and fsp */
 
1978
                                if (ut_dulint_cmp(incremental_lsn,
 
1979
                                        MACH_READ_64(page + chunk_offset + FIL_PAGE_LSN)) < 0) {
 
1980
        /* ========================================= */
 
1981
        IB_INT64 offset_on_page;
 
1982
 
 
1983
        if (page_in_buffer == page_size/4) {
 
1984
                /* flush buffer */
 
1985
                success = os_file_write(dst_path, dst_file, incremental_buffer,
 
1986
                        ((incremental_buffers * (page_size/4))
 
1987
                                << page_size_shift) & 0xFFFFFFFFUL,
 
1988
                        (incremental_buffers * (page_size/4))
 
1989
                                >> (32 - page_size_shift),
 
1990
                        page_in_buffer * page_size);
 
1991
                if (!success) {
 
1992
                        goto error;
 
1993
                }
 
1994
 
 
1995
                incremental_buffers++;
 
1996
 
 
1997
                /* clear buffer */
 
1998
                bzero(incremental_buffer, (page_size/4) * page_size);
 
1999
                page_in_buffer = 0;
 
2000
                mach_write_to_4(incremental_buffer, 0x78747261UL);/*"xtra"*/
 
2001
                page_in_buffer++;
 
2002
        }
 
2003
 
 
2004
        offset_on_page = ((offset + (IB_INT64)chunk_offset) >> page_size_shift);
 
2005
        ut_a(offset_on_page >> 32 == 0);
 
2006
 
 
2007
        mach_write_to_4(incremental_buffer + page_in_buffer * 4, (ulint)offset_on_page);
 
2008
        memcpy(incremental_buffer + page_in_buffer * page_size,
 
2009
               page + chunk_offset, page_size);
 
2010
 
 
2011
        page_in_buffer++;
 
2012
        /* ========================================= */
 
2013
                                }
 
2014
                        }
 
2015
                } else {
 
2016
                        success = os_file_write(dst_path, dst_file, page,
 
2017
                                (ulint)(offset & 0xFFFFFFFFUL),
 
2018
                                (ulint)(offset >> 32), chunk);
 
2019
                        if (!success) {
 
2020
                                goto error;
 
2021
                        }
 
2022
                }
 
2023
 
 
2024
        }
 
2025
 
 
2026
        if (xtrabackup_incremental) {
 
2027
                /* termination */
 
2028
                if (page_in_buffer != page_size/4) {
 
2029
                        mach_write_to_4(incremental_buffer + page_in_buffer * 4, 0xFFFFFFFFUL);
 
2030
                }
 
2031
 
 
2032
                mach_write_to_4(incremental_buffer, 0x58545241UL);/*"XTRA"*/
 
2033
 
 
2034
                /* flush buffer */
 
2035
                success = os_file_write(dst_path, dst_file, incremental_buffer,
 
2036
                        ((incremental_buffers * (page_size/4))
 
2037
                                << page_size_shift) & 0xFFFFFFFFUL,
 
2038
                        (incremental_buffers * (page_size/4))
 
2039
                                >> (32 - page_size_shift),
 
2040
                        page_in_buffer * page_size);
 
2041
                if (!success) {
 
2042
                        goto error;
 
2043
                }
 
2044
                if (!xb_write_delta_metadata(meta_path, &info)) {
 
2045
                        fprintf(stderr, "[%02u] xtrabackup: Error: "
 
2046
                                "failed to write meta info for %s\n",
 
2047
                                thread_n, dst_path);
 
2048
                        goto error;
 
2049
                }
 
2050
        }
 
2051
 
 
2052
        success = os_file_flush(dst_file);
 
2053
        if (!success) {
 
2054
                goto error;
 
2055
        }
 
2056
 
 
2057
 
 
2058
        /* check size again */
 
2059
        /* TODO: but is it needed ?? */
 
2060
//      if (file_size < os_file_get_size_as_iblonglong(src_file)) {
 
2061
//              offset -= COPY_CHUNK * page_size;
 
2062
//              file_size = os_file_get_size_as_iblonglong(src_file);
 
2063
//              goto copy_loop;
 
2064
//      }
 
2065
 
 
2066
        /* TODO: How should we treat double_write_buffer here? */
 
2067
        /* (currently, don't care about. Because,
 
2068
            the blocks is newer than the last checkpoint anyway.) */
 
2069
 
 
2070
        /* close */
 
2071
        printf("[%02u]        ...done\n", thread_n);
 
2072
        if (!node->open) {
 
2073
                os_file_close(src_file);
 
2074
        }
 
2075
        os_file_close(dst_file);
 
2076
        ut_free(buf2);
 
2077
        return(FALSE);
 
2078
error:
 
2079
        if (src_file != -1 && !node->open)
 
2080
                os_file_close(src_file);
 
2081
        if (dst_file != -1)
 
2082
                os_file_close(dst_file);
 
2083
        if (buf2)
 
2084
                ut_free(buf2);
 
2085
        fprintf(stderr, "[%02u] xtrabackup: Error: "
 
2086
                "xtrabackup_copy_datafile() failed.\n", thread_n);
 
2087
        return(TRUE); /*ERROR*/
 
2088
 
 
2089
skip:
 
2090
        if (src_file != -1 && !node->open)
 
2091
                os_file_close(src_file);
 
2092
        if (dst_file != -1)
 
2093
                os_file_close(dst_file);
 
2094
        if (buf2)
 
2095
                ut_free(buf2);
 
2096
        fprintf(stderr, "[%02u] xtrabackup: Warning: skipping file %s.\n",
 
2097
                thread_n, node->name);
 
2098
        return(FALSE);
 
2099
}
 
2100
 
 
2101
static bool
 
2102
xtrabackup_copy_logfile(LSN64 from_lsn, bool is_last)
 
2103
{
 
2104
        /* definition from recv_recovery_from_checkpoint_start() */
 
2105
        log_group_t*    group;
 
2106
        LSN64           group_scanned_lsn;
 
2107
        LSN64           contiguous_lsn;
 
2108
 
 
2109
        ibool           success;
 
2110
 
 
2111
        if (!xtrabackup_stream)
 
2112
                ut_a(dst_log != -1);
 
2113
 
 
2114
        /* read from checkpoint_lsn_start to current */
 
2115
        contiguous_lsn = ut_dulint_align_down(from_lsn,
 
2116
                                                OS_FILE_LOG_BLOCK_SIZE);
 
2117
 
 
2118
        /* TODO: We must check the contiguous_lsn still exists in log file.. */
 
2119
 
 
2120
        group = UT_LIST_GET_FIRST(log_sys->log_groups);
 
2121
 
 
2122
        while (group) {
 
2123
                ibool   finished;
 
2124
                LSN64   start_lsn;
 
2125
                LSN64   end_lsn;
 
2126
 
 
2127
 
 
2128
                /* reference recv_group_scan_log_recs() */
 
2129
        finished = FALSE;
 
2130
 
 
2131
        start_lsn = contiguous_lsn;
 
2132
                
 
2133
        while (!finished) {                     
 
2134
                end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE);
 
2135
 
 
2136
                xtrabackup_io_throttling();
 
2137
 
 
2138
                log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
 
2139
                                                group, start_lsn, end_lsn);
 
2140
 
 
2141
                //printf("log read from (%lu %lu) to (%lu %lu)\n",
 
2142
                //      start_lsn.high, start_lsn.low, end_lsn.high, end_lsn.low);
 
2143
 
 
2144
                /* reference recv_scan_log_recs() */
 
2145
                {
 
2146
        byte*   log_block;
 
2147
        ulint   no;
 
2148
        LSN64   scanned_lsn;
 
2149
        ulint   data_len;
 
2150
 
 
2151
        ulint   scanned_checkpoint_no = 0;
 
2152
 
 
2153
        finished = FALSE;
 
2154
        
 
2155
        log_block = log_sys->buf;
 
2156
        scanned_lsn = start_lsn;
 
2157
 
 
2158
        while (log_block < log_sys->buf + RECV_SCAN_SIZE && !finished) {
 
2159
 
 
2160
                no = log_block_get_hdr_no(log_block);
 
2161
 
 
2162
                if (no != log_block_convert_lsn_to_no(scanned_lsn)
 
2163
                    || !log_block_checksum_is_ok_or_old_format(log_block)) {
 
2164
 
 
2165
                        if (no > log_block_convert_lsn_to_no(scanned_lsn)
 
2166
                            && log_block_checksum_is_ok_or_old_format(log_block)) {
 
2167
                                fprintf(stderr,
 
2168
">> ###Warning###: The copying transaction log migh be overtaken already by the target.\n"
 
2169
">>              : Waiting log block no %lu, but the bumber is already %lu.\n"
 
2170
">>              : If the number equals %lu + n * %lu, it should be overtaken already.\n",
 
2171
                                        (ulong) log_block_convert_lsn_to_no(scanned_lsn),
 
2172
                                        (ulong) no,
 
2173
                                        (ulong) log_block_convert_lsn_to_no(scanned_lsn),
 
2174
                                        (ulong) (log_block_convert_lsn_to_no(
 
2175
                                                         log_group_get_capacity(group)
 
2176
                                                                          ) - 1));
 
2177
 
 
2178
                        } else if (no == log_block_convert_lsn_to_no(scanned_lsn)
 
2179
                            && !log_block_checksum_is_ok_or_old_format(
 
2180
                                                                log_block)) {
 
2181
                                fprintf(stderr,
 
2182
"xtrabackup: Log block no %lu at lsn %"PRIu64" has\n"
 
2183
"xtrabackup: ok header, but checksum field contains %lu, should be %lu\n",
 
2184
                                (ulong) no,
 
2185
                                scanned_lsn,
 
2186
                                (ulong) log_block_get_checksum(log_block),
 
2187
                                (ulong) log_block_calc_checksum(log_block));
 
2188
                        }
 
2189
 
 
2190
                        /* Garbage or an incompletely written log block */
 
2191
 
 
2192
                        finished = TRUE;
 
2193
 
 
2194
                        break;
 
2195
                }
 
2196
 
 
2197
                if (log_block_get_flush_bit(log_block)) {
 
2198
                        /* This block was a start of a log flush operation:
 
2199
                        we know that the previous flush operation must have
 
2200
                        been completed for all log groups before this block
 
2201
                        can have been flushed to any of the groups. Therefore,
 
2202
                        we know that log data is contiguous up to scanned_lsn
 
2203
                        in all non-corrupt log groups. */
 
2204
 
 
2205
                        if (ut_dulint_cmp(scanned_lsn, contiguous_lsn) > 0) {
 
2206
                                contiguous_lsn = scanned_lsn;
 
2207
                        }
 
2208
                }
 
2209
 
 
2210
                data_len = log_block_get_data_len(log_block);
 
2211
 
 
2212
                if (
 
2213
                    (scanned_checkpoint_no > 0)
 
2214
                    && (log_block_get_checkpoint_no(log_block)
 
2215
                       < scanned_checkpoint_no)
 
2216
                    && (scanned_checkpoint_no
 
2217
                        - log_block_get_checkpoint_no(log_block)
 
2218
                        > 0x80000000UL)) {
 
2219
 
 
2220
                        /* Garbage from a log buffer flush which was made
 
2221
                        before the most recent database recovery */
 
2222
 
 
2223
                        finished = TRUE;
 
2224
                        break;
 
2225
                }                   
 
2226
 
 
2227
                scanned_lsn = ut_dulint_add(scanned_lsn, data_len);
 
2228
                scanned_checkpoint_no = log_block_get_checkpoint_no(log_block);
 
2229
 
 
2230
                if (data_len < OS_FILE_LOG_BLOCK_SIZE) {
 
2231
                        /* Log data for this group ends here */
 
2232
 
 
2233
                        finished = TRUE;
 
2234
                } else {
 
2235
                        log_block += OS_FILE_LOG_BLOCK_SIZE;
 
2236
                }
 
2237
        } /* while (log_block < log_sys->buf + RECV_SCAN_SIZE && !finished) */
 
2238
 
 
2239
        group_scanned_lsn = scanned_lsn;
 
2240
 
 
2241
 
 
2242
 
 
2243
                }
 
2244
 
 
2245
                /* ===== write log to 'xtrabackup_logfile' ====== */
 
2246
                {
 
2247
                ulint write_size;
 
2248
 
 
2249
                if (!finished) {
 
2250
                        write_size = RECV_SCAN_SIZE;
 
2251
                } else {
 
2252
                        write_size = ut_dulint_minus(
 
2253
                                        ut_dulint_align_up(group_scanned_lsn, OS_FILE_LOG_BLOCK_SIZE),
 
2254
                                        start_lsn);
 
2255
                }
 
2256
 
 
2257
                //printf("Wrinting offset= %lld, size= %lu\n", log_copy_offset, write_size);
 
2258
 
 
2259
                if (!xtrabackup_stream) {
 
2260
                        success = os_file_write(dst_log_path, dst_log, log_sys->buf,
 
2261
                                        (ulint)(log_copy_offset & 0xFFFFFFFFUL),
 
2262
                                        (ulint)(log_copy_offset >> 32), write_size);
 
2263
                } else {
 
2264
                        ulint ret;
 
2265
                        ulint stdout_write_size = write_size;
 
2266
                        if (finished && !is_last
 
2267
                            && group_scanned_lsn % OS_FILE_LOG_BLOCK_SIZE
 
2268
                           )
 
2269
                                stdout_write_size -= OS_FILE_LOG_BLOCK_SIZE;
 
2270
                        if (stdout_write_size) {
 
2271
                                ret = write(fileno(stdout), log_sys->buf, stdout_write_size);
 
2272
                                if (ret == stdout_write_size) {
 
2273
                                        success = TRUE;
 
2274
                                } else {
 
2275
                                        fprintf(stderr, "write: %lu > %lu\n", stdout_write_size, ret);
 
2276
                                        success = FALSE;
 
2277
                                }
 
2278
                        } else {
 
2279
                                success = TRUE; /* do nothing */
 
2280
                        }
 
2281
                }
 
2282
 
 
2283
                log_copy_offset += write_size;
 
2284
 
 
2285
                if (finished && group_scanned_lsn % OS_FILE_LOG_BLOCK_SIZE)
 
2286
                {
 
2287
                        /* if continue, it will start from align_down(group_scanned_lsn) */
 
2288
                        log_copy_offset -= OS_FILE_LOG_BLOCK_SIZE;
 
2289
                }
 
2290
 
 
2291
                if(!success) {
 
2292
                        if (!xtrabackup_stream) {
 
2293
                                fprintf(stderr, "xtrabackup: Error: os_file_write to %s\n", dst_log_path);
 
2294
                        } else {
 
2295
                                fprintf(stderr, "xtrabackup: Error: write to stdout\n");
 
2296
                        }
 
2297
                        goto error;
 
2298
                }
 
2299
 
 
2300
 
 
2301
                }
 
2302
 
 
2303
 
 
2304
 
 
2305
 
 
2306
 
 
2307
                start_lsn = end_lsn;
 
2308
        }
 
2309
 
 
2310
 
 
2311
 
 
2312
                group->scanned_lsn = group_scanned_lsn;
 
2313
                
 
2314
 
 
2315
                fprintf(stderr, ">> log scanned up to (%"PRIu64")\n",group->scanned_lsn);
 
2316
 
 
2317
                group = UT_LIST_GET_NEXT(log_groups, group);
 
2318
 
 
2319
                /* update global variable*/
 
2320
                log_copy_scanned_lsn = group_scanned_lsn;
 
2321
 
 
2322
                /* innodb_mirrored_log_groups must be 1, no other groups */
 
2323
                ut_a(group == NULL);
 
2324
        }
 
2325
 
 
2326
 
 
2327
        if (!xtrabackup_stream) {
 
2328
                success = os_file_flush(dst_log);
 
2329
        } else {
 
2330
                fflush(stdout);
 
2331
                success = TRUE;
 
2332
        }
 
2333
 
 
2334
        if(!success) {
 
2335
                goto error;
 
2336
        }
 
2337
 
 
2338
        return(FALSE);
 
2339
 
 
2340
error:
 
2341
        if (!xtrabackup_stream)
 
2342
                os_file_close(dst_log);
 
2343
        fprintf(stderr, "xtrabackup: Error: xtrabackup_copy_logfile() failed.\n");
 
2344
        return(TRUE);
 
2345
}
 
2346
 
 
2347
/* copying logfile in background */
 
2348
#define SLEEPING_PERIOD 5
 
2349
 
 
2350
static
 
2351
#ifndef __WIN__
 
2352
void*
 
2353
#else
 
2354
ulint
 
2355
#endif
 
2356
log_copying_thread(
 
2357
        void*   )
 
2358
{
 
2359
        ulint   counter = 0;
 
2360
 
 
2361
        if (!xtrabackup_stream)
 
2362
                ut_a(dst_log != -1);
 
2363
 
 
2364
        log_copying_running = TRUE;
 
2365
 
 
2366
        while(log_copying) {
 
2367
                os_thread_sleep(200000); /*0.2 sec*/
 
2368
 
 
2369
                counter++;
 
2370
                if(counter >= SLEEPING_PERIOD * 5) {
 
2371
                        if(xtrabackup_copy_logfile(log_copy_scanned_lsn, FALSE))
 
2372
                                goto end;
 
2373
                        counter = 0;
 
2374
                }
 
2375
        }
 
2376
 
 
2377
        /* last copying */
 
2378
        if(xtrabackup_copy_logfile(log_copy_scanned_lsn, TRUE))
 
2379
                goto end;
 
2380
 
 
2381
        log_copying_succeed = TRUE;
 
2382
end:
 
2383
        log_copying_running = FALSE;
 
2384
        os_thread_exit(NULL);
 
2385
 
 
2386
        return(0);
 
2387
}
 
2388
 
 
2389
/* io throttle watching (rough) */
 
2390
static
 
2391
#ifndef __WIN__
 
2392
void*
 
2393
#else
 
2394
ulint
 
2395
#endif
 
2396
io_watching_thread(
 
2397
        void*   )
 
2398
{
 
2399
        /* currently, for --backup only */
 
2400
        ut_a(xtrabackup_backup);
 
2401
 
 
2402
        while (log_copying) {
 
2403
                os_thread_sleep(1000000); /*1 sec*/
 
2404
 
 
2405
                //for DEBUG
 
2406
                //if (io_ticket == xtrabackup_throttle) {
 
2407
                //      fprintf(stderr, "There seem to be no IO...?\n");
 
2408
                //}
 
2409
 
 
2410
                io_ticket = xtrabackup_throttle;
 
2411
                os_event_set(wait_throttle);
 
2412
        }
 
2413
 
 
2414
        /* stop io throttle */
 
2415
        xtrabackup_throttle = 0;
 
2416
        os_event_set(wait_throttle);
 
2417
 
 
2418
        os_thread_exit(NULL);
 
2419
 
 
2420
        return(0);
 
2421
}
 
2422
 
 
2423
/************************************************************************
 
2424
I/o-handler thread function. */
 
2425
static
 
2426
 
 
2427
#ifndef __WIN__
 
2428
void*
 
2429
#else
 
2430
ulint
 
2431
#endif
 
2432
io_handler_thread(
 
2433
/*==============*/
 
2434
        void*   arg)
 
2435
{
 
2436
        ulint   segment;
 
2437
        ulint   i;
 
2438
        
 
2439
        segment = *((ulint*)arg);
 
2440
 
 
2441
        for (i = 0;; i++) {
 
2442
                fil_aio_wait(segment);
 
2443
        }
 
2444
 
 
2445
        /* We count the number of threads in os_thread_exit(). A created
 
2446
        thread should always use that to exit and not use return() to exit.
 
2447
        The thread actually never comes here because it is exited in an
 
2448
        os_event_wait(). */
 
2449
 
 
2450
        os_thread_exit(NULL);
 
2451
 
 
2452
#ifndef __WIN__
 
2453
        return(NULL);                           /* Not reached */
 
2454
#else
 
2455
        return(0);
 
2456
#endif
 
2457
}
 
2458
 
 
2459
/***************************************************************************
 
2460
Creates an output directory for a given tablespace, if it does not exist */
 
2461
static
 
2462
int
 
2463
xtrabackup_create_output_dir(
 
2464
/*==========================*/
 
2465
                                /* out: 0 if succes, -1 if failure */
 
2466
        fil_space_t *space)     /* in: tablespace */
 
2467
{
 
2468
        char    path[FN_REFLEN];
 
2469
        char    *ptr1, *ptr2;
 
2470
 
 
2471
        /* mkdir if not exist */
 
2472
        ptr1 = strstr(space->name, SRV_PATH_SEPARATOR_STR);
 
2473
        if (ptr1) {
 
2474
                ptr2 = strstr(ptr1 + 1, SRV_PATH_SEPARATOR_STR);
 
2475
        } else {
 
2476
                ptr2 = NULL;
 
2477
        }
 
2478
#ifdef XTRADB_BASED
 
2479
        if(!trx_sys_sys_space(space->id) && ptr2)
 
2480
#else
 
2481
        if(space->id && ptr2)
 
2482
#endif
 
2483
        {
 
2484
                /* single table space */
 
2485
                *ptr2 = 0; /* temporary (it's my lazy..)*/
 
2486
                snprintf(path, sizeof(path), "%s%s", xtrabackup_target_dir,
 
2487
                         ptr1);
 
2488
                *ptr2 = SRV_PATH_SEPARATOR;
 
2489
 
 
2490
                if (mkdir(path, 0777) != 0 && errno != EEXIST) {
 
2491
                        fprintf(stderr,
 
2492
                                "xtrabackup: Error: cannot mkdir %d: %s\n",
 
2493
                                errno, path);
 
2494
                        return -1;
 
2495
                }
 
2496
        }
 
2497
        return 0;
 
2498
}
 
2499
 
 
2500
/**************************************************************************
 
2501
Datafiles copying thread.*/
 
2502
static
 
2503
os_thread_ret_t
 
2504
data_copy_thread_func(
 
2505
/*==================*/
 
2506
        void *arg) /* thread context */
 
2507
{
 
2508
        data_thread_ctxt_t      *ctxt = (data_thread_ctxt_t *) arg;
 
2509
        uint                    num = ctxt->num;
 
2510
        fil_space_t*            space;
 
2511
        ibool                   space_changed;
 
2512
        fil_node_t*             node;
 
2513
 
 
2514
        while ((node = datafiles_iter_next(ctxt->it, &space_changed)) != NULL) {
 
2515
                space = node->space;
 
2516
 
 
2517
                if (space_changed && xtrabackup_create_output_dir(space))
 
2518
                        exit(EXIT_FAILURE);
 
2519
 
 
2520
                /* copy the datafile */
 
2521
                if(xtrabackup_copy_datafile(node, num)) {
 
2522
                        fprintf(stderr, "[%02u] xtrabackup: Error: "
 
2523
                                "failed to copy datafile.\n",
 
2524
                                num);
 
2525
                        exit(EXIT_FAILURE);
 
2526
                }
 
2527
        }
 
2528
 
 
2529
        os_mutex_enter(ctxt->count_mutex);
 
2530
        (*ctxt->count)--;
 
2531
        os_mutex_exit(ctxt->count_mutex);
 
2532
 
 
2533
        os_thread_exit(NULL);
 
2534
        OS_THREAD_DUMMY_RETURN;
 
2535
}
 
2536
 
 
2537
/* CAUTION(?): Don't rename file_per_table during backup */
 
2538
static void
 
2539
xtrabackup_backup_func(void)
 
2540
{
 
2541
        struct stat stat_info;
 
2542
        LSN64 latest_cp;
 
2543
 
 
2544
#ifdef USE_POSIX_FADVISE
 
2545
        fprintf(stderr, "xtrabackup: uses posix_fadvise().\n");
 
2546
#endif
 
2547
 
 
2548
        /* cd to datadir */
 
2549
 
 
2550
        if (chdir(mysql_real_data_home) != 0)
 
2551
        {
 
2552
                fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", mysql_real_data_home);
 
2553
                exit(EXIT_FAILURE);
 
2554
        }
 
2555
        fprintf(stderr, "xtrabackup: cd to %s\n", mysql_real_data_home);
 
2556
 
 
2557
        mysql_data_home= mysql_data_home_buff;
 
2558
        mysql_data_home[0]=FN_CURLIB;           // all paths are relative from here
 
2559
        mysql_data_home[1]=0;
 
2560
 
 
2561
        /* set read only */
 
2562
        srv_read_only = TRUE;
 
2563
 
 
2564
        /* initialize components */
 
2565
        if(innodb_init_param())
 
2566
                exit(EXIT_FAILURE);
 
2567
 
 
2568
        if (srv_file_flush_method_str == NULL) {
 
2569
                /* These are the default options */
 
2570
                srv_unix_file_flush_method = SRV_UNIX_FSYNC;
 
2571
 
 
2572
                srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
 
2573
#ifndef __WIN__        
 
2574
        } else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) {
 
2575
                srv_unix_file_flush_method = SRV_UNIX_FSYNC;
 
2576
 
 
2577
        } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
 
2578
                srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
 
2579
 
 
2580
        } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) {
 
2581
                srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
 
2582
                fprintf(stderr,"xtrabackup: use O_DIRECT\n");
 
2583
        } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) {
 
2584
                srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
 
2585
 
 
2586
        } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
 
2587
                srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
 
2588
#else
 
2589
        } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
 
2590
                srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
 
2591
                os_aio_use_native_aio = FALSE;
 
2592
 
 
2593
        } else if (0 == ut_strcmp(srv_file_flush_method_str, "unbuffered")) {
 
2594
                srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
 
2595
                os_aio_use_native_aio = FALSE;
 
2596
 
 
2597
        } else if (0 == ut_strcmp(srv_file_flush_method_str,
 
2598
                                                        "async_unbuffered")) {
 
2599
                srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;      
 
2600
#endif
 
2601
        } else {
 
2602
                fprintf(stderr, 
 
2603
                "xtrabackup: Unrecognized value %s for innodb_flush_method\n",
 
2604
                                        srv_file_flush_method_str);
 
2605
                exit(EXIT_FAILURE);
 
2606
        }
 
2607
 
 
2608
        if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
 
2609
                                  /* Here we still have srv_pool_size counted
 
2610
                                  in kilobytes (in 4.0 this was in bytes)
 
2611
                                  srv_boot() converts the value to
 
2612
                                  pages; if buffer pool is less than 1000 MB,
 
2613
                                  assume fewer threads. */
 
2614
                srv_max_n_threads = 50000;
 
2615
 
 
2616
 
 
2617
        } else if (srv_buf_pool_size >= 8 * 1024 * 1024) {
 
2618
 
 
2619
                srv_max_n_threads = 10000;
 
2620
        } else {
 
2621
                srv_max_n_threads = 1000;       /* saves several MB of memory,
 
2622
                                                especially in 64-bit
 
2623
                                                computers */
 
2624
        }
 
2625
 
 
2626
        {
 
2627
        ulint   nr;
 
2628
        ulint   i;
 
2629
 
 
2630
        nr = srv_n_data_files;
 
2631
        
 
2632
        for (i = 0; i < nr; i++) {
 
2633
                srv_data_file_sizes[i] = srv_data_file_sizes[i]
 
2634
                                        * ((1024 * 1024) / UNIV_PAGE_SIZE);
 
2635
        }               
 
2636
 
 
2637
        srv_last_file_size_max = srv_last_file_size_max
 
2638
                                        * ((1024 * 1024) / UNIV_PAGE_SIZE);
 
2639
                
 
2640
        srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE;
 
2641
 
 
2642
        srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
 
2643
 
 
2644
        srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
 
2645
        }
 
2646
 
 
2647
        os_sync_mutex = NULL;
 
2648
        srv_general_init();
 
2649
 
 
2650
        {
 
2651
        ibool   create_new_db;
 
2652
#ifdef XTRADB_BASED
 
2653
        ibool   create_new_doublewrite_file;
 
2654
#endif
 
2655
        ibool   log_file_created;
 
2656
        ibool   log_created     = FALSE;
 
2657
        ibool   log_opened      = FALSE;
 
2658
        LSN64   min_flushed_lsn;
 
2659
        LSN64   max_flushed_lsn;
 
2660
        ulint   sum_of_new_sizes;
 
2661
        ulint   err;
 
2662
        ulint   i;
 
2663
 
 
2664
 
 
2665
 
 
2666
 
 
2667
#define SRV_N_PENDING_IOS_PER_THREAD    OS_AIO_N_PENDING_IOS_PER_THREAD
 
2668
#define SRV_MAX_N_PENDING_SYNC_IOS      100
 
2669
 
 
2670
        srv_n_file_io_threads = 2 + srv_n_read_io_threads + srv_n_write_io_threads;
 
2671
 
 
2672
        os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD,
 
2673
                    srv_n_read_io_threads,
 
2674
                    srv_n_write_io_threads,
 
2675
                    SRV_MAX_N_PENDING_SYNC_IOS);
 
2676
 
 
2677
        fil_init(srv_file_per_table ? 50000 : 5000,
 
2678
                 srv_max_n_open_files);
 
2679
 
 
2680
        fsp_init();
 
2681
        log_init();
 
2682
 
 
2683
        lock_sys_create(srv_lock_table_size);
 
2684
 
 
2685
        for (i = 0; i < srv_n_file_io_threads; i++) {
 
2686
                thread_nr[i] = i;
 
2687
 
 
2688
                os_thread_create(io_handler_thread, thread_nr + i, thread_ids + i);
 
2689
        }
 
2690
 
 
2691
        os_thread_sleep(200000); /*0.2 sec*/
 
2692
 
 
2693
        err = open_or_create_data_files(&create_new_db,
 
2694
#ifdef XTRADB_BASED
 
2695
                                        &create_new_doublewrite_file,
 
2696
#endif
 
2697
                                        &min_flushed_lsn, &max_flushed_lsn,
 
2698
                                        &sum_of_new_sizes);
 
2699
        if (err != DB_SUCCESS) {
 
2700
                fprintf(stderr,
 
2701
"xtrabackup: Could not open or create data files.\n"
 
2702
"xtrabackup: If you tried to add new data files, and it failed here,\n"
 
2703
"xtrabackup: you should now edit innodb_data_file_path in my.cnf back\n"
 
2704
"xtrabackup: to what it was, and remove the new ibdata files InnoDB created\n"
 
2705
"xtrabackup: in this failed attempt. InnoDB only wrote those files full of\n"
 
2706
"xtrabackup: zeros, but did not yet use them in any way. But be careful: do not\n"
 
2707
"xtrabackup: remove old data files which contain your precious data!\n");
 
2708
 
 
2709
                //return((int) err);
 
2710
                exit(EXIT_FAILURE);
 
2711
        }
 
2712
 
 
2713
        /* create_new_db must not be TRUE.. */
 
2714
        if (create_new_db) {
 
2715
                fprintf(stderr, "xtrabackup: Something wrong with source files...\n");
 
2716
                exit(EXIT_FAILURE);
 
2717
        }
 
2718
 
 
2719
        for (i = 0; i < srv_n_log_files; i++) {
 
2720
                err = open_or_create_log_file(create_new_db, &log_file_created,
 
2721
                                                             log_opened, 0, i);
 
2722
                if (err != DB_SUCCESS) {
 
2723
 
 
2724
                        //return((int) err);
 
2725
                        exit(EXIT_FAILURE);
 
2726
                }
 
2727
 
 
2728
                if (log_file_created) {
 
2729
                        log_created = TRUE;
 
2730
                } else {
 
2731
                        log_opened = TRUE;
 
2732
                }
 
2733
                if ((log_opened && create_new_db)
 
2734
                                        || (log_opened && log_created)) {
 
2735
                        fprintf(stderr, 
 
2736
        "xtrabackup: Error: all log files must be created at the same time.\n"
 
2737
        "xtrabackup: All log files must be created also in database creation.\n"
 
2738
        "xtrabackup: If you want bigger or smaller log files, shut down the\n"
 
2739
        "xtrabackup: database and make sure there were no errors in shutdown.\n"
 
2740
        "xtrabackup: Then delete the existing log files. Edit the .cnf file\n"
 
2741
        "xtrabackup: and start the database again.\n");
 
2742
 
 
2743
                        //return(DB_ERROR);
 
2744
                        exit(EXIT_FAILURE);
 
2745
                }
 
2746
        }
 
2747
 
 
2748
        /* log_file_created must not be TRUE, if online */
 
2749
        if (log_file_created) {
 
2750
                fprintf(stderr, "xtrabackup: Something wrong with source files...\n");
 
2751
                exit(EXIT_FAILURE);
 
2752
        }
 
2753
 
 
2754
        fil_load_single_table_tablespaces();
 
2755
 
 
2756
        }
 
2757
 
 
2758
        /* create extra LSN dir if it does not exist. */
 
2759
        if (xtrabackup_extra_lsndir
 
2760
            && (stat(xtrabackup_extra_lsndir,&stat_info) != 0)
 
2761
            && (mkdir(xtrabackup_extra_lsndir,0777) != 0)){
 
2762
                fprintf(stderr,"xtrabackup: Error: cannot mkdir %d: %s\n",errno,xtrabackup_extra_lsndir);
 
2763
                exit(EXIT_FAILURE);
 
2764
        }
 
2765
 
 
2766
 
 
2767
        if (!xtrabackup_stream) {
 
2768
 
 
2769
        /* create target dir if not exist */
 
2770
        if (stat(xtrabackup_target_dir,&stat_info) != 0
 
2771
            && (mkdir(xtrabackup_target_dir,0777) != 0)){
 
2772
                fprintf(stderr,"xtrabackup: Error: cannot mkdir %d: %s\n",errno,xtrabackup_target_dir);
 
2773
                exit(EXIT_FAILURE);
 
2774
        }
 
2775
 
 
2776
        } else {
 
2777
                fprintf(stderr,"xtrabackup: Stream mode.\n");
 
2778
                /* stdout can treat binary at Linux */
 
2779
                //setmode(fileno(stdout), O_BINARY);
 
2780
        }
 
2781
 
 
2782
        {
 
2783
        fil_system_t*   f_system = fil_system;
 
2784
 
 
2785
        /* definition from recv_recovery_from_checkpoint_start() */
 
2786
        log_group_t*    max_cp_group;
 
2787
        ulint           max_cp_field;
 
2788
        byte*           buf;
 
2789
        byte            log_hdr_buf_[LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE];
 
2790
        byte*           log_hdr_buf;
 
2791
        ulint           err;
 
2792
 
 
2793
        ibool           success;
 
2794
 
 
2795
        /* start back ground thread to copy newer log */
 
2796
        os_thread_id_t log_copying_thread_id;
 
2797
        datafiles_iter_t *it;
 
2798
 
 
2799
        log_hdr_buf = (unsigned char*)ut_align(log_hdr_buf_, OS_FILE_LOG_BLOCK_SIZE);
 
2800
 
 
2801
        /* log space */
 
2802
        //space = UT_LIST_GET_NEXT(space_list, UT_LIST_GET_FIRST(f_system->space_list));
 
2803
        //printf("space: name=%s, id=%d, purpose=%d, size=%d\n",
 
2804
        //      space->name, space->id, space->purpose, space->size);
 
2805
 
 
2806
        /* get current checkpoint_lsn */
 
2807
        /* Look for the latest checkpoint from any of the log groups */
 
2808
        
 
2809
        err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
 
2810
 
 
2811
        if (err != DB_SUCCESS) {
 
2812
 
 
2813
                exit(EXIT_FAILURE);
 
2814
        }
 
2815
                
 
2816
        log_group_read_checkpoint_info(max_cp_group, max_cp_field);
 
2817
        buf = log_sys->checkpoint_buf;
 
2818
 
 
2819
        checkpoint_lsn_start = MACH_READ_64(buf + LOG_CHECKPOINT_LSN);
 
2820
        checkpoint_no_start = MACH_READ_64(buf + LOG_CHECKPOINT_NO);
 
2821
 
 
2822
reread_log_header:
 
2823
        fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, max_cp_group->space_id,
 
2824
                                0,
 
2825
                                0, 0, LOG_FILE_HDR_SIZE,
 
2826
                                log_hdr_buf, max_cp_group);
 
2827
 
 
2828
        /* check consistency of log file header to copy */
 
2829
        err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
 
2830
 
 
2831
        if (err != DB_SUCCESS) {
 
2832
 
 
2833
                exit(EXIT_FAILURE);
 
2834
        }
 
2835
 
 
2836
        log_group_read_checkpoint_info(max_cp_group, max_cp_field);
 
2837
        buf = log_sys->checkpoint_buf;
 
2838
 
 
2839
        if(ut_dulint_cmp(checkpoint_no_start,
 
2840
                        MACH_READ_64(buf + LOG_CHECKPOINT_NO)) != 0) {
 
2841
                checkpoint_lsn_start = MACH_READ_64(buf + LOG_CHECKPOINT_LSN);
 
2842
                checkpoint_no_start = MACH_READ_64(buf + LOG_CHECKPOINT_NO);
 
2843
                goto reread_log_header;
 
2844
        }
 
2845
 
 
2846
        if (!xtrabackup_stream) {
 
2847
 
 
2848
                /* open 'xtrabackup_logfile' */
 
2849
                sprintf(dst_log_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
 
2850
                srv_normalize_path_for_win(dst_log_path);
 
2851
                /* os_file_create reads srv_unix_file_flush_method for OS_DATA_FILE*/
 
2852
                dst_log = os_file_create(
 
2853
                                0 /* dummy of innodb_file_data_key */,
 
2854
                                dst_log_path, OS_FILE_CREATE,
 
2855
                                OS_FILE_NORMAL, OS_DATA_FILE, &success);
 
2856
 
 
2857
                if (!success) {
 
2858
                        /* The following call prints an error message */
 
2859
                        os_file_get_last_error(TRUE);
 
2860
 
 
2861
                        fprintf(stderr,
 
2862
"xtrabackup: error: cannot open %s\n",
 
2863
                                dst_log_path);
 
2864
                        exit(EXIT_FAILURE);
 
2865
                }
 
2866
 
 
2867
#ifdef USE_POSIX_FADVISE
 
2868
                posix_fadvise(dst_log, 0, 0, POSIX_FADV_DONTNEED);
 
2869
#endif
 
2870
 
 
2871
        }
 
2872
 
 
2873
        /* label it */
 
2874
        strcpy((char*) log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
 
2875
                "xtrabkup ");
 
2876
        ut_sprintf_timestamp(
 
2877
                (char*) log_hdr_buf + (LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
 
2878
                                + (sizeof "xtrabkup ") - 1));
 
2879
 
 
2880
        if (!xtrabackup_stream) {
 
2881
                success = os_file_write(dst_log_path, dst_log, log_hdr_buf,
 
2882
                                0, 0, LOG_FILE_HDR_SIZE);
 
2883
        } else {
 
2884
                /* Stream */
 
2885
                if (write(fileno(stdout), log_hdr_buf, LOG_FILE_HDR_SIZE)
 
2886
                                == LOG_FILE_HDR_SIZE) {
 
2887
                        success = TRUE;
 
2888
                } else {
 
2889
                        success = FALSE;
 
2890
                }
 
2891
        }
 
2892
 
 
2893
        log_copy_offset += LOG_FILE_HDR_SIZE;
 
2894
        if (!success) {
 
2895
                if (dst_log != -1)
 
2896
                        os_file_close(dst_log);
 
2897
                exit(EXIT_FAILURE);
 
2898
        }
 
2899
 
 
2900
        /* start flag */
 
2901
        log_copying = TRUE;
 
2902
 
 
2903
        /* start io throttle */
 
2904
        if(xtrabackup_throttle) {
 
2905
                os_thread_id_t io_watching_thread_id;
 
2906
 
 
2907
                io_ticket = xtrabackup_throttle;
 
2908
                wait_throttle = os_event_create(NULL);
 
2909
 
 
2910
                os_thread_create(io_watching_thread, NULL, &io_watching_thread_id);
 
2911
        }
 
2912
 
 
2913
 
 
2914
        /* copy log file by current position */
 
2915
        if(xtrabackup_copy_logfile(checkpoint_lsn_start, FALSE))
 
2916
                exit(EXIT_FAILURE);
 
2917
 
 
2918
 
 
2919
        os_thread_create(log_copying_thread, NULL, &log_copying_thread_id);
 
2920
 
 
2921
 
 
2922
 
 
2923
        if (!xtrabackup_stream) { /* stream mode is transaction log only */
 
2924
                uint                    i;
 
2925
                uint                    count;
 
2926
                os_mutex_t              count_mutex;
 
2927
                data_thread_ctxt_t      *data_threads;
 
2928
 
 
2929
                ut_a(parallel > 0);
 
2930
 
 
2931
                if (parallel > 1)
 
2932
                        printf("xtrabackup: Starting %u threads for parallel "
 
2933
                               "data files transfer\n", parallel);
 
2934
 
 
2935
                it = datafiles_iter_new(f_system);
 
2936
                if (it == NULL) {
 
2937
                        fprintf(stderr,
 
2938
                                "xtrabackup: Error: "
 
2939
                                "datafiles_iter_new() failed.\n");
 
2940
                        exit(EXIT_FAILURE);
 
2941
                }
 
2942
 
 
2943
                /* Create data copying threads */
 
2944
                ut_a(parallel > 0);
 
2945
 
 
2946
                data_threads = (data_thread_ctxt_t *)
 
2947
                        ut_malloc(sizeof(data_thread_ctxt_t) * parallel);
 
2948
                count = parallel;
 
2949
                count_mutex = OS_MUTEX_CREATE();
 
2950
 
 
2951
                for (i = 0; i < parallel; i++) {
 
2952
                        data_threads[i].it = it;
 
2953
                        data_threads[i].num = i+1;
 
2954
                        data_threads[i].count = &count;
 
2955
                        data_threads[i].count_mutex = count_mutex;
 
2956
                        os_thread_create(data_copy_thread_func,
 
2957
                                         data_threads + i,
 
2958
                                         &data_threads[i].id);
 
2959
                }
 
2960
 
 
2961
                /* Wait for threads to exit */
 
2962
                while (1) {
 
2963
                        os_thread_sleep(1000000);
 
2964
                        os_mutex_enter(count_mutex);
 
2965
                        if (count == 0) {
 
2966
                                os_mutex_exit(count_mutex);
 
2967
                                break;
 
2968
                        }
 
2969
                        os_mutex_exit(count_mutex);
 
2970
                }
 
2971
                /* NOTE: It may not needed at "--backup" for now */
 
2972
                /* mutex_enter(&(f_system->mutex)); */
 
2973
 
 
2974
                os_mutex_free(count_mutex);
 
2975
                datafiles_iter_free(it);
 
2976
 
 
2977
        } //if (!xtrabackup_stream)
 
2978
 
 
2979
        //mutex_exit(&(f_system->mutex));
 
2980
        }
 
2981
 
 
2982
 
 
2983
        /* suspend-at-end */
 
2984
        if (xtrabackup_suspend_at_end) {
 
2985
                os_file_t       suspend_file = -1;
 
2986
                char    suspend_path[FN_REFLEN];
 
2987
                ibool   success, exists;
 
2988
                os_file_type_t  type;
 
2989
 
 
2990
                sprintf(suspend_path, "%s%s", xtrabackup_target_dir,
 
2991
                        "/xtrabackup_suspended");
 
2992
 
 
2993
                srv_normalize_path_for_win(suspend_path);
 
2994
                /* os_file_create reads srv_unix_file_flush_method */
 
2995
                suspend_file = os_file_create(
 
2996
                                        0 /* dummy of innodb_file_data_key */,
 
2997
                                        suspend_path, OS_FILE_OVERWRITE,
 
2998
                                        OS_FILE_NORMAL, OS_DATA_FILE, &success);
 
2999
 
 
3000
                if (!success) {
 
3001
                        fprintf(stderr, "xtrabackup: Error: failed to create file 'xtrabackup_suspended'\n");
 
3002
                }
 
3003
 
 
3004
                if (suspend_file != -1)
 
3005
                        os_file_close(suspend_file);
 
3006
 
 
3007
                exists = TRUE;
 
3008
                while (exists) {
 
3009
                        os_thread_sleep(200000); /*0.2 sec*/
 
3010
                        success = os_file_status(suspend_path, &exists, &type);
 
3011
                        if (!success)
 
3012
                                break;
 
3013
                }
 
3014
                xtrabackup_suspend_at_end = FALSE; /* suspend is 1 time */
 
3015
        }
 
3016
 
 
3017
        /* read the latest checkpoint lsn */
 
3018
        latest_cp = ut_dulint_zero;
 
3019
        {
 
3020
                log_group_t*    max_cp_group;
 
3021
                ulint   max_cp_field;
 
3022
                ulint   err;
 
3023
 
 
3024
                err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
 
3025
 
 
3026
                if (err != DB_SUCCESS) {
 
3027
                        fprintf(stderr, "xtrabackup: Error: recv_find_max_checkpoint() failed.\n");
 
3028
                        goto skip_last_cp;
 
3029
                }
 
3030
 
 
3031
                log_group_read_checkpoint_info(max_cp_group, max_cp_field);
 
3032
 
 
3033
                latest_cp = MACH_READ_64(log_sys->checkpoint_buf + LOG_CHECKPOINT_LSN);
 
3034
 
 
3035
                if (!xtrabackup_stream) {
 
3036
                        printf("xtrabackup: The latest check point (for incremental): '%"PRIu64"'\n",
 
3037
                                latest_cp);
 
3038
                } else {
 
3039
                        fprintf(stderr, "xtrabackup: The latest check point (for incremental): '%"PRIu64"'\n",
 
3040
                                latest_cp);
 
3041
                }
 
3042
        }
 
3043
skip_last_cp:
 
3044
        /* stop log_copying_thread */
 
3045
        log_copying = FALSE;
 
3046
        if (!xtrabackup_stream) {
 
3047
                printf("xtrabackup: Stopping log copying thread");
 
3048
                while (log_copying_running) {
 
3049
                        printf(".");
 
3050
                        os_thread_sleep(200000); /*0.2 sec*/
 
3051
                }
 
3052
                printf("\n");
 
3053
        } else {
 
3054
                while (log_copying_running)
 
3055
                        os_thread_sleep(200000); /*0.2 sec*/
 
3056
        }
 
3057
 
 
3058
        /* output to metadata file */
 
3059
        {
 
3060
                char    filename[FN_REFLEN];
 
3061
 
 
3062
                if(!xtrabackup_incremental) {
 
3063
                        strcpy(metadata_type, "full-backuped");
 
3064
                        metadata_from_lsn = ut_dulint_zero;
 
3065
                } else {
 
3066
                        strcpy(metadata_type, "incremental");
 
3067
                        metadata_from_lsn = incremental_lsn;
 
3068
                }
 
3069
                metadata_to_lsn = latest_cp;
 
3070
                metadata_last_lsn = log_copy_scanned_lsn;
 
3071
 
 
3072
                sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
 
3073
                if (xtrabackup_write_metadata(filename))
 
3074
                        fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_target_dir)\n");
 
3075
 
 
3076
                if(xtrabackup_extra_lsndir) {
 
3077
                        sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
 
3078
                        if (xtrabackup_write_metadata(filename))
 
3079
                                fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
 
3080
                }
 
3081
        }
 
3082
 
 
3083
        if (!log_copying_succeed) {
 
3084
                fprintf(stderr, "xtrabackup: Error: log_copying_thread failed.\n");
 
3085
                exit(EXIT_FAILURE);
 
3086
        }
 
3087
 
 
3088
        if (!xtrabackup_stream)
 
3089
                os_file_close(dst_log);
 
3090
 
 
3091
        if (wait_throttle)
 
3092
                os_event_free(wait_throttle);
 
3093
 
 
3094
        if (!xtrabackup_stream) {
 
3095
                printf("xtrabackup: Transaction log of lsn (%"PRIu64") to (%"PRIu64") was copied.\n",
 
3096
                        checkpoint_lsn_start, log_copy_scanned_lsn);
 
3097
        } else {
 
3098
                fprintf(stderr, "xtrabackup: Transaction log of lsn (%"PRIu64") to (%"PRIu64") was copied.\n",
 
3099
                        checkpoint_lsn_start, log_copy_scanned_lsn);
 
3100
                if(xtrabackup_extra_lsndir) {
 
3101
                        char    filename[FN_REFLEN];
 
3102
                        sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
 
3103
                        if (xtrabackup_write_metadata(filename))
 
3104
                                fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
 
3105
                }
 
3106
        }
 
3107
}
 
3108
 
 
3109
/* ================= stats ================= */
 
3110
static bool
 
3111
xtrabackup_stats_level(
 
3112
        dict_index_t*   index,
 
3113
        ulint           level)
 
3114
{
 
3115
        ulint   space;
 
3116
        page_t* page;
 
3117
 
 
3118
        rec_t*  node_ptr;
 
3119
 
 
3120
        ulint   right_page_no;
 
3121
 
 
3122
        page_cur_t      cursor;
 
3123
 
 
3124
        mtr_t   mtr;
 
3125
        mem_heap_t*     heap    = mem_heap_create(256);
 
3126
 
 
3127
        ulint*  offsets = NULL;
 
3128
 
 
3129
        uint64_t n_pages, n_pages_extern;
 
3130
        uint64_t sum_data, sum_data_extern;
 
3131
        uint64_t n_recs;
 
3132
        ulint   page_size;
 
3133
 
 
3134
        n_pages = sum_data = n_recs = 0;
 
3135
        n_pages_extern = sum_data_extern = 0;
 
3136
 
 
3137
        buf_block_t*    block;
 
3138
        ulint   zip_size;
 
3139
 
 
3140
        if (level == 0)
 
3141
                fprintf(stdout, "        leaf pages: ");
 
3142
        else
 
3143
                fprintf(stdout, "     level %lu pages: ", level);
 
3144
 
 
3145
        mtr_start(&mtr);
 
3146
 
 
3147
        mtr_x_lock(&(index->lock), &mtr);
 
3148
        block = btr_root_block_get(index, &mtr);
 
3149
        page = buf_block_get_frame(block);
 
3150
 
 
3151
        space = page_get_space_id(page);
 
3152
        zip_size = fil_space_get_zip_size(space);
 
3153
 
 
3154
        while (level != btr_page_get_level(page, &mtr)) {
 
3155
 
 
3156
                ut_a(space == buf_block_get_space(block));
 
3157
                ut_a(space == page_get_space_id(page));
 
3158
                ut_a(!page_is_leaf(page));
 
3159
 
 
3160
                page_cur_set_before_first(block, &cursor);
 
3161
                page_cur_move_to_next(&cursor);
 
3162
 
 
3163
                node_ptr = page_cur_get_rec(&cursor);
 
3164
                offsets = rec_get_offsets(node_ptr, index, offsets,
 
3165
                                        ULINT_UNDEFINED, &heap);
 
3166
 
 
3167
                block = btr_node_ptr_get_child(node_ptr, index, offsets, &mtr);
 
3168
                page = buf_block_get_frame(block);
 
3169
        }
 
3170
 
 
3171
loop:
 
3172
        mem_heap_empty(heap);
 
3173
        offsets = NULL;
 
3174
        mtr_x_lock(&(index->lock), &mtr);
 
3175
 
 
3176
        right_page_no = btr_page_get_next(page, &mtr);
 
3177
 
 
3178
 
 
3179
        /*=================================*/
 
3180
        //fprintf(stdout, "%lu ", (ulint) buf_frame_get_page_no(page));
 
3181
 
 
3182
        n_pages++;
 
3183
        sum_data += page_get_data_size(page);
 
3184
        n_recs += page_get_n_recs(page);
 
3185
 
 
3186
 
 
3187
        if (level == 0) {
 
3188
                page_cur_t      cur;
 
3189
                ulint   n_fields;
 
3190
                ulint   i;
 
3191
                mem_heap_t*     local_heap      = NULL;
 
3192
                ulint   offsets_[REC_OFFS_NORMAL_SIZE];
 
3193
                ulint*  local_offsets   = offsets_;
 
3194
 
 
3195
                *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
3196
 
 
3197
                page_cur_set_before_first(block, &cur);
 
3198
 
 
3199
                page_cur_move_to_next(&cur);
 
3200
 
 
3201
                for (;;) {
 
3202
                        if (page_cur_is_after_last(&cur)) {
 
3203
                                break;
 
3204
                        }
 
3205
 
 
3206
                        local_offsets = rec_get_offsets(cur.rec, index, local_offsets,
 
3207
                                                ULINT_UNDEFINED, &local_heap);
 
3208
                        n_fields = rec_offs_n_fields(local_offsets);
 
3209
 
 
3210
                        for (i = 0; i < n_fields; i++) {
 
3211
                                if (rec_offs_nth_extern(local_offsets, i)) {
 
3212
                                        page_t* local_page;
 
3213
                                        ulint   space_id;
 
3214
                                        ulint   page_no;
 
3215
                                        ulint   offset;
 
3216
                                        byte*   blob_header;
 
3217
                                        ulint   part_len;
 
3218
                                        mtr_t   local_mtr;
 
3219
                                        ulint   local_len;
 
3220
                                        byte*   data;
 
3221
                                        buf_block_t*    local_block;
 
3222
 
 
3223
                                        data = rec_get_nth_field(cur.rec, local_offsets, i, &local_len);
 
3224
 
 
3225
                                        ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
 
3226
                                        local_len -= BTR_EXTERN_FIELD_REF_SIZE;
 
3227
 
 
3228
                                        space_id = mach_read_from_4(data + local_len + BTR_EXTERN_SPACE_ID);
 
3229
                                        page_no = mach_read_from_4(data + local_len + BTR_EXTERN_PAGE_NO);
 
3230
                                        offset = mach_read_from_4(data + local_len + BTR_EXTERN_OFFSET);
 
3231
 
 
3232
                                        if (offset != FIL_PAGE_DATA)
 
3233
                                                fprintf(stderr, "\nWarning: several record may share same external page.\n");
 
3234
 
 
3235
                                        for (;;) {
 
3236
                                                mtr_start(&local_mtr);
 
3237
 
 
3238
                                                local_block = btr_block_get(space_id, zip_size, page_no, RW_S_LATCH, &local_mtr);
 
3239
                                                local_page = buf_block_get_frame(local_block);
 
3240
 
 
3241
                                                blob_header = local_page + offset;
 
3242
#define BTR_BLOB_HDR_PART_LEN           0
 
3243
#define BTR_BLOB_HDR_NEXT_PAGE_NO       4
 
3244
                                                //part_len = btr_blob_get_part_len(blob_header);
 
3245
                                                part_len = mach_read_from_4(blob_header + BTR_BLOB_HDR_PART_LEN);
 
3246
 
 
3247
                                                //page_no = btr_blob_get_next_page_no(blob_header);
 
3248
                                                page_no = mach_read_from_4(blob_header + BTR_BLOB_HDR_NEXT_PAGE_NO);
 
3249
 
 
3250
                                                offset = FIL_PAGE_DATA;
 
3251
 
 
3252
 
 
3253
 
 
3254
 
 
3255
                                                /*=================================*/
 
3256
                                                //fprintf(stdout, "[%lu] ", (ulint) buf_frame_get_page_no(page));
 
3257
 
 
3258
                                                n_pages_extern++;
 
3259
                                                sum_data_extern += part_len;
 
3260
 
 
3261
 
 
3262
                                                mtr_commit(&local_mtr);
 
3263
 
 
3264
                                                if (page_no == FIL_NULL)
 
3265
                                                        break;
 
3266
                                        }
 
3267
                                }
 
3268
                        }
 
3269
 
 
3270
                        page_cur_move_to_next(&cur);
 
3271
                }
 
3272
        }
 
3273
 
 
3274
 
 
3275
 
 
3276
 
 
3277
        mtr_commit(&mtr);
 
3278
        if (right_page_no != FIL_NULL) {
 
3279
                mtr_start(&mtr);
 
3280
                block = btr_block_get(space, zip_size, right_page_no, RW_X_LATCH, &mtr);
 
3281
                page = buf_block_get_frame(block);
 
3282
                goto loop;
 
3283
        }
 
3284
        mem_heap_free(heap);
 
3285
 
 
3286
        if (zip_size) {
 
3287
                page_size = zip_size;
 
3288
        } else {
 
3289
                page_size = UNIV_PAGE_SIZE;
 
3290
        }
 
3291
 
 
3292
        if (level == 0)
 
3293
                fprintf(stdout, "recs=%"PRIu64", ", n_recs);
 
3294
 
 
3295
        fprintf(stdout, "pages=%"PRIu64", data=%"PRIu64" bytes, data/pages=%"PRIu64"%%",
 
3296
                n_pages, sum_data,
 
3297
                ((sum_data * 100)/ page_size)/n_pages);
 
3298
 
 
3299
 
 
3300
        if (level == 0 && n_pages_extern) {
 
3301
                putc('\n', stdout);
 
3302
                /* also scan blob pages*/
 
3303
                fprintf(stdout, "    external pages: ");
 
3304
 
 
3305
                fprintf(stdout, "pages=%"PRIu64", data=%"PRIu64" bytes, data/pages=%"PRIu64"%%",
 
3306
                        n_pages_extern, sum_data_extern,
 
3307
                        ((sum_data_extern * 100)/ page_size)/n_pages_extern);
 
3308
        }
 
3309
 
 
3310
        putc('\n', stdout);
 
3311
 
 
3312
        if (level > 0) {
 
3313
                xtrabackup_stats_level(index, level - 1);
 
3314
        }
 
3315
 
 
3316
        return(TRUE);
 
3317
}
 
3318
 
 
3319
static void
 
3320
xtrabackup_stats_func(void)
 
3321
{
 
3322
        ulint n;
 
3323
 
 
3324
        /* cd to datadir */
 
3325
 
 
3326
        if (chdir(mysql_real_data_home) != 0)
 
3327
        {
 
3328
                fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", mysql_real_data_home);
 
3329
                exit(EXIT_FAILURE);
 
3330
        }
 
3331
        fprintf(stderr, "xtrabackup: cd to %s\n", mysql_real_data_home);
 
3332
 
 
3333
        mysql_data_home= mysql_data_home_buff;
 
3334
        mysql_data_home[0]=FN_CURLIB;           // all paths are relative from here
 
3335
        mysql_data_home[1]=0;
 
3336
 
 
3337
        /* set read only */
 
3338
        srv_read_only = TRUE;
 
3339
        srv_fake_write = TRUE;
 
3340
 
 
3341
        /* initialize components */
 
3342
        if(innodb_init_param())
 
3343
                exit(EXIT_FAILURE);
 
3344
 
 
3345
        /* Check if the log files have been created, otherwise innodb_init()
 
3346
        will crash when called with srv_read_only == TRUE */
 
3347
        for (n = 0; n < srv_n_log_files; n++) {
 
3348
                char            logname[FN_REFLEN];
 
3349
                ibool           exists;
 
3350
                os_file_type_t  type;
 
3351
 
 
3352
                sprintf(logname, "ib_logfile%lu", (ulong) n);
 
3353
                if (!os_file_status(logname, &exists, &type) || !exists ||
 
3354
                    type != OS_FILE_TYPE_FILE) {
 
3355
                        fprintf(stderr, "xtrabackup: Error: "
 
3356
                                "Cannot find log file %s.\n", logname);
 
3357
                        fprintf(stderr, "xtrabackup: Error: "
 
3358
                                "to use the statistics feature, you need a "
 
3359
                                "clean copy of the database including "
 
3360
                                "correctly sized log files, so you need to "
 
3361
                                "execute with --prepare twice to use this "
 
3362
                                "functionality on a backup.\n");
 
3363
                        exit(EXIT_FAILURE);
 
3364
                }
 
3365
        }
 
3366
 
 
3367
        fprintf(stderr, "xtrabackup: Starting 'read-only' InnoDB instance to gather index statistics.\n"
 
3368
                "xtrabackup: Using %"PRIu64" bytes for buffer pool (set by --use-memory parameter)\n",
 
3369
                xtrabackup_use_memory);
 
3370
 
 
3371
        if(innodb_init())
 
3372
                exit(EXIT_FAILURE);
 
3373
 
 
3374
        fprintf(stdout, "\n\n<INDEX STATISTICS>\n");
 
3375
 
 
3376
        /* gather stats */
 
3377
 
 
3378
        {
 
3379
        dict_table_t*   sys_tables;
 
3380
        dict_index_t*   sys_index;
 
3381
        dict_table_t*   table;
 
3382
        btr_pcur_t      pcur;
 
3383
        rec_t*          rec;
 
3384
        byte*           field;
 
3385
        ulint           len;
 
3386
        mtr_t           mtr;
 
3387
        
 
3388
        /* Enlarge the fatal semaphore wait timeout during the InnoDB table
 
3389
        monitor printout */
 
3390
 
 
3391
        mutex_enter(&kernel_mutex);
 
3392
        srv_fatal_semaphore_wait_threshold += 72000; /* 20 hours */
 
3393
        mutex_exit(&kernel_mutex);
 
3394
 
 
3395
        mutex_enter(&(dict_sys->mutex));
 
3396
 
 
3397
        mtr_start(&mtr);
 
3398
 
 
3399
        sys_tables = dict_table_get_low("SYS_TABLES");
 
3400
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
 
3401
 
 
3402
        btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
 
3403
                                                                TRUE, &mtr);
 
3404
loop:
 
3405
        btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
3406
 
 
3407
        rec = btr_pcur_get_rec(&pcur);
 
3408
 
 
3409
        if (!btr_pcur_is_on_user_rec(&pcur))
 
3410
        {
 
3411
                /* end of index */
 
3412
 
 
3413
                btr_pcur_close(&pcur);
 
3414
                mtr_commit(&mtr);
 
3415
                
 
3416
                mutex_exit(&(dict_sys->mutex));
 
3417
 
 
3418
                /* Restore the fatal semaphore wait timeout */
 
3419
 
 
3420
                mutex_enter(&kernel_mutex);
 
3421
                srv_fatal_semaphore_wait_threshold -= 72000; /* 20 hours */
 
3422
                mutex_exit(&kernel_mutex);
 
3423
 
 
3424
                goto end;
 
3425
        }       
 
3426
 
 
3427
        field = rec_get_nth_field_old(rec, 0, &len);
 
3428
 
 
3429
        if (!rec_get_deleted_flag(rec, 0))
 
3430
        {
 
3431
 
 
3432
                /* We found one */
 
3433
 
 
3434
                char*   table_name = mem_strdupl((char*) field, len);
 
3435
 
 
3436
                btr_pcur_store_position(&pcur, &mtr);
 
3437
 
 
3438
                mtr_commit(&mtr);
 
3439
 
 
3440
                table = dict_table_get_low(table_name);
 
3441
                mem_free(table_name);
 
3442
 
 
3443
 
 
3444
                if (xtrabackup_tables) {
 
3445
                        char *p;
 
3446
                        int regres= 0;
 
3447
                        int i;
 
3448
 
 
3449
                        p = strstr(table->name, SRV_PATH_SEPARATOR_STR);
 
3450
 
 
3451
                        if (p)
 
3452
                                *p = '.';
 
3453
 
 
3454
                        for (i = 0; i < tables_regex_num; i++) {
 
3455
                                regres = regexec(&tables_regex[i], table->name, 1, tables_regmatch, 0);
 
3456
                                if (regres != REG_NOMATCH)
 
3457
                                        break;
 
3458
                        }
 
3459
 
 
3460
                        if (p)
 
3461
                                *p = SRV_PATH_SEPARATOR;
 
3462
 
 
3463
                        if ( regres == REG_NOMATCH )
 
3464
                                goto skip;
 
3465
                }
 
3466
 
 
3467
                if (xtrabackup_tables_file) {
 
3468
                        xtrabackup_tables_t*    xtable;
 
3469
 
 
3470
                        HASH_SEARCH(name_hash, tables_hash, ut_fold_string(table->name),
 
3471
                                    xtrabackup_tables_t*,
 
3472
                                    xtable,
 
3473
                                    ut_ad(xtable->name),
 
3474
                                    !strcmp(xtable->name, table->name));
 
3475
 
 
3476
                        if (!xtable)
 
3477
                                goto skip;
 
3478
                }
 
3479
 
 
3480
 
 
3481
                if (table == NULL) {
 
3482
                        fputs("InnoDB: Failed to load table ", stderr);
 
3483
                        ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
 
3484
                        putc('\n', stderr);
 
3485
                } else {
 
3486
                        dict_index_t*   index;
 
3487
 
 
3488
                        /* The table definition was corrupt if there
 
3489
                        is no index */
 
3490
 
 
3491
                        if (dict_table_get_first_index(table)) {
 
3492
#ifdef XTRADB_BASED
 
3493
                                dict_update_statistics(table, TRUE, FALSE);
 
3494
#elif defined(INNODB_VERSION_SHORT)
 
3495
                                dict_update_statistics(table, TRUE);
 
3496
#else
 
3497
                                dict_update_statistics_low(table, TRUE);
 
3498
#endif
 
3499
                        }
 
3500
 
 
3501
                        //dict_table_print_low(table);
 
3502
 
 
3503
                        index = UT_LIST_GET_FIRST(table->indexes);
 
3504
                        while (index != NULL) {
 
3505
{
 
3506
        IB_INT64        n_vals;
 
3507
 
 
3508
        if (index->n_user_defined_cols > 0) {
 
3509
                n_vals = index->stat_n_diff_key_vals[
 
3510
                                        index->n_user_defined_cols];
 
3511
        } else {
 
3512
                n_vals = index->stat_n_diff_key_vals[1];
 
3513
        }
 
3514
 
 
3515
        fprintf(stdout,
 
3516
                "  table: %s, index: %s, space id: %lu, root page: %lu"
 
3517
                ", zip size: %lu"
 
3518
                "\n  estimated statistics in dictionary:\n"
 
3519
                "    key vals: %lu, leaf pages: %lu, size pages: %lu\n"
 
3520
                "  real statistics:\n",
 
3521
                table->name, index->name,
 
3522
                (ulong) index->space,
 
3523
                (ulong) index->page,
 
3524
                (ulong) fil_space_get_zip_size(index->space),
 
3525
                (ulong) n_vals,
 
3526
                (ulong) index->stat_n_leaf_pages,
 
3527
                (ulong) index->stat_index_size);
 
3528
 
 
3529
        {
 
3530
                mtr_t   local_mtr;
 
3531
                page_t* root;
 
3532
                ulint   page_level;
 
3533
 
 
3534
                mtr_start(&local_mtr);
 
3535
 
 
3536
                mtr_x_lock(&(index->lock), &local_mtr);
 
3537
                root = btr_root_get(index, &local_mtr);
 
3538
 
 
3539
                page_level = btr_page_get_level(root, &local_mtr);
 
3540
 
 
3541
                xtrabackup_stats_level(index, page_level);
 
3542
 
 
3543
                mtr_commit(&local_mtr);
 
3544
        }
 
3545
 
 
3546
        putc('\n', stdout);
 
3547
}
 
3548
                                index = UT_LIST_GET_NEXT(indexes, index);
 
3549
                        }
 
3550
                }
 
3551
 
 
3552
skip:
 
3553
                mtr_start(&mtr);
 
3554
 
 
3555
                btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
 
3556
        }
 
3557
 
 
3558
        goto loop;
 
3559
        }
 
3560
 
 
3561
end:
 
3562
        putc('\n', stdout);
 
3563
 
 
3564
        /* shutdown InnoDB */
 
3565
        if(innodb_end())
 
3566
                exit(EXIT_FAILURE);
 
3567
}
 
3568
 
 
3569
/* ================= prepare ================= */
 
3570
 
 
3571
static bool
 
3572
xtrabackup_init_temp_log(void)
 
3573
{
 
3574
        os_file_t       src_file = -1;
 
3575
        char    src_path[FN_REFLEN];
 
3576
        char    dst_path[FN_REFLEN];
 
3577
        ibool   success;
 
3578
 
 
3579
        ulint   field;
 
3580
        byte*   log_buf;
 
3581
        byte*   log_buf_ = NULL;
 
3582
 
 
3583
        IB_INT64        file_size;
 
3584
 
 
3585
        LSN64   max_no;
 
3586
        LSN64   max_lsn;
 
3587
        LSN64   checkpoint_no;
 
3588
 
 
3589
        ulint   fold;
 
3590
 
 
3591
        max_no = ut_dulint_zero;
 
3592
 
 
3593
        if(!xtrabackup_incremental_dir) {
 
3594
                sprintf(dst_path, "%s%s", xtrabackup_target_dir, "/ib_logfile0");
 
3595
                sprintf(src_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
 
3596
        } else {
 
3597
                sprintf(dst_path, "%s%s", xtrabackup_incremental_dir, "/ib_logfile0");
 
3598
                sprintf(src_path, "%s%s", xtrabackup_incremental_dir, "/xtrabackup_logfile");
 
3599
        }
 
3600
 
 
3601
        srv_normalize_path_for_win(dst_path);
 
3602
        srv_normalize_path_for_win(src_path);
 
3603
retry:
 
3604
        src_file = os_file_create_simple_no_error_handling(
 
3605
                                        0 /* dummy of innodb_file_data_key */,
 
3606
                                        src_path, OS_FILE_OPEN,
 
3607
                                        OS_FILE_READ_WRITE /* OS_FILE_READ_ONLY */, &success);
 
3608
        if (!success) {
 
3609
                /* The following call prints an error message */
 
3610
                os_file_get_last_error(TRUE);
 
3611
 
 
3612
                fprintf(stderr,
 
3613
"xtrabackup: Warning: cannot open %s. will try to find.\n",
 
3614
                        src_path);
 
3615
 
 
3616
                /* check if ib_logfile0 may be xtrabackup_logfile */
 
3617
                src_file = os_file_create_simple_no_error_handling(
 
3618
                                0 /* dummy of innodb_file_data_key */,
 
3619
                                dst_path, OS_FILE_OPEN,
 
3620
                                OS_FILE_READ_WRITE /* OS_FILE_READ_ONLY */, &success);
 
3621
                if (!success) {
 
3622
                        os_file_get_last_error(TRUE);
 
3623
                        fprintf(stderr,
 
3624
"  xtrabackup: Fatal error: cannot find %s.\n",
 
3625
                        src_path);
 
3626
 
 
3627
                        goto error;
 
3628
                }
 
3629
 
 
3630
                log_buf_ = (unsigned char*) ut_malloc(LOG_FILE_HDR_SIZE * 2);
 
3631
                log_buf = (unsigned char*) ut_align(log_buf_, LOG_FILE_HDR_SIZE);
 
3632
 
 
3633
                success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
 
3634
                if (!success) {
 
3635
                        goto error;
 
3636
                }
 
3637
 
 
3638
                if ( ut_memcmp(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
 
3639
                                (byte*)"xtrabkup", (sizeof "xtrabkup") - 1) == 0) {
 
3640
                        fprintf(stderr,
 
3641
"  xtrabackup: 'ib_logfile0' seems to be 'xtrabackup_logfile'. will retry.\n");
 
3642
 
 
3643
                        ut_free(log_buf_);
 
3644
                        log_buf_ = NULL;
 
3645
 
 
3646
                        os_file_close(src_file);
 
3647
                        src_file = -1;
 
3648
 
 
3649
                        /* rename and try again */
 
3650
                        success = os_file_rename(
 
3651
                                        0 /* dummy of innodb_file_data_key */,
 
3652
                                        dst_path, src_path);
 
3653
                        if (!success) {
 
3654
                                goto error;
 
3655
                        }
 
3656
 
 
3657
                        goto retry;
 
3658
                }
 
3659
 
 
3660
                fprintf(stderr,
 
3661
"  xtrabackup: Fatal error: cannot find %s.\n",
 
3662
                src_path);
 
3663
 
 
3664
                ut_free(log_buf_);
 
3665
                log_buf_ = NULL;
 
3666
 
 
3667
                os_file_close(src_file);
 
3668
                src_file = -1;
 
3669
 
 
3670
                goto error;
 
3671
        }
 
3672
 
 
3673
#ifdef USE_POSIX_FADVISE
 
3674
        posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
 
3675
        posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
 
3676
#endif
 
3677
 
 
3678
        if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
 
3679
                os_file_set_nocache(src_file, src_path, "OPEN");
 
3680
        }
 
3681
 
 
3682
        file_size = os_file_get_size_as_iblonglong(src_file);
 
3683
 
 
3684
 
 
3685
        /* TODO: We should skip the following modifies, if it is not the first time. */
 
3686
        log_buf_ = (unsigned char*) ut_malloc(UNIV_PAGE_SIZE * 129);
 
3687
        log_buf = (unsigned char*) ut_align(log_buf_, UNIV_PAGE_SIZE);
 
3688
 
 
3689
        /* read log file header */
 
3690
        success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
 
3691
        if (!success) {
 
3692
                goto error;
 
3693
        }
 
3694
 
 
3695
        if ( ut_memcmp(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
 
3696
                        (byte*)"xtrabkup", (sizeof "xtrabkup") - 1) != 0 ) {
 
3697
                printf("xtrabackup: notice: xtrabackup_logfile was already used to '--prepare'.\n");
 
3698
                goto skip_modify;
 
3699
        } else {
 
3700
                /* clear it later */
 
3701
                //memset(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
 
3702
                //              ' ', 4);
 
3703
        }
 
3704
 
 
3705
        /* read last checkpoint lsn */
 
3706
        for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2;
 
3707
                        field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) {
 
3708
                if (!recv_check_cp_is_consistent(log_buf + field))
 
3709
                        goto not_consistent;
 
3710
 
 
3711
                checkpoint_no = MACH_READ_64(log_buf + field + LOG_CHECKPOINT_NO);
 
3712
 
 
3713
                if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) {
 
3714
                        max_no = checkpoint_no;
 
3715
                        max_lsn = MACH_READ_64(log_buf + field + LOG_CHECKPOINT_LSN);
 
3716
/*
 
3717
                        mach_write_to_4(log_buf + field + LOG_CHECKPOINT_OFFSET,
 
3718
                                        LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
 
3719
                                        ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
 
3720
 
 
3721
                        ulint   fold;
 
3722
                        fold = ut_fold_binary(log_buf + field, LOG_CHECKPOINT_CHECKSUM_1);
 
3723
                        mach_write_to_4(log_buf + field + LOG_CHECKPOINT_CHECKSUM_1, fold);
 
3724
 
 
3725
                        fold = ut_fold_binary(log_buf + field + LOG_CHECKPOINT_LSN,
 
3726
                                LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
 
3727
                        mach_write_to_4(log_buf + field + LOG_CHECKPOINT_CHECKSUM_2, fold);
 
3728
*/
 
3729
                }
 
3730
not_consistent:
 
3731
                ;
 
3732
        }
 
3733
 
 
3734
        if (ut_dulint_cmp(max_no, ut_dulint_zero) == 0) {
 
3735
                fprintf(stderr, "xtrabackup: No valid checkpoint found.\n");
 
3736
                goto error;
 
3737
        }
 
3738
 
 
3739
 
 
3740
        /* It seems to be needed to overwrite the both checkpoint area. */
 
3741
        MACH_WRITE_64(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN, max_lsn);
 
3742
        mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_OFFSET,
 
3743
                        LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
 
3744
                        ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
 
3745
#ifdef XTRADB_BASED
 
3746
        MACH_WRITE_64(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_ARCHIVED_LSN,
 
3747
                        (ib_uint64_t)(LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
 
3748
                                        ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE))));
 
3749
#endif
 
3750
        fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_1, LOG_CHECKPOINT_CHECKSUM_1);
 
3751
        mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_CHECKSUM_1, fold);
 
3752
 
 
3753
        fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_LSN,
 
3754
                LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
 
3755
        mach_write_to_4(log_buf + LOG_CHECKPOINT_1 + LOG_CHECKPOINT_CHECKSUM_2, fold);
 
3756
 
 
3757
        MACH_WRITE_64(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN, max_lsn);
 
3758
        mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_OFFSET,
 
3759
                        LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
 
3760
                        ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE)));
 
3761
#ifdef XTRADB_BASED
 
3762
        MACH_WRITE_64(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_ARCHIVED_LSN,
 
3763
                        (ib_uint64_t)(LOG_FILE_HDR_SIZE + ut_dulint_minus(max_lsn,
 
3764
                                        ut_dulint_align_down(max_lsn,OS_FILE_LOG_BLOCK_SIZE))));
 
3765
#endif
 
3766
        fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_2, LOG_CHECKPOINT_CHECKSUM_1);
 
3767
        mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_CHECKSUM_1, fold);
 
3768
 
 
3769
        fold = ut_fold_binary(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_LSN,
 
3770
                LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
 
3771
        mach_write_to_4(log_buf + LOG_CHECKPOINT_2 + LOG_CHECKPOINT_CHECKSUM_2, fold);
 
3772
 
 
3773
 
 
3774
        success = os_file_write(src_path, src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
 
3775
        if (!success) {
 
3776
                goto error;
 
3777
        }
 
3778
 
 
3779
        /* expand file size (9/8) and align to UNIV_PAGE_SIZE */
 
3780
 
 
3781
        if (file_size % UNIV_PAGE_SIZE) {
 
3782
                memset(log_buf, 0, UNIV_PAGE_SIZE);
 
3783
                success = os_file_write(src_path, src_file, log_buf,
 
3784
                                (ulint)(file_size & 0xFFFFFFFFUL),
 
3785
                                (ulint)(file_size >> 32),
 
3786
                                UNIV_PAGE_SIZE - (file_size % UNIV_PAGE_SIZE));
 
3787
                if (!success) {
 
3788
                        goto error;
 
3789
                }
 
3790
 
 
3791
                file_size = os_file_get_size_as_iblonglong(src_file);
 
3792
        }
 
3793
 
 
3794
        /* TODO: We should judge whether the file is already expanded or not... */
 
3795
        {
 
3796
                ulint   expand;
 
3797
 
 
3798
                memset(log_buf, 0, UNIV_PAGE_SIZE * 128);
 
3799
                expand = file_size / UNIV_PAGE_SIZE / 8;
 
3800
 
 
3801
                for (; expand > 128; expand -= 128) {
 
3802
                        success = os_file_write(src_path, src_file, log_buf,
 
3803
                                        (ulint)(file_size & 0xFFFFFFFFUL),
 
3804
                                        (ulint)(file_size >> 32),
 
3805
                                        UNIV_PAGE_SIZE * 128);
 
3806
                        if (!success) {
 
3807
                                goto error;
 
3808
                        }
 
3809
                        file_size += UNIV_PAGE_SIZE * 128;
 
3810
                }
 
3811
 
 
3812
                if (expand) {
 
3813
                        success = os_file_write(src_path, src_file, log_buf,
 
3814
                                        (ulint)(file_size & 0xFFFFFFFFUL),
 
3815
                                        (ulint)(file_size >> 32),
 
3816
                                        expand * UNIV_PAGE_SIZE);
 
3817
                        if (!success) {
 
3818
                                goto error;
 
3819
                        }
 
3820
                        file_size += UNIV_PAGE_SIZE * expand;
 
3821
                }
 
3822
        }
 
3823
 
 
3824
        /* make larger than 2MB */
 
3825
        if (file_size < 2*1024*1024L) {
 
3826
                memset(log_buf, 0, UNIV_PAGE_SIZE);
 
3827
                while (file_size < 2*1024*1024L) {
 
3828
                        success = os_file_write(src_path, src_file, log_buf,
 
3829
                                (ulint)(file_size & 0xFFFFFFFFUL),
 
3830
                                (ulint)(file_size >> 32),
 
3831
                                UNIV_PAGE_SIZE);
 
3832
                        if (!success) {
 
3833
                                goto error;
 
3834
                        }
 
3835
                        file_size += UNIV_PAGE_SIZE;
 
3836
                }
 
3837
                file_size = os_file_get_size_as_iblonglong(src_file);
 
3838
        }
 
3839
 
 
3840
        printf("xtrabackup: xtrabackup_logfile detected: size=%"PRIu64", start_lsn=(%"PRIu64")\n",
 
3841
                file_size, max_lsn);
 
3842
 
 
3843
        os_file_close(src_file);
 
3844
        src_file = -1;
 
3845
 
 
3846
        /* Backup log parameters */
 
3847
        innobase_log_group_home_dir_backup = innobase_log_group_home_dir;
 
3848
        innobase_log_file_size_backup      = innobase_log_file_size;
 
3849
        innobase_log_files_in_group_backup = innobase_log_files_in_group;
 
3850
 
 
3851
        /* fake InnoDB */
 
3852
        innobase_log_group_home_dir = NULL;
 
3853
        innobase_log_file_size      = file_size;
 
3854
        innobase_log_files_in_group = 1;
 
3855
 
 
3856
        srv_thread_concurrency = 0;
 
3857
 
 
3858
        /* rename 'xtrabackup_logfile' to 'ib_logfile0' */
 
3859
        success = os_file_rename(
 
3860
                        0 /* dummy of innodb_file_data_key */,
 
3861
                        src_path, dst_path);
 
3862
        if (!success) {
 
3863
                goto error;
 
3864
        }
 
3865
        xtrabackup_logfile_is_renamed = TRUE;
 
3866
 
 
3867
        ut_free(log_buf_);
 
3868
 
 
3869
        return(FALSE);
 
3870
 
 
3871
skip_modify:
 
3872
        os_file_close(src_file);
 
3873
        src_file = -1;
 
3874
        ut_free(log_buf_);
 
3875
        return(FALSE);
 
3876
 
 
3877
error:
 
3878
        if (src_file != -1)
 
3879
                os_file_close(src_file);
 
3880
        if (log_buf_)
 
3881
                ut_free(log_buf_);
 
3882
        fprintf(stderr, "xtrabackup: Error: xtrabackup_init_temp_log() failed.\n");
 
3883
        return(TRUE); /*ERROR*/
 
3884
}
 
3885
 
 
3886
/***********************************************************************
 
3887
Generates path to the meta file path from a given path to an incremental .delta
 
3888
by replacing trailing ".delta" with ".meta", or returns error if 'delta_path'
 
3889
does not end with the ".delta" character sequence.
 
3890
@return TRUE on success, FALSE on error. */
 
3891
static
 
3892
ibool
 
3893
get_meta_path(
 
3894
        const char      *delta_path,    /* in: path to a .delta file */
 
3895
        char            *meta_path)     /* out: path to the corresponding .meta
 
3896
                                        file */
 
3897
{
 
3898
        size_t          len = strlen(delta_path);
 
3899
 
 
3900
        if (len <= 6 || strcmp(delta_path + len - 6, ".delta")) {
 
3901
                return FALSE;
 
3902
        }
 
3903
        memcpy(meta_path, delta_path, len - 6);
 
3904
        strcpy(meta_path + len - 6, XB_DELTA_INFO_SUFFIX);
 
3905
 
 
3906
        return TRUE;
 
3907
}
 
3908
 
 
3909
static void
 
3910
xtrabackup_apply_delta(
 
3911
        const char*     dirname,        /* in: dir name of incremental */
 
3912
        const char*     dbname,         /* in: database name (ibdata: NULL) */
 
3913
        const char*     filename,       /* in: file name (not a path),
 
3914
                                        including the .delta extension */
 
3915
        bool )
 
3916
{
 
3917
        os_file_t       src_file = -1;
 
3918
        os_file_t       dst_file = -1;
 
3919
        char    src_path[FN_REFLEN];
 
3920
        char    dst_path[FN_REFLEN];
 
3921
        char    meta_path[FN_REFLEN];
 
3922
        ibool   success;
 
3923
 
 
3924
        ibool   last_buffer = FALSE;
 
3925
        ulint   page_in_buffer;
 
3926
        ulint   incremental_buffers = 0;
 
3927
 
 
3928
        xb_delta_info_t info;
 
3929
        ulint           page_size;
 
3930
        ulint           page_size_shift;
 
3931
 
 
3932
        ut_a(xtrabackup_incremental);
 
3933
 
 
3934
        if (dbname) {
 
3935
                snprintf(src_path, sizeof(src_path), "%s/%s/%s",
 
3936
                         dirname, dbname, filename);
 
3937
                snprintf(dst_path, sizeof(dst_path), "%s/%s/%s",
 
3938
                         xtrabackup_real_target_dir, dbname, filename);
 
3939
        } else {
 
3940
                snprintf(src_path, sizeof(src_path), "%s/%s",
 
3941
                         dirname, filename);
 
3942
                snprintf(dst_path, sizeof(dst_path), "%s/%s",
 
3943
                         xtrabackup_real_target_dir, filename);
 
3944
        }
 
3945
        dst_path[strlen(dst_path) - 6] = '\0';
 
3946
 
 
3947
        if (!get_meta_path(src_path, meta_path)) {
 
3948
                goto error;
 
3949
        }
 
3950
 
 
3951
        srv_normalize_path_for_win(dst_path);
 
3952
        srv_normalize_path_for_win(src_path);
 
3953
        srv_normalize_path_for_win(meta_path);
 
3954
 
 
3955
        if (!xb_read_delta_metadata(meta_path, &info)) {
 
3956
                goto error;
 
3957
        }
 
3958
 
 
3959
        page_size = info.page_size;
 
3960
        page_size_shift = get_bit_shift(page_size);
 
3961
        fprintf(stderr, "xtrabackup: page size for %s is %lu bytes\n",
 
3962
                src_path, page_size);
 
3963
        if (page_size_shift < 10 ||
 
3964
            page_size_shift > UNIV_PAGE_SIZE_SHIFT_MAX) {
 
3965
                fprintf(stderr,
 
3966
                        "xtrabackup: error: invalid value of page_size "
 
3967
                        "(%lu bytes) read from %s\n", page_size, meta_path);
 
3968
                goto error;
 
3969
        }
 
3970
        
 
3971
        src_file = os_file_create_simple_no_error_handling(
 
3972
                        0 /* dummy of innodb_file_data_key */,
 
3973
                        src_path, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
 
3974
        if (!success) {
 
3975
                os_file_get_last_error(TRUE);
 
3976
                fprintf(stderr,
 
3977
                        "xtrabackup: error: cannot open %s\n",
 
3978
                        src_path);
 
3979
                goto error;
 
3980
        }
 
3981
 
 
3982
#ifdef USE_POSIX_FADVISE
 
3983
        posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL);
 
3984
        posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
 
3985
#endif
 
3986
 
 
3987
        if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
 
3988
                os_file_set_nocache(src_file, src_path, "OPEN");
 
3989
        }
 
3990
 
 
3991
        dst_file = os_file_create_simple_no_error_handling(
 
3992
                        0 /* dummy of innodb_file_data_key */,
 
3993
                        dst_path, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
 
3994
        if (!success) {
 
3995
                os_file_get_last_error(TRUE);
 
3996
                fprintf(stderr,
 
3997
                        "xtrabackup: error: cannot open %s\n",
 
3998
                        dst_path);
 
3999
                goto error;
 
4000
        }
 
4001
 
 
4002
#ifdef USE_POSIX_FADVISE
 
4003
        posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED);
 
4004
#endif
 
4005
 
 
4006
        if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
 
4007
                os_file_set_nocache(dst_file, dst_path, "OPEN");
 
4008
        }
 
4009
 
 
4010
        printf("Applying %s ...\n", src_path);
 
4011
 
 
4012
        while (!last_buffer) {
 
4013
                ulint cluster_header;
 
4014
 
 
4015
                /* read to buffer */
 
4016
                /* first block of block cluster */
 
4017
                success = os_file_read(src_file, incremental_buffer,
 
4018
                                       ((incremental_buffers * (page_size / 4))
 
4019
                                        << page_size_shift) & 0xFFFFFFFFUL,
 
4020
                                       (incremental_buffers * (page_size / 4))
 
4021
                                       >> (32 - page_size_shift),
 
4022
                                       page_size);
 
4023
                if (!success) {
 
4024
                        goto error;
 
4025
                }
 
4026
 
 
4027
                cluster_header = mach_read_from_4(incremental_buffer);
 
4028
                switch(cluster_header) {
 
4029
                        case 0x78747261UL: /*"xtra"*/
 
4030
                                break;
 
4031
                        case 0x58545241UL: /*"XTRA"*/
 
4032
                                last_buffer = TRUE;
 
4033
                                break;
 
4034
                        default:
 
4035
                                fprintf(stderr,
 
4036
                                        "xtrabackup: error: %s seems not .delta file.\n",
 
4037
                                        src_path);
 
4038
                                goto error;
 
4039
                }
 
4040
 
 
4041
                for (page_in_buffer = 1; page_in_buffer < page_size / 4;
 
4042
                     page_in_buffer++) {
 
4043
                        if (mach_read_from_4(incremental_buffer + page_in_buffer * 4)
 
4044
                            == 0xFFFFFFFFUL)
 
4045
                                break;
 
4046
                }
 
4047
 
 
4048
                ut_a(last_buffer || page_in_buffer == page_size / 4);
 
4049
 
 
4050
                /* read whole of the cluster */
 
4051
                success = os_file_read(src_file, incremental_buffer,
 
4052
                                       ((incremental_buffers * (page_size / 4))
 
4053
                                        << page_size_shift) & 0xFFFFFFFFUL,
 
4054
                                       (incremental_buffers * (page_size / 4))
 
4055
                                       >> (32 - page_size_shift),
 
4056
                                       page_in_buffer * page_size);
 
4057
                if (!success) {
 
4058
                        goto error;
 
4059
                }
 
4060
 
 
4061
                for (page_in_buffer = 1; page_in_buffer < page_size / 4;
 
4062
                     page_in_buffer++) {
 
4063
                        ulint offset_on_page;
 
4064
 
 
4065
                        offset_on_page = mach_read_from_4(incremental_buffer + page_in_buffer * 4);
 
4066
 
 
4067
                        if (offset_on_page == 0xFFFFFFFFUL)
 
4068
                                break;
 
4069
 
 
4070
                        /* apply blocks in the cluster */
 
4071
//                      if (ut_dulint_cmp(incremental_lsn,
 
4072
//                              MACH_READ_64(incremental_buffer
 
4073
//                                               + page_in_buffer * page_size
 
4074
//                                               + FIL_PAGE_LSN)) >= 0)
 
4075
//                              continue;
 
4076
 
 
4077
                        success = os_file_write(dst_path, dst_file,
 
4078
                                        incremental_buffer +
 
4079
                                                page_in_buffer * page_size,
 
4080
                                        (offset_on_page << page_size_shift) &
 
4081
                                                0xFFFFFFFFUL,
 
4082
                                        offset_on_page >> (32 - page_size_shift),
 
4083
                                        page_size);
 
4084
                        if (!success) {
 
4085
                                goto error;
 
4086
                        }
 
4087
                }
 
4088
 
 
4089
                incremental_buffers++;
 
4090
        }
 
4091
 
 
4092
        if (src_file != -1)
 
4093
                os_file_close(src_file);
 
4094
        if (dst_file != -1)
 
4095
                os_file_close(dst_file);
 
4096
        return;
 
4097
 
 
4098
error:
 
4099
        if (src_file != -1)
 
4100
                os_file_close(src_file);
 
4101
        if (dst_file != -1)
 
4102
                os_file_close(dst_file);
 
4103
        fprintf(stderr, "xtrabackup: Error: xtrabackup_apply_delta() failed.\n");
 
4104
        return;
 
4105
}
 
4106
 
 
4107
static void
 
4108
xtrabackup_apply_deltas(bool check_newer)
 
4109
{
 
4110
        int             ret;
 
4111
        char            dbpath[FN_REFLEN];
 
4112
        os_file_dir_t   dir;
 
4113
        os_file_dir_t   dbdir;
 
4114
        os_file_stat_t  dbinfo;
 
4115
        os_file_stat_t  fileinfo;
 
4116
        ulint           err             = DB_SUCCESS;
 
4117
        static char     current_dir[2];
 
4118
 
 
4119
        current_dir[0] = FN_CURLIB;
 
4120
        current_dir[1] = 0;
 
4121
        srv_data_home = current_dir;
 
4122
 
 
4123
        /* datafile */
 
4124
        dbdir = os_file_opendir(xtrabackup_incremental_dir, FALSE);
 
4125
 
 
4126
        if (dbdir != NULL) {
 
4127
                ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dbdir,
 
4128
                                                        &fileinfo);
 
4129
                while (ret == 0) {
 
4130
                        if (fileinfo.type == OS_FILE_TYPE_DIR) {
 
4131
                                goto next_file_item_1;
 
4132
                        }
 
4133
 
 
4134
                        if (strlen(fileinfo.name) > 6
 
4135
                            && 0 == strcmp(fileinfo.name + 
 
4136
                                        strlen(fileinfo.name) - 6,
 
4137
                                        ".delta")) {
 
4138
                                xtrabackup_apply_delta(
 
4139
                                        xtrabackup_incremental_dir, NULL,
 
4140
                                        fileinfo.name, check_newer);
 
4141
                        }
 
4142
next_file_item_1:
 
4143
                        ret = fil_file_readdir_next_file(&err,
 
4144
                                                        xtrabackup_incremental_dir, dbdir,
 
4145
                                                        &fileinfo);
 
4146
                }
 
4147
 
 
4148
                os_file_closedir(dbdir);
 
4149
        } else {
 
4150
                fprintf(stderr, "xtrabackup: Cannot open dir %s\n", xtrabackup_incremental_dir);
 
4151
        }
 
4152
 
 
4153
        /* single table tablespaces */
 
4154
        dir = os_file_opendir(xtrabackup_incremental_dir, FALSE);
 
4155
 
 
4156
        if (dir == NULL) {
 
4157
                fprintf(stderr, "xtrabackup: Cannot open dir %s\n", xtrabackup_incremental_dir);
 
4158
        }
 
4159
 
 
4160
                ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dir,
 
4161
                                                                &dbinfo);
 
4162
        while (ret == 0) {
 
4163
                if (dbinfo.type == OS_FILE_TYPE_FILE
 
4164
                    || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
 
4165
 
 
4166
                        goto next_datadir_item;
 
4167
                }
 
4168
 
 
4169
                sprintf(dbpath, "%s/%s", xtrabackup_incremental_dir,
 
4170
                                                                dbinfo.name);
 
4171
                srv_normalize_path_for_win(dbpath);
 
4172
 
 
4173
                dbdir = os_file_opendir(dbpath, FALSE);
 
4174
 
 
4175
                if (dbdir != NULL) {
 
4176
 
 
4177
                        ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
 
4178
                                                                &fileinfo);
 
4179
                        while (ret == 0) {
 
4180
 
 
4181
                                if (fileinfo.type == OS_FILE_TYPE_DIR) {
 
4182
 
 
4183
                                        goto next_file_item_2;
 
4184
                                }
 
4185
 
 
4186
                                if (strlen(fileinfo.name) > 6
 
4187
                                    && 0 == strcmp(fileinfo.name + 
 
4188
                                                strlen(fileinfo.name) - 6,
 
4189
                                                ".delta")) {
 
4190
                                        /* The name ends in .delta; try opening
 
4191
                                        the file */
 
4192
                                        xtrabackup_apply_delta(
 
4193
                                                xtrabackup_incremental_dir, dbinfo.name,
 
4194
                                                fileinfo.name, check_newer);
 
4195
                                }
 
4196
next_file_item_2:
 
4197
                                ret = fil_file_readdir_next_file(&err,
 
4198
                                                                dbpath, dbdir,
 
4199
                                                                &fileinfo);
 
4200
                        }
 
4201
 
 
4202
                        os_file_closedir(dbdir);
 
4203
                }
 
4204
next_datadir_item:
 
4205
                ret = fil_file_readdir_next_file(&err,
 
4206
                                                xtrabackup_incremental_dir,
 
4207
                                                                dir, &dbinfo);
 
4208
        }
 
4209
 
 
4210
        os_file_closedir(dir);
 
4211
 
 
4212
}
 
4213
 
 
4214
static bool
 
4215
xtrabackup_close_temp_log(bool clear_flag)
 
4216
{
 
4217
        os_file_t       src_file = -1;
 
4218
        char    src_path[FN_REFLEN];
 
4219
        char    dst_path[FN_REFLEN];
 
4220
        ibool   success;
 
4221
 
 
4222
        byte*   log_buf;
 
4223
        byte*   log_buf_ = NULL;
 
4224
 
 
4225
 
 
4226
        if (!xtrabackup_logfile_is_renamed)
 
4227
                return(FALSE);
 
4228
 
 
4229
        /* Restore log parameters */
 
4230
        innobase_log_group_home_dir = innobase_log_group_home_dir_backup;
 
4231
        innobase_log_file_size      = innobase_log_file_size_backup;
 
4232
        innobase_log_files_in_group = innobase_log_files_in_group_backup;
 
4233
 
 
4234
        /* rename 'ib_logfile0' to 'xtrabackup_logfile' */
 
4235
        if(!xtrabackup_incremental_dir) {
 
4236
                sprintf(dst_path, "%s%s", xtrabackup_target_dir, "/ib_logfile0");
 
4237
                sprintf(src_path, "%s%s", xtrabackup_target_dir, "/xtrabackup_logfile");
 
4238
        } else {
 
4239
                sprintf(dst_path, "%s%s", xtrabackup_incremental_dir, "/ib_logfile0");
 
4240
                sprintf(src_path, "%s%s", xtrabackup_incremental_dir, "/xtrabackup_logfile");
 
4241
        }
 
4242
 
 
4243
        srv_normalize_path_for_win(dst_path);
 
4244
        srv_normalize_path_for_win(src_path);
 
4245
 
 
4246
        success = os_file_rename(
 
4247
                        0 /* dummy of innodb_file_data_key */,
 
4248
                        dst_path, src_path);
 
4249
        if (!success) {
 
4250
                goto error;
 
4251
        }
 
4252
        xtrabackup_logfile_is_renamed = FALSE;
 
4253
 
 
4254
        if (!clear_flag)
 
4255
                return(FALSE);
 
4256
 
 
4257
        /* clear LOG_FILE_WAS_CREATED_BY_HOT_BACKUP field */
 
4258
        src_file = os_file_create_simple_no_error_handling(
 
4259
                                0 /* dummy of innodb_file_data_key */,
 
4260
                                src_path, OS_FILE_OPEN,
 
4261
                                OS_FILE_READ_WRITE, &success);
 
4262
        if (!success) {
 
4263
                goto error;
 
4264
        }
 
4265
 
 
4266
#ifdef USE_POSIX_FADVISE
 
4267
        posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED);
 
4268
#endif
 
4269
 
 
4270
        if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
 
4271
                os_file_set_nocache(src_file, src_path, "OPEN");
 
4272
        }
 
4273
 
 
4274
        log_buf_ = (unsigned char*) ut_malloc(LOG_FILE_HDR_SIZE * 2);
 
4275
        log_buf = (unsigned char*) ut_align(log_buf_, LOG_FILE_HDR_SIZE);
 
4276
 
 
4277
        success = os_file_read(src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
 
4278
        if (!success) {
 
4279
                goto error;
 
4280
        }
 
4281
 
 
4282
        memset(log_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, ' ', 4);
 
4283
 
 
4284
        success = os_file_write(src_path, src_file, log_buf, 0, 0, LOG_FILE_HDR_SIZE);
 
4285
        if (!success) {
 
4286
                goto error;
 
4287
        }
 
4288
 
 
4289
        os_file_close(src_file);
 
4290
        src_file = -1;
 
4291
 
 
4292
        return(FALSE);
 
4293
error:
 
4294
        if (src_file != -1)
 
4295
                os_file_close(src_file);
 
4296
        if (log_buf_)
 
4297
                ut_free(log_buf_);
 
4298
        fprintf(stderr, "xtrabackup: Error: xtrabackup_close_temp_log() failed.\n");
 
4299
        return(TRUE); /*ERROR*/
 
4300
}
 
4301
 
 
4302
static void
 
4303
xtrabackup_prepare_func(void)
 
4304
{
 
4305
        /* cd to target-dir */
 
4306
 
 
4307
        if (chdir(xtrabackup_real_target_dir) != 0)
 
4308
        {
 
4309
                fprintf(stderr, "xtrabackup: cannot my_setwd %s\n", xtrabackup_real_target_dir);
 
4310
                exit(EXIT_FAILURE);
 
4311
        }
 
4312
        fprintf(stderr, "xtrabackup: cd to %s\n", xtrabackup_real_target_dir);
 
4313
 
 
4314
        xtrabackup_target_dir= mysql_data_home_buff;
 
4315
        mysql_data_home_buff[0]=FN_CURLIB;              // all paths are relative from here
 
4316
        mysql_data_home_buff[1]=0;
 
4317
 
 
4318
        /* read metadata of target */
 
4319
        {
 
4320
                char    filename[FN_REFLEN];
 
4321
 
 
4322
                sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
 
4323
 
 
4324
                if (xtrabackup_read_metadata(filename))
 
4325
                        fprintf(stderr, "xtrabackup: error: xtrabackup_read_metadata()\n");
 
4326
 
 
4327
                if (!strcmp(metadata_type, "full-backuped")) {
 
4328
                        fprintf(stderr, "xtrabackup: This target seems to be not prepared yet.\n");
 
4329
                } else if (!strcmp(metadata_type, "full-prepared")) {
 
4330
                        fprintf(stderr, "xtrabackup: This target seems to be already prepared.\n");
 
4331
                        goto skip_check;
 
4332
                } else {
 
4333
                        fprintf(stderr, "xtrabackup: This target seems not to have correct metadata...\n");
 
4334
                }
 
4335
 
 
4336
                if (xtrabackup_incremental) {
 
4337
                        fprintf(stderr,
 
4338
                        "xtrabackup: error: applying incremental backup needs target prepared.\n");
 
4339
                        exit(EXIT_FAILURE);
 
4340
                }
 
4341
skip_check:
 
4342
                if (xtrabackup_incremental
 
4343
                    && ut_dulint_cmp(metadata_to_lsn, incremental_lsn) != 0) {
 
4344
                        fprintf(stderr,
 
4345
                        "xtrabackup: error: This incremental backup seems not to be proper for the target.\n"
 
4346
                        "xtrabackup:  Check 'to_lsn' of the target and 'from_lsn' of the incremental.\n");
 
4347
                        exit(EXIT_FAILURE);
 
4348
                }
 
4349
        }
 
4350
 
 
4351
        /* Create logfiles for recovery from 'xtrabackup_logfile', before start InnoDB */
 
4352
        srv_max_n_threads = 1000;
 
4353
        os_sync_mutex = NULL;
 
4354
        ut_mem_init();
 
4355
#ifdef XTRADB_BASED
 
4356
        /* temporally dummy value to avoid crash */
 
4357
        srv_page_size_shift = 14;
 
4358
        srv_page_size = (1 << srv_page_size_shift);
 
4359
#endif
 
4360
        os_sync_init();
 
4361
        sync_init();
 
4362
        os_io_init_simple();
 
4363
        if(xtrabackup_init_temp_log())
 
4364
                goto error;
 
4365
 
 
4366
        if(xtrabackup_incremental)
 
4367
                xtrabackup_apply_deltas(TRUE);
 
4368
 
 
4369
        sync_close();
 
4370
        sync_initialized = FALSE;
 
4371
        os_sync_free();
 
4372
        os_sync_mutex = NULL;
 
4373
        ut_free_all_mem();
 
4374
 
 
4375
        /* check the accessibility of target-dir */
 
4376
        /* ############# TODO ##################### */
 
4377
 
 
4378
        if(innodb_init_param())
 
4379
                goto error;
 
4380
 
 
4381
        srv_apply_log_only = (ibool) xtrabackup_apply_log_only;
 
4382
 
 
4383
        /* increase IO threads */
 
4384
        if(srv_n_file_io_threads < 10) {
 
4385
                srv_n_file_io_threads = 10;
 
4386
        }
 
4387
 
 
4388
        fprintf(stderr, "xtrabackup: Starting InnoDB instance for recovery.\n"
 
4389
                "xtrabackup: Using %"PRIu64" bytes for buffer pool (set by --use-memory parameter)\n",
 
4390
                xtrabackup_use_memory);
 
4391
 
 
4392
        if(innodb_init())
 
4393
                goto error;
 
4394
 
 
4395
        //printf("Hello InnoDB world!\n");
 
4396
 
 
4397
        /* TEST: innodb status*/
 
4398
/*
 
4399
        ulint   trx_list_start = ULINT_UNDEFINED;
 
4400
        ulint   trx_list_end = ULINT_UNDEFINED;
 
4401
        srv_printf_innodb_monitor(stdout, &trx_list_start, &trx_list_end);
 
4402
*/
 
4403
        /* TEST: list of datafiles and transaction log files and LSN*/
 
4404
/*
 
4405
        {
 
4406
        fil_system_t*   f_system = fil_system;
 
4407
        fil_space_t*    space;
 
4408
        fil_node_t*     node;
 
4409
 
 
4410
        mutex_enter(&(f_system->mutex));
 
4411
 
 
4412
        space = UT_LIST_GET_FIRST(f_system->space_list);
 
4413
 
 
4414
        while (space != NULL) {
 
4415
                printf("space: name=%s, id=%d, purpose=%d, size=%d\n",
 
4416
                        space->name, space->id, space->purpose, space->size);
 
4417
 
 
4418
                node = UT_LIST_GET_FIRST(space->chain);
 
4419
 
 
4420
                while (node != NULL) {
 
4421
                        printf("node: name=%s, open=%d, size=%d\n",
 
4422
                                node->name, node->open, node->size);
 
4423
 
 
4424
                        node = UT_LIST_GET_NEXT(chain, node);
 
4425
                }
 
4426
                space = UT_LIST_GET_NEXT(space_list, space);
 
4427
        }
 
4428
 
 
4429
        mutex_exit(&(f_system->mutex));
 
4430
        }
 
4431
*/
 
4432
        /* align space sizes along with fsp header */
 
4433
        {
 
4434
        fil_system_t*   f_system = fil_system;
 
4435
        fil_space_t*    space;
 
4436
 
 
4437
        mutex_enter(&(f_system->mutex));
 
4438
        space = UT_LIST_GET_FIRST(f_system->space_list);
 
4439
 
 
4440
        while (space != NULL) {
 
4441
                byte*   header;
 
4442
                ulint   size;
 
4443
                ulint   actual_size;
 
4444
                mtr_t   mtr;
 
4445
                buf_block_t*    block;
 
4446
                ulint   flags;
 
4447
 
 
4448
                if (space->purpose == FIL_TABLESPACE) {
 
4449
                        mutex_exit(&(f_system->mutex));
 
4450
 
 
4451
                        mtr_start(&mtr);
 
4452
 
 
4453
                        mtr_s_lock(fil_space_get_latch(space->id, &flags), &mtr);
 
4454
 
 
4455
                        block = buf_page_get(space->id,
 
4456
                                             dict_table_flags_to_zip_size(flags),
 
4457
                                             0, RW_S_LATCH, &mtr);
 
4458
                        header = FIL_PAGE_DATA /*FSP_HEADER_OFFSET*/
 
4459
                                + buf_block_get_frame(block);
 
4460
 
 
4461
                        size = mtr_read_ulint(header + 8 /* FSP_SIZE */, MLOG_4BYTES, &mtr);
 
4462
 
 
4463
                        mtr_commit(&mtr);
 
4464
 
 
4465
                        //printf("%d, %d\n", space->id, size);
 
4466
 
 
4467
                        fil_extend_space_to_desired_size(&actual_size, space->id, size);
 
4468
 
 
4469
                        mutex_enter(&(f_system->mutex));
 
4470
                }
 
4471
 
 
4472
                space = UT_LIST_GET_NEXT(space_list, space);
 
4473
        }
 
4474
 
 
4475
        mutex_exit(&(f_system->mutex));
 
4476
        }
 
4477
 
 
4478
 
 
4479
 
 
4480
        if (xtrabackup_export) {
 
4481
                printf("xtrabackup: export option is specified.\n");
 
4482
                if (innobase_file_per_table) {
 
4483
                        fil_system_t*   f_system = fil_system;
 
4484
                        fil_space_t*    space;
 
4485
                        fil_node_t*     node;
 
4486
                        os_file_t       info_file = -1;
 
4487
                        char            info_file_path[FN_REFLEN];
 
4488
                        ibool           success;
 
4489
                        char            table_name[FN_REFLEN];
 
4490
 
 
4491
                        byte*           page;
 
4492
                        byte*           buf = NULL;
 
4493
 
 
4494
                        buf = (byte*) ut_malloc(UNIV_PAGE_SIZE * 2);
 
4495
                        page = (byte*) ut_align(buf, UNIV_PAGE_SIZE);
 
4496
 
 
4497
                        /* flush insert buffer at shutdwon */
 
4498
                        innobase_fast_shutdown = 0;
 
4499
 
 
4500
                        mutex_enter(&(f_system->mutex));
 
4501
 
 
4502
                        space = UT_LIST_GET_FIRST(f_system->space_list);
 
4503
                        while (space != NULL) {
 
4504
                                /* treat file_per_table only */
 
4505
                                if (space->purpose != FIL_TABLESPACE
 
4506
#ifdef XTRADB_BASED
 
4507
                                    || trx_sys_sys_space(space->id)
 
4508
#else
 
4509
                                    || space->id == 0
 
4510
#endif
 
4511
                                   )
 
4512
                                {
 
4513
                                        space = UT_LIST_GET_NEXT(space_list, space);
 
4514
                                        continue;
 
4515
                                }
 
4516
 
 
4517
                                node = UT_LIST_GET_FIRST(space->chain);
 
4518
                                while (node != NULL) {
 
4519
                                        int len;
 
4520
                                        char *next, *prev, *p;
 
4521
                                        dict_table_t*   table;
 
4522
                                        dict_index_t*   index;
 
4523
                                        ulint           n_index;
 
4524
 
 
4525
                                        /* node exist == file exist, here */
 
4526
                                        strncpy(info_file_path, node->name, FN_REFLEN);
 
4527
                                        len = strlen(info_file_path);
 
4528
                                        info_file_path[len - 3] = 'e';
 
4529
                                        info_file_path[len - 2] = 'x';
 
4530
                                        info_file_path[len - 1] = 'p';
 
4531
 
 
4532
                                        p = info_file_path;
 
4533
                                        prev = NULL;
 
4534
                                        while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL)
 
4535
                                        {
 
4536
                                                prev = p;
 
4537
                                                p = next + 1;
 
4538
                                        }
 
4539
                                        info_file_path[len - 4] = 0;
 
4540
                                        strncpy(table_name, prev, FN_REFLEN);
 
4541
 
 
4542
                                        info_file_path[len - 4] = '.';
 
4543
 
 
4544
                                        mutex_exit(&(f_system->mutex));
 
4545
                                        mutex_enter(&(dict_sys->mutex));
 
4546
 
 
4547
                                        table = dict_table_get_low(table_name);
 
4548
                                        if (!table) {
 
4549
                                                fprintf(stderr,
 
4550
"xtrabackup: error: cannot find dictionary record of table %s\n", table_name);
 
4551
                                                goto next_node;
 
4552
                                        }
 
4553
                                        index = dict_table_get_first_index(table);
 
4554
                                        n_index = UT_LIST_GET_LEN(table->indexes);
 
4555
                                        if (n_index > 31) {
 
4556
                                                fprintf(stderr,
 
4557
"xtrabackup: error: sorry, cannot export over 31 indexes for now.\n");
 
4558
                                                goto next_node;
 
4559
                                        }
 
4560
 
 
4561
                                        /* init exp file */
 
4562
                                        bzero(page, UNIV_PAGE_SIZE);
 
4563
                                        mach_write_to_4(page    , 0x78706f72UL);
 
4564
                                        mach_write_to_4(page + 4, 0x74696e66UL);/*"xportinf"*/
 
4565
                                        mach_write_to_4(page + 8, n_index);
 
4566
                                        strncpy((char*)page + 12, table_name, 500);
 
4567
 
 
4568
                                        printf(
 
4569
"xtrabackup: export metadata of table '%s' to file `%s` (%lu indexes)\n",
 
4570
                                                table_name, info_file_path, n_index);
 
4571
 
 
4572
                                        n_index = 1;
 
4573
                                        while (index) {
 
4574
                                                mach_write_to_8(page + n_index * 512, index->id);
 
4575
                                                mach_write_to_4(page + n_index * 512 + 8,
 
4576
                                                                index->page);
 
4577
 
 
4578
                                                strncpy((char*)page + n_index * 512 + 12, index->name, 500);
 
4579
 
 
4580
                                                printf(
 
4581
"xtrabackup:     name=%s, id.low=%lu, page=%lu\n",
 
4582
                                                        index->name,
 
4583
                                                        (ulint)(index->id & 0xFFFFFFFFUL),
 
4584
 
 
4585
                                                        (ulint) index->page);
 
4586
 
 
4587
                                                index = dict_table_get_next_index(index);
 
4588
                                                n_index++;
 
4589
                                        }
 
4590
 
 
4591
                                        srv_normalize_path_for_win(info_file_path);
 
4592
                                        info_file = os_file_create(
 
4593
                                                                0 /* dummy of innodb_file_data_key */,
 
4594
                                                                info_file_path, OS_FILE_OVERWRITE,
 
4595
                                                                OS_FILE_NORMAL, OS_DATA_FILE, &success);
 
4596
                                        if (!success) {
 
4597
                                                os_file_get_last_error(TRUE);
 
4598
                                                goto next_node;
 
4599
                                        }
 
4600
                                        success = os_file_write(info_file_path, info_file, page,
 
4601
                                                                0, 0, UNIV_PAGE_SIZE);
 
4602
                                        if (!success) {
 
4603
                                                os_file_get_last_error(TRUE);
 
4604
                                                goto next_node;
 
4605
                                        }
 
4606
                                        success = os_file_flush(info_file);
 
4607
                                        if (!success) {
 
4608
                                                os_file_get_last_error(TRUE);
 
4609
                                                goto next_node;
 
4610
                                        }
 
4611
next_node:
 
4612
                                        if (info_file != -1) {
 
4613
                                                os_file_close(info_file);
 
4614
                                                info_file = -1;
 
4615
                                        }
 
4616
                                        mutex_exit(&(dict_sys->mutex));
 
4617
                                        mutex_enter(&(f_system->mutex));
 
4618
 
 
4619
                                        node = UT_LIST_GET_NEXT(chain, node);
 
4620
                                }
 
4621
 
 
4622
                                space = UT_LIST_GET_NEXT(space_list, space);
 
4623
                        }
 
4624
                        mutex_exit(&(f_system->mutex));
 
4625
 
 
4626
                        ut_free(buf);
 
4627
                } else {
 
4628
                        printf("xtrabackup: export option is for file_per_table only, disabled.\n");
 
4629
                }
 
4630
        }
 
4631
 
 
4632
        /* print binlog position (again?) */
 
4633
        printf("\n[notice (again)]\n"
 
4634
                "  If you use binary log and don't use any hack of group commit,\n"
 
4635
                "  the binary log position seems to be:\n");
 
4636
// FIXME:       trx_sys_print_mysql_binlog_offset();
 
4637
        printf("\n");
 
4638
 
 
4639
        /* output to xtrabackup_binlog_pos_innodb */
 
4640
        if (false) {
 
4641
//FIXME if (*trx_sys_mysql_bin_log_name != '\0') {
 
4642
                FILE *fp;
 
4643
 
 
4644
                fp = fopen("xtrabackup_binlog_pos_innodb", "w");
 
4645
                if (fp) {
 
4646
                        fprintf(fp, "%s\t%llu\n",
 
4647
                                "none", 0ULL);
 
4648
                                /* FIXME
 
4649
                                trx_sys_mysql_bin_log_name,
 
4650
                                trx_sys_mysql_bin_log_pos);*/
 
4651
                        fclose(fp);
 
4652
                } else {
 
4653
                        printf("xtrabackup: failed to open 'xtrabackup_binlog_pos_innodb'\n");
 
4654
                }
 
4655
        }
 
4656
 
 
4657
        /* Check whether the log is applied enough or not. */
 
4658
        if ((xtrabackup_incremental
 
4659
             && ut_dulint_cmp(srv_start_lsn, incremental_last_lsn) < 0)
 
4660
            ||(!xtrabackup_incremental
 
4661
               && ut_dulint_cmp(srv_start_lsn, metadata_last_lsn) < 0)) {
 
4662
                printf( "xtrabackup: ########################################################\n"
 
4663
                        "xtrabackup: # !!WARNING!!                                          #\n"
 
4664
                        "xtrabackup: # The transaction log file should be wrong or corrupt. #\n"
 
4665
                        "xtrabackup: # The log was not applied to the intended LSN!         #\n"
 
4666
                        "xtrabackup: ########################################################\n");
 
4667
                if (xtrabackup_incremental) {
 
4668
                        printf("xtrabackup: The intended lsn is %"PRIu64"\n",
 
4669
                                incremental_last_lsn);
 
4670
                } else {
 
4671
                        printf("xtrabackup: The intended lsn is %"PRIu64"\n",
 
4672
                                metadata_last_lsn);
 
4673
                }
 
4674
        }
 
4675
 
 
4676
        if(innodb_end())
 
4677
                goto error;
 
4678
 
 
4679
        sync_initialized = FALSE;
 
4680
        os_sync_mutex = NULL;
 
4681
 
 
4682
        /* re-init necessary components */
 
4683
        ut_mem_init();
 
4684
 
 
4685
        os_sync_init();
 
4686
        sync_init();
 
4687
        os_io_init_simple();
 
4688
 
 
4689
        if(xtrabackup_close_temp_log(TRUE))
 
4690
                exit(EXIT_FAILURE);
 
4691
 
 
4692
        /* output to metadata file */
 
4693
        {
 
4694
                char    filename[FN_REFLEN];
 
4695
 
 
4696
                strcpy(metadata_type, "full-prepared");
 
4697
 
 
4698
                if(xtrabackup_incremental
 
4699
                   && ut_dulint_cmp(metadata_to_lsn, incremental_to_lsn) < 0)
 
4700
                {
 
4701
                        metadata_to_lsn = incremental_to_lsn;
 
4702
                        metadata_last_lsn = incremental_last_lsn;
 
4703
                }
 
4704
 
 
4705
                sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME);
 
4706
                if (xtrabackup_write_metadata(filename))
 
4707
                        fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_target_dir)\n");
 
4708
 
 
4709
                if(xtrabackup_extra_lsndir) {
 
4710
                        sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME);
 
4711
                        if (xtrabackup_write_metadata(filename))
 
4712
                                fprintf(stderr, "xtrabackup: error: xtrabackup_write_metadata(xtrabackup_extra_lsndir)\n");
 
4713
                }
 
4714
        }
 
4715
 
 
4716
        if(!xtrabackup_create_ib_logfile)
 
4717
                return;
 
4718
 
 
4719
        /* TODO: make more smart */
 
4720
 
 
4721
        printf("\n[notice]\nWe cannot call InnoDB second time during the process lifetime.\n");
 
4722
        printf("Please re-execte to create ib_logfile*. Sorry.\n");
 
4723
/*
 
4724
        printf("Restart InnoDB to create ib_logfile*.\n");
 
4725
 
 
4726
        if(innodb_init_param())
 
4727
                goto error;
 
4728
 
 
4729
        if(innodb_init())
 
4730
                goto error;
 
4731
 
 
4732
        if(innodb_end())
 
4733
                goto error;
 
4734
*/
 
4735
 
 
4736
        return;
 
4737
 
 
4738
error:
 
4739
        xtrabackup_close_temp_log(FALSE);
 
4740
 
 
4741
        exit(EXIT_FAILURE);
 
4742
}
 
4743
 
 
4744
/* ================= main =================== */
 
4745
 
 
4746
int main(int argc, char **argv)
 
4747
{
 
4748
        po::options_description commandline_options(_("Options used only in command line"));
 
4749
        commandline_options.add_options()
 
4750
          ("target-dir", po::value<std::string>(), _("destination directory"))
 
4751
          ("backup", po::value<bool>(&xtrabackup_backup)->default_value(false)->zero_tokens(), _("take backup to target-dir"))
 
4752
        ("stats", po::value<bool>(&xtrabackup_stats)->default_value(false)->zero_tokens(), _("calc statistic of datadir (offline mysqld is recommended)"))
 
4753
        ("prepare", po::value<bool>(&xtrabackup_prepare)->default_value(false)->zero_tokens(), _("prepare a backup for starting mysql server on the backup."))
 
4754
        ("export", po::value<bool>(&xtrabackup_export)->default_value(false)->zero_tokens(), _("create files to import to another database when prepare."))
 
4755
        ("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."))
 
4756
        ("print-param", po::value<bool>(&xtrabackup_print_param)->default_value(false)->zero_tokens(), _("print parameter of mysqld needed for copyback."))
 
4757
        ("use-memory", po::value<uint64_t>(&xtrabackup_use_memory)->default_value(100*1024*1024), _("The value is used instead of buffer_pool_size"))
 
4758
        ("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'"))
 
4759
        ("throttle", po::value<long>(&xtrabackup_throttle), _("limit count of IO operations (pairs of read&write) per second to IOS values (for '--backup')"))
 
4760
        ("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')."))
 
4761
          ("extra-lsndir", po::value<std::string>(), _("(for --backup): save an extra copy of the xtrabackup_checkpoints file in this directory."))
 
4762
          ("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!"))
 
4763
          ("incremental-basedir", po::value<std::string>(), _("(for --backup): copy only .ibd pages newer than backup at specified directory."))
 
4764
          ("incremental-dir", po::value<std::string>(), _("(for --prepare): apply .delta files and logfile in the specified directory."))
 
4765
          ("tables", po::value<std::string>(), _("filtering by regexp for table names."))
 
4766
          ("tables-file", po::value<std::string>(), _("filtering by list of the exact database.table name in the file."))
 
4767
        ("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. ###"))
 
4768
          ("datadir,h", po::value<std::string>(), _("Path to the database root."))
 
4769
          ("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."))
 
4770
        ("parallel", po::value<uint32_t>(&parallel)->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."))
 
4771
        ("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."))
 
4772
        ("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."))
 
4773
        ("innodb-autoextend-increment", po::value<uint32_t>(&srv_auto_extend_increment)->default_value(8), _("Data file autoextend increment in megabytes"))
 
4774
        ("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."))
 
4775
        ("innodb-checksums", po::value<bool>(&innobase_use_checksums)->default_value(true), _("Enable InnoDB checksums validation (enabled by default). Disable with --skip-innodb-checksums."))
 
4776
          ("innodb-data-file-path", po::value<std::string>(), _("Path to individual files and their sizes."))
 
4777
          ("innodb-data-home-dir", po::value<std::string>(), _("The common part for InnoDB table spaces."))
 
4778
        ("innodb-doublewrite", po::value<bool>(&innobase_use_doublewrite)->default_value(true), _("Enable InnoDB doublewrite buffer (enabled by default). Disable with --skip-innodb-doublewrite."))
 
4779
        ("innodb-file-io-threads", po::value<long>(&innobase_file_io_threads)->default_value(4), _("Number of file I/O threads in InnoDB."))
 
4780
        ("innodb-file-per-table", po::value<bool>(&innobase_file_per_table), _("Stores each InnoDB table to an .ibd file in the database dir."))
 
4781
        ("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)."))
 
4782
          ("innodb-flush-method", po::value<std::string>(), _("With which method to flush data."))
 
4783
/* ####### Should we use this option? ####### */
 
4784
         ("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."))
 
4785
        ("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."))
 
4786
        ("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."))
 
4787
        ("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."))
 
4788
        ("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."))
 
4789
          ("innodb-log-group-home-dir", po::value<std::string>(), _("Path to InnoDB log files."))
 
4790
        ("innodb-max_dirty-pages-pct", po::value<ulong>(&srv_max_buf_pool_modified_pct)->default_value(90), _("Percentage of dirty pages allowed in bufferpool."))
 
4791
        ("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."))
 
4792
#ifdef XTRADB_BASED
 
4793
        ("innodb-page-size", po::value<uint32_t>(&innobase_page_size)->default_value(1 << 14), _("The universal page size of the database."))
 
4794
        ("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!"))
 
4795
        ("innodb-fast-checksum", po::value<bool>(&innobase_fast_checksum), _("Change the algorithm of checksum for the whole of datapage to 4-bytes word based."))
 
4796
        ("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."))
 
4797
        ("innodb-doublewrite-file", po::value<char *>(&innobase_doublewrite_file), _("Path to special datafile for doublewrite buffer. (default is "": not used)"))
 
4798
#endif
 
4799
        ;
 
4800
 
 
4801
        po::variables_map vm;
 
4802
        // Disable allow_guessing, it is evil and broken
 
4803
        int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
 
4804
        po::store(po::command_line_parser(argc, argv).options(commandline_options).style(style).run(), vm);
 
4805
        po::notify(vm);
 
4806
 
 
4807
        if (vm.count("target-dir"))
 
4808
          xtrabackup_target_dir= vm["target-dir"].as<std::string>().c_str();
 
4809
 
 
4810
        if (vm.count("extra-lsndir"))
 
4811
          xtrabackup_extra_lsndir= vm["extra-lsndir"].as<std::string>().c_str();
 
4812
 
 
4813
        if (vm.count("incremental-lsn"))
 
4814
          xtrabackup_incremental= vm["incremental-lsn"].as<std::string>().c_str();
 
4815
 
 
4816
        if (vm.count("incremental-basedir"))
 
4817
          xtrabackup_incremental_basedir= vm["incremental-basedir"].as<std::string>().c_str();
 
4818
 
 
4819
        boost::scoped_ptr<char> xtrabackup_tables_autoptr(new char[(vm.count("tables")) ? vm["tables"].as<std::string>().length() + 1: 0]);
 
4820
        if (vm.count("tables"))
 
4821
        {
 
4822
          xtrabackup_tables= xtrabackup_tables_autoptr.get();
 
4823
          strcpy(xtrabackup_tables, vm["tables"].as<std::string>().c_str());
 
4824
        }
 
4825
 
 
4826
        if (vm.count("tables-file"))
 
4827
          xtrabackup_tables_file= vm["tables-file"].as<std::string>().c_str();
 
4828
 
 
4829
        if (vm.count("tmpdir"))
 
4830
          opt_mysql_tmpdir= vm["tmpdir"].as<std::string>().c_str();
 
4831
 
 
4832
        if (vm.count("innodb-data-file-path"))
 
4833
          innobase_data_file_path= vm["innodb-data-file-path"].as<std::string>().c_str();
 
4834
 
 
4835
        boost::scoped_ptr<char> xtrabackup_incremental_dir_autoptr(new char[(vm.count("incremental-dir")) ? vm["incremental-dir"].as<std::string>().length() + 1: 0]);
 
4836
        if (vm.count("incremental-dir"))
 
4837
        {
 
4838
          xtrabackup_incremental_dir= xtrabackup_incremental_dir_autoptr.get();
 
4839
          strcpy(xtrabackup_incremental_dir, vm["incremental-dir"].as<std::string>().c_str());
 
4840
        }
 
4841
 
 
4842
        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]);
 
4843
        if (vm.count("innodb-data-home-dir"))
 
4844
        {
 
4845
          innobase_data_home_dir= innobase_data_home_dir_autoptr.get();
 
4846
          strcpy(innobase_data_home_dir, vm["innodb-data-home-dir"].as<std::string>().c_str());
 
4847
        }
 
4848
 
 
4849
        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]);
 
4850
        if (vm.count("innodb-flush-method"))
 
4851
        {
 
4852
          innobase_unix_file_flush_method= innobase_flush_method_autoptr.get();
 
4853
          strcpy(innobase_unix_file_flush_method, vm["innodb-flush-method"].as<std::string>().c_str());
 
4854
        }
 
4855
 
 
4856
        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]);
 
4857
 
 
4858
        if (vm.count("innodb-log-group-home-dir"))
 
4859
        {
 
4860
          innobase_log_group_home_dir= innobase_log_group_home_dir_autoptr.get();
 
4861
          strcpy(innobase_log_group_home_dir, vm["innodb-log-group-home-dir"].as<std::string>().c_str());
 
4862
        }
 
4863
 
 
4864
        xtrabackup_use_memory-= xtrabackup_use_memory % (1024*1024);
 
4865
        if (xtrabackup_use_memory < (1024*1024)) {
 
4866
                fprintf(stderr, "xtrabackup: use-memory out of range\n");
 
4867
                exit(EXIT_FAILURE);
 
4868
        }
 
4869
 
 
4870
        if (parallel < 1) {
 
4871
                fprintf(stderr, "xtrabackup: parallel needs to be greater than 0\n");
 
4872
                exit(EXIT_FAILURE);
 
4873
        }
 
4874
 
 
4875
        innobase_additional_mem_pool_size-= innobase_additional_mem_pool_size % 1024;
 
4876
        if (innobase_additional_mem_pool_size < (512*1024)) {
 
4877
                fprintf(stderr, "xtrabackup: innodb-additional-mem-pool-size out of range\n");
 
4878
                exit(EXIT_FAILURE);             
 
4879
        }
 
4880
 
 
4881
        if ((srv_auto_extend_increment < 1) || (srv_auto_extend_increment > 8)) {
 
4882
                fprintf(stderr, "xtrabackup: innodb-auto-extend-increment out of range\n");
 
4883
                exit(EXIT_FAILURE);             
 
4884
        }
 
4885
 
 
4886
        innobase_buffer_pool_size-= innobase_buffer_pool_size % (1024*1024);
 
4887
        if (innobase_buffer_pool_size < (1024*1024)) {
 
4888
                fprintf(stderr, "xtrabackup: innodb-buffer-pool-size out of range\n");
 
4889
                exit(EXIT_FAILURE);
 
4890
        }
 
4891
 
 
4892
        if ((innobase_file_io_threads < 4) || (innobase_file_io_threads > 64)) {
 
4893
                fprintf(stderr, "xtrabackup: innodb-file-io-threads out of range\n");
 
4894
                exit(EXIT_FAILURE);             
 
4895
        }
 
4896
 
 
4897
        if (srv_flush_log_at_trx_commit > 2) {
 
4898
                fprintf(stderr, "xtrabackup: innodb-flush-log-at-trx-commit out of range\n");
 
4899
                exit(EXIT_FAILURE);             
 
4900
        }
 
4901
 
 
4902
        if (innobase_force_recovery > 6) {
 
4903
                fprintf(stderr, "xtrabackup: innodb-force-recovery out of range\n");
 
4904
                exit(EXIT_FAILURE);             
 
4905
        }
 
4906
 
 
4907
        if ((innobase_lock_wait_timeout < 1) || (innobase_lock_wait_timeout > (1024*1024*1024))) {
 
4908
                fprintf(stderr, "xtrabackup: innodb-lock-wait-timeout out of range\n");
 
4909
                exit(EXIT_FAILURE);             
 
4910
        }
 
4911
 
 
4912
        innobase_log_buffer_size-= innobase_log_buffer_size % 1024;
 
4913
        if (innobase_additional_mem_pool_size < (256*1024)) {
 
4914
                fprintf(stderr, "xtrabackup: innodb-log-buffer-size out of range\n");
 
4915
                exit(EXIT_FAILURE);             
 
4916
        }
 
4917
 
 
4918
        if (innobase_additional_mem_pool_size < (1024*1024)) {
 
4919
                fprintf(stderr, "xtrabackup: innodb-log-file-size out of range\n");
 
4920
                exit(EXIT_FAILURE);             
 
4921
        }
 
4922
 
 
4923
        if ((innobase_log_files_in_group < 2) || (innobase_log_files_in_group > (100))) {
 
4924
                fprintf(stderr, "xtrabackup: innodb-log-files-in-group out of range\n");
 
4925
                exit(EXIT_FAILURE);             
 
4926
        }
 
4927
 
 
4928
        if (srv_max_buf_pool_modified_pct > 100) {
 
4929
                fprintf(stderr, "xtrabackup: innodb-max-buf-pool-modified-pct out of range\n");
 
4930
                exit(EXIT_FAILURE);             
 
4931
        }
 
4932
 
 
4933
        if (innobase_open_files < 10) {
 
4934
                fprintf(stderr, "xtrabackup: innodb-open-files out of range\n");
 
4935
                exit(EXIT_FAILURE);             
 
4936
        }
 
4937
 
 
4938
        if ((innobase_page_size < (1 << 12)) || (innobase_page_size > (1 << UNIV_PAGE_SIZE_SHIFT_MAX))) {
 
4939
                fprintf(stderr, "xtrabackup: innodb-page-size out of range\n");
 
4940
                exit(EXIT_FAILURE);             
 
4941
        }
 
4942
 
 
4943
        if ((innobase_log_block_size < (512)) || (innobase_log_block_size > (1 << UNIV_PAGE_SIZE_SHIFT_MAX))) {
 
4944
                fprintf(stderr, "xtrabackup: innodb-log-block-size out of range\n");
 
4945
                exit(EXIT_FAILURE);             
 
4946
        }
 
4947
 
 
4948
        if (vm.count("datadir"))
 
4949
        {
 
4950
          mysql_data_home_arg.assign(vm["datadir"].as<std::string>());
 
4951
        }
 
4952
        else
 
4953
        {
 
4954
          mysql_data_home_arg.assign(LOCALSTATEDIR);
 
4955
        }
 
4956
 
 
4957
        mysql_data_home= (char*)malloc(mysql_data_home_arg.length());
 
4958
        strcpy(mysql_data_home, mysql_data_home_arg.c_str());
 
4959
 
 
4960
        if ((!xtrabackup_prepare) && (strcmp(mysql_data_home, "./") == 0)) {
 
4961
                if (!xtrabackup_print_param)
 
4962
                        usage();
 
4963
                printf("\nxtrabackup: Error: Please set parameter 'datadir'\n");
 
4964
                exit(EXIT_FAILURE);
 
4965
        }
 
4966
 
 
4967
        if (xtrabackup_tables) {
 
4968
                /* init regexp */
 
4969
                char *p, *next;
 
4970
                int i;
 
4971
                char errbuf[100];
 
4972
 
 
4973
                tables_regex_num = 1;
 
4974
 
 
4975
                p = xtrabackup_tables;
 
4976
                while ((p = strchr(p, ',')) != NULL) {
 
4977
                        p++;
 
4978
                        tables_regex_num++;
 
4979
                }
 
4980
 
 
4981
                tables_regex = (regex_t*) ut_malloc(sizeof(regex_t) * tables_regex_num);
 
4982
 
 
4983
                p = xtrabackup_tables;
 
4984
                for (i=0; i < tables_regex_num; i++) {
 
4985
                        next = strchr(p, ',');
 
4986
                        ut_a(next || i == tables_regex_num - 1);
 
4987
 
 
4988
                        next++;
 
4989
                        if (i != tables_regex_num - 1)
 
4990
                                *(next - 1) = '\0';
 
4991
 
 
4992
                        regerror(regcomp(&tables_regex[i],p,REG_EXTENDED),
 
4993
                                        &tables_regex[i],errbuf,sizeof(errbuf));
 
4994
                        fprintf(stderr, "xtrabackup: tables regcomp(%s): %s\n",p,errbuf);
 
4995
 
 
4996
                        if (i != tables_regex_num - 1)
 
4997
                                *(next - 1) = ',';
 
4998
                        p = next;
 
4999
                }
 
5000
        }
 
5001
 
 
5002
        if (xtrabackup_tables_file) {
 
5003
                char name_buf[NAME_LEN*2+2];
 
5004
                FILE *fp;
 
5005
 
 
5006
                if (xtrabackup_stream) {
 
5007
                        fprintf(stderr, "xtrabackup: Warning: --tables_file option doesn't affect with --stream.\n");
 
5008
                        xtrabackup_tables_file = NULL;
 
5009
                        goto skip_tables_file_register;
 
5010
                }
 
5011
 
 
5012
                name_buf[NAME_LEN*2+1] = '\0';
 
5013
 
 
5014
                /* init tables_hash */
 
5015
                tables_hash = hash_create(1000);
 
5016
 
 
5017
                /* read and store the filenames */
 
5018
                fp = fopen(xtrabackup_tables_file,"r");
 
5019
                if (!fp) {
 
5020
                        fprintf(stderr, "xtrabackup: cannot open %s\n", xtrabackup_tables_file);
 
5021
                        exit(EXIT_FAILURE);
 
5022
                }
 
5023
                for (;;) {
 
5024
                        xtrabackup_tables_t*    table;
 
5025
                        char*   p = name_buf;
 
5026
 
 
5027
                        if ( fgets(name_buf, NAME_LEN*2+1, fp) == 0 ) {
 
5028
                                break;
 
5029
                        }
 
5030
 
 
5031
                        while (*p != '\0') {
 
5032
                                if (*p == '.') {
 
5033
                                        *p = '/';
 
5034
                                }
 
5035
                                p++;
 
5036
                        }
 
5037
                        p = strchr(name_buf, '\n');
 
5038
                        if (p)
 
5039
                        {
 
5040
                                *p = '\0';
 
5041
                        }
 
5042
 
 
5043
                        table = (xtrabackup_tables_t*) malloc(sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1);
 
5044
                        memset(table, '\0', sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1);
 
5045
                        table->name = ((char*)table) + sizeof(xtrabackup_tables_t);
 
5046
                        strcpy(table->name, name_buf);
 
5047
 
 
5048
                        HASH_INSERT(xtrabackup_tables_t, name_hash, tables_hash,
 
5049
                                        ut_fold_string(table->name), table);
 
5050
 
 
5051
                        printf("xtrabackup: table '%s' is registerd to the list.\n", table->name);
 
5052
                }
 
5053
        }
 
5054
skip_tables_file_register:
 
5055
 
 
5056
#ifdef XTRADB_BASED
 
5057
        /* temporary setting of enough size */
 
5058
        srv_page_size_shift = UNIV_PAGE_SIZE_SHIFT_MAX;
 
5059
        srv_page_size = UNIV_PAGE_SIZE_MAX;
 
5060
        srv_log_block_size = 512;
 
5061
#endif
 
5062
        if (xtrabackup_backup && xtrabackup_incremental) {
 
5063
                /* direct specification is only for --backup */
 
5064
                /* and the lsn is prior to the other option */
 
5065
 
 
5066
                char* endchar;
 
5067
                int error = 0;
 
5068
 
 
5069
                incremental_lsn = strtoll(xtrabackup_incremental, &endchar, 10);
 
5070
                if (*endchar != '\0')
 
5071
                        error = 1;
 
5072
 
 
5073
                if (error) {
 
5074
                        fprintf(stderr, "xtrabackup: value '%s' may be wrong format for incremental option.\n",
 
5075
                                xtrabackup_incremental);
 
5076
                        exit(EXIT_FAILURE);
 
5077
                }
 
5078
 
 
5079
                /* allocate buffer for incremental backup (4096 pages) */
 
5080
                incremental_buffer_base = (byte*) malloc((UNIV_PAGE_SIZE_MAX / 4 + 1) *
 
5081
                                                 UNIV_PAGE_SIZE_MAX);
 
5082
                incremental_buffer = (byte*) ut_align(incremental_buffer_base,
 
5083
                                              UNIV_PAGE_SIZE_MAX);
 
5084
        } else if (xtrabackup_backup && xtrabackup_incremental_basedir) {
 
5085
                char    filename[FN_REFLEN];
 
5086
 
 
5087
                sprintf(filename, "%s/%s", xtrabackup_incremental_basedir, XTRABACKUP_METADATA_FILENAME);
 
5088
 
 
5089
                if (xtrabackup_read_metadata(filename)) {
 
5090
                        fprintf(stderr,
 
5091
                                "xtrabackup: error: failed to read metadata from %s\n",
 
5092
                                filename);
 
5093
                        exit(EXIT_FAILURE);
 
5094
                }
 
5095
 
 
5096
                incremental_lsn = metadata_to_lsn;
 
5097
                xtrabackup_incremental = xtrabackup_incremental_basedir; //dummy
 
5098
 
 
5099
                /* allocate buffer for incremental backup (4096 pages) */
 
5100
                incremental_buffer_base = (byte*) malloc((UNIV_PAGE_SIZE_MAX / 4 + 1) *
 
5101
                                                 UNIV_PAGE_SIZE_MAX);
 
5102
                incremental_buffer = (byte*) ut_align(incremental_buffer_base,
 
5103
                                              UNIV_PAGE_SIZE_MAX);
 
5104
        } else if (xtrabackup_prepare && xtrabackup_incremental_dir) {
 
5105
                char    filename[FN_REFLEN];
 
5106
 
 
5107
                sprintf(filename, "%s/%s", xtrabackup_incremental_dir, XTRABACKUP_METADATA_FILENAME);
 
5108
 
 
5109
                if (xtrabackup_read_metadata(filename)) {
 
5110
                        fprintf(stderr,
 
5111
                                "xtrabackup: error: failed to read metadata from %s\n",
 
5112
                                filename);
 
5113
                        exit(EXIT_FAILURE);
 
5114
                }
 
5115
 
 
5116
                incremental_lsn = metadata_from_lsn;
 
5117
                incremental_to_lsn = metadata_to_lsn;
 
5118
                incremental_last_lsn = metadata_last_lsn;
 
5119
                xtrabackup_incremental = xtrabackup_incremental_dir; //dummy
 
5120
 
 
5121
                /* allocate buffer for incremental backup (4096 pages) */
 
5122
                incremental_buffer_base = (byte*) malloc((UNIV_PAGE_SIZE / 4 + 1) *
 
5123
                                                 UNIV_PAGE_SIZE);
 
5124
                incremental_buffer = (byte*) ut_align(incremental_buffer_base,
 
5125
                                              UNIV_PAGE_SIZE);
 
5126
        } else {
 
5127
          /* allocate buffer for applying incremental (for header page only) */
 
5128
          incremental_buffer_base = (byte*) malloc((1 + 1) * UNIV_PAGE_SIZE_MAX);
 
5129
          incremental_buffer = (byte*) ut_align(incremental_buffer_base,
 
5130
                                                UNIV_PAGE_SIZE_MAX);
 
5131
 
 
5132
                xtrabackup_incremental = NULL;
 
5133
        }
 
5134
 
 
5135
        /* --print-param */
 
5136
        if (xtrabackup_print_param) {
 
5137
                printf("# This MySQL options file was generated by XtraBackup.\n");
 
5138
                printf("[mysqld]\n");
 
5139
                printf("datadir = \"%s\"\n", mysql_data_home);
 
5140
                printf("tmpdir = \"%s\"\n", opt_mysql_tmpdir);
 
5141
                printf("innodb_data_home_dir = \"%s\"\n",
 
5142
                        innobase_data_home_dir ? innobase_data_home_dir : mysql_data_home);
 
5143
                printf("innodb_data_file_path = \"%s\"\n",
 
5144
                        innobase_data_file_path ? innobase_data_file_path : "ibdata1:10M:autoextend");
 
5145
                printf("innodb_log_group_home_dir = \"%s\"\n",
 
5146
                        innobase_log_group_home_dir ? innobase_log_group_home_dir : mysql_data_home);
 
5147
                printf("innodb_log_files_in_group = %ld\n", innobase_log_files_in_group);
 
5148
                printf("innodb_log_file_size = %"PRIu64"\n", (uint64_t)innobase_log_file_size);
 
5149
                printf("innodb_flush_method = \"%s\"\n",
 
5150
                       (innobase_unix_file_flush_method != NULL) ?
 
5151
                       innobase_unix_file_flush_method : "");
 
5152
                exit(EXIT_SUCCESS);
 
5153
        }
 
5154
 
 
5155
        if (!xtrabackup_stream) {
 
5156
                print_version();
 
5157
                if (xtrabackup_incremental) {
 
5158
                        printf("incremental backup from %"PRIu64" is enabled.\n",
 
5159
                                incremental_lsn);
 
5160
                }
 
5161
        } else {
 
5162
                if (xtrabackup_backup) {
 
5163
                        xtrabackup_suspend_at_end = TRUE;
 
5164
                        fprintf(stderr, "xtrabackup: suspend-at-end is enabled.\n");
 
5165
                }
 
5166
        }
 
5167
 
 
5168
        /* cannot execute both for now */
 
5169
        {
 
5170
                int num = 0;
 
5171
 
 
5172
                if (xtrabackup_backup) num++;
 
5173
                if (xtrabackup_stats) num++;
 
5174
                if (xtrabackup_prepare) num++;
 
5175
                if (num != 1) { /* !XOR (for now) */
 
5176
                        usage();
 
5177
                        exit(EXIT_FAILURE);
 
5178
                }
 
5179
        }
 
5180
 
 
5181
        /* --backup */
 
5182
        if (xtrabackup_backup)
 
5183
                xtrabackup_backup_func();
 
5184
 
 
5185
        /* --stats */
 
5186
        if (xtrabackup_stats)
 
5187
                xtrabackup_stats_func();
 
5188
 
 
5189
        /* --prepare */
 
5190
        if (xtrabackup_prepare)
 
5191
                xtrabackup_prepare_func();
 
5192
 
 
5193
        free(incremental_buffer_base);
 
5194
 
 
5195
        if (xtrabackup_tables) {
 
5196
                /* free regexp */
 
5197
                int i;
 
5198
 
 
5199
                for (i = 0; i < tables_regex_num; i++) {
 
5200
                        regfree(&tables_regex[i]);
 
5201
                }
 
5202
                ut_free(tables_regex);
 
5203
        }
 
5204
 
 
5205
        if (xtrabackup_tables_file) {
 
5206
                ulint   i;
 
5207
 
 
5208
                /* free the hash elements */
 
5209
                for (i = 0; i < hash_get_n_cells(tables_hash); i++) {
 
5210
                        xtrabackup_tables_t*    table;
 
5211
 
 
5212
                        table = (xtrabackup_tables_t*)
 
5213
                          HASH_GET_FIRST(tables_hash, i);
 
5214
 
 
5215
                        while (table) {
 
5216
                                xtrabackup_tables_t*    prev_table = table;
 
5217
 
 
5218
                                table =  (xtrabackup_tables_t*)
 
5219
                                  HASH_GET_NEXT(name_hash, prev_table);
 
5220
 
 
5221
                                HASH_DELETE(xtrabackup_tables_t, name_hash, tables_hash,
 
5222
                                                ut_fold_string(prev_table->name), prev_table);
 
5223
                                free(prev_table);
 
5224
                        }
 
5225
                }
 
5226
 
 
5227
                /* free tables_hash */
 
5228
                hash_table_free(tables_hash);
 
5229
        }
 
5230
 
 
5231
        exit(EXIT_SUCCESS);
 
5232
}