Merge lp:~laurynas-biveinis/percona-xtrabackup/xtrabackup-page-filters into lp:percona-xtrabackup/2.0

Proposed by Laurynas Biveinis
Status: Rejected
Rejected by: Laurynas Biveinis
Proposed branch: lp:~laurynas-biveinis/percona-xtrabackup/xtrabackup-page-filters
Merge into: lp:percona-xtrabackup/2.0
Diff against target: 6973 lines (+3263/-2355) (has conflicts)
31 files modified
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/xtrabackup.1 (+0/-15)
innobackupex (+52/-113)
src/Makefile (+14/-5)
src/common.h (+41/-8)
src/datasink.c (+113/-0)
src/datasink.h (+46/-8)
src/ds_compress.c (+31/-59)
src/ds_compress.h (+2/-2)
src/ds_local.c (+0/-3)
src/ds_local.h (+2/-2)
src/ds_stream.c (+4/-2)
src/ds_stream.h (+2/-2)
src/ds_tmpfile.c (+243/-0)
src/ds_tmpfile.h (+28/-0)
src/fil_cur.c (+266/-0)
src/fil_cur.h (+95/-0)
src/innodb_int.c (+791/-0)
src/innodb_int.h (+632/-0)
src/page_write_filt.c (+309/-0)
src/page_write_filt.h (+74/-0)
src/quicklz/quicklz.h (+1/-0)
src/xbstream.c (+15/-19)
src/xtrabackup.c (+388/-2096)
test/disabled/compact.sh (+35/-0)
test/disabled/compact_compressed.sh (+53/-0)
test/inc/common.sh (+19/-0)
test/run.sh (+2/-1)
test/t/bug766033.sh (+3/-9)
Text conflict in innobackupex
Text conflict in src/xtrabackup.c
To merge this branch: bzr merge lp:~laurynas-biveinis/percona-xtrabackup/xtrabackup-page-filters
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) Needs Resubmitting
Review via email: mp+105341@code.launchpad.net

Description of the change

First part of xtrabackup page filter refactoring: introduce source
file cursor.

- Move get_bit_shift() definition to common.h.
- New files fil_cur.h and fil_cur.c for source file cursor
  implementation. New type xb_fil_cur_t to hold source file read state
  instead of local variables in xtrabackup_copy_datafile_func(). New
  functions xb_fil_cur_open(), xb_fil_cur_read(), xb_fil_cur_close()
  for opening, reading the next page batch and closing the source
  file. Their definitions refactored out of
  xtrabackup_copy_datafile_func().
- New files innodb_int.h and innodb_int.c to introduce a portability
  layer above the different InnoDB/XtraDB versions XtraBackup can be
  compiled against. Move and simplify a bunch of definitions from
  xtrabackup.c.
- Use the file cursor abstraction in xtrabackup_copy_datafile_func().

Second part of xtrabackup page filter refactoring: introduce write
filters.

- Move XB_DELTA_INFO_SUFFIX and xb_delta_info_t declarations to
  common.h.
- Move some more InnoDB portability layer macros to innodb_int.h.
- New files page_write_filt.h and page_write_filt.c for page writer
  filter implementation. New types xb_page_write_filt_ctxt_t and
  xb_page_write_filt_t to hold the state and function pointers of the
  filters. Two new functions that return one of page write filters:
  - pwf_make_write_through_filt for a pass-everything filter;
  - pwf_make_incremental_filt for an incremental filter, i.e. writes
    only pages whose LSN is later than a specified value.
  Move xb_write_delta_metadata() and a bunch of
  xtrabackup_copy_datafile() code to page_write_filt.c.
- Remove unused method xtrabackup_create_output_dir().

To post a comment you must log in.
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

Jenkins in progress at http://jenkins.percona.com/job/percona-xtrabackup-param/182/ , I will add a note once it completes.

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

Pushed a few very minor fixes for various build configs.
New Jenkins results will be at
http://jenkins.percona.com/job/percona-xtrabackup-param/184/

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :
Revision history for this message
Alexey Kopytov (akopytov) wrote :

As discussed elsewhere, no backporting is needed, since this code is only going to be used by new features in the new trunk.

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

I believe the delta from the old compact-backups will need to be resubmitted against the new trunk.

(And here goes the 1st proper Review: Resubmit use :)

review: Needs Resubmitting
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Sure, but this will have to be another MP anyway, right?

Preview Diff

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

Subscribers

People subscribed via source and target branches