~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Lee Bieber
  • Date: 2011-03-31 14:40:56 UTC
  • mfrom: (2242.1.133 drizzle-xtrabackup)
  • Revision ID: kalebral@gmail.com-20110331144056-hdhp6cj0zo1keuc9
Merge Stewart - xtrabackup port to drizzle

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