commit 347e7259d0edbac23a5738023e28101c911be358
Author: Elan Ruusamäe <[email protected]>
Date:   Tue Mar 3 00:24:03 2009 +0000

    - revision 1 from lp:~percona-dev/percona-xtrabackup/xtrabackup-prototype
    
    Changed files:
        mysql-xtrabackup.patch -> 1.1.2.1

 mysql-xtrabackup.patch | 2060 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 2060 insertions(+)
---
diff --git a/mysql-xtrabackup.patch b/mysql-xtrabackup.patch
new file mode 100644
index 0000000..d1be917
--- /dev/null
+++ b/mysql-xtrabackup.patch
@@ -0,0 +1,2060 @@
+--- mysql-5.0.75/innobase/log/log0recv.c        2008-12-19 02:19:36.000000000 
+0900
++++ mysql-5.0.75_1/innobase/log/log0recv.c      2009-02-27 19:41:07.000000000 
+0900
+@@ -479,7 +479,7 @@
+
+ /************************************************************
+ Looks for the maximum consistent checkpoint from the log groups. */
+-static
++//static
+ ulint
+ recv_find_max_checkpoint(
+ /*=====================*/
+@@ -644,7 +644,7 @@
+ Checks the 4-byte checksum to the trailer checksum field of a log block.
+ We also accept a log block in the old format < InnoDB-3.23.52 where the
+ checksum field contains the log block number. */
+-static
++//static
+ ibool
+ log_block_checksum_is_ok_or_old_format(
+ /*===================================*/
+
+--- mysql-5.0.75/innobase/os/os0file.c  2008-12-19 02:19:36.000000000 +0900
++++ mysql-5.0.75_1/innobase/os/os0file.c        2009-02-26 11:54:47.000000000 
+0900
+@@ -435,7 +435,7 @@
+ }
+
+ #undef USE_FILE_LOCK
+-#define USE_FILE_LOCK
++//#define USE_FILE_LOCK
+ #if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__NETWARE__)
+ /* InnoDB Hot Backup does not lock the data files.
+  * On Windows, mandatory locking is used.
+
+--- mysql-5.0.75/innobase/srv/srv0start.c       2008-12-19 02:19:37.000000000 
+0900
++++ mysql-5.0.75_1/innobase/srv/srv0start.c     2009-02-26 11:48:30.000000000 
+0900
+@@ -547,7 +547,7 @@
+ #ifndef UNIV_HOTBACKUP
+ /*************************************************************************
+ Creates or opens the log files and closes them. */
+-static
++//static
+ ulint
+ open_or_create_log_file(
+ /*====================*/
+@@ -693,7 +693,7 @@
+
+ /*************************************************************************
+ Creates or opens database data files and closes them. */
+-static
++//static
+ ulint
+ open_or_create_data_files(
+ /*======================*/
+--- /dev/null  2006-03-28 14:00:37.000000000 +0300
++++ mysql-5.0.75/innobase/xtrabackup/Makefile  2009-03-02 17:54:29.089780153 
+0200
+@@ -0,0 +1,32 @@
++LIBS= -lpthread -lrt
++DEFS= -DUNIV_LINUX -DMYSQL_SERVER
++
++#x86_32
++CFLAGS=       -O2 -g -fmessage-length=0 -D_FORTIFY_SOURCE=2
++
++#5.0
++INC=  -I. -I.. -I./../include -I./../../include
++INNODBOBJS=   ../usr/libusr.a ../srv/libsrv.a ../dict/libdict.a 
../que/libque.a\
++              ../srv/libsrv.a ../ibuf/libibuf.a ../row/librow.a 
../pars/libpars.a\
++              ../btr/libbtr.a ../trx/libtrx.a ../read/libread.a 
../usr/libusr.a\
++              ../buf/libbuf.a ../ibuf/libibuf.a ../eval/libeval.a 
../log/liblog.a\
++              ../fsp/libfsp.a ../fut/libfut.a ../fil/libfil.a 
../lock/liblock.a\
++              ../mtr/libmtr.a ../page/libpage.a ../rem/librem.a 
../thr/libthr.a\
++              ../sync/libsync.a ../data/libdata.a ../mach/libmach.a 
../ha/libha.a\
++              ../dyn/libdyn.a ../mem/libmem.a ../sync/libsync.a ../ut/libut.a\
++              ../os/libos.a ../ut/libut.a
++MYSQLOBJS=    ../../mysys/libmysys.a ../../strings/libmystrings.a
++
++.SUFFIXES: .o .c
++
++.c.o:
++      $(CC) $(CFLAGS) $(INC) $(DEFS) -c $*.c
++
++all: xtrabackup
++
++xtrabackup : xtrabackup.o $(INNODBOBJS) $(MYSQLOBJS)
++      $(CC) xtrabackup.o $(INNODBOBJS) $(MYSQLOBJS) $(LIBS) -o xtrabackup
++
++clean:
++      rm -f *.o xtrabackup
++
+--- /dev/null  2006-03-28 14:00:37.000000000 +0300
++++ mysql-5.0.75/innobase/xtrabackup/xtrabackup.c      2009-03-02 
17:54:29.086446549 +0200
+@@ -0,0 +1,1969 @@
++#define XTRABACKUP_VERSION "prototype-0.0"
++
++//#define XTRABACKUP_TARGET_IS_PLUGIN
++
++#include <my_base.h>
++#include <my_getopt.h>
++#include <mysql_version.h>
++
++#include <univ.i>
++#include <os0file.h>
++#include <os0thread.h>
++#include <srv0start.h>
++#include <srv0srv.h>
++#include <trx0roll.h>
++#include <trx0trx.h>
++#include <trx0sys.h>
++#include <mtr0mtr.h>
++#include <row0ins.h>
++#include <row0mysql.h>
++#include <row0sel.h>
++#include <row0upd.h>
++#include <log0log.h>
++#include <lock0lock.h>
++#include <dict0crea.h>
++#include <btr0cur.h>
++#include <btr0btr.h>
++#include <fsp0fsp.h>
++#include <sync0sync.h>
++#include <fil0fil.h>
++#include <trx0xa.h>
++
++/* ==start === definition at fil0fil.c === */
++
++/* File node of a tablespace or the log data space */
++struct fil_node_struct {
++        fil_space_t*    space;  /* backpointer to the space where this node
++                                belongs */
++        char*           name;   /* path to the file */
++        ibool           open;   /* TRUE if file open */
++        os_file_t       handle; /* OS handle to the file, if file open */
++        ibool           is_raw_disk;/* TRUE if the 'file' is actually a raw
++                                device or a raw disk partition */
++        ulint           size;   /* size of the file in database pages, 0 if
++                                not known yet; the possible last incomplete
++                                megabyte may be ignored if space == 0 */
++        ulint           n_pending;
++                                /* count of pending i/o's on this file;
++                                closing of the file is not allowed if
++                                this is > 0 */
++        ulint           n_pending_flushes;
++                                /* count of pending flushes on this file;
++                                closing of the file is not allowed if
++                                this is > 0 */
++        ib_longlong     modification_counter;/* when we write to the file we
++                                increment this by one */
++        ib_longlong     flush_counter;/* up to what modification_counter value
++                                we have flushed the modifications to disk */
++        UT_LIST_NODE_T(fil_node_t) chain;
++                                /* link field for the file chain */
++        UT_LIST_NODE_T(fil_node_t) LRU;
++                                /* link field for the LRU list */
++        ulint           magic_n;
++};
++
++struct fil_space_struct {
++        char*           name;   /* space name = the path to the first file in
++                                it */
++        ulint           id;     /* space id */
++        ib_longlong     tablespace_version;
++                                /* in DISCARD/IMPORT this timestamp is used to
++                                check if we should ignore an insert buffer
++                                merge request for a page because it actually
++                                was for the previous incarnation of the
++                                space */
++        ibool           mark;   /* this is set to TRUE at database startup if
++                                the space corresponds to a table in the InnoDB
++                                data dictionary; so we can print a warning of
++                                orphaned tablespaces */
++        ibool           stop_ios;/* TRUE if we want to rename the .ibd file of
++                                tablespace and want to stop temporarily
++                                posting of new i/o requests on the file */
++        ibool           stop_ibuf_merges;
++                                /* we set this TRUE when we start deleting a
++                                single-table tablespace */
++        ibool           is_being_deleted;
++                                /* this is set to TRUE when we start
++                                deleting a single-table tablespace and its
++                                file; when this flag is set no further i/o
++                                or flush requests can be placed on this space,
++                                though there may be such requests still being
++                                processed on this space */
++        ulint           purpose;/* FIL_TABLESPACE, FIL_LOG, or FIL_ARCH_LOG */
++        UT_LIST_BASE_NODE_T(fil_node_t) chain;
++                                /* base node for the file chain */
++        ulint           size;   /* space size in pages; 0 if a single-table
++                                tablespace whose size we do not know yet;
++                                last incomplete megabytes in data files may be
++                                ignored if space == 0 */
++        ulint           n_reserved_extents;
++                                /* number of reserved free extents for
++                                ongoing operations like B-tree page split */
++        ulint           n_pending_flushes; /* this is > 0 when flushing
++                                the tablespace to disk; dropping of the
++                                tablespace is forbidden if this is > 0 */
++        ulint           n_pending_ibuf_merges;/* this is > 0 when merging
++                                insert buffer entries to a page so that we
++                                may need to access the ibuf bitmap page in the
++                                tablespade: dropping of the tablespace is
++                                forbidden if this is > 0 */
++        hash_node_t     hash;   /* hash chain node */
++        hash_node_t     name_hash;/* hash chain the name_hash table */
++        rw_lock_t       latch;  /* latch protecting the file space storage
++                                allocation */
++        UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
++                                /* list of spaces with at least one unflushed
++                                file we have written to */
++        ibool           is_in_unflushed_spaces; /* TRUE if this space is
++                                currently in the list above */
++        UT_LIST_NODE_T(fil_space_t) space_list;
++                                /* list of all spaces */
++        ibuf_data_t*    ibuf_data;
++                                /* insert buffer data */
++        ulint           magic_n;
++};
++typedef struct fil_system_struct        fil_system_t;
++struct fil_system_struct {
++        mutex_t         mutex;          /* The mutex protecting the cache */
++        hash_table_t*   spaces;         /* The hash table of spaces in the
++                                        system; they are hashed on the space
++                                        id */
++        hash_table_t*   name_hash;      /* hash table based on the space
++                                        name */
++        UT_LIST_BASE_NODE_T(fil_node_t) LRU;
++                                        /* base node for the LRU list of the
++                                        most recently used open files with no
++                                        pending i/o's; if we start an i/o on
++                                        the file, we first remove it from this
++                                        list, and return it to the start of
++                                        the list when the i/o ends;
++                                        log files and the system tablespace 
are
++                                        not put to this list: they are opened
++                                        after the startup, and kept open until
++                                        shutdown */
++        UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
++                                        /* base node for the list of those
++                                        tablespaces whose files contain
++                                        unflushed writes; those spaces have
++                                        at least one file node where
++                                        modification_counter > flush_counter 
*/
++        ulint           n_open;         /* number of files currently open */
++        ulint           max_n_open;     /* n_open is not allowed to exceed
++                                        this */
++        ib_longlong     modification_counter;/* when we write to a file we
++                                        increment this by one */
++        ulint           max_assigned_id;/* maximum space id in the existing
++                                        tables, or assigned during the time
++                                        mysqld has been up; at an InnoDB
++                                        startup we scan the data dictionary
++                                        and set here the maximum of the
++                                        space id's of the tables there */
++        ib_longlong     tablespace_version;
++                                        /* a counter which is incremented for
++                                        every space object memory creation;
++                                        every space mem object gets a
++                                        'timestamp' from this; in DISCARD/
++                                        IMPORT this is used to check if we
++                                        should ignore an insert buffer merge
++                                        request */
++        UT_LIST_BASE_NODE_T(fil_space_t) space_list;
++                                        /* list of all file spaces */
++};
++extern fil_system_t*   fil_system;
++
++/* ==end=== definition  at fil0fil.c === */
++
++
++bool innodb_inited= 0;
++
++/* === xtrabackup specific options === */
++char xtrabackup_real_target_dir[FN_REFLEN] = "./xtrabackup_backupfiles/";
++char *xtrabackup_target_dir= xtrabackup_real_target_dir;
++my_bool xtrabackup_backup = FALSE;
++my_bool xtrabackup_prepare = FALSE;
++
++my_bool xtrabackup_suspend_at_end = FALSE;
++longlong xtrabackup_use_memory = 8*1024*1024L;
++
++long xtrabackup_throttle = 0; /* 0:unlimited */
++my_bool xtrabackup_stream = FALSE;
++
++static ulint          n[SRV_MAX_N_IO_THREADS + 5];
++static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5];
++
++dulint checkpoint_lsn_start;
++dulint checkpoint_no_start;
++dulint log_copy_scanned_lsn;
++ib_longlong log_copy_offset = 0;
++ibool log_copying = TRUE;
++ibool log_copying_running = FALSE;
++ibool log_copying_succeed = FALSE;
++
++/* === sharing with thread === */
++os_file_t       dst_log = -1;
++char            dst_log_path[FN_REFLEN];
++
++/* === some variables from mysqld === */
++char mysql_real_data_home[FN_REFLEN] = "./";
++char *mysql_data_home= mysql_real_data_home;
++static char mysql_data_home_buff[2];
++
++char *opt_mysql_tmpdir = NULL;
++MY_TMPDIR mysql_tmpdir_list;
++
++/* === static parameters in ha_innodb.cc */
++
++#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
++#define HA_INNOBASE_RANGE_COUNT         100
++
++ulong         innobase_large_page_size = 0;
++
++/* The default values for the following, type long or longlong, start-up
++parameters are declared in mysqld.cc: */
++
++long innobase_additional_mem_pool_size = 1*1024*1024L;
++long innobase_buffer_pool_awe_mem_mb = 0;
++long innobase_file_io_threads = 4;
++long innobase_force_recovery = 0;
++long innobase_lock_wait_timeout = 50;
++long innobase_log_buffer_size = 1024*1024L;
++long innobase_log_files_in_group = 2;
++long innobase_mirrored_log_groups = 1;
++long innobase_open_files = 300L;
++
++longlong innobase_buffer_pool_size = 8*1024*1024L;
++longlong innobase_log_file_size = 5*1024*1024L;
++
++/* The default values for the following char* start-up parameters
++are determined in innobase_init below: */
++
++char* innobase_data_home_dir                  = NULL;
++char* innobase_data_file_path                 = NULL;
++char* innobase_log_group_home_dir             = NULL;
++char* innobase_log_arch_dir                   = NULL;/* unused */
++/* The following has a misleading name: starting from 4.0.5, this also
++affects Windows: */
++char* innobase_unix_file_flush_method         = NULL;
++
++/* Below we have boolean-valued start-up parameters, and their default
++values */
++
++ulong innobase_fast_shutdown                  = 0;
++my_bool innobase_log_archive                  = FALSE;/* unused */
++my_bool innobase_use_doublewrite    = TRUE;
++my_bool innobase_use_checksums      = TRUE;
++my_bool innobase_use_large_pages    = FALSE;
++my_bool       innobase_use_native_aio                 = FALSE;
++my_bool       innobase_file_per_table                 = FALSE;
++my_bool innobase_locks_unsafe_for_binlog        = FALSE;
++my_bool innobase_rollback_on_timeout          = FALSE;
++my_bool innobase_create_status_file           = FALSE;
++my_bool innobase_adaptive_hash_index          = TRUE;
++
++static char *internal_innobase_data_file_path = NULL;
++
++/* The following counter is used to convey information to InnoDB
++about server activity: in selects it is not sensible to call
++srv_active_wake_master_thread after each fetch or search, we only do
++it every INNOBASE_WAKE_INTERVAL'th step. */
++
++#define INNOBASE_WAKE_INTERVAL        32
++ulong innobase_active_counter = 0;
++
++
++/* ======== for option and variables ======== */
++
++enum options_xtrabackup
++{
++  OPT_XTRA_TARGET_DIR=256,
++  OPT_XTRA_BACKUP,
++  OPT_XTRA_PREPARE,
++  OPT_XTRA_SUSPEND_AT_END,
++  OPT_XTRA_USE_MEMORY,
++  OPT_XTRA_THROTTLE,
++  OPT_XTRA_STREAM,
++  OPT_INNODB_CHECKSUMS,
++  OPT_INNODB_DATA_FILE_PATH,
++  OPT_INNODB_DATA_HOME_DIR,
++  OPT_INNODB_ADAPTIVE_HASH_INDEX,
++  OPT_INNODB_DOUBLEWRITE,
++  OPT_INNODB_FAST_SHUTDOWN,
++  OPT_INNODB_FILE_PER_TABLE,
++  OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
++  OPT_INNODB_FLUSH_METHOD,
++  OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
++  OPT_INNODB_LOG_ARCH_DIR,
++  OPT_INNODB_LOG_ARCHIVE,
++  OPT_INNODB_LOG_GROUP_HOME_DIR,
++  OPT_INNODB_MAX_DIRTY_PAGES_PCT,
++  OPT_INNODB_MAX_PURGE_LAG,
++  OPT_INNODB_ROLLBACK_ON_TIMEOUT,
++  OPT_INNODB_STATUS_FILE,
++  OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
++  OPT_INNODB_AUTOEXTEND_INCREMENT,
++  OPT_INNODB_BUFFER_POOL_SIZE,
++  OPT_INNODB_COMMIT_CONCURRENCY,
++  OPT_INNODB_CONCURRENCY_TICKETS,
++  OPT_INNODB_FILE_IO_THREADS,
++  OPT_INNODB_FORCE_RECOVERY,
++  OPT_INNODB_LOCK_WAIT_TIMEOUT,
++  OPT_INNODB_LOG_BUFFER_SIZE,
++  OPT_INNODB_LOG_FILE_SIZE,
++  OPT_INNODB_LOG_FILES_IN_GROUP,
++  OPT_INNODB_MIRRORED_LOG_GROUPS,
++  OPT_INNODB_OPEN_FILES,
++  OPT_INNODB_SYNC_SPIN_LOOPS,
++  OPT_INNODB_THREAD_CONCURRENCY,
++  OPT_INNODB_THREAD_SLEEP_DELAY
++};
++
++static struct my_option my_long_options[] =
++{
++  {"target-dir", OPT_XTRA_TARGET_DIR, "destination directory", (gptr*) 
&xtrabackup_target_dir,
++   (gptr*) &xtrabackup_target_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 
0},
++  {"backup", OPT_XTRA_BACKUP, "take backup to target-dir",
++   (gptr*) &xtrabackup_backup, (gptr*) &xtrabackup_backup,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"prepare", OPT_XTRA_PREPARE, "prepare a backup for starting mysql server 
on the backup.",
++   (gptr*) &xtrabackup_prepare, (gptr*) &xtrabackup_prepare,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"use-memory", OPT_XTRA_USE_MEMORY, "** nothing for now (planned to use 
instead of buffer_pool_size) **",
++   (gptr*) &xtrabackup_use_memory, (gptr*) &xtrabackup_use_memory,
++   0, GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 0,
++   1024*1024L, 0},
++  {"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'",
++   (gptr*) &xtrabackup_suspend_at_end, (gptr*) &xtrabackup_suspend_at_end,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"throttle", OPT_XTRA_THROTTLE, "limit count of IO operations per second to 
IOS values",
++   (gptr*) &xtrabackup_throttle, (gptr*) &xtrabackup_throttle,
++   0, GET_LONG, REQUIRED_ARG, 0, 0, LONG_MAX, 0, 1, 0},
++  {"stream", OPT_XTRA_STREAM, "** nothing for now **",
++   (gptr*) &xtrabackup_stream, (gptr*) &xtrabackup_stream,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++
++  {"datadir", 'h', "Path to the database root.", (gptr*) &mysql_data_home,
++   (gptr*) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"tmpdir", 't',
++   "Path for temporary files. Several paths may be specified, separated by a "
++#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
++   "semicolon (;)"
++#else
++   "colon (:)"
++#endif
++   ", in this case they are used in a round-robin fashion.",
++   (gptr*) &opt_mysql_tmpdir,
++   (gptr*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++
++  {"innodb_adaptive_hash_index", OPT_INNODB_ADAPTIVE_HASH_INDEX,
++   "Enable InnoDB adaptive hash index (enabled by default).  "
++   "Disable with --skip-innodb-adaptive-hash-index.",
++   (gptr*) &innobase_adaptive_hash_index,
++   (gptr*) &innobase_adaptive_hash_index,
++   0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
++  {"innodb_additional_mem_pool_size", OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
++   "Size of a memory pool InnoDB uses to store data dictionary information 
and other internal data structures.",
++   (gptr*) &innobase_additional_mem_pool_size,
++   (gptr*) &innobase_additional_mem_pool_size, 0, GET_LONG, REQUIRED_ARG,
++   1*1024*1024L, 512*1024L, LONG_MAX, 0, 1024, 0},
++  {"innodb_autoextend_increment", OPT_INNODB_AUTOEXTEND_INCREMENT,
++   "Data file autoextend increment in megabytes",
++   (gptr*) &srv_auto_extend_increment,
++   (gptr*) &srv_auto_extend_increment,
++   0, GET_ULONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0},
++  {"innodb_buffer_pool_size", OPT_INNODB_BUFFER_POOL_SIZE,
++   "The size of the memory buffer InnoDB uses to cache data and indexes of 
its tables.",
++   (gptr*) &innobase_buffer_pool_size, (gptr*) &innobase_buffer_pool_size, 0,
++   GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 0,
++   1024*1024L, 0},
++  {"innodb_checksums", OPT_INNODB_CHECKSUMS, "Enable InnoDB checksums 
validation (enabled by default). \
++Disable with --skip-innodb-checksums.", (gptr*) &innobase_use_checksums,
++   (gptr*) &innobase_use_checksums, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
++/*
++  {"innodb_commit_concurrency", OPT_INNODB_COMMIT_CONCURRENCY,
++   "Helps in performance tuning in heavily concurrent environments.",
++   (gptr*) &srv_commit_concurrency, (gptr*) &srv_commit_concurrency,
++   0, GET_ULONG, REQUIRED_ARG, 0, 0, 1000, 0, 1, 0},
++*/
++/*
++  {"innodb_concurrency_tickets", OPT_INNODB_CONCURRENCY_TICKETS,
++   "Number of times a thread is allowed to enter InnoDB within the same \
++    SQL query after it has once got the ticket",
++   (gptr*) &srv_n_free_tickets_to_enter,
++   (gptr*) &srv_n_free_tickets_to_enter,
++   0, GET_ULONG, REQUIRED_ARG, 500L, 1L, ULONG_MAX, 0, 1L, 0},
++*/
++  {"innodb_data_file_path", OPT_INNODB_DATA_FILE_PATH,
++   "Path to individual files and their sizes.", (gptr*) 
&innobase_data_file_path,
++   (gptr*) &innobase_data_file_path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 
0},
++  {"innodb_data_home_dir", OPT_INNODB_DATA_HOME_DIR,
++   "The common part for InnoDB table spaces.", (gptr*) 
&innobase_data_home_dir,
++   (gptr*) &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0,
++   0},
++  {"innodb_doublewrite", OPT_INNODB_DOUBLEWRITE, "Enable InnoDB doublewrite 
buffer (enabled by default). \
++Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite,
++   (gptr*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
++/*
++  {"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN,
++   "Speeds up the shutdown process of the InnoDB storage engine. Possible "
++   "values are 0, 1 (faster)"
++   " or 2 (fastest - crash-like)"
++   ".",
++   (gptr*) &innobase_fast_shutdown,
++   (gptr*) &innobase_fast_shutdown, 0, GET_ULONG, OPT_ARG, 1, 0,
++   2, 0, 0, 0},
++*/
++  {"innodb_file_io_threads", OPT_INNODB_FILE_IO_THREADS,
++   "Number of file I/O threads in InnoDB.", (gptr*) &innobase_file_io_threads,
++   (gptr*) &innobase_file_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 4, 64, 0,
++   1, 0},
++  {"innodb_file_per_table", OPT_INNODB_FILE_PER_TABLE,
++   "Stores each InnoDB table to an .ibd file in the database dir.",
++   (gptr*) &innobase_file_per_table,
++   (gptr*) &innobase_file_per_table, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"innodb_flush_log_at_trx_commit", OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
++   "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).",
++   (gptr*) &srv_flush_log_at_trx_commit,
++   (gptr*) &srv_flush_log_at_trx_commit,
++   0, GET_ULONG, OPT_ARG,  1, 0, 2, 0, 0, 0},
++  {"innodb_flush_method", OPT_INNODB_FLUSH_METHOD,
++   "With which method to flush data.", (gptr*) 
&innobase_unix_file_flush_method,
++   (gptr*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 
0,
++   0, 0, 0},
++
++/* ####### Should we use this option? ####### */
++  {"innodb_force_recovery", OPT_INNODB_FORCE_RECOVERY,
++   "Helps to save your data in case the disk image of the database becomes 
corrupt.",
++   (gptr*) &innobase_force_recovery, (gptr*) &innobase_force_recovery, 0,
++   GET_LONG, REQUIRED_ARG, 0, 0, 6, 0, 1, 0},
++
++  {"innodb_lock_wait_timeout", OPT_INNODB_LOCK_WAIT_TIMEOUT,
++   "Timeout in seconds an InnoDB transaction may wait for a lock before being 
rolled back.",
++   (gptr*) &innobase_lock_wait_timeout, (gptr*) &innobase_lock_wait_timeout,
++   0, GET_LONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
++/*
++  {"innodb_locks_unsafe_for_binlog", OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
++   "Force InnoDB not to use next-key locking. Instead use only row-level 
locking",
++   (gptr*) &innobase_locks_unsafe_for_binlog,
++   (gptr*) &innobase_locks_unsafe_for_binlog, 0, GET_BOOL, NO_ARG, 0, 0, 0, 
0, 0, 0},
++*/
++/*
++  {"innodb_log_arch_dir", OPT_INNODB_LOG_ARCH_DIR,
++   "Where full logs should be archived.", (gptr*) &innobase_log_arch_dir,
++   (gptr*) &innobase_log_arch_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 
0},
++*/
++  {"innodb_log_buffer_size", OPT_INNODB_LOG_BUFFER_SIZE,
++   "The size of the buffer which InnoDB uses to write log to the log files on 
disk.",
++   (gptr*) &innobase_log_buffer_size, (gptr*) &innobase_log_buffer_size, 0,
++   GET_LONG, REQUIRED_ARG, 1024*1024L, 256*1024L, LONG_MAX, 0, 1024, 0},
++  {"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE,
++   "Size of each log file in a log group.",
++   (gptr*) &innobase_log_file_size, (gptr*) &innobase_log_file_size, 0,
++   GET_LL, REQUIRED_ARG, 5*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 0,
++   1024*1024L, 0},
++  {"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP,
++   "Number of log files in the log group. InnoDB writes to the files in a 
circular fashion. Value 3 is recommended here.",
++   (gptr*) &innobase_log_files_in_group, (gptr*) &innobase_log_files_in_group,
++   0, GET_LONG, REQUIRED_ARG, 2, 2, 100, 0, 1, 0},
++  {"innodb_log_group_home_dir", OPT_INNODB_LOG_GROUP_HOME_DIR,
++   "Path to InnoDB log files.", (gptr*) &innobase_log_group_home_dir,
++   (gptr*) &innobase_log_group_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
++   0, 0},
++  {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT,
++   "Percentage of dirty pages allowed in bufferpool.", (gptr*) 
&srv_max_buf_pool_modified_pct,
++   (gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 
100, 0, 0, 0},
++/*
++  {"innodb_max_purge_lag", OPT_INNODB_MAX_PURGE_LAG,
++   "Desired maximum length of the purge queue (0 = no limit)",
++   (gptr*) &srv_max_purge_lag,
++   (gptr*) &srv_max_purge_lag, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ULONG_MAX,
++   0, 1L, 0},
++*/
++/*
++  {"innodb_mirrored_log_groups", OPT_INNODB_MIRRORED_LOG_GROUPS,
++   "Number of identical copies of log groups we keep for the database. 
Currently this should be set to 1.",
++   (gptr*) &innobase_mirrored_log_groups,
++   (gptr*) &innobase_mirrored_log_groups, 0, GET_LONG, REQUIRED_ARG, 1, 1, 10,
++   0, 1, 0},
++*/
++  {"innodb_open_files", OPT_INNODB_OPEN_FILES,
++   "How many files at the maximum InnoDB keeps open at the same time.",
++   (gptr*) &innobase_open_files, (gptr*) &innobase_open_files, 0,
++   GET_LONG, REQUIRED_ARG, 300L, 10L, LONG_MAX, 0, 1L, 0},
++/*
++  {"innodb_rollback_on_timeout", OPT_INNODB_ROLLBACK_ON_TIMEOUT,
++   "Roll back the complete transaction on lock wait timeout, for 4.x 
compatibility (disabled by default)",
++   (gptr*) &innobase_rollback_on_timeout, (gptr*) 
&innobase_rollback_on_timeout,
++   0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
++*/
++/*
++  {"innodb_status_file", OPT_INNODB_STATUS_FILE,
++   "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
++   (gptr*) &innobase_create_status_file, (gptr*) &innobase_create_status_file,
++   0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
++*/
++/*
++  {"innodb_sync_spin_loops", OPT_INNODB_SYNC_SPIN_LOOPS,
++   "Count of spin-loop rounds in InnoDB mutexes",
++   (gptr*) &srv_n_spin_wait_rounds,
++   (gptr*) &srv_n_spin_wait_rounds,
++   0, GET_ULONG, REQUIRED_ARG, 20L, 0L, ULONG_MAX, 0, 1L, 0},
++*/
++/*
++  {"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY,
++   "Helps in performance tuning in heavily concurrent environments. "
++   "Sets the maximum number of threads allowed inside InnoDB. Value 0"
++   " will disable the thread throttling.",
++   (gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency,
++   0, GET_ULONG, REQUIRED_ARG, 8, 0, 1000, 0, 1, 0},
++*/
++/*
++  {"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY,
++   "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 
0"
++    " disable a sleep",
++   (gptr*) &srv_thread_sleep_delay,
++   (gptr*) &srv_thread_sleep_delay,
++   0, GET_ULONG, REQUIRED_ARG, 10000L, 0L, ULONG_MAX, 0, 1L, 0},
++*/
++
++  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
++};
++
++static const char *load_default_groups[]= { "mysqld","xtrabackup",0 };
++
++static void print_version(void)
++{
++  printf("%s  Ver %s for %s %s (%s)\n" ,my_progname,
++        XTRABACKUP_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
++}
++
++static void usage(void)
++{
++  print_version();
++  puts("This software comes with ABSOLUTELY NO WARRANTY. This is free 
software,\nand you are welcome to modify and redistribute it under the GPL 
license\n");
++
++  printf("Usage: [%s --backup | %s --prepare] 
[OPTIONS]\n",my_progname,my_progname);
++  print_defaults("my",load_default_groups);
++  my_print_help(my_long_options);
++  my_print_variables(my_long_options);
++}
++
++static my_bool
++get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
++             char *argument)
++{
++  switch(optid) {
++  case 'h':
++    strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
++    mysql_data_home= mysql_real_data_home;
++    break;
++  case OPT_XTRA_TARGET_DIR:
++    strmake(xtrabackup_real_target_dir,argument, 
sizeof(xtrabackup_real_target_dir)-1);
++    xtrabackup_target_dir= xtrabackup_real_target_dir;
++    break;
++  case '?':
++    usage();
++    exit(0);
++    break;
++  default:
++    break;
++  }
++  return 0;
++}
++
++/* ================ Dummys =================== */
++
++void
++innobase_mysql_prepare_print_arbitrary_thd(void)
++{
++//fprintf(stderr, "innobase_mysql_prepare_print_arbitrary_thd() is called\n");
++}
++
++void
++innobase_mysql_end_print_arbitrary_thd(void)
++{
++//fprintf(stderr, "innobase_mysql_end_print_arbitrary_thd() is called\n");
++}
++
++void
++innobase_mysql_print_thd(
++      FILE*   f,              
++      void*   input_thd,
++      uint    max_query_len)
++{
++      fprintf(stderr, "innobase_mysql_print_thd() is called\n");
++      exit(1);
++}
++
++void
++innobase_get_cset_width(
++      ulint   cset,
++      ulint*  mbminlen,
++      ulint*  mbmaxlen)
++{
++      CHARSET_INFO*   cs;
++      ut_ad(cset < 256);
++      ut_ad(mbminlen);
++      ut_ad(mbmaxlen);
++
++      cs = all_charsets[cset];
++      if (cs) {
++              *mbminlen = cs->mbminlen;
++              *mbmaxlen = cs->mbmaxlen;
++      } else {
++              ut_a(cset == 0);
++              *mbminlen = *mbmaxlen = 0;
++      }
++}
++
++int
++innobase_strcasecmp(
++      const char*     a,
++      const char*     b)
++{
++      return(my_strcasecmp(&my_charset_utf8_general_ci, a, b));
++}
++
++void
++innobase_casedn_str(
++      char*   a)
++{
++      fprintf(stderr, "innobase_casedn_str() is called\n");
++      exit(1);
++}
++
++int
++innobase_mysql_tmpfile(void)
++{
++      char    filename[FN_REFLEN];
++      int     fd2 = -1;
++      File    fd = create_temp_file(filename, my_tmpdir(&mysql_tmpdir_list), 
"ib",
++#ifdef __WIN__
++                              O_BINARY | O_TRUNC | O_SEQUENTIAL |
++                              O_TEMPORARY | O_SHORT_LIVED |
++#endif /* __WIN__ */
++                              O_CREAT | O_EXCL | O_RDWR,
++                              MYF(MY_WME));
++      if (fd >= 0) {
++#ifndef __WIN__
++              /* On Windows, open files cannot be removed, but files can be
++              created with the O_TEMPORARY flag to the same effect
++              ("delete on close"). */
++              unlink(filename);
++#endif /* !__WIN__ */
++              /* Copy the file descriptor, so that the additional resources
++              allocated by create_temp_file() can be freed by invoking
++              my_close().
++
++              Because the file descriptor returned by this function
++              will be passed to fdopen(), it will be closed by invoking
++              fclose(), which in turn will invoke close() instead of
++              my_close(). */
++              fd2 = dup(fd);
++              if (fd2 < 0) {
++                      fprintf(stderr, "Got error %d on dup",fd2);
++                }
++              my_close(fd, MYF(MY_WME));
++      }
++      return(fd2);
++}
++
++void
++innobase_invalidate_query_cache(
++      trx_t*  trx,
++      char*   full_name,
++      ulint   full_name_len)
++{
++      fprintf(stderr, "innobase_invalidate_query_cache() is called\n");
++      exit(1);
++}
++
++int
++mysql_get_identifier_quote_char(
++      trx_t*          trx,
++      const char*     name,
++      ulint           namelen)
++{
++      fprintf(stderr, "mysql_get_identifier_quote_char() is called\n");
++      exit(1);
++}
++
++ibool
++trx_is_interrupted(
++      trx_t*  trx)
++{
++      fprintf(stderr, "trx_is_interrupted() is called\n");
++      exit(1);
++}
++
++void*
++innobase_current_thd(void)
++{
++      fprintf(stderr, "innobase_current_thd() is called\n");
++      exit(1);
++}
++
++int
++innobase_mysql_cmp(
++      int             mysql_type,
++      uint            charset_number,
++      unsigned char*  a,
++      unsigned int    a_length,
++      unsigned char*  b,
++      unsigned int    b_length)
++{
++      fprintf(stderr, "innobase_mysql_cmp() is called\n");
++      exit(1);
++}
++
++ulint
++innobase_get_at_most_n_mbchars(
++      ulint charset_id,
++      ulint prefix_len,
++      ulint data_len,
++      const char* str)
++{
++      fprintf(stderr, "innobase_get_at_most_n_mbchars() is called\n");
++      exit(1);
++}
++
++ibool
++innobase_query_is_update(void)
++{
++      fprintf(stderr, "innobase_query_is_update() is called\n");
++      exit(1);
++}
++
++/* control innodb */
++
++bool
++innodb_init_param(void)
++{
++      /* === some variables from mysqld === */
++      bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
++
++      if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
++              exit(1);
++
++      /* dummy for initialize all_charsets[] */
++      get_charset_name(0);
++
++
++      /* innobase_init */
++
++      static char     current_dir[3];         /* Set if using current lib */
++      int             err;
++      bool            ret;
++      char            *default_path;
++
++      /* Check that values don't overflow on 32-bit systems. */
++      if (sizeof(ulint) == 4) {
++              if (innobase_buffer_pool_size > UINT_MAX32) {
++                      fprintf(stderr,
++                              "innobase_buffer_pool_size can't be over 4GB"
++                              " on 32-bit systems");
++
++                      goto error;
++              }
++
++              if (innobase_log_file_size > UINT_MAX32) {
++                      fprintf(stderr,
++                              "innobase_log_file_size can't be over 4GB"
++                              " on 32-bit systems");
++
++                      goto error;
++              }
++      }
++
++      os_innodb_umask = (ulint)0664;
++
++      /* First calculate the default path for innodb_data_home_dir etc.,
++      in case the user has not given any value.
++
++      Note that when using the embedded server, the datadirectory is not
++      necessarily the current directory of this program. */
++
++              /* It's better to use current lib, to keep paths short */
++              current_dir[0] = FN_CURLIB;
++              current_dir[1] = FN_LIBCHAR;
++              current_dir[2] = 0;
++              default_path = current_dir;
++
++      ut_a(default_path);
++
++//    if (specialflag & SPECIAL_NO_PRIOR) {
++              srv_set_thread_priorities = FALSE;
++//    } else {
++//            srv_set_thread_priorities = TRUE;
++//            srv_query_thread_priority = QUERY_PRIOR;
++//    }
++
++      /* Set InnoDB initialization parameters according to the values
++      read from MySQL .cnf file */
++
++      /*--------------- Data files -------------------------*/
++
++      /* The default dir for data files is the datadir of MySQL */
++
++      srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
++                       default_path);
++
++      /* Set default InnoDB data file size to 10 MB and let it be
++      auto-extending. Thus users can use InnoDB in >= 4.0 without having
++      to specify any startup options. */
++
++      if (!innobase_data_file_path) {
++              innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
++      }
++
++      /* Since InnoDB edits the argument in the next call, we make another
++      copy of it: */
++
++      internal_innobase_data_file_path = strdup(innobase_data_file_path);
++
++      ret = (bool) srv_parse_data_file_paths_and_sizes(
++                              internal_innobase_data_file_path,
++                              &srv_data_file_names,
++                              &srv_data_file_sizes,
++                              &srv_data_file_is_raw_partition,
++                              &srv_n_data_files,
++                              &srv_auto_extend_last_data_file,
++                              &srv_last_file_size_max);
++      if (ret == FALSE) {
++              fprintf(stderr,
++                      "InnoDB: syntax error in innodb_data_file_path");
++              free(internal_innobase_data_file_path);
++                goto error;
++      }
++
++      /* -------------- Log files ---------------------------*/
++
++      /* The default dir for log files is the datadir of MySQL */
++
++      if (!innobase_log_group_home_dir) {
++              innobase_log_group_home_dir = default_path;
++      }
++
++#ifdef UNIV_LOG_ARCHIVE
++      /* Since innodb_log_arch_dir has no relevance under MySQL,
++      starting from 4.0.6 we always set it the same as
++      innodb_log_group_home_dir: */
++
++      innobase_log_arch_dir = innobase_log_group_home_dir;
++
++      srv_arch_dir = innobase_log_arch_dir;
++#endif /* UNIG_LOG_ARCHIVE */
++
++      ret = (bool)
++              srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
++                                              &srv_log_group_home_dirs);
++
++      if (ret == FALSE || innobase_mirrored_log_groups != 1) {
++        fprintf(stderr, "syntax error in innodb_log_group_home_dir, or a "
++                        "wrong number of mirrored log groups");
++
++              free(internal_innobase_data_file_path);
++                goto error;
++      }
++
++      /* --------------------------------------------------*/
++
++      srv_file_flush_method_str = innobase_unix_file_flush_method;
++
++      srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
++      srv_n_log_files = (ulint) innobase_log_files_in_group;
++      srv_log_file_size = (ulint) innobase_log_file_size;
++
++#ifdef UNIV_LOG_ARCHIVE
++      srv_log_archive_on = (ulint) innobase_log_archive;
++#endif /* UNIV_LOG_ARCHIVE */
++      srv_log_buffer_size = (ulint) innobase_log_buffer_size;
++
++        /* We set srv_pool_size here in units of 1 kB. InnoDB internally
++        changes the value so that it becomes the number of database pages. */
++
++        if (innobase_buffer_pool_awe_mem_mb == 0) {
++                /* Careful here: we first convert the signed long int to ulint
++                and only after that divide */
++
++                srv_pool_size = ((ulint) innobase_buffer_pool_size) / 1024;
++        } else {
++                srv_use_awe = TRUE;
++                srv_pool_size = (ulint)
++                                (1024 * innobase_buffer_pool_awe_mem_mb);
++                srv_awe_window_size = (ulint) innobase_buffer_pool_size;
++
++                /* Note that what the user specified as
++                innodb_buffer_pool_size is actually the AWE memory window
++                size in this case, and the real buffer pool size is
++                determined by .._awe_mem_mb. */
++        }
++
++      srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
++
++      srv_n_file_io_threads = (ulint) innobase_file_io_threads;
++
++      srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
++      srv_force_recovery = (ulint) innobase_force_recovery;
++
++      srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
++      srv_use_checksums = (ibool) innobase_use_checksums;
++
++      srv_use_adaptive_hash_indexes = (ibool) innobase_adaptive_hash_index;
++
++      os_use_large_pages = (ibool) innobase_use_large_pages;
++      os_large_page_size = (ulint) innobase_large_page_size;
++
++      row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
++
++      srv_file_per_table = (ibool) innobase_file_per_table;
++        srv_locks_unsafe_for_binlog = (ibool) 
innobase_locks_unsafe_for_binlog;
++
++      srv_max_n_open_files = (ulint) innobase_open_files;
++      srv_innodb_status = (ibool) innobase_create_status_file;
++
++      srv_print_verbose_log = 1;
++
++      /* Store the default charset-collation number of this MySQL
++      installation */
++
++      /* We cannot treat characterset here for now!! */
++      data_mysql_default_charset_coll = (ulint)default_charset_info->number;
++
++      ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
++                                      my_charset_latin1.number);
++      ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
++
++      /* Store the latin1_swedish_ci character ordering table to InnoDB. For
++      non-latin1_swedish_ci charsets we use the MySQL comparison functions,
++      and consequently we do not need to know the ordering internally in
++      InnoDB. */
++
++      ut_a(0 == strcmp((char*)my_charset_latin1.name,
++                                              (char*)"latin1_swedish_ci"));
++      memcpy(srv_latin1_ordering, my_charset_latin1.sort_order, 256);
++
++      /* Since we in this module access directly the fields of a trx
++        struct, and due to different headers and flags it might happen that
++      mutex_t has a different size in this module and in InnoDB
++      modules, we check at run time that the size is the same in
++      these compilation modules. */
++
++      srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
++
++      return(FALSE);
++
++error:
++      fprintf(stderr, "innodb_init_param(): Error occured.\n");
++      return(TRUE);
++}
++
++bool
++innodb_init(void)
++{
++      int     err;
++
++      err = innobase_start_or_create_for_mysql();
++
++      if (err != DB_SUCCESS) {
++              free(internal_innobase_data_file_path);
++                goto error;
++      }
++
++      /* They may not be needed for now */
++//    (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
++//                                    (hash_get_key) innobase_get_key, 0, 0);
++//        pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
++//        pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
++//        pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
++//        pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
++//        pthread_cond_init(&commit_cond, NULL);
++
++      innodb_inited= 1;
++
++      return(FALSE);
++
++error:
++      fprintf(stderr, "innodb_init(): Error occured.\n");
++      return(TRUE);
++}
++
++bool
++innodb_end(void)
++{
++      srv_fast_shutdown = (ulint) innobase_fast_shutdown;
++      innodb_inited = 0;
++      if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
++              goto error;
++      }
++      free(internal_innobase_data_file_path);
++
++      /* They may not be needed for now */
++//    hash_free(&innobase_open_tables);
++//    pthread_mutex_destroy(&innobase_share_mutex);
++//    pthread_mutex_destroy(&prepare_commit_mutex);
++//    pthread_mutex_destroy(&commit_threads_m);
++//    pthread_mutex_destroy(&commit_cond_m);
++//    pthread_cond_destroy(&commit_cond);
++
++      return(FALSE);
++
++error:
++      fprintf(stderr, "innodb_end(): Error occured.\n");
++      return(TRUE);
++}
++
++
++/* ================= backup ================= */
++
++/* TODO: We may tune the behavior (e.g. by fil_aio)*/
++#define COPY_CHUNK 64
++
++bool
++xtrabackup_copy_datafile(fil_node_t* node)
++{
++      os_file_t       src_file = -1;
++      os_file_t       dst_file = -1;
++      char    dst_path[FN_REFLEN];
++      ibool           success;
++      byte*           page;
++      byte*           buf2 = NULL;
++      dulint          flush_lsn;
++      ulint           space_id;
++      ib_longlong     file_size;
++      ib_longlong     offset;
++
++
++      sprintf(dst_path, "%s%s", xtrabackup_target_dir, strstr(node->name, 
"/"));
++
++      /* open src_file*/
++      if (!node->open) {
++              src_file = os_file_create_simple_no_error_handling(
++                                              node->name, OS_FILE_OPEN,
++                                              OS_FILE_READ_ONLY, &success);
++              if (!success) {
++                      /* The following call prints an error message */
++                      os_file_get_last_error(TRUE);
++
++                      ut_print_timestamp(stderr);
++
++                      fprintf(stderr,
++"  InnoDB: Fatal error: cannot open %s\n."
++"InnoDB: Have you deleted .ibd files under a running mysqld server?\n",
++                              node->name);
++                      exit(1);
++              }
++      } else {
++              src_file = node->handle;
++      }
++
++      /* open dst_file */
++      dst_file = os_file_create(dst_path, OS_FILE_OVERWRITE,
++                                      OS_FILE_AIO, OS_DATA_FILE, &success);
++                if (!success) {
++                        /* The following call prints an error message */
++                        os_file_get_last_error(TRUE);
++
++                        ut_print_timestamp(stderr);
++
++                        fprintf(stderr,
++"  InnoDB: error: cannot open %s\n.",
++                                dst_path);
++                        exit(1);
++                }
++
++      /* copy : TODO: tune later */
++      printf("Copying %s \n     to %s\n", node->name, dst_path);
++
++      buf2 = ut_malloc((COPY_CHUNK + 1) * UNIV_PAGE_SIZE);
++      page = ut_align(buf2, UNIV_PAGE_SIZE);
++
++      success = os_file_read(src_file, page, 0, 0, UNIV_PAGE_SIZE);
++      if (!success) {
++              goto error;
++      }
++      flush_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
++              /* check current flush lsn newer than checkpoint@start */
++//    if (ut_dulint_cmp(backup_start_checkpoint, flush_lsn) >= 0) {
++//            goto error;
++//    }
++      space_id = fsp_header_get_space_id(page);
++
++      file_size = os_file_get_size_as_iblonglong(src_file);
++
++      for (offset = 0; offset < file_size; offset += COPY_CHUNK * 
UNIV_PAGE_SIZE) {
++              ulint chunk;
++copy_loop:
++              if (file_size - offset > COPY_CHUNK * UNIV_PAGE_SIZE) {
++                      chunk = COPY_CHUNK * UNIV_PAGE_SIZE;
++              } else {
++                      chunk = (ulint)(file_size - offset);
++              }
++
++              success = os_file_read(src_file, page,
++                              (ulint)(offset & 0xFFFFFFFFUL),
++                              (ulint)(offset >> 32), chunk);
++              if (!success) {
++                      goto error;
++              }
++
++              success = os_file_write(dst_path, dst_file, page,
++                      (ulint)(offset & 0xFFFFFFFFUL),
++                      (ulint)(offset >> 32), chunk);
++              if (!success) {
++                      goto error;
++              }
++
++      }
++
++      success = os_file_flush(dst_file);
++      if (!success) {
++              goto error;
++      }
++
++
++      /* check size again */
++      /* TODO: but is it needed ?? */
++      if (file_size < os_file_get_size_as_iblonglong(src_file)) {
++              offset -= COPY_CHUNK * UNIV_PAGE_SIZE;
++              file_size = os_file_get_size_as_iblonglong(src_file);
++              goto copy_loop;
++      }
++
++      /* TODO: How should we treat double_write_buffer here? */
++      /* (currently, don't care about...) */
++
++      /* close */
++      printf("        ...done\n");
++      os_file_close(src_file);
++      os_file_close(dst_file);
++      ut_free(buf2);
++      return(FALSE);
++error:
++      if (!src_file == -1)
++              os_file_close(src_file);
++      if (!dst_file == -1)
++              os_file_close(dst_file);
++      if (buf2)
++              ut_free(buf2);
++      fprintf(stderr, "Error: xtrabackup_copy_datafile() failed.");
++      return(TRUE); /*ERROR*/
++}
++
++/* TODO: make this function background thread */
++bool
++xtrabackup_copy_logfile(dulint from_lsn)
++{
++      char    path[FN_REFLEN];
++      char    *ptr1, *ptr2;
++
++        fil_system_t*   system = fil_system;
++        fil_space_t*    space;
++      fil_space_t*    last_src;
++        fil_node_t*     node;
++
++      /* definition from recv_recovery_from_checkpoint_start() */
++      log_group_t*    group;
++      log_group_t*    max_cp_group;
++      log_group_t*    up_to_date_group;
++      ulint           max_cp_field;
++      dulint          checkpoint_lsn;
++      dulint          checkpoint_no;
++      dulint          old_scanned_lsn;
++      dulint          group_scanned_lsn;
++      dulint          contiguous_lsn;
++      dulint          archived_lsn;
++      ulint           capacity;
++      byte*           buf;
++      byte            log_hdr_buf[LOG_FILE_HDR_SIZE];
++      ulint           err;
++
++      ibool           success;
++
++      ut_a(dst_log != -1);
++
++      /* read from checkpoint_lsn_start to current */
++      contiguous_lsn = ut_dulint_align_down(from_lsn,
++                                              OS_FILE_LOG_BLOCK_SIZE);
++
++      /* TODO: We must check the contiguous_lsn still exists in log file.. */
++
++      group = UT_LIST_GET_FIRST(log_sys->log_groups);
++
++      while (group) {
++              ibool   finished;
++              dulint  start_lsn;
++              dulint  end_lsn;
++
++
++              old_scanned_lsn = from_lsn;
++
++/*            recv_group_scan_log_recs(group, &contiguous_lsn,
++                                                      &group_scanned_lsn);
++*/
++      finished = FALSE;
++
++      start_lsn = contiguous_lsn;
++              
++      while (!finished) {                     
++              end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE);
++
++              log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
++                                              group, start_lsn, end_lsn);
++
++              printf("log read from (%lu %lu) to (%lu %lu)\n",
++                      start_lsn.high, start_lsn.low, end_lsn.high, 
end_lsn.low);
++
++//            finished = recv_scan_log_recs(TRUE,
++//                                (buf_pool->n_frames
++//                                - recv_n_pool_free_frames) * UNIV_PAGE_SIZE,
++//                            TRUE, log_sys->buf,
++//                            RECV_SCAN_SIZE, start_lsn,
++//                            &contiguous_lsn, &group_scanned_lsn);
++              {
++      byte*   log_block;
++      ulint   no;
++      dulint  scanned_lsn;
++      ulint   data_len;
++      ibool   more_data;
++
++      ulint   scanned_checkpoint_no = 0;
++
++      finished = FALSE;
++      
++      log_block = log_sys->buf;
++      scanned_lsn = start_lsn;
++      more_data = FALSE;
++
++      while (log_block < log_sys->buf + RECV_SCAN_SIZE && !finished) {
++
++              no = log_block_get_hdr_no(log_block);
++
++              if (no != log_block_convert_lsn_to_no(scanned_lsn)
++                  || !log_block_checksum_is_ok_or_old_format(log_block)) {
++
++                      if (no == log_block_convert_lsn_to_no(scanned_lsn)
++                          && !log_block_checksum_is_ok_or_old_format(
++                                                              log_block)) {
++                              fprintf(stderr,
++"InnoDB: Log block no %lu at lsn %lu %lu has\n"
++"InnoDB: ok header, but checksum field contains %lu, should be %lu\n",
++                              (ulong) no,
++                              (ulong) ut_dulint_get_high(scanned_lsn),
++                              (ulong) ut_dulint_get_low(scanned_lsn),
++                              (ulong) log_block_get_checksum(log_block),
++                              (ulong) log_block_calc_checksum(log_block));
++                      }
++
++                      /* Garbage or an incompletely written log block */
++
++                      finished = TRUE;
++
++                      break;
++              }
++
++              if (log_block_get_flush_bit(log_block)) {
++                      /* This block was a start of a log flush operation:
++                      we know that the previous flush operation must have
++                      been completed for all log groups before this block
++                      can have been flushed to any of the groups. Therefore,
++                      we know that log data is contiguous up to scanned_lsn
++                      in all non-corrupt log groups. */
++
++                      if (ut_dulint_cmp(scanned_lsn, contiguous_lsn) > 0) {
++                              contiguous_lsn = scanned_lsn;
++                      }
++              }
++
++              data_len = log_block_get_data_len(log_block);
++
++              if (
++                  (scanned_checkpoint_no > 0)
++                  && (log_block_get_checkpoint_no(log_block)
++                     < scanned_checkpoint_no)
++                  && (scanned_checkpoint_no
++                      - log_block_get_checkpoint_no(log_block)
++                      > 0x80000000UL)) {
++
++                      /* Garbage from a log buffer flush which was made
++                      before the most recent database recovery */
++
++                      finished = TRUE;
++                      break;
++              }                   
++
++              scanned_lsn = ut_dulint_add(scanned_lsn, data_len);
++              scanned_checkpoint_no = log_block_get_checkpoint_no(log_block);
++
++              if (data_len < OS_FILE_LOG_BLOCK_SIZE) {
++                      /* Log data for this group ends here */
++
++                      finished = TRUE;
++              } else {
++                      log_block += OS_FILE_LOG_BLOCK_SIZE;
++              }
++      } /* while (log_block < log_sys->buf + RECV_SCAN_SIZE && !finished) */
++
++      group_scanned_lsn = scanned_lsn;
++
++
++
++              }
++
++              /* ===== write log to 'xtrabackup_logfile' ====== */
++              {
++              ulint write_size;
++
++              if (!finished) {
++                      write_size = RECV_SCAN_SIZE;
++              } else {
++                      write_size = ut_dulint_minus(
++                                      ut_dulint_align_up(group_scanned_lsn, 
OS_FILE_LOG_BLOCK_SIZE),
++                                      start_lsn);
++              }
++
++              printf("Wrinting offset= %lld, size= %lu\n", log_copy_offset, 
write_size);
++
++              success = os_file_write(dst_log_path, dst_log, log_sys->buf,
++                              (ulint)(log_copy_offset & 0xFFFFFFFFUL),
++                              (ulint)(log_copy_offset >> 32), write_size);
++              log_copy_offset += write_size;
++
++              if (finished) {
++                      /* if continue, it will start from 
align_down(group_scanned_lsn) */
++                      log_copy_offset -= OS_FILE_LOG_BLOCK_SIZE;
++              }
++
++              if(!success) {
++                      fprintf(stderr, "Error: os_file_write to %s\n", 
dst_log_path);
++                      goto error;
++              }
++
++
++              }
++
++
++
++
++
++              start_lsn = end_lsn;
++      }
++
++
++
++              group->scanned_lsn = group_scanned_lsn;
++              
++              if (ut_dulint_cmp(old_scanned_lsn, group_scanned_lsn) < 0) {
++                      /* We found a more up-to-date group */
++
++                      up_to_date_group = group;
++              }
++
++              printf("scanned_lsn (%lu 
%lu)\n",group->scanned_lsn.high,group->scanned_lsn.low);
++
++              group = UT_LIST_GET_NEXT(log_groups, group);
++
++              /* update global variable*/
++              log_copy_scanned_lsn = group_scanned_lsn;
++
++              /* innodb_mirrored_log_groups must be 1, no other groups */
++              ut_a(group == NULL);
++      }
++
++
++      success = os_file_flush(dst_log);
++      if(!success) {
++              goto error;
++      }
++
++      /* close it later (end of the thread) */
++      //os_file_close(dst_log);
++
++      return(FALSE);
++
++error:
++      os_file_close(dst_log);
++      return(TRUE);
++}
++
++/* copying logfile in background */
++#define SLEEPING_PERIOD 5
++
++static
++#ifndef __WIN__
++void*
++#else
++ulint
++#endif
++log_copying_thread(
++      void*   arg)
++{
++      log_copying_running = TRUE;
++
++      while(log_copying) {
++              sleep(SLEEPING_PERIOD);
++
++              if(xtrabackup_copy_logfile(log_copy_scanned_lsn))
++                      goto end;
++      }
++
++      log_copying_succeed = TRUE;
++end:
++      log_copying_running = FALSE;
++      os_thread_exit(NULL);
++}
++
++
++/************************************************************************
++I/o-handler thread function. */
++static
++
++#ifndef __WIN__
++void*
++#else
++ulint
++#endif
++io_handler_thread(
++/*==============*/
++      void*   arg)
++{
++      ulint   segment;
++      ulint   i;
++      
++      segment = *((ulint*)arg);
++
++#ifdef UNIV_DEBUG_THREAD_CREATION
++      fprintf(stderr, "Io handler thread %lu starts, id %lu\n", segment,
++                      os_thread_pf(os_thread_get_curr_id()));
++#endif
++      for (i = 0;; i++) {
++              fil_aio_wait(segment);
++      }
++
++      /* We count the number of threads in os_thread_exit(). A created
++      thread should always use that to exit and not use return() to exit.
++      The thread actually never comes here because it is exited in an
++      os_event_wait(). */
++
++      os_thread_exit(NULL);
++
++#ifndef __WIN__
++      return(NULL);                           /* Not reached */
++#else
++      return(0);
++#endif
++}
++
++/* CAUTION: Don't rename file_per_table during backup */
++void
++xtrabackup_backup_func(void)
++{
++      MY_STAT stat_info;
++
++      /* cd to datadir */
++
++      if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
++      {
++              fprintf(stderr, "cannot my_setwd %s\n", mysql_real_data_home);
++              exit(1);
++      }
++      mysql_data_home= mysql_data_home_buff;
++      mysql_data_home[0]=FN_CURLIB;           // all paths are relative from 
here
++      mysql_data_home[1]=0;
++
++      /* initialize components */
++        if(innodb_init_param())
++                exit(1);
++
++        if (srv_pool_size >= 1000 * 1024) {
++                                  /* Here we still have srv_pool_size counted
++                                  in kilobytes (in 4.0 this was in bytes)
++                                srv_boot() converts the value to
++                                  pages; if buffer pool is less than 1000 MB,
++                                  assume fewer threads. */
++                srv_max_n_threads = 50000;
++
++        } else if (srv_pool_size >= 8 * 1024) {
++
++                srv_max_n_threads = 10000;
++        } else {
++              srv_max_n_threads = 1000;       /* saves several MB of memory,
++                                                especially in 64-bit
++                                                computers */
++        }
++
++      {
++      ulint   n;
++      ulint   i;
++
++      n = srv_n_data_files;
++      
++      for (i = 0; i < n; i++) {
++              srv_data_file_sizes[i] = srv_data_file_sizes[i]
++                                      * ((1024 * 1024) / UNIV_PAGE_SIZE);
++      }               
++
++      srv_last_file_size_max = srv_last_file_size_max
++                                      * ((1024 * 1024) / UNIV_PAGE_SIZE);
++              
++      srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE;
++
++      srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
++
++      srv_pool_size = srv_pool_size / (UNIV_PAGE_SIZE / 1024);
++
++      srv_awe_window_size = srv_awe_window_size / UNIV_PAGE_SIZE;
++      
++      if (srv_use_awe) {
++              /* If we are using AWE we must save memory in the 32-bit
++              address space of the process, and cannot bind the lock
++              table size to the real buffer pool size. */
++
++              srv_lock_table_size = 20 * srv_awe_window_size;
++      } else {
++              srv_lock_table_size = 5 * srv_pool_size;
++      }
++      }
++
++      srv_general_init();
++
++      {
++      buf_pool_t*     ret;
++      ibool   create_new_db;
++      ibool   log_file_created;
++      ibool   log_created     = FALSE;
++      ibool   log_opened      = FALSE;
++      dulint  min_flushed_lsn;
++      dulint  max_flushed_lsn;
++      ulint   sum_of_new_sizes;
++      ulint   sum_of_data_file_sizes;
++      ulint   tablespace_size_in_header;
++      ulint   err;
++      ulint   i;
++      ibool   srv_file_per_table_original_value  = srv_file_per_table;
++      mtr_t   mtr;
++
++
++
++
++#define SRV_N_PENDING_IOS_PER_THREAD  OS_AIO_N_PENDING_IOS_PER_THREAD
++#define SRV_MAX_N_PENDING_SYNC_IOS    100
++                os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
++                            * srv_n_file_io_threads,
++                            srv_n_file_io_threads,
++                            SRV_MAX_N_PENDING_SYNC_IOS);
++
++      fil_init(srv_max_n_open_files);
++
++      fsp_init();
++      log_init();
++
++      lock_sys_create(srv_lock_table_size);
++
++      for (i = 0; i < srv_n_file_io_threads; i++) {
++              n[i] = i;
++
++              os_thread_create(io_handler_thread, n + i, thread_ids + i);
++      }
++
++      err = open_or_create_data_files(&create_new_db,
++                                      &min_flushed_lsn, &max_flushed_lsn,
++                                      &sum_of_new_sizes);
++      if (err != DB_SUCCESS) {
++              fprintf(stderr,
++"InnoDB: Could not open or create data files.\n"
++"InnoDB: If you tried to add new data files, and it failed here,\n"
++"InnoDB: you should now edit innodb_data_file_path in my.cnf back\n"
++"InnoDB: to what it was, and remove the new ibdata files InnoDB created\n"
++"InnoDB: in this failed attempt. InnoDB only wrote those files full of\n"
++"InnoDB: zeros, but did not yet use them in any way. But be careful: do not\n"
++"InnoDB: remove old data files which contain your precious data!\n");
++
++              //return((int) err);
++              exit(1);
++      }
++
++      /* create_new_db must not be TRUE.. */
++      if (create_new_db) {
++              fprintf(stderr, "InnoDB: Something wrong with source 
files...\n");
++              exit(1);
++      }
++
++      for (i = 0; i < srv_n_log_files; i++) {
++              err = open_or_create_log_file(create_new_db, &log_file_created,
++                                                           log_opened, 0, i);
++              if (err != DB_SUCCESS) {
++
++                      //return((int) err);
++                      exit(1);
++              }
++
++              if (log_file_created) {
++                      log_created = TRUE;
++              } else {
++                      log_opened = TRUE;
++              }
++              if ((log_opened && create_new_db)
++                                      || (log_opened && log_created)) {
++                      fprintf(stderr, 
++      "InnoDB: Error: all log files must be created at the same time.\n"
++      "InnoDB: All log files must be created also in database creation.\n"
++      "InnoDB: If you want bigger or smaller log files, shut down the\n"
++      "InnoDB: database and make sure there were no errors in shutdown.\n"
++      "InnoDB: Then delete the existing log files. Edit the .cnf file\n"
++      "InnoDB: and start the database again.\n");
++
++                      //return(DB_ERROR);
++                      exit(1);
++              }
++      }
++
++      /* log_file_created must not be TRUE, if online */
++      if (log_file_created) {
++              fprintf(stderr, "InnoDB: Something wrong with source 
files...\n");
++              exit(1);
++      }
++
++      fil_load_single_table_tablespaces();
++
++      }
++
++      /* create target dir if not exist */
++      if (!my_stat(xtrabackup_target_dir,&stat_info,MYF(0))
++              && (my_mkdir(xtrabackup_target_dir,0777,MYF(0)) < 0)){
++              fprintf(stderr,"Error: cannot mkdir %d: 
%s\n",my_errno,xtrabackup_target_dir);
++              exit(1);
++      }
++
++
++        {
++      char    path[FN_REFLEN];
++      char    *ptr1, *ptr2;
++
++        fil_system_t*   system = fil_system;
++        fil_space_t*    space;
++      fil_space_t*    last_src;
++        fil_node_t*     node;
++
++      /* definition from recv_recovery_from_checkpoint_start() */
++      log_group_t*    group;
++      log_group_t*    max_cp_group;
++      log_group_t*    up_to_date_group;
++      ulint           max_cp_field;
++      dulint          checkpoint_lsn;
++      dulint          checkpoint_no;
++      dulint          old_scanned_lsn;
++      dulint          group_scanned_lsn;
++      dulint          contiguous_lsn;
++      dulint          archived_lsn;
++      ulint           capacity;
++      byte*           buf;
++      byte            log_hdr_buf_[LOG_FILE_HDR_SIZE + 
OS_FILE_LOG_BLOCK_SIZE];
++      byte*           log_hdr_buf;
++      ulint           err;
++
++      ibool           success;
++
++      log_hdr_buf = ut_align(log_hdr_buf_, OS_FILE_LOG_BLOCK_SIZE);
++
++      /* log space */
++      space = UT_LIST_GET_NEXT(space_list, 
UT_LIST_GET_FIRST(system->space_list));
++      printf("space: name=%s, id=%d, purpose=%d, size=%d\n",
++              space->name, space->id, space->purpose, space->size);
++
++      /* get current checkpoint_lsn */
++      /* Look for the latest checkpoint from any of the log groups */
++      
++      err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
++
++      if (err != DB_SUCCESS) {
++
++              exit(1);
++      }
++              
++      log_group_read_checkpoint_info(max_cp_group, max_cp_field);
++      buf = log_sys->checkpoint_buf;
++
++      checkpoint_lsn_start = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
++      checkpoint_no_start = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
++
++reread_log_header:
++      fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, max_cp_group->space_id,
++                              0, 0, LOG_FILE_HDR_SIZE,
++                              log_hdr_buf, max_cp_group);
++
++      /* check consistency of log file header to copy */
++        err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
++
++        if (err != DB_SUCCESS) {
++
++                exit(1);
++        }
++
++        log_group_read_checkpoint_info(max_cp_group, max_cp_field);
++        buf = log_sys->checkpoint_buf;
++
++      if(ut_dulint_cmp(checkpoint_no_start,
++                      mach_read_from_8(buf + LOG_CHECKPOINT_NO)) != 0) {
++              checkpoint_lsn_start = mach_read_from_8(buf + 
LOG_CHECKPOINT_LSN);
++              checkpoint_no_start = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
++              goto reread_log_header;
++      }
++
++      /* open 'xtrabackup_logfile' */
++      sprintf(dst_log_path, "%s%s", xtrabackup_target_dir, 
"/xtrabackup_logfile");
++      dst_log = os_file_create(dst_log_path, OS_FILE_OVERWRITE,
++                                      OS_FILE_AIO, OS_LOG_FILE, &success);
++
++                if (!success) {
++                        /* The following call prints an error message */
++                        os_file_get_last_error(TRUE);
++
++                        ut_print_timestamp(stderr);
++
++                        fprintf(stderr,
++"  InnoDB: error: cannot open %s\n.",
++                                dst_log_path);
++                        exit(1);
++                }
++
++      success = os_file_write(dst_log_path, dst_log, log_hdr_buf,
++                      0, 0, LOG_FILE_HDR_SIZE);
++      log_copy_offset += LOG_FILE_HDR_SIZE;
++      if (!success) {
++              if (!dst_log == -1)
++                      os_file_close(dst_log);
++              exit(1);
++      }
++
++      /* copy log file by current position */
++      if(xtrabackup_copy_logfile(checkpoint_lsn_start))
++              exit(1);
++
++
++      /* start back ground thread to copy newer log */
++      os_thread_id_t log_copying_thread_id;
++
++      log_copying = TRUE;
++      os_thread_create(log_copying_thread, NULL, &log_copying_thread_id);
++
++
++
++        //mutex_enter(&(system->mutex)); /* NOTE: It may not needed at 
"--backup" for now */
++
++        space = UT_LIST_GET_FIRST(system->space_list);
++      last_src = UT_LIST_GET_LAST(system->space_list);
++
++        while (space != NULL) {
++              if (space->purpose == FIL_TABLESPACE) { /* datafile only */
++
++                //printf("space: name=%s, id=%d, purpose=%d, size=%d\n",
++                //        space->name, space->id, space->purpose, 
space->size);
++
++              /* mkdir if not exist */
++              ptr1 = strstr(space->name, "/");
++              ptr2 = strstr(ptr1 + 1, "/");
++              if(ptr2) {
++                      /* single table space */
++                      *ptr2 = 0; /* temporary (it's my lazy..)*/
++                      sprintf(path, "%s%s",xtrabackup_target_dir,ptr1);
++                      *ptr2 = '/';
++
++                      if (!my_stat(path,&stat_info,MYF(0))
++                              && (my_mkdir(path,0777,MYF(0)) < 0)){
++
++                              fprintf(stderr,"Error: cannot mkdir %d: 
%s\n",my_errno,path);
++                              exit(1);
++                      }
++              }
++
++              node = UT_LIST_GET_FIRST(space->chain);
++                while (node != NULL) {
++                        //printf("  node: name=%s, open=%d, size=%d\n",
++                        //       node->name, node->open, node->size);
++
++                      /* copy the datafile */
++                      if(xtrabackup_copy_datafile(node))
++                              exit(1);
++
++                        node = UT_LIST_GET_NEXT(chain, node);
++                }
++              }
++
++              if (space == last_src)
++                      break;
++
++                space = UT_LIST_GET_NEXT(space_list, space);
++        }
++
++        //mutex_exit(&(system->mutex));
++        }
++
++
++
++      /* stop log_copying_thread */
++      log_copying = FALSE;
++      printf("Stopping log copying thread");
++      while (log_copying_running) {
++              printf(".");
++              sleep(1);
++      }
++      printf("\n");
++      if (!log_copying_succeed) {
++              fprintf(stderr, "Error: log_copying_thread failed.");
++              exit(1);
++      }
++
++        os_file_close(dst_log);
++
++        printf("Transaction log of lsn (%lu %lu) to (%lu %lu) was copied.\n",
++                checkpoint_lsn_start.high, checkpoint_lsn_start.low,
++                log_copy_scanned_lsn.high, log_copy_scanned_lsn.low);
++}
++
++/* ================= prepare ================= */
++
++void
++xtrabackup_prepare_func(void)
++{
++      /* cd to target-dir */
++
++      if (my_setwd(xtrabackup_real_target_dir,MYF(MY_WME)))
++      {
++              fprintf(stderr, "cannot my_setwd %s\n", 
xtrabackup_real_target_dir);
++              exit(1);
++      }
++      xtrabackup_target_dir= mysql_data_home_buff;
++      xtrabackup_target_dir[0]=FN_CURLIB;             // all paths are 
relative from here
++      xtrabackup_target_dir[1]=0;
++
++
++      /* TODO: Create logfiles for recovery from 'xtrabackup_logfile', before 
start InnoDB */
++
++
++      /* check the accessibility of target-dir */
++      /* ############# TODO ##################### */
++
++      if(innodb_init_param())
++              exit(1);
++
++      if(innodb_init())
++              exit(1);
++
++      printf("Hello InnoDB world!\n");
++
++      /* TEST: innodb status*/
++      ulint   trx_list_start = ULINT_UNDEFINED;
++      ulint   trx_list_end = ULINT_UNDEFINED;
++      srv_printf_innodb_monitor(stdout, &trx_list_start, &trx_list_end);
++
++      /* TEST: list of datafiles and transaction log files and LSN*/
++      /* ############# TODO ##################### */
++
++      {
++      fil_system_t*   system = fil_system;
++      fil_space_t*    space;
++      fil_node_t*     node;
++
++        mutex_enter(&(system->mutex));
++
++        space = UT_LIST_GET_FIRST(system->space_list);
++
++        while (space != NULL) {
++              /* print info about space */
++
++              printf("space: name=%s, id=%d, purpose=%d, size=%d\n",
++                      space->name, space->id, space->purpose, space->size);
++
++                node = UT_LIST_GET_FIRST(space->chain);
++
++                while (node != NULL) {
++                      /* print info about nodes */
++
++                      printf("node: name=%s, open=%d, size=%d\n",
++                              node->name, node->open, node->size);
++
++                        node = UT_LIST_GET_NEXT(chain, node);
++                }
++                space = UT_LIST_GET_NEXT(space_list, space);
++        }
++
++        mutex_exit(&(system->mutex));
++      }
++
++      if(innodb_end())
++              exit(1);
++
++      printf("################################################\n");
++      printf("Attention: --prepare is not implemented yet!!!!!\n");
++      printf("################################################\n");
++}
++
++/* ================= main =================== */
++
++int main(int argc, char **argv)
++{
++      int ho_error;
++
++      MY_INIT(argv[0]);
++
++      load_defaults("my",load_default_groups,&argc,&argv);
++
++      /* ignore unsupported options */
++      {
++      int i,j,argc_new,find;
++      char *optend, *prev_found;
++      argc_new = argc;
++
++      j=1;
++      for (i=1 ; i < argc ; i++) {
++              optend= strcend((argv)[i], '=');
++              uint count;
++              struct my_option *opt= (struct my_option *) my_long_options;
++              for (count= 0; opt->name; opt++) {
++                      if (!getopt_compare_strings(opt->name, (argv)[i] + 2,
++                              (uint)(optend - (argv)[i] - 2))) /* match found 
*/
++                      {
++                              if (!opt->name[(uint)(optend - (argv)[i] - 2)]) 
{
++                                      find = 1;
++                                      goto next_opt;
++                              }
++                              if (!count) {
++                                      count= 1;
++                                      prev_found= (char *) opt->name;
++                              }
++                              else if (strcmp(prev_found, opt->name)) {
++                                      count++;
++                              }
++                      }
++              }
++              find = count;
++next_opt:
++              if(!find){
++                      argc_new--;
++              } else {
++                      (argv)[j]=(argv)[i];
++                      j++;
++              }
++      }
++      argc = argc_new;
++      }
++
++      if ((ho_error=handle_options(&argc, &argv, my_long_options, 
get_one_option)))
++              exit(ho_error);
++
++      /* cannot execute both for now */
++      if (xtrabackup_backup == xtrabackup_prepare) { /* !XOR (for now) */
++              usage();
++              exit(-1);
++      }
++
++      /* --backup */
++      if (xtrabackup_backup)
++              xtrabackup_backup_func();
++
++      /* --prepare */
++      if (xtrabackup_prepare)
++              xtrabackup_prepare_func();
++
++      exit(0);
++}
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/percona-server.git/commitdiff/431f68fe79a66d5dfdd53f2655709e6c925fbc22

_______________________________________________
pld-cvs-commit mailing list
[email protected]
http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit

Reply via email to