Merge lp:~sergei.glushchenko/percona-xtrabackup/BT-26901-2.1 into lp:percona-xtrabackup/2.0

Proposed by Sergei Glushchenko on 2012-10-18
Status: Superseded
Proposed branch: lp:~sergei.glushchenko/percona-xtrabackup/BT-26901-2.1
Merge into: lp:percona-xtrabackup/2.0
Diff against target: 7928 lines (+3748/-2732) (has conflicts)
36 files modified
VERSION (+1/-1)
doc/source/conf.py (+3/-3)
doc/source/innobackupex/how_innobackupex_works.rst (+0/-4)
doc/source/innobackupex/innobackupex_option_reference.rst (+2/-6)
doc/source/innobackupex/innobackupex_script.rst (+0/-1)
doc/source/innobackupex/remote_backups_ibk.rst.THIS (+1/-5)
doc/xtrabackup.1 (+0/-15)
innobackupex (+54/-207)
src/Makefile (+14/-5)
src/common.h (+27/-7)
src/datasink.c (+113/-0)
src/datasink.h (+46/-8)
src/ds_compress.c (+31/-70)
src/ds_compress.h (+2/-5)
src/ds_local.c (+0/-3)
src/ds_local.h (+2/-2)
src/ds_stream.c (+5/-2)
src/ds_stream.h (+2/-2)
src/ds_tmpfile.c (+243/-0)
src/ds_tmpfile.h (+28/-0)
src/fil_cur.c (+270/-0)
src/fil_cur.h (+96/-0)
src/innodb_int.c (+983/-0)
src/innodb_int.h (+695/-0)
src/quicklz/quicklz.h (+1/-0)
src/write_filt.c (+321/-0)
src/write_filt.h (+65/-0)
src/xbstream.c (+15/-19)
src/xtrabackup.c (+461/-2365)
src/xtrabackup.h (+50/-0)
test/disabled/compact.sh (+35/-0)
test/disabled/compact_compressed.sh (+53/-0)
test/inc/common.sh (+19/-0)
test/run.sh (+1/-0)
test/t/bug1066843.sh (+107/-0)
test/t/bug766033.sh (+2/-2)
Text conflict in innobackupex
To merge this branch: bzr merge lp:~sergei.glushchenko/percona-xtrabackup/BT-26901-2.1
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) 2012-10-18 Needs Fixing on 2012-10-18
Review via email: mp+130328@code.launchpad.net

This proposal has been superseded by a proposal from 2012-10-18.

Description of the change

To post a comment you must log in.

#26901

There is a conflict in innobackupex.

(Just a heads-up, not a full review)

review: Needs Fixing

Ah, wrong target branch.

442. By Sergei Glushchenko on 2012-11-15

Merge fix for bugs #1066843, #1068470 from 2.0 series

Unmerged revisions

442. By Sergei Glushchenko on 2012-11-15

Merge fix for bugs #1066843, #1068470 from 2.0 series

441. By Alexey Kopytov on 2012-10-16

Manual merge from 2.0 (conflict in innobackupex).

440. By Hrvoje Matijakovic on 2012-10-01

* 2.0 trunk merge

439. By Hrvoje Matijakovic on 2012-09-21

Merged lp:~hrvojem/percona-xtrabackup/rn-2.0.3-2.1

438. By Stewart Smith on 2012-09-21

merge path to libgalera_smm.so fix from 2.0

437. By Stewart Smith on 2012-09-21

empty (null) merge from 2.0

436. By Stewart Smith on 2012-09-20

merge fixes for bug 1049174, bug 1044398, bug 1043762

435. By Hrvoje Matijakovic on 2012-09-19

Merged lp:~hrvojem/percona-xtrabackup/bug1052847-2.1

434. By Hrvoje Matijakovic on 2012-09-19

Merged lp:~hrvojem/percona-xtrabackup/bug1008826

433. By Hrvoje Matijakovic on 2012-09-19

Merged lp:~hrvojem/percona-xtrabackup/bug1048536-2.1

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'VERSION'
2--- VERSION 2012-08-06 01:11:14 +0000
3+++ VERSION 2012-10-18 11:58:23 +0000
4@@ -1,1 +1,1 @@
5-XTRABACKUP_VERSION=2.0.3
6+XTRABACKUP_VERSION=2.1.0
7
8=== modified file 'doc/source/conf.py'
9--- doc/source/conf.py 2012-09-21 12:32:30 +0000
10+++ doc/source/conf.py 2012-10-18 11:58:23 +0000
11@@ -51,9 +51,9 @@
12 # built documents.
13 #
14 # The short X.Y version.
15-version = '2.0.3'
16+version = '2.1'
17 # The full version, including alpha/beta/rc tags.
18-release = '2.0.3'
19+release = '2.1'
20
21 # The language for content autogenerated by Sphinx. Refer to documentation
22 # for a list of supported languages.
23@@ -222,7 +222,7 @@
24 # Grouping the document tree into LaTeX files. List of tuples
25 # (source start file, target name, title, author, documentclass [howto/manual]).
26 latex_documents = [
27- ('index', 'PerconaXtraBackup.tex', u'Percona XtraBackup Documentation',
28+ ('index', 'PerconaXtraBackup-2.1.tex', u'Percona XtraBackup Documentation',
29 u'Percona Inc', 'manual'),
30 ]
31
32
33=== modified file 'doc/source/innobackupex/how_innobackupex_works.rst'
34--- doc/source/innobackupex/how_innobackupex_works.rst 2012-09-06 05:15:27 +0000
35+++ doc/source/innobackupex/how_innobackupex_works.rst 2012-10-18 11:58:23 +0000
36@@ -53,10 +53,6 @@
37 :file:`mysql-stdout`
38 containing the ``STDOUT`` of the server.
39
40-If the :option:`--remote-host` was set, |innobackupex| will test the connection to the host via :command:`ssh` and create the backup directories. Then the same process will be applied but the log will be written to a temporary file and will be copied via :command:`scp` with the options set by :option:`--scpopt` (``-Cp -c arcfour`` by default).
41-
42-After each copy the files will be deleted. The same rationale is for the :option:`--stream` mode.
43-
44 Finally, the binary log position will be printed to ``STDERR`` and |innobackupex| will exit returning 0 if all went OK.
45
46 Note that the ``STDERR`` of |innobackupex| is not written in any file. You will have to redirect it to a file, e.g., ``innobackupex OPTIONS 2> backupout.log``.
47
48=== modified file 'doc/source/innobackupex/innobackupex_option_reference.rst'
49--- doc/source/innobackupex/innobackupex_option_reference.rst 2012-09-21 12:32:30 +0000
50+++ doc/source/innobackupex/innobackupex_option_reference.rst 2012-10-18 11:58:23 +0000
51@@ -127,17 +127,13 @@
52
53 This option accepts a string argument that specifies the directory in which to save an extra copy of the :file:`xtrabackup_checkpoints` file. It is passed directly to |xtrabackup|'s :option:`--extra-lsndir` option. See the :program:`xtrabackup` documentation for details.
54
55-.. option:: --remote-host=HOSTNAME
56-
57- This option accepts a string argument that specifies the remote host on which the backup files will be created, by using an ssh connection. This option is DEPRECATED and will be removed in Percona XtraBackup 2.1. In Percona XtraBackup 2.0 and later, you should use streaming backups instead.
58-
59 .. option:: --stream=STREAMNAME
60
61 This option accepts a string argument that specifies the format in which to do the streamed backup. The backup will be done to ``STDOUT`` in the specified format. Currently, supported formats are `tar` and `xbstream`. Uses :doc:`xbstream <../xbstream/xbstream>`, which is available in *XtraBackup* distributions. If you specify a path after this option, it will be interpreted as the value of :option:`tmpdir`.
62
63 .. option:: --tmpdir=DIRECTORY
64
65- This option accepts a string argument that specifies the location where a temporary file will be stored. It should be used when :option:`--remote-host` or :option:`--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.
66+ This option accepts a string argument that specifies the location where a temporary file will be stored. It should be used when :option:`--stream` is specified. For these options, the transaction log will first be stored to a temporary file, before streaming. 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.
67
68 .. option:: --scpopt = '-Cp -c arcfour'
69
70@@ -161,4 +157,4 @@
71
72 .. option:: --rsync
73
74- Use the :program:`rsync` utility to optimize local file transfers. When this option is specified, :program:`innobackupex` uses :program:`rsync` to copy all non-InnoDB files instead of spawning a separate :program:`cp` for each file, which can be much faster for servers with a large number of databases or tables. This option cannot be used together with :option:`--remote-host` or :option:`--stream`.
75+ Use the :program:`rsync` utility to optimize local file transfers. When this option is specified, :program:`innobackupex` uses :program:`rsync` to copy all non-InnoDB files instead of spawning a separate :program:`cp` for each file, which can be much faster for servers with a large number of databases or tables. This option cannot be used together with :option:`--stream`.
76
77=== modified file 'doc/source/innobackupex/innobackupex_script.rst'
78--- doc/source/innobackupex/innobackupex_script.rst 2011-07-28 05:29:04 +0000
79+++ doc/source/innobackupex/innobackupex_script.rst 2012-10-18 11:58:23 +0000
80@@ -46,7 +46,6 @@
81 replication_ibk
82 parallel_copy_ibk
83 throttling_ibk
84- remote_backups_ibk
85 importing_exporting_tables_ibk
86 pit_recovery_ibk
87
88
89=== renamed file 'doc/source/innobackupex/remote_backups_ibk.rst' => 'doc/source/innobackupex/remote_backups_ibk.rst.THIS'
90--- doc/source/innobackupex/remote_backups_ibk.rst 2012-09-19 13:00:42 +0000
91+++ doc/source/innobackupex/remote_backups_ibk.rst.THIS 2012-10-18 11:58:23 +0000
92@@ -13,10 +13,6 @@
93 Then all the log files will be written to a temporary file (you can choose where to store this file with the :option:`--tmpdir` option) and will be copied via :command:`scp`. The options for :command:`scp` can be specified with :option:`--options-scp` (``-Cp -c arcfour`` by default), for example::
94
95 $ innobackupex --remote-host=REMOTEUSER@REMOTEHOST /path/IN/REMOTE/HOST/to/backup/ \
96- --tmpdir=/tmp --scpopt="-Cp -c arcfour"
97-
98-.. note::
99-
100- `SSH public key authentication <http://www.petefreitag.com/item/532.cfm>`_ should be set up to avoid the login prompt when doing the backup to the remote host.
101+ --tmpdir=/tmp --options-scp="-Cp -c arcfour"
102
103
104
105=== modified file 'doc/xtrabackup.1'
106--- doc/xtrabackup.1 2011-01-10 12:01:38 +0000
107+++ doc/xtrabackup.1 2012-10-18 11:58:23 +0000
108@@ -1392,21 +1392,6 @@
109 .B "xtrabackup"
110 and your script are working on the same dataset.
111
112-.SS " Log Streaming "
113-
114-
115-You can instruct
116-.B "xtrabackup"
117-to omit copying data files, and simply stream the log file to its standard output instead with
118-.B "--log-stream"
119-. This automatically adds the
120-.B "--suspend-at-end"
121-option. Your script can then perform tasks such as streaming remote backups by piping the log files into an SSH connection and copying the data files to another server with a tool such as
122-.B "rsync"
123-or
124-.B "tar4ibd"
125-.
126-
127 .SH " XtraBackup Exit Codes "
128
129
130
131=== modified file 'innobackupex'
132--- innobackupex 2012-10-16 15:05:23 +0000
133+++ innobackupex 2012-10-18 11:58:23 +0000
134@@ -101,7 +101,6 @@
135 my $option_incremental_dir = '';
136 my $option_incremental_lsn = '';
137 my $option_extra_lsndir = '';
138-my $option_remote_host = '';
139 my $option_rsync = '';
140 my $option_stream = '';
141 my $stream_cmd = '';
142@@ -116,6 +115,8 @@
143 my $option_safe_slave_backup = '';
144 my $option_safe_slave_backup_timeout = 300;
145
146+my $option_compact = '';
147+
148 # name of the my.cnf configuration file
149 #my $config_file = '';
150
151@@ -290,11 +291,7 @@
152 } else {
153 # make a backup of InnoDB and MyISAM tables, indexes and .frm files.
154 $ibbackup_exit_code = backup();
155- if ($option_remote_host) {
156- open(XTRABACKUP_BINARY,
157- "| ssh $option_ssh_opt $option_remote_host 'cat > $backup_dir/$xtrabackup_binary_file'")
158- || die "Failed to open file '$option_remote_host:$backup_dir/$xtrabackup_binary_file': $!";
159- } elsif ($option_stream) {
160+ if ($option_stream) {
161 open XTRABACKUP_BINARY, "> $option_tmpdir/$xtrabackup_binary_file"
162 || die "Cannot open file $option_tmpdir/$xtrabackup_binary_file: $!\n";
163 } else {
164@@ -396,9 +393,7 @@
165 start_ibbackup();
166
167 # wait for ibbackup to suspend itself
168- if (!$option_remote_host) {
169- wait_for_ibbackup_suspend();
170- }
171+ wait_for_ibbackup_suspend();
172
173 # connect to database
174 mysql_open();
175@@ -441,11 +436,7 @@
176
177 # copy ib_lru_dump
178 if (-e "$orig_datadir/ib_lru_dump") {
179- if ($option_remote_host) {
180- print STDERR "$prefix Backing up file 'ib_lru_dump'\n";
181- system("scp $option_scp_opt '$orig_datadir/ib_lru_dump' '$option_remote_host:$backup_dir/ib_lru_dump'")
182- and Die "Failed to scp file 'ib_lru_dump': $!";
183- } elsif ($option_stream) {
184+ if ($option_stream) {
185 print STDERR "$prefix Backing up as tar stream 'ib_lru_dump'\n";
186 system("cd $orig_datadir; $stream_cmd ib_lru_dump")
187 and Die "Failed to stream 'ib_lru_dump': $!";
188@@ -457,16 +448,6 @@
189 }
190 }
191
192- if ($option_remote_host) {
193- system("scp $option_scp_opt '$tmp_logfile' '$option_remote_host:$backup_dir/xtrabackup_logfile'")
194- and Die "Failed to scp file '$option_remote_host:$backup_dir/xtrabackup_logfile': $!";
195- unlink $tmp_logfile || Die "Failed to delete '$tmp_logfile': $!";
196-
197- system("scp $option_scp_opt '$option_tmpdir/xtrabackup_checkpoints' '$option_remote_host:$backup_dir/xtrabackup_checkpoints'")
198- and Die "Failed to scp file '$option_remote_host:$backup_dir/xtrabackup_checkpoints': $!";
199- unlink "$option_tmpdir/xtrabackup_checkpoints" || Die "Failed to delete '$option_tmpdir/xtrabackup_checkpoints': $!";
200- }
201-
202 print STDERR "\n$prefix Backup created in directory '$backup_dir'\n";
203 if ($mysql_binlog_position) {
204 print STDERR "$prefix MySQL binlog position: $mysql_binlog_position\n";
205@@ -719,6 +700,14 @@
206 my $file;
207 my $backup_innodb_data_file_path;
208
209+ if (has_option(\%config, $option_defaults_group, 'innodb_doublewrite_file')) {
210+ my $doublewrite_file =
211+ (split(/\/+/,
212+ get_option(\%config, $option_defaults_group,
213+ 'innodb_doublewrite_file')))[-1];
214+ $excluded_files = $excluded_files . '|' . $doublewrite_file;
215+ }
216+
217 # check whether files should be copied or moved to dest directory
218 my $move_or_copy_file = $move_flag ? \&move_file : \&copy_file;
219 my $move_or_copy_dir = $move_flag ?
220@@ -955,14 +944,11 @@
221
222 $options = $options . "--backup --suspend-at-end";
223
224- if (!$option_remote_host && !$option_stream) {
225- $options = $options . " --target-dir=$backup_dir";
226- } else {
227+ if ($option_stream) {
228 #(datadir) for 'xtrabackup_suspended' and 'xtrabackup_checkpoints'
229 $options = $options . " --target-dir=" . $option_tmpdir;
230- if ($option_remote_host) {
231- $options = $options . " --log-stream";
232- }
233+ } else {
234+ $options = $options . " --target-dir=$backup_dir";
235 }
236
237 # prepare command line for running ibbackup
238@@ -1003,6 +989,10 @@
239 if ($option_stream) {
240 $options = $options . " --stream=$option_stream";
241 }
242+ if ($option_compact) {
243+ $options = $options. " --compact";
244+ }
245+
246 $cmdline = "$option_ibbackup_binary $options";
247
248 # run ibbackup as a child process
249@@ -1012,97 +1002,7 @@
250 if ($pid) {
251 # parent process
252 $ibbackup_pid = $pid;
253-
254- if($option_remote_host) {
255- #direct copy to remote
256- my $orig_datadir = get_option(\%config, $option_defaults_group, 'datadir');
257- my $orig_ibdata_dir =
258- get_option(\%config, $option_defaults_group, 'innodb_data_home_dir');
259- my $orig_innodb_data_file_path =
260- get_option(\%config, $option_defaults_group, 'innodb_data_file_path');
261- my $innodb_flush_method =
262- get_option(\%config, $option_defaults_group, 'innodb_flush_method');
263- my $innodb_use_odirect;
264- $innodb_use_odirect = 1 if $innodb_flush_method =~ m/^(ALL_)?O_DIRECT$/i;
265-
266- my $subdir;
267- my @list;
268-
269- if (system("ssh $option_ssh_opt $option_remote_host test -e $backup_dir/ib_logfile0")
270- == 0) {
271- print STDERR "$prefix Remove $option_remote_host:$backup_dir/ib_logfile*\n";
272- system("ssh $option_ssh_opt $option_remote_host rm $backup_dir/ib_logfile\*")
273- and Die "Failed to rm file '$backup_dir/ib_logfile*': $!";
274- }
275-
276- wait_for_ibbackup_suspend();
277-
278- #InnoDB data files from original InnoDB data directory
279- print STDERR "\n$prefix Starting to backup InnoDB tables and indexes\n";
280- print STDERR "$prefix to '$backup_dir'\n";
281- print STDERR "$prefix from original InnoDB data directory '$orig_ibdata_dir'\n";
282- foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
283- my $path = (split(/:/,$a))[0];
284- $path=~s/([\$\\\" ])/\\$1/g;
285- print STDERR "$prefix Backing up file '$orig_ibdata_dir/$path'\n";
286- system("scp $option_scp_opt '$orig_ibdata_dir/$path' '$option_remote_host:$backup_dir/$path'")
287- and Die "Failed to scp file '$path': $!";
288- }
289-
290- #copy *.ibd files
291- opendir(DIR, $orig_datadir)
292- || Die "Can't open directory '$orig_datadir': $!\n";
293- while (defined($subdir = readdir(DIR))) {
294- my $print_each_file = 0;
295- my $file_c;
296- my $file;
297- if ($subdir eq '.' || $subdir eq '..') { next; }
298- next unless -d "$orig_datadir/$subdir";
299- next unless check_if_required($subdir);
300-
301- @list = glob("$orig_datadir/$subdir/" . '*.ibd');
302-
303- $file_c = @list;
304- if ($file_c <= $backup_file_print_limit) {
305- $print_each_file = 1;
306- } else {
307- print STDERR "$prefix Backing up files " .
308- "'$orig_datadir/$subdir/*.ibd' ($file_c files)\n";
309- }
310- foreach $file (@list) {
311- next unless check_if_required($subdir, $file);
312- if($option_include) {
313- my $table_name;
314-
315- $table_name = substr($file, rindex($file, '/'));
316- $table_name = substr($table_name, 1, rindex($table_name, '.') - 1);
317- $table_name = $subdir . "." . $table_name;
318-
319- if (!($table_name =~ /$option_include/)) {
320- print STDERR "'$file' is skipped.\n";
321- next;
322- }
323- }
324-
325- if ($print_each_file) {
326- print STDERR "$prefix Backing up file '$file'\n";
327- }
328- if (system("ssh $option_ssh_opt $option_remote_host test -e $backup_dir/$subdir")
329- != 0) {
330- system("ssh $option_ssh_opt $option_remote_host mkdir $backup_dir/$subdir");
331- }
332- system("scp $option_scp_opt '$file' '$option_remote_host:$backup_dir/$subdir/'")
333- and Die "Failed to scp file '$file': $!";
334- }
335- }
336- closedir(DIR);
337- }
338 } else {
339- if($option_remote_host) {
340- open(STDOUT, "> $tmp_logfile")
341- || Die "Failed to open file '$tmp_logfile': $!"
342- }
343-
344 # child process
345 exec($cmdline) || Die "Failed to exec ibbackup: $!";
346 }
347@@ -1299,13 +1199,7 @@
348 }
349
350 # write binlog info file
351- if (!$option_remote_host) {
352- open(FILE, ">$binlog_info") ||
353- Die "Failed to open file '$binlog_info': $!";
354- } else {
355- open(FILE, "| ssh $option_ssh_opt $option_remote_host 'cat > $binlog_info'") ||
356- Die "Failed to open file '$option_remote_host:$binlog_info': $!";
357- }
358+ open(FILE, ">$binlog_info") || Die "Failed to open file '$binlog_info': $!";
359 print FILE "$filename\t$position\t\t\n";
360 close(FILE);
361
362@@ -1389,13 +1283,7 @@
363 }
364
365 # print slave status to a file
366- if (!$option_remote_host) {
367- open(FILE, ">$slave_info") ||
368- Die "Failed to open file '$slave_info': $!";
369- } else {
370- open(FILE, "| ssh $option_ssh_opt $option_remote_host 'cat > $slave_info'") ||
371- Die "Failed to open file '$option_remote_host:$slave_info': $!";
372- }
373+ open(FILE, ">$slave_info") || Die "Failed to open file '$slave_info': $!";
374 print FILE "CHANGE MASTER TO MASTER_LOG_FILE='$filename', MASTER_LOG_POS=$position\n";
375 close(FILE);
376
377@@ -1669,32 +1557,20 @@
378
379 if (!$option_apply_log && !$option_copy_back && !$option_move_back) {
380 # we are making a backup, create a new backup directory
381- if (!$option_remote_host) {
382- $backup_dir = File::Spec->rel2abs(make_backup_dir());
383- } else {
384- $backup_dir = make_backup_dir();
385- }
386+ $backup_dir = File::Spec->rel2abs(make_backup_dir());
387 print STDERR "$prefix Created backup directory $backup_dir\n";
388- if (!$option_remote_host && !$option_stream) {
389- $backup_config_file = $backup_dir . '/backup-my.cnf';
390- $suspend_file = $backup_dir . '/xtrabackup_suspended';
391- $binlog_info = $backup_dir . '/xtrabackup_binlog_info';
392- $galera_info = $backup_dir . '/xtrabackup_galera_info';
393- $slave_info = $backup_dir . '/xtrabackup_slave_info';
394- } else {
395- $suspend_file = $option_tmpdir . '/xtrabackup_suspended';
396- $tmp_logfile = $option_tmpdir . '/xtrabackup_logfile';
397- if ($option_stream) {
398- $backup_config_file = $option_tmpdir . '/backup-my.cnf';
399- $binlog_info = $option_tmpdir . '/xtrabackup_binlog_info';
400- $galera_info = $option_tmpdir . '/xtrabackup_galera_info';
401- $slave_info = $option_tmpdir . '/xtrabackup_slave_info';
402- } else {
403+ if (!$option_stream) {
404 $backup_config_file = $backup_dir . '/backup-my.cnf';
405+ $suspend_file = $backup_dir . '/xtrabackup_suspended';
406 $binlog_info = $backup_dir . '/xtrabackup_binlog_info';
407 $galera_info = $backup_dir . '/xtrabackup_galera_info';
408 $slave_info = $backup_dir . '/xtrabackup_slave_info';
409- }
410+ } else {
411+ $suspend_file = $option_tmpdir . '/xtrabackup_suspended';
412+ $tmp_logfile = $option_tmpdir . '/xtrabackup_logfile';
413+ $backup_config_file = $option_tmpdir . '/backup-my.cnf';
414+ $binlog_info = $option_tmpdir . '/xtrabackup_binlog_info';
415+ $slave_info = $option_tmpdir . '/xtrabackup_slave_info';
416 }
417 write_backup_config_file($backup_config_file);
418 } elsif ($option_copy_back || $option_move_back) {
419@@ -1714,12 +1590,7 @@
420 sub write_backup_config_file {
421 my $filename = shift;
422
423- if (!$option_remote_host) {
424- open(FILE, "> $filename") || Die "Failed to open file '$filename': $!";
425- } else {
426- open(FILE, "| ssh $option_ssh_opt $option_remote_host 'cat > $filename'")
427- || Die "Failed to open file '$option_remote_host:$filename': $!";
428- }
429+ open(FILE, "> $filename") || Die "Failed to open file '$filename': $!";
430
431 my @option_names = (
432 "innodb_data_file_path",
433@@ -1800,7 +1671,7 @@
434 'use-memory=s' => \$option_use_memory,
435 'uncompress' => \$option_uncompress,
436 'export' => \$option_export,
437- 'password=s' => \$option_mysql_password,
438+ 'password:s' => \$option_mysql_password,
439 'user=s' => \$option_mysql_user,
440 'host=s' => \$option_mysql_host,
441 'port=s' => \$option_mysql_port,
442@@ -1815,7 +1686,6 @@
443 'incremental-lsn=s' => \$option_incremental_lsn,
444 'incremental-dir=s' => \$option_incremental_dir,
445 'extra-lsndir=s' => \$option_extra_lsndir,
446- 'remote-host=s' => \$option_remote_host,
447 'stream=s' => \$option_stream,
448 'rsync' => \$option_rsync,
449 'tmpdir=s' => \$option_tmpdir,
450@@ -1825,7 +1695,12 @@
451 'sshopt=s' => \$option_ssh_opt,
452 'parallel=i' => \$option_parallel,
453 'safe-slave-backup' => \$option_safe_slave_backup,
454+<<<<<<< TREE
455 'safe-slave-backup-timeout=i' => \$option_safe_slave_backup_timeout,
456+=======
457+ 'safe-slave-backup-timeout' => $option_safe_slave_backup_timeout,
458+ 'compact' => \$option_compact
459+>>>>>>> MERGE-SOURCE
460 );
461
462 if (!$rcode) {
463@@ -1901,16 +1776,11 @@
464 }
465 }
466
467- if ($option_rsync && ($option_remote_host || $option_stream)) {
468- print STDERR "--rsync doesn't work with --remote-host or --stream\n";
469+ if ($option_rsync && $option_stream) {
470+ print STDERR "--rsync doesn't work with --stream\n";
471 exit(1);
472 }
473
474- if ($option_remote_host) {
475- print STDERR "\nWARNING: --remote-host is DEPRECATED and will be ",
476- "removed in Percona XtraBackup 2.1 in favor of streaming backups.\n";
477- }
478-
479 print STDERR "\n";
480
481 parse_databases_option_value();
482@@ -1935,11 +1805,7 @@
483
484 $dir .= '/' . strftime("%Y-%m-%d_%H-%M-%S", localtime())
485 unless $option_no_timestamp;
486- if (!$option_remote_host) {
487- mkdir($dir, 0777) || Die "Failed to create backup directory $dir: $!";
488- } else {
489- system("ssh $option_ssh_opt $option_remote_host mkdir $dir");
490- }
491+ mkdir($dir, 0777) || Die "Failed to create backup directory $dir: $!";
492
493 # create subdirectories for ibdata files if needed
494 # foreach my $a (split(/;/, $innodb_data_file_path)) {
495@@ -1975,15 +1841,9 @@
496 $path = $root;
497 foreach $a (@{$relative_path}) {
498 $path = $path . "/" . $a;
499- if (!$option_remote_host) {
500- if (! -d $path) {
501- # this directory does not exist, create it !
502- mkdir($path, 0777) || Die "Failed to create backup directory: $!";
503- }
504- } else {
505- if (system("ssh $option_ssh_opt $option_remote_host test -d $path") != 0) {
506- system("ssh $option_ssh_opt $option_remote_host mkdir $path");
507- }
508+ if (! -d $path) {
509+ # this directory does not exist, create it !
510+ mkdir($path, 0777) || Die "Failed to create backup directory: $!";
511 }
512 }
513 }
514@@ -2065,17 +1925,12 @@
515 next unless -d "$source_dir/$database";
516 next unless check_if_required($database);
517
518- if (!$option_remote_host && !$option_stream) {
519+ if (!$option_stream) {
520 if (! -e "$backup_dir/$database") {
521 # create database directory for the backup
522 mkdir("$backup_dir/$database", 0777)
523 || Die "Couldn't create directory '$backup_dir/$database': $!";
524 }
525- } elsif ($option_remote_host) {
526- if (system("ssh $option_ssh_opt $option_remote_host test -e $backup_dir/$database")
527- != 0) {
528- system("ssh $option_ssh_opt $option_remote_host mkdir $backup_dir/$database");
529- }
530 }
531
532 # copy files of this database
533@@ -2109,16 +1964,13 @@
534 if (!$prep_mode) {
535 $rsync_files_hash{"$database/$file"} = 1;
536 }
537- } elsif (!$option_remote_host && !$option_stream) {
538+ } elsif (!$option_stream) {
539 $src_name = escape_path("$source_dir/$database/$file");
540 $dst_name = escape_path("$backup_dir/$database");
541 # Copy the file - If we get an error and the file actually exists, die with error msg
542 copy_if_exists("$src_name", "$dst_name")
543 or Die "Failed to copy file '$file': $!";
544- } elsif ($option_remote_host) {
545- # Queue up files for one single scp per database.
546- push(@scp_files, "'$file'");
547- } elsif($option_stream) {
548+ } else {
549 my $ret = 0;
550 my $file_name = substr($file, rindex($file, '/') + 1);
551 $file_name=~s/([\$\\\" ])/\\$1/g;
552@@ -2138,11 +1990,6 @@
553 }
554 }
555 }
556- if ($option_remote_host and @scp_files) {
557- my $scp_file_list = join(" ", map { "$source_dir/$database/$_" } @scp_files);
558- system("scp $option_scp_opt $scp_file_list '$option_remote_host:$backup_dir/$database/'")
559- and Die "Failed to execute \"scp $option_scp_opt $scp_file_list '$option_remote_host:$backup_dir/$database/'\": $!";
560- }
561 }
562 closedir(DIR);
563
564@@ -2716,12 +2563,12 @@
565 [--password=WORD] [--port=PORT] [--socket=SOCKET]
566 [--no-timestamp] [--ibbackup=IBBACKUP-BINARY]
567 [--slave-info] [--galera-info] [--stream=tar|xbstream]
568- [--scpopt=OPTIONS-FOR-SCP] [--sshopt=OPTIONS-FOR-SSH]
569 [--defaults-file=MY.CNF] [--defaults-group=GROUP-NAME]
570- [--databases=LIST] [--remote-host=HOSTNAME] [--no-lock]
571+ [--databases=LIST] [--no-lock]
572 [--tmpdir=DIRECTORY] [--tables-file=FILE]
573 [--incremental] [--incremental-basedir]
574 [--incremental-dir] [--incremental-lsn]
575+ [--compact]
576 BACKUP-ROOT-DIR
577
578 innobackupex --apply-log [--use-memory=B] [--uncompress]
579@@ -2778,6 +2625,10 @@
580
581 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".
582
583+=item --compact
584+
585+Create a compact backup with all secondary index pages omitted. This option is passed directly to xtrabackup. See xtrabackup documentation for details.
586+
587 =item --compress
588
589 This option instructs xtrabackup to compress backup copies of InnoDB
590@@ -2875,10 +2726,6 @@
591
592 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.
593
594-=item --remote-host=HOSTNAME
595-
596-This option is DEPRECATED and will be removed in Percona XtraBackup 2.1. In Percona XtraBackup 2.0 and later, you should use streaming backups instead. 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.
597-
598 =item --safe-slave-backup
599
600 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.
601@@ -2917,7 +2764,7 @@
602
603 =item --tmpdir=DIRECTORY
604
605-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.
606+This option specifies the location where a temporary file will be stored. The option accepts a string argument. It should be used when --stream is specified. For these options, the transaction log will first be stored to a temporary file, before streaming. 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.
607
608 =item --use-memory=B
609
610
611=== modified file 'src/Makefile'
612--- src/Makefile 2012-02-10 20:05:56 +0000
613+++ src/Makefile 2012-10-18 11:58:23 +0000
614@@ -12,10 +12,10 @@
615 LIBS += -lpthread
616 DEFS = -DUNIV_LINUX -DMYSQL_SERVER
617
618-CFLAGS += -DXTRABACKUP_VERSION=\"$(XTRABACKUP_VERSION)\" -pedantic -Wall -Wundef -Wshadow -fdiagnostics-show-option -fno-strict-aliasing -Wno-strict-aliasing -Wextra -Wformat -Wno-format-nonliteral -Wno-format-security -Wno-long-long -Wmissing-declarations -Wno-redundant-decls --std=gnu99
619+CFLAGS += -g -DXTRABACKUP_VERSION=\"$(XTRABACKUP_VERSION)\" -pedantic -Wall -fdiagnostics-show-option -fno-strict-aliasing -Wno-strict-aliasing -Wextra -Wformat -Wno-format-nonliteral -Wno-format-security -Wno-long-long -Wmissing-declarations -Wno-redundant-decls --std=gnu99 # -Wundef -Wshadow
620
621 ifneq ($(DEBUG),)
622-CFLAGS += -DXB_DEBUG=1
623+CFLAGS += -DXB_DEBUG=1 -DUNIV_DEBUG
624 endif
625
626 TARGET=xtrabackup
627@@ -23,7 +23,16 @@
628 BIN_DIR=$(PREFIX)/bin
629
630 COMMON_INC = -I. -I libarchive/libarchive -I quicklz
631-XTRABACKUPOBJS = xtrabackup.o stream.o local.o compress.o xbstream_write.o \
632+XTRABACKUPOBJS = xtrabackup.o \
633+ ds_stream.o \
634+ ds_local.o \
635+ ds_compress.o \
636+ ds_tmpfile.o \
637+ datasink.o \
638+ write_filt.o \
639+ fil_cur.o \
640+ innodb_int.o \
641+ xbstream_write.o \
642 quicklz/quicklz.o
643 XBSTREAMOBJS = xbstream.o xbstream_write.o xbstream_read.o
644
645@@ -176,10 +185,10 @@
646 xbstream.o xbstream_read.o: %.o: %.c
647 $(CC) $(CFLAGS) $(INC) $(DEFS) -c $< -o $@
648
649-xbstream: $(XBSTREAMOBJS) $(MYSQLOBJS) local.o
650+xbstream: $(XBSTREAMOBJS) $(MYSQLOBJS) ds_local.o datasink.o
651 $(CC) $(CFLAGS) $^ $(INC) $(MYSQLOBJS) $(LIBS) -o $@
652
653-xtrabackup.o: xtrabackup.c xb_regex.h
654+xtrabackup.o: xtrabackup.c xb_regex.h write_filt.h fil_cur.h xtrabackup.h
655
656 $(TARGET): $(XTRABACKUPOBJS) $(INNODBOBJS) $(MYSQLOBJS) $(LIBARCHIVE_A)
657 $(CC) $(CFLAGS) $(XTRABACKUPOBJS) $(INNODBOBJS) $(MYSQLOBJS) $(LIBS) \
658
659=== modified file 'src/common.h'
660--- src/common.h 2012-02-10 20:05:56 +0000
661+++ src/common.h 2012-10-18 11:58:23 +0000
662@@ -24,12 +24,14 @@
663 #include <my_global.h>
664 #include <mysql_version.h>
665 #include <fcntl.h>
666+#include <stdarg.h>
667+#include "innodb_int.h"
668
669 #define xb_a(expr) \
670 do { \
671 if (!(expr)) { \
672 msg("Assertion \"%s\" failed at %s:%lu\n", \
673- #expr, __FILE__, (unsigned long) __LINE__); \
674+ #expr, __FILE__, (ulint) __LINE__); \
675 abort(); \
676 } \
677 } while (0);
678@@ -40,6 +42,8 @@
679 #define xb_ad(expr)
680 #endif
681
682+#define XB_DELTA_INFO_SUFFIX ".meta"
683+
684 static inline int msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
685 static inline int msg(const char *fmt, ...)
686 {
687@@ -61,13 +65,29 @@
688 /* Use POSIX_FADV_NORMAL when available */
689
690 #ifdef POSIX_FADV_NORMAL
691-#define USE_POSIX_FADVISE
692+# define USE_POSIX_FADVISE
693+#else
694+# define POSIX_FADV_NORMAL
695+# define POSIX_FADV_SEQUENTIAL
696+# define POSIX_FADV_DONTNEED
697+# define posix_fadvise(a,b,c,d) do {} while(0)
698 #endif
699
700-typedef enum {
701- XB_STREAM_FMT_NONE,
702- XB_STREAM_FMT_TAR,
703- XB_STREAM_FMT_XBSTREAM
704-} xb_stream_fmt_t;
705+/***********************************************************************
706+Computes bit shift for a given value. If the argument is not a power
707+of 2, returns 0.*/
708+static inline ulint
709+get_bit_shift(ulint value)
710+{
711+ ulint shift;
712+
713+ if (value == 0)
714+ return 0;
715+
716+ for (shift = 0; !(value & 1UL); shift++) {
717+ value >>= 1;
718+ }
719+ return (value >> 1) ? 0 : shift;
720+}
721
722 #endif
723
724=== added file 'src/datasink.c'
725--- src/datasink.c 1970-01-01 00:00:00 +0000
726+++ src/datasink.c 2012-10-18 11:58:23 +0000
727@@ -0,0 +1,113 @@
728+/******************************************************
729+Copyright (c) 2011 Percona Inc.
730+
731+Data sink interface.
732+
733+This program is free software; you can redistribute it and/or modify
734+it under the terms of the GNU General Public License as published by
735+the Free Software Foundation; version 2 of the License.
736+
737+This program is distributed in the hope that it will be useful,
738+but WITHOUT ANY WARRANTY; without even the implied warranty of
739+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
740+GNU General Public License for more details.
741+
742+You should have received a copy of the GNU General Public License
743+along with this program; if not, write to the Free Software
744+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
745+
746+*******************************************************/
747+
748+#include <my_base.h>
749+#include "common.h"
750+#include "datasink.h"
751+#include "ds_compress.h"
752+#include "ds_stream.h"
753+#include "ds_local.h"
754+#include "ds_tmpfile.h"
755+
756+/************************************************************************
757+Create a datasink of the specified type */
758+ds_ctxt_t *
759+ds_create(const char *root, ds_type_t type)
760+{
761+ datasink_t *ds;
762+ ds_ctxt_t *ctxt;
763+
764+ switch (type) {
765+ case DS_TYPE_LOCAL:
766+ ds = &datasink_local;
767+ break;
768+ case DS_TYPE_STREAM:
769+ ds = &datasink_stream;
770+ break;
771+ case DS_TYPE_COMPRESS:
772+ ds = &datasink_compress;
773+ break;
774+ case DS_TYPE_TMPFILE:
775+ ds = &datasink_tmpfile;
776+ break;
777+ default:
778+ msg("Unknown datasink type: %d\n", type);
779+ return NULL;
780+ }
781+
782+ ctxt = ds->init(root);
783+ if (ctxt != NULL) {
784+ ctxt->datasink = ds;
785+ } else {
786+ msg("Error: failed to initialize datasink.\n");
787+ exit(EXIT_FAILURE);
788+ }
789+
790+ return ctxt;
791+}
792+
793+/************************************************************************
794+Open a datasink file */
795+ds_file_t *
796+ds_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat)
797+{
798+ ds_file_t *file;
799+
800+ file = ctxt->datasink->open(ctxt, path, stat);
801+ if (file != NULL) {
802+ file->datasink = ctxt->datasink;
803+ }
804+
805+ return file;
806+}
807+
808+/************************************************************************
809+Write to a datasink file.
810+@return 0 on success, 1 on error. */
811+int
812+ds_write(ds_file_t *file, const void *buf, size_t len)
813+{
814+ return file->datasink->write(file, buf, len);
815+}
816+
817+/************************************************************************
818+Close a datasink file.
819+@return 0 on success, 1, on error. */
820+int
821+ds_close(ds_file_t *file)
822+{
823+ return file->datasink->close(file);
824+}
825+
826+/************************************************************************
827+Destroy a datasink handle */
828+void
829+ds_destroy(ds_ctxt_t *ctxt)
830+{
831+ ctxt->datasink->deinit(ctxt);
832+}
833+
834+/************************************************************************
835+Set the destination pipe for a datasink (only makes sense for compress and
836+tmpfile). */
837+void ds_set_pipe(ds_ctxt_t *ctxt, ds_ctxt_t *pipe_ctxt)
838+{
839+ ctxt->pipe_ctxt = pipe_ctxt;
840+}
841
842=== modified file 'src/datasink.h'
843--- src/datasink.h 2012-02-10 20:05:56 +0000
844+++ src/datasink.h 2012-10-18 11:58:23 +0000
845@@ -25,24 +25,62 @@
846 #include <my_dir.h>
847
848 struct datasink_struct;
849+typedef struct datasink_struct datasink_t;
850
851-typedef struct {
852- struct datasink_struct *datasink;
853- char *root;
854- void *ptr;
855+typedef struct ds_ctxt {
856+ datasink_t *datasink;
857+ char *root;
858+ void *ptr;
859+ struct ds_ctxt *pipe_ctxt;
860 } ds_ctxt_t;
861
862 typedef struct {
863- void *ptr;
864- char *path;
865+ void *ptr;
866+ char *path;
867+ datasink_t *datasink;
868 } ds_file_t;
869
870-typedef struct datasink_struct {
871+struct datasink_struct {
872 ds_ctxt_t *(*init)(const char *root);
873 ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
874 int (*write)(ds_file_t *file, const void *buf, size_t len);
875 int (*close)(ds_file_t *file);
876 void (*deinit)(ds_ctxt_t *ctxt);
877-} datasink_t;
878+};
879+
880+/* Supported datasink types */
881+typedef enum {
882+ DS_TYPE_LOCAL,
883+ DS_TYPE_STREAM,
884+ DS_TYPE_COMPRESS,
885+ DS_TYPE_TMPFILE
886+} ds_type_t;
887+
888+/************************************************************************
889+Create a datasink of the specified type */
890+ds_ctxt_t *ds_create(const char *root, ds_type_t type);
891+
892+/************************************************************************
893+Open a datasink file */
894+ds_file_t *ds_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
895+
896+/************************************************************************
897+Write to a datasink file.
898+@return 0 on success, 1 on error. */
899+int ds_write(ds_file_t *file, const void *buf, size_t len);
900+
901+/************************************************************************
902+Close a datasink file.
903+@return 0 on success, 1, on error. */
904+int ds_close(ds_file_t *file);
905+
906+/************************************************************************
907+Destroy a datasink handle */
908+void ds_destroy(ds_ctxt_t *ctxt);
909+
910+/************************************************************************
911+Set the destination pipe for a datasink (only makes sense for compress and
912+tmpfile). */
913+void ds_set_pipe(ds_ctxt_t *ctxt, ds_ctxt_t *pipe_ctxt);
914
915 #endif /* XB_DATASINK_H */
916
917=== renamed file 'src/compress.c' => 'src/ds_compress.c'
918--- src/compress.c 2012-06-14 10:50:28 +0000
919+++ src/ds_compress.c 2012-10-18 11:58:23 +0000
920@@ -25,8 +25,8 @@
921 #include <zlib.h>
922 #include "common.h"
923 #include "datasink.h"
924-#include "stream.h"
925-#include "local.h"
926+#include "ds_stream.h"
927+#include "ds_local.h"
928
929 #define COMPRESS_CHUNK_SIZE (64 * 1024UL)
930 #define MY_QLZ_COMPRESS_OVERHEAD 400
931@@ -50,20 +50,16 @@
932 } comp_thread_ctxt_t;
933
934 typedef struct {
935- ds_ctxt_t *dest_ctxt;
936 comp_thread_ctxt_t *threads;
937 uint nthreads;
938 } ds_compress_ctxt_t;
939
940 typedef struct {
941- datasink_t *dest_ds;
942 ds_file_t *dest_file;
943 ds_compress_ctxt_t *comp_ctxt;
944 size_t bytes_processed;
945 } ds_compress_file_t;
946
947-extern ibool xtrabackup_stream;
948-extern uint xtrabackup_parallel;
949 extern ibool xtrabackup_compress_threads;
950
951 static ds_ctxt_t *compress_init(const char *root);
952@@ -81,10 +77,8 @@
953 &compress_deinit
954 };
955
956-static inline int write_uint32_le(datasink_t *sink, ds_file_t *file,
957- ulong n);
958-static inline int write_uint64_le(datasink_t *sink, ds_file_t *file,
959- ulonglong n);
960+static inline int write_uint32_le(ds_file_t *file, ulong n);
961+static inline int write_uint64_le(ds_file_t *file, ulonglong n);
962
963 static comp_thread_ctxt_t *create_worker_threads(uint n);
964 static void destroy_worker_threads(comp_thread_ctxt_t *threads, uint n);
965@@ -96,25 +90,12 @@
966 {
967 ds_ctxt_t *ctxt;
968 ds_compress_ctxt_t *compress_ctxt;
969- datasink_t *dest_ds;
970- ds_ctxt_t *dest_ctxt;
971 comp_thread_ctxt_t *threads;
972
973- /* Decide whether the compressed data will be stored in local files or
974- streamed to an archive */
975- dest_ds = xtrabackup_stream ? &datasink_stream : &datasink_local;
976-
977- dest_ctxt = dest_ds->init(root);
978- if (dest_ctxt == NULL) {
979- msg("compress: failed to initialize the target datasink.\n");
980- return NULL;
981- }
982-
983 /* Create and initialize the worker threads */
984 threads = create_worker_threads(xtrabackup_compress_threads);
985 if (threads == NULL) {
986 msg("compress: failed to create worker threads.\n");
987- dest_ds->deinit(dest_ctxt);
988 return NULL;
989 }
990
991@@ -123,12 +104,11 @@
992 MYF(MY_FAE));
993
994 compress_ctxt = (ds_compress_ctxt_t *) (ctxt + 1);
995- compress_ctxt->dest_ctxt = dest_ctxt;
996 compress_ctxt->threads = threads;
997 compress_ctxt->nthreads = xtrabackup_compress_threads;
998
999- ctxt->datasink = &datasink_compress;
1000 ctxt->ptr = compress_ctxt;
1001+ ctxt->root = my_strdup(root, MYF(MY_FAE));
1002
1003 return ctxt;
1004 }
1005@@ -138,7 +118,6 @@
1006 compress_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
1007 {
1008 ds_compress_ctxt_t *comp_ctxt;
1009- datasink_t *dest_ds;
1010 ds_ctxt_t *dest_ctxt;
1011 ds_file_t *dest_file;
1012 char new_name[FN_REFLEN];
1013@@ -146,21 +125,22 @@
1014 ds_file_t *file;
1015 ds_compress_file_t *comp_file;
1016
1017+ xb_a(ctxt->pipe_ctxt != NULL);
1018+ dest_ctxt = ctxt->pipe_ctxt;
1019+
1020 comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;
1021- dest_ctxt = comp_ctxt->dest_ctxt;
1022- dest_ds = dest_ctxt->datasink;
1023
1024 /* Append the .qp extension to the filename */
1025 fn_format(new_name, path, "", ".qp", MYF(MY_APPEND_EXT));
1026
1027- dest_file = dest_ds->open(dest_ctxt, new_name, mystat);
1028+ dest_file = ds_open(dest_ctxt, new_name, mystat);
1029 if (dest_file == NULL) {
1030 return NULL;
1031 }
1032
1033 /* Write the qpress archive header */
1034- if (dest_ds->write(dest_file, "qpress10", 8) ||
1035- write_uint64_le(dest_ds, dest_file, COMPRESS_CHUNK_SIZE)) {
1036+ if (ds_write(dest_file, "qpress10", 8) ||
1037+ write_uint64_le(dest_file, COMPRESS_CHUNK_SIZE)) {
1038 goto err;
1039 }
1040
1041@@ -171,10 +151,10 @@
1042
1043 /* Write the qpress file header */
1044 name_len = strlen(new_name);
1045- if (dest_ds->write(dest_file, "F", 1) ||
1046- write_uint32_le(dest_ds, dest_file, name_len) ||
1047+ if (ds_write(dest_file, "F", 1) ||
1048+ write_uint32_le(dest_file, name_len) ||
1049 /* we want to write the terminating \0 as well */
1050- dest_ds->write(dest_file, new_name, name_len + 1)) {
1051+ ds_write(dest_file, new_name, name_len + 1)) {
1052 goto err;
1053 }
1054
1055@@ -183,7 +163,6 @@
1056 MYF(MY_FAE));
1057 comp_file = (ds_compress_file_t *) (file + 1);
1058 comp_file->dest_file = dest_file;
1059- comp_file->dest_ds = dest_ds;
1060 comp_file->comp_ctxt = comp_ctxt;
1061 comp_file->bytes_processed = 0;
1062
1063@@ -193,7 +172,7 @@
1064 return file;
1065
1066 err:
1067- dest_ds->close(dest_file);
1068+ ds_close(dest_file);
1069 return NULL;
1070 }
1071
1072@@ -208,12 +187,10 @@
1073 uint nthreads;
1074 uint i;
1075 const char *ptr;
1076- datasink_t *dest_ds;
1077 ds_file_t *dest_file;
1078
1079 comp_file = (ds_compress_file_t *) file->ptr;
1080 comp_ctxt = comp_file->comp_ctxt;
1081- dest_ds = comp_file->dest_ds;
1082 dest_file = comp_file->dest_file;
1083
1084 threads = comp_ctxt->threads;
1085@@ -262,8 +239,8 @@
1086
1087 ut_a(threads[i].to_len > 0);
1088
1089- if (dest_ds->write(dest_file, "NEWBNEWB", 8) ||
1090- write_uint64_le(dest_ds, dest_file,
1091+ if (ds_write(dest_file, "NEWBNEWB", 8) ||
1092+ write_uint64_le(dest_file,
1093 comp_file->bytes_processed)) {
1094 msg("compress: write to the destination stream "
1095 "failed.\n");
1096@@ -272,9 +249,8 @@
1097
1098 comp_file->bytes_processed += threads[i].from_len;
1099
1100- if (write_uint32_le(dest_ds, dest_file,
1101- threads[i].adler) ||
1102- dest_ds->write(dest_file, threads[i].to,
1103+ if (write_uint32_le(dest_file, threads[i].adler) ||
1104+ ds_write(dest_file, threads[i].to,
1105 threads[i].to_len)) {
1106 msg("compress: write to the destination stream "
1107 "failed.\n");
1108@@ -294,23 +270,21 @@
1109 compress_close(ds_file_t *file)
1110 {
1111 ds_compress_file_t *comp_file;
1112- datasink_t *dest_ds;
1113 ds_file_t *dest_file;
1114
1115 comp_file = (ds_compress_file_t *) file->ptr;
1116- dest_ds = comp_file->dest_ds;
1117 dest_file = comp_file->dest_file;
1118
1119 /* Write the qpress file trailer */
1120- dest_ds->write(dest_file, "ENDSENDS", 8);
1121+ ds_write(dest_file, "ENDSENDS", 8);
1122
1123 /* Supposedly the number of written bytes should be written as a
1124 "recovery information" in the file trailer, but in reality qpress
1125 always writes 8 zeros here. Let's do the same */
1126
1127- write_uint64_le(dest_ds, dest_file, 0);
1128+ write_uint64_le(dest_file, 0);
1129
1130- dest_ds->close(dest_file);
1131+ ds_close(dest_file);
1132
1133 MY_FREE(file);
1134
1135@@ -322,39 +296,37 @@
1136 compress_deinit(ds_ctxt_t *ctxt)
1137 {
1138 ds_compress_ctxt_t *comp_ctxt;
1139- ds_ctxt_t *dest_ctxt;
1140- datasink_t *dest_ds;
1141+
1142+ xb_a(ctxt->pipe_ctxt != NULL);
1143
1144 comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;;
1145
1146 destroy_worker_threads(comp_ctxt->threads, comp_ctxt->nthreads);
1147
1148- dest_ctxt = comp_ctxt->dest_ctxt;
1149- dest_ds = dest_ctxt->datasink;
1150-
1151- dest_ds->deinit(dest_ctxt);
1152-
1153+ ds_destroy(ctxt->pipe_ctxt);
1154+
1155+ MY_FREE(ctxt->root);
1156 MY_FREE(ctxt);
1157 }
1158
1159 static inline
1160 int
1161-write_uint32_le(datasink_t *sink, ds_file_t *file, ulong n)
1162+write_uint32_le(ds_file_t *file, ulong n)
1163 {
1164 char tmp[4];
1165
1166 int4store(tmp, n);
1167- return sink->write(file, tmp, sizeof(tmp));
1168+ return ds_write(file, tmp, sizeof(tmp));
1169 }
1170
1171 static inline
1172 int
1173-write_uint64_le(datasink_t *sink, ds_file_t *file, ulonglong n)
1174+write_uint64_le(ds_file_t *file, ulonglong n)
1175 {
1176 char tmp[8];
1177
1178 int8store(tmp, n);
1179- return sink->write(file, tmp, sizeof(tmp));
1180+ return ds_write(file, tmp, sizeof(tmp));
1181 }
1182
1183 static
1184@@ -489,14 +461,3 @@
1185
1186 return NULL;
1187 }
1188-
1189-/* Return a target datasink for the specified compress datasink */
1190-ds_ctxt_t *
1191-compress_get_dest_ctxt(ds_ctxt_t *ctxt)
1192-{
1193- ds_compress_ctxt_t *comp_ctxt;
1194-
1195- comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;
1196-
1197- return comp_ctxt->dest_ctxt;
1198-}
1199
1200=== renamed file 'src/compress.h' => 'src/ds_compress.h'
1201--- src/compress.h 2012-06-14 10:50:28 +0000
1202+++ src/ds_compress.h 2012-10-18 11:58:23 +0000
1203@@ -18,14 +18,11 @@
1204
1205 *******************************************************/
1206
1207-#ifndef XB_COMPRESS_H
1208-#define XB_COMPRESS_H
1209+#ifndef DS_COMPRESS_H
1210+#define DS_COMPRESS_H
1211
1212 #include "datasink.h"
1213
1214 extern datasink_t datasink_compress;
1215
1216-/* Return a target datasink for the specified compress datasink */
1217-ds_ctxt_t *compress_get_dest_ctxt(ds_ctxt_t *);
1218-
1219 #endif
1220
1221=== renamed file 'src/local.c' => 'src/ds_local.c'
1222--- src/local.c 2012-02-10 20:05:56 +0000
1223+++ src/ds_local.c 2012-10-18 11:58:23 +0000
1224@@ -57,7 +57,6 @@
1225
1226 ctxt = my_malloc(sizeof(ds_ctxt_t), MYF(MY_FAE));
1227
1228- ctxt->datasink = &datasink_local;
1229 ctxt->root = my_strdup(root, MYF(MY_FAE));
1230
1231 return ctxt;
1232@@ -117,9 +116,7 @@
1233 File fd = ((ds_local_file_t *) file->ptr)->fd;
1234
1235 if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
1236-#ifdef USE_POSIX_FADVISE
1237 posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
1238-#endif
1239 return 0;
1240 }
1241
1242
1243=== renamed file 'src/local.h' => 'src/ds_local.h'
1244--- src/local.h 2012-02-10 20:05:56 +0000
1245+++ src/ds_local.h 2012-10-18 11:58:23 +0000
1246@@ -18,8 +18,8 @@
1247
1248 *******************************************************/
1249
1250-#ifndef XB_LOCAL_H
1251-#define XB_LOCAL_H
1252+#ifndef DS_LOCAL_H
1253+#define DS_LOCAL_H
1254
1255 #include "datasink.h"
1256
1257
1258=== renamed file 'src/stream.c' => 'src/ds_stream.c'
1259--- src/stream.c 2012-04-22 13:04:24 +0000
1260+++ src/ds_stream.c 2012-10-18 11:58:23 +0000
1261@@ -24,6 +24,7 @@
1262 #include "common.h"
1263 #include "datasink.h"
1264 #include "xbstream.h"
1265+#include "xtrabackup.h"
1266
1267 typedef struct {
1268 struct archive *archive;
1269@@ -88,7 +89,10 @@
1270 }
1271
1272 if (archive_write_set_compression_none(a) != ARCHIVE_OK ||
1273- archive_write_set_format_pax_restricted(a) != ARCHIVE_OK) {
1274+ archive_write_set_format_pax_restricted(a) != ARCHIVE_OK ||
1275+ /* disable internal buffering so we don't have to flush the
1276+ output in xtrabackup */
1277+ archive_write_set_bytes_per_block(a, 0) != ARCHIVE_OK) {
1278 msg("failed to set libarchive stream options: %s\n",
1279 archive_error_string(a));
1280 archive_write_finish(a);
1281@@ -103,7 +107,6 @@
1282 }
1283
1284
1285- ctxt->datasink = &datasink_stream;
1286 ctxt->ptr = stream_ctxt;
1287
1288 return ctxt;
1289
1290=== renamed file 'src/stream.h' => 'src/ds_stream.h'
1291--- src/stream.h 2012-02-10 20:05:56 +0000
1292+++ src/ds_stream.h 2012-10-18 11:58:23 +0000
1293@@ -18,8 +18,8 @@
1294
1295 *******************************************************/
1296
1297-#ifndef XTRABACKUP_STREAM_H
1298-#define XTRABACKUP_STREAM_H
1299+#ifndef DS_STREAM_H
1300+#define DS_STREAM_H
1301
1302 #include "datasink.h"
1303
1304
1305=== added file 'src/ds_tmpfile.c'
1306--- src/ds_tmpfile.c 1970-01-01 00:00:00 +0000
1307+++ src/ds_tmpfile.c 2012-10-18 11:58:23 +0000
1308@@ -0,0 +1,243 @@
1309+/******************************************************
1310+Copyright (c) 2012 Percona Inc.
1311+
1312+tmpfile datasink for XtraBackup.
1313+
1314+This program is free software; you can redistribute it and/or modify
1315+it under the terms of the GNU General Public License as published by
1316+the Free Software Foundation; version 2 of the License.
1317+
1318+This program is distributed in the hope that it will be useful,
1319+but WITHOUT ANY WARRANTY; without even the implied warranty of
1320+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1321+GNU General Public License for more details.
1322+
1323+You should have received a copy of the GNU General Public License
1324+along with this program; if not, write to the Free Software
1325+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1326+
1327+*******************************************************/
1328+
1329+/* Do all writes to temporary files first, then pipe them to the specified
1330+datasink in a serialized way in deinit(). */
1331+
1332+#include <my_base.h>
1333+#include "common.h"
1334+#include "datasink.h"
1335+
1336+typedef struct {
1337+ pthread_mutex_t mutex;
1338+ LIST *file_list;
1339+} ds_tmpfile_ctxt_t;
1340+
1341+typedef struct {
1342+ LIST list;
1343+ File fd;
1344+ char *orig_path;
1345+ MY_STAT mystat;
1346+ ds_file_t *file;
1347+} ds_tmp_file_t;
1348+
1349+static ds_ctxt_t *tmpfile_init(const char *root);
1350+static ds_file_t *tmpfile_open(ds_ctxt_t *ctxt, const char *path,
1351+ MY_STAT *mystat);
1352+static int tmpfile_write(ds_file_t *file, const void *buf, size_t len);
1353+static int tmpfile_close(ds_file_t *file);
1354+static void tmpfile_deinit(ds_ctxt_t *ctxt);
1355+
1356+datasink_t datasink_tmpfile = {
1357+ &tmpfile_init,
1358+ &tmpfile_open,
1359+ &tmpfile_write,
1360+ &tmpfile_close,
1361+ &tmpfile_deinit
1362+};
1363+
1364+static ds_ctxt_t *
1365+tmpfile_init(const char *root)
1366+{
1367+ ds_ctxt_t *ctxt;
1368+ ds_tmpfile_ctxt_t *tmpfile_ctxt;
1369+
1370+ ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_tmpfile_ctxt_t),
1371+ MYF(MY_FAE));
1372+ tmpfile_ctxt = (ds_tmpfile_ctxt_t *) (ctxt + 1);
1373+ tmpfile_ctxt->file_list = NULL;
1374+ if (pthread_mutex_init(&tmpfile_ctxt->mutex, NULL)) {
1375+
1376+ MY_FREE(ctxt);
1377+ return NULL;
1378+ }
1379+
1380+ ctxt->ptr = tmpfile_ctxt;
1381+ ctxt->root = my_strdup(root, MYF(MY_FAE));
1382+
1383+ return ctxt;
1384+}
1385+
1386+static ds_file_t *
1387+tmpfile_open(ds_ctxt_t *ctxt, const char *path,
1388+ MY_STAT *mystat)
1389+{
1390+ ds_tmpfile_ctxt_t *tmpfile_ctxt;
1391+ char tmp_path[FN_REFLEN];
1392+ ds_tmp_file_t *tmp_file;
1393+ ds_file_t *file;
1394+ size_t path_len;
1395+ File fd;
1396+
1397+ /* Create a temporary file in tmpdir. The file will be automatically
1398+ removed on close. Code copied from mysql_tmpfile(). */
1399+ fd = create_temp_file(tmp_path, my_tmpdir(&mysql_tmpdir_list),
1400+ "xbtemp",
1401+#ifdef __WIN__
1402+ O_BINARY | O_TRUNC | O_SEQUENTIAL |
1403+ O_TEMPORARY | O_SHORT_LIVED |
1404+#endif /* __WIN__ */
1405+ O_CREAT | O_EXCL | O_RDWR,
1406+ MYF(MY_WME));
1407+
1408+#ifndef __WIN__
1409+ if (fd >= 0) {
1410+ /* On Windows, open files cannot be removed, but files can be
1411+ created with the O_TEMPORARY flag to the same effect
1412+ ("delete on close"). */
1413+ unlink(path);
1414+ }
1415+#endif /* !__WIN__ */
1416+
1417+ if (fd < 0) {
1418+ return NULL;
1419+ }
1420+
1421+ path_len = strlen(path) + 1; /* terminating '\0' */
1422+
1423+ file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
1424+ sizeof(ds_tmp_file_t) + path_len,
1425+ MYF(MY_FAE));
1426+
1427+ tmp_file = (ds_tmp_file_t *) (file + 1);
1428+ tmp_file->file = file;
1429+ memcpy(&tmp_file->mystat, mystat, sizeof(MY_STAT));
1430+ /* Save a copy of 'path', since it may not be accessible later */
1431+ tmp_file->orig_path = (char *) tmp_file + sizeof(ds_tmp_file_t);
1432+
1433+ tmp_file->fd = fd;
1434+ memcpy(tmp_file->orig_path, path, path_len);
1435+
1436+ /* Store the real temporary file name in file->path */
1437+ file->path = my_strdup(tmp_path, MYF(MY_FAE));
1438+ file->ptr = tmp_file;
1439+
1440+ /* Store the file object in the list to be piped later */
1441+ tmpfile_ctxt = (ds_tmpfile_ctxt_t *) ctxt->ptr;
1442+ tmp_file->list.data = tmp_file;
1443+
1444+ pthread_mutex_lock(&tmpfile_ctxt->mutex);
1445+ tmpfile_ctxt->file_list = list_add(tmpfile_ctxt->file_list,
1446+ &tmp_file->list);
1447+ pthread_mutex_unlock(&tmpfile_ctxt->mutex);
1448+
1449+ return file;
1450+}
1451+
1452+static int
1453+tmpfile_write(ds_file_t *file, const void *buf, size_t len)
1454+{
1455+ File fd = ((ds_tmp_file_t *) file->ptr)->fd;
1456+
1457+ if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
1458+ posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
1459+ return 0;
1460+ }
1461+
1462+ return 1;
1463+}
1464+
1465+static int
1466+tmpfile_close(ds_file_t *file)
1467+{
1468+ /* Do nothing -- we will close (and thus remove) the file after piping
1469+ it to the destination datasink in tmpfile_deinit(). */
1470+
1471+ MY_FREE(file->path);
1472+
1473+ return 0;
1474+}
1475+
1476+static void
1477+tmpfile_deinit(ds_ctxt_t *ctxt)
1478+{
1479+ LIST *list;
1480+ ds_tmpfile_ctxt_t *tmpfile_ctxt;
1481+ MY_STAT mystat;
1482+ ds_tmp_file_t *tmp_file;
1483+ ds_file_t *dst_file;
1484+ ds_ctxt_t *pipe_ctxt;
1485+ void *buf = NULL;
1486+ const size_t buf_size = 1024 * 1024;
1487+ size_t bytes;
1488+
1489+ pipe_ctxt = ctxt->pipe_ctxt;
1490+ xb_a(pipe_ctxt != NULL);
1491+
1492+ buf = my_malloc(buf_size, MYF(MY_FAE));
1493+
1494+ tmpfile_ctxt = (ds_tmpfile_ctxt_t *) ctxt->ptr;
1495+ list = tmpfile_ctxt->file_list;
1496+
1497+ /* Walk the files in the order they have been added */
1498+ list = list_reverse(list);
1499+ while (list != NULL) {
1500+ tmp_file = list->data;
1501+ /* Stat the file to replace size and mtime on the original
1502+ * mystat struct */
1503+ if (my_fstat(tmp_file->fd, &mystat, MYF(0))) {
1504+ msg("error: my_fstat() failed.\n");
1505+ exit(EXIT_FAILURE);
1506+ }
1507+ tmp_file->mystat.st_size = mystat.st_size;
1508+ tmp_file->mystat.st_mtime = mystat.st_mtime;
1509+
1510+ dst_file = ds_open(pipe_ctxt, tmp_file->orig_path,
1511+ &tmp_file->mystat);
1512+ if (dst_file == NULL) {
1513+ msg("error: could not stream a temporary file to "
1514+ "'%s'\n", tmp_file->orig_path);
1515+ exit(EXIT_FAILURE);
1516+ }
1517+
1518+ /* copy to the destination datasink */
1519+ posix_fadvise(tmp_file->fd, 0, 0, POSIX_FADV_SEQUENTIAL);
1520+ if (my_seek(tmp_file->fd, 0, SEEK_SET, MYF(0)) ==
1521+ MY_FILEPOS_ERROR) {
1522+ msg("error: my_seek() failed for '%s', errno = %d.\n",
1523+ tmp_file->file->path, my_errno);
1524+ exit(EXIT_FAILURE);
1525+ }
1526+ while ((bytes = my_read(tmp_file->fd, buf, buf_size,
1527+ MYF(MY_WME))) > 0) {
1528+ posix_fadvise(tmp_file->fd, 0, 0, POSIX_FADV_DONTNEED);
1529+ if (ds_write(dst_file, buf, bytes)) {
1530+ msg("error: cannot write to stream for '%s'.\n",
1531+ tmp_file->orig_path);
1532+ exit(EXIT_FAILURE);
1533+ }
1534+ }
1535+ if (bytes == (size_t) -1) {
1536+ exit(EXIT_FAILURE);
1537+ }
1538+
1539+ my_close(tmp_file->fd, MYF(MY_WME));
1540+ ds_close(dst_file);
1541+
1542+ list = list_rest(list);
1543+ MY_FREE(tmp_file->file);
1544+ }
1545+
1546+ pthread_mutex_destroy(&tmpfile_ctxt->mutex);
1547+
1548+ MY_FREE(buf);
1549+ MY_FREE(ctxt->root);
1550+ MY_FREE(ctxt);
1551+}
1552
1553=== added file 'src/ds_tmpfile.h'
1554--- src/ds_tmpfile.h 1970-01-01 00:00:00 +0000
1555+++ src/ds_tmpfile.h 2012-10-18 11:58:23 +0000
1556@@ -0,0 +1,28 @@
1557+/******************************************************
1558+Copyright (c) 2012 Percona Inc.
1559+
1560+tmpfile datasink for XtraBackup.
1561+
1562+This program is free software; you can redistribute it and/or modify
1563+it under the terms of the GNU General Public License as published by
1564+the Free Software Foundation; version 2 of the License.
1565+
1566+This program is distributed in the hope that it will be useful,
1567+but WITHOUT ANY WARRANTY; without even the implied warranty of
1568+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1569+GNU General Public License for more details.
1570+
1571+You should have received a copy of the GNU General Public License
1572+along with this program; if not, write to the Free Software
1573+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1574+
1575+*******************************************************/
1576+
1577+#ifndef DS_TMPFILE_H
1578+#define DS_TMPFILE_H
1579+
1580+#include "datasink.h"
1581+
1582+extern datasink_t datasink_tmpfile;
1583+
1584+#endif
1585
1586=== added file 'src/fil_cur.c'
1587--- src/fil_cur.c 1970-01-01 00:00:00 +0000
1588+++ src/fil_cur.c 2012-10-18 11:58:23 +0000
1589@@ -0,0 +1,270 @@
1590+/******************************************************
1591+XtraBackup: hot backup tool for InnoDB
1592+(c) 2009-2012 Percona Inc.
1593+Originally Created 3/3/2009 Yasufumi Kinoshita
1594+Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
1595+Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
1596+
1597+This program is free software; you can redistribute it and/or modify
1598+it under the terms of the GNU General Public License as published by
1599+the Free Software Foundation; version 2 of the License.
1600+
1601+This program is distributed in the hope that it will be useful,
1602+but WITHOUT ANY WARRANTY; without even the implied warranty of
1603+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1604+GNU General Public License for more details.
1605+
1606+You should have received a copy of the GNU General Public License
1607+along with this program; if not, write to the Free Software
1608+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1609+
1610+*******************************************************/
1611+
1612+/* Source file cursor implementation */
1613+
1614+#include <my_base.h>
1615+#include "innodb_int.h"
1616+#include <buf0buf.h>
1617+#include <fsp0types.h>
1618+#include "fil_cur.h"
1619+#include "common.h"
1620+#include "xtrabackup.h"
1621+
1622+/* Size of read buffer in pages */
1623+#define XB_FIL_CUR_PAGES 64
1624+
1625+/************************************************************************
1626+Open a source file cursor.
1627+
1628+@return XB_FIL_CUR_SUCCESS on success, XB_FIL_CUR_SKIP if the source file must
1629+be skipped and XB_FIL_CUR_ERROR on error. */
1630+xb_fil_cur_result_t
1631+xb_fil_cur_open(
1632+/*============*/
1633+ xb_fil_cur_t* cursor, /*!< out: source file cursor */
1634+ fil_node_t* node, /*!< in: source tablespace node */
1635+ uint thread_n) /*!< thread number for diagnostics */
1636+{
1637+ ulint page_size;
1638+ ulint page_size_shift;
1639+ ulint zip_size;
1640+
1641+ /* Initialize these first so xb_fil_cur_close() handles them correctly
1642+ in case of error */
1643+ cursor->orig_buf = NULL;
1644+ cursor->file = XB_FILE_UNDEFINED;
1645+
1646+ cursor->space_id = node->space->id;
1647+ cursor->is_system = trx_sys_sys_space(node->space->id);
1648+
1649+ /* Make the file path relative to the backup root,
1650+ i.e. "ibdata1" for system tablespace or database/table.ibd for
1651+ per-table spaces. */
1652+ if (cursor->is_system) {
1653+ char *next, *p;
1654+
1655+ p = node->name;
1656+ while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL) {
1657+ p = next + 1;
1658+ }
1659+ strncpy(cursor->path, p, sizeof(cursor->path));
1660+ } else {
1661+ /* file per table style "./database/table.ibd" */
1662+ strncpy(cursor->path, node->name, sizeof(cursor->path));
1663+ }
1664+
1665+ /* Open the file */
1666+
1667+ if (my_stat(node->name, &cursor->statinfo, MYF(MY_WME)) == NULL) {
1668+ msg("[%02u] xtrabackup: Warning: cannot stat %s\n",
1669+ thread_n, node->name);
1670+ return(XB_FIL_CUR_SKIP);
1671+ }
1672+
1673+ if (!node->open) {
1674+ ibool success;
1675+
1676+ cursor->file =
1677+ xb_file_create_no_error_handling(node->name,
1678+ OS_FILE_OPEN,
1679+ OS_FILE_READ_ONLY,
1680+ &success);
1681+ if (!success) {
1682+ /* The following call prints an error message */
1683+ os_file_get_last_error(TRUE);
1684+
1685+ msg("[%02u] xtrabackup: Warning: cannot open %s\n"
1686+ "[%02u] xtrabackup: Warning: We assume the "
1687+ "table was dropped or renamed during "
1688+ "xtrabackup execution and ignore the file.\n",
1689+ thread_n, node->name, thread_n);
1690+ return(XB_FIL_CUR_SKIP);
1691+ }
1692+
1693+ xb_file_set_nocache(cursor->file, node->name, "OPEN");
1694+ } else {
1695+ cursor->file = node->handle;
1696+ }
1697+ posix_fadvise(cursor->file, 0, 0, POSIX_FADV_SEQUENTIAL);
1698+
1699+ /* Determine the page size */
1700+#ifndef INNODB_VERSION_SHORT
1701+ zip_size = UNIV_PAGE_SIZE;
1702+ page_size = UNIV_PAGE_SIZE;
1703+ page_size_shift = UNIV_PAGE_SIZE_SHIFT;
1704+#else
1705+ zip_size = xb_get_zip_size(cursor->file);
1706+ if (zip_size == ULINT_UNDEFINED) {
1707+ os_file_close(cursor->file);
1708+ return(XB_FIL_CUR_SKIP);
1709+ } else if (zip_size) {
1710+ page_size = zip_size;
1711+ page_size_shift = get_bit_shift(page_size);
1712+ msg("[%02u] %s is compressed with page size = "
1713+ "%lu bytes\n", thread_n, node->name, page_size);
1714+ if (page_size_shift < 10 || page_size_shift > 14) {
1715+ msg("[%02u] xtrabackup: Error: Invalid "
1716+ "page size: %lu.\n", thread_n, page_size);
1717+ ut_error;
1718+ }
1719+ } else {
1720+ page_size = UNIV_PAGE_SIZE;
1721+ page_size_shift = UNIV_PAGE_SIZE_SHIFT;
1722+ }
1723+#endif
1724+ cursor->page_size = page_size;
1725+ cursor->page_size_shift = page_size_shift;
1726+ cursor->zip_size = zip_size;
1727+
1728+ /* Allocate read buffer */
1729+ cursor->buf_size = XB_FIL_CUR_PAGES * page_size;
1730+ cursor->orig_buf = ut_malloc(cursor->buf_size + UNIV_PAGE_SIZE);
1731+ cursor->buf = ut_align(cursor->orig_buf, UNIV_PAGE_SIZE);
1732+
1733+ cursor->offset = 0;
1734+ cursor->buf_read = 0;
1735+ cursor->buf_npages = 0;
1736+ cursor->buf_offset = 0;
1737+ cursor->buf_page_no = 0;
1738+ cursor->thread_n = thread_n;
1739+
1740+ return(XB_FIL_CUR_SUCCESS);
1741+}
1742+
1743+/************************************************************************
1744+Reads and verifies the next block of pages from the source
1745+file. Positions the cursor after the last read non-corrupted page.
1746+
1747+@return XB_FIL_CUR_SUCCESS if some have been read successfully, XB_FIL_CUR_EOF
1748+if there are no more pages to read and XB_FIL_CUR_ERROR on error. */
1749+xb_fil_cur_result_t
1750+xb_fil_cur_read(
1751+/*============*/
1752+ xb_fil_cur_t* cursor) /*!< in/out: source file cursor */
1753+{
1754+ ibool success;
1755+ ulint page_size;
1756+ ulint offset_high;
1757+ ulint offset_low;
1758+ byte* page;
1759+ ulint i;
1760+ ulint npages;
1761+ ulint retry_count;
1762+ xb_fil_cur_result_t ret;
1763+ IB_INT64 to_read;
1764+
1765+ page_size = cursor->page_size;
1766+
1767+ offset_high = (ulint) (cursor->offset >> 32);
1768+ offset_low = (ulint) (cursor->offset & 0xFFFFFFFFUL);
1769+
1770+ to_read = (IB_INT64) cursor->statinfo.st_size - cursor->offset;
1771+
1772+ if (to_read == 0LL) {
1773+ return(XB_FIL_CUR_EOF);
1774+ }
1775+
1776+ if (to_read > (IB_INT64) cursor->buf_size) {
1777+ to_read = (IB_INT64) cursor->buf_size;
1778+ }
1779+ ut_a(to_read > 0 && to_read <= 0xFFFFFFFFLL);
1780+ ut_a(to_read % page_size == 0);
1781+
1782+ npages = (ulint) (to_read >> cursor->page_size_shift);
1783+
1784+ retry_count = 10;
1785+ ret = XB_FIL_CUR_SUCCESS;
1786+
1787+read_retry:
1788+ xtrabackup_io_throttling();
1789+
1790+ cursor->buf_read = 0;
1791+ cursor->buf_npages = 0;
1792+ cursor->buf_offset = cursor->offset;
1793+ cursor->buf_page_no = (ulint) (cursor->offset >>
1794+ cursor->page_size_shift);
1795+
1796+ success = os_file_read(cursor->file, cursor->buf,
1797+ offset_low, offset_high, to_read);
1798+ if (!success) {
1799+ return(XB_FIL_CUR_ERROR);
1800+ }
1801+
1802+ /* check pages for corruption and re-read if necessary. i.e. in case of
1803+ partially written pages */
1804+ for (page = cursor->buf, i = 0; i < npages; page += page_size, i++) {
1805+ if (xb_buf_page_is_corrupted(page, cursor->zip_size))
1806+ {
1807+ ulint page_no = cursor->buf_page_no + i;
1808+
1809+ if (cursor->is_system &&
1810+ page_no >= FSP_EXTENT_SIZE &&
1811+ page_no < FSP_EXTENT_SIZE * 3) {
1812+ /* skip doublewrite buffer pages */
1813+ ut_a(page_size == UNIV_PAGE_SIZE);
1814+ msg("[%02lu] xtrabackup: "
1815+ "Page %lu is a doublewrite buffer page, "
1816+ "skipping.\n", cursor->thread_n, page_no);
1817+ } else {
1818+ retry_count--;
1819+ if (retry_count == 0) {
1820+ msg("[%02lu] xtrabackup: "
1821+ "Error: failed to read page after "
1822+ "10 retries. File %s seems to be "
1823+ "corrupted.\n", cursor->thread_n,
1824+ cursor->path);
1825+ ret = XB_FIL_CUR_ERROR;
1826+ break;
1827+ }
1828+ msg("[%02lu] xtrabackup: "
1829+ "Database page corruption detected at page "
1830+ "%lu, retrying...\n", cursor->thread_n,
1831+ page_no);
1832+ goto read_retry;
1833+ }
1834+ }
1835+ cursor->buf_read += page_size;
1836+ cursor->buf_npages++;
1837+ }
1838+
1839+ posix_fadvise(cursor->file, 0, 0, POSIX_FADV_DONTNEED);
1840+
1841+ cursor->offset += page_size * i;
1842+
1843+ return(ret);
1844+}
1845+
1846+/************************************************************************
1847+Close the source file cursor opened with xb_fil_cur_open(). */
1848+void
1849+xb_fil_cur_close(
1850+/*=============*/
1851+ xb_fil_cur_t *cursor) /*!< in/out: source file cursor */
1852+{
1853+ if (cursor->orig_buf != NULL) {
1854+ ut_free(cursor->orig_buf);
1855+ }
1856+ if (cursor->file != XB_FILE_UNDEFINED) {
1857+ os_file_close(cursor->file);
1858+ }
1859+}
1860
1861=== added file 'src/fil_cur.h'
1862--- src/fil_cur.h 1970-01-01 00:00:00 +0000
1863+++ src/fil_cur.h 2012-10-18 11:58:23 +0000
1864@@ -0,0 +1,96 @@
1865+/******************************************************
1866+XtraBackup: hot backup tool for InnoDB
1867+(c) 2009-2012 Percona Inc.
1868+Originally Created 3/3/2009 Yasufumi Kinoshita
1869+Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
1870+Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
1871+
1872+This program is free software; you can redistribute it and/or modify
1873+it under the terms of the GNU General Public License as published by
1874+the Free Software Foundation; version 2 of the License.
1875+
1876+This program is distributed in the hope that it will be useful,
1877+but WITHOUT ANY WARRANTY; without even the implied warranty of
1878+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1879+GNU General Public License for more details.
1880+
1881+You should have received a copy of the GNU General Public License
1882+along with this program; if not, write to the Free Software
1883+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1884+
1885+*******************************************************/
1886+
1887+/* Source file cursor interface */
1888+
1889+#ifndef FIL_CUR_H
1890+#define FIL_CUR_H
1891+
1892+#include <my_dir.h>
1893+#include "innodb_int.h"
1894+
1895+typedef struct {
1896+ os_file_t file; /*!< source file handle */
1897+ char path[FN_REFLEN];/*!< normalized file path */
1898+ MY_STAT statinfo; /*!< information about the file */
1899+ ulint zip_size; /*!< compressed page size in bytes or 0
1900+ for uncompressed pages */
1901+ ulint page_size; /*!< = zip_size for compressed pages or
1902+ UNIV_PAGE_SIZE for uncompressed ones */
1903+ ulint page_size_shift;/*!< bit shift corresponding to
1904+ page_size */
1905+ IB_INT64 offset; /*!< current file offset in bytes */
1906+ my_bool is_system; /*!< TRUE for system tablespace, FALSE
1907+ otherwise */
1908+ byte* orig_buf; /*!< read buffer */
1909+ byte* buf; /*!< aligned pointer for orig_buf */
1910+ ulint buf_size; /*!< buffer size in bytes */
1911+ ulint buf_read; /*!< number of read bytes in buffer
1912+ after the last cursor read */
1913+ ulint buf_npages; /*!< number of pages in buffer after the
1914+ last cursor read */
1915+ IB_INT64 buf_offset; /*!< file offset of the first page in
1916+ buffer */
1917+ ulint buf_page_no; /*!< number of the first page in
1918+ buffer */
1919+ ulint thread_n; /*!< thread number for diagnostics */
1920+ ulint space_id; /*!< ID of tablespace */
1921+} xb_fil_cur_t;
1922+
1923+typedef enum {
1924+ XB_FIL_CUR_SUCCESS,
1925+ XB_FIL_CUR_SKIP,
1926+ XB_FIL_CUR_ERROR,
1927+ XB_FIL_CUR_EOF
1928+} xb_fil_cur_result_t;
1929+
1930+/************************************************************************
1931+Open a source file cursor.
1932+
1933+@return XB_FIL_CUR_SUCCESS on success, XB_FIL_CUR_SKIP if the source file must
1934+be skipped and XB_FIL_CUR_ERROR on error. */
1935+xb_fil_cur_result_t
1936+xb_fil_cur_open(
1937+/*============*/
1938+ xb_fil_cur_t* cursor, /*!< out: source file cursor */
1939+ fil_node_t* node, /*!< in: source tablespace node */
1940+ uint thread_n); /*!< thread number for diagnostics */
1941+
1942+/************************************************************************
1943+Reads and verifies the next block of pages from the source
1944+file. Positions the cursor after the last read non-corrupted page.
1945+
1946+@return XB_FIL_CUR_SUCCESS if some have been read successfully, XB_FIL_CUR_EOF
1947+if there are no more pages to read and XB_FIL_CUR_ERROR on error. */
1948+xb_fil_cur_result_t
1949+xb_fil_cur_read(
1950+/*============*/
1951+ xb_fil_cur_t* cursor); /*!< in/out: source file cursor */
1952+
1953+/************************************************************************
1954+Close the source file cursor opened with xb_fil_cur_open(). */
1955+void
1956+xb_fil_cur_close(
1957+/*=============*/
1958+ xb_fil_cur_t *cursor); /*!< in/out: source file cursor */
1959+
1960+#endif
1961
1962=== added file 'src/innodb_int.c'
1963--- src/innodb_int.c 1970-01-01 00:00:00 +0000
1964+++ src/innodb_int.c 2012-10-18 11:58:23 +0000
1965@@ -0,0 +1,983 @@
1966+/******************************************************
1967+XtraBackup: hot backup tool for InnoDB
1968+(c) 2009-2012 Percona Inc.
1969+Originally Created 3/3/2009 Yasufumi Kinoshita
1970+Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
1971+Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
1972+
1973+This program is free software; you can redistribute it and/or modify
1974+it under the terms of the GNU General Public License as published by
1975+the Free Software Foundation; version 2 of the License.
1976+
1977+This program is distributed in the hope that it will be useful,
1978+but WITHOUT ANY WARRANTY; without even the implied warranty of
1979+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1980+GNU General Public License for more details.
1981+
1982+You should have received a copy of the GNU General Public License
1983+along with this program; if not, write to the Free Software
1984+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1985+
1986+*******************************************************/
1987+
1988+/* InnoDB portability helpers and interface to internal functions */
1989+
1990+#include <my_base.h>
1991+#include <mysql_com.h>
1992+#include "innodb_int.h"
1993+#include <srv0srv.h>
1994+#include <ha_prototypes.h>
1995+#include <trx0trx.h>
1996+#include "common.h"
1997+
1998+extern long innobase_lock_wait_timeout;
1999+
2000+char *opt_mysql_tmpdir = NULL;
2001+MY_TMPDIR mysql_tmpdir_list;
2002+
2003+
2004+/****************************************************************//**
2005+A simple function to open or create a file.
2006+@return own: handle to the file, not defined if error, error number
2007+can be retrieved with os_file_get_last_error */
2008+os_file_t
2009+xb_file_create_no_error_handling(
2010+/*=============================*/
2011+ const char* name, /*!< in: name of the file or path as a
2012+ null-terminated string */
2013+ ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
2014+ is opened (if does not exist, error), or
2015+ OS_FILE_CREATE if a new file is created
2016+ (if exists, error) */
2017+ ulint access_type,/*!< in: OS_FILE_READ_ONLY,
2018+ OS_FILE_READ_WRITE, or
2019+ OS_FILE_READ_ALLOW_DELETE; the last option is
2020+ used by a backup program reading the file */
2021+ ibool* success)/*!< out: TRUE if succeed, FALSE if error */
2022+{
2023+#if MYSQL_VERSION_ID > 50500
2024+ return os_file_create_simple_no_error_handling(
2025+ 0, /* innodb_file_data_key */
2026+ name, create_mode, access_type, success);
2027+#else
2028+ return os_file_create_simple_no_error_handling(
2029+ name, create_mode, access_type, success);
2030+#endif
2031+}
2032+
2033+/****************************************************************//**
2034+Opens an existing file or creates a new.
2035+@return own: handle to the file, not defined if error, error number
2036+can be retrieved with os_file_get_last_error */
2037+os_file_t
2038+xb_file_create(
2039+/*===========*/
2040+ const char* name, /*!< in: name of the file or path as a
2041+ null-terminated string */
2042+ ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
2043+ is opened (if does not exist, error), or
2044+ OS_FILE_CREATE if a new file is created
2045+ (if exists, error),
2046+ OS_FILE_OVERWRITE if a new file is created
2047+ or an old overwritten;
2048+ OS_FILE_OPEN_RAW, if a raw device or disk
2049+ partition should be opened */
2050+ ulint purpose,/*!< in: OS_FILE_AIO, if asynchronous,
2051+ non-buffered i/o is desired,
2052+ OS_FILE_NORMAL, if any normal file;
2053+ NOTE that it also depends on type, os_aio_..
2054+ and srv_.. variables whether we really use
2055+ async i/o or unbuffered i/o: look in the
2056+ function source code for the exact rules */
2057+ ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
2058+ ibool* success)/*!< out: TRUE if succeed, FALSE if error */
2059+{
2060+#if MYSQL_VERSION_ID > 50500
2061+ return os_file_create(0 /* innodb_file_data_key */,
2062+ name, create_mode, purpose, type, success);
2063+#else
2064+ return os_file_create(name, create_mode, purpose, type, success);
2065+#endif
2066+}
2067+
2068+/***********************************************************************//**
2069+Renames a file (can also move it to another directory). It is safest that the
2070+file is closed before calling this function.
2071+@return TRUE if success */
2072+ibool
2073+xb_file_rename(
2074+/*===========*/
2075+ const char* oldpath,/*!< in: old file path as a null-terminated
2076+ string */
2077+ const char* newpath)/*!< in: new file path */
2078+{
2079+#if MYSQL_VERSION_ID > 50500
2080+ return os_file_rename(
2081+ 0 /* innodb_file_data_key */, oldpath, newpath);
2082+#else
2083+ return os_file_rename(oldpath, newpath);
2084+#endif
2085+}
2086+
2087+void
2088+xb_file_set_nocache(
2089+/*================*/
2090+ os_file_t fd, /* in: file descriptor to alter */
2091+ const char* file_name, /* in: used in the diagnostic message */
2092+ const char* operation_name) /* in: used in the diagnostic message,
2093+ we call os_file_set_nocache()
2094+ immediately after opening or creating
2095+ a file, so this is either "open" or
2096+ "create" */
2097+{
2098+#ifndef __WIN__
2099+ if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
2100+ os_file_set_nocache(fd, file_name, operation_name);
2101+ }
2102+#endif
2103+}
2104+
2105+/***********************************************************************//**
2106+Compatibility wrapper around os_file_flush().
2107+@return TRUE if success */
2108+ibool
2109+xb_file_flush(
2110+/*==========*/
2111+ os_file_t file) /*!< in, own: handle to a file */
2112+{
2113+#ifdef XTRADB_BASED
2114+ return os_file_flush(file, TRUE);
2115+#else
2116+ return os_file_flush(file);
2117+#endif
2118+}
2119+/*******************************************************************//**
2120+Returns the table space by a given id, NULL if not found. */
2121+fil_space_t*
2122+xb_space_get_by_id(
2123+/*================*/
2124+ ulint id) /*!< in: space id */
2125+{
2126+ fil_space_t* space;
2127+
2128+ ut_ad(mutex_own(&fil_system->mutex));
2129+
2130+#ifdef INNODB_VERSION_SHORT
2131+ HASH_SEARCH(hash, fil_system->spaces, id,
2132+ fil_space_t*, space,
2133+ ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
2134+ space->id == id);
2135+#else
2136+ HASH_SEARCH(hash, fil_system->spaces, id, space, space->id == id);
2137+#endif
2138+
2139+ return(space);
2140+}
2141+
2142+/*******************************************************************//**
2143+Returns the table space by a given name, NULL if not found. */
2144+fil_space_t*
2145+xb_space_get_by_name(
2146+/*==================*/
2147+ const char* name) /*!< in: space name */
2148+{
2149+ fil_space_t* space;
2150+ ulint fold;
2151+
2152+ ut_ad(mutex_own(&fil_system->mutex));
2153+
2154+#ifdef INNODB_VERSION_SHORT
2155+ fold = ut_fold_string(name);
2156+ HASH_SEARCH(name_hash, fil_system->name_hash, fold,
2157+ fil_space_t*, space,
2158+ ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
2159+ !strcmp(name, space->name));
2160+#else
2161+ HASH_SEARCH(name_hash, fil_system->name_hash, ut_fold_string(name),
2162+ space, 0 == strcmp(name, space->name));
2163+#endif
2164+
2165+ return(space);
2166+}
2167+
2168+/****************************************************************//**
2169+Create a new tablespace on disk and return the handle to its opened
2170+file. Code adopted from fil_create_new_single_table_tablespace with
2171+the main difference that only disk file is created without updating
2172+the InnoDB in-memory dictionary data structures.
2173+
2174+@return TRUE on success, FALSE on error. */
2175+ibool
2176+xb_space_create_file(
2177+/*==================*/
2178+ const char* path, /*!<in: path to tablespace */
2179+ ulint space_id, /*!<in: space id */
2180+ ulint flags __attribute__((unused)),/*!<in: tablespace
2181+ flags */
2182+ os_file_t* file) /*!<out: file handle */
2183+{
2184+ ibool ret;
2185+ byte* buf;
2186+ byte* page;
2187+
2188+ *file = xb_file_create_no_error_handling(path, OS_FILE_CREATE,
2189+ OS_FILE_READ_WRITE, &ret);
2190+ if (!ret) {
2191+ msg("xtrabackup: cannot create file %s\n", path);
2192+ return ret;
2193+ }
2194+
2195+ ret = os_file_set_size(path, *file,
2196+ FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE, 0);
2197+ if (!ret) {
2198+ msg("xtrabackup: cannot set size for file %s\n", path);
2199+ os_file_close(*file);
2200+ os_file_delete(path);
2201+ return ret;
2202+ }
2203+
2204+ buf = ut_malloc(3 * UNIV_PAGE_SIZE);
2205+ /* Align the memory for file i/o if we might have O_DIRECT set */
2206+ page = ut_align(buf, UNIV_PAGE_SIZE);
2207+
2208+ memset(page, '\0', UNIV_PAGE_SIZE);
2209+
2210+#ifdef INNODB_VERSION_SHORT
2211+ fsp_header_init_fields(page, space_id, flags);
2212+ mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
2213+
2214+ if (!(flags & DICT_TF_ZSSIZE_MASK)) {
2215+ buf_flush_init_for_writing(page, NULL, 0);
2216+
2217+ ret = os_file_write(path, *file, page, 0, 0, UNIV_PAGE_SIZE);
2218+ }
2219+ else {
2220+ page_zip_des_t page_zip;
2221+ ulint zip_size;
2222+
2223+ zip_size = (PAGE_ZIP_MIN_SIZE >> 1)
2224+ << ((flags & DICT_TF_ZSSIZE_MASK)
2225+ >> DICT_TF_ZSSIZE_SHIFT);
2226+ page_zip_set_size(&page_zip, zip_size);
2227+ page_zip.data = page + UNIV_PAGE_SIZE;
2228+ fprintf(stderr, "zip_size = %lu\n", zip_size);
2229+
2230+#ifdef UNIV_DEBUG
2231+ page_zip.m_start =
2232+#endif /* UNIV_DEBUG */
2233+ page_zip.m_end = page_zip.m_nonempty =
2234+ page_zip.n_blobs = 0;
2235+
2236+ buf_flush_init_for_writing(page, &page_zip, 0);
2237+
2238+ ret = os_file_write(path, *file, page_zip.data, 0, 0,
2239+ zip_size);
2240+ }
2241+#else
2242+ fsp_header_write_space_id(page, space_id);
2243+
2244+ buf_flush_init_for_writing(page, ut_dulint_zero, space_id, 0);
2245+
2246+ ret = os_file_write(path, *file, page, 0, 0, UNIV_PAGE_SIZE);
2247+#endif
2248+
2249+ ut_free(buf);
2250+
2251+ if (!ret) {
2252+ msg("xtrabackup: could not write the first page to %s\n",
2253+ path);
2254+ os_file_close(*file);
2255+ os_file_delete(path);
2256+ return ret;
2257+ }
2258+
2259+ return TRUE;
2260+}
2261+
2262+
2263+#ifndef INNODB_VERSION_SHORT
2264+
2265+/********************************************************************//**
2266+Extract the compressed page size from table flags.
2267+@return compressed page size, or 0 if not compressed */
2268+ulint
2269+dict_table_flags_to_zip_size(
2270+/*=========================*/
2271+ ulint flags) /*!< in: flags */
2272+{
2273+ ulint zip_size = flags & DICT_TF_ZSSIZE_MASK;
2274+
2275+ if (UNIV_UNLIKELY(zip_size)) {
2276+ zip_size = ((PAGE_ZIP_MIN_SIZE >> 1)
2277+ << (zip_size >> DICT_TF_ZSSIZE_SHIFT));
2278+
2279+ ut_ad(zip_size <= UNIV_PAGE_SIZE);
2280+ }
2281+
2282+ return(zip_size);
2283+}
2284+
2285+
2286+/*******************************************************************//**
2287+Free all spaces in space_list. */
2288+void
2289+fil_free_all_spaces(void)
2290+/*=====================*/
2291+{
2292+ fil_space_t* space;
2293+
2294+ mutex_enter(&fil_system->mutex);
2295+
2296+ space = UT_LIST_GET_FIRST(fil_system->space_list);
2297+
2298+ while (space != NULL) {
2299+ fil_node_t* node;
2300+ fil_space_t* prev_space = space;
2301+
2302+ space = UT_LIST_GET_NEXT(space_list, space);
2303+
2304+ fil_space_free(prev_space->id, FALSE);
2305+ }
2306+
2307+ mutex_exit(&fil_system->mutex);
2308+}
2309+
2310+#endif
2311+
2312+void
2313+innobase_invalidate_query_cache(
2314+ trx_t* trx,
2315+#ifndef INNODB_VERSION_SHORT
2316+ char* full_name,
2317+#else
2318+ const char* full_name,
2319+#endif
2320+ ulint full_name_len)
2321+{
2322+ (void)trx;
2323+ (void)full_name;
2324+ (void)full_name_len;
2325+ /* do nothing */
2326+}
2327+
2328+int
2329+mysql_get_identifier_quote_char(
2330+ trx_t* trx,
2331+ const char* name,
2332+ ulint namelen)
2333+{
2334+ (void)trx;
2335+ (void)name;
2336+ (void)namelen;
2337+ return '"';
2338+}
2339+
2340+void
2341+innobase_print_identifier(
2342+ FILE* f,
2343+ trx_t* trx __attribute__((unused)),
2344+ ibool table_id __attribute__((unused)),
2345+ const char* name,
2346+ ulint namelen)
2347+{
2348+ const char* s = name;
2349+ const char* e = s + namelen;
2350+ int q;
2351+
2352+ q = '"';
2353+
2354+ putc(q, f);
2355+ while (s < e) {
2356+ int c = *s++;
2357+ if (c == q) {
2358+ putc(c, f);
2359+ }
2360+ putc(c, f);
2361+ }
2362+ putc(q, f);
2363+}
2364+
2365+/**********************************************************************//**
2366+It should be safe to use lower_case_table_names=0 for xtrabackup. If it causes
2367+any problems, we can add the lower_case_table_names option to xtrabackup
2368+later.
2369+@return 0 */
2370+ulint
2371+innobase_get_lower_case_table_names(void)
2372+/*=====================================*/
2373+{
2374+ return(0);
2375+}
2376+
2377+/******************************************************************//**
2378+Strip dir name from a full path name and return only the file name
2379+@return file name or "null" if no file name */
2380+const char*
2381+innobase_basename(
2382+/*==============*/
2383+ const char* path_name) /*!< in: full path name */
2384+{
2385+ const char* name = base_name(path_name);
2386+
2387+ return((name) ? name : "null");
2388+}
2389+
2390+/*****************************************************************//**
2391+Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
2392+and quote it if needed.
2393+@return pointer to the end of buf */
2394+static
2395+char*
2396+innobase_convert_identifier(
2397+/*========================*/
2398+ char* buf, /*!< out: buffer for converted identifier */
2399+ ulint buflen, /*!< in: length of buf, in bytes */
2400+ const char* id, /*!< in: identifier to convert */
2401+ ulint idlen, /*!< in: length of id, in bytes */
2402+ void* thd __attribute__((unused)),
2403+ /*!< in: MySQL connection thread, or NULL */
2404+ ibool file_id __attribute__((unused)))
2405+ /*!< in: TRUE=id is a table or database name;
2406+ FALSE=id is an UTF-8 string */
2407+{
2408+ const char* s = id;
2409+ int q;
2410+
2411+ /* See if the identifier needs to be quoted. */
2412+ q = '"';
2413+
2414+ if (q == EOF) {
2415+ if (UNIV_UNLIKELY(idlen > buflen)) {
2416+ idlen = buflen;
2417+ }
2418+ memcpy(buf, s, idlen);
2419+ return(buf + idlen);
2420+ }
2421+
2422+ /* Quote the identifier. */
2423+ if (buflen < 2) {
2424+ return(buf);
2425+ }
2426+
2427+ *buf++ = q;
2428+ buflen--;
2429+
2430+ for (; idlen; idlen--) {
2431+ int c = *s++;
2432+ if (UNIV_UNLIKELY(c == q)) {
2433+ if (UNIV_UNLIKELY(buflen < 3)) {
2434+ break;
2435+ }
2436+
2437+ *buf++ = c;
2438+ *buf++ = c;
2439+ buflen -= 2;
2440+ } else {
2441+ if (UNIV_UNLIKELY(buflen < 2)) {
2442+ break;
2443+ }
2444+
2445+ *buf++ = c;
2446+ buflen--;
2447+ }
2448+ }
2449+
2450+ *buf++ = q;
2451+ return(buf);
2452+}
2453+
2454+/*****************************************************************//**
2455+Convert a table or index name to the MySQL system_charset_info (UTF-8)
2456+and quote it if needed.
2457+@return pointer to the end of buf */
2458+char*
2459+innobase_convert_name(
2460+/*==================*/
2461+ char* buf, /*!< out: buffer for converted identifier */
2462+ ulint buflen, /*!< in: length of buf, in bytes */
2463+ const char* id, /*!< in: identifier to convert */
2464+ ulint idlen, /*!< in: length of id, in bytes */
2465+ void* thd, /*!< in: MySQL connection thread, or NULL */
2466+ ibool table_id)/*!< in: TRUE=id is a table or database name;
2467+ FALSE=id is an index name */
2468+{
2469+ char* s = buf;
2470+ const char* bufend = buf + buflen;
2471+
2472+ if (table_id) {
2473+ const char* slash = (const char*) memchr(id, '/', idlen);
2474+ if (!slash) {
2475+
2476+ goto no_db_name;
2477+ }
2478+
2479+ /* Print the database name and table name separately. */
2480+ s = innobase_convert_identifier(s, bufend - s, id, slash - id,
2481+ thd, TRUE);
2482+ if (UNIV_LIKELY(s < bufend)) {
2483+ *s++ = '.';
2484+ s = innobase_convert_identifier(s, bufend - s,
2485+ slash + 1, idlen
2486+ - (slash - id) - 1,
2487+ thd, TRUE);
2488+ }
2489+#ifdef INNODB_VERSION_SHORT
2490+ } else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
2491+ /* Temporary index name (smart ALTER TABLE) */
2492+ const char temp_index_suffix[]= "--temporary--";
2493+
2494+ s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
2495+ thd, FALSE);
2496+ if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
2497+ memcpy(s, temp_index_suffix,
2498+ sizeof temp_index_suffix - 1);
2499+ s += sizeof temp_index_suffix - 1;
2500+ }
2501+#endif
2502+ } else {
2503+no_db_name:
2504+ s = innobase_convert_identifier(buf, buflen, id, idlen,
2505+ thd, table_id);
2506+ }
2507+
2508+ return(s);
2509+
2510+}
2511+
2512+ibool
2513+trx_is_interrupted(
2514+ trx_t* trx)
2515+{
2516+ (void)trx;
2517+ /* There are no mysql_thd */
2518+ return(FALSE);
2519+}
2520+
2521+int
2522+innobase_mysql_cmp(
2523+ int mysql_type,
2524+ uint charset_number,
2525+ unsigned char* a,
2526+ unsigned int a_length,
2527+ unsigned char* b,
2528+ unsigned int b_length)
2529+{
2530+ CHARSET_INFO* charset;
2531+ enum enum_field_types mysql_tp;
2532+ int ret;
2533+
2534+ DBUG_ASSERT(a_length != UNIV_SQL_NULL);
2535+ DBUG_ASSERT(b_length != UNIV_SQL_NULL);
2536+
2537+ mysql_tp = (enum enum_field_types) mysql_type;
2538+
2539+ switch (mysql_tp) {
2540+
2541+ case MYSQL_TYPE_BIT:
2542+ case MYSQL_TYPE_STRING:
2543+ case MYSQL_TYPE_VAR_STRING:
2544+ case FIELD_TYPE_TINY_BLOB:
2545+ case FIELD_TYPE_MEDIUM_BLOB:
2546+ case FIELD_TYPE_BLOB:
2547+ case FIELD_TYPE_LONG_BLOB:
2548+ case MYSQL_TYPE_VARCHAR:
2549+ /* Use the charset number to pick the right charset struct for
2550+ the comparison. Since the MySQL function get_charset may be
2551+ slow before Bar removes the mutex operation there, we first
2552+ look at 2 common charsets directly. */
2553+
2554+ if (charset_number == default_charset_info->number) {
2555+ charset = default_charset_info;
2556+ } else if (charset_number == my_charset_latin1.number) {
2557+ charset = &my_charset_latin1;
2558+ } else {
2559+ charset = get_charset(charset_number, MYF(MY_WME));
2560+
2561+ if (charset == NULL) {
2562+ msg("xtrabackup: InnoDB needs charset %lu for "
2563+ "doing a comparison, but MySQL cannot "
2564+ "find that charset.\n",
2565+ (ulong) charset_number);
2566+ ut_a(0);
2567+ }
2568+ }
2569+
2570+ /* Starting from 4.1.3, we use strnncollsp() in comparisons of
2571+ non-latin1_swedish_ci strings. NOTE that the collation order
2572+ changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
2573+ having indexes on such data need to rebuild their tables! */
2574+
2575+ ret = charset->coll->strnncollsp(charset,
2576+ a, a_length,
2577+ b, b_length, 0);
2578+ if (ret < 0) {
2579+ return(-1);
2580+ } else if (ret > 0) {
2581+ return(1);
2582+ } else {
2583+ return(0);
2584+ }
2585+ default:
2586+ assert(0);
2587+ }
2588+
2589+ return(0);
2590+}
2591+
2592+ulint
2593+innobase_get_at_most_n_mbchars(
2594+ ulint charset_id,
2595+ ulint prefix_len,
2596+ ulint data_len,
2597+ const char* str)
2598+{
2599+ ulint char_length; /* character length in bytes */
2600+ ulint n_chars; /* number of characters in prefix */
2601+ CHARSET_INFO* charset; /* charset used in the field */
2602+
2603+ charset = get_charset((uint) charset_id, MYF(MY_WME));
2604+
2605+ ut_ad(charset);
2606+ ut_ad(charset->mbmaxlen);
2607+
2608+ /* Calculate how many characters at most the prefix index contains */
2609+
2610+ n_chars = prefix_len / charset->mbmaxlen;
2611+
2612+ /* If the charset is multi-byte, then we must find the length of the
2613+ first at most n chars in the string. If the string contains less
2614+ characters than n, then we return the length to the end of the last
2615+ character. */
2616+
2617+ if (charset->mbmaxlen > 1) {
2618+ /* my_charpos() returns the byte length of the first n_chars
2619+ characters, or a value bigger than the length of str, if
2620+ there were not enough full characters in str.
2621+
2622+ Why does the code below work:
2623+ Suppose that we are looking for n UTF-8 characters.
2624+
2625+ 1) If the string is long enough, then the prefix contains at
2626+ least n complete UTF-8 characters + maybe some extra
2627+ characters + an incomplete UTF-8 character. No problem in
2628+ this case. The function returns the pointer to the
2629+ end of the nth character.
2630+
2631+ 2) If the string is not long enough, then the string contains
2632+ the complete value of a column, that is, only complete UTF-8
2633+ characters, and we can store in the column prefix index the
2634+ whole string. */
2635+
2636+ char_length = my_charpos(charset, str,
2637+ str + data_len, (int) n_chars);
2638+ if (char_length > data_len) {
2639+ char_length = data_len;
2640+ }
2641+ } else {
2642+ if (data_len < prefix_len) {
2643+ char_length = data_len;
2644+ } else {
2645+ char_length = prefix_len;
2646+ }
2647+ }
2648+
2649+ return(char_length);
2650+}
2651+
2652+ibool
2653+innobase_query_is_update(void)
2654+{
2655+ msg("xtrabackup: innobase_query_is_update() is called\n");
2656+ return(0);
2657+}
2658+
2659+#ifdef INNODB_VERSION_SHORT
2660+ulint
2661+innobase_raw_format(
2662+/*================*/
2663+ const char* data, /*!< in: raw data */
2664+ ulint data_len, /*!< in: raw data length
2665+ in bytes */
2666+ ulint charset_coll, /*!< in: charset collation */
2667+ char* buf, /*!< out: output buffer */
2668+ ulint buf_size) /*!< in: output buffer size
2669+ in bytes */
2670+{
2671+ (void)data;
2672+ (void)data_len;
2673+ (void)charset_coll;
2674+ (void)buf;
2675+ (void)buf_size;
2676+
2677+ msg("xtrabackup: innobase_raw_format() is called\n");
2678+ return(0);
2679+}
2680+
2681+ulong
2682+thd_lock_wait_timeout(
2683+/*==================*/
2684+ void* thd) /*!< in: thread handle (THD*), or NULL to query
2685+ the global innodb_lock_wait_timeout */
2686+{
2687+ (void)thd;
2688+ return(innobase_lock_wait_timeout);
2689+}
2690+
2691+ibool
2692+thd_supports_xa(
2693+/*============*/
2694+ void* thd) /*!< in: thread handle (THD*), or NULL to query
2695+ the global innodb_supports_xa */
2696+{
2697+ (void)thd;
2698+ return(FALSE);
2699+}
2700+
2701+ibool
2702+trx_is_strict(
2703+/*==========*/
2704+ trx_t* trx) /*!< in: transaction */
2705+{
2706+ (void)trx;
2707+ return(FALSE);
2708+}
2709+
2710+#ifdef XTRADB_BASED
2711+trx_t*
2712+innobase_get_trx()
2713+{
2714+ return(NULL);
2715+}
2716+
2717+ibool
2718+innobase_get_slow_log()
2719+{
2720+ return(FALSE);
2721+}
2722+#endif
2723+#endif
2724+
2725+ibool
2726+thd_is_replication_slave_thread(
2727+ void* thd)
2728+{
2729+ (void)thd;
2730+ msg("xtrabackup: thd_is_replication_slave_thread() is called\n");
2731+ return(FALSE);
2732+}
2733+
2734+ibool
2735+thd_has_edited_nontrans_tables(
2736+ void* thd)
2737+{
2738+ (void)thd;
2739+ msg("xtrabackup: thd_has_edited_nontrans_tables() is called\n");
2740+ return(FALSE);
2741+}
2742+
2743+ibool
2744+thd_is_select(
2745+ const void* thd)
2746+{
2747+ (void)thd;
2748+ msg("xtrabackup: thd_is_select() is called\n");
2749+ return(FALSE);
2750+}
2751+
2752+void
2753+innobase_mysql_prepare_print_arbitrary_thd(void)
2754+{
2755+ /* do nothing */
2756+}
2757+
2758+void
2759+innobase_mysql_end_print_arbitrary_thd(void)
2760+{
2761+ /* do nothing */
2762+}
2763+
2764+void
2765+innobase_mysql_print_thd(
2766+ FILE* f,
2767+ void* input_thd,
2768+ uint max_query_len)
2769+{
2770+ (void)f;
2771+ (void)input_thd;
2772+ (void)max_query_len;
2773+ msg("xtrabackup: innobase_mysql_print_thd() is called\n");
2774+}
2775+
2776+void
2777+innobase_get_cset_width(
2778+ ulint cset,
2779+ ulint* mbminlen,
2780+ ulint* mbmaxlen)
2781+{
2782+ CHARSET_INFO* cs;
2783+ ut_ad(cset < 256);
2784+ ut_ad(mbminlen);
2785+ ut_ad(mbmaxlen);
2786+
2787+ cs = all_charsets[cset];
2788+ if (cs) {
2789+ *mbminlen = cs->mbminlen;
2790+ *mbmaxlen = cs->mbmaxlen;
2791+ } else {
2792+ ut_a(cset == 0);
2793+ *mbminlen = *mbmaxlen = 0;
2794+ }
2795+}
2796+
2797+void
2798+innobase_convert_from_table_id(
2799+#ifdef INNODB_VERSION_SHORT
2800+ struct charset_info_st* cs,
2801+#endif
2802+ char* to,
2803+ const char* from,
2804+ ulint len)
2805+{
2806+#ifdef INNODB_VERSION_SHORT
2807+ (void)cs;
2808+#endif
2809+ (void)to;
2810+ (void)from;
2811+ (void)len;
2812+
2813+ msg("xtrabackup: innobase_convert_from_table_id() is called\n");
2814+}
2815+
2816+void
2817+innobase_convert_from_id(
2818+#ifdef INNODB_VERSION_SHORT
2819+ struct charset_info_st* cs,
2820+#endif
2821+ char* to,
2822+ const char* from,
2823+ ulint len)
2824+{
2825+#ifdef INNODB_VERSION_SHORT
2826+ (void)cs;
2827+#endif
2828+ (void)to;
2829+ (void)from;
2830+ (void)len;
2831+ msg("xtrabackup: innobase_convert_from_id() is called\n");
2832+}
2833+
2834+int
2835+innobase_strcasecmp(
2836+ const char* a,
2837+ const char* b)
2838+{
2839+ return(my_strcasecmp(&my_charset_utf8_general_ci, a, b));
2840+}
2841+
2842+void
2843+innobase_casedn_str(
2844+ char* a)
2845+{
2846+ my_casedn_str(&my_charset_utf8_general_ci, a);
2847+}
2848+
2849+struct charset_info_st*
2850+innobase_get_charset(
2851+ void* mysql_thd)
2852+{
2853+ (void)mysql_thd;
2854+ msg("xtrabackup: innobase_get_charset() is called\n");
2855+ return(NULL);
2856+}
2857+
2858+const char*
2859+innobase_get_stmt(
2860+ void* mysql_thd,
2861+ size_t* length)
2862+{
2863+ (void)mysql_thd;
2864+ (void)length;
2865+ msg("xtrabackup: innobase_get_stmt() is called\n");
2866+ return("nothing");
2867+}
2868+
2869+int
2870+innobase_mysql_tmpfile(void)
2871+{
2872+ char filename[FN_REFLEN];
2873+ int fd2 = -1;
2874+ File fd = create_temp_file(filename, my_tmpdir(&mysql_tmpdir_list), "ib",
2875+#ifdef __WIN__
2876+ O_BINARY | O_TRUNC | O_SEQUENTIAL |
2877+ O_TEMPORARY | O_SHORT_LIVED |
2878+#endif /* __WIN__ */
2879+ O_CREAT | O_EXCL | O_RDWR,
2880+ MYF(MY_WME));
2881+ if (fd >= 0) {
2882+#ifndef __WIN__
2883+ /* On Windows, open files cannot be removed, but files can be
2884+ created with the O_TEMPORARY flag to the same effect
2885+ ("delete on close"). */
2886+ unlink(filename);
2887+#endif /* !__WIN__ */
2888+ /* Copy the file descriptor, so that the additional resources
2889+ allocated by create_temp_file() can be freed by invoking
2890+ my_close().
2891+
2892+ Because the file descriptor returned by this function
2893+ will be passed to fdopen(), it will be closed by invoking
2894+ fclose(), which in turn will invoke close() instead of
2895+ my_close(). */
2896+#ifdef _WIN32
2897+ /* Note that on Windows, the integer returned by mysql_tmpfile
2898+ has no relation to C runtime file descriptor. Here, we need
2899+ to call my_get_osfhandle to get the HANDLE and then convert it
2900+ to C runtime filedescriptor. */
2901+ {
2902+ HANDLE hFile = my_get_osfhandle(fd);
2903+ HANDLE hDup;
2904+ BOOL bOK =
2905+ DuplicateHandle(GetCurrentProcess(), hFile,
2906+ GetCurrentProcess(), &hDup, 0,
2907+ FALSE, DUPLICATE_SAME_ACCESS);
2908+ if(bOK) {
2909+ fd2 = _open_osfhandle((intptr_t)hDup,0);
2910+ }
2911+ else {
2912+ my_osmaperr(GetLastError());
2913+ fd2 = -1;
2914+ }
2915+ }
2916+#else
2917+ fd2 = dup(fd);
2918+#endif
2919+ if (fd2 < 0) {
2920+ msg("xtrabackup: Got error %d on dup\n",fd2);
2921+ }
2922+ my_close(fd, MYF(MY_WME));
2923+ }
2924+ return(fd2);
2925+}
2926+
2927+#if MYSQL_VERSION_ID >= 50507
2928+/*
2929+ As of MySQL 5.5.7, InnoDB uses thd_wait plugin service.
2930+ We have to provide mock functions to avoid linker errors.
2931+*/
2932+#include <mysql/plugin.h>
2933+#include <mysql/service_thd_wait.h>
2934+
2935+void thd_wait_begin(MYSQL_THD thd, int wait_type)
2936+{
2937+ (void)thd;
2938+ (void)wait_type;
2939+ return;
2940+}
2941+
2942+void thd_wait_end(MYSQL_THD thd)
2943+{
2944+ (void)thd;
2945+ return;
2946+}
2947+
2948+#endif /* MYSQL_VERSION_ID >= 50507 */
2949
2950=== added file 'src/innodb_int.h'
2951--- src/innodb_int.h 1970-01-01 00:00:00 +0000
2952+++ src/innodb_int.h 2012-10-18 11:58:23 +0000
2953@@ -0,0 +1,695 @@
2954+/******************************************************
2955+XtraBackup: hot backup tool for InnoDB
2956+(c) 2009-2012 Percona Inc.
2957+Originally Created 3/3/2009 Yasufumi Kinoshita
2958+Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
2959+Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
2960+
2961+This program is free software; you can redistribute it and/or modify
2962+it under the terms of the GNU General Public License as published by
2963+the Free Software Foundation; version 2 of the License.
2964+
2965+This program is distributed in the hope that it will be useful,
2966+but WITHOUT ANY WARRANTY; without even the implied warranty of
2967+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2968+GNU General Public License for more details.
2969+
2970+You should have received a copy of the GNU General Public License
2971+along with this program; if not, write to the Free Software
2972+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2973+
2974+*******************************************************/
2975+
2976+/* InnoDB portability helpers and interface to internal functions */
2977+
2978+#ifndef INNODB_INT_H
2979+#define INNODB_INT_H
2980+
2981+#include <my_base.h>
2982+#include <univ.i>
2983+#include <fil0fil.h>
2984+#include <os0file.h>
2985+#include <hash0hash.h>
2986+#include <btr0sea.h>
2987+#include <log0log.h>
2988+#include <log0recv.h>
2989+#include <trx0sys.h>
2990+
2991+#ifndef INNODB_VERSION_SHORT
2992+# define IB_INT64 ib_longlong
2993+# define LSN64 dulint
2994+# define MACH_READ_64 mach_read_from_8
2995+# define MACH_WRITE_64 mach_write_to_8
2996+# define OS_MUTEX_CREATE() os_mutex_create(NULL)
2997+# define xb_buf_page_is_corrupted(page, zip_size) buf_page_is_corrupted(page)
2998+# define xb_fil_space_create(name, space_id, zip_size, purpose) \
2999+ fil_space_create(name, space_id, purpose)
3000+# define PAGE_ZIP_MIN_SIZE_SHIFT 10
3001+# define PAGE_ZIP_MIN_SIZE (1 << PAGE_ZIP_MIN_SIZE_SHIFT)
3002+# define DICT_TF_ZSSIZE_SHIFT 1
3003+# define DICT_TF_ZSSIZE_MASK (15 << DICT_TF_ZSSIZE_SHIFT)
3004+# define DICT_TF_FORMAT_ZIP 1
3005+# define DICT_TF_FORMAT_SHIFT 5
3006+# define SRV_SHUTDOWN_NONE 0
3007+#else
3008+# define IB_INT64 ib_int64_t
3009+# define LSN64 ib_uint64_t
3010+# if (MYSQL_VERSION_ID < 50500)
3011+# define MACH_READ_64 mach_read_ull
3012+# define MACH_WRITE_64 mach_write_ull
3013+# define OS_MUTEX_CREATE() os_mutex_create(NULL)
3014+# else
3015+# define MACH_READ_64 mach_read_from_8
3016+# define MACH_WRITE_64 mach_write_to_8
3017+# define OS_MUTEX_CREATE() os_mutex_create()
3018+# endif
3019+# define xb_buf_page_is_corrupted(page, zip_size) \
3020+ buf_page_is_corrupted(page, zip_size)
3021+# define xb_fil_space_create(name, space_id, zip_size, purpose) \
3022+ fil_space_create(name, space_id, zip_size, purpose)
3023+# define ut_dulint_zero 0
3024+# define ut_dulint_cmp(A, B) (A > B ? 1 : (A == B ? 0 : -1))
3025+# define ut_dulint_add(A, B) (A + B)
3026+# define ut_dulint_minus(A, B) (A - B)
3027+# define ut_dulint_align_down(A, B) (A & ~((ib_int64_t)B - 1))
3028+# define ut_dulint_align_up(A, B) ((A + B - 1) & ~((ib_int64_t)B - 1))
3029+#endif
3030+
3031+#ifndef XTRADB_BASED
3032+#define trx_sys_sys_space(id) (id == 0)
3033+#endif
3034+
3035+#ifdef __WIN__
3036+#define SRV_PATH_SEPARATOR '\\'
3037+#define SRV_PATH_SEPARATOR_STR "\\"
3038+#else
3039+#define SRV_PATH_SEPARATOR '/'
3040+#define SRV_PATH_SEPARATOR_STR "/"
3041+#endif
3042+
3043+#ifndef UNIV_PAGE_SIZE_MAX
3044+#define UNIV_PAGE_SIZE_MAX UNIV_PAGE_SIZE
3045+#endif
3046+#ifndef UNIV_PAGE_SIZE_SHIFT_MAX
3047+#define UNIV_PAGE_SIZE_SHIFT_MAX UNIV_PAGE_SIZE_SHIFT
3048+#endif
3049+
3050+#ifdef __WIN__
3051+#define XB_FILE_UNDEFINED NULL
3052+#else
3053+#define XB_FILE_UNDEFINED (-1)
3054+#endif
3055+
3056+#ifdef INNODB_VERSION_SHORT
3057+#define XB_HASH_SEARCH(NAME, TABLE, FOLD, DATA, ASSERTION, TEST) \
3058+ HASH_SEARCH(NAME, TABLE, FOLD, xtrabackup_tables_t*, DATA, ASSERTION, \
3059+ TEST)
3060+#else
3061+#define XB_HASH_SEARCH(NAME, TABLE, FOLD, DATA, ASSERTION, TEST) \
3062+ HASH_SEARCH(NAME, TABLE, FOLD, DATA, TEST)
3063+#endif
3064+
3065+/* ==start === definition at fil0fil.c === */
3066+// ##################################################################
3067+// NOTE: We should check the following definitions fit to the source.
3068+// ##################################################################
3069+
3070+#ifndef INNODB_VERSION_SHORT
3071+//5.0 5.1
3072+/* File node of a tablespace or the log data space */
3073+struct fil_node_struct {
3074+ fil_space_t* space; /* backpointer to the space where this node
3075+ belongs */
3076+ char* name; /* path to the file */
3077+ ibool open; /* TRUE if file open */
3078+ os_file_t handle; /* OS handle to the file, if file open */
3079+ ibool is_raw_disk;/* TRUE if the 'file' is actually a raw
3080+ device or a raw disk partition */
3081+ ulint size; /* size of the file in database pages, 0 if
3082+ not known yet; the possible last incomplete
3083+ megabyte may be ignored if space == 0 */
3084+ ulint n_pending;
3085+ /* count of pending i/o's on this file;
3086+ closing of the file is not allowed if
3087+ this is > 0 */
3088+ ulint n_pending_flushes;
3089+ /* count of pending flushes on this file;
3090+ closing of the file is not allowed if
3091+ this is > 0 */
3092+ ib_longlong modification_counter;/* when we write to the file we
3093+ increment this by one */
3094+ ib_longlong flush_counter;/* up to what modification_counter value
3095+ we have flushed the modifications to disk */
3096+ UT_LIST_NODE_T(fil_node_t) chain;
3097+ /* link field for the file chain */
3098+ UT_LIST_NODE_T(fil_node_t) LRU;
3099+ /* link field for the LRU list */
3100+ ulint magic_n;
3101+};
3102+
3103+struct fil_space_struct {
3104+ char* name; /* space name = the path to the first file in
3105+ it */
3106+ ulint id; /* space id */
3107+ ib_longlong tablespace_version;
3108+ /* in DISCARD/IMPORT this timestamp is used to
3109+ check if we should ignore an insert buffer
3110+ merge request for a page because it actually
3111+ was for the previous incarnation of the
3112+ space */
3113+ ibool mark; /* this is set to TRUE at database startup if
3114+ the space corresponds to a table in the InnoDB
3115+ data dictionary; so we can print a warning of
3116+ orphaned tablespaces */
3117+ ibool stop_ios;/* TRUE if we want to rename the .ibd file of
3118+ tablespace and want to stop temporarily
3119+ posting of new i/o requests on the file */
3120+ ibool stop_ibuf_merges;
3121+ /* we set this TRUE when we start deleting a
3122+ single-table tablespace */
3123+ ibool is_being_deleted;
3124+ /* this is set to TRUE when we start
3125+ deleting a single-table tablespace and its
3126+ file; when this flag is set no further i/o
3127+ or flush requests can be placed on this space,
3128+ though there may be such requests still being
3129+ processed on this space */
3130+ ulint purpose;/* FIL_TABLESPACE, FIL_LOG, or FIL_ARCH_LOG */
3131+ UT_LIST_BASE_NODE_T(fil_node_t) chain;
3132+ /* base node for the file chain */
3133+ ulint size; /* space size in pages; 0 if a single-table
3134+ tablespace whose size we do not know yet;
3135+ last incomplete megabytes in data files may be
3136+ ignored if space == 0 */
3137+ ulint n_reserved_extents;
3138+ /* number of reserved free extents for
3139+ ongoing operations like B-tree page split */
3140+ ulint n_pending_flushes; /* this is > 0 when flushing
3141+ the tablespace to disk; dropping of the
3142+ tablespace is forbidden if this is > 0 */
3143+ ulint n_pending_ibuf_merges;/* this is > 0 when merging
3144+ insert buffer entries to a page so that we
3145+ may need to access the ibuf bitmap page in the
3146+ tablespade: dropping of the tablespace is
3147+ forbidden if this is > 0 */
3148+ hash_node_t hash; /* hash chain node */
3149+ hash_node_t name_hash;/* hash chain the name_hash table */
3150+ rw_lock_t latch; /* latch protecting the file space storage
3151+ allocation */
3152+ UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
3153+ /* list of spaces with at least one unflushed
3154+ file we have written to */
3155+ ibool is_in_unflushed_spaces; /* TRUE if this space is
3156+ currently in the list above */
3157+ UT_LIST_NODE_T(fil_space_t) space_list;
3158+ /* list of all spaces */
3159+ ibuf_data_t* ibuf_data;
3160+ /* insert buffer data */
3161+ ulint magic_n;
3162+};
3163+typedef struct fil_system_struct fil_system_t;
3164+struct fil_system_struct {
3165+ mutex_t mutex; /* The mutex protecting the cache */
3166+ hash_table_t* spaces; /* The hash table of spaces in the
3167+ system; they are hashed on the space
3168+ id */
3169+ hash_table_t* name_hash; /* hash table based on the space
3170+ name */
3171+ UT_LIST_BASE_NODE_T(fil_node_t) LRU;
3172+ /* base node for the LRU list of the
3173+ most recently used open files with no
3174+ pending i/o's; if we start an i/o on
3175+ the file, we first remove it from this
3176+ list, and return it to the start of
3177+ the list when the i/o ends;
3178+ log files and the system tablespace are
3179+ not put to this list: they are opened
3180+ after the startup, and kept open until
3181+ shutdown */
3182+ UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
3183+ /* base node for the list of those
3184+ tablespaces whose files contain
3185+ unflushed writes; those spaces have
3186+ at least one file node where
3187+ modification_counter > flush_counter */
3188+ ulint n_open; /* number of files currently open */
3189+ ulint max_n_open; /* n_open is not allowed to exceed
3190+ this */
3191+ ib_longlong modification_counter;/* when we write to a file we
3192+ increment this by one */
3193+ ulint max_assigned_id;/* maximum space id in the existing
3194+ tables, or assigned during the time
3195+ mysqld has been up; at an InnoDB
3196+ startup we scan the data dictionary
3197+ and set here the maximum of the
3198+ space id's of the tables there */
3199+ ib_longlong tablespace_version;
3200+ /* a counter which is incremented for
3201+ every space object memory creation;
3202+ every space mem object gets a
3203+ 'timestamp' from this; in DISCARD/
3204+ IMPORT this is used to check if we
3205+ should ignore an insert buffer merge
3206+ request */
3207+ UT_LIST_BASE_NODE_T(fil_space_t) space_list;
3208+ /* list of all file spaces */
3209+};
3210+#else
3211+//Plugin ?
3212+/** File node of a tablespace or the log data space */
3213+struct fil_node_struct {
3214+ fil_space_t* space; /*!< backpointer to the space where this node
3215+ belongs */
3216+ char* name; /*!< path to the file */
3217+ ibool open; /*!< TRUE if file open */
3218+ os_file_t handle; /*!< OS handle to the file, if file open */
3219+ ibool is_raw_disk;/*!< TRUE if the 'file' is actually a raw
3220+ device or a raw disk partition */
3221+ ulint size; /*!< size of the file in database pages, 0 if
3222+ not known yet; the possible last incomplete
3223+ megabyte may be ignored if space == 0 */
3224+ ulint n_pending;
3225+ /*!< count of pending i/o's on this file;
3226+ closing of the file is not allowed if
3227+ this is > 0 */
3228+ ulint n_pending_flushes;
3229+ /*!< count of pending flushes on this file;
3230+ closing of the file is not allowed if
3231+ this is > 0 */
3232+ ib_int64_t modification_counter;/*!< when we write to the file we
3233+ increment this by one */
3234+ ib_int64_t flush_counter;/*!< up to what
3235+ modification_counter value we have
3236+ flushed the modifications to disk */
3237+ UT_LIST_NODE_T(fil_node_t) chain;
3238+ /*!< link field for the file chain */
3239+ UT_LIST_NODE_T(fil_node_t) LRU;
3240+ /*!< link field for the LRU list */
3241+ ulint magic_n;/*!< FIL_NODE_MAGIC_N */
3242+};
3243+
3244+struct fil_space_struct {
3245+ char* name; /*!< space name = the path to the first file in
3246+ it */
3247+ ulint id; /*!< space id */
3248+ ib_int64_t tablespace_version;
3249+ /*!< in DISCARD/IMPORT this timestamp
3250+ is used to check if we should ignore
3251+ an insert buffer merge request for a
3252+ page because it actually was for the
3253+ previous incarnation of the space */
3254+ ibool mark; /*!< this is set to TRUE at database startup if
3255+ the space corresponds to a table in the InnoDB
3256+ data dictionary; so we can print a warning of
3257+ orphaned tablespaces */
3258+ ibool stop_ios;/*!< TRUE if we want to rename the
3259+ .ibd file of tablespace and want to
3260+ stop temporarily posting of new i/o
3261+ requests on the file */
3262+ ibool stop_ibuf_merges;
3263+ /*!< we set this TRUE when we start
3264+ deleting a single-table tablespace */
3265+ ibool is_being_deleted;
3266+ /*!< this is set to TRUE when we start
3267+ deleting a single-table tablespace and its
3268+ file; when this flag is set no further i/o
3269+ or flush requests can be placed on this space,
3270+ though there may be such requests still being
3271+ processed on this space */
3272+ ulint purpose;/*!< FIL_TABLESPACE, FIL_LOG, or
3273+ FIL_ARCH_LOG */
3274+ UT_LIST_BASE_NODE_T(fil_node_t) chain;
3275+ /*!< base node for the file chain */
3276+ ulint size; /*!< space size in pages; 0 if a single-table
3277+ tablespace whose size we do not know yet;
3278+ last incomplete megabytes in data files may be
3279+ ignored if space == 0 */
3280+ ulint flags; /*!< compressed page size and file format, or 0
3281+ */
3282+ ulint n_reserved_extents;
3283+ /*!< number of reserved free extents for
3284+ ongoing operations like B-tree page split */
3285+ ulint n_pending_flushes; /*!< this is positive when flushing
3286+ the tablespace to disk; dropping of the
3287+ tablespace is forbidden if this is positive */
3288+ ulint n_pending_ibuf_merges;/*!< this is positive
3289+ when merging insert buffer entries to
3290+ a page so that we may need to access
3291+ the ibuf bitmap page in the
3292+ tablespade: dropping of the tablespace
3293+ is forbidden if this is positive */
3294+ hash_node_t hash; /*!< hash chain node */
3295+ hash_node_t name_hash;/*!< hash chain the name_hash table */
3296+#ifndef UNIV_HOTBACKUP
3297+ rw_lock_t latch; /*!< latch protecting the file space storage
3298+ allocation */
3299+#endif /* !UNIV_HOTBACKUP */
3300+ UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
3301+ /*!< list of spaces with at least one unflushed
3302+ file we have written to */
3303+ ibool is_in_unflushed_spaces; /*!< TRUE if this space is
3304+ currently in unflushed_spaces */
3305+#ifdef XTRADB_BASED
3306+ ibool is_corrupt;
3307+#endif
3308+ UT_LIST_NODE_T(fil_space_t) space_list;
3309+ /*!< list of all spaces */
3310+ ulint magic_n;/*!< FIL_SPACE_MAGIC_N */
3311+};
3312+
3313+typedef struct fil_system_struct fil_system_t;
3314+
3315+struct fil_system_struct {
3316+#ifndef UNIV_HOTBACKUP
3317+ mutex_t mutex; /*!< The mutex protecting the cache */
3318+#ifdef XTRADB_BASED
3319+ mutex_t file_extend_mutex;
3320+#endif
3321+#endif /* !UNIV_HOTBACKUP */
3322+ hash_table_t* spaces; /*!< The hash table of spaces in the
3323+ system; they are hashed on the space
3324+ id */
3325+ hash_table_t* name_hash; /*!< hash table based on the space
3326+ name */
3327+ UT_LIST_BASE_NODE_T(fil_node_t) LRU;
3328+ /*!< base node for the LRU list of the
3329+ most recently used open files with no
3330+ pending i/o's; if we start an i/o on
3331+ the file, we first remove it from this
3332+ list, and return it to the start of
3333+ the list when the i/o ends;
3334+ log files and the system tablespace are
3335+ not put to this list: they are opened
3336+ after the startup, and kept open until
3337+ shutdown */
3338+ UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
3339+ /*!< base node for the list of those
3340+ tablespaces whose files contain
3341+ unflushed writes; those spaces have
3342+ at least one file node where
3343+ modification_counter > flush_counter */
3344+ ulint n_open; /*!< number of files currently open */
3345+ ulint max_n_open; /*!< n_open is not allowed to exceed
3346+ this */
3347+ ib_int64_t modification_counter;/*!< when we write to a file we
3348+ increment this by one */
3349+ ulint max_assigned_id;/*!< maximum space id in the existing
3350+ tables, or assigned during the time
3351+ mysqld has been up; at an InnoDB
3352+ startup we scan the data dictionary
3353+ and set here the maximum of the
3354+ space id's of the tables there */
3355+ ib_int64_t tablespace_version;
3356+ /*!< a counter which is incremented for
3357+ every space object memory creation;
3358+ every space mem object gets a
3359+ 'timestamp' from this; in DISCARD/
3360+ IMPORT this is used to check if we
3361+ should ignore an insert buffer merge
3362+ request */
3363+ UT_LIST_BASE_NODE_T(fil_space_t) space_list;
3364+ /*!< list of all file spaces */
3365+ ibool space_id_reuse_warned;
3366+ /* !< TRUE if fil_space_create()
3367+ has issued a warning about
3368+ potential space_id reuse */
3369+};
3370+
3371+#endif /* INNODB_VERSION_SHORT */
3372+
3373+extern fil_system_t* fil_system;
3374+extern char *opt_mysql_tmpdir;
3375+extern MY_TMPDIR mysql_tmpdir_list;
3376+
3377+/** Value of fil_space_struct::magic_n */
3378+#define FIL_SPACE_MAGIC_N 89472
3379+
3380+/* ==end=== definition at fil0fil.c === */
3381+
3382+/* prototypes for static functions in original */
3383+#ifndef INNODB_VERSION_SHORT
3384+page_t*
3385+btr_node_ptr_get_child(
3386+/*===================*/
3387+ /* out: child page, x-latched */
3388+ rec_t* node_ptr,/* in: node pointer */
3389+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
3390+ mtr_t* mtr); /* in: mtr */
3391+#else
3392+buf_block_t*
3393+btr_node_ptr_get_child(
3394+/*===================*/
3395+ const rec_t* node_ptr,/*!< in: node pointer */
3396+ dict_index_t* index, /*!< in: index */
3397+ const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
3398+ mtr_t* mtr); /*!< in: mtr */
3399+
3400+buf_block_t*
3401+btr_root_block_get(
3402+/*===============*/
3403+ dict_index_t* index, /*!< in: index tree */
3404+ mtr_t* mtr); /*!< in: mtr */
3405+#endif
3406+
3407+int
3408+fil_file_readdir_next_file(
3409+/*=======================*/
3410+ /* out: 0 if ok, -1 if error even after the
3411+ retries, 1 if at the end of the directory */
3412+ ulint* err, /* out: this is set to DB_ERROR if an error
3413+ was encountered, otherwise not changed */
3414+ const char* dirname,/* in: directory name or path */
3415+ os_file_dir_t dir, /* in: directory stream */
3416+ os_file_stat_t* info); /* in/out: buffer where the info is returned */
3417+
3418+ibool
3419+recv_check_cp_is_consistent(
3420+/*========================*/
3421+ /* out: TRUE if ok */
3422+ byte* buf); /* in: buffer containing checkpoint info */
3423+
3424+ulint
3425+recv_find_max_checkpoint(
3426+/*=====================*/
3427+ /* out: error code or DB_SUCCESS */
3428+ log_group_t** max_group, /* out: max group */
3429+ ulint* max_field); /* out: LOG_CHECKPOINT_1 or
3430+ LOG_CHECKPOINT_2 */
3431+
3432+ibool
3433+log_block_checksum_is_ok_or_old_format(
3434+/*===================================*/
3435+ /* out: TRUE if ok, or if the log block may be in the
3436+ format of InnoDB version < 3.23.52 */
3437+ byte* block); /* in: pointer to a log block */
3438+
3439+ulint
3440+open_or_create_log_file(
3441+/*====================*/
3442+ /* out: DB_SUCCESS or error code */
3443+ ibool create_new_db, /* in: TRUE if we should create a
3444+ new database */
3445+ ibool* log_file_created, /* out: TRUE if new log file
3446+ created */
3447+ ibool log_file_has_been_opened,/* in: TRUE if a log file has been
3448+ opened before: then it is an error
3449+ to try to create another log file */
3450+ ulint k, /* in: log group number */
3451+ ulint i); /* in: log file number in group */
3452+
3453+ulint
3454+open_or_create_data_files(
3455+/*======================*/
3456+ /* out: DB_SUCCESS or error code */
3457+ ibool* create_new_db, /* out: TRUE if new database should be
3458+ created */
3459+#ifdef XTRADB_BASED
3460+ ibool* create_new_doublewrite_file,
3461+#endif
3462+#ifdef UNIV_LOG_ARCHIVE
3463+ ulint* min_arch_log_no,/* out: min of archived log numbers in data
3464+ files */
3465+ ulint* max_arch_log_no,/* out: */
3466+#endif /* UNIV_LOG_ARCHIVE */
3467+ LSN64* min_flushed_lsn,/* out: min of flushed lsn values in data
3468+ files */
3469+ LSN64* max_flushed_lsn,/* out: */
3470+ ulint* sum_of_new_sizes);/* out: sum of sizes of the new files added
3471+ */
3472+
3473+/****************************************************************//**
3474+A simple function to open or create a file.
3475+@return own: handle to the file, not defined if error, error number
3476+can be retrieved with os_file_get_last_error */
3477+os_file_t
3478+xb_file_create_no_error_handling(
3479+/*=============================*/
3480+ const char* name, /*!< in: name of the file or path as a
3481+ null-terminated string */
3482+ ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
3483+ is opened (if does not exist, error), or
3484+ OS_FILE_CREATE if a new file is created
3485+ (if exists, error) */
3486+ ulint access_type,/*!< in: OS_FILE_READ_ONLY,
3487+ OS_FILE_READ_WRITE, or
3488+ OS_FILE_READ_ALLOW_DELETE; the last option is
3489+ used by a backup program reading the file */
3490+ ibool* success);/*!< out: TRUE if succeed, FALSE if error */
3491+
3492+/****************************************************************//**
3493+Opens an existing file or creates a new.
3494+@return own: handle to the file, not defined if error, error number
3495+can be retrieved with os_file_get_last_error */
3496+os_file_t
3497+xb_file_create(
3498+/*===========*/
3499+ const char* name, /*!< in: name of the file or path as a
3500+ null-terminated string */
3501+ ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
3502+ is opened (if does not exist, error), or
3503+ OS_FILE_CREATE if a new file is created
3504+ (if exists, error),
3505+ OS_FILE_OVERWRITE if a new file is created
3506+ or an old overwritten;
3507+ OS_FILE_OPEN_RAW, if a raw device or disk
3508+ partition should be opened */
3509+ ulint purpose,/*!< in: OS_FILE_AIO, if asynchronous,
3510+ non-buffered i/o is desired,
3511+ OS_FILE_NORMAL, if any normal file;
3512+ NOTE that it also depends on type, os_aio_..
3513+ and srv_.. variables whether we really use
3514+ async i/o or unbuffered i/o: look in the
3515+ function source code for the exact rules */
3516+ ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
3517+ ibool* success);/*!< out: TRUE if succeed, FALSE if error */
3518+
3519+
3520+/***********************************************************************//**
3521+Renames a file (can also move it to another directory). It is safest that the
3522+file is closed before calling this function.
3523+@return TRUE if success */
3524+ibool
3525+xb_file_rename(
3526+/*===========*/
3527+ const char* oldpath,/*!< in: old file path as a null-terminated
3528+ string */
3529+ const char* newpath);/*!< in: new file path */
3530+
3531+void
3532+xb_file_set_nocache(
3533+/*================*/
3534+ os_file_t fd, /* in: file descriptor to alter */
3535+ const char* file_name, /* in: used in the diagnostic message
3536+ */
3537+ const char* operation_name);/* in: used in the diagnostic message,
3538+ we call os_file_set_nocache()
3539+ immediately after opening or creating
3540+ a file, so this is either "open" or
3541+ "create" */
3542+
3543+/***********************************************************************//**
3544+Compatibility wrapper around os_file_flush().
3545+@return TRUE if success */
3546+ibool
3547+xb_file_flush(
3548+/*==========*/
3549+ os_file_t file); /*!< in, own: handle to a file */
3550+
3551+/*******************************************************************//**
3552+Returns the table space by a given id, NULL if not found. */
3553+fil_space_t*
3554+xb_space_get_by_id(
3555+/*================*/
3556+ ulint id); /*!< in: space id */
3557+
3558+/*******************************************************************//**
3559+Returns the table space by a given name, NULL if not found. */
3560+fil_space_t*
3561+xb_space_get_by_name(
3562+/*==================*/
3563+ const char* name); /*!< in: space name */
3564+
3565+/****************************************************************//**
3566+Create a new tablespace on disk and return the handle to its opened
3567+file. Code adopted from fil_create_new_single_table_tablespace with
3568+the main difference that only disk file is created without updating
3569+the InnoDB in-memory dictionary data structures.
3570+
3571+@return TRUE on success, FALSE on error. */
3572+ibool
3573+xb_space_create_file(
3574+/*==================*/
3575+ const char* path, /*!<in: path to tablespace */
3576+ ulint space_id, /*!<in: space id */
3577+ ulint flags __attribute__((unused)),/*!<in: tablespace
3578+ flags */
3579+ os_file_t* file); /*!<out: file handle */
3580+
3581+#ifndef INNODB_VERSION_SHORT
3582+
3583+/********************************************************************//**
3584+Extract the compressed page size from table flags.
3585+@return compressed page size, or 0 if not compressed */
3586+ulint
3587+dict_table_flags_to_zip_size(
3588+/*=========================*/
3589+ ulint flags); /*!< in: flags */
3590+
3591+
3592+/*******************************************************************//**
3593+Free all spaces in space_list. */
3594+void
3595+fil_free_all_spaces(void);
3596+/*=====================*/
3597+
3598+#endif
3599+
3600+void
3601+innobase_mysql_prepare_print_arbitrary_thd(void);
3602+
3603+void
3604+innobase_mysql_end_print_arbitrary_thd(void);
3605+
3606+int
3607+mysql_get_identifier_quote_char(
3608+ trx_t* trx,
3609+ const char* name,
3610+ ulint namelen);
3611+
3612+void
3613+innobase_print_identifier(
3614+ FILE* f,
3615+ trx_t* trx __attribute__((unused)),
3616+ ibool table_id __attribute__((unused)),
3617+ const char* name,
3618+ ulint namelen);
3619+
3620+/**********************************************************************//**
3621+It should be safe to use lower_case_table_names=0 for xtrabackup. If it causes
3622+any problems, we can add the lower_case_table_names option to xtrabackup
3623+later.
3624+@return 0 */
3625+ulint
3626+innobase_get_lower_case_table_names(void);
3627+
3628+/******************************************************************//**
3629+Strip dir name from a full path name and return only the file name
3630+@return file name or "null" if no file name */
3631+const char*
3632+innobase_basename(
3633+/*==============*/
3634+ const char* path_name); /*!< in: full path name */
3635+
3636+int
3637+innobase_mysql_cmp(
3638+ int mysql_type,
3639+ uint charset_number,
3640+ unsigned char* a,
3641+ unsigned int a_length,
3642+ unsigned char* b,
3643+ unsigned int b_length);
3644+
3645+ibool
3646+innobase_query_is_update(void);
3647+
3648+#endif /* INNODB_INT_H */
3649
3650=== modified file 'src/quicklz/quicklz.h'
3651--- src/quicklz/quicklz.h 2012-02-10 20:05:56 +0000
3652+++ src/quicklz/quicklz.h 2012-10-18 11:58:23 +0000
3653@@ -134,6 +134,7 @@
3654 size_t qlz_compress(const void *source, char *destination, size_t size, qlz_state_compress *state);
3655 size_t qlz_decompress(const char *source, void *destination, qlz_state_decompress *state);
3656 int qlz_get_setting(int setting);
3657+size_t qlz_size_header(const char *source);
3658
3659 #if defined (__cplusplus)
3660 }
3661
3662=== added file 'src/write_filt.c'
3663--- src/write_filt.c 1970-01-01 00:00:00 +0000
3664+++ src/write_filt.c 2012-10-18 11:58:23 +0000
3665@@ -0,0 +1,321 @@
3666+/******************************************************
3667+XtraBackup: hot backup tool for InnoDB
3668+(c) 2009-2012 Percona Inc.
3669+Originally Created 3/3/2009 Yasufumi Kinoshita
3670+Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
3671+Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
3672+
3673+This program is free software; you can redistribute it and/or modify
3674+it under the terms of the GNU General Public License as published by
3675+the Free Software Foundation; version 2 of the License.
3676+
3677+This program is distributed in the hope that it will be useful,
3678+but WITHOUT ANY WARRANTY; without even the implied warranty of
3679+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3680+GNU General Public License for more details.
3681+
3682+You should have received a copy of the GNU General Public License
3683+along with this program; if not, write to the Free Software
3684+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3685+
3686+*******************************************************/
3687+
3688+/* Page write filters implementation */
3689+
3690+#include <my_base.h>
3691+#include <fil0fil.h>
3692+#include <ut0mem.h>
3693+#include "common.h"
3694+#include "innodb_int.h"
3695+#include "write_filt.h"
3696+#include "fil_cur.h"
3697+#include "xtrabackup.h"
3698+
3699+/************************************************************************
3700+Write-through page write filter. */
3701+static my_bool wf_wt_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
3702+ xb_fil_cur_t *cursor);
3703+static my_bool wf_wt_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile);
3704+
3705+xb_write_filt_t wf_write_through = {
3706+ &wf_wt_init,
3707+ &wf_wt_process,
3708+ NULL,
3709+ NULL
3710+};
3711+
3712+/************************************************************************
3713+Incremental page write filter. */
3714+static my_bool wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
3715+ xb_fil_cur_t *cursor);
3716+static my_bool wf_incremental_process(xb_write_filt_ctxt_t *ctxt,
3717+ ds_file_t *dstfile);
3718+static my_bool wf_incremental_finalize(xb_write_filt_ctxt_t *ctxt,
3719+ ds_file_t *dstfile);
3720+static void wf_incremental_deinit(xb_write_filt_ctxt_t *ctxt);
3721+
3722+xb_write_filt_t wf_incremental = {
3723+ &wf_incremental_init,
3724+ &wf_incremental_process,
3725+ &wf_incremental_finalize,
3726+ &wf_incremental_deinit
3727+};
3728+
3729+/************************************************************************
3730+Compact page write filter. */
3731+static my_bool wf_compact_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
3732+ xb_fil_cur_t *cursor);
3733+static my_bool wf_compact_process(xb_write_filt_ctxt_t *ctxt,
3734+ ds_file_t *dstfile);
3735+static my_bool wf_compact_finalize(xb_write_filt_ctxt_t *ctxt,
3736+ ds_file_t *dstfile);
3737+
3738+xb_write_filt_t wf_compact = {
3739+ &wf_compact_init,
3740+ &wf_compact_process,
3741+ &wf_compact_finalize,
3742+ NULL
3743+};
3744+
3745+/************************************************************************
3746+Initialize incremental page write filter.
3747+
3748+@return TRUE on success, FALSE on error. */
3749+static my_bool
3750+wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
3751+ xb_fil_cur_t *cursor)
3752+{
3753+ char meta_name[FN_REFLEN];
3754+ xb_delta_info_t info;
3755+ ulint buf_size;
3756+ xb_wf_incremental_ctxt_t *cp =
3757+ &(ctxt->u.wf_incremental_ctxt);
3758+
3759+ ctxt->cursor = cursor;
3760+
3761+ /* allocate buffer for incremental backup (4096 pages) */
3762+ buf_size = (UNIV_PAGE_SIZE_MAX / 4 + 1) * UNIV_PAGE_SIZE_MAX;
3763+ cp->delta_buf_base = ut_malloc(buf_size);
3764+ bzero(cp->delta_buf_base, buf_size);
3765+ cp->delta_buf = ut_align(cp->delta_buf_base, UNIV_PAGE_SIZE_MAX);
3766+
3767+ /* write delta meta info */
3768+ snprintf(meta_name, sizeof(meta_name), "%s%s", dst_name,
3769+ XB_DELTA_INFO_SUFFIX);
3770+ info.page_size = cursor->page_size;
3771+ info.zip_size = cursor->zip_size;
3772+ info.space_id = cursor->space_id;
3773+ if (!xb_write_delta_metadata(meta_name, &info)) {
3774+ msg("[%02lu] xtrabackup: Error: "
3775+ "failed to write meta info for %s\n",
3776+ cursor->thread_n, cursor->path);
3777+ return(FALSE);
3778+ }
3779+
3780+ /* change the target file name, since we are only going to write
3781+ delta pages */
3782+ strcat(dst_name, ".delta");
3783+
3784+ mach_write_to_4(cp->delta_buf, 0x78747261UL); /*"xtra"*/
3785+ cp->npages = 1;
3786+
3787+ return(TRUE);
3788+}
3789+
3790+/************************************************************************
3791+Run the next batch of pages through incremental page write filter.
3792+
3793+@return TRUE on success, FALSE on error. */
3794+static my_bool
3795+wf_incremental_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
3796+{
3797+ ulint i;
3798+ xb_fil_cur_t *cursor = ctxt->cursor;
3799+ ulint page_size = cursor->page_size;
3800+ byte *page;
3801+ xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
3802+
3803+ for (i = 0, page = cursor->buf; i < cursor->buf_npages;
3804+ i++, page += page_size) {
3805+ if (ut_dulint_cmp(incremental_lsn,
3806+ MACH_READ_64(page + FIL_PAGE_LSN)) >= 0) {
3807+ continue;
3808+ }
3809+
3810+ /* updated page */
3811+ if (cp->npages == page_size / 4) {
3812+ /* flush buffer */
3813+ if (ds_write(dstfile, cp->delta_buf,
3814+ cp->npages * page_size)) {
3815+ return(FALSE);
3816+ }
3817+
3818+ /* clear buffer */
3819+ bzero(cp->delta_buf, page_size / 4 * page_size);
3820+ /*"xtra"*/
3821+ mach_write_to_4(cp->delta_buf, 0x78747261UL);
3822+ cp->npages = 1;
3823+ }
3824+
3825+ mach_write_to_4(cp->delta_buf + cp->npages * 4,
3826+ cursor->buf_page_no + i);
3827+ memcpy(cp->delta_buf + cp->npages * page_size, page,
3828+ page_size);
3829+
3830+ cp->npages++;
3831+ }
3832+
3833+ return(TRUE);
3834+}
3835+
3836+/************************************************************************
3837+Flush the incremental page write filter's buffer.
3838+
3839+@return TRUE on success, FALSE on error. */
3840+static my_bool
3841+wf_incremental_finalize(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
3842+{
3843+ xb_fil_cur_t *cursor = ctxt->cursor;
3844+ ulint page_size = cursor->page_size;
3845+ xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
3846+
3847+ if (cp->npages != page_size / 4) {
3848+ mach_write_to_4(cp->delta_buf + cp->npages * 4, 0xFFFFFFFFUL);
3849+ }
3850+
3851+ /* Mark the final block */
3852+ mach_write_to_4(cp->delta_buf, 0x58545241UL); /*"XTRA"*/
3853+
3854+ /* flush buffer */
3855+ if (ds_write(dstfile, cp->delta_buf, cp->npages * page_size)) {
3856+ return(FALSE);
3857+ }
3858+
3859+ return(TRUE);
3860+}
3861+
3862+/************************************************************************
3863+Free the incremental page write filter's buffer. */
3864+static void
3865+wf_incremental_deinit(xb_write_filt_ctxt_t *ctxt)
3866+{
3867+ xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
3868+
3869+ if (cp->delta_buf_base != NULL) {
3870+ ut_free(cp->delta_buf_base);
3871+ }
3872+}
3873+
3874+/************************************************************************
3875+Initialize the write-through page write filter.
3876+
3877+@return TRUE on success, FALSE on error. */
3878+static my_bool
3879+wf_wt_init(xb_write_filt_ctxt_t *ctxt, char *dst_name __attribute__((unused)),
3880+ xb_fil_cur_t *cursor)
3881+{
3882+ ctxt->cursor = cursor;
3883+
3884+ return(TRUE);
3885+}
3886+
3887+/************************************************************************
3888+Write the next batch of pages to the destination datasink.
3889+
3890+@return TRUE on success, FALSE on error. */
3891+static my_bool
3892+wf_wt_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
3893+{
3894+ xb_fil_cur_t *cursor = ctxt->cursor;
3895+
3896+ if (ds_write(dstfile, cursor->buf, cursor->buf_read)) {
3897+ return(FALSE);
3898+ }
3899+
3900+ return(TRUE);
3901+}
3902+
3903+/************************************************************************
3904+Initialize the compact page write filter.
3905+
3906+@return TRUE on success, FALSE on error. */
3907+static my_bool
3908+wf_compact_init(xb_write_filt_ctxt_t *ctxt,
3909+ char *dst_name __attribute__((unused)), xb_fil_cur_t *cursor)
3910+{
3911+ xb_wf_compact_ctxt_t *cp = &(ctxt->u.wf_compact_ctxt);
3912+
3913+ /* Don't compact the system table space */
3914+ cp->skip = cursor->is_system;
3915+
3916+ return(TRUE);
3917+}
3918+
3919+static my_bool
3920+check_if_skip_page(byte *page __attribute__((unused)))
3921+{
3922+ return(FALSE);
3923+}
3924+
3925+/************************************************************************
3926+Run the next batch of pages through the compact page write filter.
3927+
3928+@return TRUE on success, FALSE on error. */
3929+static my_bool
3930+wf_compact_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
3931+{
3932+ xb_fil_cur_t *cursor = ctxt->cursor;
3933+ ulint page_size = cursor->page_size;
3934+ byte *page;
3935+ byte *buf_end;
3936+ byte *write_from;
3937+ xb_wf_compact_ctxt_t *cp = &(ctxt->u.wf_compact_ctxt);
3938+
3939+ if (cp->skip) {
3940+ return(!ds_write(dstfile, cursor->buf, cursor->buf_read));
3941+ }
3942+
3943+ write_from = NULL;
3944+ buf_end = cursor->buf + cursor->buf_read;
3945+ for (page = cursor->buf; page < buf_end; page += page_size) {
3946+ if (!check_if_skip_page(page)) {
3947+ if (write_from == NULL) {
3948+ write_from = page;
3949+ }
3950+ continue;
3951+ }
3952+ }
3953+
3954+ /* Write the remaining pages in the buffer, if any */
3955+ if (write_from != NULL &&
3956+ ds_write(dstfile, write_from, buf_end - write_from)) {
3957+ return(FALSE);
3958+ }
3959+
3960+ return(TRUE);
3961+}
3962+
3963+/************************************************************************
3964+Close the compact write filter's page map stream.
3965+
3966+@return TRUE on success, FALSE on error. */
3967+static my_bool
3968+wf_compact_finalize(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
3969+{
3970+ xb_fil_cur_t *cursor = ctxt->cursor;
3971+ ulint page_size = cursor->page_size;
3972+ xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
3973+
3974+ if (cp->npages != page_size / 4) {
3975+ mach_write_to_4(cp->delta_buf + cp->npages * 4, 0xFFFFFFFFUL);
3976+ }
3977+
3978+ mach_write_to_4(cp->delta_buf, 0x58545241UL); /*"XTRA"*/
3979+
3980+ /* flush buffer */
3981+ if (ds_write(dstfile, cp->delta_buf, cp->npages * page_size)) {
3982+ return(FALSE);
3983+ }
3984+
3985+ return(TRUE);
3986+}
3987
3988=== added file 'src/write_filt.h'
3989--- src/write_filt.h 1970-01-01 00:00:00 +0000
3990+++ src/write_filt.h 2012-10-18 11:58:23 +0000
3991@@ -0,0 +1,65 @@
3992+/******************************************************
3993+XtraBackup: hot backup tool for InnoDB
3994+(c) 2009-2012 Percona Inc.
3995+Originally Created 3/3/2009 Yasufumi Kinoshita
3996+Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
3997+Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
3998+
3999+This program is free software; you can redistribute it and/or modify
4000+it under the terms of the GNU General Public License as published by
4001+the Free Software Foundation; version 2 of the License.
4002+
4003+This program is distributed in the hope that it will be useful,
4004+but WITHOUT ANY WARRANTY; without even the implied warranty of
4005+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4006+GNU General Public License for more details.
4007+
4008+You should have received a copy of the GNU General Public License
4009+along with this program; if not, write to the Free Software
4010+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4011+
4012+*******************************************************/
4013+
4014+/* Page write filter interface */
4015+
4016+#ifndef XB_WRITE_FILT_H
4017+#define XB_WRITE_FILT_H
4018+
4019+#include "fil_cur.h"
4020+#include "datasink.h"
4021+
4022+/* Incremental page filter context */
4023+typedef struct {
4024+ byte *delta_buf_base;
4025+ byte *delta_buf;
4026+ ulint npages;
4027+} xb_wf_incremental_ctxt_t;
4028+
4029+/* Compact page filter context */
4030+typedef struct {
4031+ my_bool skip;
4032+} xb_wf_compact_ctxt_t;
4033+
4034+/* Page filter context used as an opaque structure by callers */
4035+typedef struct {
4036+ xb_fil_cur_t *cursor;
4037+ union {
4038+ xb_wf_incremental_ctxt_t wf_incremental_ctxt;
4039+ xb_wf_compact_ctxt_t wf_compact_ctxt;
4040+ } u;
4041+} xb_write_filt_ctxt_t;
4042+
4043+
4044+typedef struct {
4045+ my_bool (*init)(xb_write_filt_ctxt_t *ctxt, char *dst_name,
4046+ xb_fil_cur_t *cursor);
4047+ my_bool (*process)(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile);
4048+ my_bool (*finalize)(xb_write_filt_ctxt_t *, ds_file_t *dstfile);
4049+ void (*deinit)(xb_write_filt_ctxt_t *);
4050+} xb_write_filt_t;
4051+
4052+extern xb_write_filt_t wf_write_through;
4053+extern xb_write_filt_t wf_incremental;
4054+extern xb_write_filt_t wf_compact;
4055+
4056+#endif /* XB_WRITE_FILT_H */
4057
4058=== modified file 'src/xbstream.c'
4059--- src/xbstream.c 2012-02-10 20:05:56 +0000
4060+++ src/xbstream.c 2012-10-18 11:58:23 +0000
4061@@ -23,7 +23,7 @@
4062 #include <hash.h>
4063 #include "common.h"
4064 #include "xbstream.h"
4065-#include "local.h"
4066+#include "ds_local.h"
4067
4068 #define XBSTREAM_VERSION "1.0"
4069 #define XBSTREAM_BUFFER_SIZE (1024 * 1024UL)
4070@@ -36,6 +36,12 @@
4071 RUN_MODE_EXTRACT
4072 } run_mode_t;
4073
4074+/* Need the following definitions to avoid linking with ds_stream.o,
4075+ds_compress.o, ds_tmpfile.o and their linking dependencies */
4076+datasink_t datasink_stream;
4077+datasink_t datasink_compress;
4078+datasink_t datasink_tmpfile;
4079+
4080 static run_mode_t opt_mode;
4081 static char * opt_directory = NULL;
4082 static my_bool opt_verbose = 0;
4083@@ -61,7 +67,7 @@
4084 typedef struct {
4085 char *path;
4086 uint pathlen;
4087- off_t offset;
4088+ my_off_t offset;
4089 ds_ctxt_t *ds_ctxt;
4090 ds_file_t *file;
4091 } file_entry_t;
4092@@ -199,9 +205,7 @@
4093 uchar buf[XBSTREAM_BUFFER_SIZE];
4094 size_t bytes;
4095
4096-#ifdef USE_POSIX_FADVISE
4097 posix_fadvise(file, 0, 0, POSIX_FADV_SEQUENTIAL);
4098-#endif
4099
4100 while ((bytes = my_read(file, buf, XBSTREAM_BUFFER_SIZE,
4101 MYF(MY_WME))) > 0) {
4102@@ -210,9 +214,7 @@
4103 my_progname);
4104 return 1;
4105 }
4106-#ifdef USE_POSIX_FADVISE
4107 posix_fadvise(file, 0, 0, POSIX_FADV_DONTNEED);
4108-#endif
4109
4110 }
4111
4112@@ -291,7 +293,6 @@
4113 file_entry_new(ds_ctxt_t *ds_ctxt, const char *path, uint pathlen)
4114 {
4115 file_entry_t *entry;
4116- datasink_t *ds = ds_ctxt->datasink;
4117 ds_file_t *file;
4118
4119 entry = (file_entry_t *) my_malloc(sizeof(file_entry_t),
4120@@ -306,7 +307,7 @@
4121 }
4122 entry->pathlen = pathlen;
4123
4124- file = ds->open(ds_ctxt, path, NULL);
4125+ file = ds_open(ds_ctxt, path, NULL);
4126 if (file == NULL) {
4127 msg("%s: failed to create file.\n", my_progname);
4128 goto err;
4129@@ -343,10 +344,7 @@
4130 void
4131 file_entry_free(file_entry_t *entry)
4132 {
4133- ds_ctxt_t *ds_ctxt = entry->ds_ctxt;
4134- datasink_t *ds = ds_ctxt->datasink;
4135-
4136- ds->close(entry->file);
4137+ ds_close(entry->file);
4138 MY_FREE(entry->path);
4139 MY_FREE(entry);
4140 }
4141@@ -354,14 +352,13 @@
4142 static
4143 int
4144 mode_extract(int argc __attribute__((unused)),
4145- char **argv __attribute((unused)))
4146+ char **argv __attribute__((unused)))
4147 {
4148 xb_rstream_t *stream;
4149 xb_rstream_result_t res;
4150 xb_rstream_chunk_t chunk;
4151 HASH filehash;
4152 file_entry_t *entry;
4153- datasink_t *ds;
4154 ds_ctxt_t *ds_ctxt;
4155
4156 stream = xb_stream_read_new();
4157@@ -371,8 +368,7 @@
4158 }
4159
4160 /* If --directory is specified, it is already set as CWD by now. */
4161- ds = &datasink_local;
4162- ds_ctxt = ds->init(".");
4163+ ds_ctxt = ds_create(".", DS_TYPE_LOCAL);
4164
4165 if (my_hash_init(&filehash, &my_charset_bin, START_FILE_HASH_SIZE,
4166 0, 0, (my_hash_get_key) get_file_entry_key,
4167@@ -420,7 +416,7 @@
4168 goto err;
4169 }
4170
4171- if (ds->write(entry->file, chunk.data, chunk.length)) {
4172+ if (ds_write(entry->file, chunk.data, chunk.length)) {
4173 msg("%s: my_write() failed.\n", my_progname);
4174 goto err;
4175 }
4176@@ -433,13 +429,13 @@
4177 }
4178
4179 my_hash_free(&filehash);
4180- ds->deinit(ds_ctxt);
4181+ ds_destroy(ds_ctxt);
4182 xb_stream_read_done(stream);
4183
4184 return 0;
4185 err:
4186 my_hash_free(&filehash);
4187- ds->deinit(ds_ctxt);
4188+ ds_destroy(ds_ctxt);
4189 xb_stream_read_done(stream);
4190
4191 return 1;
4192
4193=== modified file 'src/xtrabackup.c'
4194--- src/xtrabackup.c 2012-09-13 10:28:54 +0000
4195+++ src/xtrabackup.c 2012-10-18 11:58:23 +0000
4196@@ -48,9 +48,9 @@
4197
4198 //#define XTRABACKUP_TARGET_IS_PLUGIN
4199
4200+#include <mysql_version.h>
4201 #include <my_base.h>
4202 #include <my_getopt.h>
4203-#include <mysql_version.h>
4204 #include <mysql_com.h>
4205
4206 #if (MYSQL_VERSION_ID < 50100)
4207@@ -59,8 +59,6 @@
4208 #define G_PTR uchar*
4209 #endif
4210
4211-#include <univ.i>
4212-#include <os0file.h>
4213 #include <os0thread.h>
4214 #include <srv0start.h>
4215 #include <srv0srv.h>
4216@@ -72,8 +70,6 @@
4217 #include <row0mysql.h>
4218 #include <row0sel.h>
4219 #include <row0upd.h>
4220-#include <log0log.h>
4221-#include <log0recv.h>
4222 #include <lock0lock.h>
4223 #include <dict0crea.h>
4224 #include <btr0cur.h>
4225@@ -81,9 +77,7 @@
4226 #include <btr0sea.h>
4227 #include <fsp0fsp.h>
4228 #include <sync0sync.h>
4229-#include <fil0fil.h>
4230 #include <trx0xa.h>
4231-#include <btr0sea.h>
4232 #include <log0recv.h>
4233 #include <fcntl.h>
4234
4235@@ -93,676 +87,12 @@
4236
4237 #include "common.h"
4238 #include "datasink.h"
4239-#include "local.h"
4240-#include "stream.h"
4241-#include "compress.h"
4242
4243 #include "xb_regex.h"
4244-
4245-#ifndef INNODB_VERSION_SHORT
4246-#define IB_INT64 ib_longlong
4247-#define LSN64 dulint
4248-#define MACH_READ_64 mach_read_from_8
4249-#define MACH_WRITE_64 mach_write_to_8
4250-#define OS_MUTEX_CREATE() os_mutex_create(NULL)
4251-#define PAGE_ZIP_MIN_SIZE_SHIFT 10
4252-#define DICT_TF_ZSSIZE_SHIFT 1
4253-#define DICT_TF_FORMAT_ZIP 1
4254-#define DICT_TF_FORMAT_SHIFT 5
4255-#else
4256-#define IB_INT64 ib_int64_t
4257-#define LSN64 ib_uint64_t
4258-#if (MYSQL_VERSION_ID < 50500)
4259-#define MACH_READ_64 mach_read_ull
4260-#define MACH_WRITE_64 mach_write_ull
4261-#define OS_MUTEX_CREATE() os_mutex_create(NULL)
4262-#else
4263-#define MACH_READ_64 mach_read_from_8
4264-#define MACH_WRITE_64 mach_write_to_8
4265-#define OS_MUTEX_CREATE() os_mutex_create()
4266-#endif
4267-#define ut_dulint_zero 0
4268-#define ut_dulint_cmp(A, B) (A > B ? 1 : (A == B ? 0 : -1))
4269-#define ut_dulint_add(A, B) (A + B)
4270-#define ut_dulint_minus(A, B) (A - B)
4271-#define ut_dulint_align_down(A, B) (A & ~((ib_int64_t)B - 1))
4272-#define ut_dulint_align_up(A, B) ((A + B - 1) & ~((ib_int64_t)B - 1))
4273-#endif
4274-
4275-#ifdef __WIN__
4276-#define SRV_PATH_SEPARATOR '\\'
4277-#define SRV_PATH_SEPARATOR_STR "\\"
4278-#else
4279-#define SRV_PATH_SEPARATOR '/'
4280-#define SRV_PATH_SEPARATOR_STR "/"
4281-#endif
4282-
4283-#ifndef UNIV_PAGE_SIZE_MAX
4284-#define UNIV_PAGE_SIZE_MAX UNIV_PAGE_SIZE
4285-#endif
4286-#ifndef UNIV_PAGE_SIZE_SHIFT_MAX
4287-#define UNIV_PAGE_SIZE_SHIFT_MAX UNIV_PAGE_SIZE_SHIFT
4288-#endif
4289-
4290-#if MYSQL_VERSION_ID >= 50507
4291-/*
4292- As of MySQL 5.5.7, InnoDB uses thd_wait plugin service.
4293- We have to provide mock functions to avoid linker errors.
4294-*/
4295-#include <mysql/plugin.h>
4296-#include <mysql/service_thd_wait.h>
4297-
4298-void thd_wait_begin(MYSQL_THD thd, int wait_type)
4299-{
4300- (void)thd;
4301- (void)wait_type;
4302- return;
4303-}
4304-
4305-void thd_wait_end(MYSQL_THD thd)
4306-{
4307- (void)thd;
4308- return;
4309-}
4310-
4311-#endif /* MYSQL_VERSION_ID >= 50507 */
4312-
4313-/* prototypes for static functions in original */
4314-#ifndef INNODB_VERSION_SHORT
4315-page_t*
4316-btr_node_ptr_get_child(
4317-/*===================*/
4318- /* out: child page, x-latched */
4319- rec_t* node_ptr,/* in: node pointer */
4320- const ulint* offsets,/* in: array returned by rec_get_offsets() */
4321- mtr_t* mtr); /* in: mtr */
4322-#else
4323-buf_block_t*
4324-btr_node_ptr_get_child(
4325-/*===================*/
4326- const rec_t* node_ptr,/*!< in: node pointer */
4327- dict_index_t* index, /*!< in: index */
4328- const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
4329- mtr_t* mtr); /*!< in: mtr */
4330-
4331-buf_block_t*
4332-btr_root_block_get(
4333-/*===============*/
4334- dict_index_t* index, /*!< in: index tree */
4335- mtr_t* mtr); /*!< in: mtr */
4336-#endif
4337-
4338-int
4339-fil_file_readdir_next_file(
4340-/*=======================*/
4341- /* out: 0 if ok, -1 if error even after the
4342- retries, 1 if at the end of the directory */
4343- ulint* err, /* out: this is set to DB_ERROR if an error
4344- was encountered, otherwise not changed */
4345- const char* dirname,/* in: directory name or path */
4346- os_file_dir_t dir, /* in: directory stream */
4347- os_file_stat_t* info); /* in/out: buffer where the info is returned */
4348-
4349-ibool
4350-recv_check_cp_is_consistent(
4351-/*========================*/
4352- /* out: TRUE if ok */
4353- byte* buf); /* in: buffer containing checkpoint info */
4354-
4355-ulint
4356-recv_find_max_checkpoint(
4357-/*=====================*/
4358- /* out: error code or DB_SUCCESS */
4359- log_group_t** max_group, /* out: max group */
4360- ulint* max_field); /* out: LOG_CHECKPOINT_1 or
4361- LOG_CHECKPOINT_2 */
4362-
4363-ibool
4364-log_block_checksum_is_ok_or_old_format(
4365-/*===================================*/
4366- /* out: TRUE if ok, or if the log block may be in the
4367- format of InnoDB version < 3.23.52 */
4368- byte* block); /* in: pointer to a log block */
4369-
4370-ulint
4371-open_or_create_log_file(
4372-/*====================*/
4373- /* out: DB_SUCCESS or error code */
4374- ibool create_new_db, /* in: TRUE if we should create a
4375- new database */
4376- ibool* log_file_created, /* out: TRUE if new log file
4377- created */
4378- ibool log_file_has_been_opened,/* in: TRUE if a log file has been
4379- opened before: then it is an error
4380- to try to create another log file */
4381- ulint k, /* in: log group number */
4382- ulint i); /* in: log file number in group */
4383-
4384-ulint
4385-open_or_create_data_files(
4386-/*======================*/
4387- /* out: DB_SUCCESS or error code */
4388- ibool* create_new_db, /* out: TRUE if new database should be
4389- created */
4390-#ifdef XTRADB_BASED
4391- ibool* create_new_doublewrite_file,
4392-#endif
4393-#ifdef UNIV_LOG_ARCHIVE
4394- ulint* min_arch_log_no,/* out: min of archived log numbers in data
4395- files */
4396- ulint* max_arch_log_no,/* out: */
4397-#endif /* UNIV_LOG_ARCHIVE */
4398- LSN64* min_flushed_lsn,/* out: min of flushed lsn values in data
4399- files */
4400- LSN64* max_flushed_lsn,/* out: */
4401- ulint* sum_of_new_sizes);/* out: sum of sizes of the new files added */
4402-
4403-void
4404-os_file_set_nocache(
4405-/*================*/
4406- int fd, /* in: file descriptor to alter */
4407- const char* file_name, /* in: used in the diagnostic message */
4408- const char* operation_name); /* in: used in the diagnostic message,
4409- we call os_file_set_nocache()
4410- immediately after opening or creating
4411- a file, so this is either "open" or
4412- "create" */
4413-
4414-/****************************************************************//**
4415-A simple function to open or create a file.
4416-@return own: handle to the file, not defined if error, error number
4417-can be retrieved with os_file_get_last_error */
4418-UNIV_INLINE
4419-os_file_t
4420-xb_file_create_no_error_handling(
4421-/*=============================*/
4422- const char* name, /*!< in: name of the file or path as a
4423- null-terminated string */
4424- ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
4425- is opened (if does not exist, error), or
4426- OS_FILE_CREATE if a new file is created
4427- (if exists, error) */
4428- ulint access_type,/*!< in: OS_FILE_READ_ONLY,
4429- OS_FILE_READ_WRITE, or
4430- OS_FILE_READ_ALLOW_DELETE; the last option is
4431- used by a backup program reading the file */
4432- ibool* success);/*!< out: TRUE if succeed, FALSE if error */
4433-
4434-/****************************************************************//**
4435-Opens an existing file or creates a new.
4436-@return own: handle to the file, not defined if error, error number
4437-can be retrieved with os_file_get_last_error */
4438-UNIV_INLINE
4439-os_file_t
4440-xb_file_create(
4441-/*===========*/
4442- const char* name, /*!< in: name of the file or path as a
4443- null-terminated string */
4444- ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
4445- is opened (if does not exist, error), or
4446- OS_FILE_CREATE if a new file is created
4447- (if exists, error),
4448- OS_FILE_OVERWRITE if a new file is created
4449- or an old overwritten;
4450- OS_FILE_OPEN_RAW, if a raw device or disk
4451- partition should be opened */
4452- ulint purpose,/*!< in: OS_FILE_AIO, if asynchronous,
4453- non-buffered i/o is desired,
4454- OS_FILE_NORMAL, if any normal file;
4455- NOTE that it also depends on type, os_aio_..
4456- and srv_.. variables whether we really use
4457- async i/o or unbuffered i/o: look in the
4458- function source code for the exact rules */
4459- ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
4460- ibool* success);/*!< out: TRUE if succeed, FALSE if error */
4461-
4462-
4463-/***********************************************************************//**
4464-Renames a file (can also move it to another directory). It is safest that the
4465-file is closed before calling this function.
4466-@return TRUE if success */
4467-UNIV_INLINE
4468-ibool
4469-xb_file_rename(
4470-/*===========*/
4471- const char* oldpath,/*!< in: old file path as a null-terminated
4472- string */
4473- const char* newpath);/*!< in: new file path */
4474-
4475-UNIV_INLINE
4476-void
4477-xb_file_set_nocache(
4478-/*================*/
4479- os_file_t fd, /* in: file descriptor to alter */
4480- const char* file_name, /* in: used in the diagnostic message */
4481- const char* operation_name);/* in: used in the diagnostic message,
4482- we call os_file_set_nocache()
4483- immediately after opening or creating
4484- a file, so this is either "open" or
4485- "create" */
4486-
4487-/***********************************************************************//**
4488-Compatibility wrapper around os_file_flush().
4489-@return TRUE if success */
4490-static
4491-ibool
4492-xb_file_flush(
4493-/*==========*/
4494- os_file_t file); /*!< in, own: handle to a file */
4495-
4496-/* ==start === definition at fil0fil.c === */
4497-// ##################################################################
4498-// NOTE: We should check the following definitions fit to the source.
4499-// ##################################################################
4500-
4501-#ifndef INNODB_VERSION_SHORT
4502-//5.0 5.1
4503-/* File node of a tablespace or the log data space */
4504-struct fil_node_struct {
4505- fil_space_t* space; /* backpointer to the space where this node
4506- belongs */
4507- char* name; /* path to the file */
4508- ibool open; /* TRUE if file open */
4509- os_file_t handle; /* OS handle to the file, if file open */
4510- ibool is_raw_disk;/* TRUE if the 'file' is actually a raw
4511- device or a raw disk partition */
4512- ulint size; /* size of the file in database pages, 0 if
4513- not known yet; the possible last incomplete
4514- megabyte may be ignored if space == 0 */
4515- ulint n_pending;
4516- /* count of pending i/o's on this file;
4517- closing of the file is not allowed if
4518- this is > 0 */
4519- ulint n_pending_flushes;
4520- /* count of pending flushes on this file;
4521- closing of the file is not allowed if
4522- this is > 0 */
4523- ib_longlong modification_counter;/* when we write to the file we
4524- increment this by one */
4525- ib_longlong flush_counter;/* up to what modification_counter value
4526- we have flushed the modifications to disk */
4527- UT_LIST_NODE_T(fil_node_t) chain;
4528- /* link field for the file chain */
4529- UT_LIST_NODE_T(fil_node_t) LRU;
4530- /* link field for the LRU list */
4531- ulint magic_n;
4532-};
4533-
4534-struct fil_space_struct {
4535- char* name; /* space name = the path to the first file in
4536- it */
4537- ulint id; /* space id */
4538- ib_longlong tablespace_version;
4539- /* in DISCARD/IMPORT this timestamp is used to
4540- check if we should ignore an insert buffer
4541- merge request for a page because it actually
4542- was for the previous incarnation of the
4543- space */
4544- ibool mark; /* this is set to TRUE at database startup if
4545- the space corresponds to a table in the InnoDB
4546- data dictionary; so we can print a warning of
4547- orphaned tablespaces */
4548- ibool stop_ios;/* TRUE if we want to rename the .ibd file of
4549- tablespace and want to stop temporarily
4550- posting of new i/o requests on the file */
4551- ibool stop_ibuf_merges;
4552- /* we set this TRUE when we start deleting a
4553- single-table tablespace */
4554- ibool is_being_deleted;
4555- /* this is set to TRUE when we start
4556- deleting a single-table tablespace and its
4557- file; when this flag is set no further i/o
4558- or flush requests can be placed on this space,
4559- though there may be such requests still being
4560- processed on this space */
4561- ulint purpose;/* FIL_TABLESPACE, FIL_LOG, or FIL_ARCH_LOG */
4562- UT_LIST_BASE_NODE_T(fil_node_t) chain;
4563- /* base node for the file chain */
4564- ulint size; /* space size in pages; 0 if a single-table
4565- tablespace whose size we do not know yet;
4566- last incomplete megabytes in data files may be
4567- ignored if space == 0 */
4568- ulint n_reserved_extents;
4569- /* number of reserved free extents for
4570- ongoing operations like B-tree page split */
4571- ulint n_pending_flushes; /* this is > 0 when flushing
4572- the tablespace to disk; dropping of the
4573- tablespace is forbidden if this is > 0 */
4574- ulint n_pending_ibuf_merges;/* this is > 0 when merging
4575- insert buffer entries to a page so that we
4576- may need to access the ibuf bitmap page in the
4577- tablespade: dropping of the tablespace is
4578- forbidden if this is > 0 */
4579- hash_node_t hash; /* hash chain node */
4580- hash_node_t name_hash;/* hash chain the name_hash table */
4581- rw_lock_t latch; /* latch protecting the file space storage
4582- allocation */
4583- UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
4584- /* list of spaces with at least one unflushed
4585- file we have written to */
4586- ibool is_in_unflushed_spaces; /* TRUE if this space is
4587- currently in the list above */
4588- UT_LIST_NODE_T(fil_space_t) space_list;
4589- /* list of all spaces */
4590- ibuf_data_t* ibuf_data;
4591- /* insert buffer data */
4592- ulint magic_n;
4593-};
4594-typedef struct fil_system_struct fil_system_t;
4595-struct fil_system_struct {
4596- mutex_t mutex; /* The mutex protecting the cache */
4597- hash_table_t* spaces; /* The hash table of spaces in the
4598- system; they are hashed on the space
4599- id */
4600- hash_table_t* name_hash; /* hash table based on the space
4601- name */
4602- UT_LIST_BASE_NODE_T(fil_node_t) LRU;
4603- /* base node for the LRU list of the
4604- most recently used open files with no
4605- pending i/o's; if we start an i/o on
4606- the file, we first remove it from this
4607- list, and return it to the start of
4608- the list when the i/o ends;
4609- log files and the system tablespace are
4610- not put to this list: they are opened
4611- after the startup, and kept open until
4612- shutdown */
4613- UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
4614- /* base node for the list of those
4615- tablespaces whose files contain
4616- unflushed writes; those spaces have
4617- at least one file node where
4618- modification_counter > flush_counter */
4619- ulint n_open; /* number of files currently open */
4620- ulint max_n_open; /* n_open is not allowed to exceed
4621- this */
4622- ib_longlong modification_counter;/* when we write to a file we
4623- increment this by one */
4624- ulint max_assigned_id;/* maximum space id in the existing
4625- tables, or assigned during the time
4626- mysqld has been up; at an InnoDB
4627- startup we scan the data dictionary
4628- and set here the maximum of the
4629- space id's of the tables there */
4630- ib_longlong tablespace_version;
4631- /* a counter which is incremented for
4632- every space object memory creation;
4633- every space mem object gets a
4634- 'timestamp' from this; in DISCARD/
4635- IMPORT this is used to check if we
4636- should ignore an insert buffer merge
4637- request */
4638- UT_LIST_BASE_NODE_T(fil_space_t) space_list;
4639- /* list of all file spaces */
4640-};
4641-#else
4642-//Plugin ?
4643-/** File node of a tablespace or the log data space */
4644-struct fil_node_struct {
4645- fil_space_t* space; /*!< backpointer to the space where this node
4646- belongs */
4647- char* name; /*!< path to the file */
4648- ibool open; /*!< TRUE if file open */
4649- os_file_t handle; /*!< OS handle to the file, if file open */
4650- ibool is_raw_disk;/*!< TRUE if the 'file' is actually a raw
4651- device or a raw disk partition */
4652- ulint size; /*!< size of the file in database pages, 0 if
4653- not known yet; the possible last incomplete
4654- megabyte may be ignored if space == 0 */
4655- ulint n_pending;
4656- /*!< count of pending i/o's on this file;
4657- closing of the file is not allowed if
4658- this is > 0 */
4659- ulint n_pending_flushes;
4660- /*!< count of pending flushes on this file;
4661- closing of the file is not allowed if
4662- this is > 0 */
4663- ib_int64_t modification_counter;/*!< when we write to the file we
4664- increment this by one */
4665- ib_int64_t flush_counter;/*!< up to what
4666- modification_counter value we have
4667- flushed the modifications to disk */
4668- UT_LIST_NODE_T(fil_node_t) chain;
4669- /*!< link field for the file chain */
4670- UT_LIST_NODE_T(fil_node_t) LRU;
4671- /*!< link field for the LRU list */
4672- ulint magic_n;/*!< FIL_NODE_MAGIC_N */
4673-};
4674-
4675-struct fil_space_struct {
4676- char* name; /*!< space name = the path to the first file in
4677- it */
4678- ulint id; /*!< space id */
4679- ib_int64_t tablespace_version;
4680- /*!< in DISCARD/IMPORT this timestamp
4681- is used to check if we should ignore
4682- an insert buffer merge request for a
4683- page because it actually was for the
4684- previous incarnation of the space */
4685- ibool mark; /*!< this is set to TRUE at database startup if
4686- the space corresponds to a table in the InnoDB
4687- data dictionary; so we can print a warning of
4688- orphaned tablespaces */
4689- ibool stop_ios;/*!< TRUE if we want to rename the
4690- .ibd file of tablespace and want to
4691- stop temporarily posting of new i/o
4692- requests on the file */
4693- ibool stop_ibuf_merges;
4694- /*!< we set this TRUE when we start
4695- deleting a single-table tablespace */
4696- ibool is_being_deleted;
4697- /*!< this is set to TRUE when we start
4698- deleting a single-table tablespace and its
4699- file; when this flag is set no further i/o
4700- or flush requests can be placed on this space,
4701- though there may be such requests still being
4702- processed on this space */
4703- ulint purpose;/*!< FIL_TABLESPACE, FIL_LOG, or
4704- FIL_ARCH_LOG */
4705- UT_LIST_BASE_NODE_T(fil_node_t) chain;
4706- /*!< base node for the file chain */
4707- ulint size; /*!< space size in pages; 0 if a single-table
4708- tablespace whose size we do not know yet;
4709- last incomplete megabytes in data files may be
4710- ignored if space == 0 */
4711- ulint flags; /*!< compressed page size and file format, or 0 */
4712- ulint n_reserved_extents;
4713- /*!< number of reserved free extents for
4714- ongoing operations like B-tree page split */
4715- ulint n_pending_flushes; /*!< this is positive when flushing
4716- the tablespace to disk; dropping of the
4717- tablespace is forbidden if this is positive */
4718- ulint n_pending_ibuf_merges;/*!< this is positive
4719- when merging insert buffer entries to
4720- a page so that we may need to access
4721- the ibuf bitmap page in the
4722- tablespade: dropping of the tablespace
4723- is forbidden if this is positive */
4724- hash_node_t hash; /*!< hash chain node */
4725- hash_node_t name_hash;/*!< hash chain the name_hash table */
4726-#ifndef UNIV_HOTBACKUP
4727- rw_lock_t latch; /*!< latch protecting the file space storage
4728- allocation */
4729-#endif /* !UNIV_HOTBACKUP */
4730- UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
4731- /*!< list of spaces with at least one unflushed
4732- file we have written to */
4733- ibool is_in_unflushed_spaces; /*!< TRUE if this space is
4734- currently in unflushed_spaces */
4735-#ifdef XTRADB_BASED
4736- ibool is_corrupt;
4737-#endif
4738- UT_LIST_NODE_T(fil_space_t) space_list;
4739- /*!< list of all spaces */
4740- ulint magic_n;/*!< FIL_SPACE_MAGIC_N */
4741-};
4742-
4743-typedef struct fil_system_struct fil_system_t;
4744-
4745-struct fil_system_struct {
4746-#ifndef UNIV_HOTBACKUP
4747- mutex_t mutex; /*!< The mutex protecting the cache */
4748-#ifdef XTRADB_BASED
4749- mutex_t file_extend_mutex;
4750-#endif
4751-#endif /* !UNIV_HOTBACKUP */
4752- hash_table_t* spaces; /*!< The hash table of spaces in the
4753- system; they are hashed on the space
4754- id */
4755- hash_table_t* name_hash; /*!< hash table based on the space
4756- name */
4757- UT_LIST_BASE_NODE_T(fil_node_t) LRU;
4758- /*!< base node for the LRU list of the
4759- most recently used open files with no
4760- pending i/o's; if we start an i/o on
4761- the file, we first remove it from this
4762- list, and return it to the start of
4763- the list when the i/o ends;
4764- log files and the system tablespace are
4765- not put to this list: they are opened
4766- after the startup, and kept open until
4767- shutdown */
4768- UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
4769- /*!< base node for the list of those
4770- tablespaces whose files contain
4771- unflushed writes; those spaces have
4772- at least one file node where
4773- modification_counter > flush_counter */
4774- ulint n_open; /*!< number of files currently open */
4775- ulint max_n_open; /*!< n_open is not allowed to exceed
4776- this */
4777- ib_int64_t modification_counter;/*!< when we write to a file we
4778- increment this by one */
4779- ulint max_assigned_id;/*!< maximum space id in the existing
4780- tables, or assigned during the time
4781- mysqld has been up; at an InnoDB
4782- startup we scan the data dictionary
4783- and set here the maximum of the
4784- space id's of the tables there */
4785- ib_int64_t tablespace_version;
4786- /*!< a counter which is incremented for
4787- every space object memory creation;
4788- every space mem object gets a
4789- 'timestamp' from this; in DISCARD/
4790- IMPORT this is used to check if we
4791- should ignore an insert buffer merge
4792- request */
4793- UT_LIST_BASE_NODE_T(fil_space_t) space_list;
4794- /*!< list of all file spaces */
4795- ibool space_id_reuse_warned;
4796- /* !< TRUE if fil_space_create()
4797- has issued a warning about
4798- potential space_id reuse */
4799-};
4800-
4801-#endif /* INNODB_VERSION_SHORT */
4802-
4803-typedef struct {
4804- ulint page_size;
4805- ulint zip_size;
4806- ulint space_id;
4807-} xb_delta_info_t;
4808-
4809-extern fil_system_t* fil_system;
4810-
4811-/** Value of fil_space_struct::magic_n */
4812-#define FIL_SPACE_MAGIC_N 89472
4813-
4814-/*******************************************************************//**
4815-Returns the table space by a given id, NULL if not found. */
4816-fil_space_t*
4817-xb_space_get_by_id(
4818-/*================*/
4819- ulint id); /*!< in: space id */
4820-
4821-/*******************************************************************//**
4822-Returns the table space by a given name, NULL if not found. */
4823-fil_space_t*
4824-xb_space_get_by_name(
4825-/*==================*/
4826- const char* name); /*!< in: space name */
4827-
4828-/*******************************************************************//**
4829-Returns the table space by a given id, NULL if not found. */
4830-fil_space_t*
4831-xb_space_get_by_id(
4832-/*================*/
4833- ulint id) /*!< in: space id */
4834-{
4835- fil_space_t* space;
4836-
4837- ut_ad(mutex_own(&fil_system->mutex));
4838-
4839-#ifdef INNODB_VERSION_SHORT
4840- HASH_SEARCH(hash, fil_system->spaces, id,
4841- fil_space_t*, space,
4842- ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
4843- space->id == id);
4844-#else
4845- HASH_SEARCH(hash, fil_system->spaces, id, space, space->id == id);
4846-#endif
4847-
4848- return(space);
4849-}
4850-
4851-/*******************************************************************//**
4852-Returns the table space by a given name, NULL if not found. */
4853-fil_space_t*
4854-xb_space_get_by_name(
4855-/*==================*/
4856- const char* name) /*!< in: space name */
4857-{
4858- fil_space_t* space;
4859- ulint fold;
4860-
4861- ut_ad(mutex_own(&fil_system->mutex));
4862-
4863-#ifdef INNODB_VERSION_SHORT
4864- fold = ut_fold_string(name);
4865- HASH_SEARCH(name_hash, fil_system->name_hash, fold,
4866- fil_space_t*, space,
4867- ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
4868- !strcmp(name, space->name));
4869-#else
4870- HASH_SEARCH(name_hash, fil_system->name_hash, ut_fold_string(name),
4871- space, 0 == strcmp(name, space->name));
4872-#endif
4873-
4874- return(space);
4875-}
4876-
4877-#ifndef INNODB_VERSION_SHORT
4878-
4879-/*******************************************************************//**
4880-Free all spaces in space_list. */
4881-void
4882-fil_free_all_spaces(void)
4883-/*=====================*/
4884-{
4885- fil_space_t* space;
4886-
4887- mutex_enter(&fil_system->mutex);
4888-
4889- space = UT_LIST_GET_FIRST(fil_system->space_list);
4890-
4891- while (space != NULL) {
4892- fil_node_t* node;
4893- fil_space_t* prev_space = space;
4894-
4895- space = UT_LIST_GET_NEXT(space_list, space);
4896-
4897- fil_space_free(prev_space->id, FALSE);
4898- }
4899-
4900- mutex_exit(&fil_system->mutex);
4901-}
4902-
4903-#define SRV_SHUTDOWN_NONE 0
4904-
4905-#endif
4906-
4907-/* ==end=== definition at fil0fil.c === */
4908-
4909+#include "innodb_int.h"
4910+#include "fil_cur.h"
4911+#include "write_filt.h"
4912+#include "xtrabackup.h"
4913
4914 my_bool innodb_inited= 0;
4915
4916@@ -786,7 +116,6 @@
4917 lint io_ticket;
4918 os_event_t wait_throttle = NULL;
4919
4920-my_bool xtrabackup_log_only = FALSE;
4921 char *xtrabackup_incremental = NULL;
4922 LSN64 incremental_lsn;
4923 LSN64 incremental_to_lsn;
4924@@ -850,27 +179,15 @@
4925 ib_uint64_t metadata_last_lsn = 0;
4926 #endif
4927
4928-#define XB_DELTA_INFO_SUFFIX ".meta"
4929-
4930 #define XB_LOG_FILENAME "xtrabackup_logfile"
4931
4932-#ifdef __WIN__
4933-#define XB_FILE_UNDEFINED NULL
4934-#else
4935-#define XB_FILE_UNDEFINED (-1)
4936-#endif
4937-
4938-int dst_log_fd = XB_FILE_UNDEFINED;
4939-char dst_log_path[FN_REFLEN];
4940+ds_file_t *dst_log_file = NULL;
4941
4942 /* === some variables from mysqld === */
4943 char mysql_real_data_home[FN_REFLEN] = "./";
4944 char *mysql_data_home= mysql_real_data_home;
4945 static char mysql_data_home_buff[2];
4946
4947-char *opt_mysql_tmpdir = NULL;
4948-MY_TMPDIR mysql_tmpdir_list;
4949-
4950 const char *defaults_group = "mysqld";
4951
4952 /* === static parameters in ha_innodb.cc */
4953@@ -897,7 +214,9 @@
4954 long innobase_open_files = 300L;
4955
4956 long innobase_page_size = (1 << 14); /* 16KB */
4957+#ifdef XTRADB_BASED
4958 static ulong innobase_log_block_size = 512;
4959+#endif
4960 my_bool innobase_fast_checksum = FALSE;
4961 my_bool innobase_extra_undoslots = FALSE;
4962 char* innobase_doublewrite_file = NULL;
4963@@ -944,6 +263,16 @@
4964
4965 static char *xtrabackup_debug_sync = NULL;
4966
4967+static my_bool xtrabackup_compact = FALSE;
4968+
4969+/* Datasinks */
4970+static ds_ctxt_t *ds_data = NULL;
4971+static ds_ctxt_t *ds_meta = NULL;
4972+static ds_ctxt_t *ds_local = NULL;
4973+static ds_ctxt_t *ds_compress = NULL;
4974+static ds_ctxt_t *ds_tmpfile = NULL;
4975+static ds_ctxt_t *ds_stream = NULL;
4976+
4977 /* ======== Datafiles iterator ======== */
4978 typedef struct {
4979 fil_system_t *system;
4980@@ -1024,7 +353,6 @@
4981 uint *count;
4982 os_mutex_t count_mutex;
4983 os_thread_id_t id;
4984- ds_ctxt_t *ds_ctxt;
4985 } data_thread_ctxt_t;
4986
4987 /* ======== for option and variables ======== */
4988@@ -1041,7 +369,6 @@
4989 OPT_XTRA_SUSPEND_AT_END,
4990 OPT_XTRA_USE_MEMORY,
4991 OPT_XTRA_THROTTLE,
4992- OPT_XTRA_LOG_ONLY,
4993 OPT_XTRA_INCREMENTAL,
4994 OPT_XTRA_INCREMENTAL_BASEDIR,
4995 OPT_XTRA_EXTRA_LSNDIR,
4996@@ -1099,6 +426,7 @@
4997 OPT_INNODB_THREAD_CONCURRENCY,
4998 OPT_INNODB_THREAD_SLEEP_DELAY,
4999 OPT_XTRA_DEBUG_SYNC,
5000+ OPT_XTRA_COMPACT,
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches