Merge branch '10.2' of github.com:MariaDB/server into bb-10.2-mariarocks-merge

This commit is contained in:
Sergei Petrunia 2017-09-19 15:34:38 +03:00
commit 6b0588018a
2312 changed files with 188819 additions and 61333 deletions

11
.gitignore vendored
View file

@ -49,6 +49,8 @@ extra/comp_err
extra/innochecksum
extra/jemalloc/build/
extra/jemalloc/tmp/
extra/mariabackup/mariabackup
extra/mariabackup/mbstream
extra/my_print_defaults
extra/mysql_waitpid
extra/mysqld_safe_helper
@ -124,10 +126,13 @@ scripts/mytop
scripts/wsrep_sst_common
scripts/wsrep_sst_mysqldump
scripts/wsrep_sst_rsync
scripts/wsrep_sst_mariabackup
scripts/wsrep_sst_xtrabackup
scripts/wsrep_sst_xtrabackup-v2
scripts/maria_add_gis_sp.sql
scripts/maria_add_gis_sp_bootstrap.sql
scripts/galera_new_cluster
scripts/galera_recovery
sql-bench/bench-count-distinct
sql-bench/bench-init.pl
sql-bench/compare-results
@ -219,6 +224,7 @@ support-files/config.medium.ini
support-files/config.small.ini
support-files/mariadb.pc
support-files/mariadb@.service
support-files/mariadb.service
support-files/my-huge.cnf
support-files/my-innodb-heavy-4G.cnf
support-files/my-large.cnf
@ -232,6 +238,7 @@ support-files/mysqld_multi.server
support-files/wsrep.cnf
support-files/wsrep_notify
support-files/policy/selinux/mysqld-safe.pp
support-files/mariadb.pp
tags
tests/async_queries
tests/bug25714
@ -248,6 +255,10 @@ storage/mroonga/vendor/groonga/src/groonga-benchmark
storage/mroonga/vendor/groonga/src/suggest/groonga-suggest-create-dataset
storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result
storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result
xxx/*
yyy/*
zzz/*
# C and C++
# Compiled Object files

View file

@ -8,8 +8,8 @@ if [[ "${TRAVIS_OS_NAME}" == 'linux' ]]; then
CMAKE_OPT="${CMAKE_OPT} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
fi
case ${GCC_VERSION} in
5) CXX=clang++-3.9 ;;
6) CXX=clang++-4.0 ;;
5) CXX=clang++-4.0 ;;
6) CXX=clang++-5.0 ;;
esac
export CXX CC=${CXX/++/}
elif [[ "${CXX}" == 'g++' ]]; then
@ -39,8 +39,4 @@ else
fi
fi
# main.mysqlhotcopy_myisam consitently failed in travis containers
# https://travis-ci.org/grooverdan/mariadb-server/builds/217661580
echo 'main.mysqlhotcopy_myisam : unstable in containers' >> ${TRAVIS_BUILD_DIR}/mysql-test/unstable-tests
echo 'archive.mysqlhotcopy_archive : unstable in containers' >> ${TRAVIS_BUILD_DIR}/mysql-test/unstable-tests
set +v +x

View file

@ -40,15 +40,66 @@ matrix:
include:
- os: linux
compiler: gcc
addons:
apt:
packages: # make sure these match debian/control contents
- bison
- chrpath
- cmake
- debhelper
- dh-apparmor
- dpatch
- gdb
- libaio-dev
- libboost-dev
- libcurl3-dev
- libdbd-mysql
- libjudy-dev
- libncurses5-dev
- libpam0g-dev
- libpcre3-dev
- libreadline-gplv2-dev
- libstemmer-dev
- libssl-dev
- libnuma-dev
- libxml2-dev
- lsb-release
- perl
- po-debconf
- psmisc
- zlib1g-dev
- libcrack2-dev
- cracklib-runtime
- libjemalloc-dev
- libsnappy-dev
- liblzma-dev
- libzmq-dev
- libdistro-info-perl
- uuid-dev
- devscripts
- fakeroot
script:
- ${CC} --version ; ${CXX} --version
# Just for disabling hotcopy tests for now
- source .travis.compiler.sh
# https://github.com/travis-ci/travis-ci/issues/7062 - /run/shm isn't writable or executable
# in trusty containers
- export MTR_MEM=/tmp
- env DEB_BUILD_OPTIONS="parallel=6" debian/autobake-deb.sh;
- ccache --show-stats
# Until OSX becomes a bit more stable: MDEV-12435
allow_failures:
- os: osx
compiler: clang
env: GCC_VERSION=4.8 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=rpl
- os: osx
compiler: clang
env: GCC_VERSION=5 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=main,archive,optimizer_unfixed_bugs,parts,sys_vars,unit,vcol,innodb,innodb_gis,innodb_zip,innodb_fts
- os: osx
compiler: clang
env: GCC_VERSION=6 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=binlog,binlog_encryption,encryption,rocksdb
- os: osx
compiler: clang
env: GCC_VERSION=6 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=csv,federated,funcs_1,funcs_2,gcol,handler,heap,json,maria,percona,perfschema,plugins,multi_source,roles
# Matrix include for coverity
# - env:
@ -85,29 +136,26 @@ addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty
- llvm-toolchain-trusty-3.9
- llvm-toolchain-trusty-4.0
packages: # make sure these match debian/control contents
- sourceline: 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main'
packages: # make sure these match the build requirements
- gcc-5
- g++-5
- gcc-6
- g++-6
- clang-3.9
- llvm-3.9-dev
- clang-4.0
- llvm-4.0-dev
- clang-5.0
- llvm-5.0-dev
- libasan0
- bison
- chrpath
- cmake
- debhelper
- dh-apparmor
- dpatch
- gdb
- libaio-dev
- libboost-dev
- libcurl3-dev
- libdbd-mysql
- libjudy-dev
- libncurses5-dev
- libpam0g-dev
@ -119,16 +167,15 @@ addons:
- libxml2-dev
- lsb-release
- perl
- po-debconf
- psmisc
- zlib1g-dev
- libcrack2-dev
- cracklib-runtime
- libjemalloc-dev
- libsnappy-dev
- liblzma-dev
- libzmq-dev
- libdistro-info-perl
- devscripts # implicit for any build on Ubuntu
- uuid-dev
# libsystemd-daemon-dev # https://github.com/travis-ci/apt-package-whitelist/issues/3882

View file

@ -35,6 +35,11 @@ fi
# git clean -fdX removes all ignored (build) files
commands="\
git clean -fdX
cd ./libmariadb
git submodule update
cd ../storage/rocksdb/rocksdb
git submodule update
cd ../../..
path=`dirname $0`
. \"$path/autorun.sh\""

View file

@ -205,7 +205,7 @@ fi
max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max"
max_no_qc_configs="$SSL_LIBRARY --with-plugins=max --without-query-cache"
max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-libevent --without-plugin=plugin_file_key_management"
max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-libevent --without-plugin=plugin_file_key_management --with-plugin-rocksdb=dynamic"
all_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-innodb_plugin --with-libevent"
#
@ -289,6 +289,11 @@ gcov_compile_flags="-fprofile-arcs -ftest-coverage"
gcov_compile_flags="$gcov_compile_flags -DDISABLE_TAO_ASM"
gcov_compile_flags="$gcov_compile_flags -DMYSQL_SERVER_SUFFIX=-gcov -DHAVE_gcov"
#
# The following plugins doesn't work on 32 bit systems
disable_64_bit_plugins="--without-plugin-tokudb --without-plugin-rocksdb"
# GCC4 needs -fprofile-arcs -ftest-coverage on the linker command line (as well
# as on the compiler command line), and this requires setting LDFLAGS for BDB.

View file

@ -1,25 +0,0 @@
#! /bin/sh
# Copyright (C) 2005, 2006 MySQL AB
# Use is subject to license terms
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; version 2
# of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$amd64_cflags $debug_cflags"
extra_configs="$amd64_configs $debug_configs $max_configs"
. "$path/FINISH.sh"

View file

@ -1,7 +0,0 @@
#! /bin/sh
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$amd64_cflags -pg -g"
extra_configs="$amd64_configs $max_configs --disable-shared $static_link"
. "$path/FINISH.sh"

View file

@ -20,7 +20,7 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $fast_cflags"
extra_configs="$pentium_configs"
extra_configs="$pentium_configs $disable_64_bit_plugins"
strip=yes
. "$path/FINISH.sh"

View file

@ -19,6 +19,6 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags"
extra_configs="$pentium_configs $debug_configs"
extra_configs="$pentium_configs $debug_configs $disable_64_bit_plugins"
. "$path/FINISH.sh"

View file

@ -5,6 +5,6 @@ set -- "$@" --with-debug=full
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags"
extra_configs="$pentium_configs $debug_configs $all_configs $error_inject --with-experimental-collations"
extra_configs="$pentium_configs $debug_configs $all_configs $error_inject --with-experimental-collations $disable_64_bit_plugins"
. "$path/FINISH.sh"

View file

@ -19,6 +19,6 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags"
extra_configs="$pentium_configs $debug_configs $max_configs $error_inject --with-experimental-collations"
extra_configs="$pentium_configs $debug_configs $max_configs $error_inject --with-experimental-collations $disable_64_bit_plugins"
. "$path/FINISH.sh"

View file

@ -20,6 +20,6 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags"
extra_configs="$pentium_configs $debug_configs $max_no_embedded_configs"
extra_configs="$pentium_configs $debug_configs $max_no_embedded_configs $disable_64_bit_plugins"
. "$path/FINISH.sh"

View file

@ -1,24 +0,0 @@
#! /bin/sh
# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags"
extra_configs="$pentium_configs $debug_configs $max_configs"
. "$path/FINISH.sh"

View file

@ -1,10 +0,0 @@
#! /bin/sh
# Builds server without query cache support
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags"
extra_configs="$pentium_configs $debug_configs $max_no_qc_configs"
. "$path/FINISH.sh"

View file

@ -19,7 +19,7 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags"
extra_configs="$pentium_configs $debug_configs"
extra_configs="$pentium_configs $debug_configs $disable_64_bit_plugins"
extra_configs="$extra_configs --with-debug --with-ssl=/usr"

View file

@ -7,6 +7,6 @@ set -- "$@" --with-debug=full
extra_flags="$pentium_cflags $debug_cflags -g -O0 $wsrep_cflags"
c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs $wsrep_configs --with-wsrep"
extra_configs="$pentium_configs $debug_configs $wsrep_configs --with-wsrep $disable_64_bit_plugins"
. "$path/FINISH.sh"

View file

@ -40,6 +40,6 @@ export LDFLAGS="$gcov_link_flags"
extra_flags="$pentium_cflags $debug_cflags $max_cflags $gcov_compile_flags"
c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs $gcov_configs $max_configs"
extra_configs="$pentium_configs $debug_configs $gcov_configs $max_configs $disable_64_bit_plugins"
. "$path/FINISH.sh"

View file

@ -19,6 +19,6 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $gprof_compile_flags"
extra_configs="$pentium_configs $debug_configs $gprof_link_flags"
extra_configs="$pentium_configs $debug_configs $gprof_link_flags $disable_64_bit_plugins"
. "$path/FINISH.sh"

View file

@ -35,6 +35,6 @@ extra_flags="$fast_cflags -unroll2 -ip -mp -restrict"
# icpc: error: problem during multi-file optimization compilation (code 1)
extra_flags="$extra_flags -no-ipo"
base_cxxflags="-fno-exceptions -fno-rtti"
extra_configs="$pentium_configs $static_link"
extra_configs="$pentium_configs $static_link $disable_64_bit_plugins"
. "$path/FINISH.sh"

View file

@ -20,6 +20,6 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $fast_cflags -g"
extra_configs="$pentium_configs $max_configs"
extra_configs="$pentium_configs $max_configs $disable_64_bit_plugins"
. "$path/FINISH.sh"

View file

@ -33,6 +33,6 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags $valgrind_flags"
extra_configs="$pentium_configs $debug_configs $valgrind_configs $max_configs"
extra_configs="$pentium_configs $debug_configs $valgrind_configs $max_configs $disable_64_bit_plugins"
. "$path/FINISH.sh"

View file

@ -1,26 +0,0 @@
#! /bin/sh
# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; version 2
# of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags $valgrind_flags"
extra_configs="$pentium_configs $debug_configs $valgrind_configs $max_configs"
. "$path/FINISH.sh"

View file

@ -4,7 +4,7 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $fast_cflags $wsrep_cflags"
extra_configs="$pentium_configs $wsrep_configs --with-wsrep"
extra_configs="$pentium_configs $wsrep_configs --with-wsrep $disable_64_bit_plugins"
#strip=yes

View file

@ -1,25 +0,0 @@
#! /bin/sh
# Copyright (c) 2005, 2006 MySQL AB
# Use is subject to license terms
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$ppc_cflags $debug_cflags"
extra_configs="$debug_configs $max_configs"
. "$path/FINISH.sh"

View file

@ -1,5 +1,5 @@
# Copyright (c) 2006, 2014, Oracle and/or its affiliates.
# Copyright (c) 2008, 2014, Monty Program Ab
# Copyright (c) 2006, 2017, Oracle and/or its affiliates.
# Copyright (c) 2008, 2017, MariaDB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -220,11 +220,9 @@ IF(SECURITY_HARDENED)
MY_CHECK_AND_SET_COMPILER_FLAG("-D_FORTIFY_SOURCE=2" RELEASE RELWITHDEBINFO)
ENDIF()
OPTION(ENABLE_DEBUG_SYNC "Enable debug sync (debug builds only)" ON)
IF(ENABLE_DEBUG_SYNC)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
ENDIF()
# Always enable debug sync for debug builds.
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
OPTION(ENABLE_GCOV "Enable gcov (debug, Linux builds only)" OFF)
IF (ENABLE_GCOV)
@ -365,7 +363,7 @@ ENDIF()
SET (MYSQLD_STATIC_PLUGIN_LIBS "" CACHE INTERNAL "")
# mariadb_connector_c fetches submodules which is useful for plugins
INCLUDE(submodules)
INCLUDE(mariadb_connector_c) # this does ADD_SUBDIRECTORY(libmariadb)
# Add storage engines and plugins.
@ -462,7 +460,6 @@ INSTALL_DOCUMENTATION(README.md CREDITS COPYING COPYING.thirdparty
# ${CMAKE_BINARY_DIR}/Docs/INFO_BIN)
IF(UNIX)
INSTALL_DOCUMENTATION(Docs/INSTALL-BINARY COMPONENT Readme)
INSTALL_DOCUMENTATION(Docs/INSTALL-BINARY Docs/README-wsrep COMPONENT Readme)
ENDIF()

24
CREDITS
View file

@ -4,17 +4,19 @@ organization registered in the USA.
The current main sponsors of the MariaDB Foundation are:
Alibaba Cloud https://intl.aliyun.com (2017)
Booking.com https://www.booking.com (2013 - 2017)
Development Bank of Singapore https://dbs.com (2016 - 2017)
MariaDB Corporation https://www.mariadb.com (2013 - 2017)
Visma https://visma.com (2015 - 2017)
Acronis http://acronis.com (2016 - 2017)
Nexedi https://www.nexedi.com (2016 - 2017)
Automattic https://automattic.com (2014 - 2017)
Tencent Game DBA http://tencentdba.com/about (2016 - 2017)
Tencent TDSQL http://tdsql.org/ (2016 - 2017)
Verkkokauppa.com https://www.verkkokauppa.com (2015 - 2017)
Virtuozzo https://virtuozzo.com (2016 - 2017)
Booking.com https://www.booking.com (2013)
Tencent Cloud https://cloud.tencent.com (2017)
Development Bank of Singapore https://dbs.com (2016)
IBM https://www.ibm.com (2017)
MariaDB Corporation https://www.mariadb.com (2013)
Visma https://visma.com (2015)
Acronis http://acronis.com (2016)
Nexedi https://www.nexedi.com (2016)
Automattic https://automattic.com (2014)
Tencent Game DBA http://tencentdba.com/about (2016)
Tencent TDSQL http://tdsql.org (2016)
Verkkokauppa.com https://www.verkkokauppa.com (2015)
Virtuozzo https://virtuozzo.com (2016)
For a full list of sponsors, see
https://mariadb.org/about/supporters/

View file

@ -8,7 +8,7 @@ Please read the CREDITS file for details about the MariaDB Foundation,
and who is developing MariaDB.
MariaDB is developed by many of the original developers of MySQL who
now work for the MariadB Foundation and the MariaDB Corporation, and by many people in
now work for the MariaDB Foundation and the MariaDB Corporation, and by many people in
the community.
MySQL, which is the base of MariaDB, is a product and trademark of Oracle

View file

@ -1,3 +1,3 @@
MYSQL_VERSION_MAJOR=10
MYSQL_VERSION_MINOR=2
MYSQL_VERSION_PATCH=6
MYSQL_VERSION_PATCH=9

View file

@ -120,4 +120,3 @@ enum options_client
Name of the performance schema database.
*/
#define PERFORMANCE_SCHEMA_DB_NAME "performance_schema"

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2014, Oracle and/or its affiliates.
Copyright (c) 2009, 2016, MariaDB
Copyright (c) 2009, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -149,7 +149,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
default_pager_set= 0, opt_sigint_ignore= 0,
auto_vertical_output= 0,
show_warnings= 0, executing_query= 0,
ignore_spaces= 0, opt_progress_reports;
ignore_spaces= 0, opt_binhex= 0, opt_progress_reports;
static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error;
static my_bool column_types_flag;
static my_bool preserve_comments= 0;
@ -1145,8 +1145,6 @@ int main(int argc,char *argv[])
outfile[0]=0; // no (default) outfile
strmov(pager, "stdout"); // the default, if --pager wasn't given
mysql_init(&mysql);
{
char *tmp=getenv("PAGER");
if (tmp && strlen(tmp))
@ -1185,7 +1183,11 @@ int main(int argc,char *argv[])
}
defaults_argv=argv;
if ((status.exit_status= get_options(argc, (char **) argv)))
mysql_end(-1);
{
free_defaults(defaults_argv);
my_end(0);
exit(status.exit_status);
}
if (status.batch && !status.line_buff &&
!(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin)))
@ -1494,6 +1496,8 @@ static struct my_option my_long_options[] =
{"batch", 'B',
"Don't use history file. Disable interactive behavior. (Enables --silent.)",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"binary-as-hex", 'b', "Print binary data as hex", &opt_binhex, &opt_binhex,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
"Directory for character set files.", &charsets_dir,
&charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@ -2321,8 +2325,10 @@ static bool add_line(String &buffer, char *line, ulong line_length,
continue;
}
#endif
if (!*ml_comment && inchar == '\\' &&
!(*in_string &&
if (!*ml_comment && inchar == '\\' && *in_string != '`' &&
!(*in_string == '"' &&
(mysql.server_status & SERVER_STATUS_ANSI_QUOTES)) &&
!(*in_string &&
(mysql.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)))
{
// Found possbile one character command like \c
@ -3061,7 +3067,6 @@ static int com_server_help(String *buffer __attribute__((unused)),
{
unsigned int num_fields= mysql_num_fields(result);
my_ulonglong num_rows= mysql_num_rows(result);
mysql_fetch_fields(result);
if (num_fields==3 && num_rows==1)
{
if (!(cur= mysql_fetch_row(result)))
@ -3315,7 +3320,8 @@ com_go(String *buffer,char *line __attribute__((unused)))
print_table_data_html(result);
else if (opt_xml)
print_table_data_xml(result);
else if (vertical || (auto_vertical_output && (terminal_width < get_result_width(result))))
else if (vertical || (auto_vertical_output &&
(terminal_width < get_result_width(result))))
print_table_data_vertically(result);
else if (opt_silent && verbose <= 2 && !output_tables)
print_tab_data(result);
@ -3533,6 +3539,41 @@ print_field_types(MYSQL_RES *result)
}
/* Used to determine if we should invoke print_as_hex for this field */
static bool
is_binary_field(MYSQL_FIELD *field)
{
if ((field->charsetnr == 63) &&
(field->type == MYSQL_TYPE_BIT ||
field->type == MYSQL_TYPE_BLOB ||
field->type == MYSQL_TYPE_LONG_BLOB ||
field->type == MYSQL_TYPE_MEDIUM_BLOB ||
field->type == MYSQL_TYPE_TINY_BLOB ||
field->type == MYSQL_TYPE_VAR_STRING ||
field->type == MYSQL_TYPE_STRING ||
field->type == MYSQL_TYPE_VARCHAR ||
field->type == MYSQL_TYPE_GEOMETRY))
return 1;
return 0;
}
/* Print binary value as hex literal (0x ...) */
static void
print_as_hex(FILE *output_file, const char *str, ulong len, ulong total_bytes_to_send)
{
const char *ptr= str, *end= ptr+len;
ulong i;
fprintf(output_file, "0x");
for(; ptr < end; ptr++)
fprintf(output_file, "%02X", *((uchar*)ptr));
for (i= 2*len+2; i < total_bytes_to_send; i++)
tee_putc((int)' ', output_file);
}
static void
print_table_data(MYSQL_RES *result)
{
@ -3559,6 +3600,8 @@ print_table_data(MYSQL_RES *result)
length= MY_MAX(length,field->max_length);
if (length < 4 && !IS_NOT_NULL(field->flags))
length=4; // Room for "NULL"
if (opt_binhex && is_binary_field(field))
length= 2 + length * 2;
field->max_length=length;
num_flag[mysql_field_tell(result) - 1]= IS_NUM(field->type);
separator.fill(separator.length()+length+2,'-');
@ -3626,9 +3669,11 @@ print_table_data(MYSQL_RES *result)
many extra padding-characters we should send with the printing function.
*/
visible_length= charset_info->cset->numcells(charset_info, buffer, buffer + data_length);
extra_padding= data_length - visible_length;
extra_padding= (uint) (data_length - visible_length);
if (field_max_length > MAX_COLUMN_LENGTH)
if (opt_binhex && is_binary_field(field))
print_as_hex(PAGER, cur[off], lengths[off], field_max_length);
else if (field_max_length > MAX_COLUMN_LENGTH)
tee_print_sized_data(buffer, data_length, MAX_COLUMN_LENGTH+extra_padding, FALSE);
else
{
@ -3762,11 +3807,15 @@ print_table_data_html(MYSQL_RES *result)
if (interrupted_query)
break;
ulong *lengths=mysql_fetch_lengths(result);
field= mysql_fetch_fields(result);
(void) tee_fputs("<TR>", PAGER);
for (uint i=0; i < mysql_num_fields(result); i++)
{
(void) tee_fputs("<TD>", PAGER);
xmlencode_print(cur[i], lengths[i]);
if (opt_binhex && is_binary_field(&field[i]))
print_as_hex(PAGER, cur[i], lengths[i], lengths[i]);
else
xmlencode_print(cur[i], lengths[i]);
(void) tee_fputs("</TD>", PAGER);
}
(void) tee_fputs("</TR>", PAGER);
@ -3802,7 +3851,10 @@ print_table_data_xml(MYSQL_RES *result)
if (cur[i])
{
tee_fprintf(PAGER, "\">");
xmlencode_print(cur[i], lengths[i]);
if (opt_binhex && is_binary_field(&fields[i]))
print_as_hex(PAGER, cur[i], lengths[i], lengths[i]);
else
xmlencode_print(cur[i], lengths[i]);
tee_fprintf(PAGER, "</field>\n");
}
else
@ -3849,13 +3901,19 @@ print_table_data_vertically(MYSQL_RES *result)
{
unsigned int i;
const char *p;
if (opt_binhex && is_binary_field(field))
fprintf(PAGER, "0x");
for (i= 0, p= cur[off]; i < lengths[off]; i+= 1, p+= 1)
{
if (*p == '\0')
tee_putc((int)' ', PAGER);
if (opt_binhex && is_binary_field(field))
fprintf(PAGER, "%02X", *((uchar*)p));
else
tee_putc((int)*p, PAGER);
{
if (*p == '\0')
tee_putc((int)' ', PAGER);
else
tee_putc((int)*p, PAGER);
}
}
tee_putc('\n', PAGER);
}
@ -3865,7 +3923,6 @@ print_table_data_vertically(MYSQL_RES *result)
}
}
/* print_warnings should be called right after executing a statement */
static void print_warnings()
@ -4002,11 +4059,19 @@ print_tab_data(MYSQL_RES *result)
while ((cur = mysql_fetch_row(result)))
{
lengths=mysql_fetch_lengths(result);
safe_put_field(cur[0],lengths[0]);
field= mysql_fetch_fields(result);
if (opt_binhex && is_binary_field(&field[0]))
print_as_hex(PAGER, cur[0], lengths[0], lengths[0]);
else
safe_put_field(cur[0],lengths[0]);
for (uint off=1 ; off < mysql_num_fields(result); off++)
{
(void) tee_fputs("\t", PAGER);
safe_put_field(cur[off], lengths[off]);
if (opt_binhex && field && is_binary_field(&field[off]))
print_as_hex(PAGER, cur[off], lengths[off], lengths[off]);
else
safe_put_field(cur[off], lengths[off]);
}
(void) tee_fputs("\n", PAGER);
}
@ -4802,10 +4867,11 @@ com_status(String *buffer __attribute__((unused)),
tee_fprintf(stdout, "Protocol:\t\tCompressed\n");
#endif
if ((status_str= mysql_stat(&mysql)) && !mysql_error(&mysql)[0])
const char *pos;
if ((status_str= mysql_stat(&mysql)) && !mysql_error(&mysql)[0] &&
(pos= strchr(status_str,' ')))
{
ulong sec;
const char *pos= strchr(status_str,' ');
/* print label */
tee_fprintf(stdout, "%.*s\t\t\t", (int) (pos-status_str), status_str);
if ((status_str= str2int(pos,10,0,LONG_MAX,(long*) &sec)))

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2006, 2013, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
Copyright (c) 2010, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1130,7 +1130,7 @@ static int check_version_match(void)
int main(int argc, char **argv)
{
char self_name[FN_REFLEN];
char self_name[FN_REFLEN + 1];
MY_INIT(argv[0]);
@ -1138,7 +1138,7 @@ int main(int argc, char **argv)
if (GetModuleFileName(NULL, self_name, FN_REFLEN) == 0)
#endif
{
strncpy(self_name, argv[0], FN_REFLEN);
strmake_buf(self_name, argv[0]);
}
if (init_dynamic_string(&ds_args, "", 512, 256) ||
@ -1171,6 +1171,8 @@ int main(int argc, char **argv)
{
int fd= create_temp_file(cnf_file_path, opt_tmpdir[0] ? opt_tmpdir : NULL,
"mysql_upgrade-", O_CREAT | O_WRONLY, MYF(MY_FAE));
if (fd < 0)
die(NULL);
my_write(fd, USTRING_WITH_LEN( "[client]\n"), MYF(MY_FAE));
my_write(fd, (uchar*)ds_args.str, ds_args.length, MYF(MY_FAE));
my_close(fd, MYF(0));

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2014, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
Copyright (c) 2010, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -47,6 +47,7 @@ static uint opt_count_iterations= 0, my_end_arg;
static ulong opt_connect_timeout, opt_shutdown_timeout;
static char * unix_port=0;
static char *opt_plugin_dir= 0, *opt_default_auth= 0;
static bool sql_log_bin_off= false;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
@ -600,6 +601,31 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
}
static int maybe_disable_binlog(MYSQL *mysql)
{
if (opt_local && !sql_log_bin_off)
{
if (mysql_query(mysql, "set local sql_log_bin=0"))
{
my_printf_error(0, "SET LOCAL SQL_LOG_BIN=0 failed; error: '%-.200s'",
error_flags, mysql_error(mysql));
return -1;
}
}
sql_log_bin_off= true;
return 0;
}
int flush(MYSQL *mysql, const char *what)
{
char buf[FN_REFLEN];
my_snprintf(buf, sizeof(buf), "flush %s%s",
(opt_local && !sql_log_bin_off ? "local " : ""), what);
return mysql_query(mysql, buf);
}
/**
@brief Execute all commands
@ -616,6 +642,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
int ret = 0;
const char *status;
/*
MySQL documentation relies on the fact that mysqladmin will
@ -628,17 +655,6 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
struct my_rnd_struct rand_st;
char buff[FN_REFLEN + 20];
if (opt_local)
{
sprintf(buff, "set local sql_log_bin=0");
if (mysql_query(mysql, buff))
{
my_printf_error(0, "SET LOCAL SQL_LOG_BIN=0 failed; error: '%-.200s'",
error_flags, mysql_error(mysql));
return -1;
}
}
for (; argc > 0 ; argv++,argc--)
{
int command;
@ -650,6 +666,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
my_printf_error(0, "Too few arguments to create", error_flags);
return 1;
}
if (maybe_disable_binlog(mysql))
return -1;
sprintf(buff,"create database `%.*s`",FN_REFLEN,argv[1]);
if (mysql_query(mysql,buff))
{
@ -667,6 +685,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
my_printf_error(0, "Too few arguments to drop", error_flags);
return 1;
}
if (maybe_disable_binlog(mysql))
return -1;
if (drop_db(mysql,argv[1]))
return -1;
argc--; argv++;
@ -707,7 +727,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_PRIVILEGES:
case ADMIN_RELOAD:
if (mysql_query(mysql,"flush privileges"))
if (flush(mysql, "privileges"))
{
my_printf_error(0, "reload failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -911,7 +931,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_LOGS:
{
if (mysql_query(mysql,"flush logs"))
if (flush(mysql, "logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -921,7 +941,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_BINARY_LOG:
{
if (mysql_query(mysql, "flush binary logs"))
if (flush(mysql, "binary logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -931,7 +951,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_ENGINE_LOG:
{
if (mysql_query(mysql,"flush engine logs"))
if (flush(mysql, "engine logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -941,7 +961,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_ERROR_LOG:
{
if (mysql_query(mysql, "flush error logs"))
if (flush(mysql, "error logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -951,7 +971,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_GENERAL_LOG:
{
if (mysql_query(mysql, "flush general logs"))
if (flush(mysql, "general logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -961,7 +981,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_RELAY_LOG:
{
if (mysql_query(mysql, "flush relay logs"))
if (flush(mysql, "relay logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -971,7 +991,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_SLOW_LOG:
{
if (mysql_query(mysql,"flush slow logs"))
if (flush(mysql, "slow logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -981,7 +1001,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_HOSTS:
{
if (mysql_query(mysql,"flush hosts"))
if (flush(mysql, "hosts"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -991,7 +1011,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_TABLES:
{
if (mysql_query(mysql,"flush tables"))
if (flush(mysql, "tables"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -1001,7 +1021,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_STATUS:
{
if (mysql_query(mysql,"flush status"))
if (flush(mysql, "status"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -1011,7 +1031,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_TABLE_STATISTICS:
{
if (mysql_query(mysql,"flush table_statistics"))
if (flush(mysql, "table_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -1021,7 +1041,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_INDEX_STATISTICS:
{
if (mysql_query(mysql,"flush index_statistics"))
if (flush(mysql, "index_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -1031,7 +1051,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_USER_STATISTICS:
{
if (mysql_query(mysql,"flush user_statistics"))
if (flush(mysql, "user_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -1041,7 +1061,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_USER_RESOURCES:
{
if (mysql_query(mysql, "flush user_resources"))
if (flush(mysql, "user_resources"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -1051,7 +1071,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_CLIENT_STATISTICS:
{
if (mysql_query(mysql,"flush client_statistics"))
if (flush(mysql, "client_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -1061,9 +1081,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_ALL_STATISTICS:
{
if (mysql_query(mysql,
"flush table_statistics,index_statistics,"
"user_statistics,client_statistics"))
if (flush(mysql, "table_statistics,index_statistics,"
"user_statistics,client_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -1073,9 +1092,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_ALL_STATUS:
{
if (mysql_query(mysql,
"flush status,table_statistics,index_statistics,"
"user_statistics,client_statistics"))
if (flush(mysql, "status,table_statistics,index_statistics,"
"user_statistics,client_statistics"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@ -1093,6 +1111,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
start_time=time((time_t*) 0);
my_rnd_init(&rand_st,(ulong) start_time,(ulong) start_time/2);
if (maybe_disable_binlog(mysql))
return -1;
if (argc < 1)
{
my_printf_error(0, "Too few arguments to change password", error_flags);
@ -1106,7 +1126,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (strcmp(typed_password, verified) != 0)
{
my_printf_error(0,"Passwords don't match",MYF(ME_BELL));
return -1;
ret = -1;
goto password_done;
}
}
else
@ -1133,7 +1154,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
my_printf_error(0, "Could not determine old_passwords setting from server; error: '%s'",
error_flags, mysql_error(mysql));
return -1;
ret = -1;
goto password_done;
}
else
{
@ -1144,7 +1166,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
"Could not get old_passwords setting from "
"server; error: '%s'",
error_flags, mysql_error(mysql));
return -1;
ret = -1;
goto password_done;
}
if (!mysql_num_rows(res))
old= 1;
@ -1169,15 +1192,15 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
my_printf_error(0, "Can't turn off logging; error: '%s'",
error_flags, mysql_error(mysql));
return -1;
ret = -1;
}
else
if (mysql_query(mysql,buff))
{
if (mysql_errno(mysql)!=1290)
{
my_printf_error(0,"unable to change password; error: '%s'",
error_flags, mysql_error(mysql));
return -1;
}
else
{
@ -1191,9 +1214,10 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
" --skip-grant-tables).\n"
"Use: \"mysqladmin flush-privileges password '*'\""
" instead", error_flags);
return -1;
}
ret = -1;
}
password_done:
/* free up memory from prompted password */
if (typed_password != argv[1])
{
@ -1300,7 +1324,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return 1;
}
}
return 0;
return ret;
}
/**

View file

@ -68,6 +68,7 @@ CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
/* Needed for Flashback */
DYNAMIC_ARRAY binlog_events; // Storing the events output string
DYNAMIC_ARRAY events_in_stmt; // Storing the events that in one statement
String stop_event_string; // Storing the STOP_EVENT output string
char server_version[SERVER_VERSION_LENGTH];
@ -894,6 +895,25 @@ static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
print_event_info->m_table_map_ignored.get_table(table_id);
bool skip_event= (ignored_map != NULL);
if (opt_flashback)
{
Rows_log_event *e= (Rows_log_event*) ev;
// The last Row_log_event will be the first event in Flashback
if (is_stmt_end)
e->clear_flags(Rows_log_event::STMT_END_F);
// The first Row_log_event will be the last event in Flashback
if (events_in_stmt.elements == 0)
e->set_flags(Rows_log_event::STMT_END_F);
// Update the temp_buf
e->update_flags();
if (insert_dynamic(&events_in_stmt, (uchar *) &ev))
{
error("Out of memory: can't allocate memory to store the flashback events.");
exit(1);
}
}
/*
end of statement check:
i) destroy/free ignored maps
@ -945,7 +965,36 @@ static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
if (skip_event)
return 0;
return print_base64(print_event_info, ev);
if (!opt_flashback)
return print_base64(print_event_info, ev);
else
{
if (is_stmt_end)
{
bool res= false;
Log_event *e= NULL;
// Print the row_event from the last one to the first one
for (uint i= events_in_stmt.elements; i > 0; --i)
{
e= *(dynamic_element(&events_in_stmt, i - 1, Log_event**));
res= res || print_base64(print_event_info, e);
}
// Copy all output into the Log_event
ev->output_buf.copy(e->output_buf);
// Delete Log_event
for (uint i= 0; i < events_in_stmt.elements-1; ++i)
{
e= *(dynamic_element(&events_in_stmt, i, Log_event**));
delete e;
}
reset_dynamic(&events_in_stmt);
return res;
}
}
return 0;
}
@ -1386,6 +1435,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
}
if (print_base64(print_event_info, ev))
goto err;
if (opt_flashback)
reset_dynamic(&events_in_stmt);
break;
}
case WRITE_ROWS_EVENT:
@ -1402,9 +1453,12 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
case DELETE_ROWS_COMPRESSED_EVENT_V1:
{
Rows_log_event *e= (Rows_log_event*) ev;
bool is_stmt_end= e->get_flags(Rows_log_event::STMT_END_F);
if (print_row_event(print_event_info, ev, e->get_table_id(),
e->get_flags(Rows_log_event::STMT_END_F)))
goto err;
if (!is_stmt_end)
destroy_evt= FALSE;
break;
}
case PRE_GA_WRITE_ROWS_EVENT:
@ -1412,9 +1466,12 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
case PRE_GA_UPDATE_ROWS_EVENT:
{
Old_rows_log_event *e= (Old_rows_log_event*) ev;
bool is_stmt_end= e->get_flags(Rows_log_event::STMT_END_F);
if (print_row_event(print_event_info, ev, e->get_table_id(),
e->get_flags(Old_rows_log_event::STMT_END_F)))
goto err;
if (!is_stmt_end)
destroy_evt= FALSE;
break;
}
case START_ENCRYPTION_EVENT:
@ -1459,7 +1516,7 @@ end:
&my_charset_bin);
else
{
if (push_dynamic(&binlog_events, (uchar *) &tmp_str))
if (insert_dynamic(&binlog_events, (uchar *) &tmp_str))
{
error("Out of memory: can't allocate memory to store the flashback events.");
exit(1);
@ -2480,7 +2537,7 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
size_t tlen = strlen(logname);
if (tlen > UINT_MAX)
if (tlen > sizeof(buf) - 10)
{
error("Log name too long.");
DBUG_RETURN(ERROR_STOP);
@ -2915,9 +2972,12 @@ int main(int argc, char** argv)
my_set_max_open_files(open_files_limit);
if (opt_flashback)
{
my_init_dynamic_array(&binlog_events, sizeof(LEX_STRING), 1024, 1024,
MYF(0));
my_init_dynamic_array(&events_in_stmt, sizeof(Rows_log_event*), 1024, 1024,
MYF(0));
}
if (opt_stop_never)
to_last_remote_log= TRUE;
@ -3031,6 +3091,7 @@ int main(int argc, char** argv)
}
fprintf(result_file, "COMMIT\n/*!*/;\n");
delete_dynamic(&binlog_events);
delete_dynamic(&events_in_stmt);
}
/* Set delimiter back to semicolon */

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2001, 2013, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
Copyright (c) 2010, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -92,8 +92,7 @@
static void add_load_option(DYNAMIC_STRING *str, const char *option,
const char *option_value);
static ulong find_set(TYPELIB *lib, const char *x, size_t length,
char **err_pos, uint *err_len);
static ulong find_set(TYPELIB *, const char *, size_t, char **, uint *);
static char *alloc_query_str(ulong size);
static void field_escape(DYNAMIC_STRING* in, const char *from);
@ -114,7 +113,8 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_no_data_m
opt_slave_apply= 0,
opt_include_master_host_port= 0,
opt_events= 0, opt_comments_used= 0,
opt_alltspcs=0, opt_notspcs= 0, opt_logging;
opt_alltspcs=0, opt_notspcs= 0, opt_logging,
opt_drop_trigger= 0 ;
static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*mysql=0;
@ -233,6 +233,9 @@ static struct my_option my_long_options[] =
{"add-drop-table", OPT_DROP, "Add a DROP TABLE before each create.",
&opt_drop, &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
0},
{"add-drop-trigger", 0, "Add a DROP TRIGGER before each create.",
&opt_drop_trigger, &opt_drop_trigger, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
0},
{"add-locks", OPT_LOCKS, "Add locks around INSERT statements.",
&opt_lock, &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
0},
@ -2170,6 +2173,7 @@ static void print_xml_comment(FILE *xml_file, size_t len,
case '-':
if (*(comment_string + 1) == '-') /* Only one hyphen allowed. */
break;
/* fall through */
default:
fputc(*comment_string, xml_file);
break;
@ -2207,7 +2211,6 @@ static void print_comment(FILE *sql_file, my_bool is_error, const char *format,
print_xml_comment(sql_file, strlen(comment_buff), comment_buff);
}
/*
create_delimiter
Generate a new (null-terminated) string that does not exist in query
@ -2552,7 +2555,7 @@ static uint dump_routines_for_db(char *db)
query_buff);
print_comment(sql_file, 1,
"-- does %s have permissions on mysql.proc?\n\n",
current_user);
fix_for_comment(current_user));
maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!",
current_user, query_buff);
}
@ -2847,6 +2850,8 @@ static uint get_table_structure(char *table, char *db, char *table_type,
my_free(scv_buff);
if (path)
my_fclose(sql_file, MYF(MY_WME));
DBUG_RETURN(0);
}
else
@ -3281,6 +3286,10 @@ static void dump_trigger_old(FILE *sql_file, MYSQL_RES *show_triggers_rs,
if (opt_compact)
fprintf(sql_file, "/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n");
if (opt_drop_trigger)
fprintf(sql_file, "/*!50032 DROP TRIGGER IF EXISTS %s */;\n",
(*show_trigger_row)[0]);
fprintf(sql_file,
"DELIMITER ;;\n"
"/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n"
@ -3361,6 +3370,10 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs,
switch_sql_mode(sql_file, ";", row[1]);
if (opt_drop_trigger)
fprintf(sql_file, "/*!50032 DROP TRIGGER IF EXISTS %s */;\n",
row[0]);
query_str= cover_definer_clause(row[2], strlen(row[2]),
C_STRING_WITH_LEN("50017"),
C_STRING_WITH_LEN("50003"),
@ -5471,7 +5484,7 @@ static ulong find_set(TYPELIB *lib, const char *x, size_t length,
var_len= (uint) (pos - start);
strmake(buff, start, MY_MIN(sizeof(buff) - 1, var_len));
find= find_type(buff, lib, FIND_TYPE_BASIC);
if (!find)
if (find <= 0)
{
*err_pos= (char*) start;
*err_len= var_len;
@ -5929,8 +5942,7 @@ static my_bool get_view_structure(char *table, char* db)
dynstr_free(&ds_view);
}
if (switch_character_set_results(mysql, default_charset))
DBUG_RETURN(1);
switch_character_set_results(mysql, default_charset);
/* If a separate .sql file was opened, close it now */
if (sql_file != md_result_file)

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
Copyright (c) 2011, 2016, MariaDB
Copyright (c) 2011, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -677,7 +677,7 @@ int main(int argc, char **argv)
MYF(0))))
return -2;
for (counter= 0; *argv != NULL; argv++) /* Loop through tables */
for (; *argv != NULL; argv++) /* Loop through tables */
{
pthread_mutex_lock(&counter_mutex);
while (counter == opt_use_threads)

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
Copyright (c) 2010, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2005, 2015, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
Copyright (c) 2010, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2009, 2016, Monty Program Ab.
Copyright (c) 2009, 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -82,7 +82,7 @@ static my_bool non_blocking_api_enabled= 0;
#define MAX_DELIMITER_LENGTH 16
#define DEFAULT_MAX_CONN 64
#define DIE_BUFF_SIZE 8192
#define DIE_BUFF_SIZE 256*1024
/* Flags controlling send and reap */
#define QUERY_SEND_FLAG 1
@ -574,15 +574,17 @@ struct st_replace *glob_replace= 0;
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
const char *from, int len);
static void cleanup_and_exit(int exit_code) __attribute__((noreturn));
ATTRIBUTE_NORETURN
static void cleanup_and_exit(int exit_code);
void really_die(const char *msg) __attribute__((noreturn));
ATTRIBUTE_NORETURN
void really_die(const char *msg);
void report_or_die(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
void die(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2)
__attribute__((noreturn));
ATTRIBUTE_NORETURN ATTRIBUTE_FORMAT(printf, 1, 2)
void die(const char *fmt, ...);
static void make_error_message(char *buf, size_t len, const char *fmt, va_list args);
void abort_not_supported_test(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2)
__attribute__((noreturn));
ATTRIBUTE_NORETURN ATTRIBUTE_FORMAT(printf, 1, 2)
void abort_not_supported_test(const char *fmt, ...);
void verbose_msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
void log_msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
@ -602,7 +604,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
void str_to_file(const char *fname, char *str, int size);
void str_to_file2(const char *fname, char *str, int size, my_bool append);
void fix_win_paths(char *val, int len);
void fix_win_paths(char *val, size_t len);
const char *get_errname_from_code (uint error_code);
int multi_reg_replace(struct st_replace_regex* r,char* val);
@ -1063,7 +1065,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
if (!(v= var_get(p, &p, 0, 0)))
{
report_or_die( "Bad variable in eval");
return;
DBUG_VOID_RETURN;
}
dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
}
@ -1721,12 +1723,22 @@ int cat_file(DYNAMIC_STRING* ds, const char* filename)
{
int fd;
size_t len;
char buff[16384];
char *buff;
if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
return 1;
while((len= my_read(fd, (uchar*)&buff,
sizeof(buff)-1, MYF(0))) > 0)
len= (size_t) my_seek(fd, 0, SEEK_END, MYF(0));
my_seek(fd, 0, SEEK_SET, MYF(0));
if (len == (size_t)MY_FILEPOS_ERROR ||
!(buff= (char*)my_malloc(len + 1, MYF(0))))
{
my_close(fd, MYF(0));
return 1;
}
len= my_read(fd, (uchar*)buff, len, MYF(0));
my_close(fd, MYF(0));
{
char *p= buff, *start= buff,*end=buff+len;
while (p < end)
@ -1749,7 +1761,7 @@ int cat_file(DYNAMIC_STRING* ds, const char* filename)
*p= 0;
replace_dynstr_append_mem(ds, start, p-start);
}
my_close(fd, MYF(0));
my_free(buff);
return 0;
}
@ -1776,7 +1788,7 @@ static int run_command(char* cmd,
if (!(res_file= popen(cmd, "r")))
{
report_or_die("popen(\"%s\", \"r\") failed", cmd);
return -1;
DBUG_RETURN(-1);
}
while (fgets(buf, sizeof(buf), res_file))
@ -2642,6 +2654,7 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
if (!mysql)
{
struct st_command command;
DBUG_ASSERT(query_end);
memset(&command, 0, sizeof(command));
command.query= (char*)query;
command.first_word_len= (*query_end - query);
@ -2873,7 +2886,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
dynstr_free(&ds_query);
dynstr_free(&ds_col);
eval_expr(var, "", 0);
return;
DBUG_VOID_RETURN;
}
{
@ -2898,7 +2911,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
ds_col.str, ds_query.str);
dynstr_free(&ds_query);
dynstr_free(&ds_col);
return;
DBUG_VOID_RETURN;
}
DBUG_PRINT("info", ("Found column %d with name '%s'",
i, fields[i].name));
@ -3344,7 +3357,7 @@ void do_exec(struct st_command *command)
if (!*cmd)
{
report_or_die("Missing argument in exec");
return;
DBUG_VOID_RETURN;
}
command->last_argument= command->end;
@ -3370,6 +3383,12 @@ void do_exec(struct st_command *command)
#endif
#endif
if (disable_result_log)
{
/* Collect stderr output as well, for the case app. crashes or returns error.*/
dynstr_append(&ds_cmd, " 2>&1");
}
DBUG_PRINT("info", ("Executing '%s' as '%s'",
command->first_argument, ds_cmd.str));
@ -3378,7 +3397,7 @@ void do_exec(struct st_command *command)
dynstr_free(&ds_cmd);
if (command->abort_on_error)
report_or_die("popen(\"%s\", \"r\") failed", command->first_argument);
return;
DBUG_VOID_RETURN;
}
ds_result= &ds_res;
@ -3405,16 +3424,7 @@ void do_exec(struct st_command *command)
len--;
}
#endif
if (disable_result_log)
{
if (len)
buf[len-1] = 0;
DBUG_PRINT("exec_result",("%s", buf));
}
else
{
replace_dynstr_append_mem(ds_result, buf, len);
}
replace_dynstr_append_mem(ds_result, buf, len);
}
error= pclose(res_file);
@ -3424,7 +3434,7 @@ void do_exec(struct st_command *command)
dynstr_free(&ds_sorted);
}
if (error > 0)
if (error)
{
uint status= WEXITSTATUS(error);
int i;
@ -3436,7 +3446,7 @@ void do_exec(struct st_command *command)
ds_cmd.str, error, status, errno,
ds_res.str);
dynstr_free(&ds_cmd);
return;
DBUG_VOID_RETURN;
}
DBUG_PRINT("info",
@ -3470,6 +3480,12 @@ void do_exec(struct st_command *command)
}
dynstr_free(&ds_cmd);
if (disable_result_log)
{
/* Disable output in case of successful exit.*/
dynstr_set(&ds_res,"");
}
DBUG_VOID_RETURN;
}
@ -3569,7 +3585,7 @@ void do_system(struct st_command *command)
if (strlen(command->first_argument) == 0)
{
report_or_die("Missing arguments to system, nothing to do!");
return;
DBUG_VOID_RETURN;
}
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
@ -3607,6 +3623,37 @@ void do_system(struct st_command *command)
}
/* returns TRUE if path is inside a sandbox */
bool is_sub_path(const char *path, size_t plen, const char *sandbox)
{
size_t len= strlen(sandbox);
if (!sandbox || !len || plen <= len || memcmp(path, sandbox, len - 1)
|| path[len] != '/')
return false;
return true;
}
/* returns TRUE if path cannot be modified */
bool bad_path(const char *path)
{
size_t plen= strlen(path);
const char *vardir= getenv("MYSQLTEST_VARDIR");
if (is_sub_path(path, plen, vardir))
return false;
const char *tmpdir= getenv("MYSQL_TMP_DIR");
if (is_sub_path(path, plen, tmpdir))
return false;
report_or_die("Path '%s' is not a subdirectory of MYSQLTEST_VARDIR '%s'"
"or MYSQL_TMP_DIR '%s'",
path, vardir, tmpdir);
return true;
}
/*
SYNOPSIS
set_wild_chars
@ -3665,6 +3712,9 @@ void do_remove_file(struct st_command *command)
rm_args, sizeof(rm_args)/sizeof(struct command_arg),
' ');
if (bad_path(ds_filename.str))
DBUG_VOID_RETURN;
DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
error= my_delete(ds_filename.str, MYF(disable_warnings ? 0 : MY_WME)) != 0;
handle_command_error(command, error, my_errno);
@ -3708,6 +3758,9 @@ void do_remove_files_wildcard(struct st_command *command)
' ');
fn_format(dirname, ds_directory.str, "", "", MY_UNPACK_FILENAME);
if (bad_path(ds_directory.str))
DBUG_VOID_RETURN;
DBUG_PRINT("info", ("listing directory: %s", dirname));
if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT | MY_WME))))
{
@ -3782,6 +3835,9 @@ void do_copy_file(struct st_command *command)
sizeof(copy_file_args)/sizeof(struct command_arg),
' ');
if (bad_path(ds_to_file.str))
DBUG_VOID_RETURN;
DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
/* MY_HOLD_ORIGINAL_MODES prevents attempts to chown the file */
error= (my_copy(ds_from_file.str, ds_to_file.str,
@ -3819,6 +3875,9 @@ void do_move_file(struct st_command *command)
sizeof(move_file_args)/sizeof(struct command_arg),
' ');
if (bad_path(ds_to_file.str))
DBUG_VOID_RETURN;
DBUG_PRINT("info", ("Move %s to %s", ds_from_file.str, ds_to_file.str));
error= (my_rename(ds_from_file.str, ds_to_file.str,
MYF(disable_warnings ? 0 : MY_WME)) != 0);
@ -3857,6 +3916,9 @@ void do_chmod_file(struct st_command *command)
sizeof(chmod_file_args)/sizeof(struct command_arg),
' ');
if (bad_path(ds_file.str))
DBUG_VOID_RETURN;
/* Parse what mode to set */
if (ds_mode.length != 4 ||
str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
@ -3928,6 +3990,9 @@ void do_mkdir(struct st_command *command)
mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
' ');
if (bad_path(ds_dirname.str))
DBUG_VOID_RETURN;
DBUG_PRINT("info", ("creating directory: %s", ds_dirname.str));
error= my_mkdir(ds_dirname.str, 0777, MYF(MY_WME)) != 0;
handle_command_error(command, error, my_errno);
@ -3935,6 +4000,65 @@ void do_mkdir(struct st_command *command)
DBUG_VOID_RETURN;
}
/*
Remove directory recursively.
*/
static int rmtree(const char *dir)
{
char path[FN_REFLEN];
char sep[]={ FN_LIBCHAR, 0 };
int err=0;
MY_DIR *dir_info= my_dir(dir, MYF(MY_DONT_SORT | MY_WANT_STAT));
if (!dir_info)
return 1;
for (uint i= 0; i < dir_info->number_of_files; i++)
{
FILEINFO *file= dir_info->dir_entry + i;
/* Skip "." and ".." */
if (!strcmp(file->name, ".") || !strcmp(file->name, ".."))
continue;
strxnmov(path, sizeof(path), dir, sep, file->name, NULL);
if (!MY_S_ISDIR(file->mystat->st_mode))
{
err= my_delete(path, 0);
#ifdef _WIN32
/*
On Windows, check and possible reset readonly attribute.
my_delete(), or DeleteFile does not remove theses files.
*/
if (err)
{
DWORD attr= GetFileAttributes(path);
if (attr != INVALID_FILE_ATTRIBUTES &&
(attr & FILE_ATTRIBUTE_READONLY))
{
SetFileAttributes(path, attr &~ FILE_ATTRIBUTE_READONLY);
err= my_delete(path, 0);
}
}
#endif
}
else
err= rmtree(path);
if(err)
break;
}
my_dirend(dir_info);
if (!err)
err= rmdir(dir);
return err;
}
/*
SYNOPSIS
do_rmdir
@ -3942,12 +4066,11 @@ void do_mkdir(struct st_command *command)
DESCRIPTION
rmdir <dir_name>
Remove the empty directory <dir_name>
Remove the directory tree
*/
void do_rmdir(struct st_command *command)
{
int error;
static DYNAMIC_STRING ds_dirname;
const struct command_arg rmdir_args[] = {
{ "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove" }
@ -3958,9 +4081,13 @@ void do_rmdir(struct st_command *command)
rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
' ');
if (bad_path(ds_dirname.str))
DBUG_VOID_RETURN;
DBUG_PRINT("info", ("removing directory: %s", ds_dirname.str));
error= rmdir(ds_dirname.str) != 0;
handle_command_error(command, error, errno);
if (rmtree(ds_dirname.str))
handle_command_error(command, 1, errno);
dynstr_free(&ds_dirname);
DBUG_VOID_RETURN;
}
@ -4073,6 +4200,9 @@ static void do_list_files_write_file_command(struct st_command *command,
list_files_args,
sizeof(list_files_args)/sizeof(struct command_arg), ' ');
if (bad_path(ds_filename.str))
DBUG_VOID_RETURN;
init_dynamic_string(&ds_content, "", 1024, 1024);
error= get_list_files(&ds_content, &ds_dirname, &ds_wild);
handle_command_error(command, error, my_errno);
@ -4124,7 +4254,8 @@ void read_until_delimiter(DYNAMIC_STRING *ds,
while (1)
{
c= my_getc(cur_file->file);
if (c == '\r')
c= my_getc(cur_file->file);
if (c == '\n')
{
cur_file->lineno++;
@ -4175,6 +4306,9 @@ void do_write_file_command(struct st_command *command, my_bool append)
sizeof(write_file_args)/sizeof(struct command_arg),
' ');
if (bad_path(ds_filename.str))
DBUG_VOID_RETURN;
if (!append && access(ds_filename.str, F_OK) == 0)
{
/* The file should not be overwritten */
@ -4556,7 +4690,7 @@ void do_perl(struct st_command *command)
if (command->abort_on_error)
die("popen(\"%s\", \"r\") failed", buf);
dynstr_free(&ds_delimiter);
return;
DBUG_VOID_RETURN;
}
while (fgets(buf, sizeof(buf), res_file))
@ -6388,6 +6522,16 @@ my_bool end_of_query(int c)
}
static inline bool is_escape_char(char c, char in_string)
{
if (c != '\\' || in_string == '`') return false;
if (!cur_con) return true;
uint server_status= cur_con->mysql->server_status;
if (server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) return false;
return !(server_status & SERVER_STATUS_ANSI_QUOTES && in_string == '"');
}
/*
Read one "line" from the file
@ -6414,7 +6558,7 @@ my_bool end_of_query(int c)
int read_line(char *buf, int size)
{
char c, UNINIT_VAR(last_quote), last_char= 0;
char c, last_quote=0, last_char= 0;
char *p= buf, *buf_end= buf + size - 1;
int skip_char= 0;
my_bool have_slash= FALSE;
@ -6496,7 +6640,7 @@ int read_line(char *buf, int size)
state= R_Q;
}
}
have_slash= (c == '\\');
have_slash= is_escape_char(c, last_quote);
break;
case R_COMMENT:
@ -6566,7 +6710,7 @@ int read_line(char *buf, int size)
case R_Q:
if (c == last_quote)
state= R_NORMAL;
else if (c == '\\')
else if (is_escape_char(c, last_quote))
state= R_SLASH_IN_Q;
break;
@ -7345,7 +7489,7 @@ void free_win_path_patterns()
=> all \ from c:\mysql\m... until next space is converted into /
*/
void fix_win_paths(char *val, int len)
void fix_win_paths(char *val, size_t len)
{
#ifdef _WIN32
uint i;
@ -9875,25 +10019,39 @@ bool parse_re_part(char *start_re, char *end_re,
Returns: st_replace_regex struct with pairs of substitutions
*/
void append_replace_regex(char*, char*, struct st_replace_regex*, char**);
struct st_replace_regex* init_replace_regex(char* expr)
{
char *expr_end, *buf_p;
struct st_replace_regex* res;
char* buf,*expr_end;
char* p, start_re, end_re= 1;
char* buf_p;
uint expr_len= strlen(expr);
struct st_regex reg;
/* my_malloc() will die on fail with MY_FAE */
res=(struct st_replace_regex*)my_malloc(
sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME));
sizeof(*res)+8192 ,MYF(MY_FAE+MY_WME));
my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex), 128, 128, MYF(0));
buf= (char*)res + sizeof(*res);
expr_end= expr + expr_len;
buf_p= (char*)res + sizeof(*res);
append_replace_regex(expr, expr_end, res, &buf_p);
res->odd_buf_len= res->even_buf_len= 8192;
res->even_buf= (char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
res->odd_buf= (char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
res->buf= res->even_buf;
return res;
}
void append_replace_regex(char* expr, char *expr_end, struct st_replace_regex* res,
char **buf_p)
{
char* p, start_re, end_re= 1;
struct st_regex reg;
p= expr;
buf_p= buf;
/* for each regexp substitution statement */
while (p < expr_end)
@ -9912,13 +10070,34 @@ struct st_replace_regex* init_replace_regex(char* expr)
}
start_re= 0;
reg.pattern= buf_p;
if (parse_re_part(&start_re, &end_re, &p, expr_end, &buf_p))
goto err;
reg.pattern= *buf_p;
reg.replace= buf_p;
if (parse_re_part(&start_re, &end_re, &p, expr_end, &buf_p))
goto err;
/* Allow variable for the *entire* list of replacements */
if (*p == '$')
{
const char *v_end;
VAR *val= var_get(p, &v_end, 0, 1);
if (val)
{
char *expr, *expr_end;
expr= val->str_val;
expr_end= expr + val->str_val_len;
append_replace_regex(expr, expr_end, res, buf_p);
}
p= (char *) v_end + 1;
continue;
}
else
{
if (parse_re_part(&start_re, &end_re, &p, expr_end, buf_p))
goto err;
reg.replace= *buf_p;
if (parse_re_part(&start_re, &end_re, &p, expr_end, buf_p))
goto err;
}
/* Check if we should do matching case insensitive */
if (p < expr_end && *p == 'i')
@ -9931,17 +10110,12 @@ struct st_replace_regex* init_replace_regex(char* expr)
if (insert_dynamic(&res->regex_arr, &reg))
die("Out of memory");
}
res->odd_buf_len= res->even_buf_len= 8192;
res->even_buf= (char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
res->odd_buf= (char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
res->buf= res->even_buf;
return res;
return;
err:
my_free(res);
die("Error parsing replace_regex \"%s\"", expr);
return 0;
}
/*
@ -10021,12 +10195,6 @@ void do_get_replace_regex(struct st_command *command)
{
char *expr= command->first_argument;
free_replace_regex();
/* Allow variable for the *entire* list of replacements */
if (*expr == '$')
{
VAR *val= var_get(expr, NULL, 0, 1);
expr= val ? val->str_val : NULL;
}
if (expr && *expr && !(glob_replace_regex=init_replace_regex(expr)))
die("Could not init replace_regex");
command->last_argument= command->end;

View file

@ -88,20 +88,24 @@ ENDIF()
OPTION(ENABLED_LOCAL_INFILE "" ON)
SET(WITH_INNODB_SNAPPY OFF CACHE STRING "")
IF(WIN32)
SET(WITH_LIBARCHIVE STATIC CACHE STRING "")
ELSEIF(RPM)
SET(WITH_SSL system CACHE STRING "")
SET(WITH_ZLIB system CACHE STRING "")
SET(CHECKMODULE /usr/bin/checkmodule CACHE STRING "")
SET(SEMODULE_PACKAGE /usr/bin/semodule_package CACHE STRING "")
SET(WITH_LIBARCHIVE ON CACHE STRING "")
ELSEIF(DEB)
SET(WITH_SSL system CACHE STRING "")
SET(WITH_ZLIB system CACHE STRING "")
SET(WITH_LIBWRAP ON)
SET(HAVE_EMBEDDED_PRIVILEGE_CONTROL ON)
SET(WITH_LIBARCHIVE ON CACHE STRING "")
ELSE()
SET(WITH_SSL bundled CACHE STRING "")
SET(WITH_ZLIB bundled CACHE STRING "")
SET(WITH_JEMALLOC static CACHE STRING "")
SET(WITH_LIBARCHIVE STATIC CACHE STRING "")
ENDIF()
IF(NOT COMPILATION_COMMENT)

View file

@ -23,13 +23,22 @@ SET(CPACK_COMPONENT_SHAREDLIBRARIES_GROUP "shared")
SET(CPACK_COMPONENT_COMMON_GROUP "common")
SET(CPACK_COMPONENT_CLIENTPLUGINS_GROUP "common")
SET(CPACK_COMPONENT_COMPAT_GROUP "compat")
SET(CPACK_COMPONENT_BACKUP_GROUP "backup")
SET(CPACK_COMPONENTS_ALL Server ManPagesServer IniFiles Server_Scripts
SupportFiles Development ManPagesDevelopment
ManPagesTest Readme ManPagesClient Test
Common Client SharedLibraries ClientPlugins)
Common Client SharedLibraries ClientPlugins
backup
)
SET(CPACK_RPM_PACKAGE_NAME ${CPACK_PACKAGE_NAME})
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}")
IF(CMAKE_VERSION VERSION_LESS "3.6.0")
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}")
ELSE()
SET(CPACK_RPM_FILE_NAME "RPM-DEFAULT")
SET(CPACK_RPM_DEBUGINFO_PACKAGE ON)
ENDIF()
SET(CPACK_RPM_PACKAGE_RELEASE "1%{?dist}")
SET(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
@ -112,6 +121,7 @@ SET(CPACK_RPM_client_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSC
SET(CPACK_RPM_compat_USER_FILELIST ${ignored})
SET(CPACK_RPM_devel_USER_FILELIST ${ignored})
SET(CPACK_RPM_test_USER_FILELIST ${ignored})
SET(CPACK_RPM_backup_USER_FILELIST ${ignored})
# "set/append array" - append a set of strings, separated by a space
MACRO(SETA var)

View file

@ -82,7 +82,3 @@ EXECUTE_PROCESS (
IF(NOT RESULT EQUAL 0)
MESSAGE(FATAL_ERROR "Could not create initial database \n ${OUT} \n ${ERR}")
ENDIF()
EXECUTE_PROCESS (
COMMAND "@CMAKE_COMMAND@" -E touch ${CMAKE_CURRENT_BINARY_DIR}/initdb.dep
)

View file

@ -45,7 +45,7 @@ MACRO(EXTRACT_LINK_LIBRARIES target var)
ENDIF()
ENDMACRO()
EXTRACT_LINK_LIBRARIES(mariadb LIBS)
EXTRACT_LINK_LIBRARIES(libmariadb LIBS)
EXTRACT_LINK_LIBRARIES(mysqlserver EMB_LIBS)
SET(LIBS "-lmariadb ${ZLIB_DEPS} ${LIBS} ${openssl_libs}")
@ -72,6 +72,6 @@ REPLACE_FOR_CLIENTS(CFLAGS "[DU]DBUG_OFF" "[DU]SAFE_MUTEX" "[DU]NDEBUG"
"xstrconst" "xc99=none" "AC99" "restrict" "W[-A-Za-z]*=[-A-Za-z0-9]*")
# Same for --libs
REPLACE_FOR_CLIENTS(LIBS lmtmalloc static-libcxa i-static static-intel)
REPLACE_FOR_CLIENTS(LIBS "Wl,[^ ]*" lmtmalloc static-libcxa i-static static-intel)
REPLACE_FOR_CLIENTS(EMB_LIBS lmtmalloc static-libcxa i-static static-intel)

View file

@ -1,17 +1,3 @@
IF(NOT EXISTS ${CMAKE_SOURCE_DIR}/libmariadb/CMakeLists.txt AND GIT_EXECUTABLE)
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule init
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
ENDIF()
IF(NOT EXISTS ${CMAKE_SOURCE_DIR}/libmariadb/CMakeLists.txt)
MESSAGE(FATAL_ERROR "No MariaDB Connector/C! Run
git submodule init
git submodule update
Then restart the build.
")
ENDIF()
SET(OPT CONC_)
IF (CMAKE_BUILD_TYPE STREQUAL "Debug")

View file

@ -139,8 +139,8 @@ IF(MSVC)
ENDIF()
#TODO: update the code and remove the disabled warnings
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4800 /wd4805 /wd4996")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800 /wd4805 /wd4996 /wd4291 /wd4577 /we4099")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4800 /wd4805 /wd4996 /we4700")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800 /wd4805 /wd4996 /wd4291 /wd4577 /we4099 /we4700")
ENDIF()

View file

@ -5,7 +5,7 @@ MACRO (CHECK_PCRE)
IF(WITH_PCRE STREQUAL "system" OR WITH_PCRE STREQUAL "auto")
CHECK_LIBRARY_EXISTS(pcre pcre_stack_guard "" HAVE_PCRE)
ENDIF()
IF(NOT HAVE_PCRE)
IF(NOT HAVE_PCRE OR WITH_PCRE STREQUAL "bundled")
IF (WITH_PCRE STREQUAL "system")
MESSAGE(FATAL_ERROR "system pcre is not found or unusable")
ENDIF()

View file

@ -201,13 +201,15 @@ MACRO(MYSQL_ADD_PLUGIN)
# executable to the linker command line (it would result into link error).
# Thus we skip TARGET_LINK_LIBRARIES on Linux, as it would only generate
# an additional dependency.
IF(NOT ARG_CLIENT)
IF(ARG_RECOMPILE_FOR_EMBEDDED OR ARG_STORAGE_ENGINE)
IF(MSVC)
ADD_DEPENDENCIES(${target} gen_mysqld_lib)
TARGET_LINK_LIBRARIES(${target} mysqld_import_lib)
ELSEIF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
TARGET_LINK_LIBRARIES (${target} mysqld)
ENDIF()
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT WITH_ASAN)
TARGET_LINK_LIBRARIES (${target} "-Wl,--no-undefined")
ENDIF()
ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDENCIES})
@ -233,9 +235,11 @@ MACRO(MYSQL_ADD_PLUGIN)
SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_PROVIDES "cmake_bug_13248" PARENT_SCOPE)
SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_OBSOLETES "cmake_bug_13248" PARENT_SCOPE)
SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} PARENT_SCOPE)
IF(NOT ARG_CLIENT AND NOT ARG_CONFIG AND UNIX)
SET(ARG_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/${target}.cnf")
FILE(WRITE ${ARG_CONFIG} "[mariadb]\nplugin-load-add=${ARG_MODULE_OUTPUT_NAME}.so\n")
IF(NOT ARG_CLIENT AND UNIX)
IF (NOT ARG_CONFIG)
SET(ARG_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/${target}.cnf")
FILE(WRITE ${ARG_CONFIG} "[mariadb]\nplugin-load-add=${ARG_MODULE_OUTPUT_NAME}.so\n")
ENDIF()
INSTALL(FILES ${ARG_CONFIG} COMPONENT ${ARG_COMPONENT} DESTINATION ${INSTALL_SYSCONF2DIR})
SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*" PARENT_SCOPE)
ENDIF()

View file

@ -1,4 +1,5 @@
# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2009, 2012, Oracle and/or its affiliates.
# Copyright (c) 2011, 2017, MariaDB Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -11,7 +12,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# We support different versions of SSL:
# - "bundled" uses source code in <source dir>/extra/yassl
@ -159,7 +160,7 @@ MACRO (MYSQL_CHECK_SSL)
HAVE_EncryptAes128Gcm)
ELSE()
IF(WITH_SSL STREQUAL "system")
MESSAGE(SEND_ERROR "Cannot find appropriate system libraries for SSL. Use WITH_SSL=bundled to enable SSL support")
MESSAGE(SEND_ERROR "Cannot find appropriate system libraries for SSL. Use WITH_SSL=bundled to enable SSL support")
ENDIF()
MYSQL_USE_BUNDLED_SSL()
ENDIF()

31
cmake/submodules.cmake Normal file
View file

@ -0,0 +1,31 @@
# update submodules automatically
IF(GIT_EXECUTABLE AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" config --get cmake.update-submodules
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE cmake_update_submodules
RESULT_VARIABLE git_config_get_result)
IF(git_config_get_result EQUAL 128 OR cmake_update_submodules MATCHES no)
SET(update_result 0)
ELSEIF (cmake_update_submodules MATCHES force)
MESSAGE(STATUS "Updating submodules (forced)")
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --force
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE update_result)
ELSEIF (cmake_update_submodules MATCHES yes)
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE update_result)
ELSE()
MESSAGE(STATUS "Updating submodules")
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE update_result)
ENDIF()
ENDIF()
IF(update_result OR NOT EXISTS ${CMAKE_SOURCE_DIR}/libmariadb/CMakeLists.txt)
MESSAGE(FATAL_ERROR "No MariaDB Connector/C! Run
git submodule update --init
Then restart the build.
")
ENDIF()

View file

@ -70,9 +70,11 @@ MACRO(CHECK_SYSTEMD)
UNSET(HAVE_SYSTEMD_SD_NOTIFYF)
MESSAGE_ONCE(systemd "Systemd features not enabled")
IF(WITH_SYSTEMD STREQUAL "yes")
MESSAGE(FATAL_ERROR "Requested WITH_SYSTEMD=YES however no dependencies installed/found")
MESSAGE(FATAL_ERROR "Requested WITH_SYSTEMD=yes however no dependencies installed/found")
ENDIF()
ENDIF()
ELSEIF(NOT WITH_SYSTEMD STREQUAL "no")
MESSAGE(FATAL_ERROR "Invalid value for WITH_SYSTEMD. Must be 'yes', 'no', or 'auto'.")
ENDIF()
ENDIF()
ENDMACRO()

View file

@ -26,7 +26,7 @@ ENDIF()
OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ${with_wsrep_default})
# Set the patch version
SET(WSREP_PATCH_VERSION "19")
SET(WSREP_PATCH_VERSION "20")
# Obtain wsrep API version
FILE(STRINGS "${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h" WSREP_API_VERSION
@ -41,4 +41,3 @@ SET(WSREP_PROC_INFO ${WITH_WSREP})
IF(WITH_WSREP)
SET(WSREP_PATCH_VERSION "wsrep_${WSREP_VERSION}")
ENDIF()

View file

@ -576,21 +576,4 @@
#define __STDC_FORMAT_MACROS
#endif
/*
stat structure (from <sys/stat.h>) is conditionally defined
to have different layout and size depending on the defined macros.
The correct macro is defined in my_config.h, which means it MUST be
included first (or at least before <features.h> - so, practically,
before including any system headers).
Check the include order by looking at __GLIBC__ (defined in <features.h>)
But we cannot force all third-party clients/connectors to include
my_config.h first. So, their crashes are their responsibility,
we enable this check only for MariaDB sources (SAFE_MUTEX check).
*/
#if defined(__GLIBC__) && defined(SAFE_MUTEX)
#error <my_config.h> MUST be included first!
#endif
#endif

View file

@ -0,0 +1,20 @@
#
# !include this file into your my.cnf (or any of *.cnf files in /etc/mysql/conf.d)
# and it will enable data at rest encryption. This is a simple way to
# ensure that everything that can be encrypted will be and your
# data will not leak unencrypted.
#
# DO NOT EDIT THIS FILE! On MariaDB upgrades it might be replaced with a
# newer version and your edits will be lost. Instead, add your edits
# to the .cnf file after the !include directive.
#
# NOTE that you also need to install an encryption plugin for the encryption
# to work. See https://mariadb.com/kb/en/mariadb/data-at-rest-encryption/#encryption-key-management
#
[mariadb]
aria-encrypt-tables
encrypt-binlog
encrypt-tmp-disk-tables
encrypt-tmp-files
loose-innodb-encrypt-log
loose-innodb-encrypt-tables

View file

@ -81,6 +81,11 @@ if [[ $GCCVERSION -lt 40800 ]] || [[ $(arch) =~ i[346]86 ]]
then
sed '/Package: mariadb-plugin-rocksdb/,+7d' -i debian/control
fi
if [[ $GCCVERSION -lt 40800 ]]
then
sed '/Package: mariadb-plugin-aws-key-management-10.2/,+13d' -i debian/control
fi
# Adjust changelog, add new version
echo "Incrementing changelog and starting build scripts"

52
debian/control vendored
View file

@ -21,7 +21,7 @@ Build-Depends: bison,
libpam0g-dev,
libpcre3-dev (>= 2:8.35-3.2~),
libreadline-gplv2-dev,
libssl-dev,
libssl-dev | libssl1.0-dev,
libsnappy-dev,
libsystemd-dev,
libxml2-dev,
@ -30,6 +30,7 @@ Build-Depends: bison,
po-debconf,
psmisc,
unixodbc-dev,
uuid-dev,
zlib1g-dev (>= 1:1.1.3-5~)
Standards-Version: 3.8.2
Homepage: http://mariadb.org/
@ -47,13 +48,9 @@ Conflicts: mariadb-galera-server-10.0 (<< 10.0.5),
mariadb-server-5.2,
mariadb-server-5.3,
mariadb-server-5.5 (<< 5.5.33)
Replaces: libmariadbclient18,
libmysqlclient18,
libmysqlclient19,
Replaces: libmysqlclient19,
libmysqlclient20
Provides: libmariadbclient18,
libmysqlclient18,
libmysqlclient19,
Provides: libmysqlclient19,
libmysqlclient20
Description: MariaDB database client library
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
@ -67,27 +64,29 @@ Package: libmariadbclient18
Section: libs
Architecture: any
Depends: libmariadb3 (= ${binary:Version}), ${misc:Depends}
Replaces: libmariadbclient18
Provides: libmariadbclient18
Description: Virtual package to satisfy external depends
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
language in the world. The main goals of MariaDB are speed, robustness and
ease of use.
.
This is an empty package that depends on the libmariadb3
package.
This package provides compatibility symlinks for libmariadb3
Package: libmysqlclient18
Section: libs
Architecture: any
Depends: libmariadb3 (= ${binary:Version}), ${misc:Depends}
Replaces: libmysqlclient18
Provides: libmysqlclient18
Description: Virtual package to satisfy external depends
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
language in the world. The main goals of MariaDB are speed, robustness and
ease of use.
.
This is an empty package that depends on the libmariadb3
package.
This package provides compatibility symlinks for libmariadb3
Package: libmariadb-dev
Architecture: any
@ -173,8 +172,7 @@ Description: MariaDB database common files (e.g. /etc/mysql/conf.d/mariadb.cnf)
Package: mariadb-client-core-10.2
Architecture: any
Depends: libmariadb3 (>= ${source:Version}),
mariadb-common (>= ${source:Version}),
Depends: mariadb-common (>= ${source:Version}),
${misc:Depends},
${shlibs:Depends}
Conflicts: mariadb-client-10.0,
@ -237,7 +235,6 @@ Description: MariaDB database core client binaries
Package: mariadb-client-10.2
Architecture: any
Depends: debianutils (>=1.6),
libmariadb3 (>= ${source:Version}),
mariadb-client-core-10.2 (>= ${source:Version}),
mariadb-common,
${misc:Depends},
@ -291,8 +288,7 @@ Description: MariaDB database client binaries
Package: mariadb-server-core-10.2
Architecture: any
Depends: libmariadb3 (>= ${binary:Version}),
mariadb-common (>= ${source:Version}),
Depends: mariadb-common (>= ${source:Version}),
${misc:Depends},
${shlibs:Depends}
Conflicts: mariadb-server-core-10.0,
@ -552,6 +548,16 @@ Breaks: mariadb-gssapi-client-10.1, mariadb-gssapi-client-10.2
Replaces: mariadb-gssapi-client-10.1, mariadb-gssapi-client-10.2
Description: GSSAPI authentication plugin for MariaDB client
Package: mariadb-backup-10.2
Section: database
Architecture: any
Breaks: mariadb-backup-10.1
Replaces: mariadb-backup-10.1
Depends: mariadb-server-10.2,
${misc:Depends},
${shlibs:Depends}
Description: Backup tool for MariaDB server
Package: mariadb-plugin-cracklib-password-check
Architecture: any
Depends: libcrack2 (>= 2.9.0),
@ -562,6 +568,20 @@ Description: CrackLib Password Validation Plugin for MariaDB
This password validation plugin uses cracklib to allow only
sufficiently secure (as defined by cracklib) user passwords in MariaDB.
Package: mariadb-plugin-aws-key-management-10.2
Section: database
Architecture: any
Breaks: mariadb-aws-key-management-10.1
Replaces: mariadb-aws-key-management-10.1
Depends: mariadb-server-10.2,
libcurl3,
${misc:Depends},
${shlibs:Depends}
Description: Amazon Web Service Key Management Service Plugin for MariaDB
This encryption key management plugin gives an interface to the Amazon Web
Services Key Management Service for managing encryption keys used for MariaDB
data-at-rest encryption.
Package: mariadb-test
Architecture: any
Depends: mariadb-client-10.2 (= ${binary:Version}),

View file

@ -1,7 +1,8 @@
usr/bin/mysql_config
usr/include/mysql/*.h
usr/include/mysql/psi/*.h
usr/include/mysql
usr/lib/*/libmariadb.so
usr/lib/*/libmysqlclient.so
usr/lib/*/libmariadbclient.so
usr/lib/*/libmariadbclient.a
usr/lib/*/libmysqlservices.a
usr/share/aclocal/mysql.m4

View file

@ -1,2 +0,0 @@
usr/lib/libmysqlclient.so.18 usr/lib/libmysqlclient.so
usr/lib/libmysqlclient_r.so.18 usr/lib/libmysqlclient_r.so

View file

@ -1,5 +1,5 @@
usr/lib/*/libmariadbclient.so.*
usr/lib/*/libmysqlclient.so.*
usr/lib/*/libmysqlclient.so.19
usr/lib/*/libmysqlclient.so.20
usr/lib/*/libmariadb.so.*
usr/lib/mysql/plugin/dialog.so
usr/lib/mysql/plugin/mysql_clear_password.so

1
debian/libmariadbclient18.install vendored Normal file
View file

@ -0,0 +1 @@
usr/lib/*/libmariadbclient.so.18

1
debian/libmysqlclient18.install vendored Normal file
View file

@ -0,0 +1 @@
usr/lib/*/libmysqlclient.so.18

2
debian/mariadb-backup-10.2.install vendored Normal file
View file

@ -0,0 +1,2 @@
usr/bin/mariabackup
usr/bin/mbstream

View file

@ -0,0 +1,2 @@
usr/lib/mysql/plugin/aws_key_management.so
debian/additions/enable_encryption.preset etc/mysql/conf.d/

View file

@ -38,6 +38,7 @@ usr/bin/wsrep_sst_mysqldump
usr/bin/wsrep_sst_rsync
usr/bin/wsrep_sst_xtrabackup
usr/bin/wsrep_sst_xtrabackup-v2
usr/bin/wsrep_sst_mariabackup
usr/lib/mysql/plugin/auth_pam.so
usr/lib/mysql/plugin/auth_socket.so
usr/lib/mysql/plugin/file_key_management.so

View file

@ -10,6 +10,7 @@ usr/share/mysql/estonian
usr/share/mysql/french
usr/share/mysql/german
usr/share/mysql/greek
usr/share/mysql/hindi
usr/share/mysql/hungarian
usr/share/mysql/italian
usr/share/mysql/japanese

View file

@ -11,14 +11,14 @@
--- old/mysql-test/mysql-test-run.pl 2009-06-16 14:24:09.000000000 +0200
+++ new/mysql-test/mysql-test-run.pl 2009-07-04 00:03:34.000000000 +0200
@@ -3578,6 +3578,11 @@ sub mysql_install_db {
mtr_appendfile_to_file("$sql_dir/mysql_system_tables_data.sql",
$bootstrap_sql_file);
mtr_appendfile_to_file("$sql_dir/mysql_system_tables_data.sql",
$bootstrap_sql_file);
+ mtr_tofile($bootstrap_sql_file, "-- Debian removed the default privileges on the 'test' database\n");
+ mtr_tofile($bootstrap_sql_file, "INSERT INTO mysql.db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y');\n");
+ mtr_tofile($bootstrap_sql_file, "INSERT INTO mysql.db VALUES ('%','test\\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y');\n");
+
+ mtr_tofile($bootstrap_sql_file, "-- Debian removed the default privileges on the 'test' database\n");
+ mtr_tofile($bootstrap_sql_file, "INSERT INTO mysql.db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y');\n");
+ mtr_tofile($bootstrap_sql_file, "INSERT INTO mysql.db VALUES ('%','test\\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y');\n");
+
# Add test data for timezone - this is just a subset, on a real
# system these tables will be populated either by mysql_tzinfo_to_sql
# or by downloading the timezone table package from our website
+
# Add test data for timezone - this is just a subset, on a real
# system these tables will be populated either by mysql_tzinfo_to_sql
# or by downloading the timezone table package from our website

1
debian/rules vendored
View file

@ -162,6 +162,7 @@ override_dh_auto_install:
install -D -m 644 debian/mariadb-server-10.2.py $(TMP)/usr/share/apport/package-hooks/source_mariadb-10.2.py
# Install libmariadbclient18 compatibility links
ln -s /usr/lib/$(DEB_HOST_MULTIARCH)/libmariadb.so.3 $(TMP)/usr/lib/$(DEB_HOST_MULTIARCH)/libmariadbclient.so
ln -s /usr/lib/$(DEB_HOST_MULTIARCH)/libmariadb.so.3 $(TMP)/usr/lib/$(DEB_HOST_MULTIARCH)/libmariadbclient.so.18
# Install libmysqlclientclientXX compatibility links

View file

@ -79,7 +79,6 @@ IF(WITH_INNOBASE_STORAGE_ENGINE OR WITH_XTRADB_STORAGE_ENGINE)
../storage/innobase/ut/ut0ut.cc
../storage/innobase/buf/buf0buf.cc
../storage/innobase/page/page0zip.cc
../storage/innobase/os/os0file.cc
../storage/innobase/fil/fil0crypt.cc
)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,117 @@
# Copyright (c) 2013, 2017 Percona LLC and/or its affiliates.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
OPTION(WITH_MARIABACKUP "Include mariabackup" ON)
IF(NOT WITH_MARIABACKUP)
RETURN()
ENDIF()
IF(NOT WIN32)
CHECK_SYMBOL_EXISTS(regcomp regex.h HAVE_SYSTEM_REGEX)
IF(HAVE_SYSTEM_REGEX)
ADD_DEFINITIONS(-DHAVE_SYSTEM_REGEX)
ENDIF()
ENDIF()
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/sql
${CMAKE_CURRENT_SOURCE_DIR}/quicklz
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/crc
)
IF(NOT HAVE_SYSTEM_REGEX)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/pcre)
ENDIF()
ADD_DEFINITIONS(-UMYSQL_SERVER)
########################################################################
# xtrabackup binary
########################################################################
IF(WIN32)
SET(NT_SERVICE_SOURCE ${PROJECT_SOURCE_DIR}/sql/nt_servc.cc)
ELSE()
SET(NT_SERVICE_SOURCE)
ENDIF()
ADD_DEFINITIONS(-DPCRE_STATIC=1)
MYSQL_ADD_EXECUTABLE(mariabackup
xtrabackup.cc
innobackupex.cc
changed_page_bitmap.cc
datasink.c
ds_buffer.c
ds_compress.c
ds_local.c
ds_stdout.c
ds_tmpfile.c
ds_xbstream.c
fil_cur.cc
quicklz/quicklz.c
read_filt.cc
write_filt.cc
wsrep.cc
xbstream_write.c
backup_mysql.cc
backup_copy.cc
encryption_plugin.cc
${PROJECT_SOURCE_DIR}/sql/net_serv.cc
${NT_SERVICE_SOURCE}
${PROJECT_SOURCE_DIR}/libmysqld/libmysql.c
COMPONENT backup
)
# Export all symbols on Unix, for better crash callstacks
SET_TARGET_PROPERTIES(mariabackup PROPERTIES ENABLE_EXPORTS TRUE)
ADD_SUBDIRECTORY(crc)
TARGET_LINK_LIBRARIES(mariabackup sql crc)
IF(NOT HAVE_SYSTEM_REGEX)
TARGET_LINK_LIBRARIES(mariabackup pcreposix)
ENDIF()
########################################################################
# xbstream binary
########################################################################
MYSQL_ADD_EXECUTABLE(mbstream
ds_buffer.c
ds_local.c
ds_stdout.c
datasink.c
xbstream.c
xbstream_read.c
xbstream_write.c
COMPONENT backup
)
TARGET_LINK_LIBRARIES(mbstream
mysys
crc
)
IF(MSVC)
SET_TARGET_PROPERTIES(mbstream PROPERTIES LINK_FLAGS setargv.obj)
ENDIF()

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
#ifndef XTRABACKUP_BACKUP_COPY_H
#define XTRABACKUP_BACKUP_COPY_H
#include <my_global.h>
#include "datasink.h"
/* special files */
#define XTRABACKUP_SLAVE_INFO "xtrabackup_slave_info"
#define XTRABACKUP_GALERA_INFO "xtrabackup_galera_info"
#define XTRABACKUP_BINLOG_INFO "xtrabackup_binlog_info"
#define XTRABACKUP_INFO "xtrabackup_info"
extern bool binlog_locked;
bool
backup_file_printf(const char *filename, const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 2, 0);
/************************************************************************
Return true if first and second arguments are the same path. */
bool
equal_paths(const char *first, const char *second);
/************************************************************************
Copy file for backup/restore.
@return true in case of success. */
bool
copy_file(ds_ctxt_t *datasink,
const char *src_file_path,
const char *dst_file_path,
uint thread_n);
/** Start --backup */
bool backup_start();
/** Release resources after backup_start() */
void backup_release();
/** Finish after backup_start() and backup_release() */
bool backup_finish();
bool
apply_log_finish();
bool
copy_back();
bool
decrypt_decompress();
bool
is_path_separator(char);
bool
directory_exists(const char *dir, bool create);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,92 @@
#ifndef XTRABACKUP_BACKUP_MYSQL_H
#define XTRABACKUP_BACKUP_MYSQL_H
#include <mysql.h>
/* mysql flavor and version */
enum mysql_flavor_t { FLAVOR_UNKNOWN, FLAVOR_MYSQL,
FLAVOR_PERCONA_SERVER, FLAVOR_MARIADB };
extern mysql_flavor_t server_flavor;
extern unsigned long mysql_server_version;
/* server capabilities */
extern bool have_changed_page_bitmaps;
extern bool have_backup_locks;
extern bool have_lock_wait_timeout;
extern bool have_galera_enabled;
extern bool have_flush_engine_logs;
extern bool have_multi_threaded_slave;
extern bool have_gtid_slave;
/* History on server */
extern time_t history_start_time;
extern time_t history_end_time;
extern time_t history_lock_time;
extern bool sql_thread_started;
extern char *mysql_slave_position;
extern char *mysql_binlog_position;
extern char *buffer_pool_filename;
/** connection to mysql server */
extern MYSQL *mysql_connection;
void
capture_tool_command(int argc, char **argv);
bool
select_history();
bool
flush_changed_page_bitmaps();
void
backup_cleanup();
bool
get_mysql_vars(MYSQL *connection);
bool
detect_mysql_capabilities_for_backup();
MYSQL *
xb_mysql_connect();
MYSQL_RES *
xb_mysql_query(MYSQL *connection, const char *query, bool use_result,
bool die_on_error = true);
void
unlock_all(MYSQL *connection);
bool
write_current_binlog_file(MYSQL *connection);
bool
write_binlog_info(MYSQL *connection);
bool
write_xtrabackup_info(MYSQL *connection);
bool
write_backup_config_file();
bool
lock_binlog_maybe(MYSQL *connection);
bool
lock_tables(MYSQL *connection);
bool
wait_for_safe_slave(MYSQL *connection);
bool
write_galera_info(MYSQL *connection);
bool
write_slave_info(MYSQL *connection);
#endif

View file

@ -0,0 +1,32 @@
/******************************************************
Percona XtraBackup: hot backup tool for InnoDB
(c) 2009-2014 Percona LLC and/or its affiliates
Originally Created 3/3/2009 Yasufumi Kinoshita
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifndef BACKUP_WSREP_H
#define BACKUP_WSREP_H
/***********************************************************************
Store Galera checkpoint info in the 'xtrabackup_galera_info' file, if that
information is present in the trx system header. Otherwise, do nothing. */
void
xb_write_galera_info(bool incremental_prepare);
/*==================*/
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,85 @@
/******************************************************
XtraBackup: hot backup tool for InnoDB
(c) 2009-2012 Percona Inc.
Originally Created 3/3/2009 Yasufumi Kinoshita
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
/* Changed page bitmap interface */
#ifndef XB_CHANGED_PAGE_BITMAP_H
#define XB_CHANGED_PAGE_BITMAP_H
#include <ut0rbt.h>
#include <fil0fil.h>
/* The changed page bitmap structure */
typedef ib_rbt_t xb_page_bitmap;
struct xb_page_bitmap_range_struct;
/* The bitmap range iterator over one space id */
typedef struct xb_page_bitmap_range_struct xb_page_bitmap_range;
/****************************************************************//**
Read the disk bitmap and build the changed page bitmap tree for the
LSN interval incremental_lsn to checkpoint_lsn_start.
@return the built bitmap tree */
xb_page_bitmap*
xb_page_bitmap_init(void);
/*=====================*/
/****************************************************************//**
Free the bitmap tree. */
void
xb_page_bitmap_deinit(
/*==================*/
xb_page_bitmap* bitmap); /*!<in/out: bitmap tree */
/****************************************************************//**
Set up a new bitmap range iterator over a given space id changed
pages in a given bitmap.
@return bitmap range iterator */
xb_page_bitmap_range*
xb_page_bitmap_range_init(
/*======================*/
xb_page_bitmap* bitmap, /*!< in: bitmap to iterate over */
ulint space_id); /*!< in: space id */
/****************************************************************//**
Get the next page id that has its bit set or cleared, i.e. equal to
bit_value.
@return page id */
ulint
xb_page_bitmap_range_get_next_bit(
/*==============================*/
xb_page_bitmap_range* bitmap_range, /*!< in/out: bitmap range */
ibool bit_value); /*!< in: bit value */
/****************************************************************//**
Free the bitmap range iterator. */
void
xb_page_bitmap_range_deinit(
/*========================*/
xb_page_bitmap_range* bitmap_range); /*! in/out: bitmap range */
#endif

174
extra/mariabackup/common.h Normal file
View file

@ -0,0 +1,174 @@
/******************************************************
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
Common declarations for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifndef XB_COMMON_H
#define XB_COMMON_H
#include <my_global.h>
#include <mysql_version.h>
#include <fcntl.h>
#include <stdarg.h>
# define fil_is_user_tablespace_id(i) ((i) > srv_undo_tablespaces_open)
#ifdef _MSC_VER
#define stat _stati64
#define PATH_MAX MAX_PATH
#endif
#ifndef HAVE_VASPRINTF
static inline int vasprintf(char **strp, const char *fmt, va_list args)
{
int len;
#ifdef _MSC_VER
len = _vscprintf(fmt, args);
#else
len = vsnprintf(NULL, 0, fmt, args);
#endif
if (len < 0)
{
return -1;
}
*strp = (char *)malloc(len + 1);
if (!*strp)
{
return -1;
}
vsprintf(*strp, fmt, args);
return len;
}
static inline int asprintf(char **strp, const char *fmt,...)
{
va_list args;
va_start(args, fmt);
int len = vasprintf(strp, fmt, args);
va_end(args);
return len;
}
#endif
#define xb_a(expr) \
do { \
if (!(expr)) { \
msg("Assertion \"%s\" failed at %s:%lu\n", \
#expr, __FILE__, (ulong) __LINE__); \
abort(); \
} \
} while (0);
#ifdef XB_DEBUG
#define xb_ad(expr) xb_a(expr)
#else
#define xb_ad(expr)
#endif
#define XB_DELTA_INFO_SUFFIX ".meta"
static inline int msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
static inline int msg(const char *fmt, ...)
{
int result;
va_list args;
va_start(args, fmt);
result = vfprintf(stderr, fmt, args);
va_end(args);
return result;
}
static inline int msg_ts(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
static inline int msg_ts(const char *fmt, ...)
{
int result;
time_t t = time(NULL);
char date[100];
char *line;
va_list args;
strftime(date, sizeof(date), "%y%m%d %H:%M:%S", localtime(&t));
va_start(args, fmt);
result = vasprintf(&line, fmt, args);
va_end(args);
if (result != -1) {
result = fprintf(stderr, "%s %s", date, line);
free(line);
}
return result;
}
/* Use POSIX_FADV_NORMAL when available */
#ifdef POSIX_FADV_NORMAL
# define USE_POSIX_FADVISE
#else
# define POSIX_FADV_NORMAL
# define POSIX_FADV_SEQUENTIAL
# define POSIX_FADV_DONTNEED
# define posix_fadvise(a,b,c,d) do {} while(0)
#endif
/***********************************************************************
Computes bit shift for a given value. If the argument is not a power
of 2, returns 0.*/
static inline size_t
get_bit_shift(size_t value)
{
size_t shift;
if (value == 0)
return 0;
for (shift = 0; !(value & 1); shift++) {
value >>= 1;
}
return (value >> 1) ? 0 : shift;
}
/****************************************************************************
Read 'len' bytes from 'fd'. It is identical to my_read(..., MYF(MY_FULL_IO)),
i.e. tries to combine partial reads into a single block of size 'len', except
that it bails out on EOF or error, and returns the number of successfully read
bytes instead. */
static inline size_t
xb_read_full(File fd, uchar *buf, size_t len)
{
size_t tlen = 0;
size_t tbytes;
while (tlen < len) {
tbytes = my_read(fd, buf, len - tlen, MYF(MY_WME));
if (tbytes == 0 || tbytes == MY_FILE_ERROR) {
break;
}
buf += tbytes;
tlen += tbytes;
}
return tlen;
}
#endif

View file

@ -1,28 +1,33 @@
#! /bin/sh
# Copyright (C) 2000 MySQL AB
# Use is subject to license terms
# Copyright (c) 2017 Percona LLC and/or its affiliates.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
path=`dirname $0`
. "$path/SETUP.sh"
PROJECT(crc C)
extra_flags="$pentium_cflags $fast_cflags"
extra_configs="$pentium_configs --without-server"
make=no
strip=yes
. "$path/FINISH.sh"
IF(NOT CMAKE_CROSSCOMPILING AND NOT MSVC)
STRING(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} processor)
IF(processor MATCHES "86" OR processor MATCHES "amd64" OR processor MATCHES "x64")
# Check for PCLMUL instruction
CHECK_C_SOURCE_RUNS("
int main()
{
asm volatile (\"pclmulqdq \\$0x00, %%xmm1, %%xmm0\":::\"cc\");
return 0;
}" HAVE_CLMUL_INSTRUCTION)
ENDIF()
ENDIF()
IF(HAVE_CLMUL_INSTRUCTION)
ADD_DEFINITIONS(-DHAVE_CLMUL_INSTRUCTION)
ENDIF()
ADD_LIBRARY(crc STATIC crc_glue.c crc-intel-pclmul.c)

View file

@ -0,0 +1,21 @@
/******************************************************
Copyright (c) 2017 Percona LLC and/or its affiliates.
Zlib compatible CRC-32 implementation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#cmakedefine HAVE_CLMUL_INSTRUCTION 1

View file

@ -0,0 +1,511 @@
/******************************************************
Copyright (c) 2017 Percona LLC and/or its affiliates.
CRC32 using Intel's PCLMUL instruction.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
/* crc-intel-pclmul.c - Intel PCLMUL accelerated CRC implementation
* Copyright (C) 2016 Jussi Kivilinna <jussi.kivilinna@iki.fi>
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
# define U64_C(c) (c ## UL)
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint64_t u64;
#ifndef byte
typedef uint8_t byte;
#endif
# define _gcry_bswap32 __builtin_bswap32
#if __GNUC__ >= 4 && defined(__x86_64__) && defined(HAVE_CLMUL_INSTRUCTION)
#if _GCRY_GCC_VERSION >= 40400 /* 4.4 */
/* Prevent compiler from issuing SSE instructions between asm blocks. */
# pragma GCC target("no-sse")
#endif
#define ALIGNED_16 __attribute__ ((aligned (16)))
struct u16_unaligned_s
{
u16 a;
} __attribute__((packed, aligned (1), may_alias));
/* Constants structure for generic reflected/non-reflected CRC32 CLMUL
* functions. */
struct crc32_consts_s
{
/* k: { x^(32*17), x^(32*15), x^(32*5), x^(32*3), x^(32*2), 0 } mod P(x) */
u64 k[6];
/* my_p: { floor(x^64 / P(x)), P(x) } */
u64 my_p[2];
};
/* CLMUL constants for CRC32 and CRC32RFC1510. */
static const struct crc32_consts_s crc32_consts ALIGNED_16 =
{
{ /* k[6] = reverse_33bits( x^(32*y) mod P(x) ) */
U64_C(0x154442bd4), U64_C(0x1c6e41596), /* y = { 17, 15 } */
U64_C(0x1751997d0), U64_C(0x0ccaa009e), /* y = { 5, 3 } */
U64_C(0x163cd6124), 0 /* y = 2 */
},
{ /* my_p[2] = reverse_33bits ( { floor(x^64 / P(x)), P(x) } ) */
U64_C(0x1f7011641), U64_C(0x1db710641)
}
};
/* Common constants for CRC32 algorithms. */
static const byte crc32_refl_shuf_shift[3 * 16] ALIGNED_16 =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
static const byte crc32_partial_fold_input_mask[16 + 16] ALIGNED_16 =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
static const u64 crc32_merge9to15_shuf[15 - 9 + 1][2] ALIGNED_16 =
{
{ U64_C(0x0706050403020100), U64_C(0xffffffffffffff0f) }, /* 9 */
{ U64_C(0x0706050403020100), U64_C(0xffffffffffff0f0e) },
{ U64_C(0x0706050403020100), U64_C(0xffffffffff0f0e0d) },
{ U64_C(0x0706050403020100), U64_C(0xffffffff0f0e0d0c) },
{ U64_C(0x0706050403020100), U64_C(0xffffff0f0e0d0c0b) },
{ U64_C(0x0706050403020100), U64_C(0xffff0f0e0d0c0b0a) },
{ U64_C(0x0706050403020100), U64_C(0xff0f0e0d0c0b0a09) }, /* 15 */
};
static const u64 crc32_merge5to7_shuf[7 - 5 + 1][2] ALIGNED_16 =
{
{ U64_C(0xffffff0703020100), U64_C(0xffffffffffffffff) }, /* 5 */
{ U64_C(0xffff070603020100), U64_C(0xffffffffffffffff) },
{ U64_C(0xff07060503020100), U64_C(0xffffffffffffffff) }, /* 7 */
};
/* PCLMUL functions for reflected CRC32. */
static inline void
crc32_reflected_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
const struct crc32_consts_s *consts)
{
if (inlen >= 8 * 16)
{
asm volatile ("movd %[crc], %%xmm4\n\t"
"movdqu %[inbuf_0], %%xmm0\n\t"
"movdqu %[inbuf_1], %%xmm1\n\t"
"movdqu %[inbuf_2], %%xmm2\n\t"
"movdqu %[inbuf_3], %%xmm3\n\t"
"pxor %%xmm4, %%xmm0\n\t"
:
: [inbuf_0] "m" (inbuf[0 * 16]),
[inbuf_1] "m" (inbuf[1 * 16]),
[inbuf_2] "m" (inbuf[2 * 16]),
[inbuf_3] "m" (inbuf[3 * 16]),
[crc] "m" (*pcrc)
);
inbuf += 4 * 16;
inlen -= 4 * 16;
asm volatile ("movdqa %[k1k2], %%xmm4\n\t"
:
: [k1k2] "m" (consts->k[1 - 1])
);
/* Fold by 4. */
while (inlen >= 4 * 16)
{
asm volatile ("movdqu %[inbuf_0], %%xmm5\n\t"
"movdqa %%xmm0, %%xmm6\n\t"
"pclmulqdq $0x00, %%xmm4, %%xmm0\n\t"
"pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
"pxor %%xmm5, %%xmm0\n\t"
"pxor %%xmm6, %%xmm0\n\t"
"movdqu %[inbuf_1], %%xmm5\n\t"
"movdqa %%xmm1, %%xmm6\n\t"
"pclmulqdq $0x00, %%xmm4, %%xmm1\n\t"
"pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
"pxor %%xmm5, %%xmm1\n\t"
"pxor %%xmm6, %%xmm1\n\t"
"movdqu %[inbuf_2], %%xmm5\n\t"
"movdqa %%xmm2, %%xmm6\n\t"
"pclmulqdq $0x00, %%xmm4, %%xmm2\n\t"
"pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
"pxor %%xmm5, %%xmm2\n\t"
"pxor %%xmm6, %%xmm2\n\t"
"movdqu %[inbuf_3], %%xmm5\n\t"
"movdqa %%xmm3, %%xmm6\n\t"
"pclmulqdq $0x00, %%xmm4, %%xmm3\n\t"
"pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
"pxor %%xmm5, %%xmm3\n\t"
"pxor %%xmm6, %%xmm3\n\t"
:
: [inbuf_0] "m" (inbuf[0 * 16]),
[inbuf_1] "m" (inbuf[1 * 16]),
[inbuf_2] "m" (inbuf[2 * 16]),
[inbuf_3] "m" (inbuf[3 * 16])
);
inbuf += 4 * 16;
inlen -= 4 * 16;
}
asm volatile ("movdqa %[k3k4], %%xmm6\n\t"
"movdqa %[my_p], %%xmm5\n\t"
:
: [k3k4] "m" (consts->k[3 - 1]),
[my_p] "m" (consts->my_p[0])
);
/* Fold 4 to 1. */
asm volatile ("movdqa %%xmm0, %%xmm4\n\t"
"pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
"pclmulqdq $0x11, %%xmm6, %%xmm4\n\t"
"pxor %%xmm1, %%xmm0\n\t"
"pxor %%xmm4, %%xmm0\n\t"
"movdqa %%xmm0, %%xmm4\n\t"
"pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
"pclmulqdq $0x11, %%xmm6, %%xmm4\n\t"
"pxor %%xmm2, %%xmm0\n\t"
"pxor %%xmm4, %%xmm0\n\t"
"movdqa %%xmm0, %%xmm4\n\t"
"pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
"pclmulqdq $0x11, %%xmm6, %%xmm4\n\t"
"pxor %%xmm3, %%xmm0\n\t"
"pxor %%xmm4, %%xmm0\n\t"
:
:
);
}
else
{
asm volatile ("movd %[crc], %%xmm1\n\t"
"movdqu %[inbuf], %%xmm0\n\t"
"movdqa %[k3k4], %%xmm6\n\t"
"pxor %%xmm1, %%xmm0\n\t"
"movdqa %[my_p], %%xmm5\n\t"
:
: [inbuf] "m" (*inbuf),
[crc] "m" (*pcrc),
[k3k4] "m" (consts->k[3 - 1]),
[my_p] "m" (consts->my_p[0])
);
inbuf += 16;
inlen -= 16;
}
/* Fold by 1. */
if (inlen >= 16)
{
while (inlen >= 16)
{
/* Load next block to XMM2. Fold XMM0 to XMM0:XMM1. */
asm volatile ("movdqu %[inbuf], %%xmm2\n\t"
"movdqa %%xmm0, %%xmm1\n\t"
"pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
"pclmulqdq $0x11, %%xmm6, %%xmm1\n\t"
"pxor %%xmm2, %%xmm0\n\t"
"pxor %%xmm1, %%xmm0\n\t"
:
: [inbuf] "m" (*inbuf)
);
inbuf += 16;
inlen -= 16;
}
}
/* Partial fold. */
if (inlen)
{
/* Load last input and add padding zeros. */
asm volatile ("movdqu %[shr_shuf], %%xmm3\n\t"
"movdqu %[shl_shuf], %%xmm4\n\t"
"movdqu %[mask], %%xmm2\n\t"
"movdqa %%xmm0, %%xmm1\n\t"
"pshufb %%xmm4, %%xmm0\n\t"
"movdqu %[inbuf], %%xmm4\n\t"
"pshufb %%xmm3, %%xmm1\n\t"
"pand %%xmm4, %%xmm2\n\t"
"por %%xmm1, %%xmm2\n\t"
"movdqa %%xmm0, %%xmm1\n\t"
"pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
"pclmulqdq $0x11, %%xmm6, %%xmm1\n\t"
"pxor %%xmm2, %%xmm0\n\t"
"pxor %%xmm1, %%xmm0\n\t"
:
: [inbuf] "m" (*(inbuf - 16 + inlen)),
[mask] "m" (crc32_partial_fold_input_mask[inlen]),
[shl_shuf] "m" (crc32_refl_shuf_shift[inlen]),
[shr_shuf] "m" (crc32_refl_shuf_shift[inlen + 16])
);
inbuf += inlen;
inlen -= inlen;
}
/* Final fold. */
asm volatile (/* reduce 128-bits to 96-bits */
"movdqa %%xmm0, %%xmm1\n\t"
"pclmulqdq $0x10, %%xmm6, %%xmm0\n\t"
"psrldq $8, %%xmm1\n\t"
"pxor %%xmm1, %%xmm0\n\t"
/* reduce 96-bits to 64-bits */
"pshufd $0xfc, %%xmm0, %%xmm1\n\t" /* [00][00][00][x] */
"pshufd $0xf9, %%xmm0, %%xmm0\n\t" /* [00][00][x>>64][x>>32] */
"pclmulqdq $0x00, %[k5], %%xmm1\n\t" /* [00][00][xx][xx] */
"pxor %%xmm1, %%xmm0\n\t" /* top 64-bit are zero */
/* barrett reduction */
"pshufd $0xf3, %%xmm0, %%xmm1\n\t" /* [00][00][x>>32][00] */
"pslldq $4, %%xmm0\n\t" /* [??][x>>32][??][??] */
"pclmulqdq $0x00, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
"pclmulqdq $0x10, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
"pxor %%xmm1, %%xmm0\n\t"
/* store CRC */
"pextrd $2, %%xmm0, %[out]\n\t"
: [out] "=m" (*pcrc)
: [k5] "m" (consts->k[5 - 1])
);
}
static inline void
crc32_reflected_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
const struct crc32_consts_s *consts)
{
if (inlen < 4)
{
u32 crc = *pcrc;
u32 data;
asm volatile ("movdqa %[my_p], %%xmm5\n\t"
:
: [my_p] "m" (consts->my_p[0])
);
if (inlen == 1)
{
data = inbuf[0];
data ^= crc;
data <<= 24;
crc >>= 8;
}
else if (inlen == 2)
{
data = ((const struct u16_unaligned_s *)inbuf)->a;
data ^= crc;
data <<= 16;
crc >>= 16;
}
else
{
data = ((const struct u16_unaligned_s *)inbuf)->a;
data |= inbuf[2] << 16;
data ^= crc;
data <<= 8;
crc >>= 24;
}
/* Barrett reduction */
asm volatile ("movd %[in], %%xmm0\n\t"
"movd %[crc], %%xmm1\n\t"
"pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
"psllq $32, %%xmm1\n\t"
"pshufd $0xfc, %%xmm0, %%xmm0\n\t" /* [00][00][00][x] */
"pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
"pxor %%xmm1, %%xmm0\n\t"
"pextrd $1, %%xmm0, %[out]\n\t"
: [out] "=m" (*pcrc)
: [in] "rm" (data),
[crc] "rm" (crc)
);
}
else if (inlen == 4)
{
/* Barrett reduction */
asm volatile ("movd %[crc], %%xmm1\n\t"
"movd %[in], %%xmm0\n\t"
"movdqa %[my_p], %%xmm5\n\t"
"pxor %%xmm1, %%xmm0\n\t"
"pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
"pshufd $0xfc, %%xmm0, %%xmm0\n\t" /* [00][00][00][x] */
"pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
"pextrd $1, %%xmm0, %[out]\n\t"
: [out] "=m" (*pcrc)
: [in] "m" (*inbuf),
[crc] "m" (*pcrc),
[my_p] "m" (consts->my_p[0])
);
}
else
{
asm volatile ("movdqu %[shuf], %%xmm4\n\t"
"movd %[crc], %%xmm1\n\t"
"movdqa %[my_p], %%xmm5\n\t"
"movdqa %[k3k4], %%xmm6\n\t"
:
: [shuf] "m" (crc32_refl_shuf_shift[inlen]),
[crc] "m" (*pcrc),
[my_p] "m" (consts->my_p[0]),
[k3k4] "m" (consts->k[3 - 1])
);
if (inlen >= 8)
{
asm volatile ("movq %[inbuf], %%xmm0\n\t"
:
: [inbuf] "m" (*inbuf)
);
if (inlen > 8)
{
asm volatile (/*"pinsrq $1, %[inbuf_tail], %%xmm0\n\t"*/
"movq %[inbuf_tail], %%xmm2\n\t"
"punpcklqdq %%xmm2, %%xmm0\n\t"
"pshufb %[merge_shuf], %%xmm0\n\t"
:
: [inbuf_tail] "m" (inbuf[inlen - 8]),
[merge_shuf] "m"
(*crc32_merge9to15_shuf[inlen - 9])
);
}
}
else
{
asm volatile ("movd %[inbuf], %%xmm0\n\t"
"pinsrd $1, %[inbuf_tail], %%xmm0\n\t"
"pshufb %[merge_shuf], %%xmm0\n\t"
:
: [inbuf] "m" (*inbuf),
[inbuf_tail] "m" (inbuf[inlen - 4]),
[merge_shuf] "m"
(*crc32_merge5to7_shuf[inlen - 5])
);
}
/* Final fold. */
asm volatile ("pxor %%xmm1, %%xmm0\n\t"
"pshufb %%xmm4, %%xmm0\n\t"
/* reduce 128-bits to 96-bits */
"movdqa %%xmm0, %%xmm1\n\t"
"pclmulqdq $0x10, %%xmm6, %%xmm0\n\t"
"psrldq $8, %%xmm1\n\t"
"pxor %%xmm1, %%xmm0\n\t" /* top 32-bit are zero */
/* reduce 96-bits to 64-bits */
"pshufd $0xfc, %%xmm0, %%xmm1\n\t" /* [00][00][00][x] */
"pshufd $0xf9, %%xmm0, %%xmm0\n\t" /* [00][00][x>>64][x>>32] */
"pclmulqdq $0x00, %[k5], %%xmm1\n\t" /* [00][00][xx][xx] */
"pxor %%xmm1, %%xmm0\n\t" /* top 64-bit are zero */
/* barrett reduction */
"pshufd $0xf3, %%xmm0, %%xmm1\n\t" /* [00][00][x>>32][00] */
"pslldq $4, %%xmm0\n\t" /* [??][x>>32][??][??] */
"pclmulqdq $0x00, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
"pclmulqdq $0x10, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
"pxor %%xmm1, %%xmm0\n\t"
/* store CRC */
"pextrd $2, %%xmm0, %[out]\n\t"
: [out] "=m" (*pcrc)
: [k5] "m" (consts->k[5 - 1])
);
}
}
void
crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen)
{
const struct crc32_consts_s *consts = &crc32_consts;
#if defined(__x86_64__) && defined(__WIN64__)
char win64tmp[2 * 16];
/* XMM6-XMM7 need to be restored after use. */
asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t"
"movdqu %%xmm7, 1*16(%0)\n\t"
:
: "r" (win64tmp)
: "memory");
#endif
if (!inlen)
return;
if (inlen >= 16)
crc32_reflected_bulk(pcrc, inbuf, inlen, consts);
else
crc32_reflected_less_than_16(pcrc, inbuf, inlen, consts);
#if defined(__x86_64__) && defined(__WIN64__)
/* Restore used registers. */
asm volatile("movdqu 0*16(%0), %%xmm6\n\t"
"movdqu 1*16(%0), %%xmm7\n\t"
:
: "r" (win64tmp)
: "memory");
#endif
}
#endif

