~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to xtrabackup/xtrabackup.c

add xtrabackup

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