~percona-dev/percona-xtrabackup/win_tests

7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1
#!/usr/bin/perl -w
2
#
3
# A script for making backups of InnoDB and MyISAM tables, indexes and .frm
4
# files.
5
#
240 by Alexey Kopytov
Updates to built-in innobackupex usage docs.
6
# Copyright 2003, 2009 Innobase Oy and Percona Inc 2009-2011. All Rights Reserved.
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
7
#
8
9
use strict;
10
use Getopt::Long;
11
use File::Spec;
240 by Alexey Kopytov
Updates to built-in innobackupex usage docs.
12
use Pod::Usage qw(pod2usage);
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
13
use POSIX "strftime";
14
use POSIX ":sys_wait_h";
15
use POSIX "tmpnam";
16
use FileHandle;
109.1.1 by Aleksandr Kuzminsky
Fixed Bug #434486: Using dirname(), basename() instead of manual parsing of filenames
17
use File::Basename;
121.1.1 by Daniel Nichter
Get ibbackup/xtrabackup exit code. Exit with same.
18
use English qw(-no_match_vars);
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
19
20
# version of this script
21
my $innobackup_version = '1.5.1-xtrabackup';
109.3.1 by Aleksandr Kuzminsky
Fixed Bug #463709: The script outputs its own name
22
my $innobackup_script = basename($0);
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
23
24
# copyright notice
25
my $copyright_notice = 
240 by Alexey Kopytov
Updates to built-in innobackupex usage docs.
26
"InnoDB Backup Utility v${innobackup_version}; Copyright 2003, 2009 Innobase Oy
27
and Percona Inc 2009-2011.  All Rights Reserved.
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
28
29
This software is published under
30
the GNU GENERAL PUBLIC LICENSE Version 2, June 1991.
31
32
";
33
34
# required Perl version (5.005)
35
my @required_perl_version = (5, 0, 5);
36
my $required_perl_version_old_style = 5.005;
37
38
# force flush after every write and print
39
$| = 1;
40
41
######################################################################
42
# modifiable parameters
43
######################################################################
44
45
# maximum number of files in a database directory which are
46
# separately printed when a backup is made
47
my $backup_file_print_limit = 9;
48
49
# timeout in seconds for a reply from mysql
50
my $mysql_response_timeout = 900;
51
52
# default compression level (this is an argument to ibbackup)
53
my $default_compression_level = 1;
54
55
# time in seconds after which a dummy query is sent to mysql server
56
# in order to keep the database connection alive
57
my $mysql_keep_alive_timeout = 1800;
58
59
######################################################################
60
# end of modifiable parameters
61
######################################################################
62
63
64
# command line options
65
my $option_help = '';
66
my $option_version = '';
67
my $option_apply_log = '';
181 by root
added --redo-only option to innobackupex
68
my $option_redo_only = '';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
69
my $option_copy_back = '';
70
my $option_include = '';
71
my $option_databases = '';
166.1.1 by Daniel Nichter
Add --tables-file to innobackupex.
72
my $option_tables_file = '';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
73
my $option_throttle = '';
74
my $option_sleep = '';
75
my $option_compress = 999;
76
my $option_uncompress = '';
61 by kinoyasu
innobackupex can pass --export option
77
my $option_export = '';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
78
my $option_use_memory = '';
79
my $option_mysql_password = '';
80
my $option_mysql_user = '';
81
my $option_mysql_port = '';
82
my $option_mysql_socket = '';
116.1.1 by Daniel Nichter
Bug 510965: add --host, remove --host=127.0.0.1 from --port.
83
my $option_mysql_host = '';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
84
my $option_no_timestamp = '';
85
my $option_slave_info = '';
100.1.1 by Aleksandr Kuzminsky
--no-lock option is added
86
my $option_no_lock = '';
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
87
my $option_ibbackup_binary = 'autodetect';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
88
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
89
my $option_defaults_file = '';
14 by kinoyasu
using rsync for incremental backup
90
my $option_incremental = '';
130 by Vadim Tkachenko
bugfix 546876
91
my $option_incremental_basedir = '';
218 by Vadim Tkachenko
Added option --incremental-dir to innobackupex script
92
my $option_incremental_dir = '';
219 by Vadim Tkachenko
Added option --incremental-lsn to innobackupex script.
93
my $option_incremental_lsn = '';
220 by Vadim Tkachenko
Bugfix #680936
94
my $option_extra_lsndir = '';
14 by kinoyasu
using rsync for incremental backup
95
my $option_remote_host = '';
22 by kinoyasu
"innobackup --stream=tar" is supported
96
my $option_stream = '';
97
my $option_tmpdir = '';
14 by kinoyasu
using rsync for incremental backup
98
68 by kinoyasu
new mode of innobackupex --stream=tar4ibd; new command tar4ibd based on libtar-1.2.11
99
my $option_tar4ibd = '';
119.1.1 by Daniel Nichter
Make --stream=tar use tar4ibd by default unless hidden --force-tar is specified.
100
my $option_force_tar = '';
70.1.1 by Aleksandr Kuzminsky
Allow configuration of scp options
101
my $option_scp_opt = '-Cp -c arcfour';
102
195 by Alexey Kopytov
Implementation of parallel data files transfer for xtrabackup.
103
my $option_parallel = '';
104
127.1.6 by Daniel Nichter
Add and implement --safe-slave-backup and --safe-slave-backup-timeout.
105
my $option_safe_slave_backup = '';
106
my $option_safe_slave_backup_timeout = 300;
107
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
108
# name of the my.cnf configuration file
109
#my $config_file = '';
110
111
# root of the backup directory
112
my $backup_root = '';
113
114
# backup directory pathname
115
my $backup_dir = '';
116
117
# name of the ibbackup suspend-at-end file
118
my $suspend_file = '';
119
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
120
# name of the temporary transaction log file during the backup
121
my $tmp_logfile = '';
122
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
123
# home directory of innoDB log files
124
my $innodb_log_group_home_dir = '';
125
126
# backup my.cnf file
14 by kinoyasu
using rsync for incremental backup
127
my $backup_config_file = '';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
128
129
# options from the options file
130
my %config;
131
132
# options from the backup options file
133
#my %backup_config;
134
135
# list of databases to be included in a backup
136
my %databases_list;
137
171 by Daniel Nichter
Filter files copied according to --tables-file.
138
# list of tables to be included in a backup
139
my %table_list;
140
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
141
# prefix for output lines
109.3.1 by Aleksandr Kuzminsky
Fixed Bug #463709: The script outputs its own name
142
my $prefix = "$innobackup_script:";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
143
144
# process id of mysql client program (runs as a child process of this script)
145
my $mysql_pid = '';
146
147
# mysql server version string
148
my $mysql_server_version = '';
149
150
# name of the file where stderr of mysql process is directed
145 by Aleksandr Kuzminsky
Suppress output to stdout(which breaks --stream backups)Added test xb_stream.sh
151
my $mysql_stderr = 'stderr';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
152
153
# name of the file where stdout of mysql process is directed
145 by Aleksandr Kuzminsky
Suppress output to stdout(which breaks --stream backups)Added test xb_stream.sh
154
my $mysql_stdout = 'stdout';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
155
156
# name of the file where binlog position info is written
157
my $binlog_info;
158
159
# name of the file where slave info is written
160
my $slave_info;
161
162
# mysql binlog position as given by "SHOW MASTER STATUS" command
163
my $mysql_binlog_position = '';
164
165
# mysql master's binlog position as given by "SHOW SLAVE STATUS" command
166
# run on a slave server
167
my $mysql_slave_position = '';
168
169
# time of the most recent mysql_check call. (value returned by time() function)
170
my $mysql_last_access_time = 0;
171
172
# process id of ibbackup program (runs as a child process of this script)
173
my $ibbackup_pid = '';
174
175
# a counter for numbering mysql connection checks
176
my $hello_id = 0;
177
178
# the request which has been sent to mysqld, but to which
179
# mysqld has not yet replied. Empty string denotes that no
180
# request has been sent to mysqld or that mysqld has replied
181
# to all requests.
182
my $current_mysql_request = '';
183
184
# escape sequences for options files
185
my %option_value_escapes = ('b' => "\b",
186
                            't' => "\t",
187
                            'n' => "\n",
188
                            'r' => "\r",
189
                            "\\" => "\\",
190
                            's' => ' ');
191
192
# signal that is sent to child processes when they are killed
193
my $kill_signal = 15;
194
195
# current local time
196
my $now;
197
66 by Vadim Tkachenko
Added incremental option to innobackupex-1.5.1 script
198
# incremental backup base directory
199
my $incremental_basedir = '';
200
108.1.4 by Aleksandr Kuzminsky
escape_path() function is added.
201
my $src_name;
202
my $dst_name;
203
my $win = ($^O eq 'MSWin32' ? 1 : 0);
204
my $CP_CMD = ($win eq 1 ? "copy /Y" : "cp -p");
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
205
my $xtrabackup_binary_file = 'xtrabackup_binary';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
206
######################################################################
207
# program execution begins here
208
######################################################################
209
210
# check command-line args
211
check_args();
212
213
# print program version and copyright
214
print_version();
215
216
# initialize global variables and perform some checks
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
217
if ($option_copy_back) {
162 by Aleksandr Kuzminsky
changed references to old xtrabackup_50
218
    $option_ibbackup_binary = 'xtrabackup_51';
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
219
} elsif ($option_apply_log) {
220
	# Read XtraBackup version from backup dir
221
	if (-e "$backup_dir/$xtrabackup_binary_file") {
222
		# Read XtraBackup version from file
223
		open XTRABACKUP_BINARY, "$backup_dir/$xtrabackup_binary_file"
224
			or die "Cannot open file $backup_dir/$xtrabackup_binary_file: $!\n";
225
		$option_ibbackup_binary = <XTRABACKUP_BINARY>;
226
		close XTRABACKUP_BINARY;
227
		}
228
229
	else {
230
		if( $option_ibbackup_binary eq "autodetect" ){
231
			# Try to connect MySQL and get the version
232
			print "option_ibbackup_binary is autodetect, trying to connect to MySQL\n";
233
			my $options = get_mysql_options();
234
			$mysql_pid = open(*MYSQL_WRITER, "| mysql $options >$mysql_stdout 2>$mysql_stderr ");
235
			print "Connected to MySQL with pid $mysql_pid\n";
236
			sleep 1;
237
			if ($mysql_pid && $mysql_pid == waitpid($mysql_pid, &WNOHANG)) {
238
				my $reason = `cat $mysql_stderr`;
239
				$mysql_pid = '';
240
				# Failed to connect to MySQL
162 by Aleksandr Kuzminsky
changed references to old xtrabackup_50
241
				die "Failed to connect to MySQL server to detect version.\nYou must set xtrabackup version to use with --ibbackup option.\nPossible values are xtrabackup_51 (for MySQL 5.0 and 5.1) or xtrabackup (for MySQL 5.1 with InnoDB plugin or Percona Server)\n";
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
242
				}
243
			else{
244
				mysql_close();
245
				print "Connected successfully\n";
246
				$option_ibbackup_binary = set_xtrabackup_version();
247
				}
248
			}
249
		}
250
} else {
251
    $option_ibbackup_binary = set_xtrabackup_version();
252
}
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
253
init();
254
121.1.1 by Daniel Nichter
Get ibbackup/xtrabackup exit code. Exit with same.
255
my $ibbackup_exit_code = 0;
256
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
257
if ($option_copy_back) {
258
    # copy files from backup directory back to their original locations
259
    copy_back();
260
} elsif ($option_apply_log) {
261
    # expand data files in backup directory by applying log files to them
262
    apply_log();
263
} else {
264
    # make a backup of InnoDB and MyISAM tables, indexes and .frm files.
121.1.1 by Daniel Nichter
Get ibbackup/xtrabackup exit code. Exit with same.
265
    $ibbackup_exit_code = backup();
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
266
    open XTRABACKUP_BINARY, "> $backup_dir/$xtrabackup_binary_file"
267
    	or die "Cannot open file $backup_dir/$xtrabackup_binary_file: $!\n";
268
    print XTRABACKUP_BINARY $option_ibbackup_binary;
269
    close XTRABACKUP_BINARY;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
270
}
271
272
$now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
273
274
if ($option_stream eq 'tar') {
121.1.1 by Daniel Nichter
Get ibbackup/xtrabackup exit code. Exit with same.
275
   print STDERR "$prefix You must use -i (--ignore-zeros) option for extraction of the tar stream.\n";
276
}
277
278
if ( $ibbackup_exit_code == 0 ) {
279
   # program has completed successfully
280
   print STDERR "$now  $prefix completed OK!\n";
281
}
282
else {
283
   print STDERR "$now  $prefix $option_ibbackup_binary failed! (exit code $ibbackup_exit_code)  The backup may not be complete.\n";
284
}
285
286
exit $ibbackup_exit_code;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
287
288
######################################################################
289
# end of program execution
290
######################################################################
291
292
293
#
294
# print_version subroutine prints program version and copyright.
295
#
296
sub print_version {
22 by kinoyasu
"innobackup --stream=tar" is supported
297
    printf(STDERR $copyright_notice);
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
298
}
299
300
301
#
302
# usage subroutine prints instructions of how to use this program to stdout.
303
#
304
sub usage {
240 by Alexey Kopytov
Updates to built-in innobackupex usage docs.
305
   my $msg = shift || '';
306
   pod2usage({ -msg => $msg, -verbose => 1});
307
   return 0;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
308
}
309
310
311
#
312
# return current local time as string in form "070816 12:23:15"
313
#
314
sub current_time {
315
    return strftime("%y%m%d %H:%M:%S", localtime());
316
}
317
318
319
#
320
# Die subroutine kills all child processes and exits this process.
321
# This subroutine takes the same argument as the built-in die function.
322
#    Parameters:
323
#       message   string which is printed to stdout
324
#
325
sub Die {
326
    my $message = shift;
327
    my $extra_info = '';
328
329
    # kill all child processes of this process
330
    kill_child_processes();
331
332
    if ($current_mysql_request) {
333
        $extra_info = " while waiting for reply to MySQL request:" .
334
            " '$current_mysql_request'";
335
    }
336
    die "$prefix Error: $message$extra_info";
337
}
338
    
339
340
#
341
# backup subroutine makes a backup of InnoDB and MyISAM tables, indexes and 
342
# .frm files. It connects to the database server and runs ibbackup as a child
343
# process.
344
#
345
sub backup {
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
346
    my $orig_datadir = get_option(\%config, 'mysqld', 'datadir');
347
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
348
    # check that we can connect to the database. This done by
349
    # connecting, issuing a query, and closing the connection.
350
    mysql_open();
351
    mysql_check();
352
    mysql_close();
353
354
    # start ibbackup as a child process
355
    start_ibbackup();
356
357
    # wait for ibbackup to suspend itself
22 by kinoyasu
"innobackup --stream=tar" is supported
358
    if (!$option_remote_host && !$option_stream) {
14 by kinoyasu
using rsync for incremental backup
359
        wait_for_ibbackup_suspend();
360
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
361
66 by Vadim Tkachenko
Added incremental option to innobackupex-1.5.1 script
362
    if (!$option_incremental) {
363
        # connect to database
364
        mysql_open();
365
127.1.6 by Daniel Nichter
Add and implement --safe-slave-backup and --safe-slave-backup-timeout.
366
        if ( $option_safe_slave_backup ) {
367
          wait_for_safe_slave();
368
        }
369
66 by Vadim Tkachenko
Added incremental option to innobackupex-1.5.1 script
370
        # flush tables with read lock
371
        mysql_check();
100.1.1 by Aleksandr Kuzminsky
--no-lock option is added
372
        mysql_lockall() if !$option_no_lock;
66 by Vadim Tkachenko
Added incremental option to innobackupex-1.5.1 script
373
374
    }
127.1.6 by Daniel Nichter
Add and implement --safe-slave-backup and --safe-slave-backup-timeout.
375
223.2.1 by Valentine Gostev
Added fix and test for 420181, added test for 597384
376
    # backup .frm, .MRG, .MYD, .MYI, .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV and .opt files
129 by Vadim Tkachenko
bugfix 402894
377
    backup_files();
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
378
379
    # resume ibbackup and wait till it has finished
121.1.1 by Daniel Nichter
Get ibbackup/xtrabackup exit code. Exit with same.
380
    my $ibbackup_exit_code = resume_ibbackup();
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
381
66 by Vadim Tkachenko
Added incremental option to innobackupex-1.5.1 script
382
    if (!$option_incremental) {
383
        # release read locks on all tables
100.1.1 by Aleksandr Kuzminsky
--no-lock option is added
384
        mysql_unlockall() if !$option_no_lock;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
385
127.1.6 by Daniel Nichter
Add and implement --safe-slave-backup and --safe-slave-backup-timeout.
386
       if ( $option_safe_slave_backup ) {
387
         print STDERR "$prefix: Starting slave SQL thread\n";
388
         mysql_send('START SLAVE SQL_THREAD;');
389
       }
390
66 by Vadim Tkachenko
Added incremental option to innobackupex-1.5.1 script
391
        # disconnect from database
392
        mysql_close();
393
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
394
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
395
    if ($option_remote_host) {
70.1.1 by Aleksandr Kuzminsky
Allow configuration of scp options
396
        system("scp $option_scp_opt '$tmp_logfile' '$option_remote_host:$backup_dir/xtrabackup_logfile'")
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
397
            and Die "Failed to scp file '$option_remote_host:$backup_dir/xtrabackup_logfile': $!";
20 by kinoyasu
innobackup --include=REGEXP with --remote
398
        unlink $tmp_logfile || Die "Failed to delete '$tmp_logfile': $!";
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
399
70.1.1 by Aleksandr Kuzminsky
Allow configuration of scp options
400
        system("scp $option_scp_opt '$orig_datadir/xtrabackup_checkpoints' '$option_remote_host:$backup_dir/xtrabackup_checkpoints'")
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
401
            and Die "Failed to scp file '$option_remote_host:$backup_dir/xtrabackup_checkpoints': $!";
402
        unlink "$orig_datadir/xtrabackup_checkpoints" || Die "Failed to delete '$orig_datadir/xtrabackup_checkpoints': $!";
22 by kinoyasu
"innobackup --stream=tar" is supported
403
    } elsif ($option_stream eq 'tar') {
100.1.1 by Aleksandr Kuzminsky
--no-lock option is added
404
        system("cd $option_tmpdir; tar chf - xtrabackup_logfile")
22 by kinoyasu
"innobackup --stream=tar" is supported
405
            and Die "Failed to stream 'xtrabackup_logfile': $!";
406
        unlink $tmp_logfile || Die "Failed to delete '$tmp_logfile': $!";
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
407
100.1.1 by Aleksandr Kuzminsky
--no-lock option is added
408
        system("cd $orig_datadir; tar chf - xtrabackup_checkpoints")
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
409
            and Die "Failed to stream 'xtrabackup_checkpoints': $!";
410
        unlink "$orig_datadir/xtrabackup_checkpoints" || Die "Failed to delete '$orig_datadir/xtrabackup_checkpoints': $!";
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
411
    }
412
22 by kinoyasu
"innobackup --stream=tar" is supported
413
    print STDERR "\n$prefix Backup created in directory '$backup_dir'\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
414
    if ($mysql_binlog_position) {
22 by kinoyasu
"innobackup --stream=tar" is supported
415
        print STDERR "$prefix MySQL binlog position: $mysql_binlog_position\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
416
    }
417
    if ($mysql_slave_position && $option_slave_info) {
22 by kinoyasu
"innobackup --stream=tar" is supported
418
        print STDERR "$prefix MySQL slave binlog position: $mysql_slave_position\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
419
    }
121.1.1 by Daniel Nichter
Get ibbackup/xtrabackup exit code. Exit with same.
420
421
    return $ibbackup_exit_code;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
422
}
423
424
425
#
426
# are_equal_innodb_data_file_paths subroutine checks if the given
427
# InnoDB data file option values are equal.
428
#   Parameters:
429
#     str1    InnoDB data file path option value
430
#     str2    InnoDB data file path option value
431
#   Return value:
432
#     1  if values are equal
433
#     0  otherwise
434
#
435
sub are_equal_innodb_data_file_paths {
436
    my $str1 = shift;
437
    my $str2 = shift;
438
    my @array1 = split(/;/, $str1);
439
    my @array2 = split(/;/, $str2);
440
    
441
    if ($#array1 != $#array2) { return 0; }
442
443
    for (my $i = 0; $i <= $#array1; $i++) {
444
        my @def1 = split(/:/, $array1[$i]);
445
        my @def2 = split(/:/, $array2[$i]);
446
        
447
        if ($#def1 != $#def2) { return 0; }
448
449
        for (my $j = 0; $j <= $#def1; $j++) {
450
            if ($def1[$j] ne $def2[$j]) { return 0; }
451
        }
452
    }
453
    return 1;
454
}        
455
456
457
#
458
# is_in_array subroutine checks if the given string is in the array.
459
#   Parameters:
460
#     str       a string
461
#     array_ref a reference to an array of strings
462
#   Return value:
463
#     1  if string is in the array
464
#     0  otherwise
465
# 
466
sub is_in_array {
467
    my $str = shift;
468
    my $array_ref = shift;
469
470
    if (grep { $str eq $_ } @{$array_ref}) {
471
        return 1;
472
    }
473
    return 0;
474
}
475
476
477
#
478
# copy_back subroutine copies data and index files from backup directory 
479
# back to their original locations.
480
#
481
sub copy_back {
482
    my $orig_datadir = get_option(\%config, 'mysqld', 'datadir');
483
    my $orig_ibdata_dir = 
484
        get_option(\%config, 'mysqld', 'innodb_data_home_dir');
485
    my $orig_innodb_data_file_path = 
486
        get_option(\%config, 'mysqld', 'innodb_data_file_path');
487
    my $orig_iblog_dir =
488
        get_option(\%config, 'mysqld', 'innodb_log_group_home_dir');
489
    my $excluded_files = 
490
        '^(\.\.?|backup-my\.cnf|xtrabackup_logfile|mysql-std(err|out)|.*\.ibz)$';
491
    my @ibdata_files;
492
    my $iblog_files = '^ib_logfile.*$';
493
    my $compressed_data_file = '.*\.ibz$';
494
    my $file;
495
    my $backup_innodb_data_file_path;
496
    # check that original data directory exists
497
    if (! -d $orig_datadir) {
498
        Die "Original data directory '$orig_datadir' does not exist!";
499
    }
500
    # check that original InnoDB data directory exists
501
    if (! -d $orig_ibdata_dir) {
502
        Die "Original InnoDB data directory '$orig_ibdata_dir' does not exist!";
503
    }
504
    # check that original InnoDB log directory exists
505
    if (! -d $orig_iblog_dir) {
506
        Die "Original InnoDB log directory '$orig_iblog_dir' does not exist!";
507
    }
508
509
    # check that the original options file and the backup options file have
510
    # the same value for "innodb_data_file_path" option
511
    #$backup_innodb_data_file_path = 
512
    #    get_option(\%backup_config, 'mysqld', 'innodb_data_file_path');
513
    #if (!are_equal_innodb_data_file_paths($orig_innodb_data_file_path, 
514
    #                                      $backup_innodb_data_file_path)
515
    #) {
516
    #    Die "The value of 'innodb_data_file_path' option in the original "
517
    #      . "my.cnf file '$config_file' is different from the value "
518
    #      . "in the backup my.cnf file '$backup_config_file'.\n(original: "
519
    #      . "'$orig_innodb_data_file_path')\n"
520
    #      . "(backup:   '$backup_innodb_data_file_path')";
521
    #}
522
523
    # make a list of all ibdata files in the backup directory and all
524
    # directories in the backup directory under which there are ibdata files
525
    foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
526
        my $path = (split(/:/,$a))[0];
42 by kinoyasu
fix bug 357653; remove innobackup-1.5.1.patch
527
        my $filename = (split(/\/+/, $path))[-1];
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
528
529
        # check that the backup data file exists
42 by kinoyasu
fix bug 357653; remove innobackup-1.5.1.patch
530
        if (! -e "$backup_dir/$filename") {
531
            if (-e "$backup_dir/${filename}.ibz") {
532
                Die "Backup data file '$backup_dir/$filename' does not exist, but "
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
533
                  . "its compressed copy '${path}.ibz' exists. Check "
109.3.1 by Aleksandr Kuzminsky
Fixed Bug #463709: The script outputs its own name
534
                  . "that you have run '$innobackup_script --apply-log --uncompress "
535
                  . "...' before attempting '$innobackup_script --copy-back ...' !";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
536
            } else {
42 by kinoyasu
fix bug 357653; remove innobackup-1.5.1.patch
537
                Die "Backup data file '$backup_dir/$filename' does not exist.";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
538
            }
539
        }
540
541
        if (!is_in_array($filename, \@ibdata_files)) {
542
            push(@ibdata_files, $filename);
543
        }
544
    }
545
546
    # copy files from backup dir to their original locations
547
548
    # copy files to original data directory
549
    opendir(DIR, $backup_dir) 
550
        || Die "Can't open directory '$backup_dir': $!\n";
22 by kinoyasu
"innobackup --stream=tar" is supported
551
    print STDERR "$prefix Starting to copy MyISAM tables, indexes,\n"; 
223.2.1 by Valentine Gostev
Added fix and test for 420181, added test for 597384
552
    print STDERR "$prefix .MRG, .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV, .opt, and .frm files\n";
22 by kinoyasu
"innobackup --stream=tar" is supported
553
    print STDERR "$prefix in '$backup_dir'\n";
554
    print STDERR "$prefix back to original data directory '$orig_datadir'\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
555
    while (defined($file = readdir(DIR))) {
556
        if ($file =~ /$excluded_files/) { next; }
557
        if (is_in_array($file, \@ibdata_files)) { next; }
558
        if ($file =~ /$iblog_files/) { next; }
559
        if (-d "$backup_dir/$file") {
560
            my $subdir = "$backup_dir/$file";
561
            my $file2;
562
22 by kinoyasu
"innobackup --stream=tar" is supported
563
            print STDERR "$prefix Copying directory '$subdir'\n";
108.1.6 by Aleksandr Kuzminsky
fixed quoting issue in making dirs when copy_back()
564
            if (! -x "\"".escape_path("$orig_datadir/$file")."\"") {
565
                system("mkdir \"".escape_path("$orig_datadir/$file")."\"") 
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
566
                    and Die "Failed to create directory "
567
                            . "'$orig_datadir/$file' : $!";
568
            }
569
            opendir(SUBDIR, "$subdir") 
570
                || Die "Can't open directory '$subdir': $!\n";
571
            while (defined($file2 = readdir(SUBDIR))) {
572
                if (-d "$subdir/$file2") { next; }
573
                if ($file2 =~ /$compressed_data_file/) { next; }
108.1.4 by Aleksandr Kuzminsky
escape_path() function is added.
574
                $src_name = escape_path("$subdir/$file2");
575
                $dst_name = escape_path("$orig_datadir/$file");
108.1.2 by Aleksandr Kuzminsky
* Use copy instead of cp on windows
576
                system("$CP_CMD \"$src_name\" \"$dst_name\"")
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
577
                    and Die "Failed to copy file '$file': $!";
578
            }
579
            closedir(SUBDIR);
580
        } else { 
22 by kinoyasu
"innobackup --stream=tar" is supported
581
            print STDERR "$prefix Copying file " . 
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
582
                "'$backup_dir/$file'\n";
108.1.4 by Aleksandr Kuzminsky
escape_path() function is added.
583
            $src_name = escape_path("$backup_dir/$file");
584
            $dst_name = escape_path("$orig_datadir");
108.1.2 by Aleksandr Kuzminsky
* Use copy instead of cp on windows
585
            system("$CP_CMD \"$src_name\" \"$dst_name\"")
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
586
                and Die "Failed to copy file '$file': $!";
587
        }
588
    }
589
    closedir(DIR);
590
591
    # copy InnoDB data files to original InnoDB data directory
22 by kinoyasu
"innobackup --stream=tar" is supported
592
    print STDERR "\n$prefix Starting to copy InnoDB tables and indexes\n";
593
    print STDERR "$prefix in '$backup_dir'\n";
594
    print STDERR "$prefix back to original InnoDB data directory '$orig_ibdata_dir'\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
595
    foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
596
        # get the relative pathname of a data file
597
        my $path = (split(/:/,$a))[0];
42 by kinoyasu
fix bug 357653; remove innobackup-1.5.1.patch
598
        my $filename = (split(/\/+/, $path))[-1];
599
        print STDERR "$prefix Copying file '$backup_dir/$filename'\n";
108.1.4 by Aleksandr Kuzminsky
escape_path() function is added.
600
        $src_name = escape_path("$backup_dir/$filename");
601
        $dst_name = escape_path("$orig_ibdata_dir/$path");
602
        system("$CP_CMD \"$src_name\" \"$dst_name\"")
42 by kinoyasu
fix bug 357653; remove innobackup-1.5.1.patch
603
            and Die "Failed to copy file '$filename': $!";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
604
    }
605
606
    # copy InnoDB log files to original InnoDB log directory
607
    opendir(DIR, $backup_dir) 
608
        || Die "Can't open directory '$backup_dir': $!\n";
22 by kinoyasu
"innobackup --stream=tar" is supported
609
    print STDERR "\n$prefix Starting to copy InnoDB log files\n";
610
    print STDERR "$prefix in '$backup_dir'\n";
611
    print STDERR "$prefix back to original InnoDB log directory '$orig_iblog_dir'\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
612
    while (defined($file = readdir(DIR))) {
613
        if ($file =~ /$iblog_files/ && -f "$backup_dir/$file") {
22 by kinoyasu
"innobackup --stream=tar" is supported
614
            print STDERR "$prefix Copying file '$backup_dir/$file'\n";
108.1.4 by Aleksandr Kuzminsky
escape_path() function is added.
615
            $src_name = escape_path("$backup_dir/$file");
616
            $dst_name = escape_path("$orig_iblog_dir");
108.1.3 by Aleksandr Kuzminsky
Fixed a couple of copy issues
617
            system("$CP_CMD \"$src_name\" \"$dst_name\"")
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
618
                and Die "Failed to copy file '$file': $!";
619
        }
620
    }
621
    closedir(DIR);
622
22 by kinoyasu
"innobackup --stream=tar" is supported
623
    print STDERR "$prefix Finished copying back files.\n\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
624
}
625
626
627
#
628
# apply_log subroutine prepares a backup for starting database server
629
# on the backup. It applies InnoDB log files to the InnoDB data files.
630
#
631
sub apply_log {
632
    my $rcode;
633
    my $cmdline = '';
43 by kinoyasu
fix bug 358266, bug 359341
634
    my $options = '';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
635
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
636
    if ($option_defaults_file) {
108.1.5 by Aleksandr Kuzminsky
Fixed issue in quoting defaults-file when specified
637
        $options = $options . " --defaults-file=\"$option_defaults_file\" ";
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
638
    }
43 by kinoyasu
fix bug 358266, bug 359341
639
640
    $options = $options . "--prepare --target-dir=$backup_dir";
641
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
642
    if ($option_uncompress) {
643
        $options = $options . ' --uncompress';
644
    }
61 by kinoyasu
innobackupex can pass --export option
645
    if ($option_export) {
646
        $options = $options . ' --export';
647
    }
181 by root
added --redo-only option to innobackupex
648
    if ($option_redo_only) {
649
        $options = $options . ' --apply-log-only';
650
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
651
    if ($option_use_memory) {
652
        $options = $options . " --use-memory=$option_use_memory";
653
    }
654
218 by Vadim Tkachenko
Added option --incremental-dir to innobackupex script
655
    if ($option_incremental_dir) {
656
        $options = $options . " --incremental-dir=$option_incremental_dir";
657
    }
658
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
659
    # run ibbackup as a child process
660
    $cmdline = "$option_ibbackup_binary $options";
661
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
662
    print STDERR "\n$now  $prefix Starting ibbackup with command: $cmdline\n\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
663
    $rcode = system("$cmdline");
664
    if ($rcode) {
665
        # failure
666
        Die "\n$prefix ibbackup failed";
667
    }
668
222 by Vadim Tkachenko
Disabled auto-creating of ib_logfile* when
669
    # We should not create ib_logfile files if we prepare for following incremental applies
670
    # Also we do not prepare ib_logfile if we applied incremental changes
671
    if (!( ($option_redo_only) or ($option_incremental_dir))) { 
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
672
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
673
    print STDERR "\n$now  $prefix Restarting xtrabackup with command: $cmdline\nfor creating ib_logfile*\n\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
674
    $rcode = system("$cmdline");
675
    if ($rcode) {
676
        # failure
677
        Die "\n$prefix xtrabackup (2nd execution) failed";
678
    }
222 by Vadim Tkachenko
Disabled auto-creating of ib_logfile* when
679
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
680
}
681
682
683
#
684
# wait_for_ibbackup_suspend subroutine waits until ibbackup has suspended 
685
# itself.
686
#
687
sub wait_for_ibbackup_suspend {
22 by kinoyasu
"innobackup --stream=tar" is supported
688
    print STDERR "$prefix Waiting for ibbackup (pid=$ibbackup_pid) to suspend\n";
689
    print STDERR "$prefix Suspend file '$suspend_file'\n\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
690
    for (;;) {
691
        sleep 2;
692
        last if -e $suspend_file;
693
694
        # check that ibbackup child process is still alive
695
        if ($ibbackup_pid == waitpid($ibbackup_pid, &WNOHANG)) {
696
            $ibbackup_pid = '';
697
            Die "ibbackup child process has died";
698
        }
699
    }
700
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
701
    print STDERR "\n$now  $prefix Continuing after ibbackup has suspended\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
702
}
703
704
705
#
706
# resume_ibbackup subroutine signals ibbackup to complete its execution
707
# by deleting the 'ibbackup_suspended' file.
708
#
709
sub resume_ibbackup {
22 by kinoyasu
"innobackup --stream=tar" is supported
710
    print STDERR "$prefix Resuming ibbackup\n\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
711
    unlink $suspend_file || Die "Failed to delete '$suspend_file': $!";
712
713
    # wait for ibbackup to finish
714
    waitpid($ibbackup_pid, 0);
715
    $ibbackup_pid = '';
121.1.1 by Daniel Nichter
Get ibbackup/xtrabackup exit code. Exit with same.
716
    return $CHILD_ERROR >> 8;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
717
}
718
    
719
720
#
721
# start_ibbackup subroutine spawns a child process running ibbackup
722
# program for backing up InnoDB tables and indexes.
723
#
724
sub start_ibbackup {
43 by kinoyasu
fix bug 358266, bug 359341
725
    my $options = '';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
726
    my $cmdline = '';
727
    my $pid = undef;
728
43 by kinoyasu
fix bug 358266, bug 359341
729
    if ($option_defaults_file) {
108.1.5 by Aleksandr Kuzminsky
Fixed issue in quoting defaults-file when specified
730
        $options = $options . " --defaults-file=\"$option_defaults_file\" ";
43 by kinoyasu
fix bug 358266, bug 359341
731
    }
732
733
    $options = $options . "--backup --suspend-at-end";
734
22 by kinoyasu
"innobackup --stream=tar" is supported
735
    if (!$option_remote_host && !$option_stream) {
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
736
        $options = $options . " --target-dir=$backup_dir";
737
    } else {
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
738
        #(datadir) for 'xtrabackup_suspended' and 'xtrabackup_checkpoints'
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
739
        $options = $options . " --log-stream --target-dir=./";
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
740
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
741
742
    # prepare command line for running ibbackup
743
    if ($option_throttle) {
744
        $options = $options . " --throttle=$option_throttle";
745
    }
746
    if ($option_sleep) {
747
        $options = $options . " --sleep=$option_sleep";
748
    }
749
    if ($option_compress) {
750
        $options = $options . " --compress=$option_compress";
751
    }
752
    if ($option_use_memory) {
753
        $options = $options . " --use-memory=$option_use_memory";
754
    }
755
    if ($option_include) {
19 by kinoyasu
xtrabackup --tables=REGEXP, innobackup --index=REGEXP
756
        $options = $options . " --tables='$option_include'";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
757
    }
220 by Vadim Tkachenko
Bugfix #680936
758
    if ($option_extra_lsndir) {
759
        $options = $options . " --extra-lsndir='$option_extra_lsndir'";
760
    }
761
66 by Vadim Tkachenko
Added incremental option to innobackupex-1.5.1 script
762
    if ($option_incremental) {
219 by Vadim Tkachenko
Added option --incremental-lsn to innobackupex script.
763
        if($option_incremental_lsn) {
764
          $options = $options . " --incremental-lsn='$option_incremental_lsn'";
765
	} else {
766
          $options = $options . " --incremental-basedir='$incremental_basedir'";
767
	}
66 by Vadim Tkachenko
Added incremental option to innobackupex-1.5.1 script
768
    }
220 by Vadim Tkachenko
Bugfix #680936
769
166.1.1 by Daniel Nichter
Add --tables-file to innobackupex.
770
    if ($option_tables_file) {
771
        $options = $options . " --tables_file='$option_tables_file'";
772
    }
195 by Alexey Kopytov
Implementation of parallel data files transfer for xtrabackup.
773
    if ($option_parallel) {
774
        $options = $options. " --parallel=$option_parallel";
775
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
776
    $cmdline = "$option_ibbackup_binary $options";
777
778
    # run ibbackup as a child process
779
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
780
    print STDERR "\n$now  $prefix Starting ibbackup with command: $cmdline\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
781
    if (defined($pid = fork)) {
782
        if ($pid) {
783
            # parent process
784
            $ibbackup_pid = $pid;
14 by kinoyasu
using rsync for incremental backup
785
22 by kinoyasu
"innobackup --stream=tar" is supported
786
            if($option_remote_host || $option_stream) {
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
787
                #direct copy to remote
14 by kinoyasu
using rsync for incremental backup
788
                my $orig_datadir = get_option(\%config, 'mysqld', 'datadir');
789
                my $orig_ibdata_dir =
790
                    get_option(\%config, 'mysqld', 'innodb_data_home_dir');
791
                my $orig_innodb_data_file_path =
792
                    get_option(\%config, 'mysqld', 'innodb_data_file_path');
224 by Alexey Kopytov
Bug #606981: linux + o_direct + stream backup = broken?
793
                my $innodb_flush_method = 
794
                    get_option(\%config, 'mysqld', 'innodb_flush_method');
795
                my $innodb_use_odirect;
796
                $innodb_use_odirect = 1 if $innodb_flush_method =~ m/O_DIRECT/i;
797
14 by kinoyasu
using rsync for incremental backup
798
                my $subdir;
799
                my @list;
800
22 by kinoyasu
"innobackup --stream=tar" is supported
801
                if($option_remote_host) {
802
                    if (system("ssh $option_remote_host test -e $backup_dir/ib_logfile0")
803
                            == 0) {
804
                        print STDERR "$prefix Remove $option_remote_host:$backup_dir/ib_logfile*\n";
805
                        system("ssh $option_remote_host rm $backup_dir/ib_logfile\*")
806
                            and Die "Failed to rm file '$backup_dir/ib_logfile*': $!";
807
                    }
14 by kinoyasu
using rsync for incremental backup
808
                }
809
810
                wait_for_ibbackup_suspend();
811
812
                #InnoDB data files from original InnoDB data directory
22 by kinoyasu
"innobackup --stream=tar" is supported
813
                print STDERR "\n$prefix Starting to backup InnoDB tables and indexes\n";
814
                if($option_remote_host) {
815
                    print STDERR "$prefix to '$backup_dir'\n";
816
                }
817
                print STDERR "$prefix from original InnoDB data directory '$orig_ibdata_dir'\n";
14 by kinoyasu
using rsync for incremental backup
818
                foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
819
                    my $path = (split(/:/,$a))[0];
86.1.1 by akuzminsky
Fixed bug#417178
820
                    $path=~s/([\$\\\" ])/\\$1/g;
22 by kinoyasu
"innobackup --stream=tar" is supported
821
                    if($option_remote_host) {
822
                        print STDERR "$prefix Backing up file '$orig_ibdata_dir/$path'\n";
70.1.1 by Aleksandr Kuzminsky
Allow configuration of scp options
823
                        system("scp $option_scp_opt '$orig_ibdata_dir/$path' '$option_remote_host:$backup_dir/$path'")
22 by kinoyasu
"innobackup --stream=tar" is supported
824
                            and Die "Failed to scp file '$path': $!";
825
                    } elsif($option_stream eq 'tar') {
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
826
                        my $ret = 0;
224 by Alexey Kopytov
Bug #606981: linux + o_direct + stream backup = broken?
827
                        my $tarcmd;
22 by kinoyasu
"innobackup --stream=tar" is supported
828
                        print STDERR "$prefix Backing up as tar stream '$path'\n";
68 by kinoyasu
new mode of innobackupex --stream=tar4ibd; new command tar4ibd based on libtar-1.2.11
829
                        if (!$option_tar4ibd) {
224 by Alexey Kopytov
Bug #606981: linux + o_direct + stream backup = broken?
830
                            $tarcmd = "tar chf - -b 32";
68 by kinoyasu
new mode of innobackupex --stream=tar4ibd; new command tar4ibd based on libtar-1.2.11
831
                        } else {
224 by Alexey Kopytov
Bug #606981: linux + o_direct + stream backup = broken?
832
                            $tarcmd = "tar4ibd";
833
                            if ($innodb_use_odirect) {
834
                                $tarcmd = "$tarcmd -d";
835
                            }
836
                            $tarcmd = "$tarcmd -c";
68 by kinoyasu
new mode of innobackupex --stream=tar4ibd; new command tar4ibd based on libtar-1.2.11
837
                        }
224 by Alexey Kopytov
Bug #606981: linux + o_direct + stream backup = broken?
838
                        $ret = system("cd $orig_ibdata_dir; $tarcmd $path") >> 8;
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
839
                        if ($ret == 1) {
840
                            print STDERR "$prefix If you use GNU tar, this warning can be ignored.\n";
841
                        } elsif ($ret != 0) {
58 by kinoyasu
fix error handling of tar stream
842
                            print STDERR "$prefix tar returned with exit code $ret.\n";
182.1.3 by Baron Schwartz
Ignore missing files, as they are likely to be dropped table and can be skipped
843
                            if ( -e "$orig_ibdata_dir/$path" ) {
844
                                Die "Failed to stream '$orig_ibdata_dir/$path': $!";
845
                            }
846
                            else {
847
                                print STDERR "$prefix Ignoring nonexistent file '$orig_ibdata_dir/$path'.\n";
848
                            }
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
849
                        }
22 by kinoyasu
"innobackup --stream=tar" is supported
850
                    }
14 by kinoyasu
using rsync for incremental backup
851
                }
852
853
                #copy *.ibd files
854
                opendir(DIR, $orig_datadir)
855
                    || Die "Can't open directory '$orig_datadir': $!\n";
856
                while (defined($subdir = readdir(DIR))) {
857
                    my $print_each_file = 0;
858
                    my $file_c;
859
                    my $file;
860
                    if ($subdir eq '.' || $subdir eq '..') { next; }
861
                    next unless -d "$orig_datadir/$subdir";
862
                    next unless check_if_required($subdir);
863
864
                    @list = glob("$orig_datadir/$subdir/" . '*.ibd');
865
866
                    $file_c = @list;
867
                    if ($file_c <= $backup_file_print_limit) {
868
                        $print_each_file = 1;
869
                    } else {
22 by kinoyasu
"innobackup --stream=tar" is supported
870
                        print STDERR "$prefix Backing up files " .
14 by kinoyasu
using rsync for incremental backup
871
                            "'$orig_datadir/$subdir/*.ibd' ($file_c files)\n";
872
                    }
873
                    foreach $file (@list) {
174 by Vadim Tkachenko
tables_file option is applied to copy via stream also
874
			next unless check_if_required($subdir, $file);
20 by kinoyasu
innobackup --include=REGEXP with --remote
875
                        if($option_include) {
876
                            my $table_name;
877
878
                            $table_name = substr($file, rindex($file, '/'));
879
                            $table_name = substr($table_name, 1, rindex($table_name, '.') - 1);
23 by kinoyasu
fix REGEXP behavior (including database name)
880
                            $table_name = $subdir . "." . $table_name;
20 by kinoyasu
innobackup --include=REGEXP with --remote
881
882
                            if (!($table_name =~ /$option_include/)) {
22 by kinoyasu
"innobackup --stream=tar" is supported
883
                                print STDERR "'$file' is skipped.\n";
20 by kinoyasu
innobackup --include=REGEXP with --remote
884
                                next;
885
                            }
886
                        }
887
14 by kinoyasu
using rsync for incremental backup
888
                        if ($print_each_file) {
22 by kinoyasu
"innobackup --stream=tar" is supported
889
                            print STDERR "$prefix Backing up file '$file'\n";
890
                        }
891
                        if($option_remote_host) {
892
                            if (system("ssh $option_remote_host test -e $backup_dir/$subdir")
893
                                    != 0) {
894
                                system("ssh $option_remote_host mkdir $backup_dir/$subdir");
895
                            }
70.1.1 by Aleksandr Kuzminsky
Allow configuration of scp options
896
                            system("scp $option_scp_opt '$file' '$option_remote_host:$backup_dir/$subdir/'")
22 by kinoyasu
"innobackup --stream=tar" is supported
897
                                and Die "Failed to scp file '$file': $!";
898
                        } elsif($option_stream eq 'tar') {
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
899
                            my $ret = 0;
22 by kinoyasu
"innobackup --stream=tar" is supported
900
                            my $file_name = substr($file, rindex($file, '/') + 1);
86.1.1 by akuzminsky
Fixed bug#417178
901
                            $file_name=~s/([\$\\\" ])/\\$1/g;
68 by kinoyasu
new mode of innobackupex --stream=tar4ibd; new command tar4ibd based on libtar-1.2.11
902
                            if (!$option_tar4ibd) {
100.1.1 by Aleksandr Kuzminsky
--no-lock option is added
903
                                $ret = system("cd $orig_datadir; tar chf - -b 32 $subdir/$file_name") >> 8;
68 by kinoyasu
new mode of innobackupex --stream=tar4ibd; new command tar4ibd based on libtar-1.2.11
904
                            } else {
69 by kinoyasu
innobackupex: fixed return code handling
905
                                $ret = system("cd $orig_datadir; tar4ibd -c $subdir/$file_name") >> 8;
68 by kinoyasu
new mode of innobackupex --stream=tar4ibd; new command tar4ibd based on libtar-1.2.11
906
                            }
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
907
                            if ($ret == 1) {
908
                                print STDERR "$prefix If you use GNU tar, this warning can be ignored.\n";
909
                            } elsif ($ret != 0) {
58 by kinoyasu
fix error handling of tar stream
910
                                print STDERR "$prefix tar returned with exit code $ret.\n";
182.1.3 by Baron Schwartz
Ignore missing files, as they are likely to be dropped table and can be skipped
911
                                if ( -e "$orig_datadir/$subdir/$file_name" ) {
912
                                    Die "Failed to stream '$orig_datadir/$subdir/$file_name': $!";
913
                                }
914
                                else {
915
                                    print STDERR "$prefix Ignoring nonexistent file '$orig_datadir/$subdir/$file_name'.\n";
916
                                }
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
917
                            }
22 by kinoyasu
"innobackup --stream=tar" is supported
918
                        }
14 by kinoyasu
using rsync for incremental backup
919
                    }
920
                }
921
                closedir(DIR);
922
            }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
923
        } else {
22 by kinoyasu
"innobackup --stream=tar" is supported
924
            if($option_remote_host || $option_stream) {
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
925
                open(STDOUT, "> $tmp_logfile")
926
                || Die "Failed to open file '$tmp_logfile': $!"
14 by kinoyasu
using rsync for incremental backup
927
            }
928
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
929
            # child process
930
            exec($cmdline) || Die "Failed to exec ibbackup: $!";
931
        }
932
    } else {
933
        Die "failed to fork ibbackup child process: $!";
934
    }
935
}
936
                  
937
938
#
939
# get_mysql_options subroutine returns the options to mysql client program
940
# as a string. The options are determined from the options given by the
941
# user to innobackup.
942
#
943
sub get_mysql_options {
114.2.1 by Daniel Nichter
Fix bug 510964: innobackupex doesn't pass --defaults-files to mysql child proc
944
    my $options = '';
945
946
    # this option has to be first
947
    if ($option_defaults_file) {
211.1.2 by Valentine Gostev
Added fix for bug 688211 (additional single quotes)
948
        $options = "$options --defaults-file='$option_defaults_file'";
114.2.1 by Daniel Nichter
Fix bug 510964: innobackupex doesn't pass --defaults-files to mysql child proc
949
    }
950
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
951
    if ($option_mysql_password) {
211.1.2 by Valentine Gostev
Added fix for bug 688211 (additional single quotes)
952
        $options = "$options --password='$option_mysql_password'";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
953
    }
954
    if ($option_mysql_user) {
211.1.2 by Valentine Gostev
Added fix for bug 688211 (additional single quotes)
955
        $options = "$options --user='$option_mysql_user'";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
956
    }
116.1.1 by Daniel Nichter
Bug 510965: add --host, remove --host=127.0.0.1 from --port.
957
    if ($option_mysql_host) {
211.1.2 by Valentine Gostev
Added fix for bug 688211 (additional single quotes)
958
        $options = "$options --host='$option_mysql_host'";
116.1.1 by Daniel Nichter
Bug 510965: add --host, remove --host=127.0.0.1 from --port.
959
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
960
    if ($option_mysql_port) {
211.1.2 by Valentine Gostev
Added fix for bug 688211 (additional single quotes)
961
        $options = "$options --port='$option_mysql_port'";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
962
    }
963
    if ($option_mysql_socket) {
211.1.2 by Valentine Gostev
Added fix for bug 688211 (additional single quotes)
964
        $options = "$options --socket='$option_mysql_socket'";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
965
    }
114.2.1 by Daniel Nichter
Fix bug 510964: innobackupex doesn't pass --defaults-files to mysql child proc
966
    $options = "$options --unbuffered --";
967
    return $options;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
968
}
969
970
971
#
972
# mysql_open subroutine starts mysql as a child process with
973
# a pipe connection.
974
#
975
sub mysql_open {
976
    my $options = get_mysql_options();
977
    # run mysql as a child process with a pipe connection
978
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
979
    print STDERR "$now  $prefix Starting mysql with options: $options\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
980
    $mysql_pid = open(*MYSQL_WRITER, "| mysql $options >$mysql_stdout 2>$mysql_stderr ") or Die "Failed to spawn mysql child process: $!";
981
    MYSQL_WRITER->autoflush(1);
982
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
983
    print STDERR "$now  $prefix Connected to database with mysql child process (pid=$mysql_pid)\n";
239.1.1 by Valentine Gostev
Added test and fix for bug 408803
984
    print MYSQL_WRITER "SET SESSION wait_timeout = 2147000;\n" or die "Connection to mysql child process failed: $!";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
985
986
    mysql_check();
987
}
988
989
990
#
991
# mysql_check subroutine checks that the connection to mysql child process 
992
# is ok.
993
#
994
sub mysql_check {
995
    my $mysql_pid_copy = $mysql_pid;
996
997
    # send a dummy query to mysql child process
998
    $hello_id++;
999
    my $hello_message = "innobackup hello $hello_id";
1000
    print MYSQL_WRITER "select '$hello_message';\n" 
1001
        or Die "Connection to mysql child process failed: $!";
1002
1003
    # wait for reply
1004
    eval {
1005
        local $SIG{ALRM} = sub { die "alarm clock restart" };
1006
        my $stdout = '';
1007
        my $stderr = '';
1008
        alarm $mysql_response_timeout;
1009
        while (index($stdout, $hello_message) < 0) {
1010
            sleep 2;
1011
            if ($mysql_pid && $mysql_pid == waitpid($mysql_pid, &WNOHANG)) {
1012
                my $reason = `cat $mysql_stderr`;
1013
                $mysql_pid = '';
1014
                die "mysql child process has died: $reason";
1015
            }
1016
            $stdout = `cat $mysql_stdout`;
163 by Aleksandr Kuzminsky
suppress warnings in error detecting function
1017
            $stderr = `cat $mysql_stderr | grep -v ^Warning`;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1018
            if ($stderr) {
1019
                # mysql has reported an error, do exit
1020
                die "mysql error: $stderr";
1021
            }
1022
        }
1023
        alarm 0;
1024
    };
1025
    if ($@ =~ /alarm clock restart/) {
1026
        Die "Connection to mysql child process (pid=$mysql_pid_copy) timedout."
1027
            . " (Time limit of $mysql_response_timeout seconds exceeded."
1028
            . " You may adjust time limit by editing the value of parameter"
1029
            . " \"\$mysql_response_timeout\" in this script.)";
1030
    } elsif ($@) { Die $@; }
1031
    
1032
    $mysql_last_access_time = time();
1033
}
1034
1035
1036
#
1037
# mysql_keep_alive subroutine tries to keep connection to the mysqld database
1038
# server alive by sending a dummy query when the connection has been idle
1039
# for the specified time.
1040
#
1041
sub mysql_keep_alive {
1042
    if ((time() - $mysql_last_access_time) > $mysql_keep_alive_timeout) {
1043
        # too long idle, send a dummy query
1044
        mysql_check();
1045
    }
1046
}
1047
1048
1049
#
1050
# mysql_send subroutine send a request string to mysql child process.
1051
# This subroutine appends a newline character to the request and checks 
1052
# that mysqld receives the query.
1053
# Parameters:
1054
#    request  request string
1055
#
1056
sub mysql_send {
1057
    my $request = shift;
1058
1059
    $current_mysql_request = $request;
1060
    print MYSQL_WRITER "$request\n";
1061
    mysql_check();
1062
    $current_mysql_request = '';
1063
}
1064
    
1065
1066
#
1067
# mysql_close subroutine terminates mysql child process gracefully.
1068
# 
1069
sub mysql_close {
1070
    print MYSQL_WRITER "quit\n";
1071
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
1072
    print STDERR "$now  $prefix Connection to database server closed\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1073
    $mysql_pid = '';
1074
}
1075
1076
1077
#
1078
# write_binlog_info subroutine retrieves MySQL binlog position and
1079
# saves it in a file. It also prints it to stdout.
1080
#
1081
sub write_binlog_info {
1082
    my @lines;
1083
    my @info_lines = ();
1084
    my $position = '';
1085
    my $filename = '';
1086
1087
    # get binlog position
1088
    mysql_send "SHOW MASTER STATUS;";
1089
1090
    # get "show master status" output lines (2) from mysql output
1091
    file_to_array($mysql_stdout, \@lines);
1092
    foreach my $line (@lines) {
1093
        if ($line =~ m/innobackup hello/) {
1094
            # this is a hello message, ignore it
1095
        } else {
1096
            # this is output line from "show master status"
1097
            push(@info_lines, $line);
1098
        }
1099
    }
1100
1101
    # write binlog info file
1102
    if (!defined $info_lines[1]) {
1103
        $info_lines[1] = "";
1104
    }
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1105
    if (!$option_remote_host) {
1106
        open(FILE, ">$binlog_info") || 
1107
            Die "Failed to open file '$binlog_info': $!";
1108
    } else {
1109
        open(FILE, "| ssh $option_remote_host 'cat > $binlog_info'") ||
1110
            Die "Failed to open file '$option_remote_host:$binlog_info': $!";
1111
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1112
    print FILE  "$info_lines[1]\n";
1113
    close(FILE);
1114
22 by kinoyasu
"innobackup --stream=tar" is supported
1115
    if ($option_stream eq 'tar') {
100.1.1 by Aleksandr Kuzminsky
--no-lock option is added
1116
        system("cd $option_tmpdir; tar chf - xtrabackup_binlog_info")
22 by kinoyasu
"innobackup --stream=tar" is supported
1117
            and Die "Failed to stream 'xtrabackup_binlog_info': $!";
1118
        unlink $binlog_info || Die "Failed to delete '$binlog_info': $!";
1119
    }
1120
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1121
    # get the name of the last binlog file and position in it
1122
    ($filename, $position) = $info_lines[1] =~ /^\s*([^\s]+)\s+(.*)$/;
1123
1124
    if (defined $filename && defined $position) {
1125
        $mysql_binlog_position = "filename '$filename', position $position";
1126
    } else {
1127
        $mysql_binlog_position = "filename '', position ";
1128
    }        
1129
}
1130
1131
1132
# 
1133
# write_slave_info subroutine retrieves MySQL binlog position of the
1134
# master server in a replication setup and saves it in a file. It
1135
# also saves it in $msql_slave_position variable.
1136
#
1137
sub write_slave_info {
1138
    my @lines;
1139
    my @info_lines;
1140
    my $position = '';
1141
    my $filename = '';
1142
    my $master= '';
1143
	
1144
    # get slave status. Use single quotes here, otherwise
1145
    # \G is evaluated as a control character.
1146
    mysql_send 'SHOW SLAVE STATUS\G;';
1147
1148
    # get output of the "show slave status" command from mysql output
1149
    # and extract binlog position of the master server
1150
    file_to_array($mysql_stdout, \@lines);
1151
    for (@lines) {
1152
        $master = $1 if /Master_Host:\s*(\S*)\s*$/;
1153
        $filename = $1 if /Master_Log_File:\s*(\S*)\s*$/;
1154
        $position = $1 if /Master_Log_Pos:\s*(\S*)\s*$/;
1155
    }
1156
1157
    # print slave status to a file
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1158
    if (!$option_remote_host) {
1159
        open(FILE, ">$slave_info") || 
1160
            Die "Failed to open file '$slave_info': $!";
1161
    } else {
1162
        open(FILE, "| ssh $option_remote_host 'cat > $slave_info'") ||
1163
            Die "Failed to open file '$option_remote_host:$slave_info': $!";
1164
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1165
    print FILE  "CHANGE MASTER TO MASTER_LOG_FILE='$filename', MASTER_LOG_POS=$position\n";
1166
    close(FILE);
1167
22 by kinoyasu
"innobackup --stream=tar" is supported
1168
    if ($option_stream eq 'tar') {
100.1.1 by Aleksandr Kuzminsky
--no-lock option is added
1169
        system("cd $option_tmpdir; tar chf - xtrabackup_slave_info")
22 by kinoyasu
"innobackup --stream=tar" is supported
1170
            and Die "Failed to stream 'xtrabackup_slave_info': $!";
1171
        unlink $slave_info || Die "Failed to delete '$slave_info': $!";
1172
    }
1173
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1174
    $mysql_slave_position = "master host '$master', filename '$filename', position $position";
1175
}
1176
1177
1178
#
1179
# mysql_lockall subroutine puts a read lock on all tables in all databases.
1180
# 
1181
sub mysql_lockall {
1182
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
1183
    print STDERR "$now  $prefix Starting to lock all tables...\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1184
1185
    mysql_send "USE mysql;";
89 by kinoyasu
fix bug 386535, bug 402884, probability to crash --prepare
1186
#    mysql_send "DROP TABLE IF EXISTS ibbackup_binlog_marker;";
1187
#    if (compare_versions($mysql_server_version, '4.1.0') == -1) {
1188
#        # MySQL server version is 4.0 or older, ENGINE keyword not supported
1189
#        mysql_send "CREATE TABLE ibbackup_binlog_marker(a INT) TYPE=INNODB;";
1190
#    } else {
1191
#        # MySQL server version is 4.1 or newer, use ENGINE keyword
1192
#        mysql_send "CREATE TABLE ibbackup_binlog_marker(a INT) ENGINE=INNODB;";
1193
#    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1194
    mysql_send "SET AUTOCOMMIT=0;";
89 by kinoyasu
fix bug 386535, bug 402884, probability to crash --prepare
1195
#    mysql_send "INSERT INTO ibbackup_binlog_marker VALUES (1);";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1196
    if (compare_versions($mysql_server_version, '4.0.22') == 0
1197
        || compare_versions($mysql_server_version, '4.1.7') == 0) {
1198
        # MySQL server version is 4.0.22 or 4.1.7
1199
        mysql_send "COMMIT;";
1200
        mysql_send "FLUSH TABLES WITH READ LOCK;";
1201
    } else {
1202
        # MySQL server version is other than 4.0.22 or 4.1.7
1203
        mysql_send "FLUSH TABLES WITH READ LOCK;";
1204
        mysql_send "COMMIT;";
1205
    }
1206
    write_binlog_info;
1207
    write_slave_info if $option_slave_info;
1208
	
1209
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
1210
    print STDERR "$now  $prefix All tables locked and flushed to disk\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1211
}
1212
1213
1214
#
1215
# mysql_unlockall subroutine releases read locks on all tables in all 
1216
# databases.
1217
# 
1218
sub mysql_unlockall {
1219
    mysql_send "UNLOCK TABLES;";
89 by kinoyasu
fix bug 386535, bug 402884, probability to crash --prepare
1220
#    mysql_send "DROP TABLE IF EXISTS ibbackup_binlog_marker;";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1221
1222
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
1223
    print STDERR "$now  $prefix All tables unlocked\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1224
}
1225
1226
1227
#
1228
# catch_sigpipe subroutine is a signal handler for SIGPIPE.
1229
#
1230
sub catch_sigpipe {
1231
    my $rcode;
1232
1233
    if ($mysql_pid && (-1 == ($rcode = waitpid($mysql_pid, &WNOHANG))
1234
                       || $rcode == $mysql_pid)) {
1235
        my $reason = `cat $mysql_stderr`;
22 by kinoyasu
"innobackup --stream=tar" is supported
1236
        print STDERR "Pipe to mysql child process broken: $reason at";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1237
        system("date +'%H:%M:%S'");
1238
        exit(1);
1239
    } else {
1240
        Die "Broken pipe";
1241
    }
1242
}
1243
1244
1245
#
1246
# kill_child_processes subroutine kills all child processes of this process.
1247
#
1248
sub kill_child_processes {
1249
    if ($ibbackup_pid) {
1250
        kill($kill_signal, $ibbackup_pid);
1251
        $ibbackup_pid = '';
1252
    }
1253
    
1254
    if ($mysql_pid) {
1255
        kill($kill_signal, $mysql_pid);
1256
        $mysql_pid = '';
1257
    }
1258
}
1259
1260
1261
#
1262
# require_external subroutine checks that an external program is runnable
1263
# via the shell. This is tested by calling the program with the
1264
# given arguments. It is checked that the program returns 0 and does 
1265
# not print anything to stderr. If this check fails, this subroutine exits.
1266
#    Parameters:
1267
#       program      pathname of the program file
1268
#       args         arguments to the program
1269
#       pattern      a string containing a regular expression for finding 
1270
#                    the program version.
1271
#                    this pattern should contain a subpattern enclosed
1272
#                    in parentheses which is matched with the version.
1273
#       version_ref  a reference to a variable where the program version
1274
#                    string is returned. Example "2.0-beta2".
1275
#
1276
sub require_external {
1277
    my $program = shift;
1278
    my $args = shift;
1279
    my $pattern = shift;
1280
    my $version_ref = shift;
1281
    my @lines;
1282
    my $tmp_stdout = tmpnam();
1283
    my $tmp_stderr = tmpnam();
1284
    my $rcode;
1285
    my $error;
1286
1287
    $rcode = system("$program $args >$tmp_stdout 2>$tmp_stderr");
1288
    if ($rcode) {
1289
        $error = $!;
1290
    }
163 by Aleksandr Kuzminsky
suppress warnings in error detecting function
1291
    my $stderr = `cat $tmp_stderr | grep -v ^Warning`;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1292
    unlink $tmp_stderr;
1293
    if ($stderr ne '') {
1294
        # failure
1295
        unlink $tmp_stdout;
1296
        Die "Couldn't run $program: $stderr";
1297
    } elsif ($rcode) {
1298
        # failure
1299
        unlink $tmp_stdout;
1300
        Die "Couldn't run $program: $error";
1301
    }
1302
1303
    # success
1304
    my $stdout = `cat $tmp_stdout`;
1305
    unlink $tmp_stdout;
1306
    @lines = split(/\n|;/,$stdout);
22 by kinoyasu
"innobackup --stream=tar" is supported
1307
    print STDERR "$prefix Using $lines[0]\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1308
1309
    # get version string from the first output line of the program
1310
    ${$version_ref} = '';
1311
    if ($lines[0] =~ /$pattern/) {
1312
        ${$version_ref} = $1;
1313
    }
1314
}
1315
1316
1317
# compare_versions subroutine compares two GNU-style version strings.
1318
# A GNU-style version string consists of three decimal numbers delimitted 
1319
# by dots, and optionally followed by extra attributes.
1320
# Examples: "4.0.1", "4.1.1-alpha-debug". 
1321
#    Parameters:
1322
#       str1   a GNU-style version string
1323
#       str2   a GNU-style version string
1324
#    Return value:
1325
#       -1   if str1 < str2
1326
#        0   if str1 == str2
1327
#        1   is str1 > str2
1328
sub compare_versions {
1329
    my $str1 = shift;
1330
    my $str2 = shift;
1331
    my $extra1 = '';
1332
    my $extra2 = '';
1333
    my @array1 = ();
1334
    my @array2 = ();
1335
    my $i;
1336
1337
    # remove possible extra attributes
1338
    ($str1, $extra1) = $str1 =~ /^([0-9.]*)(.*)/;
1339
    ($str2, $extra2) = $str2 =~ /^([0-9.]*)(.*)/;
1340
1341
    # split "dotted" decimal number string into an array
1342
    @array1 = split('\.', $str1);
1343
    @array2 = split('\.', $str2);
1344
1345
    # compare in lexicographic order
1346
    for ($i = 0; $i <= $#array1 && $i <= $#array2; $i++) {
1347
        if ($array1[$i] < $array2[$i]) {
1348
            return -1;
1349
        } elsif ($array1[$i] > $array2[$i]) {
1350
            return 1;
1351
        }
1352
    }
1353
    if ($#array1 < $#array2) {
1354
        return -1;
1355
    } elsif ($#array1 > $#array2) {
1356
        return 1;
1357
    } else {
1358
        return 0;
1359
    }
1360
}
1361
1362
1363
#
1364
# init subroutine initializes global variables and performs some checks on the
1365
# system we are running on.
1366
#
1367
sub init {
1368
    my $mysql_version = '';
1369
    my $ibbackup_version = '';
1370
    my $run = '';
1371
1372
    # print some instructions to the user
1373
    if (!$option_apply_log && !$option_copy_back) {
1374
        $run = 'backup';
1375
    } elsif ($option_copy_back) {
1376
        $run = 'copy-back';
1377
    } else {
1378
        $run = 'apply-log';
1379
    }
22 by kinoyasu
"innobackup --stream=tar" is supported
1380
    print STDERR "IMPORTANT: Please check that the $run run completes successfully.\n";
109.3.1 by Aleksandr Kuzminsky
Fixed Bug #463709: The script outputs its own name
1381
    print STDERR "           At the end of a successful $run run $innobackup_script\n";
1382
    print STDERR "           prints \"completed OK!\".\n\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1383
1384
    # check that MySQL client program and InnoDB Hot Backup program
1385
    # are runnable via shell
1386
    if (!$option_copy_back) {
1387
        # we are making a backup or applying log to backup
1388
        if (!$option_apply_log) {
1389
            # we are making a backup, we need mysql server
1390
            my $output = '';
1391
            my @lines = ();
1392
1393
            # check that we have mysql client program
1394
            require_external('mysql', '--version', 'Ver ([^,]+)', 
1395
                             \$mysql_version);
1396
            
1397
            # get mysql server version
1398
            my $options = get_mysql_options();
1399
            @lines = split('\n', 
108.1.1 by Aleksandr Kuzminsky
Fixed number of issues in innobackupex-1.5.1 on windows platform
1400
                           `mysql $options -e "select \@\@version"`);
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1401
            $mysql_server_version = $lines[1];
22 by kinoyasu
"innobackup --stream=tar" is supported
1402
            print STDERR "$prefix Using mysql server version $mysql_server_version\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1403
        }
1404
        #require_external($option_ibbackup_binary, '--license', 
1405
        #                 'version (\S+)', \$ibbackup_version);
22 by kinoyasu
"innobackup --stream=tar" is supported
1406
        print STDERR "\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1407
        
1408
        if ($option_include 
1409
            && $ibbackup_version 
1410
            && $ibbackup_version le "2.0") {
1411
            # --include option was given, but ibbackup is too
1412
            # old to support it
1413
            Die "--include option was given, but ibbackup is too old"
1414
                . " to support it. You must upgrade to InnoDB Hot Backup"
1415
                . " v2.0 in order to use --include option.\n";
1416
        }
1417
    }
1418
    
1419
    # set signal handlers
1420
    $SIG{PIPE} = \&catch_sigpipe;
1421
1422
    # read MySQL options file
1423
    #read_config_file($config_file, \%config);
1424
    read_config_file(\%config);
1425
22 by kinoyasu
"innobackup --stream=tar" is supported
1426
    if(!$option_tmpdir) {
1427
        $option_tmpdir = get_option(\%config, 'mysqld', 'tmpdir');
1428
    }
1429
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1430
    # get innodb log home directory from options file
1431
    #$innodb_log_group_home_dir = 
1432
    #    get_option(\%config, 'mysqld', 'innodb_log_group_home_dir');
1433
1434
    if (!$option_apply_log && !$option_copy_back) {
1435
        # we are making a backup, create a new backup directory
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
1436
        if (!$option_remote_host) {
14 by kinoyasu
using rsync for incremental backup
1437
            $backup_dir = File::Spec->rel2abs(make_backup_dir());
1438
        } else {
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
1439
            $backup_dir = make_backup_dir();
14 by kinoyasu
using rsync for incremental backup
1440
        }
22 by kinoyasu
"innobackup --stream=tar" is supported
1441
        print STDERR "$prefix Created backup directory $backup_dir\n";
1442
        if (!$option_remote_host && !$option_stream) {
14 by kinoyasu
using rsync for incremental backup
1443
        $backup_config_file = $backup_dir . '/backup-my.cnf';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1444
        $suspend_file = $backup_dir . '/xtrabackup_suspended';
1445
        $mysql_stdout = $backup_dir . '/mysql-stdout';
1446
        $mysql_stderr = $backup_dir . '/mysql-stderr';
1447
        $binlog_info = $backup_dir . '/xtrabackup_binlog_info';
1448
        $slave_info = $backup_dir . '/xtrabackup_slave_info';
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1449
        } else {
1450
        $suspend_file = get_option(\%config, 'mysqld', 'datadir') . '/xtrabackup_suspended';
22 by kinoyasu
"innobackup --stream=tar" is supported
1451
        $tmp_logfile = $option_tmpdir . '/xtrabackup_logfile';
1452
        $mysql_stdout = $option_tmpdir . '/mysql-stdout';
1453
        $mysql_stderr = $option_tmpdir . '/mysql-stderr';
1454
        if ($option_stream) {
1455
            $backup_config_file = $option_tmpdir . '/backup-my.cnf';
1456
            $binlog_info = $option_tmpdir . '/xtrabackup_binlog_info';
1457
            $slave_info = $option_tmpdir . '/xtrabackup_slave_info';
1458
        } else {
1459
            $backup_config_file = $backup_dir . '/backup-my.cnf';
1460
            $binlog_info = $backup_dir . '/xtrabackup_binlog_info';
1461
            $slave_info = $backup_dir . '/xtrabackup_slave_info';
1462
        }
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1463
        }
1464
        write_backup_config_file($backup_config_file);
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1465
    } elsif ($option_copy_back) {
1466
        #$backup_config_file = $backup_dir . '/backup-my.cnf';
1467
        #read_config_file($backup_config_file, \%backup_config);
1468
    }         
1469
}
1470
1471
1472
#
1473
# write_backup_config_file subroutine creates a backup options file for
1474
# ibbackup program. It writes to the file only those options that
1475
# are required by ibbackup.
1476
#    Parameters:
1477
#       filename  name for the created options file
1478
#
1479
sub write_backup_config_file {
1480
    my $filename = shift;
1481
    my $innodb_data_file_path = 
1482
        get_option(\%config, 'mysqld', 'innodb_data_file_path');
1483
    my $innodb_log_files_in_group =
1484
        get_option(\%config, 'mysqld', 'innodb_log_files_in_group');
1485
    my $innodb_log_file_size =
1486
        get_option(\%config, 'mysqld', 'innodb_log_file_size');
16 by kinoyasu
merge from alpha-0.2 and fix remote backup-my.cnf
1487
    my $root;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1488
42 by kinoyasu
fix bug 357653; remove innobackup-1.5.1.patch
1489
    my @array = split(/;/, $innodb_data_file_path);
1490
    for (my $i = 0; $i <= $#array; $i++) {
1491
        my @tmp = split(/\/+/, $array[$i]);
1492
        $array[$i] = $tmp[-1];
1493
    }
1494
    $innodb_data_file_path = join(";", @array);
1495
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1496
    if (!$option_remote_host) {
16 by kinoyasu
merge from alpha-0.2 and fix remote backup-my.cnf
1497
        $root = $backup_dir;
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1498
        open(FILE, "> $filename") || Die "Failed to open file '$filename': $!";
1499
    } else {
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
1500
        $root = `ssh $option_remote_host 'cd $backup_dir; pwd'`;
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1501
        open(FILE, "| ssh $option_remote_host 'cat > $filename'")
1502
            || Die "Failed to open file '$option_remote_host:$filename': $!";
1503
    }
1504
109.3.1 by Aleksandr Kuzminsky
Fixed Bug #463709: The script outputs its own name
1505
    print FILE "# This MySQL options file was generated by $innobackup_script.\n\n" .
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1506
          "# The MySQL server\n" .
1507
          "[mysqld]\n" .
16 by kinoyasu
merge from alpha-0.2 and fix remote backup-my.cnf
1508
          "datadir=$root\n" .
1509
          "innodb_data_home_dir=$root\n" .
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1510
          "innodb_data_file_path=$innodb_data_file_path\n" .
16 by kinoyasu
merge from alpha-0.2 and fix remote backup-my.cnf
1511
          "innodb_log_group_home_dir=$root\n" .
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1512
          "innodb_log_files_in_group=$innodb_log_files_in_group\n" .
1513
          "innodb_log_file_size=$innodb_log_file_size\n";
1514
    close(FILE);
22 by kinoyasu
"innobackup --stream=tar" is supported
1515
1516
    if ($option_stream) {
109.1.1 by Aleksandr Kuzminsky
Fixed Bug #434486: Using dirname(), basename() instead of manual parsing of filenames
1517
        my $filename_dir = dirname($filename);
1518
        my $filename_name = basename($filename);
22 by kinoyasu
"innobackup --stream=tar" is supported
1519
        if ($option_stream eq 'tar') {
100.1.1 by Aleksandr Kuzminsky
--no-lock option is added
1520
            system("cd $filename_dir; tar chf - $filename_name")
22 by kinoyasu
"innobackup --stream=tar" is supported
1521
                and Die "Failed to stream '$filename_name': $!";
1522
        }
1523
        unlink $filename || Die "Failed to delete '$filename': $!";
1524
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1525
}
1526
1527
1528
#
1529
# check_args subroutine checks command line arguments. If there is a problem,
1530
# this subroutine prints error message and exits.
1531
#
1532
sub check_args {
1533
    my $i;
1534
    my $rcode;
1535
    my $buf;
1536
    my $perl_version;
1537
1538
    # check the version of the perl we are running
1539
    if (!defined $^V) {
1540
        # this perl is prior to 5.6.0 and uses old style version string
1541
        my $required_version = $required_perl_version_old_style;
1542
        if ($] lt $required_version) {
22 by kinoyasu
"innobackup --stream=tar" is supported
1543
            print STDERR "$prefix Warning: " . 
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1544
                "Your perl is too old! Innobackup requires\n";
22 by kinoyasu
"innobackup --stream=tar" is supported
1545
            print STDERR "$prefix Warning: perl $required_version or newer!\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1546
        }
1547
    }
1548
1549
    if (@ARGV == 0) {
1550
        # no command line arguments
240 by Alexey Kopytov
Updates to built-in innobackupex usage docs.
1551
        print STDERR "$prefix You must specify the backup directory.\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1552
        exit(1);
1553
    }
1554
1555
    # read command line options
1556
    $rcode = GetOptions('compress:i' => \$option_compress,
1557
                        'help' => \$option_help,
1558
                        'version' => \$option_version,
1559
                        'throttle=i' => \$option_throttle,
1560
                        'sleep=i' => \$option_sleep,
1561
                        'apply-log' => \$option_apply_log,
181 by root
added --redo-only option to innobackupex
1562
                        'redo-only' => \$option_redo_only,
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1563
                        'copy-back' => \$option_copy_back,
1564
                        'include=s' => \$option_include,
240 by Alexey Kopytov
Updates to built-in innobackupex usage docs.
1565
                        'databases=s' => \$option_databases,
1566
                        'tables-file=s', => \$option_tables_file,
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1567
                        'use-memory=s' => \$option_use_memory,
1568
                        'uncompress' => \$option_uncompress,
61 by kinoyasu
innobackupex can pass --export option
1569
                        'export' => \$option_export,
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1570
                        'password=s' => \$option_mysql_password,
1571
                        'user=s' => \$option_mysql_user,
116.1.1 by Daniel Nichter
Bug 510965: add --host, remove --host=127.0.0.1 from --port.
1572
                        'host=s' => \$option_mysql_host,
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1573
                        'port=s' => \$option_mysql_port,
1574
                        'slave-info' => \$option_slave_info,
1575
                        'socket=s' => \$option_mysql_socket,
1576
                        'no-timestamp' => \$option_no_timestamp,
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
1577
                        'defaults-file=s' => \$option_defaults_file,
14 by kinoyasu
using rsync for incremental backup
1578
                        'incremental' => \$option_incremental,
130 by Vadim Tkachenko
bugfix 546876
1579
                        'incremental-basedir=s' => \$option_incremental_basedir,
219 by Vadim Tkachenko
Added option --incremental-lsn to innobackupex script.
1580
                        'incremental-lsn=s' => \$option_incremental_lsn,
218 by Vadim Tkachenko
Added option --incremental-dir to innobackupex script
1581
                        'incremental-dir=s' => \$option_incremental_dir,
220 by Vadim Tkachenko
Bugfix #680936
1582
                        'extra-lsndir=s' => \$option_extra_lsndir,
14 by kinoyasu
using rsync for incremental backup
1583
                        'remote-host=s' => \$option_remote_host,
22 by kinoyasu
"innobackup --stream=tar" is supported
1584
                        'stream=s' => \$option_stream,
1585
                        'tmpdir=s' => \$option_tmpdir,
100.1.1 by Aleksandr Kuzminsky
--no-lock option is added
1586
                        'no-lock' => \$option_no_lock,
70.1.1 by Aleksandr Kuzminsky
Allow configuration of scp options
1587
                        'ibbackup=s' => \$option_ibbackup_binary,
119.1.1 by Daniel Nichter
Make --stream=tar use tar4ibd by default unless hidden --force-tar is specified.
1588
                        'scpopt=s' => \$option_scp_opt,
195 by Alexey Kopytov
Implementation of parallel data files transfer for xtrabackup.
1589
                        'force-tar', => \$option_force_tar,
211 by Alexey Kopytov
Manual merge from lp:~percona-dev/percona-xtrabackup/safe-slave-backup
1590
                        'parallel=i' => \$option_parallel,
1591
                        'safe-slave-backup' => \$option_safe_slave_backup,
1592
                        'safe-slave-backup-timeout' => $option_safe_slave_backup_timeout,
127.1.6 by Daniel Nichter
Add and implement --safe-slave-backup and --safe-slave-backup-timeout.
1593
    );
1594
                        
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1595
    if (!$rcode) {
1596
        # failed to read options
22 by kinoyasu
"innobackup --stream=tar" is supported
1597
        print STDERR "$prefix Bad command line arguments\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1598
        exit(1);
1599
    }
1600
    if ($option_help) {
1601
        # print help text and exit
1602
        usage();
1603
        exit(0);
1604
    }
1605
    if ($option_version) {
1606
        # print program version and copyright
1607
        print_version();
1608
        exit(0);
1609
    }
1610
1611
    if ($option_compress == 0) {
1612
        # compression level no specified, use default level
1613
        $option_compress = $default_compression_level;
1614
    } 
1615
1616
    if ($option_compress == 999) {
1617
        # compress option not given in the command line
1618
	$option_compress = 0;
1619
    }
1620
1621
    if (@ARGV < 1) {
22 by kinoyasu
"innobackup --stream=tar" is supported
1622
        print STDERR "$prefix Missing command line argument\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1623
        exit(1);
1624
    } elsif (@ARGV > 1) {
22 by kinoyasu
"innobackup --stream=tar" is supported
1625
        print STDERR "$prefix Too many command line arguments\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1626
        exit(1);
1627
    }
1628
22 by kinoyasu
"innobackup --stream=tar" is supported
1629
    if ($option_stream) {
1630
        if ($option_stream eq 'tar') {
119.1.1 by Daniel Nichter
Make --stream=tar use tar4ibd by default unless hidden --force-tar is specified.
1631
           if ( !$option_force_tar ) {
1632
              $option_tar4ibd = 'tar4ibd';
1633
            }
1634
            else {
1635
               print STDERR "Forcing tar instead of tar4ibd\n";
1636
            }
68 by kinoyasu
new mode of innobackupex --stream=tar4ibd; new command tar4ibd based on libtar-1.2.11
1637
        } elsif ($option_stream eq 'tar4ibd') {
1638
            $option_stream = 'tar';
1639
            $option_tar4ibd = 'tar4ibd';
22 by kinoyasu
"innobackup --stream=tar" is supported
1640
        } elsif ($option_stream eq 'cpio') {
1641
            print STDERR "$prefix --stream=cpio is not supported yet\n";
1642
            exit(1);
1643
        } else {
1644
            print STDERR "$prefix Unknown option --stream=$option_stream\n";
1645
            exit(1);
1646
        }
1647
    }
1648
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1649
    # get options file name
1650
    #$config_file = $ARGV[0];
1651
1652
    if (!$option_apply_log && !$option_copy_back) {
1653
        # we are making a backup, get backup root directory
1654
        $backup_root = $ARGV[0];
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
1655
        if ($option_incremental) {
66 by Vadim Tkachenko
Added incremental option to innobackupex-1.5.1 script
1656
            my @dirs = `ls -1 -t $backup_root`;
1657
            my $inc_dir = $dirs[0];
1658
            chomp($inc_dir);
130 by Vadim Tkachenko
bugfix 546876
1659
            if ($option_incremental_basedir) {
1660
                $incremental_basedir = $option_incremental_basedir;
1661
            } else {
1662
                $incremental_basedir = File::Spec->catfile($backup_root, $inc_dir);
1663
            }
1664
66 by Vadim Tkachenko
Added incremental option to innobackupex-1.5.1 script
1665
            #print STDERR "--incremental_basedir=$incremental_basedir\n";
1666
            #print STDERR "incremental backup is not supported for now.\n";
1667
            #exit(1);
14 by kinoyasu
using rsync for incremental backup
1668
        }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1669
    } else {
1670
        # get backup directory
1671
        $backup_dir = File::Spec->rel2abs($ARGV[0]);
1672
    }        
1673
22 by kinoyasu
"innobackup --stream=tar" is supported
1674
    print STDERR "\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1675
1676
    parse_databases_option_value();
171 by Daniel Nichter
Filter files copied according to --tables-file.
1677
    parse_tables_file_option_value($option_tables_file);
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1678
}
1679
1680
1681
#
1682
# make_backup_dir subroutine creates a new backup directory and returns
1683
# its name.
1684
#
1685
sub make_backup_dir {
1686
    my $dir;
1687
    my $innodb_data_file_path = 
1688
        get_option(\%config, 'mysqld', 'innodb_data_file_path');
1689
1690
    # create backup directory
1691
    $dir = $backup_root;
22 by kinoyasu
"innobackup --stream=tar" is supported
1692
    if ($option_stream) {
1693
        return $dir;
1694
    }
1695
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1696
    $dir .= '/' . strftime("%Y-%m-%d_%H-%M-%S", localtime())
1697
       unless $option_no_timestamp;
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
1698
    if (!$option_remote_host) {
1699
        mkdir($dir, 0777) || Die "Failed to create backup directory $dir: $!";
1700
    } else {
1701
        system("ssh $option_remote_host mkdir $dir");
1702
    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1703
1704
    # create subdirectories for ibdata files if needed
42 by kinoyasu
fix bug 357653; remove innobackup-1.5.1.patch
1705
#    foreach my $a (split(/;/, $innodb_data_file_path)) {
1706
#        my $path = (split(/:/,$a))[0];
1707
#        my @relative_path = split(/\/+/, $path);
1708
#        pop @relative_path;
1709
#        if (@relative_path) {
1710
#            # there is a non-trivial path from the backup directory
1711
#            # to the directory of this backup ibdata file, check
1712
#            # that all the directories in the path exist.
1713
#            create_path_if_needed($dir, \@relative_path);
1714
#        }
1715
#    }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1716
1717
    return $dir;
1718
}
1719
1720
1721
#
1722
# create_path_if_needed subroutine checks that all components
1723
# in the given relative path are directories. If the
1724
# directories do not exist, they are created.
1725
#    Parameters:
1726
#       root           a path to the root directory of the relative pathname
1727
#       relative_path  a relative pathname (a reference to an array of 
1728
#                      pathname components) 
1729
#
1730
sub create_path_if_needed {
1731
    my $root = shift;
1732
    my $relative_path = shift;
1733
    my $path;
1734
1735
    $path = $root;
1736
    foreach $a (@{$relative_path}) {
1737
        $path = $path . "/" . $a;
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
1738
        if (!$option_remote_host) {
1739
            if (! -d $path) {
1740
                # this directory does not exist, create it !
1741
                mkdir($path, 0777) || Die "Failed to create backup directory: $!";
1742
            }
1743
        } else {
1744
            if (system("ssh $option_remote_host test -d $path") != 0) {
1745
                system("ssh $option_remote_host mkdir $path");
1746
            }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1747
        }
1748
    }
1749
}
1750
1751
1752
#
1753
# remove_from_array subroutine removes excluded element from the array.
1754
#    Parameters:
1755
#       array_ref   a reference to an array of strings
1756
#       excluded   a string to be excluded from the copy
1757
#  
1758
sub remove_from_array {
1759
    my $array_ref = shift;
1760
    my $excluded = shift;
1761
    my @copy = ();
1762
    my $size = 0;
1763
1764
    foreach my $str (@{$array_ref}) {
1765
        if ($str ne $excluded) {
1766
            $copy[$size] = $str;
1767
            $size = $size + 1;
1768
        }
1769
    }
1770
    @{$array_ref} = @copy;
1771
}
1772
1773
1774
#
1775
# backup_files subroutine copies .frm, .MRG, .MYD and .MYI files to 
1776
# backup directory.
1777
#
1778
sub backup_files {
1779
    my $source_dir = get_option(\%config, 'mysqld', 'datadir');
1780
    my @list;
1781
    my $file;
1782
    my $database;
223.2.1 by Valentine Gostev
Added fix and test for 420181, added test for 597384
1783
    my $wildcard = '*.{frm,MYD,MYI,MRG,TRG,TRN,ARM,ARZ,CSM,CSV,opt,par}';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1784
1785
    opendir(DIR, $source_dir) 
1786
        || Die "Can't open directory '$source_dir': $!\n";
1787
    $now = current_time();
22 by kinoyasu
"innobackup --stream=tar" is supported
1788
    print STDERR "\n$now  $prefix Starting to backup .frm, .MRG, .MYD, .MYI,\n";
223.2.1 by Valentine Gostev
Added fix and test for 420181, added test for 597384
1789
    print STDERR "$prefix .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV and .opt files in\n";
22 by kinoyasu
"innobackup --stream=tar" is supported
1790
    print STDERR "$prefix subdirectories of '$source_dir'\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1791
    # loop through all database directories
1792
    while (defined($database = readdir(DIR))) {
1793
        my $print_each_file = 0;
1794
        my $file_c;
83 by Aleksandr Kuzminsky
Fixed bug394464
1795
        my @scp_files;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1796
        # skip files that are not database directories
1797
        if ($database eq '.' || $database eq '..') { next; }
1798
        next unless -d "$source_dir/$database";
171 by Daniel Nichter
Filter files copied according to --tables-file.
1799
	     next unless check_if_required($database);
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1800
        
22 by kinoyasu
"innobackup --stream=tar" is supported
1801
        if (!$option_remote_host && !$option_stream) {
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1802
            if (! -e "$backup_dir/$database") {
1803
                # create database directory for the backup
1804
                mkdir("$backup_dir/$database", 0777)
1805
                    || Die "Couldn't create directory '$backup_dir/$database': $!";
1806
            }
22 by kinoyasu
"innobackup --stream=tar" is supported
1807
        } elsif ($option_remote_host) {
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
1808
            if (system("ssh $option_remote_host test -e $backup_dir/$database")
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1809
                    != 0) {
17 by kinoyasu
--remote-host uses scp/ssh, remove using rsync
1810
                system("ssh $option_remote_host mkdir $backup_dir/$database");
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1811
            }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1812
        }
1813
1814
        # copy files of this database
108.1.1 by Aleksandr Kuzminsky
Fixed number of issues in innobackupex-1.5.1 on windows platform
1815
	opendir(DBDIR, "$source_dir/$database");
223.2.1 by Valentine Gostev
Added fix and test for 420181, added test for 597384
1816
	@list = grep(/\.(frm)|(MYD)|(MYI)|(MRG)|(TRG)|(TRN)|(ARM)|(ARZ)|(CSM)|(CSV)|(opt)|(par)$/, readdir(DBDIR)); 
108.1.1 by Aleksandr Kuzminsky
Fixed number of issues in innobackupex-1.5.1 on windows platform
1817
	closedir DBDIR;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1818
        $file_c = @list;
1819
        if ($file_c <= $backup_file_print_limit) {
1820
            $print_each_file = 1;
1821
        } else {
22 by kinoyasu
"innobackup --stream=tar" is supported
1822
            print STDERR "$prefix Backing up files " . 
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1823
                "'$source_dir/$database/$wildcard' ($file_c files)\n";
1824
        }
1825
        foreach $file (@list) {
1826
            # copying may take a long time, so we have to prevent
1827
            # mysql connection from timing out
1828
            mysql_keep_alive();
1829
            next unless check_if_required($database, $file);
217 by Vadim Tkachenko
Bugfix #597384
1830
1831
	    if($option_include) {
1832
	      if (!("$database.$file" =~ /$option_include/)) {
1833
	        print STDERR "$database.$file is skipped because it does not match $option_include.\n";
1834
	        next;
1835
	      }
1836
	    }
1837
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1838
               
1839
            if ($print_each_file) {
108.1.1 by Aleksandr Kuzminsky
Fixed number of issues in innobackupex-1.5.1 on windows platform
1840
                print STDERR "$prefix Backing up file '$source_dir/$database/$file'\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1841
            }
22 by kinoyasu
"innobackup --stream=tar" is supported
1842
            if (!$option_remote_host && !$option_stream) {
108.1.4 by Aleksandr Kuzminsky
escape_path() function is added.
1843
                $src_name = escape_path("$source_dir/$database/$file");
1844
                $dst_name = escape_path("$backup_dir/$database");
1845
                system("$CP_CMD \"$src_name\" \"$dst_name\"")
15 by kinoyasu
trial implementation of --remote-host when --incremental (innobackup)
1846
                    and Die "Failed to copy file '$file': $!";
22 by kinoyasu
"innobackup --stream=tar" is supported
1847
            } elsif ($option_remote_host) {
83 by Aleksandr Kuzminsky
Fixed bug394464
1848
                # Queue up files for one single scp per database.
1849
                push(@scp_files, "'$file'");
22 by kinoyasu
"innobackup --stream=tar" is supported
1850
            } elsif($option_stream eq 'tar') {
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
1851
                my $ret = 0;
22 by kinoyasu
"innobackup --stream=tar" is supported
1852
                my $file_name = substr($file, rindex($file, '/') + 1);
86.1.1 by akuzminsky
Fixed bug#417178
1853
                $file_name=~s/([\$\\\" ])/\\$1/g;
69 by kinoyasu
innobackupex: fixed return code handling
1854
                $ret = system("cd $source_dir; tar cf - $database/$file_name") >> 8;
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
1855
                if ($ret == 1) {
1856
                    print STDERR "$prefix If you use GNU tar, this warning can be ignored.\n";
1857
                } elsif ($ret != 0) {
59 by kinoyasu
fix error handling of tar stream again..
1858
                    print STDERR "$prefix tar returned with exit code $ret.\n";
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
1859
                    Die "Failed to stream '$database/$file_name': $!";
1860
                }
14 by kinoyasu
using rsync for incremental backup
1861
            }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1862
        }
131 by Vadim Tkachenko
bugfix 552111
1863
        if ($option_remote_host and @scp_files) {
114.1.1 by Daniel Nichter
Fix bug 510960: innobackupex --remote-host scp doesn't copy MyISAM files
1864
          my $scp_file_list = join(" ", map { "$source_dir/$database/$_" } @scp_files);
83 by Aleksandr Kuzminsky
Fixed bug394464
1865
          system("scp $option_scp_opt $scp_file_list '$option_remote_host:$backup_dir/$database/'")
102 by kinoyasu
change error message of scp .frm files
1866
              and Die "Failed to execute \"scp $option_scp_opt $scp_file_list '$option_remote_host:$backup_dir/$database/'\": $!";
83 by Aleksandr Kuzminsky
Fixed bug394464
1867
        }
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1868
    }
1869
    closedir(DIR);
1870
1871
    $now = current_time();
223.2.1 by Valentine Gostev
Added fix and test for 420181, added test for 597384
1872
    print STDERR "$now  $prefix Finished backing up .frm, .MRG, .MYD, .MYI, .TRG, .TRN, .ARM, .ARZ, .CSV, .CSM and .opt files\n\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1873
}
1874
1875
1876
#
1877
# file_to_array subroutine reads the given text file into an array and
1878
# stores each line as an element of the array. The end-of-line
1879
# character(s) are removed from the lines stored in the array.
1880
#    Parameters:
1881
#       filename   name of a text file
1882
#       lines_ref  a reference to an array
1883
#
1884
sub file_to_array {
1885
    my $filename = shift;
1886
    my $lines_ref = shift;
1887
    
1888
    open(FILE, $filename) || Die "can't open file '$filename': $!";
1889
    @{$lines_ref} = <FILE>;
1890
    close(FILE) || Die "can't close file '$filename': $!";
1891
1892
    foreach my $a (@{$lines_ref}) {
1893
        chomp($a);
1894
    }
1895
}
1896
1897
1898
#
1899
# unescape_string subroutine expands escape sequences found in the string and
1900
# returns the expanded string. It also removes possible single or double quotes
1901
# around the value.
1902
#    Parameters:
1903
#       value   a string
1904
#    Return value:
1905
#       a string with expanded escape sequences
1906
# 
1907
sub unescape_string {
1908
    my $value = shift;
1909
    my $result = '';
1910
    my $offset = 0;
1911
1912
    # remove quotes around the value if they exist
1913
    if (length($value) >= 2) {
1914
        if ((substr($value, 0, 1) eq "'" && substr($value, -1, 1) eq "'")
1915
            || (substr($value, 0, 1) eq '"' && substr($value, -1, 1) eq '"')) {
1916
            $value = substr($value, 1, -1);
1917
        }
1918
    }
1919
    
1920
    # expand escape sequences
1921
    while ($offset < length($value)) {
1922
        my $pos = index($value, "\\", $offset);
1923
        if ($pos < 0) {
1924
            $pos = length($value);
1925
            $result = $result . substr($value, $offset, $pos - $offset);
1926
            $offset = $pos;
1927
        } else {
1928
            my $replacement = substr($value, $pos, 2);
1929
            my $escape_code = substr($value, $pos + 1, 1);
1930
            if (exists $option_value_escapes{$escape_code}) {
1931
                $replacement = $option_value_escapes{$escape_code};
1932
            }
1933
            $result = $result 
1934
                . substr($value, $offset, $pos - $offset)
1935
                . $replacement;
1936
            $offset = $pos + 2;
1937
        }
1938
    }
1939
1940
    return $result;
1941
}
1942
1943
1944
#
1945
# read_config_file subroutine reads MySQL options file and
1946
# returns the options in a hash containing one hash per group.
1947
#    Parameters:
1948
#       filename    name of a MySQL options file
1949
#       groups_ref  a reference to hash variable where the read
1950
#                   options are returned
1951
#
1952
sub read_config_file {
1953
    #my $filename = shift;
1954
    my $groups_ref = shift;
1955
    my @lines ;
1956
    my $i;
1957
    my $group;
1958
    my $group_hash_ref;
1959
1960
    my $cmdline = '';
43 by kinoyasu
fix bug 358266, bug 359341
1961
    my $options = '';
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1962
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
1963
    if ($option_defaults_file) {
108.1.5 by Aleksandr Kuzminsky
Fixed issue in quoting defaults-file when specified
1964
        $options = $options . " --defaults-file=\"$option_defaults_file\" ";
36 by kinoyasu
some small fixes of innobackupex: bug 355214, bug 356776, etc
1965
    }
1966
43 by kinoyasu
fix bug 358266, bug 359341
1967
    $options = $options . "--print-param";
1968
108.1.5 by Aleksandr Kuzminsky
Fixed issue in quoting defaults-file when specified
1969
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1970
    # read file to an array, one line per element
1971
    #file_to_array($filename, \@lines);
1972
    $cmdline = "$option_ibbackup_binary $options";
1973
    @lines = `$cmdline`;
1974
1975
    # classify lines and save option values
1976
    $group = 'default';
1977
    $group_hash_ref = {}; 
1978
    ${$groups_ref}{$group} = $group_hash_ref;
1979
    # this pattern described an option value which may be
1980
    # quoted with single or double quotes. This pattern
1981
    # does not work by its own. It assumes that the first
1982
    # opening parenthesis in this string is the second opening
1983
    # parenthesis in the full pattern. 
108.1.1 by Aleksandr Kuzminsky
Fixed number of issues in innobackupex-1.5.1 on windows platform
1984
    my $value_pattern = q/((["'])([^\\\4]|(\\[^\4]))*\4)|([^\s]+)/;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
1985
    for ($i = 0; $i < @lines; $i++) {
1986
      SWITCH: for ($lines[$i]) {
1987
          # comment
1988
          /^\s*(#|;)/
1989
             && do { last; };
1990
1991
          # group      
1992
          /^\s*\[(.*)\]/ 
1993
                && do { 
1994
                    $group = $1; 
1995
                    if (!exists ${$groups_ref}{$group}) {
1996
                        $group_hash_ref = {}; 
1997
                        ${$groups_ref}{$group} = $group_hash_ref;
1998
                    } else {
1999
                        $group_hash_ref = ${$groups_ref}{$group};
2000
                    }
2001
                    last; 
2002
                };
2003
2004
          # option
2005
          /^\s*([^\s=]+)\s*(#.*)?$/
2006
              && do { 
2007
                  ${$group_hash_ref}{$1} = '';
2008
                  last; 
2009
              };
2010
2011
          # set-variable = option = value
2012
          /^\s*set-variable\s*=\s*([^\s=]+)\s*=\s*($value_pattern)\s*(#.*)?$/
2013
              && do { ${$group_hash_ref}{$1} = unescape_string($2); last; };
2014
2015
          # option = value
2016
          /^\s*([^\s=]+)\s*=\s*($value_pattern)\s*(#.*)?$/
2017
              && do { ${$group_hash_ref}{$1} = unescape_string($2); last; };
2018
2019
          # empty line
2020
          /^\s*$/
2021
              && do { last; };
2022
2023
          # unknown
2024
          print("$prefix: Warning: Ignored unrecognized line ",
2025
                $i + 1,
2026
                " in options : '${lines[$i]}'\n"
2027
                );
2028
      }
2029
   }
2030
}
2031
    
2032
2033
#
2034
# get_option subroutine returns the value of given option in the config
2035
# structure. If option is missing, this subroutine calls exit.
2036
#    Parameters:
2037
#       config_ref   a reference to a config data
2038
#       group        option group name
2039
#       option_name  name of the option
2040
#    Return value:
2041
#       option value as a string
2042
#
2043
sub get_option {
2044
    my $config_ref = shift;
2045
    my $group = shift;
2046
    my $option_name = shift;
2047
    my $group_hash_ref;
2048
2049
    if (!exists $config{$group}) {
2050
        # no group
22 by kinoyasu
"innobackup --stream=tar" is supported
2051
        print STDERR "$prefix fatal error: no '$group' group in MySQL options\n";
95 by kinoyasu
add more exact error message at innobackupex
2052
        print STDERR "$prefix fatal error: OR no 'datadir' option in group '$group' in MySQL options\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
2053
        exit(1);
2054
    }
2055
    
2056
    $group_hash_ref = ${$config_ref}{$group};
2057
    if (!exists ${$group_hash_ref}{$option_name}) {
2058
        # no option
22 by kinoyasu
"innobackup --stream=tar" is supported
2059
        print STDERR "$prefix fatal error: no '$option_name' option in group '$group' in MySQL options\n";
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
2060
        exit(1);
2061
    }
2062
2063
    return ${$group_hash_ref}{$option_name};
2064
}
2065
2066
# check_if_required subroutine returns 1 if the specified database and
2067
# table needs to be backed up.
2068
#    Parameters:
2069
#       $_[0]        name of database to be checked 
2070
#       $_[1]        full path of table file (This argument is optional)
2071
#    Return value:
2072
#       1 if backup should be done and 0 if not
2073
#
2074
sub check_if_required {
171 by Daniel Nichter
Filter files copied according to --tables-file.
2075
   my ( $db, $table_path ) = @_;
2076
   my $db_count  = scalar keys %databases_list;
2077
   my $tbl_count = scalar keys %table_list;
2078
   my $filename;
2079
   my $table;
2080
2081
   if ( $db_count == 0 && $tbl_count == 0 ) {
2082
      # No databases defined with --databases option, include all databases,
2083
      # and no tables defined with --tables-file option, include all tables.
2084
      return 1;
2085
   }
2086
   else {
2087
      if ( $table_path ) {
2088
         # get the last component in the table pathname 
2089
         $filename = (reverse(split(/\//, $table_path)))[0];
2090
         # get name of the table by removing file suffix
2091
         $table = (split(/\./, $filename))[0];
2092
      }
2093
   }
2094
2095
   # Filter for --databases.
2096
   if ( $db_count ) {
2097
      if (defined $databases_list{$db}) {
2098
         if (defined $table_path) {
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
2099
            my $db_hash = $databases_list{$db};
2100
            $db_count = keys %$db_hash;
2101
            if ($db_count > 0 && ! defined $databases_list{$db}->{$table}) {
171 by Daniel Nichter
Filter files copied according to --tables-file.
2102
               # --databases option specified, but table is not included
2103
               return 0;
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
2104
            }
171 by Daniel Nichter
Filter files copied according to --tables-file.
2105
         }
2106
         # include this database and table
2107
         return 1;
2108
      }
2109
      else {
2110
         # --databases option given, but database is not included
2111
         return 0;
2112
      }
2113
   }
2114
2115
   # Filter for --tables-file.
2116
   if ( $tbl_count ) {
2117
      return 0 unless exists $table_list{$db};
2118
      return 0 if $table && !$table_list{$db}->{$table};
2119
   }
2120
2121
   return 1;  # backup the table
7 by Vadim Tkachenko
patche innobackup-1.5.1 added
2122
}
2123
2124
2125
# parse_databases_option_value subroutine parses the value of 
2126
# --databases option. If the option value begins with a slash
2127
# it is considered a pathname and the option value is read
2128
# from the file.
2129
# 
2130
# This subroutine sets the global "databases_list" variable.
2131
#
2132
sub parse_databases_option_value {
2133
    my $item;
2134
2135
    if ($option_databases =~ /^\//) {
2136
        # the value of the --databases option begins with a slash,
2137
        # the option value is pathname of the file containing
2138
        # list of databases
2139
        if (! -f $option_databases) {
2140
            Die "can't find file '$option_databases'";
2141
        }
2142
2143
        # read from file the value of --databases option
2144
        my @lines;
2145
    	file_to_array($option_databases, \@lines);
2146
	$option_databases = join(" ", @lines);
2147
    }
2148
2149
    # mark each database or database.table definition in the
2150
    # global databases_list.
2151
    foreach $item (split(/\s/, $option_databases)) {
2152
        my $db = "";
2153
        my $table = "";
2154
        my %hash;
2155
2156
        if ($item eq "") {
2157
            # ignore empty strings
2158
            next;
2159
        }
2160
2161
        # get database and table names
2162
        if ($item =~ /(\S*)\.(\S*)/) {
2163
            # item is of the form DATABASE.TABLE
2164
            $db = $1;
2165
            $table = $2;
2166
        } else {
2167
            # item is database name, table is undefined
2168
            $db = $item;
2169
        }
2170
2171
        if (! defined $databases_list{$db}) {
2172
            # create empty hash for the database
2173
            $databases_list{$db} = \%hash;
2174
        }
2175
        if ($table ne "") {
2176
            # add mapping table --> 1 to the database hash
2177
            my $h = $databases_list{$db};
2178
            $h->{$table} = 1;
2179
        }
2180
    }
2181
}
108.1.4 by Aleksandr Kuzminsky
escape_path() function is added.
2182
171 by Daniel Nichter
Filter files copied according to --tables-file.
2183
# Parse the --tables-file file to determine which InnoDB tables
2184
# are backedup up.  Only backedup tables have their .frm, etc.
2185
# files copied.
2186
sub parse_tables_file_option_value {
2187
   my ( $filename ) = @_;
2188
2189
   return unless $filename;
2190
2191
   open my $fh, '<', $filename;
2192
   if ( $fh ) {
2193
      while ( my $line = <$fh> ) {
172 by Daniel Nichter
Parse tables file as simple list of databases.tables.
2194
         chomp $line;
2195
         my ( $db, $tbl ) = $line =~ m/\s*([^\.]+)\.([^\.]+)\s*/;
171 by Daniel Nichter
Filter files copied according to --tables-file.
2196
         if ( $db && $tbl ) {
2197
            $table_list{$db}->{$tbl} = 1;
2198
            print STDERR "$prefix $db.$tbl will be registerd to the list\n";
2199
         }
2200
         else {
2201
            warn "$prefix Invalid line in $filename: $line";
2202
         }
2203
      }
2204
   }
2205
   else {
2206
      warn "$prefix Cannot read --tables-file $filename: $OS_ERROR";
2207
   }
2208
2209
   return;
2210
}
2211
108.1.4 by Aleksandr Kuzminsky
escape_path() function is added.
2212
sub escape_path {
2213
  my $str = shift;
2214
  if ($win eq 1) {
2215
    $str =~ s/\//\\/g;
2216
    $str =~ s/\\\\/\\/g;
2217
    }
2218
  else{
2219
    $str =~ s/\/\//\//g;
2220
    }
2221
  return $str;
2222
2223
}
136.1.2 by Aleksandr Kuzminsky
innobackupex checks MySQL version.
2224
2225
sub set_xtrabackup_version {
2226
# Based on MySQL version choose correct binary
178 by root
support for 5.5 in scripts
2227
#  MySQL 5.0.* - xtrabackup_51
2228
#  MySQL 5.1.* - xtrabackup_51
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
2229
#  MySQL 5.1.* with InnoDB plugin - xtrabackup
2230
#  Percona Server >= 11.0 - xtrabackup
178 by root
support for 5.5 in scripts
2231
#  MySQL 5.5.* - xtrabackup_55 
2232
136.1.2 by Aleksandr Kuzminsky
innobackupex checks MySQL version.
2233
my @lines;
2234
my $var_version = '';
2235
my $var_innodb_version = '';
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
2236
my $ibbackup_binary;
136.1.2 by Aleksandr Kuzminsky
innobackupex checks MySQL version.
2237
mysql_open();
2238
mysql_send "SHOW VARIABLES LIKE 'version'\\G";
2239
file_to_array($mysql_stdout, \@lines);
2240
for (@lines) {
2241
	$var_version = $1 if /Value:\s+(\S+)/;
2242
	}
2243
mysql_send "SHOW VARIABLES LIKE 'innodb_version'\\G";
2244
file_to_array($mysql_stdout, \@lines);
2245
for (@lines) {
2246
	$var_innodb_version = $1 if /Value:\s+(\S+)/;
2247
	}
2248
if($var_version =~ m/5\.0\.\d/){
160 by Aleksandr Kuzminsky
Use new patch for MySQL 5.1
2249
	$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup_51');
136.1.2 by Aleksandr Kuzminsky
innobackupex checks MySQL version.
2250
}
2251
if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m//){
160 by Aleksandr Kuzminsky
Use new patch for MySQL 5.1
2252
	$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup_51');
136.1.2 by Aleksandr Kuzminsky
innobackupex checks MySQL version.
2253
}
2254
if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m/1\.0\.\d+$/){
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
2255
	$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
136.1.2 by Aleksandr Kuzminsky
innobackupex checks MySQL version.
2256
}
2257
if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m/1\.0\.\d+-\d/){
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
2258
	$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
136.1.2 by Aleksandr Kuzminsky
innobackupex checks MySQL version.
2259
}
178 by root
support for 5.5 in scripts
2260
if($var_version =~ m/5\.5\.\d/){
2261
	$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup_55');
2262
}
136.1.2 by Aleksandr Kuzminsky
innobackupex checks MySQL version.
2263
mysql_close();
152 by Aleksandr Kuzminsky
1. innobackupex saves the xtrabackup binary name in a file xtrabackup_binary.
2264
return $ibbackup_binary;
136.1.2 by Aleksandr Kuzminsky
innobackupex checks MySQL version.
2265
}
211 by Alexey Kopytov
Manual merge from lp:~percona-dev/percona-xtrabackup/safe-slave-backup
2266
127.1.6 by Daniel Nichter
Add and implement --safe-slave-backup and --safe-slave-backup-timeout.
2267
# Wait until it's safe to backup a slave.  Returns immediately if
2268
# the host isn't a slave.  Currently there's only one check:
2269
# Slave_open_temp_tables has to be zero.  Dies on timeout.
2270
sub wait_for_safe_slave {
2271
   my @lines;
2272
2273
   my $host_is_slave = 0;
2274
   mysql_send 'SHOW SLAVE STATUS\G;';
2275
   file_to_array($mysql_stdout, \@lines);
2276
   foreach my $line ( @lines ) {
2277
      if ( $line =~ m/Read_Master_Log_Pos/ ) {
2278
         $host_is_slave = 1;
2279
         last;
2280
      }
2281
   }
2282
   if ( !$host_is_slave ) {
2283
      print STDERR "$prefix: Not checking slave open temp tables for --safe-slave-backup because host is not a slave\n";
2284
      return;
2285
   }
2286
2287
   mysql_send 'STOP SLAVE SQL_THREAD;';
2288
2289
   my $open_temp_tables = get_slave_open_temp_tables();
2290
   print STDERR "$prefix: Slave open temp tables: $open_temp_tables\n";
2291
2292
   return if $open_temp_tables == 0;
2293
2294
   my $sleep_time = 3;
2295
   my $n_attempts = int($option_safe_slave_backup_timeout / $sleep_time) || 1;
2296
   while ( $n_attempts-- ) {
2297
      print STDERR "$prefix: Starting slave SQL thread, waiting $sleep_time seconds, then checking Slave_open_temp_tables again ($n_attempts attempts remaining)...\n";
2298
      
2299
      mysql_send 'START SLAVE SQL_THREAD;';
2300
      sleep $sleep_time;
2301
      mysql_send 'STOP SLAVE SQL_THREAD;';
2302
2303
      $open_temp_tables = get_slave_open_temp_tables();
2304
      print STDERR "$prefix: Slave open temp tables: $open_temp_tables\n";
2305
      if ( !$open_temp_tables ) {
2306
         print STDERR "$prefix: Slave is safe to backup\n";
2307
         return;
2308
      }
2309
   } 
2310
2311
   Die "Slave_open_temp_tables did not become zero after waiting $option_safe_slave_backup_timeout seconds";
2312
}
2313
2314
sub get_slave_open_temp_tables {
2315
   my @lines;
2316
   mysql_send 'SHOW STATUS LIKE "slave_open_temp_tables"\G;';
2317
   file_to_array($mysql_stdout, \@lines);
2318
   my $last_value;
2319
   for my $i ( 0..$#lines ) {
2320
      $last_value = $i + 1
2321
         if $lines[$i] =~ m/Variable_name: Slave_open_temp_tables/i;
2322
   }
2323
   Die "SHOW STATUS LIKE 'slave_open_temp_tables' did not return anything"
2324
      unless $last_value;
2325
2326
   Die "Failed to get Slave_open_temp_tables from SHOW STATUS"
2327
      unless defined $lines[$last_value];
2328
2329
   my ($n) = $lines[$last_value] =~ m/(\d+)/;
2330
   return $n;
2331
}
240 by Alexey Kopytov
Updates to built-in innobackupex usage docs.
2332
2333
=pod
2334
2335
=head1 NAME
2336
2337
innobackupex - Non-blocking backup tool for InnoDB, XtraDB and HailDB databases
2338
2339
=head1 SYNOPOSIS
2340
2341
innobackupex [--compress[=LEVEL]] [--include=REGEXP] [--user=NAME] 
2342
             [--password=WORD] [--port=PORT] [--socket=SOCKET]
2343
             [--no-timestamp] [--ibbackup-binary=IBBACKUP-BINARY]
2344
             [--slave-info] [--stream=tar] [--force-tar]
2345
             [--scpopt=OPTIONS-FOR-SCP] [--defaults-file=MY.CNF]
2346
             [--databases=LIST] [--remote-host=HOSTNAME] [--no-lock] 
2347
             [--tmpdir=DIRECTORY] [--tables-file=FILE]
2348
             [--incremental] [--incremental-basedir]
2349
             [--incremental-dir] [--incremental-lsn]
2350
             BACKUP-ROOT-DIR
2351
2352
innobackupex --apply-log [--use-memory=MB] [--uncompress]
2353
             [--defaults-file=MY.CNF]
2354
             [--export] [--redo-only] [--ibbackup=IBBACKUP-BINARY]
2355
             BACKUP-DIR
2356
2357
innobackupex --copy-back [--defaults-file=MY.CNF] BACKUP-DIR
2358
2359
=head1 DESCRIPTION
2360
2361
The first command line above makes a hot backup of a MySQL database.
2362
By default it creates a backup directory (named by the current date
2363
and time) in the given backup root directory.  With the --no-timestamp
2364
option it does not create a time-stamped backup directory, but it puts
2365
the backup in the given directory (which must not exist).  This
2366
command makes a complete backup of all MyISAM and InnoDB tables and
2367
indexes in all databases or in all of the databases specified with the
2368
--databases option.  The created backup contains .frm, .MRG, .MYD,
2369
.MYI, .TRG, .TRN, .ARM, .ARZ, .CSM, CSV, .opt, .par, and InnoDB data and log files.
2370
The MY.CNF options file defines the location of the database.  This command
2371
connects to the MySQL server using the mysql client program, and runs
2372
xtrabackup as a child process.
2373
2374
The --apply-log command prepares a backup for starting a MySQL
2375
server on the backup. This command recovers InnoDB data files as specified
2376
in BACKUP-DIR/backup-my.cnf using BACKUP-DIR/xtrabackup_logfile,
2377
and creates new InnoDB log files as specified in BACKUP-DIR/backup-my.cnf.
2378
The BACKUP-DIR should be the path to a backup directory created by
2379
xtrabackup. This command runs xtrabackup as a child process, but it does not 
2380
connect to the database server.
2381
2382
The --copy-back command copies data, index, and log files
2383
from the backup directory back to their original locations.
2384
The MY.CNF options file defines the original location of the database.
2385
The BACKUP-DIR is the path to a backup directory created by xtrabackup.
2386
2387
On success the exit code innobackupex is 0. A non-zero exit code 
2388
indicates an error.
2389
2390
2391
=head1 OPTIONS
2392
2393
=over
2394
2395
=item --apply-log
2396
2397
Prepare a backup in BACKUP-DIR by applying the transaction log file named "xtrabackup_logfile" located in the same directory. Also, create new transaction logs. The InnoDB configuration is read from the file "backup-my.cnf".
2398
2399
=item --copy-back
2400
2401
Copy all the files in a previously made backup from the backup directory to their original locations.
2402
2403
=item --databases=LIST
2404
2405
This option specifies the list of databases that innobackupex should back up.  The option accepts a string argument. The list is of the form "databasename1[.table_name1] databasename2[.table_name2] . . .". If this option is not specified, all databases containing MyISAM and InnoDB tables will be backed up. Please make sure that --databases contains all of the InnoDB databases and tables, so that all of the innodb.frm files are also backed up. In case the list is very long, this can be specified in a file, and the full path of the file can be specified instead of the list. (See option --tables-file.)
2406
2407
=item --defaults-file=[MY.CNF]
2408
2409
This option specifies what file to read the default MySQL options from.  The option accepts a string argument. It is also passed directly to xtrabackup's --defaults-file option. See the xtrabackup documentation for details.
2410
2411
=item --export
2412
2413
This option is passed directly to xtrabackup's --export option. It enables exporting individual tables for import into another server. See the xtrabackup documentation for details.
2414
2415
=item --extra-lsndir=DIRECTORY
2416
2417
This option specifies the directory in which to save an extra copy of the "xtrabackup_checkpoints" file.  The option accepts a string argument. It is passed directly to xtrabackup's --extra-lsndir option. See the xtrabackup documentation for details.
2418
2419
=item --force-tar
2420
2421
This option forces the use of tar when creating a streamed backup, rather than tar4ibd, which is the default.
2422
2423
=item --help
2424
2425
This option displays a help screen and exits.
2426
2427
=item --host=HOST
2428
2429
This option specifies the host to use when connecting to the database server with TCP/IP.  The option accepts a string argument. It is passed to the mysql child process without alteration. See mysql --help for details.
2430
2431
=item --ibbackup-binary=IBBACKUP-BINARY
2432
2433
This option specifies which xtrabackup binary should be used.  The option accepts a string argument. IBBACKUP-BINARY should be the command used to run XtraBackup. The option can be useful if the xtrabackup binary is not in your search path or working directory. If this option is not specified, innobackupex attempts to determine the binary to use automatically. By default, "xtrabackup" is the command used. However, when option --copy-back is specified, "xtrabackup_51" is the command used. And when option --apply-log is specified, the binary is used whose name is in the file "xtrabackup_binary" in the backup directory, if that file exists.
2434
2435
=item --include=REGEXP
2436
2437
This option is a regular expression to be matched against table names in databasename.tablename format. It is passed directly to xtrabackup's --tables option. See the xtrabackup documentation for details.
2438
2439
=item --incremental
2440
2441
This option tells xtrabackup to create an incremental backup, rather than a full one. It is passed to the xtrabackup child process. When this option is specified, either --incremental-lsn or --incremental-basedir can also be given. If neither option is given, option --incremental-basedir is passed to xtrabackup by default, set to the first timestamped backup directory in the backup base directory.
2442
2443
=item --incremental-basedir=DIRECTORY
2444
2445
This option specifies the directory containing the full backup that is the base dataset for the incremental backup.  The option accepts a string argument. It is used with the --incremental option.
2446
2447
=item --incremental-dir=DIRECTORY
2448
2449
This option specifies the directory where the incremental backup will be combined with the full backup to make a new full backup.  The option accepts a string argument. It is used with the --incremental option.
2450
2451
=item --incremental-lsn
2452
2453
This option specifies the log sequence number (LSN) to use for the incremental backup.  The option accepts a string argument. It is used with the --incremental option. It is used instead of specifying --incremental-basedir. For databases created by MySQL and Percona Server 5.0-series versions, specify the LSN as two 32-bit integers in high:low format. For databases created in 5.1 and later, specify the LSN as a single 64-bit integer.
2454
2455
=item --no-lock
2456
2457
Use this option to disable table lock with "FLUSH TABLES WITH READ LOCK". Use it only if ALL your tables are InnoDB and you DO NOT CARE about the binary log position of the backup.
2458
2459
=item --no-timestamp
2460
2461
This option prevents creation of a time-stamped subdirectory of the BACKUP-ROOT-DIR given on the command line. When it is specified, the backup is done in BACKUP-ROOT-DIR instead.
2462
2463
=item --parallel=NUMBER-OF-THREADS
2464
2465
This option specifies the number of threads the xtrabackup child process should use to back up files concurrently.  The option accepts an integer argument. It is passed directly to xtrabackup's --parallel option. See the xtrabackup documentation for details.
2466
2467
2468
=item --password=WORD
2469
2470
This option specifies the password to use when connecting to the database. It accepts a string argument.  It is passed to the mysql child process without alteration. See mysql --help for details.
2471
2472
=item --port=PORT
2473
2474
This option specifies the port to use when connecting to the database server with TCP/IP.  The option accepts a string argument. It is passed to the mysql child process. It is passed to the mysql child process without alteration. See mysql --help for details.
2475
2476
=item --redo-only
2477
2478
This option is passed directly to xtrabackup's --apply-log-only option. This forces xtrabackup to skip the "rollback" phase and do a "redo" only. This is necessary if the backup will have incremental changes applied to it later. See the xtrabackup documentation for details. 
2479
2480
=item --remote-host=HOSTNAME 
2481
2482
This option specifies the remote host on which the backup files will be created, by using an ssh connection.  The option accepts a string argument.
2483
2484
=item --safe-slave-backup
2485
2486
Stop slave SQL thread and wait to start backup until Slave_open_temp_tables in "SHOW STATUS" is zero. If there are no open temporary tables, the backup will take place, otherwise the SQL thread will be started and stopped until there are no open temporary tables. The backup will fail if Slave_open_temp_tables does not become zero after --safe-slave-backup-timeout seconds. The slave SQL thread will be restarted when the backup finishes.
2487
2488
=item --safe-slave-backup-timeout
2489
2490
How many seconds --safe-slave-backup should wait for Slave_open_temp_tables to become zero. (default 300)
2491
2492
=item --scpopt=SCP-OPTIONS
2493
2494
This option specifies the command line options to pass to scp when the option --remost-host is specified.  The option accepts a string argument. If the option is not specified, the default options are "-Cp -c arcfour".
2495
2496
=item --slave-info
2497
2498
This option is useful when backing up a replication slave server. It prints the binary log position and name of the master server. It also writes this information to the "xtrabackup_slave_info" file as a "CHANGE MASTER" command. A new slave for this master can be set up by starting a slave server on this backup and issuing a "CHANGE MASTER" command with the binary log position saved in the "xtrabackup_slave_info" file.
2499
2500
=item --socket=SOCKET
2501
2502
This option specifies the socket to use when connecting to the local database server with a UNIX domain socket.  The option accepts a string argument. It is passed to the mysql child process without alteration. See mysql --help for details.
2503
2504
=item --stream=[tar|. . .]
2505
2506
This option specifies the format in which to do the streamed backup.  The option accepts a string argument. The backup will be done to STDOUT in the specified format. Currently, the only supported format is tar. Uses tar4ibd, which is available in XtraBackup distributions.
2507
2508
=item --tables-file=FILE
2509
2510
This option specifies the file in which there are a list of names of the form database.  The option accepts a string argument.table, one per line. The option is passed directly to xtrabackup's --tables-file option.
2511
2512
=item --throttle=IOS
2513
2514
This option specifies a number of I/O operations (pairs of read+write) per second.  It accepts an integer argument.  It is passed directly to xtrabackup's --throttle option.
2515
2516
=item --tmpdir=DIRECTORY
2517
2518
This option specifies the location where a temporary file will be stored.  The option accepts a string argument. It should be used when --remote-host or --stream is specified. For these options, the transaction log will first be stored to a temporary file, before streaming or copying to a remote host. This option specifies the location where that temporary file will be stored. If the option is not specifed, the default is to use the value of tmpdir read from the server configuration.
2519
2520
=item --use-memory=MB
2521
2522
This option specifies the amount of memory in megabytes for xtrabackup to use for crash recovery while preparing a backup.  The option accepts a string argument. It is used only with the option --apply-log. It is passed directly to xtrabackup's --use-memory option. See the xtrabackup documentation for details.
2523
2524
=item --user=NAME
2525
2526
This option specifies the MySQL username used when connecting to the server, if that's not the current user. The option accepts a string argument.  It is passed to the mysql child process without alteration. See mysql --help for details.
2527
2528
=item --version
2529
2530
This option displays the xtrabackup version and copyright notice and then exits.
2531
2532
=back
2533
2534
=head1 BUGS
2535
2536
Bugs can be reported on Launchpad: https://bugs.launchpad.net/percona-xtrabackup/+filebug
2537
2538
=head1 COPYRIGHT
2539
2540
InnoDB Backup Utility Copyright 2003, 2009 Innobase Oy and Percona, Inc 2009-2011. All Rights Reserved.
2541
2542
This software is published under the GNU GENERAL PUBLIC LICENSE Version 2, June 1991.
2543
2544
=cut