summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Lindström <jplindst@mariadb.org>2014-04-16 13:08:29 +0300
committerJan Lindström <jplindst@mariadb.org>2014-04-16 13:08:29 +0300
commitfa18dc394406ad684ab2623e7451c9f3ec7adf08 (patch)
tree6b708eaa3b970ee14451c2ffdd5d89c7d8dce0dd
parent150e88e8c9b85e3e6ce500a91fd215d231e99881 (diff)
downloadmariadb-git-fa18dc394406ad684ab2623e7451c9f3ec7adf08.tar.gz
Merge lp:codership-mysql/5.5 -r3961..3980.
-rw-r--r--cmake/wsrep.cmake2
-rw-r--r--scripts/CMakeLists.txt8
-rwxr-xr-xscripts/wsrep_sst_common12
-rw-r--r--scripts/wsrep_sst_common.sh12
-rwxr-xr-xscripts/wsrep_sst_rsync.sh31
-rwxr-xr-xscripts/wsrep_sst_xtrabackup-v2879
-rw-r--r--scripts/wsrep_sst_xtrabackup-v2.sh879
-rw-r--r--scripts/wsrep_sst_xtrabackup.sh600
-rw-r--r--sql/slave.cc33
-rw-r--r--sql/sql_base.cc1
-rw-r--r--sql/sys_vars.cc4
-rw-r--r--sql/wsrep_binlog.cc56
-rw-r--r--sql/wsrep_binlog.h3
-rw-r--r--sql/wsrep_hton.cc6
-rw-r--r--sql/wsrep_mysqld.cc46
-rw-r--r--sql/wsrep_mysqld.h2
-rw-r--r--sql/wsrep_notify.cc19
-rw-r--r--sql/wsrep_sst.cc3
-rw-r--r--support-files/mysql.spec.sh1
-rw-r--r--support-files/wsrep_notify.sh1
-rw-r--r--wsrep/wsrep_api.h4
-rw-r--r--wsrep/wsrep_dummy.c1
22 files changed, 2380 insertions, 223 deletions
diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake
index a5ca4508da4..95f3f4fcd8f 100644
--- a/cmake/wsrep.cmake
+++ b/cmake/wsrep.cmake
@@ -18,7 +18,7 @@
# so WSREP_VERSION is produced regardless
# Set the patch version
-SET(WSREP_PATCH_VERSION "9")
+SET(WSREP_PATCH_VERSION "10")
# MariaDB addition: Revision number of the last revision merged from
# codership branch visible in @@visible_comment.
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index 57fc70ea508..8be77f590a5 100644
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -328,7 +328,13 @@ IF(WIN32)
ENDFOREACH()
ELSE()
IF(WITH_WSREP)
- SET(WSREP_BINARIES wsrep_sst_common wsrep_sst_mysqldump wsrep_sst_rsync wsrep_sst_xtrabackup)
+ SET(WSREP_BINARIES
+ wsrep_sst_common
+ wsrep_sst_mysqldump
+ wsrep_sst_rsync
+ wsrep_sst_xtrabackup
+ wsrep_sst_xtrabackup-v2
+ )
ENDIF()
# Configure this one, for testing, but do not install it.
diff --git a/scripts/wsrep_sst_common b/scripts/wsrep_sst_common
index 30303de0779..f9a08c1c695 100755
--- a/scripts/wsrep_sst_common
+++ b/scripts/wsrep_sst_common
@@ -28,7 +28,7 @@ case "$1" in
shift
;;
'--auth')
- readonly WSREP_SST_OPT_AUTH="$2"
+ WSREP_SST_OPT_AUTH="$2"
shift
;;
'--bypass')
@@ -87,13 +87,21 @@ shift
done
readonly WSREP_SST_OPT_BYPASS
-if [ -n "$WSREP_SST_OPT_DATA" ]
+# For Bug:1200727
+if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then
+ if [ -z $WSREP_SST_OPT_AUTH -o $WSREP_SST_OPT_AUTH = "(null)" ];then
+ WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2)
+ fi
+fi
+
+if [ -n "${WSREP_SST_OPT_DATA:-}" ]
then
SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress"
else
SST_PROGRESS_FILE=""
fi
+
wsrep_log()
{
# echo everything to stderr so that it gets into common error log
diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh
index 30303de0779..f9a08c1c695 100644
--- a/scripts/wsrep_sst_common.sh
+++ b/scripts/wsrep_sst_common.sh
@@ -28,7 +28,7 @@ case "$1" in
shift
;;
'--auth')
- readonly WSREP_SST_OPT_AUTH="$2"
+ WSREP_SST_OPT_AUTH="$2"
shift
;;
'--bypass')
@@ -87,13 +87,21 @@ shift
done
readonly WSREP_SST_OPT_BYPASS
-if [ -n "$WSREP_SST_OPT_DATA" ]
+# For Bug:1200727
+if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then
+ if [ -z $WSREP_SST_OPT_AUTH -o $WSREP_SST_OPT_AUTH = "(null)" ];then
+ WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2)
+ fi
+fi
+
+if [ -n "${WSREP_SST_OPT_DATA:-}" ]
then
SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress"
else
SST_PROGRESS_FILE=""
fi
+
wsrep_log()
{
# echo everything to stderr so that it gets into common error log
diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh
index 4b78071542c..960eef2df4b 100755
--- a/scripts/wsrep_sst_rsync.sh
+++ b/scripts/wsrep_sst_rsync.sh
@@ -49,19 +49,21 @@ check_pid()
check_pid_and_port()
{
local pid_file=$1
- local rsync_pid=$(cat $pid_file)
- local rsync_port=$2
-
- if [ "$OS" == "Darwin" -o "$OS" == "FreeBSD" ]; then
- # no netstat --program(-p) option in Darwin and FreeBSD
- check_pid $pid_file && \
- lsof -i -Pn 2>/dev/null | \
- grep "(LISTEN)" | grep ":$rsync_port" | grep -w '^rsync[[:space:]]\+'"$rsync_pid" >/dev/null
- else
- check_pid $pid_file && \
- netstat -lnpt 2>/dev/null | \
- grep LISTEN | grep \:$rsync_port | grep $rsync_pid/rsync >/dev/null
+ local rsync_pid=$2
+ local rsync_port=$3
+
+ local port_info=$(lsof -i :$rsync_port -Pn 2>/dev/null | \
+ grep "(LISTEN)")
+ local is_rsync=$(echo $port_info | \
+ grep -w '^rsync[[:space:]]\+'"$rsync_pid" 2>/dev/null)
+
+ if [ -n "$port_info" -a -z "$is_rsync" ]; then
+ wsrep_log_error "rsync daemon port '$rsync_port' has been taken"
+ exit 16 # EBUSY
fi
+ check_pid $pid_file && \
+ [ -n "$port_info" ] && [ -n "$is_rsync" ] && \
+ [ $(cat $pid_file) -eq $rsync_pid ]
}
MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete"
@@ -234,9 +236,10 @@ EOF
# rm -rf "$DATA"/ib_logfile* # we don't want old logs around
# listen at all interfaces (for firewalled setups)
- rsync --daemon --port $RSYNC_PORT --config "$RSYNC_CONF"
+ rsync --daemon --no-detach --port $RSYNC_PORT --config "$RSYNC_CONF" &
+ RSYNC_REAL_PID=$!
- until check_pid_and_port $RSYNC_PID $RSYNC_PORT
+ until check_pid_and_port $RSYNC_PID $RSYNC_REAL_PID $RSYNC_PORT
do
sleep 0.2
done
diff --git a/scripts/wsrep_sst_xtrabackup-v2 b/scripts/wsrep_sst_xtrabackup-v2
new file mode 100755
index 00000000000..59017fff8df
--- /dev/null
+++ b/scripts/wsrep_sst_xtrabackup-v2
@@ -0,0 +1,879 @@
+#!/bin/bash -ue
+# Copyright (C) 2013 Percona Inc
+#
+# 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; see the file COPYING. If not, write to the
+# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston
+# MA 02110-1301 USA.
+
+# Documentation: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
+# Make sure to read that before proceeding!
+
+
+
+
+. $(dirname $0)/wsrep_sst_common
+
+ealgo=""
+ekey=""
+ekeyfile=""
+encrypt=0
+nproc=1
+ecode=0
+XTRABACKUP_PID=""
+SST_PORT=""
+REMOTEIP=""
+tcert=""
+tpem=""
+tkey=""
+sockopt=""
+progress=""
+ttime=0
+totime=0
+lsn=""
+incremental=0
+ecmd=""
+rlimit=""
+# Initially
+stagemsg="${WSREP_SST_OPT_ROLE}"
+cpat=""
+speciald=0
+ib_home_dir=""
+ib_log_dir=""
+
+sfmt="tar"
+strmcmd=""
+tfmt=""
+tcmd=""
+rebuild=0
+rebuildcmd=""
+payload=0
+pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' "
+pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE "
+STATDIR=""
+uextra=0
+disver=""
+
+scomp=""
+sdecomp=""
+
+if which pv &>/dev/null && pv --help | grep -q FORMAT;then
+ pvopts+=$pvformat
+fi
+pcmd="pv $pvopts"
+declare -a RC
+
+INNOBACKUPEX_BIN=innobackupex
+readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
+DATA="${WSREP_SST_OPT_DATA}"
+INFO_FILE="xtrabackup_galera_info"
+IST_FILE="xtrabackup_ist"
+MAGIC_FILE="${DATA}/${INFO_FILE}"
+
+# Setting the path for ss and ip
+export PATH="/usr/sbin:/sbin:$PATH"
+
+timeit(){
+ local stage=$1
+ shift
+ local cmd="$@"
+ local x1 x2 took extcode
+
+ if [[ $ttime -eq 1 ]];then
+ x1=$(date +%s)
+ wsrep_log_info "Evaluating $cmd"
+ eval "$cmd"
+ extcode=$?
+ x2=$(date +%s)
+ took=$(( x2-x1 ))
+ wsrep_log_info "NOTE: $stage took $took seconds"
+ totime=$(( totime+took ))
+ else
+ wsrep_log_info "Evaluating $cmd"
+ eval "$cmd"
+ extcode=$?
+ fi
+ return $extcode
+}
+
+get_keys()
+{
+ # $encrypt -eq 1 is for internal purposes only
+ if [[ $encrypt -ge 2 || $encrypt -eq -1 ]];then
+ return
+ fi
+
+ if [[ $encrypt -eq 0 ]];then
+ if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then
+ wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html "
+ fi
+ return
+ fi
+
+ if [[ $sfmt == 'tar' ]];then
+ wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format"
+ encrypt=-1
+ return
+ fi
+
+ wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4"
+
+ if [[ -z $ealgo ]];then
+ wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out"
+ exit 3
+ fi
+
+ if [[ -z $ekey && ! -r $ekeyfile ]];then
+ wsrep_log_error "FATAL: Either key or keyfile must be readable"
+ exit 3
+ fi
+
+ if [[ -z $ekey ]];then
+ ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile"
+ else
+ ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey"
+ fi
+
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ ecmd+=" -d"
+ fi
+
+ stagemsg+="-XB-Encrypted"
+}
+
+get_transfer()
+{
+ if [[ -z $SST_PORT ]];then
+ TSST_PORT=4444
+ else
+ TSST_PORT=$SST_PORT
+ fi
+
+ if [[ $tfmt == 'nc' ]];then
+ if [[ ! -x `which nc` ]];then
+ wsrep_log_error "nc(netcat) not found in path: $PATH"
+ exit 2
+ fi
+ wsrep_log_info "Using netcat as streamer"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ tcmd="nc -dl ${TSST_PORT}"
+ else
+ tcmd="nc ${REMOTEIP} ${TSST_PORT}"
+ fi
+ else
+ tfmt='socat'
+ wsrep_log_info "Using socat as streamer"
+ if [[ ! -x `which socat` ]];then
+ wsrep_log_error "socat not found in path: $PATH"
+ exit 2
+ fi
+
+ if [[ $encrypt -eq 2 || $encrypt -eq 3 ]] && ! socat -V | grep -q WITH_OPENSSL;then
+ wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer"
+ encrypt=-1
+ fi
+
+ if [[ $encrypt -eq 2 ]];then
+ wsrep_log_info "Using openssl based encryption with socat: with crt and pem"
+ if [[ -z $tpem || -z $tcert ]];then
+ wsrep_log_error "Both PEM and CRT files required"
+ exit 22
+ fi
+ stagemsg+="-OpenSSL-Encrypted-2"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert"
+ tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio"
+ else
+ wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert"
+ tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}"
+ fi
+ elif [[ $encrypt -eq 3 ]];then
+ wsrep_log_info "Using openssl based encryption with socat: with key and crt"
+ if [[ -z $tpem || -z $tkey ]];then
+ wsrep_log_error "Both certificate and key files required"
+ exit 22
+ fi
+ stagemsg+="-OpenSSL-Encrypted-3"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ wsrep_log_info "Decrypting with certificate $tpem, key $tkey"
+ tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,key=${tkey},verify=0${sockopt} stdio"
+ else
+ wsrep_log_info "Encrypting with certificate $tpem, key $tkey"
+ tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,key=${tkey},verify=0${sockopt}"
+ fi
+
+ else
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio"
+ else
+ tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}"
+ fi
+ fi
+ fi
+
+}
+
+parse_cnf()
+{
+ local group=$1
+ local var=$2
+ reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-)
+ if [[ -z $reval ]];then
+ [[ -n $3 ]] && reval=$3
+ fi
+ echo $reval
+}
+
+get_footprint()
+{
+ pushd $WSREP_SST_OPT_DATA 1>/dev/null
+ payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }')
+ if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then
+ # QuickLZ has around 50% compression ratio
+ # When compression/compaction used, the progress is only an approximate.
+ payload=$(( payload*1/2 ))
+ fi
+ popd 1>/dev/null
+ pcmd+=" -s $payload"
+ adjust_progress
+}
+
+adjust_progress()
+{
+ if [[ -n $progress && $progress != '1' ]];then
+ if [[ -e $progress ]];then
+ pcmd+=" 2>>$progress"
+ else
+ pcmd+=" 2>$progress"
+ fi
+ elif [[ -z $progress && -n $rlimit ]];then
+ # When rlimit is non-zero
+ pcmd="pv -q"
+ fi
+
+ if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then
+ wsrep_log_info "Rate-limiting SST to $rlimit"
+ pcmd+=" -L \$rlimit"
+ fi
+}
+
+read_cnf()
+{
+ sfmt=$(parse_cnf sst streamfmt "xbstream")
+ tfmt=$(parse_cnf sst transferfmt "socat")
+ tcert=$(parse_cnf sst tca "")
+ tpem=$(parse_cnf sst tcert "")
+ tkey=$(parse_cnf sst tkey "")
+ encrypt=$(parse_cnf sst encrypt 0)
+ sockopt=$(parse_cnf sst sockopt "")
+ progress=$(parse_cnf sst progress "")
+ rebuild=$(parse_cnf sst rebuild 0)
+ ttime=$(parse_cnf sst time 0)
+ cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$')
+ incremental=$(parse_cnf sst incremental 0)
+ ealgo=$(parse_cnf xtrabackup encrypt "")
+ ekey=$(parse_cnf xtrabackup encrypt-key "")
+ ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "")
+ scomp=$(parse_cnf sst compressor "")
+ sdecomp=$(parse_cnf sst decompressor "")
+
+
+ # Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
+ if [[ -z $ealgo ]];then
+ ealgo=$(parse_cnf sst encrypt-algo "")
+ ekey=$(parse_cnf sst encrypt-key "")
+ ekeyfile=$(parse_cnf sst encrypt-key-file "")
+ fi
+ rlimit=$(parse_cnf sst rlimit "")
+ uextra=$(parse_cnf sst use_extra 0)
+ speciald=$(parse_cnf sst sst-special-dirs 1)
+ iopts=$(parse_cnf sst inno-backup-opts "")
+ iapts=$(parse_cnf sst inno-apply-opts "")
+ impts=$(parse_cnf sst inno-move-opts "")
+}
+
+get_stream()
+{
+ if [[ $sfmt == 'xbstream' ]];then
+ wsrep_log_info "Streaming with xbstream"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ strmcmd="xbstream -x"
+ else
+ strmcmd="xbstream -c \${INFO_FILE}"
+ fi
+ else
+ sfmt="tar"
+ wsrep_log_info "Streaming with tar"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ strmcmd="tar xfi - "
+ else
+ strmcmd="tar cf - \${INFO_FILE} "
+ fi
+
+ fi
+}
+
+get_proc()
+{
+ set +e
+ nproc=$(grep -c processor /proc/cpuinfo)
+ [[ -z $nproc || $nproc -eq 0 ]] && nproc=1
+ set -e
+}
+
+sig_joiner_cleanup()
+{
+ wsrep_log_error "Removing $MAGIC_FILE file due to signal"
+ rm -f "$MAGIC_FILE"
+}
+
+cleanup_joiner()
+{
+ # Since this is invoked just after exit NNN
+ local estatus=$?
+ if [[ $estatus -ne 0 ]];then
+ wsrep_log_error "Cleanup after exit with status:$estatus"
+ fi
+ if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
+ wsrep_log_info "Removing the sst_in_progress file"
+ wsrep_cleanup_progress_file
+ fi
+ if [[ -n $progress && -p $progress ]];then
+ wsrep_log_info "Cleaning up fifo file $progress"
+ rm $progress
+ fi
+ if [[ -n ${STATDIR:-} ]];then
+ [[ -d $STATDIR ]] && rm -rf $STATDIR
+ fi
+}
+
+check_pid()
+{
+ local pid_file="$1"
+ [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1
+}
+
+cleanup_donor()
+{
+ # Since this is invoked just after exit NNN
+ local estatus=$?
+ if [[ $estatus -ne 0 ]];then
+ wsrep_log_error "Cleanup after exit with status:$estatus"
+ fi
+
+ if [[ -n $XTRABACKUP_PID ]];then
+ if check_pid $XTRABACKUP_PID
+ then
+ wsrep_log_error "xtrabackup process is still running. Killing... "
+ kill_xtrabackup
+ fi
+
+ rm -f $XTRABACKUP_PID
+ fi
+ rm -f ${DATA}/${IST_FILE}
+
+ if [[ -n $progress && -p $progress ]];then
+ wsrep_log_info "Cleaning up fifo file $progress"
+ rm $progress
+ fi
+}
+
+kill_xtrabackup()
+{
+ local PID=$(cat $XTRABACKUP_PID)
+ [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
+ rm -f "$XTRABACKUP_PID"
+}
+
+setup_ports()
+{
+ if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
+ SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
+ REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
+ lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }')
+ else
+ SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }')
+ fi
+}
+
+# waits ~10 seconds for nc to open the port and then reports ready
+# (regardless of timeout)
+wait_for_listen()
+{
+ local PORT=$1
+ local ADDR=$2
+ local MODULE=$3
+ for i in {1..50}
+ do
+ ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break
+ sleep 0.2
+ done
+ if [[ $incremental -eq 1 ]];then
+ echo "ready ${ADDR}/${MODULE}/$lsn"
+ else
+ echo "ready ${ADDR}/${MODULE}"
+ fi
+}
+
+check_extra()
+{
+ local use_socket=1
+ if [[ $uextra -eq 1 ]];then
+ if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then
+ local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2)
+ if [[ -n $eport ]];then
+ # Xtrabackup works only locally.
+ # Hence, setting host to 127.0.0.1 unconditionally.
+ wsrep_log_info "SST through extra_port $eport"
+ INNOEXTRA+=" --host=127.0.0.1 --port=$eport "
+ use_socket=0
+ else
+ wsrep_log_error "Extra port $eport null, failing"
+ exit 1
+ fi
+ else
+ wsrep_log_info "Thread pool not set, ignore the option use_extra"
+ fi
+ fi
+ if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then
+ INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}"
+ fi
+}
+
+recv_joiner()
+{
+ local dir=$1
+ local msg=$2
+
+ pushd ${dir} 1>/dev/null
+ set +e
+ timeit "$msg" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
+ set -e
+ popd 1>/dev/null
+
+
+ for ecode in "${RC[@]}";do
+ if [[ $ecode -ne 0 ]];then
+ wsrep_log_error "Error while getting data from donor node: " \
+ "exit codes: ${RC[@]}"
+ exit 32
+ fi
+ done
+
+ if [ ! -r "${MAGIC_FILE}" ];then
+ # this message should cause joiner to abort
+ wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'"
+ wsrep_log_info "Contents of datadir"
+ wsrep_log_info "$(ls -l ${dir}/*)"
+ exit 32
+ fi
+}
+
+
+send_donor()
+{
+ local dir=$1
+ local msg=$2
+
+ pushd ${dir} 1>/dev/null
+ set +e
+ timeit "$msg" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
+ set -e
+ popd 1>/dev/null
+
+
+ for ecode in "${RC[@]}";do
+ if [[ $ecode -ne 0 ]];then
+ wsrep_log_error "Error while getting data from donor node: " \
+ "exit codes: ${RC[@]}"
+ exit 32
+ fi
+ done
+
+}
+
+if [[ ! -x `which innobackupex` ]];then
+ wsrep_log_error "innobackupex not in path: $PATH"
+ exit 2
+fi
+
+rm -f "${MAGIC_FILE}"
+
+if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then
+ wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}"
+ exit 22
+fi
+
+read_cnf
+setup_ports
+get_stream
+get_transfer
+
+if ${INNOBACKUPEX_BIN} /tmp --help | grep -q -- '--version-check'; then
+ disver="--no-version-check"
+fi
+
+
+INNOEXTRA=""
+INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log"
+INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log"
+INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log"
+
+if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
+then
+ trap cleanup_donor EXIT
+
+ if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
+ then
+
+ TMPDIR="${TMPDIR:-/tmp}"
+
+ if [ "${AUTH[0]}" != "(null)" ]; then
+ INNOEXTRA+=" --user=${AUTH[0]}"
+ fi
+
+ if [ ${#AUTH[*]} -eq 2 ]; then
+ INNOEXTRA+=" --password=${AUTH[1]}"
+ elif [ "${AUTH[0]}" != "(null)" ]; then
+ # Empty password, used for testing, debugging etc.
+ INNOEXTRA+=" --password="
+ fi
+
+ get_keys
+ if [[ $encrypt -eq 1 ]];then
+ if [[ -n $ekey ]];then
+ INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey "
+ else
+ INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile "
+ fi
+ fi
+
+ if [[ -n $lsn ]];then
+ INNOEXTRA+=" --incremental --incremental-lsn=$lsn "
+ fi
+
+ check_extra
+
+ wsrep_log_info "Streaming GTID file before SST"
+
+ echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}"
+
+ ttcmd="$tcmd"
+
+ if [[ $encrypt -eq 1 ]];then
+ if [[ -n $scomp ]];then
+ tcmd=" $ecmd | $scomp | $tcmd "
+ else
+ tcmd=" $ecmd | $tcmd "
+ fi
+ elif [[ -n $scomp ]];then
+ tcmd=" $scomp | $tcmd "
+ fi
+
+
+ send_donor $DATA "${stagemsg}-gtid"
+
+ tcmd="$ttcmd"
+ if [[ -n $progress ]];then
+ get_footprint
+ tcmd="$pcmd | $tcmd"
+ elif [[ -n $rlimit ]];then
+ adjust_progress
+ tcmd="$pcmd | $tcmd"
+ fi
+
+ wsrep_log_info "Sleeping before data transfer for SST"
+ sleep 10
+
+ wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT:-4444}"
+
+ if [[ -n $scomp ]];then
+ tcmd="$scomp | $tcmd"
+ fi
+
+ set +e
+ timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
+ set -e
+
+ if [ ${RC[0]} -ne 0 ]; then
+ wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \
+ "Check ${DATA}/innobackup.backup.log"
+ exit 22
+ elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
+ wsrep_log_error "$tcmd finished with error: ${RC[1]}"
+ exit 22
+ fi
+
+ # innobackupex implicitly writes PID to fixed location in ${TMPDIR}
+ XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid"
+
+
+ else # BYPASS FOR IST
+
+ wsrep_log_info "Bypassing the SST for IST"
+ echo "continue" # now server can resume updating data
+ echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}"
+ echo "1" > "${DATA}/${IST_FILE}"
+ get_keys
+ if [[ $encrypt -eq 1 ]];then
+ if [[ -n $scomp ]];then
+ tcmd=" $ecmd | $scomp | $tcmd "
+ else
+ tcmd=" $ecmd | $tcmd "
+ fi
+ elif [[ -n $scomp ]];then
+ tcmd=" $scomp | $tcmd "
+ fi
+ strmcmd+=" \${IST_FILE}"
+
+ send_donor $DATA "${stagemsg}-IST"
+
+ fi
+
+ echo "done ${WSREP_SST_OPT_GTID}"
+ wsrep_log_info "Total time on donor: $totime seconds"
+
+elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ]
+then
+ [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
+ [[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE
+
+ if [[ $speciald -eq 1 ]];then
+ wsrep_log_info "WARNING: sst-special-dirs feature requires PXC 2.1.6 or latter."
+ fi
+
+ if [[ $speciald -eq 1 ]];then
+ ib_home_dir=$(parse_cnf mysqld innodb-data-home-dir "")
+ ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "")
+ if [[ -z $ib_home_dir && -z $ib_log_dir ]];then
+ speciald=0
+ fi
+ fi
+
+ stagemsg="Joiner-Recv"
+
+ if [[ ! -e ${DATA}/ibdata1 ]];then
+ incremental=0
+ fi
+
+ if [[ $incremental -eq 1 ]];then
+ wsrep_log_info "Incremental SST enabled: NOT SUPPORTED yet"
+ lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ')
+ wsrep_log_info "Recovered LSN: $lsn"
+ fi
+
+ sencrypted=1
+ nthreads=1
+
+ MODULE="xtrabackup_sst"
+
+ rm -f "${DATA}/${IST_FILE}"
+
+ # May need xtrabackup_checkpoints later on
+ rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile
+
+ ADDR=${WSREP_SST_OPT_ADDR}
+ if [ -z "${SST_PORT}" ]
+ then
+ SST_PORT=4444
+ ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}"
+ fi
+
+ wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} &
+
+ trap sig_joiner_cleanup HUP PIPE INT TERM
+ trap cleanup_joiner EXIT
+
+ if [[ -n $progress ]];then
+ adjust_progress
+ tcmd+=" | $pcmd"
+ fi
+
+ if [[ $incremental -eq 1 ]];then
+ BDATA=$DATA
+ DATA=$(mktemp -d)
+ MAGIC_FILE="${DATA}/${INFO_FILE}"
+ fi
+
+ get_keys
+ if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
+ if [[ -n $sdecomp ]];then
+ strmcmd=" $sdecomp | $ecmd | $strmcmd"
+ else
+ strmcmd=" $ecmd | $strmcmd"
+ fi
+ elif [[ -n $sdecomp ]];then
+ strmcmd=" $sdecomp | $strmcmd"
+ fi
+
+ STATDIR=$(mktemp -d)
+ MAGIC_FILE="${STATDIR}/${INFO_FILE}"
+ recv_joiner $STATDIR "${stagemsg}-gtid" 1
+
+ if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null
+ then
+ wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly."
+ exit 32
+ fi
+
+ if [ ! -r "${STATDIR}/${IST_FILE}" ]
+ then
+ wsrep_log_info "Proceeding with SST"
+
+ if [[ $speciald -eq 1 && -d ${DATA}/.sst ]];then
+ wsrep_log_info "WARNING: Stale temporary SST directory: ${DATA}/.sst from previous SST"
+ fi
+
+ if [[ $incremental -ne 1 ]];then
+ if [[ $speciald -eq 1 ]];then
+ wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories"
+ find $ib_home_dir $ib_log_dir $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+
+ else
+ wsrep_log_info "Cleaning the existing datadir"
+ find $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+
+ fi
+ tempdir=$(parse_cnf mysqld log-bin "")
+ if [[ -n ${tempdir:-} ]];then
+ binlog_dir=$(dirname $tempdir)
+ binlog_file=$(basename $tempdir)
+ if [[ -n ${binlog_dir:-} && $binlog_dir != '.' && $binlog_dir != $DATA ]];then
+ pattern="$binlog_dir/$binlog_file\.[0-9]+$"
+ wsrep_log_info "Cleaning the binlog directory $binlog_dir as well"
+ find $binlog_dir -maxdepth 1 -type f -regex $pattern -exec rm -fv {} 1>&2 \+
+ rm $binlog_dir/*.index || true
+ fi
+ fi
+
+ else
+ wsrep_log_info "Removing existing ib_logfile files"
+ rm -f ${BDATA}/ib_logfile*
+ fi
+
+
+ if [[ $speciald -eq 1 ]];then
+ mkdir -p ${DATA}/.sst
+ TDATA=${DATA}
+ DATA="${DATA}/.sst"
+ fi
+
+
+ MAGIC_FILE="${DATA}/${INFO_FILE}"
+ recv_joiner $DATA "${stagemsg}-SST" 0
+
+ get_proc
+
+ # Rebuild indexes for compact backups
+ if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then
+ wsrep_log_info "Index compaction detected"
+ rebuild=1
+ fi
+
+ if [[ $rebuild -eq 1 ]];then
+ nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc)
+ wsrep_log_info "Rebuilding during prepare with $nthreads threads"
+ rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads"
+ fi
+
+ if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then
+
+ wsrep_log_info "Compressed qpress files found"
+
+ if [[ ! -x `which qpress` ]];then
+ wsrep_log_error "qpress not found in path: $PATH"
+ exit 22
+ fi
+
+ if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then
+ count=$(find ${DATA} -type f -name '*.qp' | wc -l)
+ count=$(( count*2 ))
+ if pv --help | grep -q FORMAT;then
+ pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'"
+ else
+ pvopts="-f -s $count -l -N Decompression"
+ fi
+ pcmd="pv $pvopts"
+ adjust_progress
+ dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d"
+ else
+ dcmd="xargs -n 2 qpress -T${nproc}d"
+ fi
+
+
+ # Decompress the qpress files
+ wsrep_log_info "Decompression with $nproc threads"
+ timeit "Joiner-Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd"
+ extcode=$?
+
+ if [[ $extcode -eq 0 ]];then
+ wsrep_log_info "Removing qpress files after decompression"
+ find ${DATA} -type f -name '*.qp' -delete
+ if [[ $? -ne 0 ]];then
+ wsrep_log_error "Something went wrong with deletion of qpress files. Investigate"
+ fi
+ else
+ wsrep_log_error "Decompression failed. Exit code: $extcode"
+ exit 22
+ fi
+ fi
+
+ if [[ $incremental -eq 1 ]];then
+ # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues.
+ INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \
+ --ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log"
+ fi
+
+ wsrep_log_info "Preparing the backup at ${DATA}"
+ timeit "Xtrabackup prepare stage" "$INNOAPPLY"
+
+ if [ $? -ne 0 ];
+ then
+ wsrep_log_error "${INNOBACKUPEX_BIN} apply finished with errors. Check ${DATA}/innobackup.prepare.log"
+ exit 22
+ fi
+
+ if [[ $speciald -eq 1 ]];then
+ MAGIC_FILE="${TDATA}/${INFO_FILE}"
+ set +e
+ rm $TDATA/innobackup.prepare.log $TDATA/innobackup.move.log
+ set -e
+ wsrep_log_info "Moving the backup to ${TDATA}"
+ timeit "Xtrabackup move stage" "$INNOMOVE"
+ if [[ $? -eq 0 ]];then
+ wsrep_log_info "Move successful, removing ${DATA}"
+ rm -rf $DATA
+ DATA=${TDATA}
+ else
+ wsrep_log_error "Move failed, keeping ${DATA} for further diagnosis"
+ wsrep_log_error "Check ${DATA}/innobackup.move.log for details"
+ fi
+ fi
+
+ if [[ $incremental -eq 1 ]];then
+ wsrep_log_info "Cleaning up ${DATA} after incremental SST"
+ [[ -d ${DATA} ]] && rm -rf ${DATA}
+ DATA=$BDATA
+ fi
+
+ else
+ wsrep_log_info "${IST_FILE} received from donor: Running IST"
+ fi
+
+ if [[ ! -r ${MAGIC_FILE} ]];then
+ wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable"
+ exit 2
+ fi
+
+ cat "${MAGIC_FILE}" # output UUID:seqno
+ wsrep_log_info "Total time on joiner: $totime seconds"
+fi
+
+exit 0
diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh
new file mode 100644
index 00000000000..59017fff8df
--- /dev/null
+++ b/scripts/wsrep_sst_xtrabackup-v2.sh
@@ -0,0 +1,879 @@
+#!/bin/bash -ue
+# Copyright (C) 2013 Percona Inc
+#
+# 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; see the file COPYING. If not, write to the
+# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston
+# MA 02110-1301 USA.
+
+# Documentation: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
+# Make sure to read that before proceeding!
+
+
+
+
+. $(dirname $0)/wsrep_sst_common
+
+ealgo=""
+ekey=""
+ekeyfile=""
+encrypt=0
+nproc=1
+ecode=0
+XTRABACKUP_PID=""
+SST_PORT=""
+REMOTEIP=""
+tcert=""
+tpem=""
+tkey=""
+sockopt=""
+progress=""
+ttime=0
+totime=0
+lsn=""
+incremental=0
+ecmd=""
+rlimit=""
+# Initially
+stagemsg="${WSREP_SST_OPT_ROLE}"
+cpat=""
+speciald=0
+ib_home_dir=""
+ib_log_dir=""
+
+sfmt="tar"
+strmcmd=""
+tfmt=""
+tcmd=""
+rebuild=0
+rebuildcmd=""
+payload=0
+pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' "
+pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE "
+STATDIR=""
+uextra=0
+disver=""
+
+scomp=""
+sdecomp=""
+
+if which pv &>/dev/null && pv --help | grep -q FORMAT;then
+ pvopts+=$pvformat
+fi
+pcmd="pv $pvopts"
+declare -a RC
+
+INNOBACKUPEX_BIN=innobackupex
+readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
+DATA="${WSREP_SST_OPT_DATA}"
+INFO_FILE="xtrabackup_galera_info"
+IST_FILE="xtrabackup_ist"
+MAGIC_FILE="${DATA}/${INFO_FILE}"
+
+# Setting the path for ss and ip
+export PATH="/usr/sbin:/sbin:$PATH"
+
+timeit(){
+ local stage=$1
+ shift
+ local cmd="$@"
+ local x1 x2 took extcode
+
+ if [[ $ttime -eq 1 ]];then
+ x1=$(date +%s)
+ wsrep_log_info "Evaluating $cmd"
+ eval "$cmd"
+ extcode=$?
+ x2=$(date +%s)
+ took=$(( x2-x1 ))
+ wsrep_log_info "NOTE: $stage took $took seconds"
+ totime=$(( totime+took ))
+ else
+ wsrep_log_info "Evaluating $cmd"
+ eval "$cmd"
+ extcode=$?
+ fi
+ return $extcode
+}
+
+get_keys()
+{
+ # $encrypt -eq 1 is for internal purposes only
+ if [[ $encrypt -ge 2 || $encrypt -eq -1 ]];then
+ return
+ fi
+
+ if [[ $encrypt -eq 0 ]];then
+ if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then
+ wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html "
+ fi
+ return
+ fi
+
+ if [[ $sfmt == 'tar' ]];then
+ wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format"
+ encrypt=-1
+ return
+ fi
+
+ wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4"
+
+ if [[ -z $ealgo ]];then
+ wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out"
+ exit 3
+ fi
+
+ if [[ -z $ekey && ! -r $ekeyfile ]];then
+ wsrep_log_error "FATAL: Either key or keyfile must be readable"
+ exit 3
+ fi
+
+ if [[ -z $ekey ]];then
+ ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile"
+ else
+ ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey"
+ fi
+
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ ecmd+=" -d"
+ fi
+
+ stagemsg+="-XB-Encrypted"
+}
+
+get_transfer()
+{
+ if [[ -z $SST_PORT ]];then
+ TSST_PORT=4444
+ else
+ TSST_PORT=$SST_PORT
+ fi
+
+ if [[ $tfmt == 'nc' ]];then
+ if [[ ! -x `which nc` ]];then
+ wsrep_log_error "nc(netcat) not found in path: $PATH"
+ exit 2
+ fi
+ wsrep_log_info "Using netcat as streamer"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ tcmd="nc -dl ${TSST_PORT}"
+ else
+ tcmd="nc ${REMOTEIP} ${TSST_PORT}"
+ fi
+ else
+ tfmt='socat'
+ wsrep_log_info "Using socat as streamer"
+ if [[ ! -x `which socat` ]];then
+ wsrep_log_error "socat not found in path: $PATH"
+ exit 2
+ fi
+
+ if [[ $encrypt -eq 2 || $encrypt -eq 3 ]] && ! socat -V | grep -q WITH_OPENSSL;then
+ wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer"
+ encrypt=-1
+ fi
+
+ if [[ $encrypt -eq 2 ]];then
+ wsrep_log_info "Using openssl based encryption with socat: with crt and pem"
+ if [[ -z $tpem || -z $tcert ]];then
+ wsrep_log_error "Both PEM and CRT files required"
+ exit 22
+ fi
+ stagemsg+="-OpenSSL-Encrypted-2"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert"
+ tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio"
+ else
+ wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert"
+ tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}"
+ fi
+ elif [[ $encrypt -eq 3 ]];then
+ wsrep_log_info "Using openssl based encryption with socat: with key and crt"
+ if [[ -z $tpem || -z $tkey ]];then
+ wsrep_log_error "Both certificate and key files required"
+ exit 22
+ fi
+ stagemsg+="-OpenSSL-Encrypted-3"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ wsrep_log_info "Decrypting with certificate $tpem, key $tkey"
+ tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,key=${tkey},verify=0${sockopt} stdio"
+ else
+ wsrep_log_info "Encrypting with certificate $tpem, key $tkey"
+ tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,key=${tkey},verify=0${sockopt}"
+ fi
+
+ else
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio"
+ else
+ tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}"
+ fi
+ fi
+ fi
+
+}
+
+parse_cnf()
+{
+ local group=$1
+ local var=$2
+ reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-)
+ if [[ -z $reval ]];then
+ [[ -n $3 ]] && reval=$3
+ fi
+ echo $reval
+}
+
+get_footprint()
+{
+ pushd $WSREP_SST_OPT_DATA 1>/dev/null
+ payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }')
+ if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then
+ # QuickLZ has around 50% compression ratio
+ # When compression/compaction used, the progress is only an approximate.
+ payload=$(( payload*1/2 ))
+ fi
+ popd 1>/dev/null
+ pcmd+=" -s $payload"
+ adjust_progress
+}
+
+adjust_progress()
+{
+ if [[ -n $progress && $progress != '1' ]];then
+ if [[ -e $progress ]];then
+ pcmd+=" 2>>$progress"
+ else
+ pcmd+=" 2>$progress"
+ fi
+ elif [[ -z $progress && -n $rlimit ]];then
+ # When rlimit is non-zero
+ pcmd="pv -q"
+ fi
+
+ if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then
+ wsrep_log_info "Rate-limiting SST to $rlimit"
+ pcmd+=" -L \$rlimit"
+ fi
+}
+
+read_cnf()
+{
+ sfmt=$(parse_cnf sst streamfmt "xbstream")
+ tfmt=$(parse_cnf sst transferfmt "socat")
+ tcert=$(parse_cnf sst tca "")
+ tpem=$(parse_cnf sst tcert "")
+ tkey=$(parse_cnf sst tkey "")
+ encrypt=$(parse_cnf sst encrypt 0)
+ sockopt=$(parse_cnf sst sockopt "")
+ progress=$(parse_cnf sst progress "")
+ rebuild=$(parse_cnf sst rebuild 0)
+ ttime=$(parse_cnf sst time 0)
+ cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$')
+ incremental=$(parse_cnf sst incremental 0)
+ ealgo=$(parse_cnf xtrabackup encrypt "")
+ ekey=$(parse_cnf xtrabackup encrypt-key "")
+ ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "")
+ scomp=$(parse_cnf sst compressor "")
+ sdecomp=$(parse_cnf sst decompressor "")
+
+
+ # Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
+ if [[ -z $ealgo ]];then
+ ealgo=$(parse_cnf sst encrypt-algo "")
+ ekey=$(parse_cnf sst encrypt-key "")
+ ekeyfile=$(parse_cnf sst encrypt-key-file "")
+ fi
+ rlimit=$(parse_cnf sst rlimit "")
+ uextra=$(parse_cnf sst use_extra 0)
+ speciald=$(parse_cnf sst sst-special-dirs 1)
+ iopts=$(parse_cnf sst inno-backup-opts "")
+ iapts=$(parse_cnf sst inno-apply-opts "")
+ impts=$(parse_cnf sst inno-move-opts "")
+}
+
+get_stream()
+{
+ if [[ $sfmt == 'xbstream' ]];then
+ wsrep_log_info "Streaming with xbstream"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ strmcmd="xbstream -x"
+ else
+ strmcmd="xbstream -c \${INFO_FILE}"
+ fi
+ else
+ sfmt="tar"
+ wsrep_log_info "Streaming with tar"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ strmcmd="tar xfi - "
+ else
+ strmcmd="tar cf - \${INFO_FILE} "
+ fi
+
+ fi
+}
+
+get_proc()
+{
+ set +e
+ nproc=$(grep -c processor /proc/cpuinfo)
+ [[ -z $nproc || $nproc -eq 0 ]] && nproc=1
+ set -e
+}
+
+sig_joiner_cleanup()
+{
+ wsrep_log_error "Removing $MAGIC_FILE file due to signal"
+ rm -f "$MAGIC_FILE"
+}
+
+cleanup_joiner()
+{
+ # Since this is invoked just after exit NNN
+ local estatus=$?
+ if [[ $estatus -ne 0 ]];then
+ wsrep_log_error "Cleanup after exit with status:$estatus"
+ fi
+ if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
+ wsrep_log_info "Removing the sst_in_progress file"
+ wsrep_cleanup_progress_file
+ fi
+ if [[ -n $progress && -p $progress ]];then
+ wsrep_log_info "Cleaning up fifo file $progress"
+ rm $progress
+ fi
+ if [[ -n ${STATDIR:-} ]];then
+ [[ -d $STATDIR ]] && rm -rf $STATDIR
+ fi
+}
+
+check_pid()
+{
+ local pid_file="$1"
+ [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1
+}
+
+cleanup_donor()
+{
+ # Since this is invoked just after exit NNN
+ local estatus=$?
+ if [[ $estatus -ne 0 ]];then
+ wsrep_log_error "Cleanup after exit with status:$estatus"
+ fi
+
+ if [[ -n $XTRABACKUP_PID ]];then
+ if check_pid $XTRABACKUP_PID
+ then
+ wsrep_log_error "xtrabackup process is still running. Killing... "
+ kill_xtrabackup
+ fi
+
+ rm -f $XTRABACKUP_PID
+ fi
+ rm -f ${DATA}/${IST_FILE}
+
+ if [[ -n $progress && -p $progress ]];then
+ wsrep_log_info "Cleaning up fifo file $progress"
+ rm $progress
+ fi
+}
+
+kill_xtrabackup()
+{
+ local PID=$(cat $XTRABACKUP_PID)
+ [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
+ rm -f "$XTRABACKUP_PID"
+}
+
+setup_ports()
+{
+ if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
+ SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
+ REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
+ lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }')
+ else
+ SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }')
+ fi
+}
+
+# waits ~10 seconds for nc to open the port and then reports ready
+# (regardless of timeout)
+wait_for_listen()
+{
+ local PORT=$1
+ local ADDR=$2
+ local MODULE=$3
+ for i in {1..50}
+ do
+ ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break
+ sleep 0.2
+ done
+ if [[ $incremental -eq 1 ]];then
+ echo "ready ${ADDR}/${MODULE}/$lsn"
+ else
+ echo "ready ${ADDR}/${MODULE}"
+ fi
+}
+
+check_extra()
+{
+ local use_socket=1
+ if [[ $uextra -eq 1 ]];then
+ if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then
+ local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2)
+ if [[ -n $eport ]];then
+ # Xtrabackup works only locally.
+ # Hence, setting host to 127.0.0.1 unconditionally.
+ wsrep_log_info "SST through extra_port $eport"
+ INNOEXTRA+=" --host=127.0.0.1 --port=$eport "
+ use_socket=0
+ else
+ wsrep_log_error "Extra port $eport null, failing"
+ exit 1
+ fi
+ else
+ wsrep_log_info "Thread pool not set, ignore the option use_extra"
+ fi
+ fi
+ if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then
+ INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}"
+ fi
+}
+
+recv_joiner()
+{
+ local dir=$1
+ local msg=$2
+
+ pushd ${dir} 1>/dev/null
+ set +e
+ timeit "$msg" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
+ set -e
+ popd 1>/dev/null
+
+
+ for ecode in "${RC[@]}";do
+ if [[ $ecode -ne 0 ]];then
+ wsrep_log_error "Error while getting data from donor node: " \
+ "exit codes: ${RC[@]}"
+ exit 32
+ fi
+ done
+
+ if [ ! -r "${MAGIC_FILE}" ];then
+ # this message should cause joiner to abort
+ wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'"
+ wsrep_log_info "Contents of datadir"
+ wsrep_log_info "$(ls -l ${dir}/*)"
+ exit 32
+ fi
+}
+
+
+send_donor()
+{
+ local dir=$1
+ local msg=$2
+
+ pushd ${dir} 1>/dev/null
+ set +e
+ timeit "$msg" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
+ set -e
+ popd 1>/dev/null
+
+
+ for ecode in "${RC[@]}";do
+ if [[ $ecode -ne 0 ]];then
+ wsrep_log_error "Error while getting data from donor node: " \
+ "exit codes: ${RC[@]}"
+ exit 32
+ fi
+ done
+
+}
+
+if [[ ! -x `which innobackupex` ]];then
+ wsrep_log_error "innobackupex not in path: $PATH"
+ exit 2
+fi
+
+rm -f "${MAGIC_FILE}"
+
+if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then
+ wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}"
+ exit 22
+fi
+
+read_cnf
+setup_ports
+get_stream
+get_transfer
+
+if ${INNOBACKUPEX_BIN} /tmp --help | grep -q -- '--version-check'; then
+ disver="--no-version-check"
+fi
+
+
+INNOEXTRA=""
+INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log"
+INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log"
+INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log"
+
+if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
+then
+ trap cleanup_donor EXIT
+
+ if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
+ then
+
+ TMPDIR="${TMPDIR:-/tmp}"
+
+ if [ "${AUTH[0]}" != "(null)" ]; then
+ INNOEXTRA+=" --user=${AUTH[0]}"
+ fi
+
+ if [ ${#AUTH[*]} -eq 2 ]; then
+ INNOEXTRA+=" --password=${AUTH[1]}"
+ elif [ "${AUTH[0]}" != "(null)" ]; then
+ # Empty password, used for testing, debugging etc.
+ INNOEXTRA+=" --password="
+ fi
+
+ get_keys
+ if [[ $encrypt -eq 1 ]];then
+ if [[ -n $ekey ]];then
+ INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey "
+ else
+ INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile "
+ fi
+ fi
+
+ if [[ -n $lsn ]];then
+ INNOEXTRA+=" --incremental --incremental-lsn=$lsn "
+ fi
+
+ check_extra
+
+ wsrep_log_info "Streaming GTID file before SST"
+
+ echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}"
+
+ ttcmd="$tcmd"
+
+ if [[ $encrypt -eq 1 ]];then
+ if [[ -n $scomp ]];then
+ tcmd=" $ecmd | $scomp | $tcmd "
+ else
+ tcmd=" $ecmd | $tcmd "
+ fi
+ elif [[ -n $scomp ]];then
+ tcmd=" $scomp | $tcmd "
+ fi
+
+
+ send_donor $DATA "${stagemsg}-gtid"
+
+ tcmd="$ttcmd"
+ if [[ -n $progress ]];then
+ get_footprint
+ tcmd="$pcmd | $tcmd"
+ elif [[ -n $rlimit ]];then
+ adjust_progress
+ tcmd="$pcmd | $tcmd"
+ fi
+
+ wsrep_log_info "Sleeping before data transfer for SST"
+ sleep 10
+
+ wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT:-4444}"
+
+ if [[ -n $scomp ]];then
+ tcmd="$scomp | $tcmd"
+ fi
+
+ set +e
+ timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
+ set -e
+
+ if [ ${RC[0]} -ne 0 ]; then
+ wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \
+ "Check ${DATA}/innobackup.backup.log"
+ exit 22
+ elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
+ wsrep_log_error "$tcmd finished with error: ${RC[1]}"
+ exit 22
+ fi
+
+ # innobackupex implicitly writes PID to fixed location in ${TMPDIR}
+ XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid"
+
+
+ else # BYPASS FOR IST
+
+ wsrep_log_info "Bypassing the SST for IST"
+ echo "continue" # now server can resume updating data
+ echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}"
+ echo "1" > "${DATA}/${IST_FILE}"
+ get_keys
+ if [[ $encrypt -eq 1 ]];then
+ if [[ -n $scomp ]];then
+ tcmd=" $ecmd | $scomp | $tcmd "
+ else
+ tcmd=" $ecmd | $tcmd "
+ fi
+ elif [[ -n $scomp ]];then
+ tcmd=" $scomp | $tcmd "
+ fi
+ strmcmd+=" \${IST_FILE}"
+
+ send_donor $DATA "${stagemsg}-IST"
+
+ fi
+
+ echo "done ${WSREP_SST_OPT_GTID}"
+ wsrep_log_info "Total time on donor: $totime seconds"
+
+elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ]
+then
+ [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
+ [[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE
+
+ if [[ $speciald -eq 1 ]];then
+ wsrep_log_info "WARNING: sst-special-dirs feature requires PXC 2.1.6 or latter."
+ fi
+
+ if [[ $speciald -eq 1 ]];then
+ ib_home_dir=$(parse_cnf mysqld innodb-data-home-dir "")
+ ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "")
+ if [[ -z $ib_home_dir && -z $ib_log_dir ]];then
+ speciald=0
+ fi
+ fi
+
+ stagemsg="Joiner-Recv"
+
+ if [[ ! -e ${DATA}/ibdata1 ]];then
+ incremental=0
+ fi
+
+ if [[ $incremental -eq 1 ]];then
+ wsrep_log_info "Incremental SST enabled: NOT SUPPORTED yet"
+ lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ')
+ wsrep_log_info "Recovered LSN: $lsn"
+ fi
+
+ sencrypted=1
+ nthreads=1
+
+ MODULE="xtrabackup_sst"
+
+ rm -f "${DATA}/${IST_FILE}"
+
+ # May need xtrabackup_checkpoints later on
+ rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile
+
+ ADDR=${WSREP_SST_OPT_ADDR}
+ if [ -z "${SST_PORT}" ]
+ then
+ SST_PORT=4444
+ ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}"
+ fi
+
+ wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} &
+
+ trap sig_joiner_cleanup HUP PIPE INT TERM
+ trap cleanup_joiner EXIT
+
+ if [[ -n $progress ]];then
+ adjust_progress
+ tcmd+=" | $pcmd"
+ fi
+
+ if [[ $incremental -eq 1 ]];then
+ BDATA=$DATA
+ DATA=$(mktemp -d)
+ MAGIC_FILE="${DATA}/${INFO_FILE}"
+ fi
+
+ get_keys
+ if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
+ if [[ -n $sdecomp ]];then
+ strmcmd=" $sdecomp | $ecmd | $strmcmd"
+ else
+ strmcmd=" $ecmd | $strmcmd"
+ fi
+ elif [[ -n $sdecomp ]];then
+ strmcmd=" $sdecomp | $strmcmd"
+ fi
+
+ STATDIR=$(mktemp -d)
+ MAGIC_FILE="${STATDIR}/${INFO_FILE}"
+ recv_joiner $STATDIR "${stagemsg}-gtid" 1
+
+ if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null
+ then
+ wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly."
+ exit 32
+ fi
+
+ if [ ! -r "${STATDIR}/${IST_FILE}" ]
+ then
+ wsrep_log_info "Proceeding with SST"
+
+ if [[ $speciald -eq 1 && -d ${DATA}/.sst ]];then
+ wsrep_log_info "WARNING: Stale temporary SST directory: ${DATA}/.sst from previous SST"
+ fi
+
+ if [[ $incremental -ne 1 ]];then
+ if [[ $speciald -eq 1 ]];then
+ wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories"
+ find $ib_home_dir $ib_log_dir $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+
+ else
+ wsrep_log_info "Cleaning the existing datadir"
+ find $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+
+ fi
+ tempdir=$(parse_cnf mysqld log-bin "")
+ if [[ -n ${tempdir:-} ]];then
+ binlog_dir=$(dirname $tempdir)
+ binlog_file=$(basename $tempdir)
+ if [[ -n ${binlog_dir:-} && $binlog_dir != '.' && $binlog_dir != $DATA ]];then
+ pattern="$binlog_dir/$binlog_file\.[0-9]+$"
+ wsrep_log_info "Cleaning the binlog directory $binlog_dir as well"
+ find $binlog_dir -maxdepth 1 -type f -regex $pattern -exec rm -fv {} 1>&2 \+
+ rm $binlog_dir/*.index || true
+ fi
+ fi
+
+ else
+ wsrep_log_info "Removing existing ib_logfile files"
+ rm -f ${BDATA}/ib_logfile*
+ fi
+
+
+ if [[ $speciald -eq 1 ]];then
+ mkdir -p ${DATA}/.sst
+ TDATA=${DATA}
+ DATA="${DATA}/.sst"
+ fi
+
+
+ MAGIC_FILE="${DATA}/${INFO_FILE}"
+ recv_joiner $DATA "${stagemsg}-SST" 0
+
+ get_proc
+
+ # Rebuild indexes for compact backups
+ if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then
+ wsrep_log_info "Index compaction detected"
+ rebuild=1
+ fi
+
+ if [[ $rebuild -eq 1 ]];then
+ nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc)
+ wsrep_log_info "Rebuilding during prepare with $nthreads threads"
+ rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads"
+ fi
+
+ if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then
+
+ wsrep_log_info "Compressed qpress files found"
+
+ if [[ ! -x `which qpress` ]];then
+ wsrep_log_error "qpress not found in path: $PATH"
+ exit 22
+ fi
+
+ if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then
+ count=$(find ${DATA} -type f -name '*.qp' | wc -l)
+ count=$(( count*2 ))
+ if pv --help | grep -q FORMAT;then
+ pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'"
+ else
+ pvopts="-f -s $count -l -N Decompression"
+ fi
+ pcmd="pv $pvopts"
+ adjust_progress
+ dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d"
+ else
+ dcmd="xargs -n 2 qpress -T${nproc}d"
+ fi
+
+
+ # Decompress the qpress files
+ wsrep_log_info "Decompression with $nproc threads"
+ timeit "Joiner-Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd"
+ extcode=$?
+
+ if [[ $extcode -eq 0 ]];then
+ wsrep_log_info "Removing qpress files after decompression"
+ find ${DATA} -type f -name '*.qp' -delete
+ if [[ $? -ne 0 ]];then
+ wsrep_log_error "Something went wrong with deletion of qpress files. Investigate"
+ fi
+ else
+ wsrep_log_error "Decompression failed. Exit code: $extcode"
+ exit 22
+ fi
+ fi
+
+ if [[ $incremental -eq 1 ]];then
+ # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues.
+ INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \
+ --ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log"
+ fi
+
+ wsrep_log_info "Preparing the backup at ${DATA}"
+ timeit "Xtrabackup prepare stage" "$INNOAPPLY"
+
+ if [ $? -ne 0 ];
+ then
+ wsrep_log_error "${INNOBACKUPEX_BIN} apply finished with errors. Check ${DATA}/innobackup.prepare.log"
+ exit 22
+ fi
+
+ if [[ $speciald -eq 1 ]];then
+ MAGIC_FILE="${TDATA}/${INFO_FILE}"
+ set +e
+ rm $TDATA/innobackup.prepare.log $TDATA/innobackup.move.log
+ set -e
+ wsrep_log_info "Moving the backup to ${TDATA}"
+ timeit "Xtrabackup move stage" "$INNOMOVE"
+ if [[ $? -eq 0 ]];then
+ wsrep_log_info "Move successful, removing ${DATA}"
+ rm -rf $DATA
+ DATA=${TDATA}
+ else
+ wsrep_log_error "Move failed, keeping ${DATA} for further diagnosis"
+ wsrep_log_error "Check ${DATA}/innobackup.move.log for details"
+ fi
+ fi
+
+ if [[ $incremental -eq 1 ]];then
+ wsrep_log_info "Cleaning up ${DATA} after incremental SST"
+ [[ -d ${DATA} ]] && rm -rf ${DATA}
+ DATA=$BDATA
+ fi
+
+ else
+ wsrep_log_info "${IST_FILE} received from donor: Running IST"
+ fi
+
+ if [[ ! -r ${MAGIC_FILE} ]];then
+ wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable"
+ exit 2
+ fi
+
+ cat "${MAGIC_FILE}" # output UUID:seqno
+ wsrep_log_info "Total time on joiner: $totime seconds"
+fi
+
+exit 0
diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh
index 75ffe3eb15f..01c9c3f3049 100644
--- a/scripts/wsrep_sst_xtrabackup.sh
+++ b/scripts/wsrep_sst_xtrabackup.sh
@@ -15,25 +15,11 @@
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston
# MA 02110-1301 USA.
-#############################################################################################################
-# This is a reference script for Percona XtraBackup-based state snapshot transfer #
-# Dependencies: (depending on configuration) #
-# xbcrypt for encryption/decryption. #
-# qpress for decompression. Download from http://www.quicklz.com/qpress-11-linux-x64.tar till #
-# https://blueprints.launchpad.net/percona-xtrabackup/+spec/package-qpress is fixed. #
-# my_print_defaults to extract values from my.cnf. #
-# netcat for transfer. #
-# xbstream/tar for streaming. (and xtrabackup ofc) #
-# #
-# Currently only option in cnf is read specifically for SST #
-# [sst] #
-# streamfmt=tar|xbstream #
-# #
-# Default is tar till lp:1193240 is fixed #
-# You need to use xbstream for encryption, compression etc., however, #
-# lp:1193240 requires you to manually cleanup the directory prior to SST #
-# #
-#############################################################################################################
+# Optional dependencies and options documented here: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
+# Make sure to read that before proceeding!
+
+
+
. $(dirname $0)/wsrep_sst_common
@@ -44,28 +30,89 @@ encrypt=0
nproc=1
ecode=0
XTRABACKUP_PID=""
+SST_PORT=""
+REMOTEIP=""
+tcert=""
+tpem=""
+sockopt=""
+progress=""
+ttime=0
+totime=0
+lsn=""
+incremental=0
+ecmd=""
+rlimit=""
sfmt="tar"
strmcmd=""
+tfmt=""
+tcmd=""
+rebuild=0
+rebuildcmd=""
+payload=0
+pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' "
+pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE "
+uextra=0
+
+if which pv &>/dev/null && pv --help | grep -q FORMAT;then
+ pvopts+=$pvformat
+fi
+pcmd="pv $pvopts"
declare -a RC
+INNOBACKUPEX_BIN=innobackupex
+readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
+DATA="${WSREP_SST_OPT_DATA}"
+INFO_FILE="xtrabackup_galera_info"
+IST_FILE="xtrabackup_ist"
+MAGIC_FILE="${DATA}/${INFO_FILE}"
+
+# Setting the path for ss and ip
+export PATH="/usr/sbin:/sbin:$PATH"
+
+timeit(){
+ local stage=$1
+ shift
+ local cmd="$@"
+ local x1 x2 took extcode
+
+ if [[ $ttime -eq 1 ]];then
+ x1=$(date +%s)
+ wsrep_log_info "Evaluating $cmd"
+ eval "$cmd"
+ extcode=$?
+ x2=$(date +%s)
+ took=$(( x2-x1 ))
+ wsrep_log_info "NOTE: $stage took $took seconds"
+ totime=$(( totime+took ))
+ else
+ wsrep_log_info "Evaluating $cmd"
+ eval "$cmd"
+ extcode=$?
+ fi
+ return $extcode
+}
+
get_keys()
{
- # There is no metadata in the stream to indicate that it is encrypted
- # So, if the cnf file on joiner contains 'encrypt' under [xtrabackup] section then
- # it means encryption is being used
- if ! my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then
+ if [[ $encrypt -eq 2 ]];then
+ return
+ fi
+
+ if [[ $encrypt -eq 0 ]];then
+ if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then
+ wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html "
+ fi
return
fi
+
if [[ $sfmt == 'tar' ]];then
- wsrep_log_info "NOTE: Encryption cannot be enabled with tar format"
+ wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format"
+ encrypt=0
return
fi
- wsrep_log_info "Encryption enabled in my.cnf - not supported at the moment - Bug in Xtrabackup - lp:1190343"
- ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2)
- ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2)
- ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2)
+ wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4"
if [[ -z $ealgo ]];then
wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out"
@@ -76,35 +123,160 @@ get_keys()
wsrep_log_error "FATAL: Either key or keyfile must be readable"
exit 3
fi
- encrypt=1
+
+ if [[ -z $ekey ]];then
+ ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile"
+ else
+ ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey"
+ fi
+
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ ecmd+=" -d"
+ fi
+}
+
+get_transfer()
+{
+ if [[ -z $SST_PORT ]];then
+ TSST_PORT=4444
+ else
+ TSST_PORT=$SST_PORT
+ fi
+
+ if [[ $tfmt == 'nc' ]];then
+ if [[ ! -x `which nc` ]];then
+ wsrep_log_error "nc(netcat) not found in path: $PATH"
+ exit 2
+ fi
+ wsrep_log_info "Using netcat as streamer"
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ tcmd="nc -dl ${TSST_PORT}"
+ else
+ tcmd="nc ${REMOTEIP} ${TSST_PORT}"
+ fi
+ else
+ tfmt='socat'
+ wsrep_log_info "Using socat as streamer"
+ if [[ ! -x `which socat` ]];then
+ wsrep_log_error "socat not found in path: $PATH"
+ exit 2
+ fi
+
+ if [[ $encrypt -eq 2 ]] && ! socat -V | grep -q OPENSSL;then
+ wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer"
+ encrypt=0
+ fi
+
+ if [[ $encrypt -eq 2 ]];then
+ wsrep_log_info "Using openssl based encryption with socat"
+ if [[ -z $tpem || -z $tcert ]];then
+ wsrep_log_error "Both PEM and CRT files required"
+ exit 22
+ fi
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert"
+ tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio"
+ else
+ wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert"
+ tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}"
+ fi
+ else
+ if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
+ tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio"
+ else
+ tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}"
+ fi
+ fi
+ fi
+
+}
+
+parse_cnf()
+{
+ local group=$1
+ local var=$2
+ reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-)
+ if [[ -z $reval ]];then
+ [[ -n $3 ]] && reval=$3
+ fi
+ echo $reval
+}
+
+get_footprint()
+{
+ pushd $WSREP_SST_OPT_DATA 1>/dev/null
+ payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }')
+ if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then
+ # QuickLZ has around 50% compression ratio
+ # When compression/compaction used, the progress is only an approximate.
+ payload=$(( payload*1/2 ))
+ fi
+ popd 1>/dev/null
+ pcmd+=" -s $payload"
+ adjust_progress
+}
+
+adjust_progress()
+{
+ if [[ -n $progress && $progress != '1' ]];then
+ if [[ -e $progress ]];then
+ pcmd+=" 2>>$progress"
+ else
+ pcmd+=" 2>$progress"
+ fi
+ elif [[ -z $progress && -n $rlimit ]];then
+ # When rlimit is non-zero
+ pcmd="pv -q"
+ fi
+
+ if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then
+ wsrep_log_info "Rate-limiting SST to $rlimit"
+ pcmd+=" -L \$rlimit"
+ fi
}
read_cnf()
{
- sfmt=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- '--streamfmt' | cut -d= -f2)
+ sfmt=$(parse_cnf sst streamfmt "tar")
+ tfmt=$(parse_cnf sst transferfmt "socat")
+ tcert=$(parse_cnf sst tca "")
+ tpem=$(parse_cnf sst tcert "")
+ encrypt=$(parse_cnf sst encrypt 0)
+ sockopt=$(parse_cnf sst sockopt "")
+ progress=$(parse_cnf sst progress "")
+ rebuild=$(parse_cnf sst rebuild 0)
+ ttime=$(parse_cnf sst time 0)
+ incremental=$(parse_cnf sst incremental 0)
+ ealgo=$(parse_cnf xtrabackup encrypt "")
+ ekey=$(parse_cnf xtrabackup encrypt-key "")
+ ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "")
+
+ # Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
+ if [[ -z $ealgo ]];then
+ ealgo=$(parse_cnf sst encrypt-algo "")
+ ekey=$(parse_cnf sst encrypt-key "")
+ ekeyfile=$(parse_cnf sst encrypt-key-file "")
+ fi
+ rlimit=$(parse_cnf sst rlimit "")
+ uextra=$(parse_cnf sst use_extra 0)
+}
+
+get_stream()
+{
if [[ $sfmt == 'xbstream' ]];then
wsrep_log_info "Streaming with xbstream"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
- wsrep_log_info "xbstream requires manual cleanup of data directory before SST - lp:1193240"
- strmcmd="xbstream -x -C ${DATA}"
- elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
- strmcmd="xbstream -c ${INFO_FILE} ${IST_FILE}"
+ strmcmd="xbstream -x"
else
- wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE"
- exit 22
+ strmcmd="xbstream -c \${INFO_FILE} \${IST_FILE}"
fi
else
sfmt="tar"
wsrep_log_info "Streaming with tar"
- wsrep_log_info "Note: Advanced xtrabackup features - encryption,compression etc. not available with tar."
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
- wsrep_log_info "However, xbstream requires manual cleanup of data directory before SST - lp:1193240."
- strmcmd="tar xfi - -C ${DATA}"
- elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
- strmcmd="tar cf - ${INFO_FILE} ${IST_FILE}"
- else
- wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE"
- exit 22
+ strmcmd="tar xfi - --recursive-unlink -h"
+ else
+ strmcmd="tar cf - \${INFO_FILE} \${IST_FILE}"
fi
fi
@@ -118,6 +290,12 @@ get_proc()
set -e
}
+sig_joiner_cleanup()
+{
+ wsrep_log_error "Removing $MAGIC_FILE file due to signal"
+ rm -f "$MAGIC_FILE"
+}
+
cleanup_joiner()
{
# Since this is invoked just after exit NNN
@@ -125,18 +303,14 @@ cleanup_joiner()
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus"
fi
- local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }')
- if [[ $estatus -ne 0 ]];then
- wsrep_log_error "Killing nc pid $PID"
- else
- wsrep_log_info "Killing nc pid $PID"
- fi
- [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
- rm -f "$MAGIC_FILE"
if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
wsrep_log_info "Removing the sst_in_progress file"
wsrep_cleanup_progress_file
fi
+ if [[ -n $progress && -p $progress ]];then
+ wsrep_log_info "Cleaning up fifo file $progress"
+ rm $progress
+ fi
}
check_pid()
@@ -152,119 +326,161 @@ cleanup_donor()
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus"
fi
- local pid=$XTRABACKUP_PID
- if check_pid "$pid"
- then
- wsrep_log_error "xtrabackup process is still running. Killing... "
- kill_xtrabackup
- fi
- rm -f "$pid"
+ if [[ -n $XTRABACKUP_PID ]];then
+ if check_pid $XTRABACKUP_PID
+ then
+ wsrep_log_error "xtrabackup process is still running. Killing... "
+ kill_xtrabackup
+ fi
+
+ rm -f $XTRABACKUP_PID
+ fi
rm -f ${DATA}/${IST_FILE}
+
+ if [[ -n $progress && -p $progress ]];then
+ wsrep_log_info "Cleaning up fifo file $progress"
+ rm $progress
+ fi
}
kill_xtrabackup()
{
-#set -x
local PID=$(cat $XTRABACKUP_PID)
[ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
rm -f "$XTRABACKUP_PID"
-#set +x
+}
+
+setup_ports()
+{
+ if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
+ SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
+ REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
+ lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }')
+ else
+ SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }')
+ fi
}
# waits ~10 seconds for nc to open the port and then reports ready
# (regardless of timeout)
-wait_for_nc()
+wait_for_listen()
{
local PORT=$1
local ADDR=$2
local MODULE=$3
- for i in $(seq 1 50)
+ for i in {1..50}
do
- netstat -nptl 2>/dev/null | grep '/nc\s*$' | awk '{ print $4 }' | \
- sed 's/.*://' | grep \^${PORT}\$ >/dev/null && break
+ ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break
sleep 0.2
done
+ if [[ $incremental -eq 1 ]];then
+ echo "ready ${ADDR}/${MODULE}/$lsn"
+ else
echo "ready ${ADDR}/${MODULE}"
+ fi
}
-INNOBACKUPEX_BIN=innobackupex
-INNOBACKUPEX_ARGS=""
-NC_BIN=nc
-
-for TOOL_BIN in INNOBACKUPEX_BIN NC_BIN ; do
- if ! which ${!TOOL_BIN} > /dev/null 2>&1
- then
- echo "Can't find ${!TOOL_BIN} in the path"
- exit 22 # EINVAL
- fi
-done
-
-#ROLE=$1
-#ADDR=$2
-readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
-readonly DATA="${WSREP_SST_OPT_DATA}"
-#CONF=$5
+check_extra()
+{
+ local use_socket=1
+ if [[ $uextra -eq 1 ]];then
+ if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then
+ local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2)
+ if [[ -n $eport ]];then
+ # Xtrabackup works only locally.
+ # Hence, setting host to 127.0.0.1 unconditionally.
+ wsrep_log_info "SST through extra_port $eport"
+ INNOEXTRA+=" --host=127.0.0.1 --port=$eport "
+ use_socket=0
+ else
+ wsrep_log_error "Extra port $eport null, failing"
+ exit 1
+ fi
+ else
+ wsrep_log_info "Thread pool not set, ignore the option use_extra"
+ fi
+ fi
+ if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then
+ INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}"
+ fi
+}
-INFO_FILE="xtrabackup_galera_info"
-IST_FILE="xtrabackup_ist"
+if [[ ! -x `which innobackupex` ]];then
+ wsrep_log_error "innobackupex not in path: $PATH"
+ exit 2
+fi
-MAGIC_FILE="${DATA}/${INFO_FILE}"
rm -f "${MAGIC_FILE}"
+if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then
+ wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}"
+ exit 22
+fi
+
read_cnf
+setup_ports
+get_stream
+get_transfer
+
+INNOEXTRA=""
+INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log"
+INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log"
if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
then
trap cleanup_donor EXIT
- NC_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
- REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
-
if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
then
- TMPDIR="/tmp"
-
- INNOBACKUPEX_ARGS="--galera-info --stream=$sfmt
- --defaults-file=${WSREP_SST_OPT_CONF}
- --socket=${WSREP_SST_OPT_SOCKET}"
+ TMPDIR="${TMPDIR:-/tmp}"
if [ "${AUTH[0]}" != "(null)" ]; then
- INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --user=${AUTH[0]}"
- fi
+ INNOEXTRA+=" --user=${AUTH[0]}"
+ fi
if [ ${#AUTH[*]} -eq 2 ]; then
- INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=${AUTH[1]}"
- else
+ INNOEXTRA+=" --password=${AUTH[1]}"
+ elif [ "${AUTH[0]}" != "(null)" ]; then
# Empty password, used for testing, debugging etc.
- INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password="
- fi
+ INNOEXTRA+=" --password="
+ fi
get_keys
if [[ $encrypt -eq 1 ]];then
if [[ -n $ekey ]];then
- INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key=$ekey"
+ INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey "
else
- INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key-file=$ekeyfile"
+ INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile "
fi
fi
- wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${NC_PORT}"
+ if [[ -n $lsn ]];then
+ INNOEXTRA+=" --incremental --incremental-lsn=$lsn "
+ fi
- set +e
- ${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \
- 2> ${DATA}/innobackup.backup.log | \
- ${NC_BIN} ${REMOTEIP} ${NC_PORT}
+ check_extra
+
+ wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT}"
- RC=( "${PIPESTATUS[@]}" )
+ if [[ -n $progress ]];then
+ get_footprint
+ tcmd="$pcmd | $tcmd"
+ elif [[ -n $rlimit ]];then
+ adjust_progress
+ tcmd="$pcmd | $tcmd"
+ fi
+
+ set +e
+ timeit "Donor-Transfer" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e
if [ ${RC[0]} -ne 0 ]; then
wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \
"Check ${DATA}/innobackup.backup.log"
exit 22
- elif [ ${RC[1]} -ne 0 ]; then
- wsrep_log_error "${NC_BIN} finished with error: ${RC[1]}"
+ elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
+ wsrep_log_error "$tcmd finished with error: ${RC[1]}"
exit 22
fi
@@ -272,7 +488,8 @@ then
XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid"
- else # BYPASS
+ else # BYPASS FOR IST
+
wsrep_log_info "Bypassing the SST for IST"
STATE="${WSREP_SST_OPT_GTID}"
echo "continue" # now server can resume updating data
@@ -282,15 +499,9 @@ then
pushd ${DATA} 1>/dev/null
set +e
if [[ $encrypt -eq 1 ]];then
- if [[ -n $ekey ]];then
- xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
- else
- xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
- fi
- else
- $strmcmd | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
+ tcmd=" $ecmd | $tcmd"
fi
- RC=( "${PIPESTATUS[@]}" )
+ timeit "Donor-IST-Unencrypted-transfer" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e
popd 1>/dev/null
@@ -301,62 +512,81 @@ then
exit 1
fi
done
- #rm -f ${DATA}/${IST_FILE}
fi
echo "done ${WSREP_SST_OPT_GTID}"
+ wsrep_log_info "Total time on donor: $totime seconds"
elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ]
then
[[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
touch $SST_PROGRESS_FILE
+ if [[ ! -e ${DATA}/ibdata1 ]];then
+ incremental=0
+ fi
+
+ if [[ $incremental -eq 1 ]];then
+ wsrep_log_info "Incremental SST enabled"
+ #lsn=$(/pxc/bin/mysqld --defaults-file=$WSREP_SST_OPT_CONF --basedir=/pxc --wsrep-recover 2>&1 | grep -o 'log sequence number .*' | cut -d " " -f 4 | head -1)
+ lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ')
+ wsrep_log_info "Recovered LSN: $lsn"
+ fi
+
sencrypted=1
nthreads=1
MODULE="xtrabackup_sst"
- rm -f ${DATA}/xtrabackup_*
+ # May need xtrabackup_checkpoints later on
+ rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile
ADDR=${WSREP_SST_OPT_ADDR}
- NC_PORT=$(echo ${ADDR} | awk -F ':' '{ print $2 }')
- if [ -z "${NC_PORT}" ]
+ if [ -z "${SST_PORT}" ]
then
- NC_PORT=4444
- ADDR="$(echo ${ADDR} | awk -F ':' '{ print $1 }'):${NC_PORT}"
+ SST_PORT=4444
+ ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}"
fi
- wait_for_nc ${NC_PORT} ${ADDR} ${MODULE} &
+ wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} &
- trap "exit 32" HUP PIPE
- trap "exit 3" INT TERM
+ trap sig_joiner_cleanup HUP PIPE INT TERM
trap cleanup_joiner EXIT
+ if [[ -n $progress ]];then
+ adjust_progress
+ tcmd+=" | $pcmd"
+ fi
+
+ if [[ $incremental -eq 1 ]];then
+ BDATA=$DATA
+ DATA=$(mktemp -d)
+ MAGIC_FILE="${DATA}/${INFO_FILE}"
+ fi
+
get_keys
set +e
if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
- if [[ -n $ekey ]];then
- ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey | xbstream -x -C ${DATA}
- else
- ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | xbstream -x -C ${DATA}
- fi
- else
- ${NC_BIN} -dl ${NC_PORT} | $strmcmd
+ strmcmd=" $ecmd | $strmcmd"
fi
- RC=( "${PIPESTATUS[@]}" )
+
+ pushd ${DATA} 1>/dev/null
+ timeit "Joiner-Recv-Unencrypted" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
+ popd 1>/dev/null
+
set -e
if [[ $sfmt == 'xbstream' ]];then
# Special handling till lp:1193240 is fixed"
if [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
wsrep_log_error "Xbstream failed"
- wsrep_log_error "Data directory ${DATA} needs to be empty for SST: lp:1193240" \
+ wsrep_log_error "Data directory ${DATA} may not be empty: lp:1193240" \
"Manual intervention required in that case"
exit 32
fi
fi
- wait %% # join wait_for_nc thread
+ wait %% # join for wait_for_listen thread
for ecode in "${RC[@]}";do
if [[ $ecode -ne 0 ]];then
@@ -370,43 +600,25 @@ then
then
# this message should cause joiner to abort
wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'"
+ wsrep_log_info "Contents of datadir"
+ wsrep_log_info "$(ls -l ${DATA}/**/*)"
exit 32
fi
- if ! ps -p ${WSREP_SST_OPT_PARENT} >/dev/null
+ if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null
then
wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly."
exit 32
fi
- if [ ! -r "${IST_FILE}" ]
+ if [ ! -r "${DATA}/${IST_FILE}" ]
then
wsrep_log_info "Proceeding with SST"
- rebuild=""
wsrep_log_info "Removing existing ib_logfile files"
- rm -f ${DATA}/ib_logfile*
-
- # Decrypt only if not encrypted in stream.
- # NOT USED NOW.
- # Till https://blueprints.launchpad.net/percona-xtrabackup/+spec/add-support-for-rsync-url
- # is implemented
- #get_keys
- if [[ $encrypt -eq 1 && $sencrypted -eq 0 ]];then
- # Decrypt the files if any
- find ${DATA} -type f -name '*.xbcrypt' -printf '%p\n' | while read line;do
- input=$line
- output=${input%.xbcrypt}
-
- if [[ -n $ekey ]];then
- xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey -i $input > $output
- else
- xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile -i $input > $output
- fi
- done
-
- if [[ $? = 0 ]];then
- find ${DATA} -type f -name '*.xbcrypt' -delete
- fi
+ if [[ $incremental -ne 1 ]];then
+ rm -f ${DATA}/ib_logfile*
+ else
+ rm -f ${BDATA}/ib_logfile*
fi
get_proc
@@ -414,33 +626,47 @@ then
# Rebuild indexes for compact backups
if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then
wsrep_log_info "Index compaction detected"
- nthreads=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--rebuild-threads' | cut -d= -f2)
- [[ -z $nthreads ]] && nthreads=$nproc
- wsrep_log_info "Rebuilding with $nthreads threads"
- rebuild="--rebuild-indexes --rebuild-threads=$nthreads"
+ rebuild=1
fi
- if test -n "$(find ${DATA} -maxdepth 1 -name '*.qp' -print -quit)";then
+ if [[ $rebuild -eq 1 ]];then
+ nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc)
+ wsrep_log_info "Rebuilding during prepare with $nthreads threads"
+ rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads"
+ fi
+
+ if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then
wsrep_log_info "Compressed qpress files found"
if [[ ! -x `which qpress` ]];then
- wsrep_log_error "qpress not found in PATH"
+ wsrep_log_error "qpress not found in path: $PATH"
exit 22
fi
- set +e
+ if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then
+ count=$(find ${DATA} -type f -name '*.qp' | wc -l)
+ count=$(( count*2 ))
+ if pv --help | grep -q FORMAT;then
+ pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'"
+ else
+ pvopts="-f -s $count -l -N Decompression"
+ fi
+ pcmd="pv $pvopts"
+ adjust_progress
+ dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d"
+ else
+ dcmd="xargs -n 2 qpress -T${nproc}d"
+ fi
wsrep_log_info "Removing existing ibdata1 file"
rm -f ${DATA}/ibdata1
# Decompress the qpress files
wsrep_log_info "Decompression with $nproc threads"
- find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | xargs -P $nproc -n 2 qpress -d
+ timeit "Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd"
extcode=$?
- set -e
-
if [[ $extcode -eq 0 ]];then
wsrep_log_info "Removing qpress files after decompression"
find ${DATA} -type f -name '*.qp' -delete
@@ -453,10 +679,21 @@ then
fi
fi
+ if [[ $incremental -eq 1 ]];then
+ # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues.
+ INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \
+ --ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log"
+ fi
+
wsrep_log_info "Preparing the backup at ${DATA}"
+ timeit "Xtrabackup prepare stage" "$INNOAPPLY"
+
+ if [[ $incremental -eq 1 ]];then
+ wsrep_log_info "Cleaning up ${DATA} after incremental SST"
+ [[ -d ${DATA} ]] && rm -rf ${DATA}
+ DATA=$BDATA
+ fi
- ${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log $rebuild \
- ${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log
if [ $? -ne 0 ];
then
wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log"
@@ -466,14 +703,13 @@ then
wsrep_log_info "${IST_FILE} received from donor: Running IST"
fi
- cat "${MAGIC_FILE}" # output UUID:seqno
-
- #Cleanup not required here since EXIT trap should be called
- #wsrep_cleanup_progress_file
+ if [[ ! -r ${MAGIC_FILE} ]];then
+ wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable"
+ exit 2
+ fi
-else
- wsrep_log_error "Unrecognized role: ${WSREP_SST_OPT_ROLE}"
- exit 22 # EINVAL
+ cat "${MAGIC_FILE}" # output UUID:seqno
+ wsrep_log_info "Total time on joiner: $totime seconds"
fi
exit 0
diff --git a/sql/slave.cc b/sql/slave.cc
index 7469f28457d..563caf287a7 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -3456,12 +3456,18 @@ pthread_handler_t handle_slave_sql(void *arg)
my_off_t UNINIT_VAR(saved_log_pos);
my_off_t UNINIT_VAR(saved_master_log_pos);
my_off_t saved_skip= 0;
+#ifdef WITH_WSREP
+ my_bool wsrep_node_dropped= FALSE;
+#endif /* WITH_WSREP */
Relay_log_info* rli = &((Master_info*)arg)->rli;
const char *errmsg;
// needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
my_thread_init();
DBUG_ENTER("handle_slave_sql");
+#ifdef WITH_WSREP
+ wsrep_restart_point:
+#endif /* WITH_WSREP */
LINT_INIT(saved_master_log_pos);
LINT_INIT(saved_log_pos);
@@ -3727,6 +3733,12 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
Error running query, slave SQL thread aborted. Fix the problem, and restart \
the slave SQL thread with \"SLAVE START\". We stopped at log \
'%s' position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos, llbuff));
+#ifdef WITH_WSREP
+ if (WSREP_ON && last_errno == ER_UNKNOWN_COM_ERROR)
+ {
+ wsrep_node_dropped= TRUE;
+ }
+#endif /* WITH_WSREP */
}
goto err;
}
@@ -3791,6 +3803,27 @@ err_during_init:
THD_CHECK_SENTRY(thd);
delete thd;
mysql_mutex_unlock(&LOCK_thread_count);
+#ifdef WITH_WSREP
+ /* if slave stopped due to node going non primary, we set global flag to
+ trigger automatic restart of slave when node joins back to cluster
+ */
+ if (wsrep_node_dropped && wsrep_restart_slave)
+ {
+ if (wsrep_ready)
+ {
+ WSREP_INFO("Slave error due to node temporarily non-primary"
+ "SQL slave will continue");
+ wsrep_node_dropped= FALSE;
+ mysql_mutex_unlock(&rli->run_lock);
+ goto wsrep_restart_point;
+ } else {
+ WSREP_INFO("Slave error due to node going non-primary");
+ WSREP_INFO("wsrep_restart_slave was set and therefore slave will be "
+ "automatically restarted when node joins back to cluster");
+ wsrep_restart_slave_activated= TRUE;
+ }
+ }
+#endif /* WITH_WSREP */
/*
Note: the order of the broadcast and unlock calls below (first broadcast, then unlock)
is important. Otherwise a killer_thread can execute between the calls and
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index e840b5c7072..893d358d8a8 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -5181,6 +5181,7 @@ restart:
thd->lex->sql_command== SQLCOM_LOAD ||
thd->lex->sql_command== SQLCOM_DELETE) &&
wsrep_replicate_myisam &&
+ (*start) &&
(*start)->table && (*start)->table->file->ht->db_type == DB_TYPE_MYISAM)
{
WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start));
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 30833588e06..aba051d214d 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -3918,6 +3918,10 @@ static Sys_var_mybool Sys_wsrep_load_data_splitting(
"transaction after every 10K rows inserted",
GLOBAL_VAR(wsrep_load_data_splitting),
CMD_LINE(OPT_ARG), DEFAULT(TRUE));
+
+static Sys_var_mybool Sys_wsrep_restart_slave(
+ "wsrep_restart_slave", "Should MySQL slave be restarted automatically, when node joins back to cluster",
+ GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
#endif /* WITH_WSREP */
static Sys_var_charptr Sys_ignore_db_dirs(
diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc
index 933ef3dc31f..af4ec84db85 100644
--- a/sql/wsrep_binlog.cc
+++ b/sql/wsrep_binlog.cc
@@ -320,3 +320,59 @@ void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len)
}
}
+void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache)
+{
+ char filename[PATH_MAX]= {0};
+ int len= snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld.log",
+ wsrep_data_home_dir, thd->thread_id,
+ (long long)wsrep_thd_trx_seqno(thd));
+ size_t bytes_in_cache = 0;
+ // check path
+ if (len >= PATH_MAX)
+ {
+ WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len);
+ return ;
+ }
+ // init cache
+ my_off_t const saved_pos(my_b_tell(cache));
+ if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
+ {
+ WSREP_ERROR("failed to initialize io-cache");
+ return ;
+ }
+ // open file
+ FILE* of = fopen(filename, "wb");
+ if (!of)
+ {
+ WSREP_ERROR("Failed to open file '%s': %d (%s)",
+ filename, errno, strerror(errno));
+ goto cleanup;
+ }
+ // ready to write
+ bytes_in_cache= my_b_bytes_in_cache(cache);
+ if (unlikely(bytes_in_cache == 0)) bytes_in_cache = my_b_fill(cache);
+ if (likely(bytes_in_cache > 0)) do
+ {
+ if (my_fwrite(of, cache->read_pos, bytes_in_cache,
+ MYF(MY_WME | MY_NABP)) == (size_t) -1)
+ {
+ WSREP_ERROR("Failed to write file '%s'", filename);
+ goto cleanup;
+ }
+ cache->read_pos= cache->read_end;
+ } while ((cache->file >= 0) && (bytes_in_cache= my_b_fill(cache)));
+ if(cache->error == -1)
+ {
+ WSREP_ERROR("RBR inconsistent");
+ goto cleanup;
+ }
+cleanup:
+ // init back
+ if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
+ {
+ WSREP_ERROR("failed to reinitialize io-cache");
+ }
+ // close file
+ if (of) fclose(of);
+}
+
diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h
index 6de73b2f5ee..76192f6e119 100644
--- a/sql/wsrep_binlog.h
+++ b/sql/wsrep_binlog.h
@@ -46,4 +46,7 @@ int wsrep_write_cache (wsrep_t* wsrep,
/* Dump replication buffer to disk */
void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len);
+/* Dump replication buffer to disk without intermediate buffer */
+void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache);
+
#endif /* WSREP_BINLOG_H */
diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc
index c5627ff97fb..84034ec776e 100644
--- a/sql/wsrep_hton.cc
+++ b/sql/wsrep_hton.cc
@@ -505,11 +505,17 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all)
DBUG_RETURN(WSREP_TRX_CERT_FAIL);
+ case WSREP_SIZE_EXCEEDED:
+ WSREP_ERROR("transaction size exceeded");
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ DBUG_RETURN(WSREP_TRX_SIZE_EXCEEDED);
case WSREP_CONN_FAIL:
WSREP_ERROR("connection failure");
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
DBUG_RETURN(WSREP_TRX_ERROR);
default:
WSREP_ERROR("unknown connection failure");
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
DBUG_RETURN(WSREP_TRX_ERROR);
}
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 5867b063426..4fd07a9945c 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -26,6 +26,7 @@
#include <cstdio>
#include <cstdlib>
#include "log_event.h"
+#include <slave.h>
Format_description_log_event *wsrep_format_desc = NULL;
wsrep_t *wsrep = NULL;
@@ -59,7 +60,10 @@ ulong wsrep_mysql_replication_bundle = 0;
my_bool wsrep_desync = 0; // desynchronize the node from the
// cluster
my_bool wsrep_load_data_splitting = 1; // commit load data every 10K intervals
-
+my_bool wsrep_restart_slave = 0; // should mysql slave thread be
+ // restarted, if node joins back
+my_bool wsrep_restart_slave_activated = 0; // node has dropped, and slave
+ // restart will be needed
/*
* End configuration options
*/
@@ -406,6 +410,25 @@ static void wsrep_synced_cb(void* app_ctx)
// and wait for SE initialization
wsrep_SE_init_wait();
}
+ if (wsrep_restart_slave_activated)
+ {
+ int rcode;
+ WSREP_INFO("MySQL slave restart");
+ wsrep_restart_slave_activated= FALSE;
+
+ mysql_mutex_lock(&LOCK_active_mi);
+ if ((rcode = start_slave_threads(1 /* need mutex */,
+ 0 /* no wait for start*/,
+ active_mi,
+ master_info_file,
+ relay_log_info_file,
+ SLAVE_SQL)))
+ {
+ WSREP_WARN("Failed to create slave threads: %d", rcode);
+ }
+ mysql_mutex_unlock(&LOCK_active_mi);
+
+ }
}
static void wsrep_init_position()
@@ -627,6 +650,7 @@ int wsrep_init()
{
DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode));
WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode);
+ wsrep->free(wsrep);
free(wsrep);
wsrep = NULL;
} else {
@@ -1159,7 +1183,7 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len)
}
buff.append(STRING_WITH_LEN(" AS "));
//buff.append(views->source.str, views->source.length);
- buff.append(thd->lex->create_view_select.str,
+ buff.append(thd->lex->create_view_select.str,
thd->lex->create_view_select.length);
//int errcode= query_error_code(thd, TRUE);
//if (thd->binlog_query(THD::STMT_QUERY_TYPE,
@@ -1168,7 +1192,7 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len)
}
static int wsrep_TOI_begin(THD *thd, char *db_, char *table_,
- const TABLE_LIST* table_list)
+ const TABLE_LIST* table_list)
{
wsrep_status_t ret(WSREP_WARNING);
uchar* buf(0);
@@ -1193,7 +1217,7 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_,
buf_err= wsrep_create_event_query(thd, &buf, &buf_len);
break;
default:
- buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), &buf,
+ buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), &buf,
&buf_len);
break;
}
@@ -1243,7 +1267,7 @@ static void wsrep_TOI_end(THD *thd) {
}
}
-static int wsrep_RSU_begin(THD *thd, char *db_, char *table_)
+static int wsrep_RSU_begin(THD *thd, char *db_, char *table_)
{
wsrep_status_t ret(WSREP_WARNING);
WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
@@ -1325,9 +1349,9 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
int ret= 0;
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
- if (thd->wsrep_conflict_state == MUST_ABORT)
+ if (thd->wsrep_conflict_state == MUST_ABORT)
{
- WSREP_INFO("thread: %lu, %s has been aborted due to multi-master conflict",
+ WSREP_INFO("thread: %lu, %s has been aborted due to multi-master conflict",
thd->thread_id, thd->query());
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
return WSREP_TRX_FAIL;
@@ -1346,7 +1370,7 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
if (wsrep_debug && thd->mdl_context.has_locks())
{
- WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu",
+ WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu",
thd->query(), thd->thread_id);
}
@@ -1438,7 +1462,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd);
ret = TRUE;
}
- else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE)
+ else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE)
{
WSREP_DEBUG("DROP caused BF abort");
ticket->wsrep_report(wsrep_debug);
@@ -1446,7 +1470,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1);
ret = FALSE;
}
- else if (granted_thd->wsrep_query_state == QUERY_COMMITTING)
+ else if (granted_thd->wsrep_query_state == QUERY_COMMITTING)
{
WSREP_DEBUG("mdl granted, but commiting thd abort scheduled");
ticket->wsrep_report(wsrep_debug);
@@ -1454,7 +1478,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1);
ret = FALSE;
}
- else
+ else
{
WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", request_thd, granted_thd);
ticket->wsrep_report(wsrep_debug);
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 5cf0d9dc0c5..ec2a38278ab 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -95,6 +95,8 @@ extern my_bool wsrep_replicate_myisam;
extern my_bool wsrep_log_conflicts;
extern ulong wsrep_mysql_replication_bundle;
extern my_bool wsrep_load_data_splitting;
+extern my_bool wsrep_restart_slave;
+extern my_bool wsrep_restart_slave_activated;
enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU };
diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc
index 291cdbb7c75..6eefb961b62 100644
--- a/sql/wsrep_notify.cc
+++ b/sql/wsrep_notify.cc
@@ -75,15 +75,18 @@ void wsrep_notify_status (wsrep_member_status_t status,
cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off,
" --index %d", view->my_idx);
- cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, " --members");
-
- for (int i = 0; i < view->memb_num; i++)
+ if (view->memb_num)
{
- wsrep_uuid_print (&view->members[i].id, uuid_str, sizeof(uuid_str));
- cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off,
- "%c%s/%s/%s", i > 0 ? ',' : ' ',
- uuid_str, view->members[i].name,
- view->members[i].incoming);
+ cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, " --members");
+
+ for (int i = 0; i < view->memb_num; i++)
+ {
+ wsrep_uuid_print (&view->members[i].id, uuid_str, sizeof(uuid_str));
+ cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off,
+ "%c%s/%s/%s", i > 0 ? ',' : ' ',
+ uuid_str, view->members[i].name,
+ view->members[i].incoming);
+ }
}
}
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index ec636a8b1ec..37c55707b28 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -934,8 +934,9 @@ wait_signal:
else
{
WSREP_ERROR("Failed to read from: %s", proc.cmd());
+ proc.wait();
}
- if (err && proc.error()) err= proc.error();
+ if (!err && proc.error()) err= proc.error();
}
else
{
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 189d4bacc0e..c03763c7d45 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -1207,6 +1207,7 @@ echo "=====" >> $STATUS_HISTORY
%attr(755, root, root) %{_bindir}/wsrep_sst_rsync
%attr(755, root, root) %{_bindir}/wsrep_sst_rsync_wan
%attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup
+%attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup-v2
%endif
%attr(755, root, root) %{_sbindir}/mysqld
diff --git a/support-files/wsrep_notify.sh b/support-files/wsrep_notify.sh
index bdbe3d12a39..c36a9ddc62a 100644
--- a/support-files/wsrep_notify.sh
+++ b/support-files/wsrep_notify.sh
@@ -87,6 +87,7 @@ do
--members)
MEMBERS=$2
shift
+ fi
;;
esac
shift
diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h
index f713de66d57..c3304d7ed7c 100644
--- a/wsrep/wsrep_api.h
+++ b/wsrep/wsrep_api.h
@@ -137,7 +137,11 @@ typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *);
typedef uint64_t wsrep_trx_id_t; //!< application transaction ID
typedef uint64_t wsrep_conn_id_t; //!< application connection ID
typedef int64_t wsrep_seqno_t; //!< sequence number of a writeset, etc.
+#ifdef __cplusplus
+typedef bool wsrep_bool_t;
+#else
typedef _Bool wsrep_bool_t; //!< should be the same as standard (C99) bool
+#endif /* __cplusplus */
/*! undefined seqno */
#define WSREP_SEQNO_UNDEFINED (-1)
diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c
index 3c7a7c2e354..3c7f97ede3f 100644
--- a/wsrep/wsrep_dummy.c
+++ b/wsrep/wsrep_dummy.c
@@ -388,4 +388,3 @@ int wsrep_dummy_loader(wsrep_t* w)
return 0;
}
-