View file

@ -0,0 +1,25 @@
/******************************************************
Copyright (c) 2017 Percona LLC and/or its affiliates.
CRC32 using Intel's PCLMUL instruction.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#include <stdint.h>
#include <stddef.h>
void
crc32_intel_pclmul(uint32_t *pcrc, const uint8_t *inbuf, size_t inlen);

View file

@ -0,0 +1,72 @@
/******************************************************
Copyright (c) 2017 Percona LLC and/or its affiliates.
Zlib compatible CRC-32 implementation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#include "my_config.h"
#include "crc_glue.h"
#include "crc-intel-pclmul.h"
#include <stdint.h>
#include <string.h>
#include <zlib.h>
#if __GNUC__ >= 4 && defined(__x86_64__)
static int pclmul_enabled = 0;
#endif
#if defined(__GNUC__) && defined(__x86_64__)
static
uint32_t
cpuid(uint32_t* ecx, uint32_t* edx)
{
uint32_t level;
asm("cpuid" : "=a" (level) : "a" (0) : "ebx", "ecx", "edx");
if (level < 1) {
return level;
}
asm("cpuid" : "=c" (*ecx), "=d" (*edx)
: "a" (1)
: "ebx");
return level;
}
#endif
void crc_init() {
#if defined(__GNUC__) && defined(__x86_64__)
uint32_t ecx, edx;
if (cpuid(&ecx, &edx) > 0) {
pclmul_enabled = ((ecx >> 19) & 1) && ((ecx >> 1) & 1);
}
#endif
}
unsigned long crc32_iso3309(unsigned long crc, const unsigned char *buf, unsigned int len)
{
#if __GNUC__ >= 4 && defined(__x86_64__) && defined(HAVE_CLMUL_INSTRUCTION)
if (pclmul_enabled) {
uint32_t crc_accum = crc ^ 0xffffffffL;
crc32_intel_pclmul(&crc_accum, buf, len);
return crc_accum ^ 0xffffffffL;
}
#endif
return crc32(crc, buf, len);
}

View file

@ -0,0 +1,31 @@
/******************************************************
Copyright (c) 2017 Percona LLC and/or its affiliates.
Zlib compatible CRC-32 implementation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifdef __cplusplus
extern "C" {
#endif
void crc_init();
unsigned long crc32_iso3309(unsigned long crc, const unsigned char *buf, unsigned int len);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,137 @@
/******************************************************
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
Data sink interface.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#include <my_base.h>
#include "common.h"
#include "datasink.h"
#include "ds_compress.h"
#include "ds_archive.h"
#include "ds_xbstream.h"
#include "ds_local.h"
#include "ds_stdout.h"
#include "ds_tmpfile.h"
#include "ds_buffer.h"
/************************************************************************
Create a datasink of the specified type */
ds_ctxt_t *
ds_create(const char *root, ds_type_t type)
{
datasink_t *ds;
ds_ctxt_t *ctxt;
switch (type) {
case DS_TYPE_STDOUT:
ds = &datasink_stdout;
break;
case DS_TYPE_LOCAL:
ds = &datasink_local;
break;
case DS_TYPE_ARCHIVE:
#ifdef HAVE_LIBARCHIVE
ds = &datasink_archive;
#else
msg("Error : mariabackup was built without libarchive support");
exit(EXIT_FAILURE);
#endif
break;
case DS_TYPE_XBSTREAM:
ds = &datasink_xbstream;
break;
case DS_TYPE_COMPRESS:
ds = &datasink_compress;
break;
case DS_TYPE_ENCRYPT:
case DS_TYPE_DECRYPT:
msg("Error : mariabackup does not support encrypted backups.");
exit(EXIT_FAILURE);
break;
case DS_TYPE_TMPFILE:
ds = &datasink_tmpfile;
break;
case DS_TYPE_BUFFER:
ds = &datasink_buffer;
break;
default:
msg("Unknown datasink type: %d\n", type);
xb_ad(0);
return NULL;
}
ctxt = ds->init(root);
if (ctxt != NULL) {
ctxt->datasink = ds;
} else {
msg("Error: failed to initialize datasink.\n");
exit(EXIT_FAILURE);
}
return ctxt;
}
/************************************************************************
Open a datasink file */
ds_file_t *
ds_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat)
{
ds_file_t *file;
file = ctxt->datasink->open(ctxt, path, stat);
if (file != NULL) {
file->datasink = ctxt->datasink;
}
return file;
}
/************************************************************************
Write to a datasink file.
@return 0 on success, 1 on error. */
int
ds_write(ds_file_t *file, const void *buf, size_t len)
{
return file->datasink->write(file, buf, len);
}
/************************************************************************
Close a datasink file.
@return 0 on success, 1, on error. */
int
ds_close(ds_file_t *file)
{
return file->datasink->close(file);
}
/************************************************************************
Destroy a datasink handle */
void
ds_destroy(ds_ctxt_t *ctxt)
{
ctxt->datasink->deinit(ctxt);
}
/************************************************************************
Set the destination pipe for a datasink (only makes sense for compress and
tmpfile). */
void ds_set_pipe(ds_ctxt_t *ctxt, ds_ctxt_t *pipe_ctxt)
{
ctxt->pipe_ctxt = pipe_ctxt;
}

View file

@ -0,0 +1,100 @@
/******************************************************
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
Data sink interface.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifndef XB_DATASINK_H
#define XB_DATASINK_H
#include <my_global.h>
#include <my_dir.h>
#ifdef __cplusplus
extern "C" {
#endif
extern char *xtrabackup_tmpdir;
struct datasink_struct;
typedef struct datasink_struct datasink_t;
typedef struct ds_ctxt {
datasink_t *datasink;
char *root;
void *ptr;
struct ds_ctxt *pipe_ctxt;
} ds_ctxt_t;
typedef struct {
void *ptr;
char *path;
datasink_t *datasink;
} ds_file_t;
struct datasink_struct {
ds_ctxt_t *(*init)(const char *root);
ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
int (*write)(ds_file_t *file, const void *buf, size_t len);
int (*close)(ds_file_t *file);
void (*deinit)(ds_ctxt_t *ctxt);
};
/* Supported datasink types */
typedef enum {
DS_TYPE_STDOUT,
DS_TYPE_LOCAL,
DS_TYPE_ARCHIVE,
DS_TYPE_XBSTREAM,
DS_TYPE_COMPRESS,
DS_TYPE_ENCRYPT,
DS_TYPE_DECRYPT,
DS_TYPE_TMPFILE,
DS_TYPE_BUFFER
} ds_type_t;
/************************************************************************
Create a datasink of the specified type */
ds_ctxt_t *ds_create(const char *root, ds_type_t type);
/************************************************************************
Open a datasink file */
ds_file_t *ds_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
/************************************************************************
Write to a datasink file.
@return 0 on success, 1 on error. */
int ds_write(ds_file_t *file, const void *buf, size_t len);
/************************************************************************
Close a datasink file.
@return 0 on success, 1, on error. */
int ds_close(ds_file_t *file);
/************************************************************************
Destroy a datasink handle */
void ds_destroy(ds_ctxt_t *ctxt);
/************************************************************************
Set the destination pipe for a datasink (only makes sense for compress and
tmpfile). */
void ds_set_pipe(ds_ctxt_t *ctxt, ds_ctxt_t *pipe_ctxt);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* XB_DATASINK_H */

View file

@ -0,0 +1,280 @@
/******************************************************
Copyright (c) 2013 Percona LLC and/or its affiliates.
Streaming implementation for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#include <my_base.h>
#include <archive.h>
#include <archive_entry.h>
#include "common.h"
#include "datasink.h"
#if ARCHIVE_VERSION_NUMBER < 3000000
#define archive_write_add_filter_none(X) archive_write_set_compression_none(X)
#define archive_write_free(X) archive_write_finish(X)
#endif
typedef struct {
struct archive *archive;
ds_file_t *dest_file;
pthread_mutex_t mutex;
} ds_archive_ctxt_t;
typedef struct {
struct archive_entry *entry;
ds_archive_ctxt_t *archive_ctxt;
} ds_archive_file_t;
/***********************************************************************
General archive interface */
static ds_ctxt_t *archive_init(const char *root);
static ds_file_t *archive_open(ds_ctxt_t *ctxt, const char *path,
MY_STAT *mystat);
static int archive_write(ds_file_t *file, const void *buf, size_t len);
static int archive_close(ds_file_t *file);
static void archive_deinit(ds_ctxt_t *ctxt);
datasink_t datasink_archive = {
&archive_init,
&archive_open,
&archive_write,
&archive_close,
&archive_deinit
};
static
int
my_archive_open_callback(struct archive *a __attribute__((unused)),
void *data __attribute__((unused)))
{
return ARCHIVE_OK;
}
static
ssize_t
my_archive_write_callback(struct archive *a __attribute__((unused)),
void *data, const void *buffer, size_t length)
{
ds_archive_ctxt_t *archive_ctxt;
archive_ctxt = (ds_archive_ctxt_t *) data;
xb_ad(archive_ctxt != NULL);
xb_ad(archive_ctxt->dest_file != NULL);
if (!ds_write(archive_ctxt->dest_file, buffer, length)) {
return length;
}
return -1;
}
static
int
my_archive_close_callback(struct archive *a __attribute__((unused)),
void *data __attribute__((unused)))
{
return ARCHIVE_OK;
}
static
ds_ctxt_t *
archive_init(const char *root __attribute__((unused)))
{
ds_ctxt_t *ctxt;
ds_archive_ctxt_t *archive_ctxt;
struct archive *a;
ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_archive_ctxt_t),
MYF(MY_FAE));
archive_ctxt = (ds_archive_ctxt_t *)(ctxt + 1);
if (pthread_mutex_init(&archive_ctxt->mutex, NULL)) {
msg("archive_init: pthread_mutex_init() failed.\n");
goto err;
}
a = archive_write_new();
if (a == NULL) {
msg("archive_write_new() failed.\n");
goto err;
}
archive_ctxt->archive = a;
archive_ctxt->dest_file = NULL;
if(archive_write_add_filter_none(a) != ARCHIVE_OK ||
archive_write_set_format_pax_restricted(a) != ARCHIVE_OK ||
/* disable internal buffering so we don't have to flush the
output in xtrabackup */
archive_write_set_bytes_per_block(a, 0) != ARCHIVE_OK) {
msg("failed to set libarchive archive options: %s\n",
archive_error_string(a));
archive_write_free(a);
goto err;
}
if (archive_write_open(a, archive_ctxt, my_archive_open_callback,
my_archive_write_callback,
my_archive_close_callback) != ARCHIVE_OK) {
msg("cannot open output archive.\n");
return NULL;
}
ctxt->ptr = archive_ctxt;
return ctxt;
err:
my_free(ctxt);
return NULL;
}
static
ds_file_t *
archive_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
{
ds_archive_ctxt_t *archive_ctxt;
ds_ctxt_t *dest_ctxt;
ds_file_t *file;
ds_archive_file_t *archive_file;
struct archive *a;
struct archive_entry *entry;
xb_ad(ctxt->pipe_ctxt != NULL);
dest_ctxt = ctxt->pipe_ctxt;
archive_ctxt = (ds_archive_ctxt_t *) ctxt->ptr;
pthread_mutex_lock(&archive_ctxt->mutex);
if (archive_ctxt->dest_file == NULL) {
archive_ctxt->dest_file = ds_open(dest_ctxt, path, mystat);
if (archive_ctxt->dest_file == NULL) {
return NULL;
}
}
pthread_mutex_unlock(&archive_ctxt->mutex);
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
sizeof(ds_archive_file_t),
MYF(MY_FAE));
archive_file = (ds_archive_file_t *) (file + 1);
a = archive_ctxt->archive;
entry = archive_entry_new();
if (entry == NULL) {
msg("archive_entry_new() failed.\n");
goto err;
}
archive_entry_set_size(entry, mystat->st_size);
archive_entry_set_mode(entry, 0660);
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_pathname(entry, path);
archive_entry_set_mtime(entry, mystat->st_mtime, 0);
archive_file->entry = entry;
archive_file->archive_ctxt = archive_ctxt;
if (archive_write_header(a, entry) != ARCHIVE_OK) {
msg("archive_write_header() failed.\n");
archive_entry_free(entry);
goto err;
}
file->ptr = archive_file;
file->path = archive_ctxt->dest_file->path;
return file;
err:
if (archive_ctxt->dest_file) {
ds_close(archive_ctxt->dest_file);
archive_ctxt->dest_file = NULL;
}
my_free(file);
return NULL;
}
static
int
archive_write(ds_file_t *file, const void *buf, size_t len)
{
ds_archive_file_t *archive_file;
struct archive *a;
archive_file = (ds_archive_file_t *) file->ptr;
a = archive_file->archive_ctxt->archive;
xb_ad(archive_file->archive_ctxt->dest_file != NULL);
if (archive_write_data(a, buf, len) < 0) {
msg("archive_write_data() failed: %s (errno = %d)\n",
archive_error_string(a), archive_errno(a));
return 1;
}
return 0;
}
static
int
archive_close(ds_file_t *file)
{
ds_archive_file_t *archive_file;
int rc = 0;
archive_file = (ds_archive_file_t *)file->ptr;
archive_entry_free(archive_file->entry);
my_free(file);
return rc;
}
static
void
archive_deinit(ds_ctxt_t *ctxt)
{
struct archive *a;
ds_archive_ctxt_t *archive_ctxt;
archive_ctxt = (ds_archive_ctxt_t *) ctxt->ptr;
a = archive_ctxt->archive;
if (archive_write_close(a) != ARCHIVE_OK) {
msg("archive_write_close() failed.\n");
}
archive_write_free(a);
if (archive_ctxt->dest_file) {
ds_close(archive_ctxt->dest_file);
archive_ctxt->dest_file = NULL;
}
pthread_mutex_destroy(&archive_ctxt->mutex);
my_free(ctxt);
}

View file

@ -0,0 +1,28 @@
/******************************************************
Copyright (c) 2013 Percona LLC and/or its affiliates.
Streaming interface for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifndef DS_ARCHIVE_H
#define DS_ARCHIVE_H
#include "datasink.h"
extern datasink_t datasink_archive;
#endif

View file

@ -0,0 +1,189 @@
/******************************************************
Copyright (c) 2012-2013 Percona LLC and/or its affiliates.
buffer datasink for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
/* Does buffered output to a destination datasink set with ds_set_pipe().
Writes to the destination datasink are guaranteed to not be smaller than a
specified buffer size (DS_DEFAULT_BUFFER_SIZE by default), with the only
exception for the last write for a file. */
#include <mysql_version.h>
#include <my_base.h>
#include "ds_buffer.h"
#include "common.h"
#include "datasink.h"
#define DS_DEFAULT_BUFFER_SIZE (64 * 1024)
typedef struct {
ds_file_t *dst_file;
char *buf;
size_t pos;
size_t size;
} ds_buffer_file_t;
typedef struct {
size_t buffer_size;
} ds_buffer_ctxt_t;
static ds_ctxt_t *buffer_init(const char *root);
static ds_file_t *buffer_open(ds_ctxt_t *ctxt, const char *path,
MY_STAT *mystat);
static int buffer_write(ds_file_t *file, const void *buf, size_t len);
static int buffer_close(ds_file_t *file);
static void buffer_deinit(ds_ctxt_t *ctxt);
datasink_t datasink_buffer = {
&buffer_init,
&buffer_open,
&buffer_write,
&buffer_close,
&buffer_deinit
};
/* Change the default buffer size */
void ds_buffer_set_size(ds_ctxt_t *ctxt, size_t size)
{
ds_buffer_ctxt_t *buffer_ctxt = (ds_buffer_ctxt_t *) ctxt->ptr;
buffer_ctxt->buffer_size = size;
}
static ds_ctxt_t *
buffer_init(const char *root)
{
ds_ctxt_t *ctxt;
ds_buffer_ctxt_t *buffer_ctxt;
ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_buffer_ctxt_t),
MYF(MY_FAE));
buffer_ctxt = (ds_buffer_ctxt_t *) (ctxt + 1);
buffer_ctxt->buffer_size = DS_DEFAULT_BUFFER_SIZE;
ctxt->ptr = buffer_ctxt;
ctxt->root = my_strdup(root, MYF(MY_FAE));
return ctxt;
}
static ds_file_t *
buffer_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
{
ds_buffer_ctxt_t *buffer_ctxt;
ds_ctxt_t *pipe_ctxt;
ds_file_t *dst_file;
ds_file_t *file;
ds_buffer_file_t *buffer_file;
pipe_ctxt = ctxt->pipe_ctxt;
xb_a(pipe_ctxt != NULL);
dst_file = ds_open(pipe_ctxt, path, mystat);
if (dst_file == NULL) {
exit(EXIT_FAILURE);
}
buffer_ctxt = (ds_buffer_ctxt_t *) ctxt->ptr;
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
sizeof(ds_buffer_file_t) +
buffer_ctxt->buffer_size,
MYF(MY_FAE));
buffer_file = (ds_buffer_file_t *) (file + 1);
buffer_file->dst_file = dst_file;
buffer_file->buf = (char *) (buffer_file + 1);
buffer_file->size = buffer_ctxt->buffer_size;
buffer_file->pos = 0;
file->path = dst_file->path;
file->ptr = buffer_file;
return file;
}
static int
buffer_write(ds_file_t *file, const void *buf, size_t len)
{
ds_buffer_file_t *buffer_file;
buffer_file = (ds_buffer_file_t *) file->ptr;
while (len > 0) {
if (buffer_file->pos + len > buffer_file->size) {
if (buffer_file->pos > 0) {
size_t bytes;
bytes = buffer_file->size - buffer_file->pos;
memcpy(buffer_file->buf + buffer_file->pos, buf,
bytes);
if (ds_write(buffer_file->dst_file,
buffer_file->buf,
buffer_file->size)) {
return 1;
}
buffer_file->pos = 0;
buf = (const char *) buf + bytes;
len -= bytes;
} else {
/* We don't have any buffered bytes, just write
the entire source buffer */
if (ds_write(buffer_file->dst_file, buf, len)) {
return 1;
}
break;
}
} else {
memcpy(buffer_file->buf + buffer_file->pos, buf, len);
buffer_file->pos += len;
break;
}
}
return 0;
}
static int
buffer_close(ds_file_t *file)
{
ds_buffer_file_t *buffer_file;
int ret;
buffer_file = (ds_buffer_file_t *) file->ptr;
if (buffer_file->pos > 0) {
ds_write(buffer_file->dst_file, buffer_file->buf,
buffer_file->pos);
}
ret = ds_close(buffer_file->dst_file);
my_free(file);
return ret;
}
static void
buffer_deinit(ds_ctxt_t *ctxt)
{
my_free(ctxt->root);
my_free(ctxt);
}

View file

@ -0,0 +1,39 @@
/******************************************************
Copyright (c) 2012-2013 Percona LLC and/or its affiliates.
buffer datasink for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifndef DS_BUFFER_H
#define DS_BUFFER_H
#include "datasink.h"
#ifdef __cplusplus
extern "C" {
#endif
extern datasink_t datasink_buffer;
/* Change the default buffer size */
void ds_buffer_set_size(ds_ctxt_t *ctxt, size_t size);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,462 @@
/******************************************************
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
Compressing datasink implementation for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#include <mysql_version.h>
#include <my_base.h>
#include <quicklz.h>
#include <zlib.h>
#include "common.h"
#include "datasink.h"
#define COMPRESS_CHUNK_SIZE ((size_t) (xtrabackup_compress_chunk_size))
#define MY_QLZ_COMPRESS_OVERHEAD 400
typedef struct {
pthread_t id;
uint num;
pthread_mutex_t ctrl_mutex;
pthread_cond_t ctrl_cond;
pthread_mutex_t data_mutex;
pthread_cond_t data_cond;
my_bool started;
my_bool data_avail;
my_bool cancelled;
const char *from;
size_t from_len;
char *to;
size_t to_len;
qlz_state_compress state;
ulong adler;
} comp_thread_ctxt_t;
typedef struct {
comp_thread_ctxt_t *threads;
uint nthreads;
} ds_compress_ctxt_t;
typedef struct {
ds_file_t *dest_file;
ds_compress_ctxt_t *comp_ctxt;
size_t bytes_processed;
} ds_compress_file_t;
/* Compression options */
extern char *xtrabackup_compress_alg;
extern uint xtrabackup_compress_threads;
extern ulonglong xtrabackup_compress_chunk_size;
static ds_ctxt_t *compress_init(const char *root);
static ds_file_t *compress_open(ds_ctxt_t *ctxt, const char *path,
MY_STAT *mystat);
static int compress_write(ds_file_t *file, const void *buf, size_t len);
static int compress_close(ds_file_t *file);
static void compress_deinit(ds_ctxt_t *ctxt);
datasink_t datasink_compress = {
&compress_init,
&compress_open,
&compress_write,
&compress_close,
&compress_deinit
};
static inline int write_uint32_le(ds_file_t *file, ulong n);
static inline int write_uint64_le(ds_file_t *file, ulonglong n);
static comp_thread_ctxt_t *create_worker_threads(uint n);
static void destroy_worker_threads(comp_thread_ctxt_t *threads, uint n);
static void *compress_worker_thread_func(void *arg);
static
ds_ctxt_t *
compress_init(const char *root)
{
ds_ctxt_t *ctxt;
ds_compress_ctxt_t *compress_ctxt;
comp_thread_ctxt_t *threads;
/* Create and initialize the worker threads */
threads = create_worker_threads(xtrabackup_compress_threads);
if (threads == NULL) {
msg("compress: failed to create worker threads.\n");
return NULL;
}
ctxt = (ds_ctxt_t *) my_malloc(sizeof(ds_ctxt_t) +
sizeof(ds_compress_ctxt_t),
MYF(MY_FAE));
compress_ctxt = (ds_compress_ctxt_t *) (ctxt + 1);
compress_ctxt->threads = threads;
compress_ctxt->nthreads = xtrabackup_compress_threads;
ctxt->ptr = compress_ctxt;
ctxt->root = my_strdup(root, MYF(MY_FAE));
return ctxt;
}
static
ds_file_t *
compress_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
{
ds_compress_ctxt_t *comp_ctxt;
ds_ctxt_t *dest_ctxt;
ds_file_t *dest_file;
char new_name[FN_REFLEN];
size_t name_len;
ds_file_t *file;
ds_compress_file_t *comp_file;
xb_ad(ctxt->pipe_ctxt != NULL);
dest_ctxt = ctxt->pipe_ctxt;
comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;
/* Append the .qp extension to the filename */
fn_format(new_name, path, "", ".qp", MYF(MY_APPEND_EXT));
dest_file = ds_open(dest_ctxt, new_name, mystat);
if (dest_file == NULL) {
return NULL;
}
/* Write the qpress archive header */
if (ds_write(dest_file, "qpress10", 8) ||
write_uint64_le(dest_file, COMPRESS_CHUNK_SIZE)) {
goto err;
}
/* We are going to create a one-file "flat" (i.e. with no
subdirectories) archive. So strip the directory part from the path and
remove the '.qp' suffix. */
fn_format(new_name, path, "", "", MYF(MY_REPLACE_DIR));
/* Write the qpress file header */
name_len = strlen(new_name);
if (ds_write(dest_file, "F", 1) ||
write_uint32_le(dest_file, (uint)name_len) ||
/* we want to write the terminating \0 as well */
ds_write(dest_file, new_name, name_len + 1)) {
goto err;
}
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
sizeof(ds_compress_file_t),
MYF(MY_FAE));
comp_file = (ds_compress_file_t *) (file + 1);
comp_file->dest_file = dest_file;
comp_file->comp_ctxt = comp_ctxt;
comp_file->bytes_processed = 0;
file->ptr = comp_file;
file->path = dest_file->path;
return file;
err:
ds_close(dest_file);
return NULL;
}
static
int
compress_write(ds_file_t *file, const void *buf, size_t len)
{
ds_compress_file_t *comp_file;
ds_compress_ctxt_t *comp_ctxt;
comp_thread_ctxt_t *threads;
comp_thread_ctxt_t *thd;
uint nthreads;
uint i;
const char *ptr;
ds_file_t *dest_file;
comp_file = (ds_compress_file_t *) file->ptr;
comp_ctxt = comp_file->comp_ctxt;
dest_file = comp_file->dest_file;
threads = comp_ctxt->threads;
nthreads = comp_ctxt->nthreads;
ptr = (const char *) buf;
while (len > 0) {
uint max_thread;
/* Send data to worker threads for compression */
for (i = 0; i < nthreads; i++) {
size_t chunk_len;
thd = threads + i;
pthread_mutex_lock(&thd->ctrl_mutex);
chunk_len = (len > COMPRESS_CHUNK_SIZE) ?
COMPRESS_CHUNK_SIZE : len;
thd->from = ptr;
thd->from_len = chunk_len;
pthread_mutex_lock(&thd->data_mutex);
thd->data_avail = TRUE;
pthread_cond_signal(&thd->data_cond);
pthread_mutex_unlock(&thd->data_mutex);
len -= chunk_len;
if (len == 0) {
break;
}
ptr += chunk_len;
}
max_thread = (i < nthreads) ? i : nthreads - 1;
/* Reap and stream the compressed data */
for (i = 0; i <= max_thread; i++) {
thd = threads + i;
pthread_mutex_lock(&thd->data_mutex);
while (thd->data_avail == TRUE) {
pthread_cond_wait(&thd->data_cond,
&thd->data_mutex);
}
xb_a(threads[i].to_len > 0);
if (ds_write(dest_file, "NEWBNEWB", 8) ||
write_uint64_le(dest_file,
comp_file->bytes_processed)) {
msg("compress: write to the destination stream "
"failed.\n");
return 1;
}
comp_file->bytes_processed += threads[i].from_len;
if (write_uint32_le(dest_file, threads[i].adler) ||
ds_write(dest_file, threads[i].to,
threads[i].to_len)) {
msg("compress: write to the destination stream "
"failed.\n");
return 1;
}
pthread_mutex_unlock(&threads[i].data_mutex);
pthread_mutex_unlock(&threads[i].ctrl_mutex);
}
}
return 0;
}
static
int
compress_close(ds_file_t *file)
{
ds_compress_file_t *comp_file;
ds_file_t *dest_file;
int rc;
comp_file = (ds_compress_file_t *) file->ptr;
dest_file = comp_file->dest_file;
/* Write the qpress file trailer */
ds_write(dest_file, "ENDSENDS", 8);
/* Supposedly the number of written bytes should be written as a
"recovery information" in the file trailer, but in reality qpress
always writes 8 zeros here. Let's do the same */
write_uint64_le(dest_file, 0);
rc = ds_close(dest_file);
my_free(file);
return rc;
}
static
void
compress_deinit(ds_ctxt_t *ctxt)
{
ds_compress_ctxt_t *comp_ctxt;
xb_ad(ctxt->pipe_ctxt != NULL);
comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;;
destroy_worker_threads(comp_ctxt->threads, comp_ctxt->nthreads);
my_free(ctxt->root);
my_free(ctxt);
}
static inline
int
write_uint32_le(ds_file_t *file, ulong n)
{
char tmp[4];
int4store(tmp, n);
return ds_write(file, tmp, sizeof(tmp));
}
static inline
int
write_uint64_le(ds_file_t *file, ulonglong n)
{
char tmp[8];
int8store(tmp, n);
return ds_write(file, tmp, sizeof(tmp));
}
static
comp_thread_ctxt_t *
create_worker_threads(uint n)
{
comp_thread_ctxt_t *threads;
uint i;
threads = (comp_thread_ctxt_t *)
my_malloc(sizeof(comp_thread_ctxt_t) * n, MYF(MY_FAE));
for (i = 0; i < n; i++) {
comp_thread_ctxt_t *thd = threads + i;
thd->num = i + 1;
thd->started = FALSE;
thd->cancelled = FALSE;
thd->data_avail = FALSE;
thd->to = (char *) my_malloc(COMPRESS_CHUNK_SIZE +
MY_QLZ_COMPRESS_OVERHEAD,
MYF(MY_FAE));
/* Initialize the control mutex and condition var */
if (pthread_mutex_init(&thd->ctrl_mutex, NULL) ||
pthread_cond_init(&thd->ctrl_cond, NULL)) {
goto err;
}
/* Initialize and data mutex and condition var */
if (pthread_mutex_init(&thd->data_mutex, NULL) ||
pthread_cond_init(&thd->data_cond, NULL)) {
goto err;
}
pthread_mutex_lock(&thd->ctrl_mutex);
if (pthread_create(&thd->id, NULL, compress_worker_thread_func,
thd)) {
msg("compress: pthread_create() failed: "
"errno = %d\n", errno);
goto err;
}
}
/* Wait for the threads to start */
for (i = 0; i < n; i++) {
comp_thread_ctxt_t *thd = threads + i;
while (thd->started == FALSE)
pthread_cond_wait(&thd->ctrl_cond, &thd->ctrl_mutex);
pthread_mutex_unlock(&thd->ctrl_mutex);
}
return threads;
err:
return NULL;
}
static
void
destroy_worker_threads(comp_thread_ctxt_t *threads, uint n)
{
uint i;
for (i = 0; i < n; i++) {
comp_thread_ctxt_t *thd = threads + i;
pthread_mutex_lock(&thd->data_mutex);
threads[i].cancelled = TRUE;
pthread_cond_signal(&thd->data_cond);
pthread_mutex_unlock(&thd->data_mutex);
pthread_join(thd->id, NULL);
pthread_cond_destroy(&thd->data_cond);
pthread_mutex_destroy(&thd->data_mutex);
pthread_cond_destroy(&thd->ctrl_cond);
pthread_mutex_destroy(&thd->ctrl_mutex);
my_free(thd->to);
}
my_free(threads);
}
static
void *
compress_worker_thread_func(void *arg)
{
comp_thread_ctxt_t *thd = (comp_thread_ctxt_t *) arg;
pthread_mutex_lock(&thd->ctrl_mutex);
pthread_mutex_lock(&thd->data_mutex);
thd->started = TRUE;
pthread_cond_signal(&thd->ctrl_cond);
pthread_mutex_unlock(&thd->ctrl_mutex);
while (1) {
thd->data_avail = FALSE;
pthread_cond_signal(&thd->data_cond);
while (!thd->data_avail && !thd->cancelled) {
pthread_cond_wait(&thd->data_cond, &thd->data_mutex);
}
if (thd->cancelled)
break;
thd->to_len = qlz_compress(thd->from, thd->to, thd->from_len,
&thd->state);
/* qpress uses 0x00010000 as the initial value, but its own
Adler-32 implementation treats the value differently:
1. higher order bits are the sum of all bytes in the sequence
2. lower order bits are the sum of resulting values at every
step.
So it's the other way around as compared to zlib's adler32().
That's why 0x00000001 is being passed here to be compatible
with qpress implementation. */
thd->adler = adler32(0x00000001, (uchar *) thd->to,
(uInt)thd->to_len);
}
pthread_mutex_unlock(&thd->data_mutex);
return NULL;
}

View file

@ -0,0 +1,28 @@
/******************************************************
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
Compression interface for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifndef DS_COMPRESS_H
#define DS_COMPRESS_H
#include "datasink.h"
extern datasink_t datasink_compress;
#endif

View file

@ -0,0 +1,151 @@
/******************************************************
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
Local datasink implementation for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#include <mysql_version.h>
#include <my_base.h>
#include <mysys_err.h>
#include "common.h"
#include "datasink.h"
typedef struct {
File fd;
} ds_local_file_t;
static ds_ctxt_t *local_init(const char *root);
static ds_file_t *local_open(ds_ctxt_t *ctxt, const char *path,
MY_STAT *mystat);
static int local_write(ds_file_t *file, const void *buf, size_t len);
static int local_close(ds_file_t *file);
static void local_deinit(ds_ctxt_t *ctxt);
datasink_t datasink_local = {
&local_init,
&local_open,
&local_write,
&local_close,
&local_deinit
};
static
ds_ctxt_t *
local_init(const char *root)
{
ds_ctxt_t *ctxt;
if (my_mkdir(root, 0777, MYF(0)) < 0
&& my_errno != EEXIST && my_errno != EISDIR)
{
char errbuf[MYSYS_STRERROR_SIZE];
my_strerror(errbuf, sizeof(errbuf),my_errno);
my_error(EE_CANT_MKDIR, MYF(ME_BELL | ME_WAITTANG),
root, my_errno,errbuf, my_errno);
return NULL;
}
ctxt = my_malloc(sizeof(ds_ctxt_t), MYF(MY_FAE));
ctxt->root = my_strdup(root, MYF(MY_FAE));
return ctxt;
}
static
ds_file_t *
local_open(ds_ctxt_t *ctxt, const char *path,
MY_STAT *mystat __attribute__((unused)))
{
char fullpath[FN_REFLEN];
char dirpath[FN_REFLEN];
size_t dirpath_len;
size_t path_len;
ds_local_file_t *local_file;
ds_file_t *file;
File fd;
fn_format(fullpath, path, ctxt->root, "", MYF(MY_RELATIVE_PATH));
/* Create the directory if needed */
dirname_part(dirpath, fullpath, &dirpath_len);
if (my_mkdir(dirpath, 0777, MYF(0)) < 0 && my_errno != EEXIST) {
char errbuf[MYSYS_STRERROR_SIZE];
my_strerror(errbuf, sizeof(errbuf), my_errno);
my_error(EE_CANT_MKDIR, MYF(ME_BELL | ME_WAITTANG),
dirpath, my_errno, errbuf);
return NULL;
}
fd = my_create(fullpath, 0, O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
MYF(MY_WME));
if (fd < 0) {
return NULL;
}
path_len = strlen(fullpath) + 1; /* terminating '\0' */
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
sizeof(ds_local_file_t) +
path_len,
MYF(MY_FAE));
local_file = (ds_local_file_t *) (file + 1);
local_file->fd = fd;
file->path = (char *) local_file + sizeof(ds_local_file_t);
memcpy(file->path, fullpath, path_len);
file->ptr = local_file;
return file;
}
static
int
local_write(ds_file_t *file, const void *buf, size_t len)
{
File fd = ((ds_local_file_t *) file->ptr)->fd;
if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
return 0;
}
return 1;
}
static
int
local_close(ds_file_t *file)
{
File fd = ((ds_local_file_t *) file->ptr)->fd;
my_free(file);
my_sync(fd, MYF(MY_WME));
return my_close(fd, MYF(MY_WME));
}
static
void
local_deinit(ds_ctxt_t *ctxt)
{
my_free(ctxt->root);
my_free(ctxt);
}

View file

@ -0,0 +1,28 @@
/******************************************************
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
Local datasink interface for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifndef DS_LOCAL_H
#define DS_LOCAL_H
#include "datasink.h"
extern datasink_t datasink_local;
#endif

View file

@ -0,0 +1,121 @@
/******************************************************
Copyright (c) 2013 Percona LLC and/or its affiliates.
Local datasink implementation for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#include <my_base.h>
#include <mysys_err.h>
#include "common.h"
#include "datasink.h"
typedef struct {
File fd;
} ds_stdout_file_t;
static ds_ctxt_t *stdout_init(const char *root);
static ds_file_t *stdout_open(ds_ctxt_t *ctxt, const char *path,
MY_STAT *mystat);
static int stdout_write(ds_file_t *file, const void *buf, size_t len);
static int stdout_close(ds_file_t *file);
static void stdout_deinit(ds_ctxt_t *ctxt);
datasink_t datasink_stdout = {
&stdout_init,
&stdout_open,
&stdout_write,
&stdout_close,
&stdout_deinit
};
static
ds_ctxt_t *
stdout_init(const char *root)
{
ds_ctxt_t *ctxt;
ctxt = my_malloc(sizeof(ds_ctxt_t), MYF(MY_FAE));
ctxt->root = my_strdup(root, MYF(MY_FAE));
return ctxt;
}
static
ds_file_t *
stdout_open(ds_ctxt_t *ctxt __attribute__((unused)),
const char *path __attribute__((unused)),
MY_STAT *mystat __attribute__((unused)))
{
ds_stdout_file_t *stdout_file;
ds_file_t *file;
size_t pathlen;
const char *fullpath = "<STDOUT>";
pathlen = strlen(fullpath) + 1;
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
sizeof(ds_stdout_file_t) +
pathlen,
MYF(MY_FAE));
stdout_file = (ds_stdout_file_t *) (file + 1);
#ifdef __WIN__
setmode(fileno(stdout), _O_BINARY);
#endif
stdout_file->fd = my_fileno(stdout);
file->path = (char *) stdout_file + sizeof(ds_stdout_file_t);
memcpy(file->path, fullpath, pathlen);
file->ptr = stdout_file;
return file;
}
static
int
stdout_write(ds_file_t *file, const void *buf, size_t len)
{
File fd = ((ds_stdout_file_t *) file->ptr)->fd;
if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
return 0;
}
return 1;
}
static
int
stdout_close(ds_file_t *file)
{
my_free(file);
return 1;
}
static
void
stdout_deinit(ds_ctxt_t *ctxt)
{
my_free(ctxt->root);
my_free(ctxt);
}

View file

@ -0,0 +1,28 @@
/******************************************************
Copyright (c) 2013 Percona LLC and/or its affiliates.
Local datasink interface for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifndef DS_STDOUT_H
#define DS_STDOUT_H
#include "datasink.h"
extern datasink_t datasink_stdout;
#endif

View file

@ -0,0 +1,247 @@
/******************************************************
Copyright (c) 2012 Percona LLC and/or its affiliates.
tmpfile datasink for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
/* Do all writes to temporary files first, then pipe them to the specified
datasink in a serialized way in deinit(). */
#include <my_base.h>
#include "common.h"
#include "datasink.h"
typedef struct {
pthread_mutex_t mutex;
LIST *file_list;
} ds_tmpfile_ctxt_t;
typedef struct {
LIST list;
File fd;
char *orig_path;
MY_STAT mystat;
ds_file_t *file;
} ds_tmp_file_t;
static ds_ctxt_t *tmpfile_init(const char *root);
static ds_file_t *tmpfile_open(ds_ctxt_t *ctxt, const char *path,
MY_STAT *mystat);
static int tmpfile_write(ds_file_t *file, const void *buf, size_t len);
static int tmpfile_close(ds_file_t *file);
static void tmpfile_deinit(ds_ctxt_t *ctxt);
datasink_t datasink_tmpfile = {
&tmpfile_init,
&tmpfile_open,
&tmpfile_write,
&tmpfile_close,
&tmpfile_deinit
};
static ds_ctxt_t *
tmpfile_init(const char *root)
{
ds_ctxt_t *ctxt;
ds_tmpfile_ctxt_t *tmpfile_ctxt;
ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_tmpfile_ctxt_t),
MYF(MY_FAE));
tmpfile_ctxt = (ds_tmpfile_ctxt_t *) (ctxt + 1);
tmpfile_ctxt->file_list = NULL;
if (pthread_mutex_init(&tmpfile_ctxt->mutex, NULL)) {
my_free(ctxt);
return NULL;
}
ctxt->ptr = tmpfile_ctxt;
ctxt->root = my_strdup(root, MYF(MY_FAE));
return ctxt;
}
static ds_file_t *
tmpfile_open(ds_ctxt_t *ctxt, const char *path,
MY_STAT *mystat)
{
ds_tmpfile_ctxt_t *tmpfile_ctxt;
char tmp_path[FN_REFLEN];
ds_tmp_file_t *tmp_file;
ds_file_t *file;
size_t path_len;
File fd;
/* Create a temporary file in tmpdir. The file will be automatically
removed on close. Code copied from mysql_tmpfile(). */
fd = create_temp_file(tmp_path,xtrabackup_tmpdir,
"xbtemp",
#ifdef __WIN__
O_BINARY | O_TRUNC | O_SEQUENTIAL |
O_TEMPORARY | O_SHORT_LIVED |
#endif /* __WIN__ */
O_CREAT | O_EXCL | O_RDWR,
MYF(MY_WME));
#ifndef __WIN__
if (fd >= 0) {
/* On Windows, open files cannot be removed, but files can be
created with the O_TEMPORARY flag to the same effect
("delete on close"). */
unlink(tmp_path);
}
#endif /* !__WIN__ */
if (fd < 0) {
return NULL;
}
path_len = strlen(path) + 1; /* terminating '\0' */
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
sizeof(ds_tmp_file_t) + path_len,
MYF(MY_FAE));
tmp_file = (ds_tmp_file_t *) (file + 1);
tmp_file->file = file;
memcpy(&tmp_file->mystat, mystat, sizeof(MY_STAT));
/* Save a copy of 'path', since it may not be accessible later */
tmp_file->orig_path = (char *) tmp_file + sizeof(ds_tmp_file_t);
tmp_file->fd = fd;
memcpy(tmp_file->orig_path, path, path_len);
/* Store the real temporary file name in file->path */
file->path = my_strdup(tmp_path, MYF(MY_FAE));
file->ptr = tmp_file;
/* Store the file object in the list to be piped later */
tmpfile_ctxt = (ds_tmpfile_ctxt_t *) ctxt->ptr;
tmp_file->list.data = tmp_file;
pthread_mutex_lock(&tmpfile_ctxt->mutex);
tmpfile_ctxt->file_list = list_add(tmpfile_ctxt->file_list,
&tmp_file->list);
pthread_mutex_unlock(&tmpfile_ctxt->mutex);
return file;
}
static int
tmpfile_write(ds_file_t *file, const void *buf, size_t len)
{
File fd = ((ds_tmp_file_t *) file->ptr)->fd;
if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
return 0;
}
return 1;
}
static int
tmpfile_close(ds_file_t *file)
{
/* Do nothing -- we will close (and thus remove) the file after piping
it to the destination datasink in tmpfile_deinit(). */
my_free(file->path);
return 0;
}
static void
tmpfile_deinit(ds_ctxt_t *ctxt)
{
LIST *list;
ds_tmpfile_ctxt_t *tmpfile_ctxt;
MY_STAT mystat;
ds_tmp_file_t *tmp_file;
ds_file_t *dst_file;
ds_ctxt_t *pipe_ctxt;
void *buf = NULL;
const size_t buf_size = 10 * 1024 * 1024;
size_t bytes;
size_t offset;
pipe_ctxt = ctxt->pipe_ctxt;
xb_a(pipe_ctxt != NULL);
buf = my_malloc(buf_size, MYF(MY_FAE));
tmpfile_ctxt = (ds_tmpfile_ctxt_t *) ctxt->ptr;
list = tmpfile_ctxt->file_list;
/* Walk the files in the order they have been added */
list = list_reverse(list);
while (list != NULL) {
tmp_file = list->data;
/* Stat the file to replace size and mtime on the original
* mystat struct */
if (my_fstat(tmp_file->fd, &mystat, MYF(0))) {
msg("error: my_fstat() failed.\n");
exit(EXIT_FAILURE);
}
tmp_file->mystat.st_size = mystat.st_size;
tmp_file->mystat.st_mtime = mystat.st_mtime;
dst_file = ds_open(pipe_ctxt, tmp_file->orig_path,
&tmp_file->mystat);
if (dst_file == NULL) {
msg("error: could not stream a temporary file to "
"'%s'\n", tmp_file->orig_path);
exit(EXIT_FAILURE);
}
/* copy to the destination datasink */
posix_fadvise(tmp_file->fd, 0, 0, POSIX_FADV_SEQUENTIAL);
if (my_seek(tmp_file->fd, 0, SEEK_SET, MYF(0)) ==
MY_FILEPOS_ERROR) {
msg("error: my_seek() failed for '%s', errno = %d.\n",
tmp_file->file->path, my_errno);
exit(EXIT_FAILURE);
}
offset = 0;
while ((bytes = my_read(tmp_file->fd, buf, buf_size,
MYF(MY_WME))) > 0) {
posix_fadvise(tmp_file->fd, offset, buf_size, POSIX_FADV_DONTNEED);
offset += buf_size;
if (ds_write(dst_file, buf, bytes)) {
msg("error: cannot write to stream for '%s'.\n",
tmp_file->orig_path);
exit(EXIT_FAILURE);
}
}
if (bytes == (size_t) -1) {
exit(EXIT_FAILURE);
}
my_close(tmp_file->fd, MYF(MY_WME));
ds_close(dst_file);
list = list_rest(list);
my_free(tmp_file->file);
}
pthread_mutex_destroy(&tmpfile_ctxt->mutex);
my_free(buf);
my_free(ctxt->root);
my_free(ctxt);
}

View file

@ -0,0 +1,30 @@
/******************************************************
Copyright (c) 2012 Percona LLC and/or its affiliates.
tmpfile datasink for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifndef DS_TMPFILE_H
#define DS_TMPFILE_H
#include "datasink.h"
extern datasink_t datasink_tmpfile;
extern MY_TMPDIR mysql_tmpdir_list;
#endif

View file

@ -0,0 +1,223 @@
/******************************************************
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
Streaming implementation for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#include <mysql_version.h>
#include <my_base.h>
#include "common.h"
#include "datasink.h"
#include "xbstream.h"
typedef struct {
xb_wstream_t *xbstream;
ds_file_t *dest_file;
pthread_mutex_t mutex;
} ds_stream_ctxt_t;
typedef struct {
xb_wstream_file_t *xbstream_file;
ds_stream_ctxt_t *stream_ctxt;
} ds_stream_file_t;
/***********************************************************************
General streaming interface */
static ds_ctxt_t *xbstream_init(const char *root);
static ds_file_t *xbstream_open(ds_ctxt_t *ctxt, const char *path,
MY_STAT *mystat);
static int xbstream_write(ds_file_t *file, const void *buf, size_t len);
static int xbstream_close(ds_file_t *file);
static void xbstream_deinit(ds_ctxt_t *ctxt);
datasink_t datasink_xbstream = {
&xbstream_init,
&xbstream_open,
&xbstream_write,
&xbstream_close,
&xbstream_deinit
};
static
ssize_t
my_xbstream_write_callback(xb_wstream_file_t *f __attribute__((unused)),
void *userdata, const void *buf, size_t len)
{
ds_stream_ctxt_t *stream_ctxt;
stream_ctxt = (ds_stream_ctxt_t *) userdata;
xb_ad(stream_ctxt != NULL);
xb_ad(stream_ctxt->dest_file != NULL);
if (!ds_write(stream_ctxt->dest_file, buf, len)) {
return len;
}
return -1;
}
static
ds_ctxt_t *
xbstream_init(const char *root __attribute__((unused)))
{
ds_ctxt_t *ctxt;
ds_stream_ctxt_t *stream_ctxt;
xb_wstream_t *xbstream;
ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_stream_ctxt_t),
MYF(MY_FAE));
stream_ctxt = (ds_stream_ctxt_t *)(ctxt + 1);
if (pthread_mutex_init(&stream_ctxt->mutex, NULL)) {
msg("xbstream_init: pthread_mutex_init() failed.\n");
goto err;
}
xbstream = xb_stream_write_new();
if (xbstream == NULL) {
msg("xb_stream_write_new() failed.\n");
goto err;
}
stream_ctxt->xbstream = xbstream;
stream_ctxt->dest_file = NULL;
ctxt->ptr = stream_ctxt;
return ctxt;
err:
my_free(ctxt);
return NULL;
}
static
ds_file_t *
xbstream_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
{
ds_file_t *file;
ds_stream_file_t *stream_file;
ds_stream_ctxt_t *stream_ctxt;
ds_ctxt_t *dest_ctxt;
xb_wstream_t *xbstream;
xb_wstream_file_t *xbstream_file;
xb_ad(ctxt->pipe_ctxt != NULL);
dest_ctxt = ctxt->pipe_ctxt;
stream_ctxt = (ds_stream_ctxt_t *) ctxt->ptr;
pthread_mutex_lock(&stream_ctxt->mutex);
if (stream_ctxt->dest_file == NULL) {
stream_ctxt->dest_file = ds_open(dest_ctxt, path, mystat);
if (stream_ctxt->dest_file == NULL) {
return NULL;
}
}
pthread_mutex_unlock(&stream_ctxt->mutex);
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
sizeof(ds_stream_file_t),
MYF(MY_FAE));
stream_file = (ds_stream_file_t *) (file + 1);
xbstream = stream_ctxt->xbstream;
xbstream_file = xb_stream_write_open(xbstream, path, mystat,
stream_ctxt,
my_xbstream_write_callback);
if (xbstream_file == NULL) {
msg("xb_stream_write_open() failed.\n");
goto err;
}
stream_file->xbstream_file = xbstream_file;
stream_file->stream_ctxt = stream_ctxt;
file->ptr = stream_file;
file->path = stream_ctxt->dest_file->path;
return file;
err:
if (stream_ctxt->dest_file) {
ds_close(stream_ctxt->dest_file);
stream_ctxt->dest_file = NULL;
}
my_free(file);
return NULL;
}
static
int
xbstream_write(ds_file_t *file, const void *buf, size_t len)
{
ds_stream_file_t *stream_file;
xb_wstream_file_t *xbstream_file;
stream_file = (ds_stream_file_t *) file->ptr;
xbstream_file = stream_file->xbstream_file;
if (xb_stream_write_data(xbstream_file, buf, len)) {
msg("xb_stream_write_data() failed.\n");
return 1;
}
return 0;
}
static
int
xbstream_close(ds_file_t *file)
{
ds_stream_file_t *stream_file;
int rc = 0;
stream_file = (ds_stream_file_t *)file->ptr;
rc = xb_stream_write_close(stream_file->xbstream_file);
my_free(file);
return rc;
}
static
void
xbstream_deinit(ds_ctxt_t *ctxt)
{
ds_stream_ctxt_t *stream_ctxt;
stream_ctxt = (ds_stream_ctxt_t *) ctxt->ptr;
if (xb_stream_write_done(stream_ctxt->xbstream)) {
msg("xb_stream_done() failed.\n");
}
if (stream_ctxt->dest_file) {
ds_close(stream_ctxt->dest_file);
stream_ctxt->dest_file = NULL;
}
pthread_mutex_destroy(&stream_ctxt->mutex);
my_free(ctxt);
}

View file

@ -0,0 +1,28 @@
/******************************************************
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
Streaming interface for XtraBackup.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
#ifndef DS_XBSTREAM_H
#define DS_XBSTREAM_H
#include "datasink.h"
extern datasink_t datasink_xbstream;
#endif

View file

@ -0,0 +1,157 @@
#include <mysqld.h>
#include <mysql.h>
#include <xtrabackup.h>
#include <encryption_plugin.h>
#include <backup_copy.h>
#include <sql_plugin.h>
#include <sstream>
#include <vector>
#include <common.h>
#include <backup_mysql.h>
#include <log0crypt.h>
extern struct st_maria_plugin *mysql_optional_plugins[];
extern struct st_maria_plugin *mysql_mandatory_plugins[];
static void encryption_plugin_init(int argc, char **argv);
extern char *xb_plugin_load;
extern char *xb_plugin_dir;
const int PLUGIN_MAX_ARGS = 1024;
std::vector<std::string> backup_plugins_args;
const char *QUERY_PLUGIN =
"SELECT plugin_name, plugin_library, @@plugin_dir"
" FROM information_schema.plugins WHERE plugin_type='ENCRYPTION'"
" AND plugin_status='ACTIVE'";
std::string encryption_plugin_config;
static void add_to_plugin_load_list(const char *plugin_def)
{
opt_plugin_load_list_ptr->push_back(new i_string(plugin_def));
}
static char XTRABACKUP_EXE[] = "xtrabackup";
void encryption_plugin_backup_init(MYSQL *mysql)
{
MYSQL_RES *result;
MYSQL_ROW row;
std::ostringstream oss;
char *argv[PLUGIN_MAX_ARGS];
int argc;
result = xb_mysql_query(mysql, QUERY_PLUGIN, true, true);
row = mysql_fetch_row(result);
if (!row)
{
mysql_free_result(result);
return;
}
char *name= row[0];
char *library= row[1];
char *dir= row[2];
#ifdef _WIN32
for (char *p = dir; *p; p++)
if (*p == '\\') *p = '/';
#endif
std::string plugin_load(name);
if (library)
plugin_load += std::string("=") + library;
oss << "plugin_load=" << plugin_load << std::endl;
/* Required to load the plugin later.*/
add_to_plugin_load_list(plugin_load.c_str());
strncpy(opt_plugin_dir, dir, FN_REFLEN);
oss << "plugin_dir=" << '"' << dir << '"' << std::endl;
/* Read plugin variables. */
char query[1024];
snprintf(query, 1024, "SHOW variables like '%s_%%'", name);
mysql_free_result(result);
result = xb_mysql_query(mysql, query, true, true);
while ((row = mysql_fetch_row(result)))
{
std::string arg("--");
arg += row[0];
arg += "=";
arg += row[1];
backup_plugins_args.push_back(arg);
oss << row[0] << "=" << row[1] << std::endl;
}
mysql_free_result(result);
/* Check whether to encrypt logs. */
result = xb_mysql_query(mysql, "select @@innodb_encrypt_log", true, true);
row = mysql_fetch_row(result);
srv_encrypt_log = (row != 0 && row[0][0] == '1');
oss << "innodb_encrypt_log=" << row[0] << std::endl;
mysql_free_result(result);
encryption_plugin_config = oss.str();
argc = 0;
argv[argc++] = XTRABACKUP_EXE;
for(size_t i = 0; i < backup_plugins_args.size(); i++)
{
argv[argc++] = (char *)backup_plugins_args[i].c_str();
if (argc == PLUGIN_MAX_ARGS - 2)
break;
}
argv[argc] = 0;
encryption_plugin_init(argc, argv);
}
const char *encryption_plugin_get_config()
{
return encryption_plugin_config.c_str();
}
extern int finalize_encryption_plugin(st_plugin_int *plugin);
void encryption_plugin_prepare_init(int argc, char **argv)
{
if (!xb_plugin_load)
{
finalize_encryption_plugin(0);
return;
}
add_to_plugin_load_list(xb_plugin_load);
if (xb_plugin_dir)
strncpy(opt_plugin_dir, xb_plugin_dir, FN_REFLEN);
char **new_argv = new char *[argc + 1];
new_argv[0] = XTRABACKUP_EXE;
memcpy(&new_argv[1], argv, argc*sizeof(char *));
encryption_plugin_init(argc+1, new_argv);
delete[] new_argv;
}
static void encryption_plugin_init(int argc, char **argv)
{
/* Patch optional and mandatory plugins, we only need to load the one in xb_plugin_load. */
mysql_optional_plugins[0] = mysql_mandatory_plugins[0] = 0;
msg("Loading encryption plugin\n");
for (int i= 1; i < argc; i++)
msg("\t Encryption plugin parameter : '%s'\n", argv[i]);
plugin_init(&argc, argv, PLUGIN_INIT_SKIP_PLUGIN_TABLE);
}

Some files were not shown because too many files have changed in this diff Show more