Commit fa5f18d6 authored by Nirbhay Choubey's avatar Nirbhay Choubey

Merge branch '5.5-galera' into 10.0-galera

parents f533b2b4 37ae601a
...@@ -18,12 +18,12 @@ ...@@ -18,12 +18,12 @@
# so WSREP_VERSION is produced regardless # so WSREP_VERSION is produced regardless
# Set the patch version # Set the patch version
SET(WSREP_PATCH_VERSION "10") SET(WSREP_PATCH_VERSION "12")
# MariaDB addition: Revision number of the last revision merged from # MariaDB addition: Revision number of the last revision merged from
# codership branch visible in @@visible_comment. # codership branch visible in @@visible_comment.
# Branch : codership-mysql/5.6 # Branch : https://github.com/codership/mysql-wsrep/tree/5.5
SET(WSREP_PATCH_REVNO "4144") # Should be updated on every merge. SET(WSREP_PATCH_REVNO "4f81026") # Should be updated on every merge.
# MariaDB: Obtain patch revision number: # MariaDB: Obtain patch revision number:
# Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. # Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set.
......
# Copyright (C) 2012-2014 Codership Oy # Copyright (C) 2012-2015 Codership Oy
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
...@@ -20,8 +20,11 @@ set -u ...@@ -20,8 +20,11 @@ set -u
WSREP_SST_OPT_BYPASS=0 WSREP_SST_OPT_BYPASS=0
WSREP_SST_OPT_BINLOG="" WSREP_SST_OPT_BINLOG=""
WSREP_SST_OPT_CONF_SUFFIX=""
WSREP_SST_OPT_DATA="" 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 while [ $# -gt 0 ]; do
case "$1" in case "$1" in
...@@ -29,10 +32,6 @@ case "$1" in ...@@ -29,10 +32,6 @@ case "$1" in
readonly WSREP_SST_OPT_ADDR="$2" readonly WSREP_SST_OPT_ADDR="$2"
shift shift
;; ;;
'--auth')
WSREP_SST_OPT_AUTH="$2"
shift
;;
'--bypass') '--bypass')
WSREP_SST_OPT_BYPASS=1 WSREP_SST_OPT_BYPASS=1
;; ;;
...@@ -45,7 +44,7 @@ case "$1" in ...@@ -45,7 +44,7 @@ case "$1" in
shift shift
;; ;;
'--defaults-group-suffix') '--defaults-group-suffix')
readonly WSREP_SST_OPT_CONF_SUFFIX="$2" WSREP_SST_OPT_CONF_SUFFIX="$2"
shift shift
;; ;;
'--host') '--host')
...@@ -97,6 +96,7 @@ shift ...@@ -97,6 +96,7 @@ shift
done done
readonly WSREP_SST_OPT_BYPASS readonly WSREP_SST_OPT_BYPASS
readonly WSREP_SST_OPT_BINLOG 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 # try to use my_print_defaults, mysql and mysqldump that come with the sources
# (for MTR suite) # (for MTR suite)
...@@ -124,12 +124,30 @@ else ...@@ -124,12 +124,30 @@ else
MY_PRINT_DEFAULTS=$(which my_print_defaults) MY_PRINT_DEFAULTS=$(which my_print_defaults)
fi fi
wsrep_auth_not_set()
{
[ -z "$WSREP_SST_OPT_AUTH" -o "$WSREP_SST_OPT_AUTH" = "(null)" ]
}
# For Bug:1200727 # For Bug:1200727
if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth"
if [ -z "$WSREP_SST_OPT_AUTH" -o "$WSREP_SST_OPT_AUTH" = "(null)" ];then then
WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2) 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
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:-}" ] if [ -n "${WSREP_SST_OPT_DATA:-}" ]
then then
...@@ -138,7 +156,6 @@ else ...@@ -138,7 +156,6 @@ else
SST_PROGRESS_FILE="" SST_PROGRESS_FILE=""
fi fi
wsrep_log() wsrep_log()
{ {
# echo everything to stderr so that it gets into common error log # echo everything to stderr so that it gets into common error log
......
#!/bin/bash -e #!/bin/bash -ue
# Copyright (C) 2009 Codership Oy # Copyright (C) 2009-2015 Codership Oy
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
...@@ -41,7 +41,6 @@ local_ip() ...@@ -41,7 +41,6 @@ local_ip()
return 1 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_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_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 if test -z "$WSREP_SST_OPT_LPORT"; then wsrep_log_error "LPORT cannot be nil"; exit $EINVAL; fi
...@@ -64,13 +63,18 @@ then ...@@ -64,13 +63,18 @@ then
exit $EINVAL exit $EINVAL
fi fi
# For Bug:1293798 [ -n "$WSREP_SST_OPT_USER" ] && AUTH="-u$WSREP_SST_OPT_USER" || AUTH=
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) # Refs https://github.com/codership/mysql-wsrep/issues/141
WSREP_SST_OPT_PSWD=$(echo $WSREP_SST_OPT_AUTH | cut -d: -f2) # Passing password in MYSQL_PWD environment variable is considered
fi # "extremely insecure" by MySQL Guidelines for Password Security
AUTH="-u$WSREP_SST_OPT_USER" # (https://dev.mysql.com/doc/refman/5.6/en/password-security-user.html)
if test -n "$WSREP_SST_OPT_PSWD"; then AUTH="$AUTH -p$WSREP_SST_OPT_PSWD"; fi # 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;" STOP_WSREP="SET wsrep_on=OFF;"
...@@ -136,15 +140,15 @@ fi ...@@ -136,15 +140,15 @@ fi
MYSQLDUMP="$MYSQLDUMP $AUTH -S$WSREP_SST_OPT_SOCKET \ MYSQLDUMP="$MYSQLDUMP $AUTH -S$WSREP_SST_OPT_SOCKET \
--add-drop-database --add-drop-table --skip-add-locks --create-options \ --add-drop-database --add-drop-table --skip-add-locks --create-options \
--disable-keys --extended-insert --skip-lock-tables --quick --set-charset \ --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 # need to disable logging when loading the dump
# reason is that dump contains ALTER TABLE for log tables, and # reason is that dump contains ALTER TABLE for log tables, and
# this causes an error if logging is enabled # this causes an error if logging is enabled
GENERAL_LOG_OPT=`$MYSQL --skip-column-names -e"$STOP_WSREP SELECT @@GENERAL_LOG"` 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"` 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 GENERAL_LOG=OFF"
$MYSQL -e"$STOP_WSREP SET GLOBAL SLOW_QUERY_LOG=OFF" $MYSQL -e "$STOP_WSREP SET GLOBAL SLOW_QUERY_LOG=OFF"
# commands to restore log settings # commands to restore log settings
RESTORE_GENERAL_LOG="SET GLOBAL GENERAL_LOG=$GENERAL_LOG_OPT;" RESTORE_GENERAL_LOG="SET GLOBAL GENERAL_LOG=$GENERAL_LOG_OPT;"
......
...@@ -32,8 +32,8 @@ wsrep_check_programs rsync ...@@ -32,8 +32,8 @@ wsrep_check_programs rsync
cleanup_joiner() cleanup_joiner()
{ {
wsrep_log_info "Joiner cleanup."
local PID=$(cat "$RSYNC_PID" 2>/dev/null || echo 0) 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 \ [ "0" != "$PID" ] && kill $PID && sleep 0.5 && kill -9 $PID >/dev/null 2>&1 \
|| : || :
rm -rf "$RSYNC_CONF" rm -rf "$RSYNC_CONF"
......
...@@ -29,6 +29,8 @@ ekeyfile="" ...@@ -29,6 +29,8 @@ ekeyfile=""
encrypt=0 encrypt=0
nproc=1 nproc=1
ecode=0 ecode=0
ssyslog=""
ssystag=""
XTRABACKUP_PID="" XTRABACKUP_PID=""
SST_PORT="" SST_PORT=""
REMOTEIP="" REMOTEIP=""
...@@ -40,15 +42,15 @@ progress="" ...@@ -40,15 +42,15 @@ progress=""
ttime=0 ttime=0
totime=0 totime=0
lsn="" lsn=""
incremental=0
ecmd="" ecmd=""
rlimit="" rlimit=""
# Initially # Initially
stagemsg="${WSREP_SST_OPT_ROLE}" stagemsg="${WSREP_SST_OPT_ROLE}"
cpat="" cpat=""
speciald=0 speciald=1
ib_home_dir="" ib_home_dir=""
ib_log_dir="" ib_log_dir=""
ib_undo_dir=""
sfmt="tar" sfmt="tar"
strmcmd="" strmcmd=""
...@@ -70,6 +72,11 @@ xtmpdir="" ...@@ -70,6 +72,11 @@ xtmpdir=""
scomp="" scomp=""
sdecomp="" 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 if which pv &>/dev/null && pv --help | grep -q FORMAT;then
pvopts+=$pvformat pvopts+=$pvformat
fi fi
...@@ -77,7 +84,6 @@ pcmd="pv $pvopts" ...@@ -77,7 +84,6 @@ pcmd="pv $pvopts"
declare -a RC declare -a RC
INNOBACKUPEX_BIN=innobackupex INNOBACKUPEX_BIN=innobackupex
readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
DATA="${WSREP_SST_OPT_DATA}" DATA="${WSREP_SST_OPT_DATA}"
INFO_FILE="xtrabackup_galera_info" INFO_FILE="xtrabackup_galera_info"
IST_FILE="xtrabackup_ist" IST_FILE="xtrabackup_ist"
...@@ -169,7 +175,11 @@ get_transfer() ...@@ -169,7 +175,11 @@ get_transfer()
fi fi
wsrep_log_info "Using netcat as streamer" wsrep_log_info "Using netcat as streamer"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
if nc -h | grep -q ncat;then
tcmd="nc -l ${TSST_PORT}"
else
tcmd="nc -dl ${TSST_PORT}" tcmd="nc -dl ${TSST_PORT}"
fi
else else
tcmd="nc ${REMOTEIP} ${TSST_PORT}" tcmd="nc ${REMOTEIP} ${TSST_PORT}"
fi fi
...@@ -253,6 +263,16 @@ get_footprint() ...@@ -253,6 +263,16 @@ get_footprint()
adjust_progress() 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 [[ -n $progress && $progress != '1' ]];then
if [[ -e $progress ]];then if [[ -e $progress ]];then
pcmd+=" 2>>$progress" pcmd+=" 2>>$progress"
...@@ -282,8 +302,7 @@ read_cnf() ...@@ -282,8 +302,7 @@ read_cnf()
progress=$(parse_cnf sst progress "") progress=$(parse_cnf sst progress "")
rebuild=$(parse_cnf sst rebuild 0) rebuild=$(parse_cnf sst rebuild 0)
ttime=$(parse_cnf sst time 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$') cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*\.sst$\|.*gvwstate\.dat$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$')
incremental=$(parse_cnf sst incremental 0)
ealgo=$(parse_cnf xtrabackup encrypt "") ealgo=$(parse_cnf xtrabackup encrypt "")
ekey=$(parse_cnf xtrabackup encrypt-key "") ekey=$(parse_cnf xtrabackup encrypt-key "")
ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "") ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "")
...@@ -304,6 +323,20 @@ read_cnf() ...@@ -304,6 +323,20 @@ read_cnf()
iapts=$(parse_cnf sst inno-apply-opts "") iapts=$(parse_cnf sst inno-apply-opts "")
impts=$(parse_cnf sst inno-move-opts "") impts=$(parse_cnf sst inno-move-opts "")
stimeout=$(parse_cnf sst sst-initial-timeout 100) 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() get_stream()
...@@ -347,8 +380,7 @@ cleanup_joiner() ...@@ -347,8 +380,7 @@ cleanup_joiner()
local estatus=$? local estatus=$?
if [[ $estatus -ne 0 ]];then if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus" wsrep_log_error "Cleanup after exit with status:$estatus"
fi elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
wsrep_log_info "Removing the sst_in_progress file" wsrep_log_info "Removing the sst_in_progress file"
wsrep_cleanup_progress_file wsrep_cleanup_progress_file
fi fi
...@@ -359,6 +391,23 @@ cleanup_joiner() ...@@ -359,6 +391,23 @@ cleanup_joiner()
if [[ -n ${STATDIR:-} ]];then if [[ -n ${STATDIR:-} ]];then
[[ -d $STATDIR ]] && rm -rf $STATDIR [[ -d $STATDIR ]] && rm -rf $STATDIR
fi 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() check_pid()
...@@ -399,6 +448,24 @@ cleanup_donor() ...@@ -399,6 +448,24 @@ cleanup_donor()
if [[ -n $itmpdir ]];then if [[ -n $itmpdir ]];then
[[ -d $itmpdir ]] && rm -rf $itmpdir || true [[ -d $itmpdir ]] && rm -rf $itmpdir || true
fi 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() kill_xtrabackup()
...@@ -415,6 +482,7 @@ setup_ports() ...@@ -415,6 +482,7 @@ setup_ports()
SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }') lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }')
sst_ver=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $5 }')
else else
SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }') SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }')
fi fi
...@@ -432,11 +500,7 @@ wait_for_listen() ...@@ -432,11 +500,7 @@ wait_for_listen()
ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break
sleep 0.2 sleep 0.2
done done
if [[ $incremental -eq 1 ]];then echo "ready ${ADDR}/${MODULE}//$sst_ver"
echo "ready ${ADDR}/${MODULE}/$lsn"
else
echo "ready ${ADDR}/${MODULE}"
fi
} }
check_extra() check_extra()
...@@ -444,7 +508,7 @@ check_extra() ...@@ -444,7 +508,7 @@ check_extra()
local use_socket=1 local use_socket=1
if [[ $uextra -eq 1 ]];then 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 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 if [[ -n $eport ]];then
# Xtrabackup works only locally. # Xtrabackup works only locally.
# Hence, setting host to 127.0.0.1 unconditionally. # Hence, setting host to 127.0.0.1 unconditionally.
...@@ -469,8 +533,14 @@ recv_joiner() ...@@ -469,8 +533,14 @@ recv_joiner()
local dir=$1 local dir=$1
local msg=$2 local msg=$2
local tmt=$3 local tmt=$3
local checkf=$4
local ltcmd local ltcmd
if [[ ! -d ${dir} ]];then
# This indicates that IST is in progress
return
fi
pushd ${dir} 1>/dev/null pushd ${dir} 1>/dev/null
set +e set +e
...@@ -478,7 +548,7 @@ recv_joiner() ...@@ -478,7 +548,7 @@ recv_joiner()
if timeout --help | grep -q -- '-k';then if timeout --help | grep -q -- '-k';then
ltcmd="timeout -k $(( tmt+10 )) $tmt $tcmd" ltcmd="timeout -k $(( tmt+10 )) $tmt $tcmd"
else else
ltcmd="timeout $tmt $tcmd" ltcmd="timeout -s9 $tmt $tcmd"
fi fi
timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
else else
...@@ -501,7 +571,7 @@ recv_joiner() ...@@ -501,7 +571,7 @@ recv_joiner()
fi fi
done done
if [ ! -r "${MAGIC_FILE}" ];then if [[ $checkf -eq 1 && ! -r "${MAGIC_FILE}" ]];then
# this message should cause joiner to abort # this message should cause joiner to abort
wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'"
wsrep_log_info "Contents of datadir" wsrep_log_info "Contents of datadir"
...@@ -547,18 +617,52 @@ fi ...@@ -547,18 +617,52 @@ fi
read_cnf read_cnf
setup_ports 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" disver="--no-version-check"
fi 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="" 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" if [[ $ssyslog -eq 1 ]];then
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 [[ ! -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" ] if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
then then
...@@ -566,6 +670,11 @@ then ...@@ -566,6 +670,11 @@ then
if [ $WSREP_SST_OPT_BYPASS -eq 0 ] if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
then 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 if [[ -z $(parse_cnf mysqld tmpdir "") && -z $(parse_cnf xtrabackup tmpdir "") ]];then
xtmpdir=$(mktemp -d) xtmpdir=$(mktemp -d)
...@@ -576,13 +685,14 @@ then ...@@ -576,13 +685,14 @@ then
itmpdir=$(mktemp -d) itmpdir=$(mktemp -d)
wsrep_log_info "Using $itmpdir as innobackupex temporary directory" wsrep_log_info "Using $itmpdir as innobackupex temporary directory"
if [ "${AUTH[0]}" != "(null)" ]; then if [ "$WSREP_SST_OPT_USER" != "(null)" ]; then
INNOEXTRA+=" --user=${AUTH[0]}" INNOEXTRA+=" --user=$WSREP_SST_OPT_USER"
fi fi
if [ ${#AUTH[*]} -eq 2 ]; then if [ -n "$WSREP_SST_OPT_PSWD" ]; then
INNOEXTRA+=" --password=${AUTH[1]}" # INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD"
elif [ "${AUTH[0]}" != "(null)" ]; then export MYSQL_PWD="$WSREP_SST_OPT_PSWD"
else
# Empty password, used for testing, debugging etc. # Empty password, used for testing, debugging etc.
INNOEXTRA+=" --password=" INNOEXTRA+=" --password="
fi fi
...@@ -596,9 +706,6 @@ then ...@@ -596,9 +706,6 @@ then
fi fi
fi fi
if [[ -n $lsn ]];then
INNOEXTRA+=" --incremental --incremental-lsn=$lsn "
fi
check_extra check_extra
...@@ -686,25 +793,12 @@ then ...@@ -686,25 +793,12 @@ then
[[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
[[ -n $SST_PROGRESS_FILE ]] && touch $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_home_dir=$(parse_cnf mysqld innodb-data-home-dir "")
ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "") ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "")
if [[ -z $ib_home_dir && -z $ib_log_dir ]];then ib_undo_dir=$(parse_cnf mysqld innodb-undo-directory "")
speciald=0
fi
fi
stagemsg="Joiner-Recv" 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 sencrypted=1
nthreads=1 nthreads=1
...@@ -733,12 +827,6 @@ then ...@@ -733,12 +827,6 @@ then
tcmd+=" | $pcmd" tcmd+=" | $pcmd"
fi fi
if [[ $incremental -eq 1 ]];then
BDATA=$DATA
DATA=$(mktemp -d)
MAGIC_FILE="${DATA}/${INFO_FILE}"
fi
get_keys get_keys
if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
if [[ -n $sdecomp ]];then if [[ -n $sdecomp ]];then
...@@ -752,7 +840,8 @@ then ...@@ -752,7 +840,8 @@ then
STATDIR=$(mktemp -d) STATDIR=$(mktemp -d)
MAGIC_FILE="${STATDIR}/${INFO_FILE}" 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 if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null
then then
...@@ -762,20 +851,19 @@ then ...@@ -762,20 +851,19 @@ then
if [ ! -r "${STATDIR}/${IST_FILE}" ] if [ ! -r "${STATDIR}/${IST_FILE}" ]
then then
wsrep_log_info "Proceeding with SST"
if [[ $speciald -eq 1 && -d ${DATA}/.sst ]];then if [[ -d ${DATA}/.sst ]];then
wsrep_log_info "WARNING: Stale temporary SST directory: ${DATA}/.sst from previous SST" wsrep_log_info "WARNING: Stale temporary SST directory: ${DATA}/.sst from previous state transfer"
fi 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" 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 \+ find $ib_home_dir $ib_log_dir $ib_undo_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 "") tempdir=$(parse_cnf mysqld log-bin "")
if [[ -n ${tempdir:-} ]];then if [[ -n ${tempdir:-} ]];then
binlog_dir=$(dirname $tempdir) binlog_dir=$(dirname $tempdir)
...@@ -783,30 +871,28 @@ then ...@@ -783,30 +871,28 @@ then
if [[ -n ${binlog_dir:-} && $binlog_dir != '.' && $binlog_dir != $DATA ]];then if [[ -n ${binlog_dir:-} && $binlog_dir != '.' && $binlog_dir != $DATA ]];then
pattern="$binlog_dir/$binlog_file\.[0-9]+$" pattern="$binlog_dir/$binlog_file\.[0-9]+$"
wsrep_log_info "Cleaning the binlog directory $binlog_dir as well" 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 \+ find $binlog_dir -maxdepth 1 -type f -regex $pattern -exec rm -fv {} 1>&2 \+ || true
rm $binlog_dir/*.index || true rm $binlog_dir/*.index || true
rm $binlog_dir/*.state || true
fi fi
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} TDATA=${DATA}
DATA="${DATA}/.sst" DATA="${DATA}/.sst"
fi
MAGIC_FILE="${DATA}/${INFO_FILE}" MAGIC_FILE="${DATA}/${INFO_FILE}"
recv_joiner $DATA "${stagemsg}-SST" 0 wsrep_log_info "Waiting for SST streaming to complete!"
wait $jpid
get_proc 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 # Rebuild indexes for compact backups
if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then
wsrep_log_info "Index compaction detected" wsrep_log_info "Index compaction detected"
...@@ -878,11 +964,6 @@ then ...@@ -878,11 +964,6 @@ then
fi 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}" wsrep_log_info "Preparing the backup at ${DATA}"
timeit "Xtrabackup prepare stage" "$INNOAPPLY" timeit "Xtrabackup prepare stage" "$INNOAPPLY"
...@@ -893,7 +974,6 @@ then ...@@ -893,7 +974,6 @@ then
exit 22 exit 22
fi fi
if [[ $speciald -eq 1 ]];then
MAGIC_FILE="${TDATA}/${INFO_FILE}" MAGIC_FILE="${TDATA}/${INFO_FILE}"
set +e set +e
rm $TDATA/innobackup.prepare.log $TDATA/innobackup.move.log rm $TDATA/innobackup.prepare.log $TDATA/innobackup.move.log
...@@ -907,14 +987,9 @@ then ...@@ -907,14 +987,9 @@ then
else else
wsrep_log_error "Move failed, keeping ${DATA} for further diagnosis" wsrep_log_error "Move failed, keeping ${DATA} for further diagnosis"
wsrep_log_error "Check ${DATA}/innobackup.move.log for details" wsrep_log_error "Check ${DATA}/innobackup.move.log for details"
fi exit 22
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 else
wsrep_log_info "${IST_FILE} received from donor: Running IST" wsrep_log_info "${IST_FILE} received from donor: Running IST"
...@@ -924,6 +999,7 @@ then ...@@ -924,6 +999,7 @@ then
wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable" wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable"
exit 2 exit 2
fi fi
wsrep_log_info "Galera co-ords from recovery: $(cat ${MAGIC_FILE})"
cat "${MAGIC_FILE}" # output UUID:seqno cat "${MAGIC_FILE}" # output UUID:seqno
wsrep_log_info "Total time on joiner: $totime seconds" wsrep_log_info "Total time on joiner: $totime seconds"
fi fi
......
...@@ -61,7 +61,6 @@ pcmd="pv $pvopts" ...@@ -61,7 +61,6 @@ pcmd="pv $pvopts"
declare -a RC declare -a RC
INNOBACKUPEX_BIN=innobackupex INNOBACKUPEX_BIN=innobackupex
readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
DATA="${WSREP_SST_OPT_DATA}" DATA="${WSREP_SST_OPT_DATA}"
INFO_FILE="xtrabackup_galera_info" INFO_FILE="xtrabackup_galera_info"
IST_FILE="xtrabackup_ist" IST_FILE="xtrabackup_ist"
...@@ -150,7 +149,11 @@ get_transfer() ...@@ -150,7 +149,11 @@ get_transfer()
fi fi
wsrep_log_info "Using netcat as streamer" wsrep_log_info "Using netcat as streamer"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
if nc -h | grep -q ncat;then
tcmd="nc -l ${TSST_PORT}"
else
tcmd="nc -dl ${TSST_PORT}" tcmd="nc -dl ${TSST_PORT}"
fi
else else
tcmd="nc ${REMOTEIP} ${TSST_PORT}" tcmd="nc ${REMOTEIP} ${TSST_PORT}"
fi fi
...@@ -435,13 +438,14 @@ then ...@@ -435,13 +438,14 @@ then
then then
TMPDIR="${TMPDIR:-/tmp}" TMPDIR="${TMPDIR:-/tmp}"
if [ "${AUTH[0]}" != "(null)" ]; then if [ "$WSREP_SST_OPT_USER" != "(null)" ]; then
INNOEXTRA+=" --user=${AUTH[0]}" INNOEXTRA+=" --user=$WSREP_SST_OPT_USER"
fi fi
if [ ${#AUTH[*]} -eq 2 ]; then if [ -n "$WSREP_SST_OPT_PSWD" ]; then
INNOEXTRA+=" --password=${AUTH[1]}" # INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD"
elif [ "${AUTH[0]}" != "(null)" ]; then export MYSQL_PWD="$WSREP_SST_OPT_PSWD"
else
# Empty password, used for testing, debugging etc. # Empty password, used for testing, debugging etc.
INNOEXTRA+=" --password=" INNOEXTRA+=" --password="
fi fi
......
...@@ -777,19 +777,10 @@ bool wsrep_start_replication() ...@@ -777,19 +777,10 @@ bool wsrep_start_replication()
wsrep_sst_donor, wsrep_sst_donor,
bootstrap))) bootstrap)))
{ {
if (-ESOCKTNOSUPPORT == rcode) DBUG_PRINT("wsrep",("wsrep->connect(%s) failed: %d",
{
DBUG_PRINT("wsrep",("unrecognized cluster address: '%s', rcode: %d",
wsrep_cluster_address, rcode)); wsrep_cluster_address, rcode));
WSREP_ERROR("unrecognized cluster address: '%s', rcode: %d", WSREP_ERROR("wsrep::connect(%s) failed: %d",
wsrep_cluster_address, rcode); wsrep_cluster_address, rcode);
}
else
{
DBUG_PRINT("wsrep",("wsrep->connect() failed: %d", rcode));
WSREP_ERROR("wsrep::connect() failed: %d", rcode);
}
return false; return false;
} }
else else
......
...@@ -97,7 +97,7 @@ void wsrep_notify_status (wsrep_member_status_t status, ...@@ -97,7 +97,7 @@ void wsrep_notify_status (wsrep_member_status_t status,
return; return;
} }
wsp::process p(cmd_ptr, "r"); wsp::process p(cmd_ptr, "r", NULL);
p.wait(); p.wait();
int err = p.error(); int err = p.error();
......
...@@ -296,12 +296,14 @@ void wsrep_sst_continue () ...@@ -296,12 +296,14 @@ void wsrep_sst_continue ()
struct sst_thread_arg struct sst_thread_arg
{ {
const char* cmd; const char* cmd;
int err; char** env;
char* ret_str; char* ret_str;
int err;
mysql_mutex_t lock; mysql_mutex_t lock;
mysql_cond_t cond; 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_mutex_init(key_LOCK_wsrep_sst_thread, &lock, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_COND_wsrep_sst_thread, &cond, NULL); mysql_cond_init(key_COND_wsrep_sst_thread, &cond, NULL);
...@@ -386,7 +388,7 @@ static void* sst_joiner_thread (void* a) ...@@ -386,7 +388,7 @@ static void* sst_joiner_thread (void* a)
WSREP_INFO("Running: '%s'", arg->cmd); 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()) if (proc.pipe() && !proc.error())
{ {
...@@ -460,12 +462,44 @@ static void* sst_joiner_thread (void* a) ...@@ -460,12 +462,44 @@ static void* sst_joiner_thread (void* a)
return NULL; 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, static ssize_t sst_prepare_other (const char* method,
const char* sst_auth,
const char* addr_in, const char* addr_in,
const char** addr_out) const char** addr_out)
{ {
char cmd_str[1024]; int const cmd_len= 4096;
const char* sst_dir= mysql_real_data_home; 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= ""; const char* binlog_opt= "";
char* binlog_opt_val= NULL; char* binlog_opt_val= NULL;
...@@ -478,37 +512,48 @@ static ssize_t sst_prepare_other (const char* method, ...@@ -478,37 +512,48 @@ static ssize_t sst_prepare_other (const char* method,
} }
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG; if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG;
ret= snprintf (cmd_str(), cmd_len,
ret= snprintf (cmd_str, sizeof(cmd_str),
"wsrep_sst_%s " "wsrep_sst_%s "
WSREP_SST_OPT_ROLE" 'joiner' " WSREP_SST_OPT_ROLE" 'joiner' "
WSREP_SST_OPT_ADDR" '%s' " WSREP_SST_OPT_ADDR" '%s' "
WSREP_SST_OPT_AUTH" '%s' "
WSREP_SST_OPT_DATA" '%s' " WSREP_SST_OPT_DATA" '%s' "
WSREP_SST_OPT_CONF" '%s' " WSREP_SST_OPT_CONF" '%s' "
WSREP_SST_OPT_CONF_SUFFIX" '%s' " WSREP_SST_OPT_CONF_SUFFIX" '%s' "
WSREP_SST_OPT_PARENT" '%d'" WSREP_SST_OPT_PARENT" '%d'"
" %s '%s' ", " %s '%s' ",
method, addr_in, (sst_auth_real) ? sst_auth_real : "", method, addr_in, mysql_real_data_home,
sst_dir, wsrep_defaults_file, wsrep_defaults_group_suffix, wsrep_defaults_file, wsrep_defaults_group_suffix,
(int) getpid(), binlog_opt, binlog_opt_val); (int)getpid(), binlog_opt, binlog_opt_val);
my_free(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); WSREP_ERROR("sst_prepare_other(): snprintf() failed: %d", ret);
return (ret < 0 ? ret : -EMSGSIZE); 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; pthread_t tmp;
sst_thread_arg arg(cmd_str); sst_thread_arg arg(cmd_str(), env());
mysql_mutex_lock (&arg.lock); mysql_mutex_lock (&arg.lock);
ret = pthread_create (&tmp, NULL, sst_joiner_thread, &arg); ret = pthread_create (&tmp, NULL, sst_joiner_thread, &arg);
if (ret) if (ret)
{ {
WSREP_ERROR("sst_prepare_other(): pthread_create() failed: %d (%s)", WSREP_ERROR("sst_prepare_other(): pthread_create() failed: %d (%s)",
ret, strerror(ret)); ret, strerror(ret));
return ret; return -ret;
} }
mysql_cond_wait (&arg.cond, &arg.lock); mysql_cond_wait (&arg.cond, &arg.lock);
...@@ -650,7 +695,8 @@ ssize_t wsrep_sst_prepare (void** msg) ...@@ -650,7 +695,8 @@ ssize_t wsrep_sst_prepare (void** msg)
return 0; 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) if (addr_len < 0)
{ {
WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.", WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.",
...@@ -683,13 +729,13 @@ ssize_t wsrep_sst_prepare (void** msg) ...@@ -683,13 +729,13 @@ ssize_t wsrep_sst_prepare (void** msg)
} }
// helper method for donors // 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; int ret = 0;
for (int tries=1; tries <= max_tries; tries++) 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()) if (NULL != proc.pipe())
{ {
...@@ -719,17 +765,12 @@ static void sst_reject_queries(my_bool close_conn) ...@@ -719,17 +765,12 @@ static void sst_reject_queries(my_bool close_conn)
if (TRUE == close_conn) wsrep_close_client_connections(FALSE); 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, static int sst_donate_mysqldump (const char* addr,
const wsrep_uuid_t* uuid, const wsrep_uuid_t* uuid,
const char* uuid_str, const char* uuid_str,
wsrep_seqno_t seqno, wsrep_seqno_t seqno,
bool bypass) bool bypass,
char** env) // carries auth info
{ {
size_t host_len; size_t host_len;
const char* port = strchr (addr, ':'); const char* port = strchr (addr, ':');
...@@ -750,37 +791,20 @@ static int sst_donate_mysqldump (const char* addr, ...@@ -750,37 +791,20 @@ static int sst_donate_mysqldump (const char* addr,
strncpy (host, addr, host_len - 1); strncpy (host, addr, host_len - 1);
host[host_len - 1] = '\0'; host[host_len - 1] = '\0';
const char* auth = sst_auth_real; int const cmd_len= 4096;
const char* pswd = (auth) ? strchr (auth, ':') : NULL; wsp::string cmd_str(cmd_len);
size_t user_len;
if (pswd) if (!cmd_str())
{
pswd += 1;
user_len = pswd - auth;
}
else
{ {
pswd = ""; WSREP_ERROR("sst_donate_mysqldump(): "
user_len = (auth) ? strlen (auth) + 1 : 1; "could not allocate cmd buffer of %d bytes", cmd_len);
return -ENOMEM;
} }
char *user= (char *) alloca(user_len);
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); if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE);
snprintf (cmd_str, sizeof(cmd_str), int ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_mysqldump " "wsrep_sst_mysqldump "
WSREP_SST_OPT_USER" '%s' "
WSREP_SST_OPT_PSWD" '%s' "
WSREP_SST_OPT_HOST" '%s' " WSREP_SST_OPT_HOST" '%s' "
WSREP_SST_OPT_PORT" '%s' " WSREP_SST_OPT_PORT" '%s' "
WSREP_SST_OPT_LPORT" '%u' " WSREP_SST_OPT_LPORT" '%u' "
...@@ -788,15 +812,20 @@ static int sst_donate_mysqldump (const char* addr, ...@@ -788,15 +812,20 @@ static int sst_donate_mysqldump (const char* addr,
WSREP_SST_OPT_CONF" '%s' " WSREP_SST_OPT_CONF" '%s' "
WSREP_SST_OPT_GTID" '%s:%lld'" WSREP_SST_OPT_GTID" '%s:%lld'"
"%s", "%s",
user, pswd, host, port, mysqld_port, mysqld_unix_port, host, port, mysqld_port, mysqld_unix_port,
wsrep_defaults_file, uuid_str, wsrep_defaults_file, uuid_str,
(long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : ""); (long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : "");
WSREP_DEBUG("Running: '%s'", cmd_str); if (ret < 0 || ret >= cmd_len)
{
ret= sst_run_shell (cmd_str, 3); WSREP_ERROR("sst_donate_mysqldump(): snprintf() failed: %d", ret);
return (ret < 0 ? ret : -EMSGSIZE);
} }
WSREP_DEBUG("Running: '%s'", cmd_str());
ret= sst_run_shell (cmd_str(), env, 3);
wsrep_gtid_t const state_id = { *uuid, (ret ? WSREP_SEQNO_UNDEFINED : seqno)}; wsrep_gtid_t const state_id = { *uuid, (ret ? WSREP_SEQNO_UNDEFINED : seqno)};
wsrep->sst_sent (wsrep, &state_id, ret); wsrep->sst_sent (wsrep, &state_id, ret);
...@@ -950,7 +979,7 @@ static void* sst_donor_thread (void* a) ...@@ -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 wsp::thd thd(FALSE); // we turn off wsrep_on for this THD so that it can
// operate with wsrep_ready == OFF // operate with wsrep_ready == OFF
wsp::process proc(arg->cmd, "r"); wsp::process proc(arg->cmd, "r", arg->env);
err= proc.error(); err= proc.error();
...@@ -1037,9 +1066,19 @@ static int sst_donate_other (const char* method, ...@@ -1037,9 +1066,19 @@ static int sst_donate_other (const char* method,
const char* addr, const char* addr,
const char* uuid, const char* uuid,
wsrep_seqno_t seqno, 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= ""; const char* binlog_opt= "";
char* binlog_opt_val= NULL; char* binlog_opt_val= NULL;
...@@ -1051,11 +1090,10 @@ static int sst_donate_other (const char* method, ...@@ -1051,11 +1090,10 @@ static int sst_donate_other (const char* method,
} }
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG; 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_%s "
WSREP_SST_OPT_ROLE" 'donor' " WSREP_SST_OPT_ROLE" 'donor' "
WSREP_SST_OPT_ADDR" '%s' " WSREP_SST_OPT_ADDR" '%s' "
WSREP_SST_OPT_AUTH" '%s' "
WSREP_SST_OPT_SOCKET" '%s' " WSREP_SST_OPT_SOCKET" '%s' "
WSREP_SST_OPT_DATA" '%s' " WSREP_SST_OPT_DATA" '%s' "
WSREP_SST_OPT_CONF" '%s' " WSREP_SST_OPT_CONF" '%s' "
...@@ -1063,14 +1101,14 @@ static int sst_donate_other (const char* method, ...@@ -1063,14 +1101,14 @@ static int sst_donate_other (const char* method,
" %s '%s' " " %s '%s' "
WSREP_SST_OPT_GTID" '%s:%lld'" WSREP_SST_OPT_GTID" '%s:%lld'"
"%s", "%s",
method, addr, sst_auth_real, mysqld_unix_port, method, addr, mysqld_unix_port, mysql_real_data_home,
mysql_real_data_home, wsrep_defaults_file, wsrep_defaults_file, wsrep_defaults_group_suffix,
wsrep_defaults_group_suffix, binlog_opt, binlog_opt_val, binlog_opt, binlog_opt_val,
uuid, (long long) seqno, uuid, (long long) seqno,
bypass ? " "WSREP_SST_OPT_BYPASS : ""); bypass ? " "WSREP_SST_OPT_BYPASS : "");
my_free(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_donate_other(): snprintf() failed: %d", ret); WSREP_ERROR("sst_donate_other(): snprintf() failed: %d", ret);
return (ret < 0 ? ret : -EMSGSIZE); return (ret < 0 ? ret : -EMSGSIZE);
...@@ -1079,7 +1117,7 @@ static int sst_donate_other (const char* method, ...@@ -1079,7 +1117,7 @@ static int sst_donate_other (const char* method,
if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(FALSE); if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(FALSE);
pthread_t tmp; pthread_t tmp;
sst_thread_arg arg(cmd_str); sst_thread_arg arg(cmd_str(), env);
mysql_mutex_lock (&arg.lock); mysql_mutex_lock (&arg.lock);
ret = pthread_create (&tmp, NULL, sst_donor_thread, &arg); ret = pthread_create (&tmp, NULL, sst_donor_thread, &arg);
if (ret) if (ret)
...@@ -1112,18 +1150,32 @@ wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, ...@@ -1112,18 +1150,32 @@ wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx,
char uuid_str[37]; char uuid_str[37];
wsrep_uuid_print (&current_gtid->uuid, uuid_str, sizeof(uuid_str)); 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; 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)) if (!strcmp (WSREP_SST_MYSQLDUMP, method))
{ {
ret = sst_donate_mysqldump(data, &current_gtid->uuid, uuid_str, ret = sst_donate_mysqldump(data, &current_gtid->uuid, uuid_str,
current_gtid->seqno, bypass); current_gtid->seqno, bypass, env());
} }
else 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() void wsrep_SE_init_grab()
......
...@@ -63,7 +63,7 @@ wsrep_prepend_PATH (const char* path) ...@@ -63,7 +63,7 @@ wsrep_prepend_PATH (const char* path)
size_t const new_path_len(strlen(old_path) + strlen(":") + size_t const new_path_len(strlen(old_path) + strlen(":") +
strlen(path) + 1); 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) if (new_path)
{ {
...@@ -89,6 +89,90 @@ wsrep_prepend_PATH (const char* path) ...@@ -89,6 +89,90 @@ wsrep_prepend_PATH (const char* path)
namespace wsp 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_READ 0
#define PIPE_WRITE 1 #define PIPE_WRITE 1
#define STDIN_FD 0 #define STDIN_FD 0
...@@ -98,7 +182,7 @@ namespace wsp ...@@ -98,7 +182,7 @@ namespace wsp
# define POSIX_SPAWN_USEVFORK 0 # define POSIX_SPAWN_USEVFORK 0
#endif #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) : str_(cmd ? strdup(cmd) : strdup("")), io_(NULL), err_(EINVAL), pid_(0)
{ {
if (0 == str_) if (0 == str_)
...@@ -120,6 +204,8 @@ process::process (const char* cmd, const char* type) ...@@ -120,6 +204,8 @@ process::process (const char* cmd, const char* type)
return; return;
} }
if (NULL == env) { env = environ; } // default to global environment
int pipe_fds[2] = { -1, }; int pipe_fds[2] = { -1, };
if (::pipe(pipe_fds)) if (::pipe(pipe_fds))
{ {
...@@ -215,7 +301,7 @@ process::process (const char* cmd, const char* type) ...@@ -215,7 +301,7 @@ process::process (const char* cmd, const char* type)
goto cleanup_fact; 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_) if (err_)
{ {
WSREP_ERROR ("posix_spawnp(%s) failed: %d (%s)", WSREP_ERROR ("posix_spawnp(%s) failed: %d (%s)",
...@@ -309,6 +395,7 @@ process::wait () ...@@ -309,6 +395,7 @@ process::wait ()
{ {
case 126: err_ = EACCES; break; /* Permission denied */ case 126: err_ = EACCES; break; /* Permission denied */
case 127: err_ = ENOENT; break; /* No such file or directory */ 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)", WSREP_ERROR("Process completed with error: %s: %d (%s)",
str_, err_, strerror(err_)); str_, err_, strerror(err_));
......
/* 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 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 it under the terms of the GNU General Public License as published by
...@@ -44,6 +44,25 @@ class node_status ...@@ -44,6 +44,25 @@ class node_status
extern wsp::node_status local_status; extern wsp::node_status local_status;
namespace wsp { 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. */ /* A small class to run external programs. */
class process class process
{ {
...@@ -56,8 +75,9 @@ class process ...@@ -56,8 +75,9 @@ class process
public: public:
/*! @arg type is a pointer to a null-terminated string which must contain /*! @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. 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 (); ~process ();
FILE* pipe () { return io_; } FILE* pipe () { return io_; }
...@@ -90,6 +110,8 @@ class string ...@@ -90,6 +110,8 @@ class string
{ {
public: public:
string() : string_(0) {} 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; } void set(char* str) { if (string_) free (string_); string_ = str; }
~string() { set (0); } ~string() { set (0); }
private: private:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment