Merge lp:~akopytov/percona-xtrabackup/bug1164945-2.1 into lp:percona-xtrabackup/2.1

Proposed by Alexey Kopytov
Status: Merged
Approved by: Alexey Kopytov
Approved revision: no longer in the source branch.
Merged at revision: 701
Proposed branch: lp:~akopytov/percona-xtrabackup/bug1164945-2.1
Merge into: lp:percona-xtrabackup/2.1
Diff against target: 273 lines (+176/-15)
4 files modified
innobackupex.pl (+65/-15)
test/t/bug1049291.sh (+23/-0)
test/t/bug1164945.sh (+47/-0)
test/t/bug382742.sh (+41/-0)
To merge this branch: bzr merge lp:~akopytov/percona-xtrabackup/bug1164945-2.1
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) Approve
Review via email: mp+195922@code.launchpad.net

Description of the change

    Bug #1164945: move-back/copy-back should allow non-empty directories in
                  some cases

    The patches introduces a new innobackupex option,
    --force-non-empty-directories. When specified, it makes --copy-back or
    --move-back transfer files to non-empty directories. Note that no
    existing files will be overwritten. If --copy-back or --nove-back has to
    copy a file from the backup directory which already exists in the
    destination directory, it will still fail with an error.

http://jenkins.percona.com/view/XtraBackup/job/percona-xtrabackup-2.1-param/500/

To post a comment you must log in.
Revision history for this message
Alexey Kopytov (akopytov) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'innobackupex.pl'
2--- innobackupex.pl 2013-11-15 11:01:25 +0000
3+++ innobackupex.pl 2013-11-20 09:11:18 +0000
4@@ -144,6 +144,8 @@
5
6 my $option_version_check = '1';
7
8+my $option_force_non_empty_dirs = '';
9+
10 my %mysql;
11 my $option_backup = '';
12
13@@ -2090,6 +2092,18 @@
14 }
15
16 #
17+# Check if a given directory exists, or fail with an error otherwise
18+#
19+
20+sub if_directory_exists {
21+ my $empty_dir = shift;
22+ my $is_directory_empty_comment = shift;
23+ if (! -d $empty_dir) {
24+ die "$is_directory_empty_comment directory '$empty_dir' does not exist!";
25+ }
26+}
27+
28+#
29 # if_directory_exists_and_empty accepts two arguments:
30 # variable with directory name and comment.
31 # Sub checks that directory exists and is empty
32@@ -2099,14 +2113,30 @@
33 sub if_directory_exists_and_empty {
34 my $empty_dir = shift;
35 my $is_directory_empty_comment = shift;
36- if (! -d $empty_dir) {
37- die "$is_directory_empty_comment directory '$empty_dir' does not exist!";
38- }
39- opendir (my $dh, $empty_dir) or die "$is_directory_empty_comment directory '$empty_dir': Not a directory";
40- if ( ! scalar( grep { $_ ne "." && $_ ne ".." && $_ ne "my.cnf" && $_ ne "master.info"} readdir($dh)) == 0) {
41- die "$is_directory_empty_comment directory '$empty_dir' is not empty!";
42- }
43- closedir($dh);
44+
45+ if_directory_exists($empty_dir, $is_directory_empty_comment);
46+
47+ if (!$option_force_non_empty_dirs) {
48+ opendir (my $dh, $empty_dir) or
49+ die "$is_directory_empty_comment directory '$empty_dir': Not a directory";
50+ if ( ! scalar( grep { $_ ne "." && $_ ne ".." && $_ ne "my.cnf" &&
51+ $_ ne "master.info"} readdir($dh)) == 0) {
52+ die "$is_directory_empty_comment directory '$empty_dir' is not empty!";
53+ }
54+ closedir($dh);
55+ }
56+}
57+
58+#
59+# Fail with an error if file exists
60+#
61+
62+sub die_if_exists {
63+ my $path = shift;
64+
65+ if (-e $path) {
66+ die "Cannot overwrite file: $path";
67+ }
68 }
69
70 #
71@@ -2358,10 +2388,12 @@
72
73 # check that original data directories exist and they are empty
74 if_directory_exists_and_empty($orig_datadir, "Original data");
75- if_directory_exists_and_empty($orig_ibdata_dir, "Original InnoDB data");
76- if_directory_exists_and_empty($orig_iblog_dir, "Original InnoDB log");
77+ if ($orig_ibdata_dir) {
78+ if_directory_exists($orig_ibdata_dir, "Original InnoDB data");
79+ }
80+ if_directory_exists($orig_iblog_dir, "Original InnoDB log");
81 if ($orig_undo_dir) {
82- if_directory_exists_and_empty($orig_undo_dir,
83+ if_directory_exists($orig_undo_dir,
84 "Original undo directory");
85 }
86
87@@ -2421,7 +2453,17 @@
88 foreach my $c (parse_innodb_data_file_path($orig_innodb_data_file_path)) {
89 # get the relative pathname of a data file
90 $src_name = escape_path("$backup_dir/$c->{filename}");
91- $dst_name = escape_path("$orig_ibdata_dir/$c->{path}");
92+ if ($orig_ibdata_dir) {
93+ $dst_name = escape_path("$orig_ibdata_dir/$c->{path}");
94+ } else {
95+ # If innodb_data_home_dir is empty, but file path(s) in
96+ # innodb_data_file_path are relative, InnoDB treats them as if
97+ # innodb_data_home_dir was the same as datadir.
98+
99+ my $dst_root = ($c->{path} =~ /^\//) ? "" : $orig_datadir;
100+ $dst_name = escape_path("$dst_root/$c->{path}");
101+ }
102+ die_if_exists($dst_name);
103 &$move_or_copy_file($src_name, $dst_name);
104 }
105
106@@ -2435,7 +2477,8 @@
107 while (defined($file = readdir(DIR))) {
108 if ($file =~ /^$ibundo_files$/ && -f "$backup_dir/$file") {
109 $src_name = escape_path("$backup_dir/$file");
110- $dst_name = escape_path("$orig_undo_dir");
111+ $dst_name = escape_path("$orig_undo_dir/$file");
112+ die_if_exists($dst_name);
113 &$move_or_copy_file($src_name, $dst_name);
114 }
115 }
116@@ -2450,7 +2493,8 @@
117 while (defined($file = readdir(DIR))) {
118 if ($file =~ /^$iblog_files$/ && -f "$backup_dir/$file") {
119 $src_name = escape_path("$backup_dir/$file");
120- $dst_name = escape_path("$orig_iblog_dir");
121+ $dst_name = escape_path("$orig_iblog_dir/$file");
122+ die_if_exists($dst_name);
123 &$move_or_copy_file($src_name, $dst_name);
124 }
125 }
126@@ -3695,7 +3739,9 @@
127 'lock-wait-threshold=i' => \$option_lock_wait_threshold,
128 'lock-wait-query-type=s' =>
129 \$option_lock_wait_query_type,
130- 'version-check!' => \$option_version_check
131+ 'version-check!' => \$option_version_check,
132+ 'force-non-empty-directories' =>
133+ \$option_force_non_empty_dirs
134 );
135
136 if (@ARGV == 0) {
137@@ -4950,6 +4996,10 @@
138
139 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.
140
141+==item --force-non-empty-directories
142+
143+This option, when specified, makes --copy-back or --move-back transfer files to non-empty directories. Note that no existing files will be overwritten. If --copy-back or --nove-back has to copy a file from the backup directory which already exists in the destination directory, it will still fail with an error.
144+
145 =item --galera-info
146
147 This options creates the xtrabackup_galera_info file which contains the local node state at the time of the backup. Option should be used when performing the backup of Percona-XtraDB-Cluster.
148
149=== added file 'test/t/bug1049291.sh'
150--- test/t/bug1049291.sh 1970-01-01 00:00:00 +0000
151+++ test/t/bug1049291.sh 2013-11-20 09:11:18 +0000
152@@ -0,0 +1,23 @@
153+########################################################################
154+# Bug #1049291: innobackupex --copy-back fails with an empty
155+# innodb-data-home-dir
156+########################################################################
157+
158+MYSQLD_EXTRA_MY_CNF_OPTS="
159+innodb_data_home_dir=
160+"
161+start_server
162+
163+innobackupex --no-timestamp $topdir/backup
164+
165+stop_server
166+
167+rm -rf $MYSQLD_DATADIR/*
168+
169+innobackupex --apply-log $topdir/backup
170+
171+innobackupex --copy-back $topdir/backup
172+
173+test -f $MYSQLD_DATADIR/ibdata1
174+
175+rm -rf $MYSQLD_DATADIR
176
177=== added file 'test/t/bug1164945.sh'
178--- test/t/bug1164945.sh 1970-01-01 00:00:00 +0000
179+++ test/t/bug1164945.sh 2013-11-20 09:11:18 +0000
180@@ -0,0 +1,47 @@
181+##############################################################################
182+# Bug #1164945: move-back/copy-back should allow non-empty directories in some
183+# cases
184+##############################################################################
185+
186+start_server
187+
188+innobackupex --no-timestamp $topdir/backup
189+
190+stop_server
191+
192+innobackupex --apply-log $topdir/backup
193+
194+cp -a $topdir/backup $topdir/backup_copy
195+
196+function test_force_non_empty_dirs()
197+{
198+ rm -rf $MYSQLD_DATADIR/*
199+
200+ mkdir $MYSQLD_DATADIR/empty_subdir
201+
202+ touch $MYSQLD_DATADIR/non_existing_file
203+
204+ # check that --*-back fails without --force-non-empty-directories
205+ run_cmd_expect_failure $IB_BIN $IB_ARGS $1 $topdir/backup
206+
207+ rm -rf $topdir/backup
208+ cp -a $topdir/backup_copy $topdir/backup
209+
210+ # check that --*-back works with --force-non-empty-directories
211+ innobackupex $1 --force-non-empty-directories $topdir/backup
212+
213+ rm -rf $topdir/backup
214+ cp -a $topdir/backup_copy $topdir/backup
215+
216+ # check that --*-back --force-non-empty-directories does not overwrite files
217+ touch $MYSQLD_DATADIR/ibdata1
218+ run_cmd_expect_failure $IB_BIN $IB_ARGS $1 --force-non-empty-directories \
219+ $topdir/backup
220+
221+ rm -rf $topdir/backup
222+ cp -a $topdir/backup_copy $topdir/backup
223+}
224+
225+test_force_non_empty_dirs --copy-back
226+
227+test_force_non_empty_dirs --move-back
228
229=== added file 'test/t/bug382742.sh'
230--- test/t/bug382742.sh 1970-01-01 00:00:00 +0000
231+++ test/t/bug382742.sh 2013-11-20 09:11:18 +0000
232@@ -0,0 +1,41 @@
233+########################################################################
234+# Bug #382742: Absolute paths in innodb_data_file_path are not supported
235+########################################################################
236+
237+# Use this as an absolute path prefix in innodb_data_file_path
238+innodb_data_home_dir=$TEST_VAR_ROOT/innodb_data_home_dir
239+
240+mkdir $innodb_data_home_dir
241+
242+MYSQLD_EXTRA_MY_CNF_OPTS="
243+innodb_file_per_table=0
244+innodb_data_home_dir=/
245+innodb_data_file_path=$innodb_data_home_dir/ibdata1:3M;$innodb_data_home_dir/ibdata2:10M:autoextend
246+"
247+
248+start_server
249+
250+test -f $innodb_data_home_dir/ibdata1
251+test -f $innodb_data_home_dir/ibdata2
252+
253+$MYSQL $MYSQL_ARGS -e "CREATE TABLE test.t(a INT)"
254+
255+record_db_state test
256+
257+innobackupex --no-timestamp $topdir/backup
258+
259+stop_server
260+
261+rm -rf $MYSQLD_DATADIR/*
262+rm -rf $innodb_data_home_dir/*
263+
264+innobackupex --apply-log $topdir/backup
265+
266+innobackupex --copy-back $topdir/backup
267+
268+test -f $innodb_data_home_dir/ibdata1
269+test -f $innodb_data_home_dir/ibdata2
270+
271+start_server
272+
273+verify_db_state test

Subscribers

People subscribed via source and target branches

to all changes: