summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbhay Choubey <nirbhay@mariadb.com>2015-09-09 20:51:39 -0400
committerNirbhay Choubey <nirbhay@mariadb.com>2015-09-09 20:51:39 -0400
commitfa5f18d6734249aa326d6296c9b9c2338cb33b10 (patch)
tree63233fb5a049d4683cc6faa910875702a7836d8c
parentf533b2b462b5b73630245172b627506d36f95b39 (diff)
parent37ae601a8766f37cdd919efc801133d2a8cfaf70 (diff)
downloadmariadb-git-fa5f18d6734249aa326d6296c9b9c2338cb33b10.tar.gz
Merge branch '5.5-galera' into 10.0-galera
-rw-r--r--cmake/wsrep.cmake6
-rw-r--r--scripts/wsrep_sst_common.sh39
-rw-r--r--scripts/wsrep_sst_mysqldump.sh34
-rw-r--r--scripts/wsrep_sst_rsync.sh2
-rw-r--r--scripts/wsrep_sst_xtrabackup-v2.sh298
-rw-r--r--scripts/wsrep_sst_xtrabackup.sh20
-rw-r--r--sql/wsrep_mysqld.cc17
-rw-r--r--sql/wsrep_notify.cc2
-rw-r--r--sql/wsrep_sst.cc204
-rw-r--r--sql/wsrep_utils.cc93
-rw-r--r--sql/wsrep_utils.h26
11 files changed, 497 insertions, 244 deletions
diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake
index d52097b9046..7740a4608f6 100644
--- a/cmake/wsrep.cmake
+++ b/cmake/wsrep.cmake
@@ -18,12 +18,12 @@
# so WSREP_VERSION is produced regardless
# Set the patch version
-SET(WSREP_PATCH_VERSION "10")
+SET(WSREP_PATCH_VERSION "12")
# MariaDB addition: Revision number of the last revision merged from
# codership branch visible in @@visible_comment.
-# Branch : codership-mysql/5.6
-SET(WSREP_PATCH_REVNO "4144") # Should be updated on every merge.
+# Branch : https://github.com/codership/mysql-wsrep/tree/5.5
+SET(WSREP_PATCH_REVNO "4f81026") # Should be updated on every merge.
# MariaDB: Obtain patch revision number:
# Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set.
diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh
index 46f4076111f..0aa338510e0 100644
--- a/scripts/wsrep_sst_common.sh
+++ b/scripts/wsrep_sst_common.sh
@@ -1,4 +1,4 @@
-# Copyright (C) 2012-2014 Codership Oy
+# Copyright (C) 2012-2015 Codership Oy
#
# 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
@@ -20,8 +20,11 @@ set -u
WSREP_SST_OPT_BYPASS=0
WSREP_SST_OPT_BINLOG=""
+WSREP_SST_OPT_CONF_SUFFIX=""
WSREP_SST_OPT_DATA=""
-WSREP_SST_OPT_AUTH=""
+WSREP_SST_OPT_AUTH=${WSREP_SST_OPT_AUTH:-}
+WSREP_SST_OPT_USER=${WSREP_SST_OPT_USER:-}
+WSREP_SST_OPT_PSWD=${WSREP_SST_OPT_PSWD:-}
while [ $# -gt 0 ]; do
case "$1" in
@@ -29,10 +32,6 @@ case "$1" in
readonly WSREP_SST_OPT_ADDR="$2"
shift
;;
- '--auth')
- WSREP_SST_OPT_AUTH="$2"
- shift
- ;;
'--bypass')
WSREP_SST_OPT_BYPASS=1
;;
@@ -45,7 +44,7 @@ case "$1" in
shift
;;
'--defaults-group-suffix')
- readonly WSREP_SST_OPT_CONF_SUFFIX="$2"
+ WSREP_SST_OPT_CONF_SUFFIX="$2"
shift
;;
'--host')
@@ -97,6 +96,7 @@ shift
done
readonly WSREP_SST_OPT_BYPASS
readonly WSREP_SST_OPT_BINLOG
+readonly WSREP_SST_OPT_CONF_SUFFIX
# try to use my_print_defaults, mysql and mysqldump that come with the sources
# (for MTR suite)
@@ -124,12 +124,30 @@ else
MY_PRINT_DEFAULTS=$(which my_print_defaults)
fi
+wsrep_auth_not_set()
+{
+ [ -z "$WSREP_SST_OPT_AUTH" -o "$WSREP_SST_OPT_AUTH" = "(null)" ]
+}
+
# 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)
+if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth"
+then
+ if wsrep_auth_not_set
+ then
+ WSREP_SST_OPT_AUTH=$(MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2)
fi
fi
+readonly WSREP_SST_OPT_AUTH
+
+# Splitting AUTH into potential user:password pair
+if ! wsrep_auth_not_set
+then
+ readonly AUTH_VEC=(${WSREP_SST_OPT_AUTH//:/ })
+ WSREP_SST_OPT_USER="${AUTH_VEC[0]:-}"
+ WSREP_SST_OPT_PSWD="${AUTH_VEC[1]:-}"
+fi
+readonly WSREP_SST_OPT_USER
+readonly WSREP_SST_OPT_PSWD
if [ -n "${WSREP_SST_OPT_DATA:-}" ]
then
@@ -138,7 +156,6 @@ 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_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh
index 3153cbcdfe0..9a061f89e43 100644
--- a/scripts/wsrep_sst_mysqldump.sh
+++ b/scripts/wsrep_sst_mysqldump.sh
@@ -1,5 +1,5 @@
-#!/bin/bash -e
-# Copyright (C) 2009 Codership Oy
+#!/bin/bash -ue
+# Copyright (C) 2009-2015 Codership Oy
#
# 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
@@ -41,7 +41,6 @@ local_ip()
return 1
}
-if test -z "$WSREP_SST_OPT_USER"; then wsrep_log_error "USER cannot be nil"; exit $EINVAL; fi
if test -z "$WSREP_SST_OPT_HOST"; then wsrep_log_error "HOST cannot be nil"; exit $EINVAL; fi
if test -z "$WSREP_SST_OPT_PORT"; then wsrep_log_error "PORT cannot be nil"; exit $EINVAL; fi
if test -z "$WSREP_SST_OPT_LPORT"; then wsrep_log_error "LPORT cannot be nil"; exit $EINVAL; fi
@@ -64,13 +63,18 @@ then
exit $EINVAL
fi
-# For Bug:1293798
-if [ -z "$WSREP_SST_OPT_PSWD" -a -n "$WSREP_SST_OPT_AUTH" ]; then
- WSREP_SST_OPT_USER=$(echo $WSREP_SST_OPT_AUTH | cut -d: -f1)
- WSREP_SST_OPT_PSWD=$(echo $WSREP_SST_OPT_AUTH | cut -d: -f2)
-fi
-AUTH="-u$WSREP_SST_OPT_USER"
-if test -n "$WSREP_SST_OPT_PSWD"; then AUTH="$AUTH -p$WSREP_SST_OPT_PSWD"; fi
+[ -n "$WSREP_SST_OPT_USER" ] && AUTH="-u$WSREP_SST_OPT_USER" || AUTH=
+
+# Refs https://github.com/codership/mysql-wsrep/issues/141
+# Passing password in MYSQL_PWD environment variable is considered
+# "extremely insecure" by MySQL Guidelines for Password Security
+# (https://dev.mysql.com/doc/refman/5.6/en/password-security-user.html)
+# that is even less secure than passing it on a command line! It is doubtful:
+# the whole command line is easily observable by any unprivileged user via ps,
+# whereas (at least on Linux) unprivileged user can't see process environment
+# that he does not own. So while it may be not secure in the NSA sense of the
+# word, it is arguably more secure than passing password on the command line.
+[ -n "$WSREP_SST_OPT_PSWD" ] && export MYSQL_PWD="$WSREP_SST_OPT_PSWD"
STOP_WSREP="SET wsrep_on=OFF;"
@@ -136,15 +140,15 @@ fi
MYSQLDUMP="$MYSQLDUMP $AUTH -S$WSREP_SST_OPT_SOCKET \
--add-drop-database --add-drop-table --skip-add-locks --create-options \
--disable-keys --extended-insert --skip-lock-tables --quick --set-charset \
---skip-comments --flush-privileges --all-databases"
+--skip-comments --flush-privileges --all-databases --events"
# need to disable logging when loading the dump
# reason is that dump contains ALTER TABLE for log tables, and
# this causes an error if logging is enabled
-GENERAL_LOG_OPT=`$MYSQL --skip-column-names -e"$STOP_WSREP SELECT @@GENERAL_LOG"`
-SLOW_LOG_OPT=`$MYSQL --skip-column-names -e"$STOP_WSREP SELECT @@SLOW_QUERY_LOG"`
-$MYSQL -e"$STOP_WSREP SET GLOBAL GENERAL_LOG=OFF"
-$MYSQL -e"$STOP_WSREP SET GLOBAL SLOW_QUERY_LOG=OFF"
+GENERAL_LOG_OPT=`$MYSQL --skip-column-names -e "$STOP_WSREP SELECT @@GENERAL_LOG"`
+SLOW_LOG_OPT=`$MYSQL --skip-column-names -e "$STOP_WSREP SELECT @@SLOW_QUERY_LOG"`
+$MYSQL -e "$STOP_WSREP SET GLOBAL GENERAL_LOG=OFF"
+$MYSQL -e "$STOP_WSREP SET GLOBAL SLOW_QUERY_LOG=OFF"
# commands to restore log settings
RESTORE_GENERAL_LOG="SET GLOBAL GENERAL_LOG=$GENERAL_LOG_OPT;"
diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh
index f5e304a1033..b3a07f8bbf6 100644
--- a/scripts/wsrep_sst_rsync.sh
+++ b/scripts/wsrep_sst_rsync.sh
@@ -32,8 +32,8 @@ wsrep_check_programs rsync
cleanup_joiner()
{
- wsrep_log_info "Joiner cleanup."
local PID=$(cat "$RSYNC_PID" 2>/dev/null || echo 0)
+ wsrep_log_info "Joiner cleanup. rsync PID: $PID"
[ "0" != "$PID" ] && kill $PID && sleep 0.5 && kill -9 $PID >/dev/null 2>&1 \
|| :
rm -rf "$RSYNC_CONF"
diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh
index d5916b81a53..e3ad8257df6 100644
--- a/scripts/wsrep_sst_xtrabackup-v2.sh
+++ b/scripts/wsrep_sst_xtrabackup-v2.sh
@@ -29,6 +29,8 @@ ekeyfile=""
encrypt=0
nproc=1
ecode=0
+ssyslog=""
+ssystag=""
XTRABACKUP_PID=""
SST_PORT=""
REMOTEIP=""
@@ -40,15 +42,15 @@ progress=""
ttime=0
totime=0
lsn=""
-incremental=0
ecmd=""
rlimit=""
# Initially
stagemsg="${WSREP_SST_OPT_ROLE}"
cpat=""
-speciald=0
+speciald=1
ib_home_dir=""
ib_log_dir=""
+ib_undo_dir=""
sfmt="tar"
strmcmd=""
@@ -70,6 +72,11 @@ xtmpdir=""
scomp=""
sdecomp=""
+# Required for backup locks
+# For backup locks it is 1 sent by joiner
+# 5.6.21 PXC and later can't donate to an older joiner
+sst_ver=1
+
if which pv &>/dev/null && pv --help | grep -q FORMAT;then
pvopts+=$pvformat
fi
@@ -77,7 +84,6 @@ 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"
@@ -169,7 +175,11 @@ get_transfer()
fi
wsrep_log_info "Using netcat as streamer"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
- tcmd="nc -dl ${TSST_PORT}"
+ if nc -h | grep -q ncat;then
+ tcmd="nc -l ${TSST_PORT}"
+ else
+ tcmd="nc -dl ${TSST_PORT}"
+ fi
else
tcmd="nc ${REMOTEIP} ${TSST_PORT}"
fi
@@ -253,6 +263,16 @@ get_footprint()
adjust_progress()
{
+
+ if [[ ! -x `which pv` ]];then
+ wsrep_log_error "pv not found in path: $PATH"
+ wsrep_log_error "Disabling all progress/rate-limiting"
+ pcmd=""
+ rlimit=""
+ progress=""
+ return
+ fi
+
if [[ -n $progress && $progress != '1' ]];then
if [[ -e $progress ]];then
pcmd+=" 2>>$progress"
@@ -282,8 +302,7 @@ read_cnf()
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$\|.*gvwstate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$')
- incremental=$(parse_cnf sst incremental 0)
+ cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*\.sst$\|.*gvwstate\.dat$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$')
ealgo=$(parse_cnf xtrabackup encrypt "")
ekey=$(parse_cnf xtrabackup encrypt-key "")
ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "")
@@ -304,6 +323,20 @@ read_cnf()
iapts=$(parse_cnf sst inno-apply-opts "")
impts=$(parse_cnf sst inno-move-opts "")
stimeout=$(parse_cnf sst sst-initial-timeout 100)
+ ssyslog=$(parse_cnf sst sst-syslog 0)
+ ssystag=$(parse_cnf mysqld_safe syslog-tag "${SST_SYSLOG_TAG:-}")
+ ssystag+="-"
+
+ if [[ $speciald -eq 0 ]];then
+ wsrep_log_error "sst-special-dirs equal to 0 is not supported, falling back to 1"
+ speciald=1
+ fi
+
+ if [[ $ssyslog -ne -1 ]];then
+ if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld_safe | tr '_' '-' | grep -q -- "--syslog";then
+ ssyslog=1
+ fi
+ fi
}
get_stream()
@@ -347,8 +380,7 @@ cleanup_joiner()
local estatus=$?
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus"
- fi
- if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
+ elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
wsrep_log_info "Removing the sst_in_progress file"
wsrep_cleanup_progress_file
fi
@@ -359,6 +391,23 @@ cleanup_joiner()
if [[ -n ${STATDIR:-} ]];then
[[ -d $STATDIR ]] && rm -rf $STATDIR
fi
+
+ # Final cleanup
+ pgid=$(ps -o pgid= $$ | grep -o '[0-9]*')
+
+ # This means no setsid done in mysqld.
+ # We don't want to kill mysqld here otherwise.
+ if [[ $$ -eq $pgid ]];then
+
+ # This means a signal was delivered to the process.
+ # So, more cleanup.
+ if [[ $estatus -ge 128 ]];then
+ kill -KILL -$$ || true
+ fi
+
+ fi
+
+ exit $estatus
}
check_pid()
@@ -399,6 +448,24 @@ cleanup_donor()
if [[ -n $itmpdir ]];then
[[ -d $itmpdir ]] && rm -rf $itmpdir || true
fi
+
+ # Final cleanup
+ pgid=$(ps -o pgid= $$ | grep -o '[0-9]*')
+
+ # This means no setsid done in mysqld.
+ # We don't want to kill mysqld here otherwise.
+ if [[ $$ -eq $pgid ]];then
+
+ # This means a signal was delivered to the process.
+ # So, more cleanup.
+ if [[ $estatus -ge 128 ]];then
+ kill -KILL -$$ || true
+ fi
+
+ fi
+
+ exit $estatus
+
}
kill_xtrabackup()
@@ -415,6 +482,7 @@ setup_ports()
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 }')
+ sst_ver=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $5 }')
else
SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }')
fi
@@ -432,11 +500,7 @@ wait_for_listen()
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
+ echo "ready ${ADDR}/${MODULE}//$sst_ver"
}
check_extra()
@@ -444,7 +508,7 @@ 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)
+ 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.
@@ -469,8 +533,14 @@ recv_joiner()
local dir=$1
local msg=$2
local tmt=$3
+ local checkf=$4
local ltcmd
+ if [[ ! -d ${dir} ]];then
+ # This indicates that IST is in progress
+ return
+ fi
+
pushd ${dir} 1>/dev/null
set +e
@@ -478,7 +548,7 @@ recv_joiner()
if timeout --help | grep -q -- '-k';then
ltcmd="timeout -k $(( tmt+10 )) $tmt $tcmd"
else
- ltcmd="timeout $tmt $tcmd"
+ ltcmd="timeout -s9 $tmt $tcmd"
fi
timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
else
@@ -501,7 +571,7 @@ recv_joiner()
fi
done
- if [ ! -r "${MAGIC_FILE}" ];then
+ if [[ $checkf -eq 1 && ! -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"
@@ -547,18 +617,52 @@ fi
read_cnf
setup_ports
-get_stream
-get_transfer
-if ${INNOBACKUPEX_BIN} /tmp --help | grep -- '--version-check' >/dev/null ; then
+if ${INNOBACKUPEX_BIN} /tmp --help 2>/dev/null | grep -q -- '--version-check'; then
disver="--no-version-check"
fi
+if [[ ${FORCE_FTWRL:-0} -eq 1 ]];then
+ wsrep_log_info "Forcing FTWRL due to environment variable FORCE_FTWRL equal to $FORCE_FTWRL"
+ iopts+=" --no-backup-locks "
+fi
+
INNOEXTRA=""
-INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log"
-INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log"
-INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2>\${DATA}/innobackup.backup.log"
+
+if [[ $ssyslog -eq 1 ]];then
+
+ if [[ ! -x `which logger` ]];then
+ wsrep_log_error "logger not in path: $PATH. Ignoring"
+ else
+
+ wsrep_log_info "Logging all stderr of SST/Innobackupex to syslog"
+
+ exec 2> >(logger -p daemon.err -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE)
+
+ wsrep_log_error()
+ {
+ logger -p daemon.err -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE "$@"
+ }
+
+ wsrep_log_info()
+ {
+ logger -p daemon.info -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE "$@"
+ }
+
+ INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply "
+ INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move "
+ INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)"
+ fi
+
+else
+ INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log"
+ INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log"
+ INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2>\${DATA}/innobackup.backup.log"
+fi
+
+get_stream
+get_transfer
if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
then
@@ -566,6 +670,11 @@ then
if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
then
+ if [[ -z $sst_ver ]];then
+ wsrep_log_error "Upgrade joiner to 5.6.21 or higher for backup locks support"
+ wsrep_log_error "The joiner is not supported for this version of donor"
+ exit 93
+ fi
if [[ -z $(parse_cnf mysqld tmpdir "") && -z $(parse_cnf xtrabackup tmpdir "") ]];then
xtmpdir=$(mktemp -d)
@@ -576,13 +685,14 @@ then
itmpdir=$(mktemp -d)
wsrep_log_info "Using $itmpdir as innobackupex temporary directory"
- if [ "${AUTH[0]}" != "(null)" ]; then
- INNOEXTRA+=" --user=${AUTH[0]}"
- fi
+ if [ "$WSREP_SST_OPT_USER" != "(null)" ]; then
+ INNOEXTRA+=" --user=$WSREP_SST_OPT_USER"
+ fi
- if [ ${#AUTH[*]} -eq 2 ]; then
- INNOEXTRA+=" --password=${AUTH[1]}"
- elif [ "${AUTH[0]}" != "(null)" ]; then
+ if [ -n "$WSREP_SST_OPT_PSWD" ]; then
+# INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD"
+ export MYSQL_PWD="$WSREP_SST_OPT_PSWD"
+ else
# Empty password, used for testing, debugging etc.
INNOEXTRA+=" --password="
fi
@@ -596,9 +706,6 @@ then
fi
fi
- if [[ -n $lsn ]];then
- INNOEXTRA+=" --incremental --incremental-lsn=$lsn "
- fi
check_extra
@@ -686,25 +793,12 @@ 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
- 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
+ ib_home_dir=$(parse_cnf mysqld innodb-data-home-dir "")
+ ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "")
+ ib_undo_dir=$(parse_cnf mysqld innodb-undo-directory "")
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
@@ -733,12 +827,6 @@ then
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
@@ -752,7 +840,8 @@ then
STATDIR=$(mktemp -d)
MAGIC_FILE="${STATDIR}/${INFO_FILE}"
- recv_joiner $STATDIR "${stagemsg}-gtid" $stimeout
+ recv_joiner $STATDIR "${stagemsg}-gtid" $stimeout 1
+
if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null
then
@@ -762,51 +851,48 @@ then
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"
+ if [[ -d ${DATA}/.sst ]];then
+ wsrep_log_info "WARNING: Stale temporary SST directory: ${DATA}/.sst from previous state transfer"
fi
+ mkdir -p ${DATA}/.sst
+ (recv_joiner $DATA/.sst "${stagemsg}-SST" 0 0) &
+ jpid=$!
+ wsrep_log_info "Proceeding with SST"
- 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
- rm $binlog_dir/*.state || true
- fi
- fi
- else
- wsrep_log_info "Removing existing ib_logfile files"
- rm -f ${BDATA}/ib_logfile*
+ wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories"
+ find $ib_home_dir $ib_log_dir $ib_undo_dir $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+
+
+ 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 \+ || true
+ rm $binlog_dir/*.index || true
+ fi
fi
- if [[ $speciald -eq 1 ]];then
- mkdir -p ${DATA}/.sst
- TDATA=${DATA}
- DATA="${DATA}/.sst"
- fi
+
+ TDATA=${DATA}
+ DATA="${DATA}/.sst"
MAGIC_FILE="${DATA}/${INFO_FILE}"
- recv_joiner $DATA "${stagemsg}-SST" 0
+ wsrep_log_info "Waiting for SST streaming to complete!"
+ wait $jpid
get_proc
+ if [[ ! -s ${DATA}/xtrabackup_checkpoints ]];then
+ wsrep_log_error "xtrabackup_checkpoints missing, failed innobackupex/SST on donor"
+ exit 2
+ fi
+
# Rebuild indexes for compact backups
if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then
wsrep_log_info "Index compaction detected"
@@ -878,11 +964,6 @@ then
fi
- if [[ $incremental -eq 1 ]];then
- # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues.
- INNOAPPLY="${INNOBACKUPEX_BIN} $disver --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} \
- --ibbackup=xtrabackup_56 --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"
@@ -893,28 +974,22 @@ then
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
+ 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"
+ exit 22
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"
@@ -924,6 +999,7 @@ then
wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable"
exit 2
fi
+ wsrep_log_info "Galera co-ords from recovery: $(cat ${MAGIC_FILE})"
cat "${MAGIC_FILE}" # output UUID:seqno
wsrep_log_info "Total time on joiner: $totime seconds"
fi
diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh
index 044f9995580..7279c623288 100644
--- a/scripts/wsrep_sst_xtrabackup.sh
+++ b/scripts/wsrep_sst_xtrabackup.sh
@@ -61,7 +61,6 @@ 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"
@@ -150,7 +149,11 @@ get_transfer()
fi
wsrep_log_info "Using netcat as streamer"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
- tcmd="nc -dl ${TSST_PORT}"
+ if nc -h | grep -q ncat;then
+ tcmd="nc -l ${TSST_PORT}"
+ else
+ tcmd="nc -dl ${TSST_PORT}"
+ fi
else
tcmd="nc ${REMOTEIP} ${TSST_PORT}"
fi
@@ -435,13 +438,14 @@ then
then
TMPDIR="${TMPDIR:-/tmp}"
- if [ "${AUTH[0]}" != "(null)" ]; then
- INNOEXTRA+=" --user=${AUTH[0]}"
- fi
+ if [ "$WSREP_SST_OPT_USER" != "(null)" ]; then
+ INNOEXTRA+=" --user=$WSREP_SST_OPT_USER"
+ fi
- if [ ${#AUTH[*]} -eq 2 ]; then
- INNOEXTRA+=" --password=${AUTH[1]}"
- elif [ "${AUTH[0]}" != "(null)" ]; then
+ if [ -n "$WSREP_SST_OPT_PSWD" ]; then
+# INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD"
+ export MYSQL_PWD="$WSREP_SST_OPT_PSWD"
+ else
# Empty password, used for testing, debugging etc.
INNOEXTRA+=" --password="
fi
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index cc8a6b64526..548db8245c3 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -777,19 +777,10 @@ bool wsrep_start_replication()
wsrep_sst_donor,
bootstrap)))
{
- if (-ESOCKTNOSUPPORT == rcode)
- {
- DBUG_PRINT("wsrep",("unrecognized cluster address: '%s', rcode: %d",
- wsrep_cluster_address, rcode));
- WSREP_ERROR("unrecognized cluster address: '%s', rcode: %d",
- wsrep_cluster_address, rcode);
- }
- else
- {
- DBUG_PRINT("wsrep",("wsrep->connect() failed: %d", rcode));
- WSREP_ERROR("wsrep::connect() failed: %d", rcode);
- }
-
+ DBUG_PRINT("wsrep",("wsrep->connect(%s) failed: %d",
+ wsrep_cluster_address, rcode));
+ WSREP_ERROR("wsrep::connect(%s) failed: %d",
+ wsrep_cluster_address, rcode);
return false;
}
else
diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc
index 6eefb961b62..e7d30d5a9c1 100644
--- a/sql/wsrep_notify.cc
+++ b/sql/wsrep_notify.cc
@@ -97,7 +97,7 @@ void wsrep_notify_status (wsrep_member_status_t status,
return;
}
- wsp::process p(cmd_ptr, "r");
+ wsp::process p(cmd_ptr, "r", NULL);
p.wait();
int err = p.error();
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index 73fd9d9a0f5..b697a557476 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -296,12 +296,14 @@ void wsrep_sst_continue ()
struct sst_thread_arg
{
const char* cmd;
- int err;
+ char** env;
char* ret_str;
+ int err;
mysql_mutex_t lock;
mysql_cond_t cond;
- sst_thread_arg (const char* c) : cmd(c), err(-1), ret_str(0)
+ sst_thread_arg (const char* c, char** e)
+ : cmd(c), env(e), ret_str(0), err(-1)
{
mysql_mutex_init(key_LOCK_wsrep_sst_thread, &lock, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_COND_wsrep_sst_thread, &cond, NULL);
@@ -386,7 +388,7 @@ static void* sst_joiner_thread (void* a)
WSREP_INFO("Running: '%s'", arg->cmd);
- wsp::process proc (arg->cmd, "r");
+ wsp::process proc (arg->cmd, "r", arg->env);
if (proc.pipe() && !proc.error())
{
@@ -460,12 +462,44 @@ static void* sst_joiner_thread (void* a)
return NULL;
}
+#define WSREP_SST_AUTH_ENV "WSREP_SST_OPT_AUTH"
+
+static int sst_append_auth_env(wsp::env& env, const char* sst_auth)
+{
+ int const sst_auth_size= strlen(WSREP_SST_AUTH_ENV) + 1 /* = */
+ + (sst_auth ? strlen(sst_auth) : 0) + 1 /* \0 */;
+
+ wsp::string sst_auth_str(sst_auth_size); // for automatic cleanup on return
+ if (!sst_auth_str()) return -ENOMEM;
+
+ int ret= snprintf(sst_auth_str(), sst_auth_size, "%s=%s",
+ WSREP_SST_AUTH_ENV, sst_auth ? sst_auth : "");
+
+ if (ret < 0 || ret >= sst_auth_size)
+ {
+ WSREP_ERROR("sst_append_auth_env(): snprintf() failed: %d", ret);
+ return (ret < 0 ? ret : -EMSGSIZE);
+ }
+
+ env.append(sst_auth_str());
+ return -env.error();
+}
+
static ssize_t sst_prepare_other (const char* method,
+ const char* sst_auth,
const char* addr_in,
const char** addr_out)
{
- char cmd_str[1024];
- const char* sst_dir= mysql_real_data_home;
+ int const cmd_len= 4096;
+ wsp::string cmd_str(cmd_len);
+
+ if (!cmd_str())
+ {
+ WSREP_ERROR("sst_prepare_other(): could not allocate cmd buffer of %d bytes",
+ cmd_len);
+ return -ENOMEM;
+ }
+
const char* binlog_opt= "";
char* binlog_opt_val= NULL;
@@ -478,37 +512,48 @@ static ssize_t sst_prepare_other (const char* method,
}
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG;
-
- ret= snprintf (cmd_str, sizeof(cmd_str),
+ ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_%s "
WSREP_SST_OPT_ROLE" 'joiner' "
WSREP_SST_OPT_ADDR" '%s' "
- WSREP_SST_OPT_AUTH" '%s' "
WSREP_SST_OPT_DATA" '%s' "
WSREP_SST_OPT_CONF" '%s' "
WSREP_SST_OPT_CONF_SUFFIX" '%s' "
WSREP_SST_OPT_PARENT" '%d'"
" %s '%s' ",
- method, addr_in, (sst_auth_real) ? sst_auth_real : "",
- sst_dir, wsrep_defaults_file, wsrep_defaults_group_suffix,
- (int) getpid(), binlog_opt, binlog_opt_val);
+ method, addr_in, mysql_real_data_home,
+ wsrep_defaults_file, wsrep_defaults_group_suffix,
+ (int)getpid(), binlog_opt, binlog_opt_val);
my_free(binlog_opt_val);
- if (ret < 0 || ret >= (int)sizeof(cmd_str))
+ if (ret < 0 || ret >= cmd_len)
{
WSREP_ERROR("sst_prepare_other(): snprintf() failed: %d", ret);
return (ret < 0 ? ret : -EMSGSIZE);
}
+ wsp::env env(NULL);
+ if (env.error())
+ {
+ WSREP_ERROR("sst_prepare_other(): env. var ctor failed: %d", -env.error());
+ return -env.error();
+ }
+
+ if ((ret= sst_append_auth_env(env, sst_auth)))
+ {
+ WSREP_ERROR("sst_prepare_other(): appending auth failed: %d", ret);
+ return ret;
+ }
+
pthread_t tmp;
- sst_thread_arg arg(cmd_str);
+ sst_thread_arg arg(cmd_str(), env());
mysql_mutex_lock (&arg.lock);
ret = pthread_create (&tmp, NULL, sst_joiner_thread, &arg);
if (ret)
{
WSREP_ERROR("sst_prepare_other(): pthread_create() failed: %d (%s)",
ret, strerror(ret));
- return ret;
+ return -ret;
}
mysql_cond_wait (&arg.cond, &arg.lock);
@@ -650,7 +695,8 @@ ssize_t wsrep_sst_prepare (void** msg)
return 0;
}
- addr_len = sst_prepare_other (wsrep_sst_method, addr_in, &addr_out);
+ addr_len = sst_prepare_other (wsrep_sst_method, sst_auth_real,
+ addr_in, &addr_out);
if (addr_len < 0)
{
WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.",
@@ -683,13 +729,13 @@ ssize_t wsrep_sst_prepare (void** msg)
}
// helper method for donors
-static int sst_run_shell (const char* cmd_str, int max_tries)
+static int sst_run_shell (const char* cmd_str, char** env, int max_tries)
{
int ret = 0;
for (int tries=1; tries <= max_tries; tries++)
{
- wsp::process proc (cmd_str, "r");
+ wsp::process proc (cmd_str, "r", env);
if (NULL != proc.pipe())
{
@@ -719,17 +765,12 @@ static void sst_reject_queries(my_bool close_conn)
if (TRUE == close_conn) wsrep_close_client_connections(FALSE);
}
-static int sst_mysqldump_check_addr (const char* user, const char* pswd,
- const char* host, const char* port)
-{
- return 0;
-}
-
static int sst_donate_mysqldump (const char* addr,
const wsrep_uuid_t* uuid,
const char* uuid_str,
wsrep_seqno_t seqno,
- bool bypass)
+ bool bypass,
+ char** env) // carries auth info
{
size_t host_len;
const char* port = strchr (addr, ':');
@@ -750,52 +791,40 @@ static int sst_donate_mysqldump (const char* addr,
strncpy (host, addr, host_len - 1);
host[host_len - 1] = '\0';
- const char* auth = sst_auth_real;
- const char* pswd = (auth) ? strchr (auth, ':') : NULL;
- size_t user_len;
+ int const cmd_len= 4096;
+ wsp::string cmd_str(cmd_len);
- if (pswd)
+ if (!cmd_str())
{
- pswd += 1;
- user_len = pswd - auth;
+ WSREP_ERROR("sst_donate_mysqldump(): "
+ "could not allocate cmd buffer of %d bytes", cmd_len);
+ return -ENOMEM;
}
- else
+
+ if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE);
+
+ int ret= snprintf (cmd_str(), cmd_len,
+ "wsrep_sst_mysqldump "
+ WSREP_SST_OPT_HOST" '%s' "
+ WSREP_SST_OPT_PORT" '%s' "
+ WSREP_SST_OPT_LPORT" '%u' "
+ WSREP_SST_OPT_SOCKET" '%s' "
+ WSREP_SST_OPT_CONF" '%s' "
+ WSREP_SST_OPT_GTID" '%s:%lld'"
+ "%s",
+ host, port, mysqld_port, mysqld_unix_port,
+ wsrep_defaults_file, uuid_str,
+ (long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : "");
+
+ if (ret < 0 || ret >= cmd_len)
{
- pswd = "";
- user_len = (auth) ? strlen (auth) + 1 : 1;
+ WSREP_ERROR("sst_donate_mysqldump(): snprintf() failed: %d", ret);
+ return (ret < 0 ? ret : -EMSGSIZE);
}
- char *user= (char *) alloca(user_len);
+ WSREP_DEBUG("Running: '%s'", cmd_str());
- strncpy (user, (auth) ? auth : "", user_len - 1);
- user[user_len - 1] = '\0';
-
- int ret = sst_mysqldump_check_addr (user, pswd, host, port);
- if (!ret)
- {
- char cmd_str[1024];
-
- if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE);
-
- snprintf (cmd_str, sizeof(cmd_str),
- "wsrep_sst_mysqldump "
- WSREP_SST_OPT_USER" '%s' "
- WSREP_SST_OPT_PSWD" '%s' "
- WSREP_SST_OPT_HOST" '%s' "
- WSREP_SST_OPT_PORT" '%s' "
- WSREP_SST_OPT_LPORT" '%u' "
- WSREP_SST_OPT_SOCKET" '%s' "
- WSREP_SST_OPT_CONF" '%s' "
- WSREP_SST_OPT_GTID" '%s:%lld'"
- "%s",
- user, pswd, host, port, mysqld_port, mysqld_unix_port,
- wsrep_defaults_file, uuid_str,
- (long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : "");
-
- WSREP_DEBUG("Running: '%s'", cmd_str);
-
- ret= sst_run_shell (cmd_str, 3);
- }
+ ret= sst_run_shell (cmd_str(), env, 3);
wsrep_gtid_t const state_id = { *uuid, (ret ? WSREP_SEQNO_UNDEFINED : seqno)};
@@ -950,7 +979,7 @@ static void* sst_donor_thread (void* a)
wsp::thd thd(FALSE); // we turn off wsrep_on for this THD so that it can
// operate with wsrep_ready == OFF
- wsp::process proc(arg->cmd, "r");
+ wsp::process proc(arg->cmd, "r", arg->env);
err= proc.error();
@@ -1037,9 +1066,19 @@ static int sst_donate_other (const char* method,
const char* addr,
const char* uuid,
wsrep_seqno_t seqno,
- bool bypass)
+ bool bypass,
+ char** env) // carries auth info
{
- char cmd_str[4096];
+ int const cmd_len= 4096;
+ wsp::string cmd_str(cmd_len);
+
+ if (!cmd_str())
+ {
+ WSREP_ERROR("sst_donate_other(): "
+ "could not allocate cmd buffer of %d bytes", cmd_len);
+ return -ENOMEM;
+ }
+
const char* binlog_opt= "";
char* binlog_opt_val= NULL;
@@ -1051,11 +1090,10 @@ static int sst_donate_other (const char* method,
}
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG;
- ret= snprintf (cmd_str, sizeof(cmd_str),
+ ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_%s "
WSREP_SST_OPT_ROLE" 'donor' "
WSREP_SST_OPT_ADDR" '%s' "
- WSREP_SST_OPT_AUTH" '%s' "
WSREP_SST_OPT_SOCKET" '%s' "
WSREP_SST_OPT_DATA" '%s' "
WSREP_SST_OPT_CONF" '%s' "
@@ -1063,14 +1101,14 @@ static int sst_donate_other (const char* method,
" %s '%s' "
WSREP_SST_OPT_GTID" '%s:%lld'"
"%s",
- method, addr, sst_auth_real, mysqld_unix_port,
- mysql_real_data_home, wsrep_defaults_file,
- wsrep_defaults_group_suffix, binlog_opt, binlog_opt_val,
+ method, addr, mysqld_unix_port, mysql_real_data_home,
+ wsrep_defaults_file, wsrep_defaults_group_suffix,
+ binlog_opt, binlog_opt_val,
uuid, (long long) seqno,
bypass ? " "WSREP_SST_OPT_BYPASS : "");
my_free(binlog_opt_val);
- if (ret < 0 || ret >= (int) sizeof(cmd_str))
+ if (ret < 0 || ret >= cmd_len)
{
WSREP_ERROR("sst_donate_other(): snprintf() failed: %d", ret);
return (ret < 0 ? ret : -EMSGSIZE);
@@ -1079,7 +1117,7 @@ static int sst_donate_other (const char* method,
if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(FALSE);
pthread_t tmp;
- sst_thread_arg arg(cmd_str);
+ sst_thread_arg arg(cmd_str(), env);
mysql_mutex_lock (&arg.lock);
ret = pthread_create (&tmp, NULL, sst_donor_thread, &arg);
if (ret)
@@ -1112,18 +1150,32 @@ wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx,
char uuid_str[37];
wsrep_uuid_print (&current_gtid->uuid, uuid_str, sizeof(uuid_str));
+ wsp::env env(NULL);
+ if (env.error())
+ {
+ WSREP_ERROR("wsrep_sst_donate_cb(): env var ctor failed: %d", -env.error());
+ return WSREP_CB_FAILURE;
+ }
+
int ret;
+ if ((ret= sst_append_auth_env(env, sst_auth_real)))
+ {
+ WSREP_ERROR("wsrep_sst_donate_cb(): appending auth env failed: %d", ret);
+ return WSREP_CB_FAILURE;
+ }
+
if (!strcmp (WSREP_SST_MYSQLDUMP, method))
{
ret = sst_donate_mysqldump(data, &current_gtid->uuid, uuid_str,
- current_gtid->seqno, bypass);
+ current_gtid->seqno, bypass, env());
}
else
{
- ret = sst_donate_other(method, data, uuid_str, current_gtid->seqno,bypass);
+ ret = sst_donate_other(method, data, uuid_str,
+ current_gtid->seqno, bypass, env());
}
- return (ret > 0 ? WSREP_CB_SUCCESS : WSREP_CB_FAILURE);
+ return (ret >= 0 ? WSREP_CB_SUCCESS : WSREP_CB_FAILURE);
}
void wsrep_SE_init_grab()
diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc
index 7a87d38d430..719e8e6b473 100644
--- a/sql/wsrep_utils.cc
+++ b/sql/wsrep_utils.cc
@@ -63,7 +63,7 @@ wsrep_prepend_PATH (const char* path)
size_t const new_path_len(strlen(old_path) + strlen(":") +
strlen(path) + 1);
- char* const new_path (reinterpret_cast<char*>(malloc(new_path_len)));
+ char* const new_path (static_cast<char*>(malloc(new_path_len)));
if (new_path)
{
@@ -89,6 +89,90 @@ wsrep_prepend_PATH (const char* path)
namespace wsp
{
+bool
+env::ctor_common(char** e)
+{
+ env_ = static_cast<char**>(malloc((len_ + 1) * sizeof(char*)));
+
+ if (env_)
+ {
+ for (size_t i(0); i < len_; ++i)
+ {
+ assert(e[i]); // caller should make sure about len_
+ env_[i] = strdup(e[i]);
+ if (!env_[i])
+ {
+ errno_ = errno;
+ WSREP_ERROR("Failed to allocate env. var: %s", e[i]);
+ return true;
+ }
+ }
+
+ env_[len_] = NULL;
+ return false;
+ }
+ else
+ {
+ errno_ = errno;
+ WSREP_ERROR("Failed to allocate env. var vector of length: %zu", len_);
+ return true;
+ }
+}
+
+void
+env::dtor()
+{
+ if (env_)
+ {
+ /* don't need to go beyond the first NULL */
+ for (size_t i(0); env_[i] != NULL; ++i) { free(env_[i]); }
+ free(env_);
+ env_ = NULL;
+ }
+ len_ = 0;
+}
+
+env::env(char** e)
+ : len_(0), env_(NULL), errno_(0)
+{
+ if (!e) { e = environ; }
+ /* count the size of the vector */
+ while (e[len_]) { ++len_; }
+
+ if (ctor_common(e)) dtor();
+}
+
+env::env(const env& e)
+ : len_(e.len_), env_(0), errno_(0)
+{
+ if (ctor_common(e.env_)) dtor();
+}
+
+env::~env() { dtor(); }
+
+int
+env::append(const char* val)
+{
+ char** tmp = static_cast<char**>(realloc(env_, (len_ + 2)*sizeof(char*)));
+
+ if (tmp)
+ {
+ env_ = tmp;
+ env_[len_] = strdup(val);
+
+ if (env_[len_])
+ {
+ ++len_;
+ env_[len_] = NULL;
+ }
+ else errno_ = errno;
+ }
+ else errno_ = errno;
+
+ return errno_;
+}
+
+
#define PIPE_READ 0
#define PIPE_WRITE 1
#define STDIN_FD 0
@@ -98,7 +182,7 @@ namespace wsp
# define POSIX_SPAWN_USEVFORK 0
#endif
-process::process (const char* cmd, const char* type)
+process::process (const char* cmd, const char* type, char** env)
: str_(cmd ? strdup(cmd) : strdup("")), io_(NULL), err_(EINVAL), pid_(0)
{
if (0 == str_)
@@ -120,6 +204,8 @@ process::process (const char* cmd, const char* type)
return;
}
+ if (NULL == env) { env = environ; } // default to global environment
+
int pipe_fds[2] = { -1, };
if (::pipe(pipe_fds))
{
@@ -215,7 +301,7 @@ process::process (const char* cmd, const char* type)
goto cleanup_fact;
}
- err_ = posix_spawnp (&pid_, pargv[0], &fact, &attr, pargv, environ);
+ err_ = posix_spawnp (&pid_, pargv[0], &fact, &attr, pargv, env);
if (err_)
{
WSREP_ERROR ("posix_spawnp(%s) failed: %d (%s)",
@@ -309,6 +395,7 @@ process::wait ()
{
case 126: err_ = EACCES; break; /* Permission denied */
case 127: err_ = ENOENT; break; /* No such file or directory */
+ case 143: err_ = EINTR; break; /* Subprocess killed */
}
WSREP_ERROR("Process completed with error: %s: %d (%s)",
str_, err_, strerror(err_));
diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h
index dfb68bcd1b7..7d864603c7f 100644
--- a/sql/wsrep_utils.h
+++ b/sql/wsrep_utils.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013 Codership Oy <info@codership.com>
+/* Copyright (C) 2013-2015 Codership Oy <info@codership.com>
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
@@ -44,6 +44,25 @@ private:
extern wsp::node_status local_status;
namespace wsp {
+/* a class to manage env vars array */
+class env
+{
+private:
+ size_t len_;
+ char** env_;
+ int errno_;
+ bool ctor_common(char** e);
+ void dtor();
+ env& operator =(env);
+public:
+ explicit env(char** env);
+ explicit env(const env&);
+ ~env();
+ int append(const char* var); /* add a new env. var */
+ int error() const { return errno_; }
+ char** operator()() { return env_; }
+};
+
/* A small class to run external programs. */
class process
{
@@ -56,8 +75,9 @@ private:
public:
/*! @arg type is a pointer to a null-terminated string which must contain
either the letter 'r' for reading or the letter 'w' for writing.
+ @arg env optional null-terminated vector of environment variables
*/
- process (const char* cmd, const char* type);
+ process (const char* cmd, const char* type, char** env);
~process ();
FILE* pipe () { return io_; }
@@ -90,6 +110,8 @@ class string
{
public:
string() : string_(0) {}
+ explicit string(size_t s) : string_(static_cast<char*>(malloc(s))) {}
+ char* operator()() { return string_; }
void set(char* str) { if (string_) free (string_); string_ = str; }
~string() { set (0); }
private: