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

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

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

Description of the change

To post a comment you must log in.
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

#26901

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

There is a conflict in innobackupex.

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

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

Ah, wrong target branch.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'VERSION'
--- VERSION 2012-08-06 01:11:14 +0000
+++ VERSION 2012-10-18 11:58:23 +0000
@@ -1,1 +1,1 @@
1XTRABACKUP_VERSION=2.0.31XTRABACKUP_VERSION=2.1.0
22
=== modified file 'doc/source/conf.py'
--- doc/source/conf.py 2012-09-21 12:32:30 +0000
+++ doc/source/conf.py 2012-10-18 11:58:23 +0000
@@ -51,9 +51,9 @@
51# built documents.51# built documents.
52#52#
53# The short X.Y version.53# The short X.Y version.
54version = '2.0.3'54version = '2.1'
55# The full version, including alpha/beta/rc tags.55# The full version, including alpha/beta/rc tags.
56release = '2.0.3'56release = '2.1'
5757
58# The language for content autogenerated by Sphinx. Refer to documentation58# The language for content autogenerated by Sphinx. Refer to documentation
59# for a list of supported languages.59# for a list of supported languages.
@@ -222,7 +222,7 @@
222# Grouping the document tree into LaTeX files. List of tuples222# Grouping the document tree into LaTeX files. List of tuples
223# (source start file, target name, title, author, documentclass [howto/manual]).223# (source start file, target name, title, author, documentclass [howto/manual]).
224latex_documents = [224latex_documents = [
225 ('index', 'PerconaXtraBackup.tex', u'Percona XtraBackup Documentation',225 ('index', 'PerconaXtraBackup-2.1.tex', u'Percona XtraBackup Documentation',
226 u'Percona Inc', 'manual'),226 u'Percona Inc', 'manual'),
227]227]
228228
229229
=== modified file 'doc/source/innobackupex/how_innobackupex_works.rst'
--- doc/source/innobackupex/how_innobackupex_works.rst 2012-09-06 05:15:27 +0000
+++ doc/source/innobackupex/how_innobackupex_works.rst 2012-10-18 11:58:23 +0000
@@ -53,10 +53,6 @@
53:file:`mysql-stdout`53:file:`mysql-stdout`
54 containing the ``STDOUT`` of the server.54 containing the ``STDOUT`` of the server.
5555
56If 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).
57
58After each copy the files will be deleted. The same rationale is for the :option:`--stream` mode.
59
60Finally, the binary log position will be printed to ``STDERR`` and |innobackupex| will exit returning 0 if all went OK.56Finally, the binary log position will be printed to ``STDERR`` and |innobackupex| will exit returning 0 if all went OK.
6157
62Note 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``.58Note 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``.
6359
=== modified file 'doc/source/innobackupex/innobackupex_option_reference.rst'
--- doc/source/innobackupex/innobackupex_option_reference.rst 2012-09-21 12:32:30 +0000
+++ doc/source/innobackupex/innobackupex_option_reference.rst 2012-10-18 11:58:23 +0000
@@ -127,17 +127,13 @@
127127
128 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.128 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.
129129
130.. option:: --remote-host=HOSTNAME
131
132 This option accepts a string argument that specifies the remote host on which the backup files will be created, by using an ssh connection. This option is DEPRECATED and will be removed in Percona XtraBackup 2.1. In Percona XtraBackup 2.0 and later, you should use streaming backups instead.
133
134.. option:: --stream=STREAMNAME130.. option:: --stream=STREAMNAME
135131
136 This option accepts a string argument that specifies the format in which to do the streamed backup. The backup will be done to ``STDOUT`` in the specified format. Currently, supported formats are `tar` and `xbstream`. Uses :doc:`xbstream <../xbstream/xbstream>`, which is available in *XtraBackup* distributions. If you specify a path after this option, it will be interpreted as the value of :option:`tmpdir`.132 This option accepts a string argument that specifies the format in which to do the streamed backup. The backup will be done to ``STDOUT`` in the specified format. Currently, supported formats are `tar` and `xbstream`. Uses :doc:`xbstream <../xbstream/xbstream>`, which is available in *XtraBackup* distributions. If you specify a path after this option, it will be interpreted as the value of :option:`tmpdir`.
137133
138.. option:: --tmpdir=DIRECTORY134.. option:: --tmpdir=DIRECTORY
139135
140 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.136 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.
141137
142.. option:: --scpopt = '-Cp -c arcfour'138.. option:: --scpopt = '-Cp -c arcfour'
143139
@@ -161,4 +157,4 @@
161157
162.. option:: --rsync158.. option:: --rsync
163159
164 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`.160 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`.
165161
=== modified file 'doc/source/innobackupex/innobackupex_script.rst'
--- doc/source/innobackupex/innobackupex_script.rst 2011-07-28 05:29:04 +0000
+++ doc/source/innobackupex/innobackupex_script.rst 2012-10-18 11:58:23 +0000
@@ -46,7 +46,6 @@
46 replication_ibk46 replication_ibk
47 parallel_copy_ibk47 parallel_copy_ibk
48 throttling_ibk48 throttling_ibk
49 remote_backups_ibk
50 importing_exporting_tables_ibk49 importing_exporting_tables_ibk
51 pit_recovery_ibk50 pit_recovery_ibk
5251
5352
=== renamed file 'doc/source/innobackupex/remote_backups_ibk.rst' => 'doc/source/innobackupex/remote_backups_ibk.rst.THIS'
--- doc/source/innobackupex/remote_backups_ibk.rst 2012-09-19 13:00:42 +0000
+++ doc/source/innobackupex/remote_backups_ibk.rst.THIS 2012-10-18 11:58:23 +0000
@@ -13,10 +13,6 @@
13Then all the log files will be written to a temporary file (you can choose where to store this file with the :option:`--tmpdir` option) and will be copied via :command:`scp`. The options for :command:`scp` can be specified with :option:`--options-scp` (``-Cp -c arcfour`` by default), for example::13Then all the log files will be written to a temporary file (you can choose where to store this file with the :option:`--tmpdir` option) and will be copied via :command:`scp`. The options for :command:`scp` can be specified with :option:`--options-scp` (``-Cp -c arcfour`` by default), for example::
1414
15 $ innobackupex --remote-host=REMOTEUSER@REMOTEHOST /path/IN/REMOTE/HOST/to/backup/ \15 $ innobackupex --remote-host=REMOTEUSER@REMOTEHOST /path/IN/REMOTE/HOST/to/backup/ \
16 --tmpdir=/tmp --scpopt="-Cp -c arcfour"16 --tmpdir=/tmp --options-scp="-Cp -c arcfour"
17
18.. note::
19
20 `SSH public key authentication <http://www.petefreitag.com/item/532.cfm>`_ should be set up to avoid the login prompt when doing the backup to the remote host.
2117
2218
2319
=== modified file 'doc/xtrabackup.1'
--- doc/xtrabackup.1 2011-01-10 12:01:38 +0000
+++ doc/xtrabackup.1 2012-10-18 11:58:23 +0000
@@ -1392,21 +1392,6 @@
1392.B "xtrabackup"1392.B "xtrabackup"
1393and your script are working on the same dataset.1393and your script are working on the same dataset.
13941394
1395.SS " Log Streaming "
1396
1397
1398You can instruct
1399.B "xtrabackup"
1400to omit copying data files, and simply stream the log file to its standard output instead with
1401.B "--log-stream"
1402. This automatically adds the
1403.B "--suspend-at-end"
1404option. 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
1405.B "rsync"
1406or
1407.B "tar4ibd"
1408.
1409
1410.SH " XtraBackup Exit Codes "1395.SH " XtraBackup Exit Codes "
14111396
14121397
14131398
=== modified file 'innobackupex'
--- innobackupex 2012-10-16 15:05:23 +0000
+++ innobackupex 2012-10-18 11:58:23 +0000
@@ -101,7 +101,6 @@
101my $option_incremental_dir = '';101my $option_incremental_dir = '';
102my $option_incremental_lsn = '';102my $option_incremental_lsn = '';
103my $option_extra_lsndir = '';103my $option_extra_lsndir = '';
104my $option_remote_host = '';
105my $option_rsync = '';104my $option_rsync = '';
106my $option_stream = '';105my $option_stream = '';
107my $stream_cmd = '';106my $stream_cmd = '';
@@ -116,6 +115,8 @@
116my $option_safe_slave_backup = '';115my $option_safe_slave_backup = '';
117my $option_safe_slave_backup_timeout = 300;116my $option_safe_slave_backup_timeout = 300;
118117
118my $option_compact = '';
119
119# name of the my.cnf configuration file120# name of the my.cnf configuration file
120#my $config_file = '';121#my $config_file = '';
121122
@@ -290,11 +291,7 @@
290} else {291} else {
291 # make a backup of InnoDB and MyISAM tables, indexes and .frm files.292 # make a backup of InnoDB and MyISAM tables, indexes and .frm files.
292 $ibbackup_exit_code = backup();293 $ibbackup_exit_code = backup();
293 if ($option_remote_host) {294 if ($option_stream) {
294 open(XTRABACKUP_BINARY,
295 "| ssh $option_ssh_opt $option_remote_host 'cat > $backup_dir/$xtrabackup_binary_file'")
296 || die "Failed to open file '$option_remote_host:$backup_dir/$xtrabackup_binary_file': $!";
297 } elsif ($option_stream) {
298 open XTRABACKUP_BINARY, "> $option_tmpdir/$xtrabackup_binary_file"295 open XTRABACKUP_BINARY, "> $option_tmpdir/$xtrabackup_binary_file"
299 || die "Cannot open file $option_tmpdir/$xtrabackup_binary_file: $!\n";296 || die "Cannot open file $option_tmpdir/$xtrabackup_binary_file: $!\n";
300 } else {297 } else {
@@ -396,9 +393,7 @@
396 start_ibbackup();393 start_ibbackup();
397394
398 # wait for ibbackup to suspend itself395 # wait for ibbackup to suspend itself
399 if (!$option_remote_host) {396 wait_for_ibbackup_suspend();
400 wait_for_ibbackup_suspend();
401 }
402397
403 # connect to database398 # connect to database
404 mysql_open();399 mysql_open();
@@ -441,11 +436,7 @@
441436
442 # copy ib_lru_dump437 # copy ib_lru_dump
443 if (-e "$orig_datadir/ib_lru_dump") {438 if (-e "$orig_datadir/ib_lru_dump") {
444 if ($option_remote_host) {439 if ($option_stream) {
445 print STDERR "$prefix Backing up file 'ib_lru_dump'\n";
446 system("scp $option_scp_opt '$orig_datadir/ib_lru_dump' '$option_remote_host:$backup_dir/ib_lru_dump'")
447 and Die "Failed to scp file 'ib_lru_dump': $!";
448 } elsif ($option_stream) {
449 print STDERR "$prefix Backing up as tar stream 'ib_lru_dump'\n";440 print STDERR "$prefix Backing up as tar stream 'ib_lru_dump'\n";
450 system("cd $orig_datadir; $stream_cmd ib_lru_dump")441 system("cd $orig_datadir; $stream_cmd ib_lru_dump")
451 and Die "Failed to stream 'ib_lru_dump': $!";442 and Die "Failed to stream 'ib_lru_dump': $!";
@@ -457,16 +448,6 @@
457 }448 }
458 }449 }
459450
460 if ($option_remote_host) {
461 system("scp $option_scp_opt '$tmp_logfile' '$option_remote_host:$backup_dir/xtrabackup_logfile'")
462 and Die "Failed to scp file '$option_remote_host:$backup_dir/xtrabackup_logfile': $!";
463 unlink $tmp_logfile || Die "Failed to delete '$tmp_logfile': $!";
464
465 system("scp $option_scp_opt '$option_tmpdir/xtrabackup_checkpoints' '$option_remote_host:$backup_dir/xtrabackup_checkpoints'")
466 and Die "Failed to scp file '$option_remote_host:$backup_dir/xtrabackup_checkpoints': $!";
467 unlink "$option_tmpdir/xtrabackup_checkpoints" || Die "Failed to delete '$option_tmpdir/xtrabackup_checkpoints': $!";
468 }
469
470 print STDERR "\n$prefix Backup created in directory '$backup_dir'\n";451 print STDERR "\n$prefix Backup created in directory '$backup_dir'\n";
471 if ($mysql_binlog_position) {452 if ($mysql_binlog_position) {
472 print STDERR "$prefix MySQL binlog position: $mysql_binlog_position\n";453 print STDERR "$prefix MySQL binlog position: $mysql_binlog_position\n";
@@ -719,6 +700,14 @@
719 my $file;700 my $file;
720 my $backup_innodb_data_file_path;701 my $backup_innodb_data_file_path;
721702
703 if (has_option(\%config, $option_defaults_group, 'innodb_doublewrite_file')) {
704 my $doublewrite_file =
705 (split(/\/+/,
706 get_option(\%config, $option_defaults_group,
707 'innodb_doublewrite_file')))[-1];
708 $excluded_files = $excluded_files . '|' . $doublewrite_file;
709 }
710
722 # check whether files should be copied or moved to dest directory711 # check whether files should be copied or moved to dest directory
723 my $move_or_copy_file = $move_flag ? \&move_file : \&copy_file;712 my $move_or_copy_file = $move_flag ? \&move_file : \&copy_file;
724 my $move_or_copy_dir = $move_flag ?713 my $move_or_copy_dir = $move_flag ?
@@ -955,14 +944,11 @@
955944
956 $options = $options . "--backup --suspend-at-end";945 $options = $options . "--backup --suspend-at-end";
957946
958 if (!$option_remote_host && !$option_stream) {947 if ($option_stream) {
959 $options = $options . " --target-dir=$backup_dir";
960 } else {
961 #(datadir) for 'xtrabackup_suspended' and 'xtrabackup_checkpoints'948 #(datadir) for 'xtrabackup_suspended' and 'xtrabackup_checkpoints'
962 $options = $options . " --target-dir=" . $option_tmpdir;949 $options = $options . " --target-dir=" . $option_tmpdir;
963 if ($option_remote_host) {950 } else {
964 $options = $options . " --log-stream";951 $options = $options . " --target-dir=$backup_dir";
965 }
966 }952 }
967953
968 # prepare command line for running ibbackup954 # prepare command line for running ibbackup
@@ -1003,6 +989,10 @@
1003 if ($option_stream) {989 if ($option_stream) {
1004 $options = $options . " --stream=$option_stream";990 $options = $options . " --stream=$option_stream";
1005 }991 }
992 if ($option_compact) {
993 $options = $options. " --compact";
994 }
995
1006 $cmdline = "$option_ibbackup_binary $options";996 $cmdline = "$option_ibbackup_binary $options";
1007997
1008 # run ibbackup as a child process998 # run ibbackup as a child process
@@ -1012,97 +1002,7 @@
1012 if ($pid) {1002 if ($pid) {
1013 # parent process1003 # parent process
1014 $ibbackup_pid = $pid;1004 $ibbackup_pid = $pid;
1015
1016 if($option_remote_host) {
1017 #direct copy to remote
1018 my $orig_datadir = get_option(\%config, $option_defaults_group, 'datadir');
1019 my $orig_ibdata_dir =
1020 get_option(\%config, $option_defaults_group, 'innodb_data_home_dir');
1021 my $orig_innodb_data_file_path =
1022 get_option(\%config, $option_defaults_group, 'innodb_data_file_path');
1023 my $innodb_flush_method =
1024 get_option(\%config, $option_defaults_group, 'innodb_flush_method');
1025 my $innodb_use_odirect;
1026 $innodb_use_odirect = 1 if $innodb_flush_method =~ m/^(ALL_)?O_DIRECT$/i;
1027
1028 my $subdir;
1029 my @list;
1030
1031 if (system("ssh $option_ssh_opt $option_remote_host test -e $backup_dir/ib_logfile0")
1032 == 0) {
1033 print STDERR "$prefix Remove $option_remote_host:$backup_dir/ib_logfile*\n";
1034 system("ssh $option_ssh_opt $option_remote_host rm $backup_dir/ib_logfile\*")
1035 and Die "Failed to rm file '$backup_dir/ib_logfile*': $!";
1036 }
1037
1038 wait_for_ibbackup_suspend();
1039
1040 #InnoDB data files from original InnoDB data directory
1041 print STDERR "\n$prefix Starting to backup InnoDB tables and indexes\n";
1042 print STDERR "$prefix to '$backup_dir'\n";
1043 print STDERR "$prefix from original InnoDB data directory '$orig_ibdata_dir'\n";
1044 foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
1045 my $path = (split(/:/,$a))[0];
1046 $path=~s/([\$\\\" ])/\\$1/g;
1047 print STDERR "$prefix Backing up file '$orig_ibdata_dir/$path'\n";
1048 system("scp $option_scp_opt '$orig_ibdata_dir/$path' '$option_remote_host:$backup_dir/$path'")
1049 and Die "Failed to scp file '$path': $!";
1050 }
1051
1052 #copy *.ibd files
1053 opendir(DIR, $orig_datadir)
1054 || Die "Can't open directory '$orig_datadir': $!\n";
1055 while (defined($subdir = readdir(DIR))) {
1056 my $print_each_file = 0;
1057 my $file_c;
1058 my $file;
1059 if ($subdir eq '.' || $subdir eq '..') { next; }
1060 next unless -d "$orig_datadir/$subdir";
1061 next unless check_if_required($subdir);
1062
1063 @list = glob("$orig_datadir/$subdir/" . '*.ibd');
1064
1065 $file_c = @list;
1066 if ($file_c <= $backup_file_print_limit) {
1067 $print_each_file = 1;
1068 } else {
1069 print STDERR "$prefix Backing up files " .
1070 "'$orig_datadir/$subdir/*.ibd' ($file_c files)\n";
1071 }
1072 foreach $file (@list) {
1073 next unless check_if_required($subdir, $file);
1074 if($option_include) {
1075 my $table_name;
1076
1077 $table_name = substr($file, rindex($file, '/'));
1078 $table_name = substr($table_name, 1, rindex($table_name, '.') - 1);
1079 $table_name = $subdir . "." . $table_name;
1080
1081 if (!($table_name =~ /$option_include/)) {
1082 print STDERR "'$file' is skipped.\n";
1083 next;
1084 }
1085 }
1086
1087 if ($print_each_file) {
1088 print STDERR "$prefix Backing up file '$file'\n";
1089 }
1090 if (system("ssh $option_ssh_opt $option_remote_host test -e $backup_dir/$subdir")
1091 != 0) {
1092 system("ssh $option_ssh_opt $option_remote_host mkdir $backup_dir/$subdir");
1093 }
1094 system("scp $option_scp_opt '$file' '$option_remote_host:$backup_dir/$subdir/'")
1095 and Die "Failed to scp file '$file': $!";
1096 }
1097 }
1098 closedir(DIR);
1099 }
1100 } else {1005 } else {
1101 if($option_remote_host) {
1102 open(STDOUT, "> $tmp_logfile")
1103 || Die "Failed to open file '$tmp_logfile': $!"
1104 }
1105
1106 # child process1006 # child process
1107 exec($cmdline) || Die "Failed to exec ibbackup: $!";1007 exec($cmdline) || Die "Failed to exec ibbackup: $!";
1108 }1008 }
@@ -1299,13 +1199,7 @@
1299 }1199 }
13001200
1301 # write binlog info file1201 # write binlog info file
1302 if (!$option_remote_host) {1202 open(FILE, ">$binlog_info") || Die "Failed to open file '$binlog_info': $!";
1303 open(FILE, ">$binlog_info") ||
1304 Die "Failed to open file '$binlog_info': $!";
1305 } else {
1306 open(FILE, "| ssh $option_ssh_opt $option_remote_host 'cat > $binlog_info'") ||
1307 Die "Failed to open file '$option_remote_host:$binlog_info': $!";
1308 }
1309 print FILE "$filename\t$position\t\t\n";1203 print FILE "$filename\t$position\t\t\n";
1310 close(FILE);1204 close(FILE);
13111205
@@ -1389,13 +1283,7 @@
1389 }1283 }
13901284
1391 # print slave status to a file1285 # print slave status to a file
1392 if (!$option_remote_host) {1286 open(FILE, ">$slave_info") || Die "Failed to open file '$slave_info': $!";
1393 open(FILE, ">$slave_info") ||
1394 Die "Failed to open file '$slave_info': $!";
1395 } else {
1396 open(FILE, "| ssh $option_ssh_opt $option_remote_host 'cat > $slave_info'") ||
1397 Die "Failed to open file '$option_remote_host:$slave_info': $!";
1398 }
1399 print FILE "CHANGE MASTER TO MASTER_LOG_FILE='$filename', MASTER_LOG_POS=$position\n";1287 print FILE "CHANGE MASTER TO MASTER_LOG_FILE='$filename', MASTER_LOG_POS=$position\n";
1400 close(FILE);1288 close(FILE);
14011289
@@ -1669,32 +1557,20 @@
16691557
1670 if (!$option_apply_log && !$option_copy_back && !$option_move_back) {1558 if (!$option_apply_log && !$option_copy_back && !$option_move_back) {
1671 # we are making a backup, create a new backup directory1559 # we are making a backup, create a new backup directory
1672 if (!$option_remote_host) {1560 $backup_dir = File::Spec->rel2abs(make_backup_dir());
1673 $backup_dir = File::Spec->rel2abs(make_backup_dir());
1674 } else {
1675 $backup_dir = make_backup_dir();
1676 }
1677 print STDERR "$prefix Created backup directory $backup_dir\n";1561 print STDERR "$prefix Created backup directory $backup_dir\n";
1678 if (!$option_remote_host && !$option_stream) {1562 if (!$option_stream) {
1679 $backup_config_file = $backup_dir . '/backup-my.cnf';
1680 $suspend_file = $backup_dir . '/xtrabackup_suspended';
1681 $binlog_info = $backup_dir . '/xtrabackup_binlog_info';
1682 $galera_info = $backup_dir . '/xtrabackup_galera_info';
1683 $slave_info = $backup_dir . '/xtrabackup_slave_info';
1684 } else {
1685 $suspend_file = $option_tmpdir . '/xtrabackup_suspended';
1686 $tmp_logfile = $option_tmpdir . '/xtrabackup_logfile';
1687 if ($option_stream) {
1688 $backup_config_file = $option_tmpdir . '/backup-my.cnf';
1689 $binlog_info = $option_tmpdir . '/xtrabackup_binlog_info';
1690 $galera_info = $option_tmpdir . '/xtrabackup_galera_info';
1691 $slave_info = $option_tmpdir . '/xtrabackup_slave_info';
1692 } else {
1693 $backup_config_file = $backup_dir . '/backup-my.cnf';1563 $backup_config_file = $backup_dir . '/backup-my.cnf';
1564 $suspend_file = $backup_dir . '/xtrabackup_suspended';
1694 $binlog_info = $backup_dir . '/xtrabackup_binlog_info';1565 $binlog_info = $backup_dir . '/xtrabackup_binlog_info';
1695 $galera_info = $backup_dir . '/xtrabackup_galera_info';1566 $galera_info = $backup_dir . '/xtrabackup_galera_info';
1696 $slave_info = $backup_dir . '/xtrabackup_slave_info';1567 $slave_info = $backup_dir . '/xtrabackup_slave_info';
1697 }1568 } else {
1569 $suspend_file = $option_tmpdir . '/xtrabackup_suspended';
1570 $tmp_logfile = $option_tmpdir . '/xtrabackup_logfile';
1571 $backup_config_file = $option_tmpdir . '/backup-my.cnf';
1572 $binlog_info = $option_tmpdir . '/xtrabackup_binlog_info';
1573 $slave_info = $option_tmpdir . '/xtrabackup_slave_info';
1698 }1574 }
1699 write_backup_config_file($backup_config_file);1575 write_backup_config_file($backup_config_file);
1700 } elsif ($option_copy_back || $option_move_back) {1576 } elsif ($option_copy_back || $option_move_back) {
@@ -1714,12 +1590,7 @@
1714sub write_backup_config_file {1590sub write_backup_config_file {
1715 my $filename = shift;1591 my $filename = shift;
17161592
1717 if (!$option_remote_host) {1593 open(FILE, "> $filename") || Die "Failed to open file '$filename': $!";
1718 open(FILE, "> $filename") || Die "Failed to open file '$filename': $!";
1719 } else {
1720 open(FILE, "| ssh $option_ssh_opt $option_remote_host 'cat > $filename'")
1721 || Die "Failed to open file '$option_remote_host:$filename': $!";
1722 }
17231594
1724 my @option_names = (1595 my @option_names = (
1725 "innodb_data_file_path",1596 "innodb_data_file_path",
@@ -1800,7 +1671,7 @@
1800 'use-memory=s' => \$option_use_memory,1671 'use-memory=s' => \$option_use_memory,
1801 'uncompress' => \$option_uncompress,1672 'uncompress' => \$option_uncompress,
1802 'export' => \$option_export,1673 'export' => \$option_export,
1803 'password=s' => \$option_mysql_password,1674 'password:s' => \$option_mysql_password,
1804 'user=s' => \$option_mysql_user,1675 'user=s' => \$option_mysql_user,
1805 'host=s' => \$option_mysql_host,1676 'host=s' => \$option_mysql_host,
1806 'port=s' => \$option_mysql_port,1677 'port=s' => \$option_mysql_port,
@@ -1815,7 +1686,6 @@
1815 'incremental-lsn=s' => \$option_incremental_lsn,1686 'incremental-lsn=s' => \$option_incremental_lsn,
1816 'incremental-dir=s' => \$option_incremental_dir,1687 'incremental-dir=s' => \$option_incremental_dir,
1817 'extra-lsndir=s' => \$option_extra_lsndir,1688 'extra-lsndir=s' => \$option_extra_lsndir,
1818 'remote-host=s' => \$option_remote_host,
1819 'stream=s' => \$option_stream,1689 'stream=s' => \$option_stream,
1820 'rsync' => \$option_rsync,1690 'rsync' => \$option_rsync,
1821 'tmpdir=s' => \$option_tmpdir,1691 'tmpdir=s' => \$option_tmpdir,
@@ -1825,7 +1695,12 @@
1825 'sshopt=s' => \$option_ssh_opt,1695 'sshopt=s' => \$option_ssh_opt,
1826 'parallel=i' => \$option_parallel,1696 'parallel=i' => \$option_parallel,
1827 'safe-slave-backup' => \$option_safe_slave_backup,1697 'safe-slave-backup' => \$option_safe_slave_backup,
1698<<<<<<< TREE
1828 'safe-slave-backup-timeout=i' => \$option_safe_slave_backup_timeout,1699 'safe-slave-backup-timeout=i' => \$option_safe_slave_backup_timeout,
1700=======
1701 'safe-slave-backup-timeout' => $option_safe_slave_backup_timeout,
1702 'compact' => \$option_compact
1703>>>>>>> MERGE-SOURCE
1829 );1704 );
1830 1705
1831 if (!$rcode) {1706 if (!$rcode) {
@@ -1901,16 +1776,11 @@
1901 }1776 }
1902 }1777 }
19031778
1904 if ($option_rsync && ($option_remote_host || $option_stream)) {1779 if ($option_rsync && $option_stream) {
1905 print STDERR "--rsync doesn't work with --remote-host or --stream\n";1780 print STDERR "--rsync doesn't work with --stream\n";
1906 exit(1);1781 exit(1);
1907 }1782 }
19081783
1909 if ($option_remote_host) {
1910 print STDERR "\nWARNING: --remote-host is DEPRECATED and will be ",
1911 "removed in Percona XtraBackup 2.1 in favor of streaming backups.\n";
1912 }
1913
1914 print STDERR "\n";1784 print STDERR "\n";
19151785
1916 parse_databases_option_value();1786 parse_databases_option_value();
@@ -1935,11 +1805,7 @@
19351805
1936 $dir .= '/' . strftime("%Y-%m-%d_%H-%M-%S", localtime())1806 $dir .= '/' . strftime("%Y-%m-%d_%H-%M-%S", localtime())
1937 unless $option_no_timestamp;1807 unless $option_no_timestamp;
1938 if (!$option_remote_host) {1808 mkdir($dir, 0777) || Die "Failed to create backup directory $dir: $!";
1939 mkdir($dir, 0777) || Die "Failed to create backup directory $dir: $!";
1940 } else {
1941 system("ssh $option_ssh_opt $option_remote_host mkdir $dir");
1942 }
19431809
1944 # create subdirectories for ibdata files if needed1810 # create subdirectories for ibdata files if needed
1945# foreach my $a (split(/;/, $innodb_data_file_path)) {1811# foreach my $a (split(/;/, $innodb_data_file_path)) {
@@ -1975,15 +1841,9 @@
1975 $path = $root;1841 $path = $root;
1976 foreach $a (@{$relative_path}) {1842 foreach $a (@{$relative_path}) {
1977 $path = $path . "/" . $a;1843 $path = $path . "/" . $a;
1978 if (!$option_remote_host) {1844 if (! -d $path) {
1979 if (! -d $path) {1845 # this directory does not exist, create it !
1980 # this directory does not exist, create it !1846 mkdir($path, 0777) || Die "Failed to create backup directory: $!";
1981 mkdir($path, 0777) || Die "Failed to create backup directory: $!";
1982 }
1983 } else {
1984 if (system("ssh $option_ssh_opt $option_remote_host test -d $path") != 0) {
1985 system("ssh $option_ssh_opt $option_remote_host mkdir $path");
1986 }
1987 }1847 }
1988 }1848 }
1989}1849}
@@ -2065,17 +1925,12 @@
2065 next unless -d "$source_dir/$database";1925 next unless -d "$source_dir/$database";
2066 next unless check_if_required($database);1926 next unless check_if_required($database);
2067 1927
2068 if (!$option_remote_host && !$option_stream) {1928 if (!$option_stream) {
2069 if (! -e "$backup_dir/$database") {1929 if (! -e "$backup_dir/$database") {
2070 # create database directory for the backup1930 # create database directory for the backup
2071 mkdir("$backup_dir/$database", 0777)1931 mkdir("$backup_dir/$database", 0777)
2072 || Die "Couldn't create directory '$backup_dir/$database': $!";1932 || Die "Couldn't create directory '$backup_dir/$database': $!";
2073 }1933 }
2074 } elsif ($option_remote_host) {
2075 if (system("ssh $option_ssh_opt $option_remote_host test -e $backup_dir/$database")
2076 != 0) {
2077 system("ssh $option_ssh_opt $option_remote_host mkdir $backup_dir/$database");
2078 }
2079 }1934 }
20801935
2081 # copy files of this database1936 # copy files of this database
@@ -2109,16 +1964,13 @@
2109 if (!$prep_mode) {1964 if (!$prep_mode) {
2110 $rsync_files_hash{"$database/$file"} = 1;1965 $rsync_files_hash{"$database/$file"} = 1;
2111 }1966 }
2112 } elsif (!$option_remote_host && !$option_stream) {1967 } elsif (!$option_stream) {
2113 $src_name = escape_path("$source_dir/$database/$file");1968 $src_name = escape_path("$source_dir/$database/$file");
2114 $dst_name = escape_path("$backup_dir/$database");1969 $dst_name = escape_path("$backup_dir/$database");
2115 # Copy the file - If we get an error and the file actually exists, die with error msg1970 # Copy the file - If we get an error and the file actually exists, die with error msg
2116 copy_if_exists("$src_name", "$dst_name")1971 copy_if_exists("$src_name", "$dst_name")
2117 or Die "Failed to copy file '$file': $!";1972 or Die "Failed to copy file '$file': $!";
2118 } elsif ($option_remote_host) {1973 } else {
2119 # Queue up files for one single scp per database.
2120 push(@scp_files, "'$file'");
2121 } elsif($option_stream) {
2122 my $ret = 0;1974 my $ret = 0;
2123 my $file_name = substr($file, rindex($file, '/') + 1);1975 my $file_name = substr($file, rindex($file, '/') + 1);
2124 $file_name=~s/([\$\\\" ])/\\$1/g;1976 $file_name=~s/([\$\\\" ])/\\$1/g;
@@ -2138,11 +1990,6 @@
2138 }1990 }
2139 }1991 }
2140 }1992 }
2141 if ($option_remote_host and @scp_files) {
2142 my $scp_file_list = join(" ", map { "$source_dir/$database/$_" } @scp_files);
2143 system("scp $option_scp_opt $scp_file_list '$option_remote_host:$backup_dir/$database/'")
2144 and Die "Failed to execute \"scp $option_scp_opt $scp_file_list '$option_remote_host:$backup_dir/$database/'\": $!";
2145 }
2146 }1993 }
2147 closedir(DIR);1994 closedir(DIR);
21481995
@@ -2716,12 +2563,12 @@
2716 [--password=WORD] [--port=PORT] [--socket=SOCKET]2563 [--password=WORD] [--port=PORT] [--socket=SOCKET]
2717 [--no-timestamp] [--ibbackup=IBBACKUP-BINARY]2564 [--no-timestamp] [--ibbackup=IBBACKUP-BINARY]
2718 [--slave-info] [--galera-info] [--stream=tar|xbstream]2565 [--slave-info] [--galera-info] [--stream=tar|xbstream]
2719 [--scpopt=OPTIONS-FOR-SCP] [--sshopt=OPTIONS-FOR-SSH]
2720 [--defaults-file=MY.CNF] [--defaults-group=GROUP-NAME]2566 [--defaults-file=MY.CNF] [--defaults-group=GROUP-NAME]
2721 [--databases=LIST] [--remote-host=HOSTNAME] [--no-lock] 2567 [--databases=LIST] [--no-lock]
2722 [--tmpdir=DIRECTORY] [--tables-file=FILE]2568 [--tmpdir=DIRECTORY] [--tables-file=FILE]
2723 [--incremental] [--incremental-basedir]2569 [--incremental] [--incremental-basedir]
2724 [--incremental-dir] [--incremental-lsn]2570 [--incremental-dir] [--incremental-lsn]
2571 [--compact]
2725 BACKUP-ROOT-DIR2572 BACKUP-ROOT-DIR
27262573
2727innobackupex --apply-log [--use-memory=B] [--uncompress]2574innobackupex --apply-log [--use-memory=B] [--uncompress]
@@ -2778,6 +2625,10 @@
27782625
2779Prepare 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".2626Prepare 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".
27802627
2628=item --compact
2629
2630Create a compact backup with all secondary index pages omitted. This option is passed directly to xtrabackup. See xtrabackup documentation for details.
2631
2781=item --compress2632=item --compress
27822633
2783This option instructs xtrabackup to compress backup copies of InnoDB2634This option instructs xtrabackup to compress backup copies of InnoDB
@@ -2875,10 +2726,6 @@
28752726
2876This 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. 2727This 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.
28772728
2878=item --remote-host=HOSTNAME
2879
2880This 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.
2881
2882=item --safe-slave-backup2729=item --safe-slave-backup
28832730
2884Stop 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.2731Stop 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.
@@ -2917,7 +2764,7 @@
29172764
2918=item --tmpdir=DIRECTORY2765=item --tmpdir=DIRECTORY
29192766
2920This 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.2767This 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.
29212768
2922=item --use-memory=B2769=item --use-memory=B
29232770
29242771
=== modified file 'src/Makefile'
--- src/Makefile 2012-02-10 20:05:56 +0000
+++ src/Makefile 2012-10-18 11:58:23 +0000
@@ -12,10 +12,10 @@
12LIBS += -lpthread12LIBS += -lpthread
13DEFS = -DUNIV_LINUX -DMYSQL_SERVER13DEFS = -DUNIV_LINUX -DMYSQL_SERVER
1414
15CFLAGS += -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=gnu9915CFLAGS += -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
1616
17ifneq ($(DEBUG),)17ifneq ($(DEBUG),)
18CFLAGS += -DXB_DEBUG=118CFLAGS += -DXB_DEBUG=1 -DUNIV_DEBUG
19endif19endif
2020
21TARGET=xtrabackup21TARGET=xtrabackup
@@ -23,7 +23,16 @@
23BIN_DIR=$(PREFIX)/bin23BIN_DIR=$(PREFIX)/bin
2424
25COMMON_INC = -I. -I libarchive/libarchive -I quicklz25COMMON_INC = -I. -I libarchive/libarchive -I quicklz
26XTRABACKUPOBJS = xtrabackup.o stream.o local.o compress.o xbstream_write.o \26XTRABACKUPOBJS = xtrabackup.o \
27 ds_stream.o \
28 ds_local.o \
29 ds_compress.o \
30 ds_tmpfile.o \
31 datasink.o \
32 write_filt.o \
33 fil_cur.o \
34 innodb_int.o \
35 xbstream_write.o \
27 quicklz/quicklz.o36 quicklz/quicklz.o
28XBSTREAMOBJS = xbstream.o xbstream_write.o xbstream_read.o37XBSTREAMOBJS = xbstream.o xbstream_write.o xbstream_read.o
2938
@@ -176,10 +185,10 @@
176xbstream.o xbstream_read.o: %.o: %.c185xbstream.o xbstream_read.o: %.o: %.c
177 $(CC) $(CFLAGS) $(INC) $(DEFS) -c $< -o $@186 $(CC) $(CFLAGS) $(INC) $(DEFS) -c $< -o $@
178187
179xbstream: $(XBSTREAMOBJS) $(MYSQLOBJS) local.o188xbstream: $(XBSTREAMOBJS) $(MYSQLOBJS) ds_local.o datasink.o
180 $(CC) $(CFLAGS) $^ $(INC) $(MYSQLOBJS) $(LIBS) -o $@189 $(CC) $(CFLAGS) $^ $(INC) $(MYSQLOBJS) $(LIBS) -o $@
181190
182xtrabackup.o: xtrabackup.c xb_regex.h191xtrabackup.o: xtrabackup.c xb_regex.h write_filt.h fil_cur.h xtrabackup.h
183192
184$(TARGET): $(XTRABACKUPOBJS) $(INNODBOBJS) $(MYSQLOBJS) $(LIBARCHIVE_A)193$(TARGET): $(XTRABACKUPOBJS) $(INNODBOBJS) $(MYSQLOBJS) $(LIBARCHIVE_A)
185 $(CC) $(CFLAGS) $(XTRABACKUPOBJS) $(INNODBOBJS) $(MYSQLOBJS) $(LIBS) \194 $(CC) $(CFLAGS) $(XTRABACKUPOBJS) $(INNODBOBJS) $(MYSQLOBJS) $(LIBS) \
186195
=== modified file 'src/common.h'
--- src/common.h 2012-02-10 20:05:56 +0000
+++ src/common.h 2012-10-18 11:58:23 +0000
@@ -24,12 +24,14 @@
24#include <my_global.h>24#include <my_global.h>
25#include <mysql_version.h>25#include <mysql_version.h>
26#include <fcntl.h>26#include <fcntl.h>
27#include <stdarg.h>
28#include "innodb_int.h"
2729
28#define xb_a(expr) \30#define xb_a(expr) \
29 do { \31 do { \
30 if (!(expr)) { \32 if (!(expr)) { \
31 msg("Assertion \"%s\" failed at %s:%lu\n", \33 msg("Assertion \"%s\" failed at %s:%lu\n", \
32 #expr, __FILE__, (unsigned long) __LINE__); \34 #expr, __FILE__, (ulint) __LINE__); \
33 abort(); \35 abort(); \
34 } \36 } \
35 } while (0);37 } while (0);
@@ -40,6 +42,8 @@
40#define xb_ad(expr)42#define xb_ad(expr)
41#endif43#endif
4244
45#define XB_DELTA_INFO_SUFFIX ".meta"
46
43static inline int msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);47static inline int msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
44static inline int msg(const char *fmt, ...)48static inline int msg(const char *fmt, ...)
45{49{
@@ -61,13 +65,29 @@
61/* Use POSIX_FADV_NORMAL when available */65/* Use POSIX_FADV_NORMAL when available */
6266
63#ifdef POSIX_FADV_NORMAL67#ifdef POSIX_FADV_NORMAL
64#define USE_POSIX_FADVISE68# define USE_POSIX_FADVISE
69#else
70# define POSIX_FADV_NORMAL
71# define POSIX_FADV_SEQUENTIAL
72# define POSIX_FADV_DONTNEED
73# define posix_fadvise(a,b,c,d) do {} while(0)
65#endif74#endif
6675
67typedef enum {76/***********************************************************************
68 XB_STREAM_FMT_NONE,77Computes bit shift for a given value. If the argument is not a power
69 XB_STREAM_FMT_TAR,78of 2, returns 0.*/
70 XB_STREAM_FMT_XBSTREAM79static inline ulint
71} xb_stream_fmt_t;80get_bit_shift(ulint value)
81{
82 ulint shift;
83
84 if (value == 0)
85 return 0;
86
87 for (shift = 0; !(value & 1UL); shift++) {
88 value >>= 1;
89 }
90 return (value >> 1) ? 0 : shift;
91}
7292
73#endif93#endif
7494
=== added file 'src/datasink.c'
--- src/datasink.c 1970-01-01 00:00:00 +0000
+++ src/datasink.c 2012-10-18 11:58:23 +0000
@@ -0,0 +1,113 @@
1/******************************************************
2Copyright (c) 2011 Percona Inc.
3
4Data sink interface.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19*******************************************************/
20
21#include <my_base.h>
22#include "common.h"
23#include "datasink.h"
24#include "ds_compress.h"
25#include "ds_stream.h"
26#include "ds_local.h"
27#include "ds_tmpfile.h"
28
29/************************************************************************
30Create a datasink of the specified type */
31ds_ctxt_t *
32ds_create(const char *root, ds_type_t type)
33{
34 datasink_t *ds;
35 ds_ctxt_t *ctxt;
36
37 switch (type) {
38 case DS_TYPE_LOCAL:
39 ds = &datasink_local;
40 break;
41 case DS_TYPE_STREAM:
42 ds = &datasink_stream;
43 break;
44 case DS_TYPE_COMPRESS:
45 ds = &datasink_compress;
46 break;
47 case DS_TYPE_TMPFILE:
48 ds = &datasink_tmpfile;
49 break;
50 default:
51 msg("Unknown datasink type: %d\n", type);
52 return NULL;
53 }
54
55 ctxt = ds->init(root);
56 if (ctxt != NULL) {
57 ctxt->datasink = ds;
58 } else {
59 msg("Error: failed to initialize datasink.\n");
60 exit(EXIT_FAILURE);
61 }
62
63 return ctxt;
64}
65
66/************************************************************************
67Open a datasink file */
68ds_file_t *
69ds_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat)
70{
71 ds_file_t *file;
72
73 file = ctxt->datasink->open(ctxt, path, stat);
74 if (file != NULL) {
75 file->datasink = ctxt->datasink;
76 }
77
78 return file;
79}
80
81/************************************************************************
82Write to a datasink file.
83@return 0 on success, 1 on error. */
84int
85ds_write(ds_file_t *file, const void *buf, size_t len)
86{
87 return file->datasink->write(file, buf, len);
88}
89
90/************************************************************************
91Close a datasink file.
92@return 0 on success, 1, on error. */
93int
94ds_close(ds_file_t *file)
95{
96 return file->datasink->close(file);
97}
98
99/************************************************************************
100Destroy a datasink handle */
101void
102ds_destroy(ds_ctxt_t *ctxt)
103{
104 ctxt->datasink->deinit(ctxt);
105}
106
107/************************************************************************
108Set the destination pipe for a datasink (only makes sense for compress and
109tmpfile). */
110void ds_set_pipe(ds_ctxt_t *ctxt, ds_ctxt_t *pipe_ctxt)
111{
112 ctxt->pipe_ctxt = pipe_ctxt;
113}
0114
=== modified file 'src/datasink.h'
--- src/datasink.h 2012-02-10 20:05:56 +0000
+++ src/datasink.h 2012-10-18 11:58:23 +0000
@@ -25,24 +25,62 @@
25#include <my_dir.h>25#include <my_dir.h>
2626
27struct datasink_struct;27struct datasink_struct;
28typedef struct datasink_struct datasink_t;
2829
29typedef struct {30typedef struct ds_ctxt {
30 struct datasink_struct *datasink;31 datasink_t *datasink;
31 char *root;32 char *root;
32 void *ptr;33 void *ptr;
34 struct ds_ctxt *pipe_ctxt;
33} ds_ctxt_t;35} ds_ctxt_t;
3436
35typedef struct {37typedef struct {
36 void *ptr;38 void *ptr;
37 char *path;39 char *path;
40 datasink_t *datasink;
38} ds_file_t;41} ds_file_t;
3942
40typedef struct datasink_struct {43struct datasink_struct {
41 ds_ctxt_t *(*init)(const char *root);44 ds_ctxt_t *(*init)(const char *root);
42 ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);45 ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
43 int (*write)(ds_file_t *file, const void *buf, size_t len);46 int (*write)(ds_file_t *file, const void *buf, size_t len);
44 int (*close)(ds_file_t *file);47 int (*close)(ds_file_t *file);
45 void (*deinit)(ds_ctxt_t *ctxt);48 void (*deinit)(ds_ctxt_t *ctxt);
46} datasink_t;49};
50
51/* Supported datasink types */
52typedef enum {
53 DS_TYPE_LOCAL,
54 DS_TYPE_STREAM,
55 DS_TYPE_COMPRESS,
56 DS_TYPE_TMPFILE
57} ds_type_t;
58
59/************************************************************************
60Create a datasink of the specified type */
61ds_ctxt_t *ds_create(const char *root, ds_type_t type);
62
63/************************************************************************
64Open a datasink file */
65ds_file_t *ds_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
66
67/************************************************************************
68Write to a datasink file.
69@return 0 on success, 1 on error. */
70int ds_write(ds_file_t *file, const void *buf, size_t len);
71
72/************************************************************************
73Close a datasink file.
74@return 0 on success, 1, on error. */
75int ds_close(ds_file_t *file);
76
77/************************************************************************
78Destroy a datasink handle */
79void ds_destroy(ds_ctxt_t *ctxt);
80
81/************************************************************************
82Set the destination pipe for a datasink (only makes sense for compress and
83tmpfile). */
84void ds_set_pipe(ds_ctxt_t *ctxt, ds_ctxt_t *pipe_ctxt);
4785
48#endif /* XB_DATASINK_H */86#endif /* XB_DATASINK_H */
4987
=== renamed file 'src/compress.c' => 'src/ds_compress.c'
--- src/compress.c 2012-06-14 10:50:28 +0000
+++ src/ds_compress.c 2012-10-18 11:58:23 +0000
@@ -25,8 +25,8 @@
25#include <zlib.h>25#include <zlib.h>
26#include "common.h"26#include "common.h"
27#include "datasink.h"27#include "datasink.h"
28#include "stream.h"28#include "ds_stream.h"
29#include "local.h"29#include "ds_local.h"
3030
31#define COMPRESS_CHUNK_SIZE (64 * 1024UL)31#define COMPRESS_CHUNK_SIZE (64 * 1024UL)
32#define MY_QLZ_COMPRESS_OVERHEAD 40032#define MY_QLZ_COMPRESS_OVERHEAD 400
@@ -50,20 +50,16 @@
50} comp_thread_ctxt_t;50} comp_thread_ctxt_t;
5151
52typedef struct {52typedef struct {
53 ds_ctxt_t *dest_ctxt;
54 comp_thread_ctxt_t *threads;53 comp_thread_ctxt_t *threads;
55 uint nthreads;54 uint nthreads;
56} ds_compress_ctxt_t;55} ds_compress_ctxt_t;
5756
58typedef struct {57typedef struct {
59 datasink_t *dest_ds;
60 ds_file_t *dest_file;58 ds_file_t *dest_file;
61 ds_compress_ctxt_t *comp_ctxt;59 ds_compress_ctxt_t *comp_ctxt;
62 size_t bytes_processed;60 size_t bytes_processed;
63} ds_compress_file_t;61} ds_compress_file_t;
6462
65extern ibool xtrabackup_stream;
66extern uint xtrabackup_parallel;
67extern ibool xtrabackup_compress_threads;63extern ibool xtrabackup_compress_threads;
6864
69static ds_ctxt_t *compress_init(const char *root);65static ds_ctxt_t *compress_init(const char *root);
@@ -81,10 +77,8 @@
81 &compress_deinit77 &compress_deinit
82};78};
8379
84static inline int write_uint32_le(datasink_t *sink, ds_file_t *file,80static inline int write_uint32_le(ds_file_t *file, ulong n);
85 ulong n);81static inline int write_uint64_le(ds_file_t *file, ulonglong n);
86static inline int write_uint64_le(datasink_t *sink, ds_file_t *file,
87 ulonglong n);
8882
89static comp_thread_ctxt_t *create_worker_threads(uint n);83static comp_thread_ctxt_t *create_worker_threads(uint n);
90static void destroy_worker_threads(comp_thread_ctxt_t *threads, uint n);84static void destroy_worker_threads(comp_thread_ctxt_t *threads, uint n);
@@ -96,25 +90,12 @@
96{90{
97 ds_ctxt_t *ctxt;91 ds_ctxt_t *ctxt;
98 ds_compress_ctxt_t *compress_ctxt;92 ds_compress_ctxt_t *compress_ctxt;
99 datasink_t *dest_ds;
100 ds_ctxt_t *dest_ctxt;
101 comp_thread_ctxt_t *threads;93 comp_thread_ctxt_t *threads;
10294
103 /* Decide whether the compressed data will be stored in local files or
104 streamed to an archive */
105 dest_ds = xtrabackup_stream ? &datasink_stream : &datasink_local;
106
107 dest_ctxt = dest_ds->init(root);
108 if (dest_ctxt == NULL) {
109 msg("compress: failed to initialize the target datasink.\n");
110 return NULL;
111 }
112
113 /* Create and initialize the worker threads */95 /* Create and initialize the worker threads */
114 threads = create_worker_threads(xtrabackup_compress_threads);96 threads = create_worker_threads(xtrabackup_compress_threads);
115 if (threads == NULL) {97 if (threads == NULL) {
116 msg("compress: failed to create worker threads.\n");98 msg("compress: failed to create worker threads.\n");
117 dest_ds->deinit(dest_ctxt);
118 return NULL;99 return NULL;
119 }100 }
120101
@@ -123,12 +104,11 @@
123 MYF(MY_FAE));104 MYF(MY_FAE));
124105
125 compress_ctxt = (ds_compress_ctxt_t *) (ctxt + 1);106 compress_ctxt = (ds_compress_ctxt_t *) (ctxt + 1);
126 compress_ctxt->dest_ctxt = dest_ctxt;
127 compress_ctxt->threads = threads;107 compress_ctxt->threads = threads;
128 compress_ctxt->nthreads = xtrabackup_compress_threads;108 compress_ctxt->nthreads = xtrabackup_compress_threads;
129109
130 ctxt->datasink = &datasink_compress;
131 ctxt->ptr = compress_ctxt;110 ctxt->ptr = compress_ctxt;
111 ctxt->root = my_strdup(root, MYF(MY_FAE));
132112
133 return ctxt;113 return ctxt;
134}114}
@@ -138,7 +118,6 @@
138compress_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)118compress_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
139{119{
140 ds_compress_ctxt_t *comp_ctxt;120 ds_compress_ctxt_t *comp_ctxt;
141 datasink_t *dest_ds;
142 ds_ctxt_t *dest_ctxt;121 ds_ctxt_t *dest_ctxt;
143 ds_file_t *dest_file;122 ds_file_t *dest_file;
144 char new_name[FN_REFLEN];123 char new_name[FN_REFLEN];
@@ -146,21 +125,22 @@
146 ds_file_t *file;125 ds_file_t *file;
147 ds_compress_file_t *comp_file;126 ds_compress_file_t *comp_file;
148127
128 xb_a(ctxt->pipe_ctxt != NULL);
129 dest_ctxt = ctxt->pipe_ctxt;
130
149 comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;131 comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;
150 dest_ctxt = comp_ctxt->dest_ctxt;
151 dest_ds = dest_ctxt->datasink;
152132
153 /* Append the .qp extension to the filename */133 /* Append the .qp extension to the filename */
154 fn_format(new_name, path, "", ".qp", MYF(MY_APPEND_EXT));134 fn_format(new_name, path, "", ".qp", MYF(MY_APPEND_EXT));
155135
156 dest_file = dest_ds->open(dest_ctxt, new_name, mystat);136 dest_file = ds_open(dest_ctxt, new_name, mystat);
157 if (dest_file == NULL) {137 if (dest_file == NULL) {
158 return NULL;138 return NULL;
159 }139 }
160140
161 /* Write the qpress archive header */141 /* Write the qpress archive header */
162 if (dest_ds->write(dest_file, "qpress10", 8) ||142 if (ds_write(dest_file, "qpress10", 8) ||
163 write_uint64_le(dest_ds, dest_file, COMPRESS_CHUNK_SIZE)) {143 write_uint64_le(dest_file, COMPRESS_CHUNK_SIZE)) {
164 goto err;144 goto err;
165 }145 }
166146
@@ -171,10 +151,10 @@
171151
172 /* Write the qpress file header */152 /* Write the qpress file header */
173 name_len = strlen(new_name);153 name_len = strlen(new_name);
174 if (dest_ds->write(dest_file, "F", 1) ||154 if (ds_write(dest_file, "F", 1) ||
175 write_uint32_le(dest_ds, dest_file, name_len) ||155 write_uint32_le(dest_file, name_len) ||
176 /* we want to write the terminating \0 as well */156 /* we want to write the terminating \0 as well */
177 dest_ds->write(dest_file, new_name, name_len + 1)) {157 ds_write(dest_file, new_name, name_len + 1)) {
178 goto err;158 goto err;
179 }159 }
180160
@@ -183,7 +163,6 @@
183 MYF(MY_FAE));163 MYF(MY_FAE));
184 comp_file = (ds_compress_file_t *) (file + 1);164 comp_file = (ds_compress_file_t *) (file + 1);
185 comp_file->dest_file = dest_file;165 comp_file->dest_file = dest_file;
186 comp_file->dest_ds = dest_ds;
187 comp_file->comp_ctxt = comp_ctxt;166 comp_file->comp_ctxt = comp_ctxt;
188 comp_file->bytes_processed = 0;167 comp_file->bytes_processed = 0;
189168
@@ -193,7 +172,7 @@
193 return file;172 return file;
194173
195err:174err:
196 dest_ds->close(dest_file);175 ds_close(dest_file);
197 return NULL;176 return NULL;
198}177}
199178
@@ -208,12 +187,10 @@
208 uint nthreads;187 uint nthreads;
209 uint i;188 uint i;
210 const char *ptr;189 const char *ptr;
211 datasink_t *dest_ds;
212 ds_file_t *dest_file;190 ds_file_t *dest_file;
213191
214 comp_file = (ds_compress_file_t *) file->ptr;192 comp_file = (ds_compress_file_t *) file->ptr;
215 comp_ctxt = comp_file->comp_ctxt;193 comp_ctxt = comp_file->comp_ctxt;
216 dest_ds = comp_file->dest_ds;
217 dest_file = comp_file->dest_file;194 dest_file = comp_file->dest_file;
218195
219 threads = comp_ctxt->threads;196 threads = comp_ctxt->threads;
@@ -262,8 +239,8 @@
262239
263 ut_a(threads[i].to_len > 0);240 ut_a(threads[i].to_len > 0);
264241
265 if (dest_ds->write(dest_file, "NEWBNEWB", 8) ||242 if (ds_write(dest_file, "NEWBNEWB", 8) ||
266 write_uint64_le(dest_ds, dest_file,243 write_uint64_le(dest_file,
267 comp_file->bytes_processed)) {244 comp_file->bytes_processed)) {
268 msg("compress: write to the destination stream "245 msg("compress: write to the destination stream "
269 "failed.\n");246 "failed.\n");
@@ -272,9 +249,8 @@
272249
273 comp_file->bytes_processed += threads[i].from_len;250 comp_file->bytes_processed += threads[i].from_len;
274251
275 if (write_uint32_le(dest_ds, dest_file,252 if (write_uint32_le(dest_file, threads[i].adler) ||
276 threads[i].adler) ||253 ds_write(dest_file, threads[i].to,
277 dest_ds->write(dest_file, threads[i].to,
278 threads[i].to_len)) {254 threads[i].to_len)) {
279 msg("compress: write to the destination stream "255 msg("compress: write to the destination stream "
280 "failed.\n");256 "failed.\n");
@@ -294,23 +270,21 @@
294compress_close(ds_file_t *file)270compress_close(ds_file_t *file)
295{271{
296 ds_compress_file_t *comp_file;272 ds_compress_file_t *comp_file;
297 datasink_t *dest_ds;
298 ds_file_t *dest_file;273 ds_file_t *dest_file;
299274
300 comp_file = (ds_compress_file_t *) file->ptr;275 comp_file = (ds_compress_file_t *) file->ptr;
301 dest_ds = comp_file->dest_ds;
302 dest_file = comp_file->dest_file;276 dest_file = comp_file->dest_file;
303277
304 /* Write the qpress file trailer */278 /* Write the qpress file trailer */
305 dest_ds->write(dest_file, "ENDSENDS", 8);279 ds_write(dest_file, "ENDSENDS", 8);
306280
307 /* Supposedly the number of written bytes should be written as a281 /* Supposedly the number of written bytes should be written as a
308 "recovery information" in the file trailer, but in reality qpress282 "recovery information" in the file trailer, but in reality qpress
309 always writes 8 zeros here. Let's do the same */283 always writes 8 zeros here. Let's do the same */
310284
311 write_uint64_le(dest_ds, dest_file, 0);285 write_uint64_le(dest_file, 0);
312286
313 dest_ds->close(dest_file);287 ds_close(dest_file);
314288
315 MY_FREE(file);289 MY_FREE(file);
316290
@@ -322,39 +296,37 @@
322compress_deinit(ds_ctxt_t *ctxt)296compress_deinit(ds_ctxt_t *ctxt)
323{297{
324 ds_compress_ctxt_t *comp_ctxt;298 ds_compress_ctxt_t *comp_ctxt;
325 ds_ctxt_t *dest_ctxt;299
326 datasink_t *dest_ds;300 xb_a(ctxt->pipe_ctxt != NULL);
327301
328 comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;;302 comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;;
329303
330 destroy_worker_threads(comp_ctxt->threads, comp_ctxt->nthreads);304 destroy_worker_threads(comp_ctxt->threads, comp_ctxt->nthreads);
331305
332 dest_ctxt = comp_ctxt->dest_ctxt;306 ds_destroy(ctxt->pipe_ctxt);
333 dest_ds = dest_ctxt->datasink;307
334308 MY_FREE(ctxt->root);
335 dest_ds->deinit(dest_ctxt);
336
337 MY_FREE(ctxt);309 MY_FREE(ctxt);
338}310}
339311
340static inline312static inline
341int313int
342write_uint32_le(datasink_t *sink, ds_file_t *file, ulong n)314write_uint32_le(ds_file_t *file, ulong n)
343{315{
344 char tmp[4];316 char tmp[4];
345317
346 int4store(tmp, n);318 int4store(tmp, n);
347 return sink->write(file, tmp, sizeof(tmp));319 return ds_write(file, tmp, sizeof(tmp));
348}320}
349321
350static inline322static inline
351int323int
352write_uint64_le(datasink_t *sink, ds_file_t *file, ulonglong n)324write_uint64_le(ds_file_t *file, ulonglong n)
353{325{
354 char tmp[8];326 char tmp[8];
355327
356 int8store(tmp, n);328 int8store(tmp, n);
357 return sink->write(file, tmp, sizeof(tmp));329 return ds_write(file, tmp, sizeof(tmp));
358}330}
359331
360static332static
@@ -489,14 +461,3 @@
489461
490 return NULL;462 return NULL;
491}463}
492
493/* Return a target datasink for the specified compress datasink */
494ds_ctxt_t *
495compress_get_dest_ctxt(ds_ctxt_t *ctxt)
496{
497 ds_compress_ctxt_t *comp_ctxt;
498
499 comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;
500
501 return comp_ctxt->dest_ctxt;
502}
503464
=== renamed file 'src/compress.h' => 'src/ds_compress.h'
--- src/compress.h 2012-06-14 10:50:28 +0000
+++ src/ds_compress.h 2012-10-18 11:58:23 +0000
@@ -18,14 +18,11 @@
1818
19*******************************************************/19*******************************************************/
2020
21#ifndef XB_COMPRESS_H21#ifndef DS_COMPRESS_H
22#define XB_COMPRESS_H22#define DS_COMPRESS_H
2323
24#include "datasink.h"24#include "datasink.h"
2525
26extern datasink_t datasink_compress;26extern datasink_t datasink_compress;
2727
28/* Return a target datasink for the specified compress datasink */
29ds_ctxt_t *compress_get_dest_ctxt(ds_ctxt_t *);
30
31#endif28#endif
3229
=== renamed file 'src/local.c' => 'src/ds_local.c'
--- src/local.c 2012-02-10 20:05:56 +0000
+++ src/ds_local.c 2012-10-18 11:58:23 +0000
@@ -57,7 +57,6 @@
5757
58 ctxt = my_malloc(sizeof(ds_ctxt_t), MYF(MY_FAE));58 ctxt = my_malloc(sizeof(ds_ctxt_t), MYF(MY_FAE));
5959
60 ctxt->datasink = &datasink_local;
61 ctxt->root = my_strdup(root, MYF(MY_FAE));60 ctxt->root = my_strdup(root, MYF(MY_FAE));
6261
63 return ctxt;62 return ctxt;
@@ -117,9 +116,7 @@
117 File fd = ((ds_local_file_t *) file->ptr)->fd;116 File fd = ((ds_local_file_t *) file->ptr)->fd;
118117
119 if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {118 if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
120#ifdef USE_POSIX_FADVISE
121 posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);119 posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
122#endif
123 return 0;120 return 0;
124 }121 }
125122
126123
=== renamed file 'src/local.h' => 'src/ds_local.h'
--- src/local.h 2012-02-10 20:05:56 +0000
+++ src/ds_local.h 2012-10-18 11:58:23 +0000
@@ -18,8 +18,8 @@
1818
19*******************************************************/19*******************************************************/
2020
21#ifndef XB_LOCAL_H21#ifndef DS_LOCAL_H
22#define XB_LOCAL_H22#define DS_LOCAL_H
2323
24#include "datasink.h"24#include "datasink.h"
2525
2626
=== renamed file 'src/stream.c' => 'src/ds_stream.c'
--- src/stream.c 2012-04-22 13:04:24 +0000
+++ src/ds_stream.c 2012-10-18 11:58:23 +0000
@@ -24,6 +24,7 @@
24#include "common.h"24#include "common.h"
25#include "datasink.h"25#include "datasink.h"
26#include "xbstream.h"26#include "xbstream.h"
27#include "xtrabackup.h"
2728
28typedef struct {29typedef struct {
29 struct archive *archive;30 struct archive *archive;
@@ -88,7 +89,10 @@
88 }89 }
8990
90 if (archive_write_set_compression_none(a) != ARCHIVE_OK ||91 if (archive_write_set_compression_none(a) != ARCHIVE_OK ||
91 archive_write_set_format_pax_restricted(a) != ARCHIVE_OK) {92 archive_write_set_format_pax_restricted(a) != ARCHIVE_OK ||
93 /* disable internal buffering so we don't have to flush the
94 output in xtrabackup */
95 archive_write_set_bytes_per_block(a, 0) != ARCHIVE_OK) {
92 msg("failed to set libarchive stream options: %s\n",96 msg("failed to set libarchive stream options: %s\n",
93 archive_error_string(a));97 archive_error_string(a));
94 archive_write_finish(a);98 archive_write_finish(a);
@@ -103,7 +107,6 @@
103 }107 }
104108
105109
106 ctxt->datasink = &datasink_stream;
107 ctxt->ptr = stream_ctxt;110 ctxt->ptr = stream_ctxt;
108111
109 return ctxt;112 return ctxt;
110113
=== renamed file 'src/stream.h' => 'src/ds_stream.h'
--- src/stream.h 2012-02-10 20:05:56 +0000
+++ src/ds_stream.h 2012-10-18 11:58:23 +0000
@@ -18,8 +18,8 @@
1818
19*******************************************************/19*******************************************************/
2020
21#ifndef XTRABACKUP_STREAM_H21#ifndef DS_STREAM_H
22#define XTRABACKUP_STREAM_H22#define DS_STREAM_H
2323
24#include "datasink.h"24#include "datasink.h"
2525
2626
=== added file 'src/ds_tmpfile.c'
--- src/ds_tmpfile.c 1970-01-01 00:00:00 +0000
+++ src/ds_tmpfile.c 2012-10-18 11:58:23 +0000
@@ -0,0 +1,243 @@
1/******************************************************
2Copyright (c) 2012 Percona Inc.
3
4tmpfile datasink for XtraBackup.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19*******************************************************/
20
21/* Do all writes to temporary files first, then pipe them to the specified
22datasink in a serialized way in deinit(). */
23
24#include <my_base.h>
25#include "common.h"
26#include "datasink.h"
27
28typedef struct {
29 pthread_mutex_t mutex;
30 LIST *file_list;
31} ds_tmpfile_ctxt_t;
32
33typedef struct {
34 LIST list;
35 File fd;
36 char *orig_path;
37 MY_STAT mystat;
38 ds_file_t *file;
39} ds_tmp_file_t;
40
41static ds_ctxt_t *tmpfile_init(const char *root);
42static ds_file_t *tmpfile_open(ds_ctxt_t *ctxt, const char *path,
43 MY_STAT *mystat);
44static int tmpfile_write(ds_file_t *file, const void *buf, size_t len);
45static int tmpfile_close(ds_file_t *file);
46static void tmpfile_deinit(ds_ctxt_t *ctxt);
47
48datasink_t datasink_tmpfile = {
49 &tmpfile_init,
50 &tmpfile_open,
51 &tmpfile_write,
52 &tmpfile_close,
53 &tmpfile_deinit
54};
55
56static ds_ctxt_t *
57tmpfile_init(const char *root)
58{
59 ds_ctxt_t *ctxt;
60 ds_tmpfile_ctxt_t *tmpfile_ctxt;
61
62 ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_tmpfile_ctxt_t),
63 MYF(MY_FAE));
64 tmpfile_ctxt = (ds_tmpfile_ctxt_t *) (ctxt + 1);
65 tmpfile_ctxt->file_list = NULL;
66 if (pthread_mutex_init(&tmpfile_ctxt->mutex, NULL)) {
67
68 MY_FREE(ctxt);
69 return NULL;
70 }
71
72 ctxt->ptr = tmpfile_ctxt;
73 ctxt->root = my_strdup(root, MYF(MY_FAE));
74
75 return ctxt;
76}
77
78static ds_file_t *
79tmpfile_open(ds_ctxt_t *ctxt, const char *path,
80 MY_STAT *mystat)
81{
82 ds_tmpfile_ctxt_t *tmpfile_ctxt;
83 char tmp_path[FN_REFLEN];
84 ds_tmp_file_t *tmp_file;
85 ds_file_t *file;
86 size_t path_len;
87 File fd;
88
89 /* Create a temporary file in tmpdir. The file will be automatically
90 removed on close. Code copied from mysql_tmpfile(). */
91 fd = create_temp_file(tmp_path, my_tmpdir(&mysql_tmpdir_list),
92 "xbtemp",
93#ifdef __WIN__
94 O_BINARY | O_TRUNC | O_SEQUENTIAL |
95 O_TEMPORARY | O_SHORT_LIVED |
96#endif /* __WIN__ */
97 O_CREAT | O_EXCL | O_RDWR,
98 MYF(MY_WME));
99
100#ifndef __WIN__
101 if (fd >= 0) {
102 /* On Windows, open files cannot be removed, but files can be
103 created with the O_TEMPORARY flag to the same effect
104 ("delete on close"). */
105 unlink(path);
106 }
107#endif /* !__WIN__ */
108
109 if (fd < 0) {
110 return NULL;
111 }
112
113 path_len = strlen(path) + 1; /* terminating '\0' */
114
115 file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
116 sizeof(ds_tmp_file_t) + path_len,
117 MYF(MY_FAE));
118
119 tmp_file = (ds_tmp_file_t *) (file + 1);
120 tmp_file->file = file;
121 memcpy(&tmp_file->mystat, mystat, sizeof(MY_STAT));
122 /* Save a copy of 'path', since it may not be accessible later */
123 tmp_file->orig_path = (char *) tmp_file + sizeof(ds_tmp_file_t);
124
125 tmp_file->fd = fd;
126 memcpy(tmp_file->orig_path, path, path_len);
127
128 /* Store the real temporary file name in file->path */
129 file->path = my_strdup(tmp_path, MYF(MY_FAE));
130 file->ptr = tmp_file;
131
132 /* Store the file object in the list to be piped later */
133 tmpfile_ctxt = (ds_tmpfile_ctxt_t *) ctxt->ptr;
134 tmp_file->list.data = tmp_file;
135
136 pthread_mutex_lock(&tmpfile_ctxt->mutex);
137 tmpfile_ctxt->file_list = list_add(tmpfile_ctxt->file_list,
138 &tmp_file->list);
139 pthread_mutex_unlock(&tmpfile_ctxt->mutex);
140
141 return file;
142}
143
144static int
145tmpfile_write(ds_file_t *file, const void *buf, size_t len)
146{
147 File fd = ((ds_tmp_file_t *) file->ptr)->fd;
148
149 if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
150 posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
151 return 0;
152 }
153
154 return 1;
155}
156
157static int
158tmpfile_close(ds_file_t *file)
159{
160 /* Do nothing -- we will close (and thus remove) the file after piping
161 it to the destination datasink in tmpfile_deinit(). */
162
163 MY_FREE(file->path);
164
165 return 0;
166}
167
168static void
169tmpfile_deinit(ds_ctxt_t *ctxt)
170{
171 LIST *list;
172 ds_tmpfile_ctxt_t *tmpfile_ctxt;
173 MY_STAT mystat;
174 ds_tmp_file_t *tmp_file;
175 ds_file_t *dst_file;
176 ds_ctxt_t *pipe_ctxt;
177 void *buf = NULL;
178 const size_t buf_size = 1024 * 1024;
179 size_t bytes;
180
181 pipe_ctxt = ctxt->pipe_ctxt;
182 xb_a(pipe_ctxt != NULL);
183
184 buf = my_malloc(buf_size, MYF(MY_FAE));
185
186 tmpfile_ctxt = (ds_tmpfile_ctxt_t *) ctxt->ptr;
187 list = tmpfile_ctxt->file_list;
188
189 /* Walk the files in the order they have been added */
190 list = list_reverse(list);
191 while (list != NULL) {
192 tmp_file = list->data;
193 /* Stat the file to replace size and mtime on the original
194 * mystat struct */
195 if (my_fstat(tmp_file->fd, &mystat, MYF(0))) {
196 msg("error: my_fstat() failed.\n");
197 exit(EXIT_FAILURE);
198 }
199 tmp_file->mystat.st_size = mystat.st_size;
200 tmp_file->mystat.st_mtime = mystat.st_mtime;
201
202 dst_file = ds_open(pipe_ctxt, tmp_file->orig_path,
203 &tmp_file->mystat);
204 if (dst_file == NULL) {
205 msg("error: could not stream a temporary file to "
206 "'%s'\n", tmp_file->orig_path);
207 exit(EXIT_FAILURE);
208 }
209
210 /* copy to the destination datasink */
211 posix_fadvise(tmp_file->fd, 0, 0, POSIX_FADV_SEQUENTIAL);
212 if (my_seek(tmp_file->fd, 0, SEEK_SET, MYF(0)) ==
213 MY_FILEPOS_ERROR) {
214 msg("error: my_seek() failed for '%s', errno = %d.\n",
215 tmp_file->file->path, my_errno);
216 exit(EXIT_FAILURE);
217 }
218 while ((bytes = my_read(tmp_file->fd, buf, buf_size,
219 MYF(MY_WME))) > 0) {
220 posix_fadvise(tmp_file->fd, 0, 0, POSIX_FADV_DONTNEED);
221 if (ds_write(dst_file, buf, bytes)) {
222 msg("error: cannot write to stream for '%s'.\n",
223 tmp_file->orig_path);
224 exit(EXIT_FAILURE);
225 }
226 }
227 if (bytes == (size_t) -1) {
228 exit(EXIT_FAILURE);
229 }
230
231 my_close(tmp_file->fd, MYF(MY_WME));
232 ds_close(dst_file);
233
234 list = list_rest(list);
235 MY_FREE(tmp_file->file);
236 }
237
238 pthread_mutex_destroy(&tmpfile_ctxt->mutex);
239
240 MY_FREE(buf);
241 MY_FREE(ctxt->root);
242 MY_FREE(ctxt);
243}
0244
=== added file 'src/ds_tmpfile.h'
--- src/ds_tmpfile.h 1970-01-01 00:00:00 +0000
+++ src/ds_tmpfile.h 2012-10-18 11:58:23 +0000
@@ -0,0 +1,28 @@
1/******************************************************
2Copyright (c) 2012 Percona Inc.
3
4tmpfile datasink for XtraBackup.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19*******************************************************/
20
21#ifndef DS_TMPFILE_H
22#define DS_TMPFILE_H
23
24#include "datasink.h"
25
26extern datasink_t datasink_tmpfile;
27
28#endif
029
=== added file 'src/fil_cur.c'
--- src/fil_cur.c 1970-01-01 00:00:00 +0000
+++ src/fil_cur.c 2012-10-18 11:58:23 +0000
@@ -0,0 +1,270 @@
1/******************************************************
2XtraBackup: hot backup tool for InnoDB
3(c) 2009-2012 Percona Inc.
4Originally Created 3/3/2009 Yasufumi Kinoshita
5Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
6Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; version 2 of the License.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21*******************************************************/
22
23/* Source file cursor implementation */
24
25#include <my_base.h>
26#include "innodb_int.h"
27#include <buf0buf.h>
28#include <fsp0types.h>
29#include "fil_cur.h"
30#include "common.h"
31#include "xtrabackup.h"
32
33/* Size of read buffer in pages */
34#define XB_FIL_CUR_PAGES 64
35
36/************************************************************************
37Open a source file cursor.
38
39@return XB_FIL_CUR_SUCCESS on success, XB_FIL_CUR_SKIP if the source file must
40be skipped and XB_FIL_CUR_ERROR on error. */
41xb_fil_cur_result_t
42xb_fil_cur_open(
43/*============*/
44 xb_fil_cur_t* cursor, /*!< out: source file cursor */
45 fil_node_t* node, /*!< in: source tablespace node */
46 uint thread_n) /*!< thread number for diagnostics */
47{
48 ulint page_size;
49 ulint page_size_shift;
50 ulint zip_size;
51
52 /* Initialize these first so xb_fil_cur_close() handles them correctly
53 in case of error */
54 cursor->orig_buf = NULL;
55 cursor->file = XB_FILE_UNDEFINED;
56
57 cursor->space_id = node->space->id;
58 cursor->is_system = trx_sys_sys_space(node->space->id);
59
60 /* Make the file path relative to the backup root,
61 i.e. "ibdata1" for system tablespace or database/table.ibd for
62 per-table spaces. */
63 if (cursor->is_system) {
64 char *next, *p;
65
66 p = node->name;
67 while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL) {
68 p = next + 1;
69 }
70 strncpy(cursor->path, p, sizeof(cursor->path));
71 } else {
72 /* file per table style "./database/table.ibd" */
73 strncpy(cursor->path, node->name, sizeof(cursor->path));
74 }
75
76 /* Open the file */
77
78 if (my_stat(node->name, &cursor->statinfo, MYF(MY_WME)) == NULL) {
79 msg("[%02u] xtrabackup: Warning: cannot stat %s\n",
80 thread_n, node->name);
81 return(XB_FIL_CUR_SKIP);
82 }
83
84 if (!node->open) {
85 ibool success;
86
87 cursor->file =
88 xb_file_create_no_error_handling(node->name,
89 OS_FILE_OPEN,
90 OS_FILE_READ_ONLY,
91 &success);
92 if (!success) {
93 /* The following call prints an error message */
94 os_file_get_last_error(TRUE);
95
96 msg("[%02u] xtrabackup: Warning: cannot open %s\n"
97 "[%02u] xtrabackup: Warning: We assume the "
98 "table was dropped or renamed during "
99 "xtrabackup execution and ignore the file.\n",
100 thread_n, node->name, thread_n);
101 return(XB_FIL_CUR_SKIP);
102 }
103
104 xb_file_set_nocache(cursor->file, node->name, "OPEN");
105 } else {
106 cursor->file = node->handle;
107 }
108 posix_fadvise(cursor->file, 0, 0, POSIX_FADV_SEQUENTIAL);
109
110 /* Determine the page size */
111#ifndef INNODB_VERSION_SHORT
112 zip_size = UNIV_PAGE_SIZE;
113 page_size = UNIV_PAGE_SIZE;
114 page_size_shift = UNIV_PAGE_SIZE_SHIFT;
115#else
116 zip_size = xb_get_zip_size(cursor->file);
117 if (zip_size == ULINT_UNDEFINED) {
118 os_file_close(cursor->file);
119 return(XB_FIL_CUR_SKIP);
120 } else if (zip_size) {
121 page_size = zip_size;
122 page_size_shift = get_bit_shift(page_size);
123 msg("[%02u] %s is compressed with page size = "
124 "%lu bytes\n", thread_n, node->name, page_size);
125 if (page_size_shift < 10 || page_size_shift > 14) {
126 msg("[%02u] xtrabackup: Error: Invalid "
127 "page size: %lu.\n", thread_n, page_size);
128 ut_error;
129 }
130 } else {
131 page_size = UNIV_PAGE_SIZE;
132 page_size_shift = UNIV_PAGE_SIZE_SHIFT;
133 }
134#endif
135 cursor->page_size = page_size;
136 cursor->page_size_shift = page_size_shift;
137 cursor->zip_size = zip_size;
138
139 /* Allocate read buffer */
140 cursor->buf_size = XB_FIL_CUR_PAGES * page_size;
141 cursor->orig_buf = ut_malloc(cursor->buf_size + UNIV_PAGE_SIZE);
142 cursor->buf = ut_align(cursor->orig_buf, UNIV_PAGE_SIZE);
143
144 cursor->offset = 0;
145 cursor->buf_read = 0;
146 cursor->buf_npages = 0;
147 cursor->buf_offset = 0;
148 cursor->buf_page_no = 0;
149 cursor->thread_n = thread_n;
150
151 return(XB_FIL_CUR_SUCCESS);
152}
153
154/************************************************************************
155Reads and verifies the next block of pages from the source
156file. Positions the cursor after the last read non-corrupted page.
157
158@return XB_FIL_CUR_SUCCESS if some have been read successfully, XB_FIL_CUR_EOF
159if there are no more pages to read and XB_FIL_CUR_ERROR on error. */
160xb_fil_cur_result_t
161xb_fil_cur_read(
162/*============*/
163 xb_fil_cur_t* cursor) /*!< in/out: source file cursor */
164{
165 ibool success;
166 ulint page_size;
167 ulint offset_high;
168 ulint offset_low;
169 byte* page;
170 ulint i;
171 ulint npages;
172 ulint retry_count;
173 xb_fil_cur_result_t ret;
174 IB_INT64 to_read;
175
176 page_size = cursor->page_size;
177
178 offset_high = (ulint) (cursor->offset >> 32);
179 offset_low = (ulint) (cursor->offset & 0xFFFFFFFFUL);
180
181 to_read = (IB_INT64) cursor->statinfo.st_size - cursor->offset;
182
183 if (to_read == 0LL) {
184 return(XB_FIL_CUR_EOF);
185 }
186
187 if (to_read > (IB_INT64) cursor->buf_size) {
188 to_read = (IB_INT64) cursor->buf_size;
189 }
190 ut_a(to_read > 0 && to_read <= 0xFFFFFFFFLL);
191 ut_a(to_read % page_size == 0);
192
193 npages = (ulint) (to_read >> cursor->page_size_shift);
194
195 retry_count = 10;
196 ret = XB_FIL_CUR_SUCCESS;
197
198read_retry:
199 xtrabackup_io_throttling();
200
201 cursor->buf_read = 0;
202 cursor->buf_npages = 0;
203 cursor->buf_offset = cursor->offset;
204 cursor->buf_page_no = (ulint) (cursor->offset >>
205 cursor->page_size_shift);
206
207 success = os_file_read(cursor->file, cursor->buf,
208 offset_low, offset_high, to_read);
209 if (!success) {
210 return(XB_FIL_CUR_ERROR);
211 }
212
213 /* check pages for corruption and re-read if necessary. i.e. in case of
214 partially written pages */
215 for (page = cursor->buf, i = 0; i < npages; page += page_size, i++) {
216 if (xb_buf_page_is_corrupted(page, cursor->zip_size))
217 {
218 ulint page_no = cursor->buf_page_no + i;
219
220 if (cursor->is_system &&
221 page_no >= FSP_EXTENT_SIZE &&
222 page_no < FSP_EXTENT_SIZE * 3) {
223 /* skip doublewrite buffer pages */
224 ut_a(page_size == UNIV_PAGE_SIZE);
225 msg("[%02lu] xtrabackup: "
226 "Page %lu is a doublewrite buffer page, "
227 "skipping.\n", cursor->thread_n, page_no);
228 } else {
229 retry_count--;
230 if (retry_count == 0) {
231 msg("[%02lu] xtrabackup: "
232 "Error: failed to read page after "
233 "10 retries. File %s seems to be "
234 "corrupted.\n", cursor->thread_n,
235 cursor->path);
236 ret = XB_FIL_CUR_ERROR;
237 break;
238 }
239 msg("[%02lu] xtrabackup: "
240 "Database page corruption detected at page "
241 "%lu, retrying...\n", cursor->thread_n,
242 page_no);
243 goto read_retry;
244 }
245 }
246 cursor->buf_read += page_size;
247 cursor->buf_npages++;
248 }
249
250 posix_fadvise(cursor->file, 0, 0, POSIX_FADV_DONTNEED);
251
252 cursor->offset += page_size * i;
253
254 return(ret);
255}
256
257/************************************************************************
258Close the source file cursor opened with xb_fil_cur_open(). */
259void
260xb_fil_cur_close(
261/*=============*/
262 xb_fil_cur_t *cursor) /*!< in/out: source file cursor */
263{
264 if (cursor->orig_buf != NULL) {
265 ut_free(cursor->orig_buf);
266 }
267 if (cursor->file != XB_FILE_UNDEFINED) {
268 os_file_close(cursor->file);
269 }
270}
0271
=== added file 'src/fil_cur.h'
--- src/fil_cur.h 1970-01-01 00:00:00 +0000
+++ src/fil_cur.h 2012-10-18 11:58:23 +0000
@@ -0,0 +1,96 @@
1/******************************************************
2XtraBackup: hot backup tool for InnoDB
3(c) 2009-2012 Percona Inc.
4Originally Created 3/3/2009 Yasufumi Kinoshita
5Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
6Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; version 2 of the License.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21*******************************************************/
22
23/* Source file cursor interface */
24
25#ifndef FIL_CUR_H
26#define FIL_CUR_H
27
28#include <my_dir.h>
29#include "innodb_int.h"
30
31typedef struct {
32 os_file_t file; /*!< source file handle */
33 char path[FN_REFLEN];/*!< normalized file path */
34 MY_STAT statinfo; /*!< information about the file */
35 ulint zip_size; /*!< compressed page size in bytes or 0
36 for uncompressed pages */
37 ulint page_size; /*!< = zip_size for compressed pages or
38 UNIV_PAGE_SIZE for uncompressed ones */
39 ulint page_size_shift;/*!< bit shift corresponding to
40 page_size */
41 IB_INT64 offset; /*!< current file offset in bytes */
42 my_bool is_system; /*!< TRUE for system tablespace, FALSE
43 otherwise */
44 byte* orig_buf; /*!< read buffer */
45 byte* buf; /*!< aligned pointer for orig_buf */
46 ulint buf_size; /*!< buffer size in bytes */
47 ulint buf_read; /*!< number of read bytes in buffer
48 after the last cursor read */
49 ulint buf_npages; /*!< number of pages in buffer after the
50 last cursor read */
51 IB_INT64 buf_offset; /*!< file offset of the first page in
52 buffer */
53 ulint buf_page_no; /*!< number of the first page in
54 buffer */
55 ulint thread_n; /*!< thread number for diagnostics */
56 ulint space_id; /*!< ID of tablespace */
57} xb_fil_cur_t;
58
59typedef enum {
60 XB_FIL_CUR_SUCCESS,
61 XB_FIL_CUR_SKIP,
62 XB_FIL_CUR_ERROR,
63 XB_FIL_CUR_EOF
64} xb_fil_cur_result_t;
65
66/************************************************************************
67Open a source file cursor.
68
69@return XB_FIL_CUR_SUCCESS on success, XB_FIL_CUR_SKIP if the source file must
70be skipped and XB_FIL_CUR_ERROR on error. */
71xb_fil_cur_result_t
72xb_fil_cur_open(
73/*============*/
74 xb_fil_cur_t* cursor, /*!< out: source file cursor */
75 fil_node_t* node, /*!< in: source tablespace node */
76 uint thread_n); /*!< thread number for diagnostics */
77
78/************************************************************************
79Reads and verifies the next block of pages from the source
80file. Positions the cursor after the last read non-corrupted page.
81
82@return XB_FIL_CUR_SUCCESS if some have been read successfully, XB_FIL_CUR_EOF
83if there are no more pages to read and XB_FIL_CUR_ERROR on error. */
84xb_fil_cur_result_t
85xb_fil_cur_read(
86/*============*/
87 xb_fil_cur_t* cursor); /*!< in/out: source file cursor */
88
89/************************************************************************
90Close the source file cursor opened with xb_fil_cur_open(). */
91void
92xb_fil_cur_close(
93/*=============*/
94 xb_fil_cur_t *cursor); /*!< in/out: source file cursor */
95
96#endif
097
=== added file 'src/innodb_int.c'
--- src/innodb_int.c 1970-01-01 00:00:00 +0000
+++ src/innodb_int.c 2012-10-18 11:58:23 +0000
@@ -0,0 +1,983 @@
1/******************************************************
2XtraBackup: hot backup tool for InnoDB
3(c) 2009-2012 Percona Inc.
4Originally Created 3/3/2009 Yasufumi Kinoshita
5Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
6Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; version 2 of the License.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21*******************************************************/
22
23/* InnoDB portability helpers and interface to internal functions */
24
25#include <my_base.h>
26#include <mysql_com.h>
27#include "innodb_int.h"
28#include <srv0srv.h>
29#include <ha_prototypes.h>
30#include <trx0trx.h>
31#include "common.h"
32
33extern long innobase_lock_wait_timeout;
34
35char *opt_mysql_tmpdir = NULL;
36MY_TMPDIR mysql_tmpdir_list;
37
38
39/****************************************************************//**
40A simple function to open or create a file.
41@return own: handle to the file, not defined if error, error number
42can be retrieved with os_file_get_last_error */
43os_file_t
44xb_file_create_no_error_handling(
45/*=============================*/
46 const char* name, /*!< in: name of the file or path as a
47 null-terminated string */
48 ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
49 is opened (if does not exist, error), or
50 OS_FILE_CREATE if a new file is created
51 (if exists, error) */
52 ulint access_type,/*!< in: OS_FILE_READ_ONLY,
53 OS_FILE_READ_WRITE, or
54 OS_FILE_READ_ALLOW_DELETE; the last option is
55 used by a backup program reading the file */
56 ibool* success)/*!< out: TRUE if succeed, FALSE if error */
57{
58#if MYSQL_VERSION_ID > 50500
59 return os_file_create_simple_no_error_handling(
60 0, /* innodb_file_data_key */
61 name, create_mode, access_type, success);
62#else
63 return os_file_create_simple_no_error_handling(
64 name, create_mode, access_type, success);
65#endif
66}
67
68/****************************************************************//**
69Opens an existing file or creates a new.
70@return own: handle to the file, not defined if error, error number
71can be retrieved with os_file_get_last_error */
72os_file_t
73xb_file_create(
74/*===========*/
75 const char* name, /*!< in: name of the file or path as a
76 null-terminated string */
77 ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
78 is opened (if does not exist, error), or
79 OS_FILE_CREATE if a new file is created
80 (if exists, error),
81 OS_FILE_OVERWRITE if a new file is created
82 or an old overwritten;
83 OS_FILE_OPEN_RAW, if a raw device or disk
84 partition should be opened */
85 ulint purpose,/*!< in: OS_FILE_AIO, if asynchronous,
86 non-buffered i/o is desired,
87 OS_FILE_NORMAL, if any normal file;
88 NOTE that it also depends on type, os_aio_..
89 and srv_.. variables whether we really use
90 async i/o or unbuffered i/o: look in the
91 function source code for the exact rules */
92 ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
93 ibool* success)/*!< out: TRUE if succeed, FALSE if error */
94{
95#if MYSQL_VERSION_ID > 50500
96 return os_file_create(0 /* innodb_file_data_key */,
97 name, create_mode, purpose, type, success);
98#else
99 return os_file_create(name, create_mode, purpose, type, success);
100#endif
101}
102
103/***********************************************************************//**
104Renames a file (can also move it to another directory). It is safest that the
105file is closed before calling this function.
106@return TRUE if success */
107ibool
108xb_file_rename(
109/*===========*/
110 const char* oldpath,/*!< in: old file path as a null-terminated
111 string */
112 const char* newpath)/*!< in: new file path */
113{
114#if MYSQL_VERSION_ID > 50500
115 return os_file_rename(
116 0 /* innodb_file_data_key */, oldpath, newpath);
117#else
118 return os_file_rename(oldpath, newpath);
119#endif
120}
121
122void
123xb_file_set_nocache(
124/*================*/
125 os_file_t fd, /* in: file descriptor to alter */
126 const char* file_name, /* in: used in the diagnostic message */
127 const char* operation_name) /* in: used in the diagnostic message,
128 we call os_file_set_nocache()
129 immediately after opening or creating
130 a file, so this is either "open" or
131 "create" */
132{
133#ifndef __WIN__
134 if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
135 os_file_set_nocache(fd, file_name, operation_name);
136 }
137#endif
138}
139
140/***********************************************************************//**
141Compatibility wrapper around os_file_flush().
142@return TRUE if success */
143ibool
144xb_file_flush(
145/*==========*/
146 os_file_t file) /*!< in, own: handle to a file */
147{
148#ifdef XTRADB_BASED
149 return os_file_flush(file, TRUE);
150#else
151 return os_file_flush(file);
152#endif
153}
154/*******************************************************************//**
155Returns the table space by a given id, NULL if not found. */
156fil_space_t*
157xb_space_get_by_id(
158/*================*/
159 ulint id) /*!< in: space id */
160{
161 fil_space_t* space;
162
163 ut_ad(mutex_own(&fil_system->mutex));
164
165#ifdef INNODB_VERSION_SHORT
166 HASH_SEARCH(hash, fil_system->spaces, id,
167 fil_space_t*, space,
168 ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
169 space->id == id);
170#else
171 HASH_SEARCH(hash, fil_system->spaces, id, space, space->id == id);
172#endif
173
174 return(space);
175}
176
177/*******************************************************************//**
178Returns the table space by a given name, NULL if not found. */
179fil_space_t*
180xb_space_get_by_name(
181/*==================*/
182 const char* name) /*!< in: space name */
183{
184 fil_space_t* space;
185 ulint fold;
186
187 ut_ad(mutex_own(&fil_system->mutex));
188
189#ifdef INNODB_VERSION_SHORT
190 fold = ut_fold_string(name);
191 HASH_SEARCH(name_hash, fil_system->name_hash, fold,
192 fil_space_t*, space,
193 ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
194 !strcmp(name, space->name));
195#else
196 HASH_SEARCH(name_hash, fil_system->name_hash, ut_fold_string(name),
197 space, 0 == strcmp(name, space->name));
198#endif
199
200 return(space);
201}
202
203/****************************************************************//**
204Create a new tablespace on disk and return the handle to its opened
205file. Code adopted from fil_create_new_single_table_tablespace with
206the main difference that only disk file is created without updating
207the InnoDB in-memory dictionary data structures.
208
209@return TRUE on success, FALSE on error. */
210ibool
211xb_space_create_file(
212/*==================*/
213 const char* path, /*!<in: path to tablespace */
214 ulint space_id, /*!<in: space id */
215 ulint flags __attribute__((unused)),/*!<in: tablespace
216 flags */
217 os_file_t* file) /*!<out: file handle */
218{
219 ibool ret;
220 byte* buf;
221 byte* page;
222
223 *file = xb_file_create_no_error_handling(path, OS_FILE_CREATE,
224 OS_FILE_READ_WRITE, &ret);
225 if (!ret) {
226 msg("xtrabackup: cannot create file %s\n", path);
227 return ret;
228 }
229
230 ret = os_file_set_size(path, *file,
231 FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE, 0);
232 if (!ret) {
233 msg("xtrabackup: cannot set size for file %s\n", path);
234 os_file_close(*file);
235 os_file_delete(path);
236 return ret;
237 }
238
239 buf = ut_malloc(3 * UNIV_PAGE_SIZE);
240 /* Align the memory for file i/o if we might have O_DIRECT set */
241 page = ut_align(buf, UNIV_PAGE_SIZE);
242
243 memset(page, '\0', UNIV_PAGE_SIZE);
244
245#ifdef INNODB_VERSION_SHORT
246 fsp_header_init_fields(page, space_id, flags);
247 mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
248
249 if (!(flags & DICT_TF_ZSSIZE_MASK)) {
250 buf_flush_init_for_writing(page, NULL, 0);
251
252 ret = os_file_write(path, *file, page, 0, 0, UNIV_PAGE_SIZE);
253 }
254 else {
255 page_zip_des_t page_zip;
256 ulint zip_size;
257
258 zip_size = (PAGE_ZIP_MIN_SIZE >> 1)
259 << ((flags & DICT_TF_ZSSIZE_MASK)
260 >> DICT_TF_ZSSIZE_SHIFT);
261 page_zip_set_size(&page_zip, zip_size);
262 page_zip.data = page + UNIV_PAGE_SIZE;
263 fprintf(stderr, "zip_size = %lu\n", zip_size);
264
265#ifdef UNIV_DEBUG
266 page_zip.m_start =
267#endif /* UNIV_DEBUG */
268 page_zip.m_end = page_zip.m_nonempty =
269 page_zip.n_blobs = 0;
270
271 buf_flush_init_for_writing(page, &page_zip, 0);
272
273 ret = os_file_write(path, *file, page_zip.data, 0, 0,
274 zip_size);
275 }
276#else
277 fsp_header_write_space_id(page, space_id);
278
279 buf_flush_init_for_writing(page, ut_dulint_zero, space_id, 0);
280
281 ret = os_file_write(path, *file, page, 0, 0, UNIV_PAGE_SIZE);
282#endif
283
284 ut_free(buf);
285
286 if (!ret) {
287 msg("xtrabackup: could not write the first page to %s\n",
288 path);
289 os_file_close(*file);
290 os_file_delete(path);
291 return ret;
292 }
293
294 return TRUE;
295}
296
297
298#ifndef INNODB_VERSION_SHORT
299
300/********************************************************************//**
301Extract the compressed page size from table flags.
302@return compressed page size, or 0 if not compressed */
303ulint
304dict_table_flags_to_zip_size(
305/*=========================*/
306 ulint flags) /*!< in: flags */
307{
308 ulint zip_size = flags & DICT_TF_ZSSIZE_MASK;
309
310 if (UNIV_UNLIKELY(zip_size)) {
311 zip_size = ((PAGE_ZIP_MIN_SIZE >> 1)
312 << (zip_size >> DICT_TF_ZSSIZE_SHIFT));
313
314 ut_ad(zip_size <= UNIV_PAGE_SIZE);
315 }
316
317 return(zip_size);
318}
319
320
321/*******************************************************************//**
322Free all spaces in space_list. */
323void
324fil_free_all_spaces(void)
325/*=====================*/
326{
327 fil_space_t* space;
328
329 mutex_enter(&fil_system->mutex);
330
331 space = UT_LIST_GET_FIRST(fil_system->space_list);
332
333 while (space != NULL) {
334 fil_node_t* node;
335 fil_space_t* prev_space = space;
336
337 space = UT_LIST_GET_NEXT(space_list, space);
338
339 fil_space_free(prev_space->id, FALSE);
340 }
341
342 mutex_exit(&fil_system->mutex);
343}
344
345#endif
346
347void
348innobase_invalidate_query_cache(
349 trx_t* trx,
350#ifndef INNODB_VERSION_SHORT
351 char* full_name,
352#else
353 const char* full_name,
354#endif
355 ulint full_name_len)
356{
357 (void)trx;
358 (void)full_name;
359 (void)full_name_len;
360 /* do nothing */
361}
362
363int
364mysql_get_identifier_quote_char(
365 trx_t* trx,
366 const char* name,
367 ulint namelen)
368{
369 (void)trx;
370 (void)name;
371 (void)namelen;
372 return '"';
373}
374
375void
376innobase_print_identifier(
377 FILE* f,
378 trx_t* trx __attribute__((unused)),
379 ibool table_id __attribute__((unused)),
380 const char* name,
381 ulint namelen)
382{
383 const char* s = name;
384 const char* e = s + namelen;
385 int q;
386
387 q = '"';
388
389 putc(q, f);
390 while (s < e) {
391 int c = *s++;
392 if (c == q) {
393 putc(c, f);
394 }
395 putc(c, f);
396 }
397 putc(q, f);
398}
399
400/**********************************************************************//**
401It should be safe to use lower_case_table_names=0 for xtrabackup. If it causes
402any problems, we can add the lower_case_table_names option to xtrabackup
403later.
404@return 0 */
405ulint
406innobase_get_lower_case_table_names(void)
407/*=====================================*/
408{
409 return(0);
410}
411
412/******************************************************************//**
413Strip dir name from a full path name and return only the file name
414@return file name or "null" if no file name */
415const char*
416innobase_basename(
417/*==============*/
418 const char* path_name) /*!< in: full path name */
419{
420 const char* name = base_name(path_name);
421
422 return((name) ? name : "null");
423}
424
425/*****************************************************************//**
426Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
427and quote it if needed.
428@return pointer to the end of buf */
429static
430char*
431innobase_convert_identifier(
432/*========================*/
433 char* buf, /*!< out: buffer for converted identifier */
434 ulint buflen, /*!< in: length of buf, in bytes */
435 const char* id, /*!< in: identifier to convert */
436 ulint idlen, /*!< in: length of id, in bytes */
437 void* thd __attribute__((unused)),
438 /*!< in: MySQL connection thread, or NULL */
439 ibool file_id __attribute__((unused)))
440 /*!< in: TRUE=id is a table or database name;
441 FALSE=id is an UTF-8 string */
442{
443 const char* s = id;
444 int q;
445
446 /* See if the identifier needs to be quoted. */
447 q = '"';
448
449 if (q == EOF) {
450 if (UNIV_UNLIKELY(idlen > buflen)) {
451 idlen = buflen;
452 }
453 memcpy(buf, s, idlen);
454 return(buf + idlen);
455 }
456
457 /* Quote the identifier. */
458 if (buflen < 2) {
459 return(buf);
460 }
461
462 *buf++ = q;
463 buflen--;
464
465 for (; idlen; idlen--) {
466 int c = *s++;
467 if (UNIV_UNLIKELY(c == q)) {
468 if (UNIV_UNLIKELY(buflen < 3)) {
469 break;
470 }
471
472 *buf++ = c;
473 *buf++ = c;
474 buflen -= 2;
475 } else {
476 if (UNIV_UNLIKELY(buflen < 2)) {
477 break;
478 }
479
480 *buf++ = c;
481 buflen--;
482 }
483 }
484
485 *buf++ = q;
486 return(buf);
487}
488
489/*****************************************************************//**
490Convert a table or index name to the MySQL system_charset_info (UTF-8)
491and quote it if needed.
492@return pointer to the end of buf */
493char*
494innobase_convert_name(
495/*==================*/
496 char* buf, /*!< out: buffer for converted identifier */
497 ulint buflen, /*!< in: length of buf, in bytes */
498 const char* id, /*!< in: identifier to convert */
499 ulint idlen, /*!< in: length of id, in bytes */
500 void* thd, /*!< in: MySQL connection thread, or NULL */
501 ibool table_id)/*!< in: TRUE=id is a table or database name;
502 FALSE=id is an index name */
503{
504 char* s = buf;
505 const char* bufend = buf + buflen;
506
507 if (table_id) {
508 const char* slash = (const char*) memchr(id, '/', idlen);
509 if (!slash) {
510
511 goto no_db_name;
512 }
513
514 /* Print the database name and table name separately. */
515 s = innobase_convert_identifier(s, bufend - s, id, slash - id,
516 thd, TRUE);
517 if (UNIV_LIKELY(s < bufend)) {
518 *s++ = '.';
519 s = innobase_convert_identifier(s, bufend - s,
520 slash + 1, idlen
521 - (slash - id) - 1,
522 thd, TRUE);
523 }
524#ifdef INNODB_VERSION_SHORT
525 } else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
526 /* Temporary index name (smart ALTER TABLE) */
527 const char temp_index_suffix[]= "--temporary--";
528
529 s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
530 thd, FALSE);
531 if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
532 memcpy(s, temp_index_suffix,
533 sizeof temp_index_suffix - 1);
534 s += sizeof temp_index_suffix - 1;
535 }
536#endif
537 } else {
538no_db_name:
539 s = innobase_convert_identifier(buf, buflen, id, idlen,
540 thd, table_id);
541 }
542
543 return(s);
544
545}
546
547ibool
548trx_is_interrupted(
549 trx_t* trx)
550{
551 (void)trx;
552 /* There are no mysql_thd */
553 return(FALSE);
554}
555
556int
557innobase_mysql_cmp(
558 int mysql_type,
559 uint charset_number,
560 unsigned char* a,
561 unsigned int a_length,
562 unsigned char* b,
563 unsigned int b_length)
564{
565 CHARSET_INFO* charset;
566 enum enum_field_types mysql_tp;
567 int ret;
568
569 DBUG_ASSERT(a_length != UNIV_SQL_NULL);
570 DBUG_ASSERT(b_length != UNIV_SQL_NULL);
571
572 mysql_tp = (enum enum_field_types) mysql_type;
573
574 switch (mysql_tp) {
575
576 case MYSQL_TYPE_BIT:
577 case MYSQL_TYPE_STRING:
578 case MYSQL_TYPE_VAR_STRING:
579 case FIELD_TYPE_TINY_BLOB:
580 case FIELD_TYPE_MEDIUM_BLOB:
581 case FIELD_TYPE_BLOB:
582 case FIELD_TYPE_LONG_BLOB:
583 case MYSQL_TYPE_VARCHAR:
584 /* Use the charset number to pick the right charset struct for
585 the comparison. Since the MySQL function get_charset may be
586 slow before Bar removes the mutex operation there, we first
587 look at 2 common charsets directly. */
588
589 if (charset_number == default_charset_info->number) {
590 charset = default_charset_info;
591 } else if (charset_number == my_charset_latin1.number) {
592 charset = &my_charset_latin1;
593 } else {
594 charset = get_charset(charset_number, MYF(MY_WME));
595
596 if (charset == NULL) {
597 msg("xtrabackup: InnoDB needs charset %lu for "
598 "doing a comparison, but MySQL cannot "
599 "find that charset.\n",
600 (ulong) charset_number);
601 ut_a(0);
602 }
603 }
604
605 /* Starting from 4.1.3, we use strnncollsp() in comparisons of
606 non-latin1_swedish_ci strings. NOTE that the collation order
607 changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
608 having indexes on such data need to rebuild their tables! */
609
610 ret = charset->coll->strnncollsp(charset,
611 a, a_length,
612 b, b_length, 0);
613 if (ret < 0) {
614 return(-1);
615 } else if (ret > 0) {
616 return(1);
617 } else {
618 return(0);
619 }
620 default:
621 assert(0);
622 }
623
624 return(0);
625}
626
627ulint
628innobase_get_at_most_n_mbchars(
629 ulint charset_id,
630 ulint prefix_len,
631 ulint data_len,
632 const char* str)
633{
634 ulint char_length; /* character length in bytes */
635 ulint n_chars; /* number of characters in prefix */
636 CHARSET_INFO* charset; /* charset used in the field */
637
638 charset = get_charset((uint) charset_id, MYF(MY_WME));
639
640 ut_ad(charset);
641 ut_ad(charset->mbmaxlen);
642
643 /* Calculate how many characters at most the prefix index contains */
644
645 n_chars = prefix_len / charset->mbmaxlen;
646
647 /* If the charset is multi-byte, then we must find the length of the
648 first at most n chars in the string. If the string contains less
649 characters than n, then we return the length to the end of the last
650 character. */
651
652 if (charset->mbmaxlen > 1) {
653 /* my_charpos() returns the byte length of the first n_chars
654 characters, or a value bigger than the length of str, if
655 there were not enough full characters in str.
656
657 Why does the code below work:
658 Suppose that we are looking for n UTF-8 characters.
659
660 1) If the string is long enough, then the prefix contains at
661 least n complete UTF-8 characters + maybe some extra
662 characters + an incomplete UTF-8 character. No problem in
663 this case. The function returns the pointer to the
664 end of the nth character.
665
666 2) If the string is not long enough, then the string contains
667 the complete value of a column, that is, only complete UTF-8
668 characters, and we can store in the column prefix index the
669 whole string. */
670
671 char_length = my_charpos(charset, str,
672 str + data_len, (int) n_chars);
673 if (char_length > data_len) {
674 char_length = data_len;
675 }
676 } else {
677 if (data_len < prefix_len) {
678 char_length = data_len;
679 } else {
680 char_length = prefix_len;
681 }
682 }
683
684 return(char_length);
685}
686
687ibool
688innobase_query_is_update(void)
689{
690 msg("xtrabackup: innobase_query_is_update() is called\n");
691 return(0);
692}
693
694#ifdef INNODB_VERSION_SHORT
695ulint
696innobase_raw_format(
697/*================*/
698 const char* data, /*!< in: raw data */
699 ulint data_len, /*!< in: raw data length
700 in bytes */
701 ulint charset_coll, /*!< in: charset collation */
702 char* buf, /*!< out: output buffer */
703 ulint buf_size) /*!< in: output buffer size
704 in bytes */
705{
706 (void)data;
707 (void)data_len;
708 (void)charset_coll;
709 (void)buf;
710 (void)buf_size;
711
712 msg("xtrabackup: innobase_raw_format() is called\n");
713 return(0);
714}
715
716ulong
717thd_lock_wait_timeout(
718/*==================*/
719 void* thd) /*!< in: thread handle (THD*), or NULL to query
720 the global innodb_lock_wait_timeout */
721{
722 (void)thd;
723 return(innobase_lock_wait_timeout);
724}
725
726ibool
727thd_supports_xa(
728/*============*/
729 void* thd) /*!< in: thread handle (THD*), or NULL to query
730 the global innodb_supports_xa */
731{
732 (void)thd;
733 return(FALSE);
734}
735
736ibool
737trx_is_strict(
738/*==========*/
739 trx_t* trx) /*!< in: transaction */
740{
741 (void)trx;
742 return(FALSE);
743}
744
745#ifdef XTRADB_BASED
746trx_t*
747innobase_get_trx()
748{
749 return(NULL);
750}
751
752ibool
753innobase_get_slow_log()
754{
755 return(FALSE);
756}
757#endif
758#endif
759
760ibool
761thd_is_replication_slave_thread(
762 void* thd)
763{
764 (void)thd;
765 msg("xtrabackup: thd_is_replication_slave_thread() is called\n");
766 return(FALSE);
767}
768
769ibool
770thd_has_edited_nontrans_tables(
771 void* thd)
772{
773 (void)thd;
774 msg("xtrabackup: thd_has_edited_nontrans_tables() is called\n");
775 return(FALSE);
776}
777
778ibool
779thd_is_select(
780 const void* thd)
781{
782 (void)thd;
783 msg("xtrabackup: thd_is_select() is called\n");
784 return(FALSE);
785}
786
787void
788innobase_mysql_prepare_print_arbitrary_thd(void)
789{
790 /* do nothing */
791}
792
793void
794innobase_mysql_end_print_arbitrary_thd(void)
795{
796 /* do nothing */
797}
798
799void
800innobase_mysql_print_thd(
801 FILE* f,
802 void* input_thd,
803 uint max_query_len)
804{
805 (void)f;
806 (void)input_thd;
807 (void)max_query_len;
808 msg("xtrabackup: innobase_mysql_print_thd() is called\n");
809}
810
811void
812innobase_get_cset_width(
813 ulint cset,
814 ulint* mbminlen,
815 ulint* mbmaxlen)
816{
817 CHARSET_INFO* cs;
818 ut_ad(cset < 256);
819 ut_ad(mbminlen);
820 ut_ad(mbmaxlen);
821
822 cs = all_charsets[cset];
823 if (cs) {
824 *mbminlen = cs->mbminlen;
825 *mbmaxlen = cs->mbmaxlen;
826 } else {
827 ut_a(cset == 0);
828 *mbminlen = *mbmaxlen = 0;
829 }
830}
831
832void
833innobase_convert_from_table_id(
834#ifdef INNODB_VERSION_SHORT
835 struct charset_info_st* cs,
836#endif
837 char* to,
838 const char* from,
839 ulint len)
840{
841#ifdef INNODB_VERSION_SHORT
842 (void)cs;
843#endif
844 (void)to;
845 (void)from;
846 (void)len;
847
848 msg("xtrabackup: innobase_convert_from_table_id() is called\n");
849}
850
851void
852innobase_convert_from_id(
853#ifdef INNODB_VERSION_SHORT
854 struct charset_info_st* cs,
855#endif
856 char* to,
857 const char* from,
858 ulint len)
859{
860#ifdef INNODB_VERSION_SHORT
861 (void)cs;
862#endif
863 (void)to;
864 (void)from;
865 (void)len;
866 msg("xtrabackup: innobase_convert_from_id() is called\n");
867}
868
869int
870innobase_strcasecmp(
871 const char* a,
872 const char* b)
873{
874 return(my_strcasecmp(&my_charset_utf8_general_ci, a, b));
875}
876
877void
878innobase_casedn_str(
879 char* a)
880{
881 my_casedn_str(&my_charset_utf8_general_ci, a);
882}
883
884struct charset_info_st*
885innobase_get_charset(
886 void* mysql_thd)
887{
888 (void)mysql_thd;
889 msg("xtrabackup: innobase_get_charset() is called\n");
890 return(NULL);
891}
892
893const char*
894innobase_get_stmt(
895 void* mysql_thd,
896 size_t* length)
897{
898 (void)mysql_thd;
899 (void)length;
900 msg("xtrabackup: innobase_get_stmt() is called\n");
901 return("nothing");
902}
903
904int
905innobase_mysql_tmpfile(void)
906{
907 char filename[FN_REFLEN];
908 int fd2 = -1;
909 File fd = create_temp_file(filename, my_tmpdir(&mysql_tmpdir_list), "ib",
910#ifdef __WIN__
911 O_BINARY | O_TRUNC | O_SEQUENTIAL |
912 O_TEMPORARY | O_SHORT_LIVED |
913#endif /* __WIN__ */
914 O_CREAT | O_EXCL | O_RDWR,
915 MYF(MY_WME));
916 if (fd >= 0) {
917#ifndef __WIN__
918 /* On Windows, open files cannot be removed, but files can be
919 created with the O_TEMPORARY flag to the same effect
920 ("delete on close"). */
921 unlink(filename);
922#endif /* !__WIN__ */
923 /* Copy the file descriptor, so that the additional resources
924 allocated by create_temp_file() can be freed by invoking
925 my_close().
926
927 Because the file descriptor returned by this function
928 will be passed to fdopen(), it will be closed by invoking
929 fclose(), which in turn will invoke close() instead of
930 my_close(). */
931#ifdef _WIN32
932 /* Note that on Windows, the integer returned by mysql_tmpfile
933 has no relation to C runtime file descriptor. Here, we need
934 to call my_get_osfhandle to get the HANDLE and then convert it
935 to C runtime filedescriptor. */
936 {
937 HANDLE hFile = my_get_osfhandle(fd);
938 HANDLE hDup;
939 BOOL bOK =
940 DuplicateHandle(GetCurrentProcess(), hFile,
941 GetCurrentProcess(), &hDup, 0,
942 FALSE, DUPLICATE_SAME_ACCESS);
943 if(bOK) {
944 fd2 = _open_osfhandle((intptr_t)hDup,0);
945 }
946 else {
947 my_osmaperr(GetLastError());
948 fd2 = -1;
949 }
950 }
951#else
952 fd2 = dup(fd);
953#endif
954 if (fd2 < 0) {
955 msg("xtrabackup: Got error %d on dup\n",fd2);
956 }
957 my_close(fd, MYF(MY_WME));
958 }
959 return(fd2);
960}
961
962#if MYSQL_VERSION_ID >= 50507
963/*
964 As of MySQL 5.5.7, InnoDB uses thd_wait plugin service.
965 We have to provide mock functions to avoid linker errors.
966*/
967#include <mysql/plugin.h>
968#include <mysql/service_thd_wait.h>
969
970void thd_wait_begin(MYSQL_THD thd, int wait_type)
971{
972 (void)thd;
973 (void)wait_type;
974 return;
975}
976
977void thd_wait_end(MYSQL_THD thd)
978{
979 (void)thd;
980 return;
981}
982
983#endif /* MYSQL_VERSION_ID >= 50507 */
0984
=== added file 'src/innodb_int.h'
--- src/innodb_int.h 1970-01-01 00:00:00 +0000
+++ src/innodb_int.h 2012-10-18 11:58:23 +0000
@@ -0,0 +1,695 @@
1/******************************************************
2XtraBackup: hot backup tool for InnoDB
3(c) 2009-2012 Percona Inc.
4Originally Created 3/3/2009 Yasufumi Kinoshita
5Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
6Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; version 2 of the License.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21*******************************************************/
22
23/* InnoDB portability helpers and interface to internal functions */
24
25#ifndef INNODB_INT_H
26#define INNODB_INT_H
27
28#include <my_base.h>
29#include <univ.i>
30#include <fil0fil.h>
31#include <os0file.h>
32#include <hash0hash.h>
33#include <btr0sea.h>
34#include <log0log.h>
35#include <log0recv.h>
36#include <trx0sys.h>
37
38#ifndef INNODB_VERSION_SHORT
39# define IB_INT64 ib_longlong
40# define LSN64 dulint
41# define MACH_READ_64 mach_read_from_8
42# define MACH_WRITE_64 mach_write_to_8
43# define OS_MUTEX_CREATE() os_mutex_create(NULL)
44# define xb_buf_page_is_corrupted(page, zip_size) buf_page_is_corrupted(page)
45# define xb_fil_space_create(name, space_id, zip_size, purpose) \
46 fil_space_create(name, space_id, purpose)
47# define PAGE_ZIP_MIN_SIZE_SHIFT 10
48# define PAGE_ZIP_MIN_SIZE (1 << PAGE_ZIP_MIN_SIZE_SHIFT)
49# define DICT_TF_ZSSIZE_SHIFT 1
50# define DICT_TF_ZSSIZE_MASK (15 << DICT_TF_ZSSIZE_SHIFT)
51# define DICT_TF_FORMAT_ZIP 1
52# define DICT_TF_FORMAT_SHIFT 5
53# define SRV_SHUTDOWN_NONE 0
54#else
55# define IB_INT64 ib_int64_t
56# define LSN64 ib_uint64_t
57# if (MYSQL_VERSION_ID < 50500)
58# define MACH_READ_64 mach_read_ull
59# define MACH_WRITE_64 mach_write_ull
60# define OS_MUTEX_CREATE() os_mutex_create(NULL)
61# else
62# define MACH_READ_64 mach_read_from_8
63# define MACH_WRITE_64 mach_write_to_8
64# define OS_MUTEX_CREATE() os_mutex_create()
65# endif
66# define xb_buf_page_is_corrupted(page, zip_size) \
67 buf_page_is_corrupted(page, zip_size)
68# define xb_fil_space_create(name, space_id, zip_size, purpose) \
69 fil_space_create(name, space_id, zip_size, purpose)
70# define ut_dulint_zero 0
71# define ut_dulint_cmp(A, B) (A > B ? 1 : (A == B ? 0 : -1))
72# define ut_dulint_add(A, B) (A + B)
73# define ut_dulint_minus(A, B) (A - B)
74# define ut_dulint_align_down(A, B) (A & ~((ib_int64_t)B - 1))
75# define ut_dulint_align_up(A, B) ((A + B - 1) & ~((ib_int64_t)B - 1))
76#endif
77
78#ifndef XTRADB_BASED
79#define trx_sys_sys_space(id) (id == 0)
80#endif
81
82#ifdef __WIN__
83#define SRV_PATH_SEPARATOR '\\'
84#define SRV_PATH_SEPARATOR_STR "\\"
85#else
86#define SRV_PATH_SEPARATOR '/'
87#define SRV_PATH_SEPARATOR_STR "/"
88#endif
89
90#ifndef UNIV_PAGE_SIZE_MAX
91#define UNIV_PAGE_SIZE_MAX UNIV_PAGE_SIZE
92#endif
93#ifndef UNIV_PAGE_SIZE_SHIFT_MAX
94#define UNIV_PAGE_SIZE_SHIFT_MAX UNIV_PAGE_SIZE_SHIFT
95#endif
96
97#ifdef __WIN__
98#define XB_FILE_UNDEFINED NULL
99#else
100#define XB_FILE_UNDEFINED (-1)
101#endif
102
103#ifdef INNODB_VERSION_SHORT
104#define XB_HASH_SEARCH(NAME, TABLE, FOLD, DATA, ASSERTION, TEST) \
105 HASH_SEARCH(NAME, TABLE, FOLD, xtrabackup_tables_t*, DATA, ASSERTION, \
106 TEST)
107#else
108#define XB_HASH_SEARCH(NAME, TABLE, FOLD, DATA, ASSERTION, TEST) \
109 HASH_SEARCH(NAME, TABLE, FOLD, DATA, TEST)
110#endif
111
112/* ==start === definition at fil0fil.c === */
113// ##################################################################
114// NOTE: We should check the following definitions fit to the source.
115// ##################################################################
116
117#ifndef INNODB_VERSION_SHORT
118//5.0 5.1
119/* File node of a tablespace or the log data space */
120struct fil_node_struct {
121 fil_space_t* space; /* backpointer to the space where this node
122 belongs */
123 char* name; /* path to the file */
124 ibool open; /* TRUE if file open */
125 os_file_t handle; /* OS handle to the file, if file open */
126 ibool is_raw_disk;/* TRUE if the 'file' is actually a raw
127 device or a raw disk partition */
128 ulint size; /* size of the file in database pages, 0 if
129 not known yet; the possible last incomplete
130 megabyte may be ignored if space == 0 */
131 ulint n_pending;
132 /* count of pending i/o's on this file;
133 closing of the file is not allowed if
134 this is > 0 */
135 ulint n_pending_flushes;
136 /* count of pending flushes on this file;
137 closing of the file is not allowed if
138 this is > 0 */
139 ib_longlong modification_counter;/* when we write to the file we
140 increment this by one */
141 ib_longlong flush_counter;/* up to what modification_counter value
142 we have flushed the modifications to disk */
143 UT_LIST_NODE_T(fil_node_t) chain;
144 /* link field for the file chain */
145 UT_LIST_NODE_T(fil_node_t) LRU;
146 /* link field for the LRU list */
147 ulint magic_n;
148};
149
150struct fil_space_struct {
151 char* name; /* space name = the path to the first file in
152 it */
153 ulint id; /* space id */
154 ib_longlong tablespace_version;
155 /* in DISCARD/IMPORT this timestamp is used to
156 check if we should ignore an insert buffer
157 merge request for a page because it actually
158 was for the previous incarnation of the
159 space */
160 ibool mark; /* this is set to TRUE at database startup if
161 the space corresponds to a table in the InnoDB
162 data dictionary; so we can print a warning of
163 orphaned tablespaces */
164 ibool stop_ios;/* TRUE if we want to rename the .ibd file of
165 tablespace and want to stop temporarily
166 posting of new i/o requests on the file */
167 ibool stop_ibuf_merges;
168 /* we set this TRUE when we start deleting a
169 single-table tablespace */
170 ibool is_being_deleted;
171 /* this is set to TRUE when we start
172 deleting a single-table tablespace and its
173 file; when this flag is set no further i/o
174 or flush requests can be placed on this space,
175 though there may be such requests still being
176 processed on this space */
177 ulint purpose;/* FIL_TABLESPACE, FIL_LOG, or FIL_ARCH_LOG */
178 UT_LIST_BASE_NODE_T(fil_node_t) chain;
179 /* base node for the file chain */
180 ulint size; /* space size in pages; 0 if a single-table
181 tablespace whose size we do not know yet;
182 last incomplete megabytes in data files may be
183 ignored if space == 0 */
184 ulint n_reserved_extents;
185 /* number of reserved free extents for
186 ongoing operations like B-tree page split */
187 ulint n_pending_flushes; /* this is > 0 when flushing
188 the tablespace to disk; dropping of the
189 tablespace is forbidden if this is > 0 */
190 ulint n_pending_ibuf_merges;/* this is > 0 when merging
191 insert buffer entries to a page so that we
192 may need to access the ibuf bitmap page in the
193 tablespade: dropping of the tablespace is
194 forbidden if this is > 0 */
195 hash_node_t hash; /* hash chain node */
196 hash_node_t name_hash;/* hash chain the name_hash table */
197 rw_lock_t latch; /* latch protecting the file space storage
198 allocation */
199 UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
200 /* list of spaces with at least one unflushed
201 file we have written to */
202 ibool is_in_unflushed_spaces; /* TRUE if this space is
203 currently in the list above */
204 UT_LIST_NODE_T(fil_space_t) space_list;
205 /* list of all spaces */
206 ibuf_data_t* ibuf_data;
207 /* insert buffer data */
208 ulint magic_n;
209};
210typedef struct fil_system_struct fil_system_t;
211struct fil_system_struct {
212 mutex_t mutex; /* The mutex protecting the cache */
213 hash_table_t* spaces; /* The hash table of spaces in the
214 system; they are hashed on the space
215 id */
216 hash_table_t* name_hash; /* hash table based on the space
217 name */
218 UT_LIST_BASE_NODE_T(fil_node_t) LRU;
219 /* base node for the LRU list of the
220 most recently used open files with no
221 pending i/o's; if we start an i/o on
222 the file, we first remove it from this
223 list, and return it to the start of
224 the list when the i/o ends;
225 log files and the system tablespace are
226 not put to this list: they are opened
227 after the startup, and kept open until
228 shutdown */
229 UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
230 /* base node for the list of those
231 tablespaces whose files contain
232 unflushed writes; those spaces have
233 at least one file node where
234 modification_counter > flush_counter */
235 ulint n_open; /* number of files currently open */
236 ulint max_n_open; /* n_open is not allowed to exceed
237 this */
238 ib_longlong modification_counter;/* when we write to a file we
239 increment this by one */
240 ulint max_assigned_id;/* maximum space id in the existing
241 tables, or assigned during the time
242 mysqld has been up; at an InnoDB
243 startup we scan the data dictionary
244 and set here the maximum of the
245 space id's of the tables there */
246 ib_longlong tablespace_version;
247 /* a counter which is incremented for
248 every space object memory creation;
249 every space mem object gets a
250 'timestamp' from this; in DISCARD/
251 IMPORT this is used to check if we
252 should ignore an insert buffer merge
253 request */
254 UT_LIST_BASE_NODE_T(fil_space_t) space_list;
255 /* list of all file spaces */
256};
257#else
258//Plugin ?
259/** File node of a tablespace or the log data space */
260struct fil_node_struct {
261 fil_space_t* space; /*!< backpointer to the space where this node
262 belongs */
263 char* name; /*!< path to the file */
264 ibool open; /*!< TRUE if file open */
265 os_file_t handle; /*!< OS handle to the file, if file open */
266 ibool is_raw_disk;/*!< TRUE if the 'file' is actually a raw
267 device or a raw disk partition */
268 ulint size; /*!< size of the file in database pages, 0 if
269 not known yet; the possible last incomplete
270 megabyte may be ignored if space == 0 */
271 ulint n_pending;
272 /*!< count of pending i/o's on this file;
273 closing of the file is not allowed if
274 this is > 0 */
275 ulint n_pending_flushes;
276 /*!< count of pending flushes on this file;
277 closing of the file is not allowed if
278 this is > 0 */
279 ib_int64_t modification_counter;/*!< when we write to the file we
280 increment this by one */
281 ib_int64_t flush_counter;/*!< up to what
282 modification_counter value we have
283 flushed the modifications to disk */
284 UT_LIST_NODE_T(fil_node_t) chain;
285 /*!< link field for the file chain */
286 UT_LIST_NODE_T(fil_node_t) LRU;
287 /*!< link field for the LRU list */
288 ulint magic_n;/*!< FIL_NODE_MAGIC_N */
289};
290
291struct fil_space_struct {
292 char* name; /*!< space name = the path to the first file in
293 it */
294 ulint id; /*!< space id */
295 ib_int64_t tablespace_version;
296 /*!< in DISCARD/IMPORT this timestamp
297 is used to check if we should ignore
298 an insert buffer merge request for a
299 page because it actually was for the
300 previous incarnation of the space */
301 ibool mark; /*!< this is set to TRUE at database startup if
302 the space corresponds to a table in the InnoDB
303 data dictionary; so we can print a warning of
304 orphaned tablespaces */
305 ibool stop_ios;/*!< TRUE if we want to rename the
306 .ibd file of tablespace and want to
307 stop temporarily posting of new i/o
308 requests on the file */
309 ibool stop_ibuf_merges;
310 /*!< we set this TRUE when we start
311 deleting a single-table tablespace */
312 ibool is_being_deleted;
313 /*!< this is set to TRUE when we start
314 deleting a single-table tablespace and its
315 file; when this flag is set no further i/o
316 or flush requests can be placed on this space,
317 though there may be such requests still being
318 processed on this space */
319 ulint purpose;/*!< FIL_TABLESPACE, FIL_LOG, or
320 FIL_ARCH_LOG */
321 UT_LIST_BASE_NODE_T(fil_node_t) chain;
322 /*!< base node for the file chain */
323 ulint size; /*!< space size in pages; 0 if a single-table
324 tablespace whose size we do not know yet;
325 last incomplete megabytes in data files may be
326 ignored if space == 0 */
327 ulint flags; /*!< compressed page size and file format, or 0
328 */
329 ulint n_reserved_extents;
330 /*!< number of reserved free extents for
331 ongoing operations like B-tree page split */
332 ulint n_pending_flushes; /*!< this is positive when flushing
333 the tablespace to disk; dropping of the
334 tablespace is forbidden if this is positive */
335 ulint n_pending_ibuf_merges;/*!< this is positive
336 when merging insert buffer entries to
337 a page so that we may need to access
338 the ibuf bitmap page in the
339 tablespade: dropping of the tablespace
340 is forbidden if this is positive */
341 hash_node_t hash; /*!< hash chain node */
342 hash_node_t name_hash;/*!< hash chain the name_hash table */
343#ifndef UNIV_HOTBACKUP
344 rw_lock_t latch; /*!< latch protecting the file space storage
345 allocation */
346#endif /* !UNIV_HOTBACKUP */
347 UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
348 /*!< list of spaces with at least one unflushed
349 file we have written to */
350 ibool is_in_unflushed_spaces; /*!< TRUE if this space is
351 currently in unflushed_spaces */
352#ifdef XTRADB_BASED
353 ibool is_corrupt;
354#endif
355 UT_LIST_NODE_T(fil_space_t) space_list;
356 /*!< list of all spaces */
357 ulint magic_n;/*!< FIL_SPACE_MAGIC_N */
358};
359
360typedef struct fil_system_struct fil_system_t;
361
362struct fil_system_struct {
363#ifndef UNIV_HOTBACKUP
364 mutex_t mutex; /*!< The mutex protecting the cache */
365#ifdef XTRADB_BASED
366 mutex_t file_extend_mutex;
367#endif
368#endif /* !UNIV_HOTBACKUP */
369 hash_table_t* spaces; /*!< The hash table of spaces in the
370 system; they are hashed on the space
371 id */
372 hash_table_t* name_hash; /*!< hash table based on the space
373 name */
374 UT_LIST_BASE_NODE_T(fil_node_t) LRU;
375 /*!< base node for the LRU list of the
376 most recently used open files with no
377 pending i/o's; if we start an i/o on
378 the file, we first remove it from this
379 list, and return it to the start of
380 the list when the i/o ends;
381 log files and the system tablespace are
382 not put to this list: they are opened
383 after the startup, and kept open until
384 shutdown */
385 UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
386 /*!< base node for the list of those
387 tablespaces whose files contain
388 unflushed writes; those spaces have
389 at least one file node where
390 modification_counter > flush_counter */
391 ulint n_open; /*!< number of files currently open */
392 ulint max_n_open; /*!< n_open is not allowed to exceed
393 this */
394 ib_int64_t modification_counter;/*!< when we write to a file we
395 increment this by one */
396 ulint max_assigned_id;/*!< maximum space id in the existing
397 tables, or assigned during the time
398 mysqld has been up; at an InnoDB
399 startup we scan the data dictionary
400 and set here the maximum of the
401 space id's of the tables there */
402 ib_int64_t tablespace_version;
403 /*!< a counter which is incremented for
404 every space object memory creation;
405 every space mem object gets a
406 'timestamp' from this; in DISCARD/
407 IMPORT this is used to check if we
408 should ignore an insert buffer merge
409 request */
410 UT_LIST_BASE_NODE_T(fil_space_t) space_list;
411 /*!< list of all file spaces */
412 ibool space_id_reuse_warned;
413 /* !< TRUE if fil_space_create()
414 has issued a warning about
415 potential space_id reuse */
416};
417
418#endif /* INNODB_VERSION_SHORT */
419
420extern fil_system_t* fil_system;
421extern char *opt_mysql_tmpdir;
422extern MY_TMPDIR mysql_tmpdir_list;
423
424/** Value of fil_space_struct::magic_n */
425#define FIL_SPACE_MAGIC_N 89472
426
427/* ==end=== definition at fil0fil.c === */
428
429/* prototypes for static functions in original */
430#ifndef INNODB_VERSION_SHORT
431page_t*
432btr_node_ptr_get_child(
433/*===================*/
434 /* out: child page, x-latched */
435 rec_t* node_ptr,/* in: node pointer */
436 const ulint* offsets,/* in: array returned by rec_get_offsets() */
437 mtr_t* mtr); /* in: mtr */
438#else
439buf_block_t*
440btr_node_ptr_get_child(
441/*===================*/
442 const rec_t* node_ptr,/*!< in: node pointer */
443 dict_index_t* index, /*!< in: index */
444 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
445 mtr_t* mtr); /*!< in: mtr */
446
447buf_block_t*
448btr_root_block_get(
449/*===============*/
450 dict_index_t* index, /*!< in: index tree */
451 mtr_t* mtr); /*!< in: mtr */
452#endif
453
454int
455fil_file_readdir_next_file(
456/*=======================*/
457 /* out: 0 if ok, -1 if error even after the
458 retries, 1 if at the end of the directory */
459 ulint* err, /* out: this is set to DB_ERROR if an error
460 was encountered, otherwise not changed */
461 const char* dirname,/* in: directory name or path */
462 os_file_dir_t dir, /* in: directory stream */
463 os_file_stat_t* info); /* in/out: buffer where the info is returned */
464
465ibool
466recv_check_cp_is_consistent(
467/*========================*/
468 /* out: TRUE if ok */
469 byte* buf); /* in: buffer containing checkpoint info */
470
471ulint
472recv_find_max_checkpoint(
473/*=====================*/
474 /* out: error code or DB_SUCCESS */
475 log_group_t** max_group, /* out: max group */
476 ulint* max_field); /* out: LOG_CHECKPOINT_1 or
477 LOG_CHECKPOINT_2 */
478
479ibool
480log_block_checksum_is_ok_or_old_format(
481/*===================================*/
482 /* out: TRUE if ok, or if the log block may be in the
483 format of InnoDB version < 3.23.52 */
484 byte* block); /* in: pointer to a log block */
485
486ulint
487open_or_create_log_file(
488/*====================*/
489 /* out: DB_SUCCESS or error code */
490 ibool create_new_db, /* in: TRUE if we should create a
491 new database */
492 ibool* log_file_created, /* out: TRUE if new log file
493 created */
494 ibool log_file_has_been_opened,/* in: TRUE if a log file has been
495 opened before: then it is an error
496 to try to create another log file */
497 ulint k, /* in: log group number */
498 ulint i); /* in: log file number in group */
499
500ulint
501open_or_create_data_files(
502/*======================*/
503 /* out: DB_SUCCESS or error code */
504 ibool* create_new_db, /* out: TRUE if new database should be
505 created */
506#ifdef XTRADB_BASED
507 ibool* create_new_doublewrite_file,
508#endif
509#ifdef UNIV_LOG_ARCHIVE
510 ulint* min_arch_log_no,/* out: min of archived log numbers in data
511 files */
512 ulint* max_arch_log_no,/* out: */
513#endif /* UNIV_LOG_ARCHIVE */
514 LSN64* min_flushed_lsn,/* out: min of flushed lsn values in data
515 files */
516 LSN64* max_flushed_lsn,/* out: */
517 ulint* sum_of_new_sizes);/* out: sum of sizes of the new files added
518 */
519
520/****************************************************************//**
521A simple function to open or create a file.
522@return own: handle to the file, not defined if error, error number
523can be retrieved with os_file_get_last_error */
524os_file_t
525xb_file_create_no_error_handling(
526/*=============================*/
527 const char* name, /*!< in: name of the file or path as a
528 null-terminated string */
529 ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
530 is opened (if does not exist, error), or
531 OS_FILE_CREATE if a new file is created
532 (if exists, error) */
533 ulint access_type,/*!< in: OS_FILE_READ_ONLY,
534 OS_FILE_READ_WRITE, or
535 OS_FILE_READ_ALLOW_DELETE; the last option is
536 used by a backup program reading the file */
537 ibool* success);/*!< out: TRUE if succeed, FALSE if error */
538
539/****************************************************************//**
540Opens an existing file or creates a new.
541@return own: handle to the file, not defined if error, error number
542can be retrieved with os_file_get_last_error */
543os_file_t
544xb_file_create(
545/*===========*/
546 const char* name, /*!< in: name of the file or path as a
547 null-terminated string */
548 ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
549 is opened (if does not exist, error), or
550 OS_FILE_CREATE if a new file is created
551 (if exists, error),
552 OS_FILE_OVERWRITE if a new file is created
553 or an old overwritten;
554 OS_FILE_OPEN_RAW, if a raw device or disk
555 partition should be opened */
556 ulint purpose,/*!< in: OS_FILE_AIO, if asynchronous,
557 non-buffered i/o is desired,
558 OS_FILE_NORMAL, if any normal file;
559 NOTE that it also depends on type, os_aio_..
560 and srv_.. variables whether we really use
561 async i/o or unbuffered i/o: look in the
562 function source code for the exact rules */
563 ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
564 ibool* success);/*!< out: TRUE if succeed, FALSE if error */
565
566
567/***********************************************************************//**
568Renames a file (can also move it to another directory). It is safest that the
569file is closed before calling this function.
570@return TRUE if success */
571ibool
572xb_file_rename(
573/*===========*/
574 const char* oldpath,/*!< in: old file path as a null-terminated
575 string */
576 const char* newpath);/*!< in: new file path */
577
578void
579xb_file_set_nocache(
580/*================*/
581 os_file_t fd, /* in: file descriptor to alter */
582 const char* file_name, /* in: used in the diagnostic message
583 */
584 const char* operation_name);/* in: used in the diagnostic message,
585 we call os_file_set_nocache()
586 immediately after opening or creating
587 a file, so this is either "open" or
588 "create" */
589
590/***********************************************************************//**
591Compatibility wrapper around os_file_flush().
592@return TRUE if success */
593ibool
594xb_file_flush(
595/*==========*/
596 os_file_t file); /*!< in, own: handle to a file */
597
598/*******************************************************************//**
599Returns the table space by a given id, NULL if not found. */
600fil_space_t*
601xb_space_get_by_id(
602/*================*/
603 ulint id); /*!< in: space id */
604
605/*******************************************************************//**
606Returns the table space by a given name, NULL if not found. */
607fil_space_t*
608xb_space_get_by_name(
609/*==================*/
610 const char* name); /*!< in: space name */
611
612/****************************************************************//**
613Create a new tablespace on disk and return the handle to its opened
614file. Code adopted from fil_create_new_single_table_tablespace with
615the main difference that only disk file is created without updating
616the InnoDB in-memory dictionary data structures.
617
618@return TRUE on success, FALSE on error. */
619ibool
620xb_space_create_file(
621/*==================*/
622 const char* path, /*!<in: path to tablespace */
623 ulint space_id, /*!<in: space id */
624 ulint flags __attribute__((unused)),/*!<in: tablespace
625 flags */
626 os_file_t* file); /*!<out: file handle */
627
628#ifndef INNODB_VERSION_SHORT
629
630/********************************************************************//**
631Extract the compressed page size from table flags.
632@return compressed page size, or 0 if not compressed */
633ulint
634dict_table_flags_to_zip_size(
635/*=========================*/
636 ulint flags); /*!< in: flags */
637
638
639/*******************************************************************//**
640Free all spaces in space_list. */
641void
642fil_free_all_spaces(void);
643/*=====================*/
644
645#endif
646
647void
648innobase_mysql_prepare_print_arbitrary_thd(void);
649
650void
651innobase_mysql_end_print_arbitrary_thd(void);
652
653int
654mysql_get_identifier_quote_char(
655 trx_t* trx,
656 const char* name,
657 ulint namelen);
658
659void
660innobase_print_identifier(
661 FILE* f,
662 trx_t* trx __attribute__((unused)),
663 ibool table_id __attribute__((unused)),
664 const char* name,
665 ulint namelen);
666
667/**********************************************************************//**
668It should be safe to use lower_case_table_names=0 for xtrabackup. If it causes
669any problems, we can add the lower_case_table_names option to xtrabackup
670later.
671@return 0 */
672ulint
673innobase_get_lower_case_table_names(void);
674
675/******************************************************************//**
676Strip dir name from a full path name and return only the file name
677@return file name or "null" if no file name */
678const char*
679innobase_basename(
680/*==============*/
681 const char* path_name); /*!< in: full path name */
682
683int
684innobase_mysql_cmp(
685 int mysql_type,
686 uint charset_number,
687 unsigned char* a,
688 unsigned int a_length,
689 unsigned char* b,
690 unsigned int b_length);
691
692ibool
693innobase_query_is_update(void);
694
695#endif /* INNODB_INT_H */
0696
=== modified file 'src/quicklz/quicklz.h'
--- src/quicklz/quicklz.h 2012-02-10 20:05:56 +0000
+++ src/quicklz/quicklz.h 2012-10-18 11:58:23 +0000
@@ -134,6 +134,7 @@
134size_t qlz_compress(const void *source, char *destination, size_t size, qlz_state_compress *state);134size_t qlz_compress(const void *source, char *destination, size_t size, qlz_state_compress *state);
135size_t qlz_decompress(const char *source, void *destination, qlz_state_decompress *state);135size_t qlz_decompress(const char *source, void *destination, qlz_state_decompress *state);
136int qlz_get_setting(int setting);136int qlz_get_setting(int setting);
137size_t qlz_size_header(const char *source);
137138
138#if defined (__cplusplus)139#if defined (__cplusplus)
139}140}
140141
=== added file 'src/write_filt.c'
--- src/write_filt.c 1970-01-01 00:00:00 +0000
+++ src/write_filt.c 2012-10-18 11:58:23 +0000
@@ -0,0 +1,321 @@
1/******************************************************
2XtraBackup: hot backup tool for InnoDB
3(c) 2009-2012 Percona Inc.
4Originally Created 3/3/2009 Yasufumi Kinoshita
5Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
6Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; version 2 of the License.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21*******************************************************/
22
23/* Page write filters implementation */
24
25#include <my_base.h>
26#include <fil0fil.h>
27#include <ut0mem.h>
28#include "common.h"
29#include "innodb_int.h"
30#include "write_filt.h"
31#include "fil_cur.h"
32#include "xtrabackup.h"
33
34/************************************************************************
35Write-through page write filter. */
36static my_bool wf_wt_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
37 xb_fil_cur_t *cursor);
38static my_bool wf_wt_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile);
39
40xb_write_filt_t wf_write_through = {
41 &wf_wt_init,
42 &wf_wt_process,
43 NULL,
44 NULL
45};
46
47/************************************************************************
48Incremental page write filter. */
49static my_bool wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
50 xb_fil_cur_t *cursor);
51static my_bool wf_incremental_process(xb_write_filt_ctxt_t *ctxt,
52 ds_file_t *dstfile);
53static my_bool wf_incremental_finalize(xb_write_filt_ctxt_t *ctxt,
54 ds_file_t *dstfile);
55static void wf_incremental_deinit(xb_write_filt_ctxt_t *ctxt);
56
57xb_write_filt_t wf_incremental = {
58 &wf_incremental_init,
59 &wf_incremental_process,
60 &wf_incremental_finalize,
61 &wf_incremental_deinit
62};
63
64/************************************************************************
65Compact page write filter. */
66static my_bool wf_compact_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
67 xb_fil_cur_t *cursor);
68static my_bool wf_compact_process(xb_write_filt_ctxt_t *ctxt,
69 ds_file_t *dstfile);
70static my_bool wf_compact_finalize(xb_write_filt_ctxt_t *ctxt,
71 ds_file_t *dstfile);
72
73xb_write_filt_t wf_compact = {
74 &wf_compact_init,
75 &wf_compact_process,
76 &wf_compact_finalize,
77 NULL
78};
79
80/************************************************************************
81Initialize incremental page write filter.
82
83@return TRUE on success, FALSE on error. */
84static my_bool
85wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
86 xb_fil_cur_t *cursor)
87{
88 char meta_name[FN_REFLEN];
89 xb_delta_info_t info;
90 ulint buf_size;
91 xb_wf_incremental_ctxt_t *cp =
92 &(ctxt->u.wf_incremental_ctxt);
93
94 ctxt->cursor = cursor;
95
96 /* allocate buffer for incremental backup (4096 pages) */
97 buf_size = (UNIV_PAGE_SIZE_MAX / 4 + 1) * UNIV_PAGE_SIZE_MAX;
98 cp->delta_buf_base = ut_malloc(buf_size);
99 bzero(cp->delta_buf_base, buf_size);
100 cp->delta_buf = ut_align(cp->delta_buf_base, UNIV_PAGE_SIZE_MAX);
101
102 /* write delta meta info */
103 snprintf(meta_name, sizeof(meta_name), "%s%s", dst_name,
104 XB_DELTA_INFO_SUFFIX);
105 info.page_size = cursor->page_size;
106 info.zip_size = cursor->zip_size;
107 info.space_id = cursor->space_id;
108 if (!xb_write_delta_metadata(meta_name, &info)) {
109 msg("[%02lu] xtrabackup: Error: "
110 "failed to write meta info for %s\n",
111 cursor->thread_n, cursor->path);
112 return(FALSE);
113 }
114
115 /* change the target file name, since we are only going to write
116 delta pages */
117 strcat(dst_name, ".delta");
118
119 mach_write_to_4(cp->delta_buf, 0x78747261UL); /*"xtra"*/
120 cp->npages = 1;
121
122 return(TRUE);
123}
124
125/************************************************************************
126Run the next batch of pages through incremental page write filter.
127
128@return TRUE on success, FALSE on error. */
129static my_bool
130wf_incremental_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
131{
132 ulint i;
133 xb_fil_cur_t *cursor = ctxt->cursor;
134 ulint page_size = cursor->page_size;
135 byte *page;
136 xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
137
138 for (i = 0, page = cursor->buf; i < cursor->buf_npages;
139 i++, page += page_size) {
140 if (ut_dulint_cmp(incremental_lsn,
141 MACH_READ_64(page + FIL_PAGE_LSN)) >= 0) {
142 continue;
143 }
144
145 /* updated page */
146 if (cp->npages == page_size / 4) {
147 /* flush buffer */
148 if (ds_write(dstfile, cp->delta_buf,
149 cp->npages * page_size)) {
150 return(FALSE);
151 }
152
153 /* clear buffer */
154 bzero(cp->delta_buf, page_size / 4 * page_size);
155 /*"xtra"*/
156 mach_write_to_4(cp->delta_buf, 0x78747261UL);
157 cp->npages = 1;
158 }
159
160 mach_write_to_4(cp->delta_buf + cp->npages * 4,
161 cursor->buf_page_no + i);
162 memcpy(cp->delta_buf + cp->npages * page_size, page,
163 page_size);
164
165 cp->npages++;
166 }
167
168 return(TRUE);
169}
170
171/************************************************************************
172Flush the incremental page write filter's buffer.
173
174@return TRUE on success, FALSE on error. */
175static my_bool
176wf_incremental_finalize(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
177{
178 xb_fil_cur_t *cursor = ctxt->cursor;
179 ulint page_size = cursor->page_size;
180 xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
181
182 if (cp->npages != page_size / 4) {
183 mach_write_to_4(cp->delta_buf + cp->npages * 4, 0xFFFFFFFFUL);
184 }
185
186 /* Mark the final block */
187 mach_write_to_4(cp->delta_buf, 0x58545241UL); /*"XTRA"*/
188
189 /* flush buffer */
190 if (ds_write(dstfile, cp->delta_buf, cp->npages * page_size)) {
191 return(FALSE);
192 }
193
194 return(TRUE);
195}
196
197/************************************************************************
198Free the incremental page write filter's buffer. */
199static void
200wf_incremental_deinit(xb_write_filt_ctxt_t *ctxt)
201{
202 xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
203
204 if (cp->delta_buf_base != NULL) {
205 ut_free(cp->delta_buf_base);
206 }
207}
208
209/************************************************************************
210Initialize the write-through page write filter.
211
212@return TRUE on success, FALSE on error. */
213static my_bool
214wf_wt_init(xb_write_filt_ctxt_t *ctxt, char *dst_name __attribute__((unused)),
215 xb_fil_cur_t *cursor)
216{
217 ctxt->cursor = cursor;
218
219 return(TRUE);
220}
221
222/************************************************************************
223Write the next batch of pages to the destination datasink.
224
225@return TRUE on success, FALSE on error. */
226static my_bool
227wf_wt_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
228{
229 xb_fil_cur_t *cursor = ctxt->cursor;
230
231 if (ds_write(dstfile, cursor->buf, cursor->buf_read)) {
232 return(FALSE);
233 }
234
235 return(TRUE);
236}
237
238/************************************************************************
239Initialize the compact page write filter.
240
241@return TRUE on success, FALSE on error. */
242static my_bool
243wf_compact_init(xb_write_filt_ctxt_t *ctxt,
244 char *dst_name __attribute__((unused)), xb_fil_cur_t *cursor)
245{
246 xb_wf_compact_ctxt_t *cp = &(ctxt->u.wf_compact_ctxt);
247
248 /* Don't compact the system table space */
249 cp->skip = cursor->is_system;
250
251 return(TRUE);
252}
253
254static my_bool
255check_if_skip_page(byte *page __attribute__((unused)))
256{
257 return(FALSE);
258}
259
260/************************************************************************
261Run the next batch of pages through the compact page write filter.
262
263@return TRUE on success, FALSE on error. */
264static my_bool
265wf_compact_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
266{
267 xb_fil_cur_t *cursor = ctxt->cursor;
268 ulint page_size = cursor->page_size;
269 byte *page;
270 byte *buf_end;
271 byte *write_from;
272 xb_wf_compact_ctxt_t *cp = &(ctxt->u.wf_compact_ctxt);
273
274 if (cp->skip) {
275 return(!ds_write(dstfile, cursor->buf, cursor->buf_read));
276 }
277
278 write_from = NULL;
279 buf_end = cursor->buf + cursor->buf_read;
280 for (page = cursor->buf; page < buf_end; page += page_size) {
281 if (!check_if_skip_page(page)) {
282 if (write_from == NULL) {
283 write_from = page;
284 }
285 continue;
286 }
287 }
288
289 /* Write the remaining pages in the buffer, if any */
290 if (write_from != NULL &&
291 ds_write(dstfile, write_from, buf_end - write_from)) {
292 return(FALSE);
293 }
294
295 return(TRUE);
296}
297
298/************************************************************************
299Close the compact write filter's page map stream.
300
301@return TRUE on success, FALSE on error. */
302static my_bool
303wf_compact_finalize(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
304{
305 xb_fil_cur_t *cursor = ctxt->cursor;
306 ulint page_size = cursor->page_size;
307 xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
308
309 if (cp->npages != page_size / 4) {
310 mach_write_to_4(cp->delta_buf + cp->npages * 4, 0xFFFFFFFFUL);
311 }
312
313 mach_write_to_4(cp->delta_buf, 0x58545241UL); /*"XTRA"*/
314
315 /* flush buffer */
316 if (ds_write(dstfile, cp->delta_buf, cp->npages * page_size)) {
317 return(FALSE);
318 }
319
320 return(TRUE);
321}
0322
=== added file 'src/write_filt.h'
--- src/write_filt.h 1970-01-01 00:00:00 +0000
+++ src/write_filt.h 2012-10-18 11:58:23 +0000
@@ -0,0 +1,65 @@
1/******************************************************
2XtraBackup: hot backup tool for InnoDB
3(c) 2009-2012 Percona Inc.
4Originally Created 3/3/2009 Yasufumi Kinoshita
5Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
6Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; version 2 of the License.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21*******************************************************/
22
23/* Page write filter interface */
24
25#ifndef XB_WRITE_FILT_H
26#define XB_WRITE_FILT_H
27
28#include "fil_cur.h"
29#include "datasink.h"
30
31/* Incremental page filter context */
32typedef struct {
33 byte *delta_buf_base;
34 byte *delta_buf;
35 ulint npages;
36} xb_wf_incremental_ctxt_t;
37
38/* Compact page filter context */
39typedef struct {
40 my_bool skip;
41} xb_wf_compact_ctxt_t;
42
43/* Page filter context used as an opaque structure by callers */
44typedef struct {
45 xb_fil_cur_t *cursor;
46 union {
47 xb_wf_incremental_ctxt_t wf_incremental_ctxt;
48 xb_wf_compact_ctxt_t wf_compact_ctxt;
49 } u;
50} xb_write_filt_ctxt_t;
51
52
53typedef struct {
54 my_bool (*init)(xb_write_filt_ctxt_t *ctxt, char *dst_name,
55 xb_fil_cur_t *cursor);
56 my_bool (*process)(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile);
57 my_bool (*finalize)(xb_write_filt_ctxt_t *, ds_file_t *dstfile);
58 void (*deinit)(xb_write_filt_ctxt_t *);
59} xb_write_filt_t;
60
61extern xb_write_filt_t wf_write_through;
62extern xb_write_filt_t wf_incremental;
63extern xb_write_filt_t wf_compact;
64
65#endif /* XB_WRITE_FILT_H */
066
=== modified file 'src/xbstream.c'
--- src/xbstream.c 2012-02-10 20:05:56 +0000
+++ src/xbstream.c 2012-10-18 11:58:23 +0000
@@ -23,7 +23,7 @@
23#include <hash.h>23#include <hash.h>
24#include "common.h"24#include "common.h"
25#include "xbstream.h"25#include "xbstream.h"
26#include "local.h"26#include "ds_local.h"
2727
28#define XBSTREAM_VERSION "1.0"28#define XBSTREAM_VERSION "1.0"
29#define XBSTREAM_BUFFER_SIZE (1024 * 1024UL)29#define XBSTREAM_BUFFER_SIZE (1024 * 1024UL)
@@ -36,6 +36,12 @@
36 RUN_MODE_EXTRACT36 RUN_MODE_EXTRACT
37} run_mode_t;37} run_mode_t;
3838
39/* Need the following definitions to avoid linking with ds_stream.o,
40ds_compress.o, ds_tmpfile.o and their linking dependencies */
41datasink_t datasink_stream;
42datasink_t datasink_compress;
43datasink_t datasink_tmpfile;
44
39static run_mode_t opt_mode;45static run_mode_t opt_mode;
40static char * opt_directory = NULL;46static char * opt_directory = NULL;
41static my_bool opt_verbose = 0;47static my_bool opt_verbose = 0;
@@ -61,7 +67,7 @@
61typedef struct {67typedef struct {
62 char *path;68 char *path;
63 uint pathlen;69 uint pathlen;
64 off_t offset;70 my_off_t offset;
65 ds_ctxt_t *ds_ctxt;71 ds_ctxt_t *ds_ctxt;
66 ds_file_t *file;72 ds_file_t *file;
67} file_entry_t;73} file_entry_t;
@@ -199,9 +205,7 @@
199 uchar buf[XBSTREAM_BUFFER_SIZE];205 uchar buf[XBSTREAM_BUFFER_SIZE];
200 size_t bytes;206 size_t bytes;
201207
202#ifdef USE_POSIX_FADVISE
203 posix_fadvise(file, 0, 0, POSIX_FADV_SEQUENTIAL);208 posix_fadvise(file, 0, 0, POSIX_FADV_SEQUENTIAL);
204#endif
205209
206 while ((bytes = my_read(file, buf, XBSTREAM_BUFFER_SIZE,210 while ((bytes = my_read(file, buf, XBSTREAM_BUFFER_SIZE,
207 MYF(MY_WME))) > 0) {211 MYF(MY_WME))) > 0) {
@@ -210,9 +214,7 @@
210 my_progname);214 my_progname);
211 return 1;215 return 1;
212 }216 }
213#ifdef USE_POSIX_FADVISE
214 posix_fadvise(file, 0, 0, POSIX_FADV_DONTNEED);217 posix_fadvise(file, 0, 0, POSIX_FADV_DONTNEED);
215#endif
216218
217 }219 }
218220
@@ -291,7 +293,6 @@
291file_entry_new(ds_ctxt_t *ds_ctxt, const char *path, uint pathlen)293file_entry_new(ds_ctxt_t *ds_ctxt, const char *path, uint pathlen)
292{294{
293 file_entry_t *entry;295 file_entry_t *entry;
294 datasink_t *ds = ds_ctxt->datasink;
295 ds_file_t *file;296 ds_file_t *file;
296297
297 entry = (file_entry_t *) my_malloc(sizeof(file_entry_t),298 entry = (file_entry_t *) my_malloc(sizeof(file_entry_t),
@@ -306,7 +307,7 @@
306 }307 }
307 entry->pathlen = pathlen;308 entry->pathlen = pathlen;
308309
309 file = ds->open(ds_ctxt, path, NULL);310 file = ds_open(ds_ctxt, path, NULL);
310 if (file == NULL) {311 if (file == NULL) {
311 msg("%s: failed to create file.\n", my_progname);312 msg("%s: failed to create file.\n", my_progname);
312 goto err;313 goto err;
@@ -343,10 +344,7 @@
343void344void
344file_entry_free(file_entry_t *entry)345file_entry_free(file_entry_t *entry)
345{346{
346 ds_ctxt_t *ds_ctxt = entry->ds_ctxt;347 ds_close(entry->file);
347 datasink_t *ds = ds_ctxt->datasink;
348
349 ds->close(entry->file);
350 MY_FREE(entry->path);348 MY_FREE(entry->path);
351 MY_FREE(entry);349 MY_FREE(entry);
352}350}
@@ -354,14 +352,13 @@
354static352static
355int353int
356mode_extract(int argc __attribute__((unused)),354mode_extract(int argc __attribute__((unused)),
357 char **argv __attribute((unused)))355 char **argv __attribute__((unused)))
358{356{
359 xb_rstream_t *stream;357 xb_rstream_t *stream;
360 xb_rstream_result_t res;358 xb_rstream_result_t res;
361 xb_rstream_chunk_t chunk;359 xb_rstream_chunk_t chunk;
362 HASH filehash;360 HASH filehash;
363 file_entry_t *entry;361 file_entry_t *entry;
364 datasink_t *ds;
365 ds_ctxt_t *ds_ctxt;362 ds_ctxt_t *ds_ctxt;
366363
367 stream = xb_stream_read_new();364 stream = xb_stream_read_new();
@@ -371,8 +368,7 @@
371 }368 }
372369
373 /* If --directory is specified, it is already set as CWD by now. */370 /* If --directory is specified, it is already set as CWD by now. */
374 ds = &datasink_local;371 ds_ctxt = ds_create(".", DS_TYPE_LOCAL);
375 ds_ctxt = ds->init(".");
376372
377 if (my_hash_init(&filehash, &my_charset_bin, START_FILE_HASH_SIZE,373 if (my_hash_init(&filehash, &my_charset_bin, START_FILE_HASH_SIZE,
378 0, 0, (my_hash_get_key) get_file_entry_key,374 0, 0, (my_hash_get_key) get_file_entry_key,
@@ -420,7 +416,7 @@
420 goto err;416 goto err;
421 }417 }
422418
423 if (ds->write(entry->file, chunk.data, chunk.length)) {419 if (ds_write(entry->file, chunk.data, chunk.length)) {
424 msg("%s: my_write() failed.\n", my_progname);420 msg("%s: my_write() failed.\n", my_progname);
425 goto err;421 goto err;
426 }422 }
@@ -433,13 +429,13 @@
433 }429 }
434430
435 my_hash_free(&filehash);431 my_hash_free(&filehash);
436 ds->deinit(ds_ctxt);432 ds_destroy(ds_ctxt);
437 xb_stream_read_done(stream);433 xb_stream_read_done(stream);
438434
439 return 0;435 return 0;
440err:436err:
441 my_hash_free(&filehash);437 my_hash_free(&filehash);
442 ds->deinit(ds_ctxt);438 ds_destroy(ds_ctxt);
443 xb_stream_read_done(stream);439 xb_stream_read_done(stream);
444440
445 return 1;441 return 1;
446442
=== modified file 'src/xtrabackup.c'
--- src/xtrabackup.c 2012-09-13 10:28:54 +0000
+++ src/xtrabackup.c 2012-10-18 11:58:23 +0000
@@ -48,9 +48,9 @@
4848
49//#define XTRABACKUP_TARGET_IS_PLUGIN49//#define XTRABACKUP_TARGET_IS_PLUGIN
5050
51#include <mysql_version.h>
51#include <my_base.h>52#include <my_base.h>
52#include <my_getopt.h>53#include <my_getopt.h>
53#include <mysql_version.h>
54#include <mysql_com.h>54#include <mysql_com.h>
5555
56#if (MYSQL_VERSION_ID < 50100)56#if (MYSQL_VERSION_ID < 50100)
@@ -59,8 +59,6 @@
59#define G_PTR uchar*59#define G_PTR uchar*
60#endif60#endif
6161
62#include <univ.i>
63#include <os0file.h>
64#include <os0thread.h>62#include <os0thread.h>
65#include <srv0start.h>63#include <srv0start.h>
66#include <srv0srv.h>64#include <srv0srv.h>
@@ -72,8 +70,6 @@
72#include <row0mysql.h>70#include <row0mysql.h>
73#include <row0sel.h>71#include <row0sel.h>
74#include <row0upd.h>72#include <row0upd.h>
75#include <log0log.h>
76#include <log0recv.h>
77#include <lock0lock.h>73#include <lock0lock.h>
78#include <dict0crea.h>74#include <dict0crea.h>
79#include <btr0cur.h>75#include <btr0cur.h>
@@ -81,9 +77,7 @@
81#include <btr0sea.h>77#include <btr0sea.h>
82#include <fsp0fsp.h>78#include <fsp0fsp.h>
83#include <sync0sync.h>79#include <sync0sync.h>
84#include <fil0fil.h>
85#include <trx0xa.h>80#include <trx0xa.h>
86#include <btr0sea.h>
87#include <log0recv.h>81#include <log0recv.h>
88#include <fcntl.h>82#include <fcntl.h>
8983
@@ -93,676 +87,12 @@
9387
94#include "common.h"88#include "common.h"
95#include "datasink.h"89#include "datasink.h"
96#include "local.h"
97#include "stream.h"
98#include "compress.h"
9990
100#include "xb_regex.h"91#include "xb_regex.h"
10192#include "innodb_int.h"
102#ifndef INNODB_VERSION_SHORT93#include "fil_cur.h"
103#define IB_INT64 ib_longlong94#include "write_filt.h"
104#define LSN64 dulint95#include "xtrabackup.h"
105#define MACH_READ_64 mach_read_from_8
106#define MACH_WRITE_64 mach_write_to_8
107#define OS_MUTEX_CREATE() os_mutex_create(NULL)
108#define PAGE_ZIP_MIN_SIZE_SHIFT 10
109#define DICT_TF_ZSSIZE_SHIFT 1
110#define DICT_TF_FORMAT_ZIP 1
111#define DICT_TF_FORMAT_SHIFT 5
112#else
113#define IB_INT64 ib_int64_t
114#define LSN64 ib_uint64_t
115#if (MYSQL_VERSION_ID < 50500)
116#define MACH_READ_64 mach_read_ull
117#define MACH_WRITE_64 mach_write_ull
118#define OS_MUTEX_CREATE() os_mutex_create(NULL)
119#else
120#define MACH_READ_64 mach_read_from_8
121#define MACH_WRITE_64 mach_write_to_8
122#define OS_MUTEX_CREATE() os_mutex_create()
123#endif
124#define ut_dulint_zero 0
125#define ut_dulint_cmp(A, B) (A > B ? 1 : (A == B ? 0 : -1))
126#define ut_dulint_add(A, B) (A + B)
127#define ut_dulint_minus(A, B) (A - B)
128#define ut_dulint_align_down(A, B) (A & ~((ib_int64_t)B - 1))
129#define ut_dulint_align_up(A, B) ((A + B - 1) & ~((ib_int64_t)B - 1))
130#endif
131
132#ifdef __WIN__
133#define SRV_PATH_SEPARATOR '\\'
134#define SRV_PATH_SEPARATOR_STR "\\"
135#else
136#define SRV_PATH_SEPARATOR '/'
137#define SRV_PATH_SEPARATOR_STR "/"
138#endif
139
140#ifndef UNIV_PAGE_SIZE_MAX
141#define UNIV_PAGE_SIZE_MAX UNIV_PAGE_SIZE
142#endif
143#ifndef UNIV_PAGE_SIZE_SHIFT_MAX
144#define UNIV_PAGE_SIZE_SHIFT_MAX UNIV_PAGE_SIZE_SHIFT
145#endif
146
147#if MYSQL_VERSION_ID >= 50507
148/*
149 As of MySQL 5.5.7, InnoDB uses thd_wait plugin service.
150 We have to provide mock functions to avoid linker errors.
151*/
152#include <mysql/plugin.h>
153#include <mysql/service_thd_wait.h>
154
155void thd_wait_begin(MYSQL_THD thd, int wait_type)
156{
157 (void)thd;
158 (void)wait_type;
159 return;
160}
161
162void thd_wait_end(MYSQL_THD thd)
163{
164 (void)thd;
165 return;
166}
167
168#endif /* MYSQL_VERSION_ID >= 50507 */
169
170/* prototypes for static functions in original */
171#ifndef INNODB_VERSION_SHORT
172page_t*
173btr_node_ptr_get_child(
174/*===================*/
175 /* out: child page, x-latched */
176 rec_t* node_ptr,/* in: node pointer */
177 const ulint* offsets,/* in: array returned by rec_get_offsets() */
178 mtr_t* mtr); /* in: mtr */
179#else
180buf_block_t*
181btr_node_ptr_get_child(
182/*===================*/
183 const rec_t* node_ptr,/*!< in: node pointer */
184 dict_index_t* index, /*!< in: index */
185 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
186 mtr_t* mtr); /*!< in: mtr */
187
188buf_block_t*
189btr_root_block_get(
190/*===============*/
191 dict_index_t* index, /*!< in: index tree */
192 mtr_t* mtr); /*!< in: mtr */
193#endif
194
195int
196fil_file_readdir_next_file(
197/*=======================*/
198 /* out: 0 if ok, -1 if error even after the
199 retries, 1 if at the end of the directory */
200 ulint* err, /* out: this is set to DB_ERROR if an error
201 was encountered, otherwise not changed */
202 const char* dirname,/* in: directory name or path */
203 os_file_dir_t dir, /* in: directory stream */
204 os_file_stat_t* info); /* in/out: buffer where the info is returned */
205
206ibool
207recv_check_cp_is_consistent(
208/*========================*/
209 /* out: TRUE if ok */
210 byte* buf); /* in: buffer containing checkpoint info */
211
212ulint
213recv_find_max_checkpoint(
214/*=====================*/
215 /* out: error code or DB_SUCCESS */
216 log_group_t** max_group, /* out: max group */
217 ulint* max_field); /* out: LOG_CHECKPOINT_1 or
218 LOG_CHECKPOINT_2 */
219
220ibool
221log_block_checksum_is_ok_or_old_format(
222/*===================================*/
223 /* out: TRUE if ok, or if the log block may be in the
224 format of InnoDB version < 3.23.52 */
225 byte* block); /* in: pointer to a log block */
226
227ulint
228open_or_create_log_file(
229/*====================*/
230 /* out: DB_SUCCESS or error code */
231 ibool create_new_db, /* in: TRUE if we should create a
232 new database */
233 ibool* log_file_created, /* out: TRUE if new log file
234 created */
235 ibool log_file_has_been_opened,/* in: TRUE if a log file has been
236 opened before: then it is an error
237 to try to create another log file */
238 ulint k, /* in: log group number */
239 ulint i); /* in: log file number in group */
240
241ulint
242open_or_create_data_files(
243/*======================*/
244 /* out: DB_SUCCESS or error code */
245 ibool* create_new_db, /* out: TRUE if new database should be
246 created */
247#ifdef XTRADB_BASED
248 ibool* create_new_doublewrite_file,
249#endif
250#ifdef UNIV_LOG_ARCHIVE
251 ulint* min_arch_log_no,/* out: min of archived log numbers in data
252 files */
253 ulint* max_arch_log_no,/* out: */
254#endif /* UNIV_LOG_ARCHIVE */
255 LSN64* min_flushed_lsn,/* out: min of flushed lsn values in data
256 files */
257 LSN64* max_flushed_lsn,/* out: */
258 ulint* sum_of_new_sizes);/* out: sum of sizes of the new files added */
259
260void
261os_file_set_nocache(
262/*================*/
263 int fd, /* in: file descriptor to alter */
264 const char* file_name, /* in: used in the diagnostic message */
265 const char* operation_name); /* in: used in the diagnostic message,
266 we call os_file_set_nocache()
267 immediately after opening or creating
268 a file, so this is either "open" or
269 "create" */
270
271/****************************************************************//**
272A simple function to open or create a file.
273@return own: handle to the file, not defined if error, error number
274can be retrieved with os_file_get_last_error */
275UNIV_INLINE
276os_file_t
277xb_file_create_no_error_handling(
278/*=============================*/
279 const char* name, /*!< in: name of the file or path as a
280 null-terminated string */
281 ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
282 is opened (if does not exist, error), or
283 OS_FILE_CREATE if a new file is created
284 (if exists, error) */
285 ulint access_type,/*!< in: OS_FILE_READ_ONLY,
286 OS_FILE_READ_WRITE, or
287 OS_FILE_READ_ALLOW_DELETE; the last option is
288 used by a backup program reading the file */
289 ibool* success);/*!< out: TRUE if succeed, FALSE if error */
290
291/****************************************************************//**
292Opens an existing file or creates a new.
293@return own: handle to the file, not defined if error, error number
294can be retrieved with os_file_get_last_error */
295UNIV_INLINE
296os_file_t
297xb_file_create(
298/*===========*/
299 const char* name, /*!< in: name of the file or path as a
300 null-terminated string */
301 ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
302 is opened (if does not exist, error), or
303 OS_FILE_CREATE if a new file is created
304 (if exists, error),
305 OS_FILE_OVERWRITE if a new file is created
306 or an old overwritten;
307 OS_FILE_OPEN_RAW, if a raw device or disk
308 partition should be opened */
309 ulint purpose,/*!< in: OS_FILE_AIO, if asynchronous,
310 non-buffered i/o is desired,
311 OS_FILE_NORMAL, if any normal file;
312 NOTE that it also depends on type, os_aio_..
313 and srv_.. variables whether we really use
314 async i/o or unbuffered i/o: look in the
315 function source code for the exact rules */
316 ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
317 ibool* success);/*!< out: TRUE if succeed, FALSE if error */
318
319
320/***********************************************************************//**
321Renames a file (can also move it to another directory). It is safest that the
322file is closed before calling this function.
323@return TRUE if success */
324UNIV_INLINE
325ibool
326xb_file_rename(
327/*===========*/
328 const char* oldpath,/*!< in: old file path as a null-terminated
329 string */
330 const char* newpath);/*!< in: new file path */
331
332UNIV_INLINE
333void
334xb_file_set_nocache(
335/*================*/
336 os_file_t fd, /* in: file descriptor to alter */
337 const char* file_name, /* in: used in the diagnostic message */
338 const char* operation_name);/* in: used in the diagnostic message,
339 we call os_file_set_nocache()
340 immediately after opening or creating
341 a file, so this is either "open" or
342 "create" */
343
344/***********************************************************************//**
345Compatibility wrapper around os_file_flush().
346@return TRUE if success */
347static
348ibool
349xb_file_flush(
350/*==========*/
351 os_file_t file); /*!< in, own: handle to a file */
352
353/* ==start === definition at fil0fil.c === */
354// ##################################################################
355// NOTE: We should check the following definitions fit to the source.
356// ##################################################################
357
358#ifndef INNODB_VERSION_SHORT
359//5.0 5.1
360/* File node of a tablespace or the log data space */
361struct fil_node_struct {
362 fil_space_t* space; /* backpointer to the space where this node
363 belongs */
364 char* name; /* path to the file */
365 ibool open; /* TRUE if file open */
366 os_file_t handle; /* OS handle to the file, if file open */
367 ibool is_raw_disk;/* TRUE if the 'file' is actually a raw
368 device or a raw disk partition */
369 ulint size; /* size of the file in database pages, 0 if
370 not known yet; the possible last incomplete
371 megabyte may be ignored if space == 0 */
372 ulint n_pending;
373 /* count of pending i/o's on this file;
374 closing of the file is not allowed if
375 this is > 0 */
376 ulint n_pending_flushes;
377 /* count of pending flushes on this file;
378 closing of the file is not allowed if
379 this is > 0 */
380 ib_longlong modification_counter;/* when we write to the file we
381 increment this by one */
382 ib_longlong flush_counter;/* up to what modification_counter value
383 we have flushed the modifications to disk */
384 UT_LIST_NODE_T(fil_node_t) chain;
385 /* link field for the file chain */
386 UT_LIST_NODE_T(fil_node_t) LRU;
387 /* link field for the LRU list */
388 ulint magic_n;
389};
390
391struct fil_space_struct {
392 char* name; /* space name = the path to the first file in
393 it */
394 ulint id; /* space id */
395 ib_longlong tablespace_version;
396 /* in DISCARD/IMPORT this timestamp is used to
397 check if we should ignore an insert buffer
398 merge request for a page because it actually
399 was for the previous incarnation of the
400 space */
401 ibool mark; /* this is set to TRUE at database startup if
402 the space corresponds to a table in the InnoDB
403 data dictionary; so we can print a warning of
404 orphaned tablespaces */
405 ibool stop_ios;/* TRUE if we want to rename the .ibd file of
406 tablespace and want to stop temporarily
407 posting of new i/o requests on the file */
408 ibool stop_ibuf_merges;
409 /* we set this TRUE when we start deleting a
410 single-table tablespace */
411 ibool is_being_deleted;
412 /* this is set to TRUE when we start
413 deleting a single-table tablespace and its
414 file; when this flag is set no further i/o
415 or flush requests can be placed on this space,
416 though there may be such requests still being
417 processed on this space */
418 ulint purpose;/* FIL_TABLESPACE, FIL_LOG, or FIL_ARCH_LOG */
419 UT_LIST_BASE_NODE_T(fil_node_t) chain;
420 /* base node for the file chain */
421 ulint size; /* space size in pages; 0 if a single-table
422 tablespace whose size we do not know yet;
423 last incomplete megabytes in data files may be
424 ignored if space == 0 */
425 ulint n_reserved_extents;
426 /* number of reserved free extents for
427 ongoing operations like B-tree page split */
428 ulint n_pending_flushes; /* this is > 0 when flushing
429 the tablespace to disk; dropping of the
430 tablespace is forbidden if this is > 0 */
431 ulint n_pending_ibuf_merges;/* this is > 0 when merging
432 insert buffer entries to a page so that we
433 may need to access the ibuf bitmap page in the
434 tablespade: dropping of the tablespace is
435 forbidden if this is > 0 */
436 hash_node_t hash; /* hash chain node */
437 hash_node_t name_hash;/* hash chain the name_hash table */
438 rw_lock_t latch; /* latch protecting the file space storage
439 allocation */
440 UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
441 /* list of spaces with at least one unflushed
442 file we have written to */
443 ibool is_in_unflushed_spaces; /* TRUE if this space is
444 currently in the list above */
445 UT_LIST_NODE_T(fil_space_t) space_list;
446 /* list of all spaces */
447 ibuf_data_t* ibuf_data;
448 /* insert buffer data */
449 ulint magic_n;
450};
451typedef struct fil_system_struct fil_system_t;
452struct fil_system_struct {
453 mutex_t mutex; /* The mutex protecting the cache */
454 hash_table_t* spaces; /* The hash table of spaces in the
455 system; they are hashed on the space
456 id */
457 hash_table_t* name_hash; /* hash table based on the space
458 name */
459 UT_LIST_BASE_NODE_T(fil_node_t) LRU;
460 /* base node for the LRU list of the
461 most recently used open files with no
462 pending i/o's; if we start an i/o on
463 the file, we first remove it from this
464 list, and return it to the start of
465 the list when the i/o ends;
466 log files and the system tablespace are
467 not put to this list: they are opened
468 after the startup, and kept open until
469 shutdown */
470 UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
471 /* base node for the list of those
472 tablespaces whose files contain
473 unflushed writes; those spaces have
474 at least one file node where
475 modification_counter > flush_counter */
476 ulint n_open; /* number of files currently open */
477 ulint max_n_open; /* n_open is not allowed to exceed
478 this */
479 ib_longlong modification_counter;/* when we write to a file we
480 increment this by one */
481 ulint max_assigned_id;/* maximum space id in the existing
482 tables, or assigned during the time
483 mysqld has been up; at an InnoDB
484 startup we scan the data dictionary
485 and set here the maximum of the
486 space id's of the tables there */
487 ib_longlong tablespace_version;
488 /* a counter which is incremented for
489 every space object memory creation;
490 every space mem object gets a
491 'timestamp' from this; in DISCARD/
492 IMPORT this is used to check if we
493 should ignore an insert buffer merge
494 request */
495 UT_LIST_BASE_NODE_T(fil_space_t) space_list;
496 /* list of all file spaces */
497};
498#else
499//Plugin ?
500/** File node of a tablespace or the log data space */
501struct fil_node_struct {
502 fil_space_t* space; /*!< backpointer to the space where this node
503 belongs */
504 char* name; /*!< path to the file */
505 ibool open; /*!< TRUE if file open */
506 os_file_t handle; /*!< OS handle to the file, if file open */
507 ibool is_raw_disk;/*!< TRUE if the 'file' is actually a raw
508 device or a raw disk partition */
509 ulint size; /*!< size of the file in database pages, 0 if
510 not known yet; the possible last incomplete
511 megabyte may be ignored if space == 0 */
512 ulint n_pending;
513 /*!< count of pending i/o's on this file;
514 closing of the file is not allowed if
515 this is > 0 */
516 ulint n_pending_flushes;
517 /*!< count of pending flushes on this file;
518 closing of the file is not allowed if
519 this is > 0 */
520 ib_int64_t modification_counter;/*!< when we write to the file we
521 increment this by one */
522 ib_int64_t flush_counter;/*!< up to what
523 modification_counter value we have
524 flushed the modifications to disk */
525 UT_LIST_NODE_T(fil_node_t) chain;
526 /*!< link field for the file chain */
527 UT_LIST_NODE_T(fil_node_t) LRU;
528 /*!< link field for the LRU list */
529 ulint magic_n;/*!< FIL_NODE_MAGIC_N */
530};
531
532struct fil_space_struct {
533 char* name; /*!< space name = the path to the first file in
534 it */
535 ulint id; /*!< space id */
536 ib_int64_t tablespace_version;
537 /*!< in DISCARD/IMPORT this timestamp
538 is used to check if we should ignore
539 an insert buffer merge request for a
540 page because it actually was for the
541 previous incarnation of the space */
542 ibool mark; /*!< this is set to TRUE at database startup if
543 the space corresponds to a table in the InnoDB
544 data dictionary; so we can print a warning of
545 orphaned tablespaces */
546 ibool stop_ios;/*!< TRUE if we want to rename the
547 .ibd file of tablespace and want to
548 stop temporarily posting of new i/o
549 requests on the file */
550 ibool stop_ibuf_merges;
551 /*!< we set this TRUE when we start
552 deleting a single-table tablespace */
553 ibool is_being_deleted;
554 /*!< this is set to TRUE when we start
555 deleting a single-table tablespace and its
556 file; when this flag is set no further i/o
557 or flush requests can be placed on this space,
558 though there may be such requests still being
559 processed on this space */
560 ulint purpose;/*!< FIL_TABLESPACE, FIL_LOG, or
561 FIL_ARCH_LOG */
562 UT_LIST_BASE_NODE_T(fil_node_t) chain;
563 /*!< base node for the file chain */
564 ulint size; /*!< space size in pages; 0 if a single-table
565 tablespace whose size we do not know yet;
566 last incomplete megabytes in data files may be
567 ignored if space == 0 */
568 ulint flags; /*!< compressed page size and file format, or 0 */
569 ulint n_reserved_extents;
570 /*!< number of reserved free extents for
571 ongoing operations like B-tree page split */
572 ulint n_pending_flushes; /*!< this is positive when flushing
573 the tablespace to disk; dropping of the
574 tablespace is forbidden if this is positive */
575 ulint n_pending_ibuf_merges;/*!< this is positive
576 when merging insert buffer entries to
577 a page so that we may need to access
578 the ibuf bitmap page in the
579 tablespade: dropping of the tablespace
580 is forbidden if this is positive */
581 hash_node_t hash; /*!< hash chain node */
582 hash_node_t name_hash;/*!< hash chain the name_hash table */
583#ifndef UNIV_HOTBACKUP
584 rw_lock_t latch; /*!< latch protecting the file space storage
585 allocation */
586#endif /* !UNIV_HOTBACKUP */
587 UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
588 /*!< list of spaces with at least one unflushed
589 file we have written to */
590 ibool is_in_unflushed_spaces; /*!< TRUE if this space is
591 currently in unflushed_spaces */
592#ifdef XTRADB_BASED
593 ibool is_corrupt;
594#endif
595 UT_LIST_NODE_T(fil_space_t) space_list;
596 /*!< list of all spaces */
597 ulint magic_n;/*!< FIL_SPACE_MAGIC_N */
598};
599
600typedef struct fil_system_struct fil_system_t;
601
602struct fil_system_struct {
603#ifndef UNIV_HOTBACKUP
604 mutex_t mutex; /*!< The mutex protecting the cache */
605#ifdef XTRADB_BASED
606 mutex_t file_extend_mutex;
607#endif
608#endif /* !UNIV_HOTBACKUP */
609 hash_table_t* spaces; /*!< The hash table of spaces in the
610 system; they are hashed on the space
611 id */
612 hash_table_t* name_hash; /*!< hash table based on the space
613 name */
614 UT_LIST_BASE_NODE_T(fil_node_t) LRU;
615 /*!< base node for the LRU list of the
616 most recently used open files with no
617 pending i/o's; if we start an i/o on
618 the file, we first remove it from this
619 list, and return it to the start of
620 the list when the i/o ends;
621 log files and the system tablespace are
622 not put to this list: they are opened
623 after the startup, and kept open until
624 shutdown */
625 UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
626 /*!< base node for the list of those
627 tablespaces whose files contain
628 unflushed writes; those spaces have
629 at least one file node where
630 modification_counter > flush_counter */
631 ulint n_open; /*!< number of files currently open */
632 ulint max_n_open; /*!< n_open is not allowed to exceed
633 this */
634 ib_int64_t modification_counter;/*!< when we write to a file we
635 increment this by one */
636 ulint max_assigned_id;/*!< maximum space id in the existing
637 tables, or assigned during the time
638 mysqld has been up; at an InnoDB
639 startup we scan the data dictionary
640 and set here the maximum of the
641 space id's of the tables there */
642 ib_int64_t tablespace_version;
643 /*!< a counter which is incremented for
644 every space object memory creation;
645 every space mem object gets a
646 'timestamp' from this; in DISCARD/
647 IMPORT this is used to check if we
648 should ignore an insert buffer merge
649 request */
650 UT_LIST_BASE_NODE_T(fil_space_t) space_list;
651 /*!< list of all file spaces */
652 ibool space_id_reuse_warned;
653 /* !< TRUE if fil_space_create()
654 has issued a warning about
655 potential space_id reuse */
656};
657
658#endif /* INNODB_VERSION_SHORT */
659
660typedef struct {
661 ulint page_size;
662 ulint zip_size;
663 ulint space_id;
664} xb_delta_info_t;
665
666extern fil_system_t* fil_system;
667
668/** Value of fil_space_struct::magic_n */
669#define FIL_SPACE_MAGIC_N 89472
670
671/*******************************************************************//**
672Returns the table space by a given id, NULL if not found. */
673fil_space_t*
674xb_space_get_by_id(
675/*================*/
676 ulint id); /*!< in: space id */
677
678/*******************************************************************//**
679Returns the table space by a given name, NULL if not found. */
680fil_space_t*
681xb_space_get_by_name(
682/*==================*/
683 const char* name); /*!< in: space name */
684
685/*******************************************************************//**
686Returns the table space by a given id, NULL if not found. */
687fil_space_t*
688xb_space_get_by_id(
689/*================*/
690 ulint id) /*!< in: space id */
691{
692 fil_space_t* space;
693
694 ut_ad(mutex_own(&fil_system->mutex));
695
696#ifdef INNODB_VERSION_SHORT
697 HASH_SEARCH(hash, fil_system->spaces, id,
698 fil_space_t*, space,
699 ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
700 space->id == id);
701#else
702 HASH_SEARCH(hash, fil_system->spaces, id, space, space->id == id);
703#endif
704
705 return(space);
706}
707
708/*******************************************************************//**
709Returns the table space by a given name, NULL if not found. */
710fil_space_t*
711xb_space_get_by_name(
712/*==================*/
713 const char* name) /*!< in: space name */
714{
715 fil_space_t* space;
716 ulint fold;
717
718 ut_ad(mutex_own(&fil_system->mutex));
719
720#ifdef INNODB_VERSION_SHORT
721 fold = ut_fold_string(name);
722 HASH_SEARCH(name_hash, fil_system->name_hash, fold,
723 fil_space_t*, space,
724 ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
725 !strcmp(name, space->name));
726#else
727 HASH_SEARCH(name_hash, fil_system->name_hash, ut_fold_string(name),
728 space, 0 == strcmp(name, space->name));
729#endif
730
731 return(space);
732}
733
734#ifndef INNODB_VERSION_SHORT
735
736/*******************************************************************//**
737Free all spaces in space_list. */
738void
739fil_free_all_spaces(void)
740/*=====================*/
741{
742 fil_space_t* space;
743
744 mutex_enter(&fil_system->mutex);
745
746 space = UT_LIST_GET_FIRST(fil_system->space_list);
747
748 while (space != NULL) {
749 fil_node_t* node;
750 fil_space_t* prev_space = space;
751
752 space = UT_LIST_GET_NEXT(space_list, space);
753
754 fil_space_free(prev_space->id, FALSE);
755 }
756
757 mutex_exit(&fil_system->mutex);
758}
759
760#define SRV_SHUTDOWN_NONE 0
761
762#endif
763
764/* ==end=== definition at fil0fil.c === */
765
76696
767my_bool innodb_inited= 0;97my_bool innodb_inited= 0;
76898
@@ -786,7 +116,6 @@
786lint io_ticket;116lint io_ticket;
787os_event_t wait_throttle = NULL;117os_event_t wait_throttle = NULL;
788118
789my_bool xtrabackup_log_only = FALSE;
790char *xtrabackup_incremental = NULL;119char *xtrabackup_incremental = NULL;
791LSN64 incremental_lsn;120LSN64 incremental_lsn;
792LSN64 incremental_to_lsn;121LSN64 incremental_to_lsn;
@@ -850,27 +179,15 @@
850ib_uint64_t metadata_last_lsn = 0;179ib_uint64_t metadata_last_lsn = 0;
851#endif180#endif
852181
853#define XB_DELTA_INFO_SUFFIX ".meta"
854
855#define XB_LOG_FILENAME "xtrabackup_logfile"182#define XB_LOG_FILENAME "xtrabackup_logfile"
856183
857#ifdef __WIN__184ds_file_t *dst_log_file = NULL;
858#define XB_FILE_UNDEFINED NULL
859#else
860#define XB_FILE_UNDEFINED (-1)
861#endif
862
863int dst_log_fd = XB_FILE_UNDEFINED;
864char dst_log_path[FN_REFLEN];
865185
866/* === some variables from mysqld === */186/* === some variables from mysqld === */
867char mysql_real_data_home[FN_REFLEN] = "./";187char mysql_real_data_home[FN_REFLEN] = "./";
868char *mysql_data_home= mysql_real_data_home;188char *mysql_data_home= mysql_real_data_home;
869static char mysql_data_home_buff[2];189static char mysql_data_home_buff[2];
870190
871char *opt_mysql_tmpdir = NULL;
872MY_TMPDIR mysql_tmpdir_list;
873
874const char *defaults_group = "mysqld";191const char *defaults_group = "mysqld";
875192
876/* === static parameters in ha_innodb.cc */193/* === static parameters in ha_innodb.cc */
@@ -897,7 +214,9 @@
897long innobase_open_files = 300L;214long innobase_open_files = 300L;
898215
899long innobase_page_size = (1 << 14); /* 16KB */216long innobase_page_size = (1 << 14); /* 16KB */
217#ifdef XTRADB_BASED
900static ulong innobase_log_block_size = 512;218static ulong innobase_log_block_size = 512;
219#endif
901my_bool innobase_fast_checksum = FALSE;220my_bool innobase_fast_checksum = FALSE;
902my_bool innobase_extra_undoslots = FALSE;221my_bool innobase_extra_undoslots = FALSE;
903char* innobase_doublewrite_file = NULL;222char* innobase_doublewrite_file = NULL;
@@ -944,6 +263,16 @@
944263
945static char *xtrabackup_debug_sync = NULL;264static char *xtrabackup_debug_sync = NULL;
946265
266static my_bool xtrabackup_compact = FALSE;
267
268/* Datasinks */
269static ds_ctxt_t *ds_data = NULL;
270static ds_ctxt_t *ds_meta = NULL;
271static ds_ctxt_t *ds_local = NULL;
272static ds_ctxt_t *ds_compress = NULL;
273static ds_ctxt_t *ds_tmpfile = NULL;
274static ds_ctxt_t *ds_stream = NULL;
275
947/* ======== Datafiles iterator ======== */276/* ======== Datafiles iterator ======== */
948typedef struct {277typedef struct {
949 fil_system_t *system;278 fil_system_t *system;
@@ -1024,7 +353,6 @@
1024 uint *count;353 uint *count;
1025 os_mutex_t count_mutex;354 os_mutex_t count_mutex;
1026 os_thread_id_t id;355 os_thread_id_t id;
1027 ds_ctxt_t *ds_ctxt;
1028} data_thread_ctxt_t;356} data_thread_ctxt_t;
1029357
1030/* ======== for option and variables ======== */358/* ======== for option and variables ======== */
@@ -1041,7 +369,6 @@
1041 OPT_XTRA_SUSPEND_AT_END,369 OPT_XTRA_SUSPEND_AT_END,
1042 OPT_XTRA_USE_MEMORY,370 OPT_XTRA_USE_MEMORY,
1043 OPT_XTRA_THROTTLE,371 OPT_XTRA_THROTTLE,
1044 OPT_XTRA_LOG_ONLY,
1045 OPT_XTRA_INCREMENTAL,372 OPT_XTRA_INCREMENTAL,
1046 OPT_XTRA_INCREMENTAL_BASEDIR,373 OPT_XTRA_INCREMENTAL_BASEDIR,
1047 OPT_XTRA_EXTRA_LSNDIR,374 OPT_XTRA_EXTRA_LSNDIR,
@@ -1099,6 +426,7 @@
1099 OPT_INNODB_THREAD_CONCURRENCY,426 OPT_INNODB_THREAD_CONCURRENCY,
1100 OPT_INNODB_THREAD_SLEEP_DELAY,427 OPT_INNODB_THREAD_SLEEP_DELAY,
1101 OPT_XTRA_DEBUG_SYNC,428 OPT_XTRA_DEBUG_SYNC,
429 OPT_XTRA_COMPACT,
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches