mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merged revisions 3409..3411 from mariadb-galera-5.5
This commit is contained in:
@ -72,6 +72,9 @@ RelWithDebInfo
|
||||
.vimrc
|
||||
ac_available_languages_fragment
|
||||
BitKeeper/
|
||||
build_debug
|
||||
build_install
|
||||
build_release
|
||||
client/*.ds?
|
||||
client/completion_hash.cpp
|
||||
client/decimal.c
|
||||
|
@ -13,8 +13,30 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
if(APPLE)
|
||||
LIST(APPEND CMAKE_CXX_LINK_EXECUTABLE "dsymutil <TARGET>")
|
||||
LIST(APPEND CMAKE_C_LINK_EXECUTABLE "dsymutil <TARGET>")
|
||||
LIST(APPEND CMAKE_CXX_CREATE_SHARED_LIBRARY "dsymutil <TARGET>")
|
||||
LIST(APPEND CMAKE_C_CREATE_SHARED_LIBRARY "dsymutil <TARGET>")
|
||||
LIST(APPEND CMAKE_CXX_CREATE_SHARED_MODULE "dsymutil <TARGET>")
|
||||
LIST(APPEND CMAKE_C_CREATE_SHARED_MODULE "dsymutil <TARGET>")
|
||||
ENDIF()
|
||||
|
||||
GET_FILENAME_COMPONENT(MYSQL_CMAKE_SCRIPT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
INCLUDE(${MYSQL_CMAKE_SCRIPT_DIR}/cmake_parse_arguments.cmake)
|
||||
MACRO (INSTALL_DSYM_DIRECTORIES targets)
|
||||
IF(APPLE)
|
||||
FOREACH(target ${targets})
|
||||
GET_TARGET_PROPERTY(location ${target} LOCATION)
|
||||
GET_TARGET_PROPERTY(type ${target} TYPE)
|
||||
# It's a dirty hack, but cmake too stupid and mysql cmake files too buggy */
|
||||
STRING(REPLACE "liblibmysql.dylib" "libmysqlclient.${SHARED_LIB_MAJOR_VERSION}.dylib" location ${location})
|
||||
IF(type MATCHES "EXECUTABLE" OR type MATCHES "MODULE" OR type MATCHES "SHARED_LIBRARY")
|
||||
INSTALL(DIRECTORY "${location}.dSYM" DESTINATION ${INSTALL_LOCATION} COMPONENT Debuginfo)
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
|
||||
FUNCTION (INSTALL_DEBUG_SYMBOLS)
|
||||
IF(MSVC)
|
||||
@ -31,6 +53,7 @@ FUNCTION (INSTALL_DEBUG_SYMBOLS)
|
||||
MESSAGE(FATAL_ERROR "No INSTALL_LOCATION passed to INSTALL_DEBUG_SYMBOLS")
|
||||
ENDIF()
|
||||
SET(targets ${ARG_DEFAULT_ARGS})
|
||||
|
||||
FOREACH(target ${targets})
|
||||
GET_TARGET_PROPERTY(type ${target} TYPE)
|
||||
GET_TARGET_PROPERTY(location ${target} LOCATION)
|
||||
@ -252,6 +275,7 @@ FUNCTION(MYSQL_INSTALL_TARGETS)
|
||||
|
||||
INSTALL(TARGETS ${TARGETS} DESTINATION ${ARG_DESTINATION} ${COMP})
|
||||
INSTALL_DEBUG_SYMBOLS(${TARGETS} ${COMP} INSTALL_LOCATION ${ARG_DESTINATION})
|
||||
INSTALL_DSYM_DIRECTORIES("${TARGETS}")
|
||||
|
||||
ENDFUNCTION()
|
||||
|
||||
|
@ -32,3 +32,9 @@ IF(EXECINFO)
|
||||
SET(LIBEXECINFO ${EXECINFO})
|
||||
ENDIF()
|
||||
|
||||
<<<<<<< TREE
|
||||
=======
|
||||
|
||||
SET(HAVE_SYS_TIMEB_H CACHE INTERNAL "")
|
||||
|
||||
>>>>>>> MERGE-SOURCE
|
||||
|
@ -239,7 +239,8 @@ wsrep_recover_position() {
|
||||
if [ -z "$rp" ]; then
|
||||
local skipped="$(grep WSREP $wr_logfile | grep 'skipping position recovery')"
|
||||
if [ -z "$skipped" ]; then
|
||||
log_error "WSREP: Failed to recover position: " `cat $wr_logfile`;
|
||||
log_error "WSREP: Failed to recover position:
|
||||
'`cat $wr_logfile`'"
|
||||
ret=1
|
||||
else
|
||||
log_notice "WSREP: Position recovery skipped"
|
||||
@ -251,7 +252,7 @@ wsrep_recover_position() {
|
||||
wsrep_start_position_opt="--wsrep_start_position=$start_pos"
|
||||
fi
|
||||
|
||||
rm $wr_logfile
|
||||
[ $ret -eq 0 ] && rm $wr_logfile
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
261
scripts/wsrep_sst_rsync.sh.moved
Executable file
261
scripts/wsrep_sst_rsync.sh.moved
Executable file
@ -0,0 +1,261 @@
|
||||
#!/bin/bash -ue
|
||||
|
||||
# Copyright (C) 2010 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
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to the
|
||||
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston
|
||||
# MA 02110-1301 USA.
|
||||
|
||||
# This is a reference script for rsync-based state snapshot tansfer
|
||||
|
||||
RSYNC_PID=
|
||||
RSYNC_CONF=
|
||||
OS=$(uname)
|
||||
[ "$OS" == "Darwin" ] && export -n LD_LIBRARY_PATH
|
||||
|
||||
. $(dirname $0)/wsrep_sst_common
|
||||
|
||||
cleanup_joiner()
|
||||
{
|
||||
wsrep_log_info "Joiner cleanup."
|
||||
local PID=$(cat "$RSYNC_PID" 2>/dev/null || echo 0)
|
||||
[ "0" != "$PID" ] && kill $PID && sleep 0.5 && kill -9 $PID >/dev/null 2>&1 \
|
||||
|| :
|
||||
rm -rf "$RSYNC_CONF"
|
||||
rm -rf "$MAGIC_FILE"
|
||||
rm -rf "$RSYNC_PID"
|
||||
wsrep_log_info "Joiner cleanup done."
|
||||
if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
|
||||
wsrep_cleanup_progress_file
|
||||
fi
|
||||
}
|
||||
|
||||
check_pid()
|
||||
{
|
||||
local pid_file=$1
|
||||
[ -r "$pid_file" ] && ps -p $(cat $pid_file) >/dev/null 2>&1
|
||||
}
|
||||
|
||||
check_pid_and_port()
|
||||
{
|
||||
local pid_file=$1
|
||||
local rsync_pid=$(cat $pid_file)
|
||||
local rsync_port=$2
|
||||
|
||||
if [ "$OS" == "Darwin" -o "$OS" == "FreeBSD" ]; then
|
||||
# no netstat --program(-p) option in Darwin and FreeBSD
|
||||
check_pid $pid_file && \
|
||||
lsof -i -Pn 2>/dev/null | \
|
||||
grep "(LISTEN)" | grep ":$rsync_port" | grep -w '^rsync[[:space:]]\+'"$rsync_pid" >/dev/null
|
||||
else
|
||||
check_pid $pid_file && \
|
||||
netstat -lnpt 2>/dev/null | \
|
||||
grep LISTEN | grep \:$rsync_port | grep $rsync_pid/rsync >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete"
|
||||
rm -rf "$MAGIC_FILE"
|
||||
|
||||
# Old filter - include everything except selected
|
||||
# FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \
|
||||
# --exclude '*.conf' --exclude core --exclude 'galera.*' \
|
||||
# --exclude grastate.txt --exclude '*.pem' \
|
||||
# --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index')
|
||||
|
||||
# New filter - exclude everything except dirs (schemas) and innodb files
|
||||
FILTER=(-f '- lost+found' -f '+ /ib_lru_dump' -f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*')
|
||||
# Old versions of rsync have a bug transferring filter rules to daemon, so specify filter rules directly to daemon
|
||||
FILTER_DAEMON="- lost+found + /ib_lru_dump + /ibdata* + ib_logfile* + */ -! */*"
|
||||
|
||||
if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
|
||||
then
|
||||
|
||||
if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
|
||||
then
|
||||
|
||||
FLUSHED="$WSREP_SST_OPT_DATA/tables_flushed"
|
||||
rm -rf "$FLUSHED"
|
||||
|
||||
# Use deltaxfer only for WAN
|
||||
inv=$(basename $0)
|
||||
[ "$inv" = "wsrep_sst_rsync_wan" ] && WHOLE_FILE_OPT="" \
|
||||
|| WHOLE_FILE_OPT="--whole-file"
|
||||
|
||||
echo "flush tables"
|
||||
|
||||
# wait for tables flushed and state ID written to the file
|
||||
while [ ! -r "$FLUSHED" ] && ! grep -q ':' "$FLUSHED" >/dev/null 2>&1
|
||||
do
|
||||
sleep 0.2
|
||||
done
|
||||
|
||||
STATE="$(cat $FLUSHED)"
|
||||
rm -rf "$FLUSHED"
|
||||
|
||||
sync
|
||||
|
||||
# first, the normal directories, so that we can detect incompatible protocol
|
||||
RC=0
|
||||
rsync --archive --no-times --ignore-times --inplace --delete --quiet \
|
||||
--no-recursive --dirs \
|
||||
$WHOLE_FILE_OPT "${FILTER[@]}" "$WSREP_SST_OPT_DATA/" \
|
||||
rsync://$WSREP_SST_OPT_ADDR-with_filter || RC=$?
|
||||
|
||||
[ $RC -ne 0 ] && wsrep_log_error "rsync returned code $RC:"
|
||||
|
||||
case $RC in
|
||||
0) RC=0 # Success
|
||||
;;
|
||||
12) RC=71 # EPROTO
|
||||
wsrep_log_error \
|
||||
"rsync server on the other end has incompatible protocol. " \
|
||||
"Make sure you have the same version of rsync on all nodes."
|
||||
;;
|
||||
22) RC=12 # ENOMEM
|
||||
;;
|
||||
*) RC=255 # unknown error
|
||||
;;
|
||||
esac
|
||||
|
||||
[ $RC -ne 0 ] && exit $RC
|
||||
|
||||
# then, we parallelize the transfer of database directories, use . so that pathconcatenation works
|
||||
pushd "$WSREP_SST_OPT_DATA" 1>/dev/null
|
||||
|
||||
count=1
|
||||
[ "$OS" == "Linux" ] && count=$(grep -c processor /proc/cpuinfo)
|
||||
[ "$OS" == "Darwin" -o "$OS" == "FreeBSD" ] && count=$(sysctl -n hw.ncpu)
|
||||
|
||||
find . -maxdepth 1 -mindepth 1 -type d -print0 | xargs -I{} -0 -P $count \
|
||||
rsync --archive --no-times --ignore-times --inplace --delete --quiet \
|
||||
$WHOLE_FILE_OPT "$WSREP_SST_OPT_DATA"/{}/ \
|
||||
rsync://$WSREP_SST_OPT_ADDR/{} || RC=$?
|
||||
|
||||
popd 1>/dev/null
|
||||
|
||||
[ $RC -ne 0 ] && wsrep_log_error "find/rsync returned code $RC:"
|
||||
|
||||
case $RC in
|
||||
0) RC=0 # Success
|
||||
;;
|
||||
*) RC=255 # unknown error
|
||||
;;
|
||||
esac
|
||||
|
||||
[ $RC -ne 0 ] && exit $RC
|
||||
|
||||
|
||||
else # BYPASS
|
||||
wsrep_log_info "Bypassing state dump."
|
||||
STATE="$WSREP_SST_OPT_GTID"
|
||||
fi
|
||||
|
||||
echo "continue" # now server can resume updating data
|
||||
|
||||
echo "$STATE" > "$MAGIC_FILE"
|
||||
rsync --archive --quiet --checksum "$MAGIC_FILE" rsync://$WSREP_SST_OPT_ADDR
|
||||
|
||||
echo "done $STATE"
|
||||
|
||||
elif [ "$WSREP_SST_OPT_ROLE" = "joiner" ]
|
||||
then
|
||||
touch $SST_PROGRESS_FILE
|
||||
MYSQLD_PID=$WSREP_SST_OPT_PARENT
|
||||
|
||||
MODULE="rsync_sst"
|
||||
|
||||
RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid"
|
||||
|
||||
if check_pid $RSYNC_PID
|
||||
then
|
||||
wsrep_log_error "rsync daemon already running."
|
||||
exit 114 # EALREADY
|
||||
fi
|
||||
rm -rf "$RSYNC_PID"
|
||||
|
||||
ADDR=$WSREP_SST_OPT_ADDR
|
||||
RSYNC_PORT=$(echo $ADDR | awk -F ':' '{ print $2 }')
|
||||
if [ -z "$RSYNC_PORT" ]
|
||||
then
|
||||
RSYNC_PORT=4444
|
||||
ADDR="$(echo $ADDR | awk -F ':' '{ print $1 }'):$RSYNC_PORT"
|
||||
fi
|
||||
|
||||
trap "exit 32" HUP PIPE
|
||||
trap "exit 3" INT TERM ABRT
|
||||
trap cleanup_joiner EXIT
|
||||
|
||||
MYUID=$(id -u)
|
||||
MYGID=$(id -g)
|
||||
RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf"
|
||||
|
||||
cat << EOF > "$RSYNC_CONF"
|
||||
pid file = $RSYNC_PID
|
||||
use chroot = no
|
||||
[$MODULE-with_filter]
|
||||
path = $WSREP_SST_OPT_DATA
|
||||
read only = no
|
||||
timeout = 300
|
||||
uid = $MYUID
|
||||
gid = $MYGID
|
||||
filter = $FILTER_DAEMON
|
||||
[$MODULE]
|
||||
path = $WSREP_SST_OPT_DATA
|
||||
read only = no
|
||||
timeout = 300
|
||||
uid = $MYUID
|
||||
gid = $MYGID
|
||||
EOF
|
||||
|
||||
# rm -rf "$DATA"/ib_logfile* # we don't want old logs around
|
||||
|
||||
# listen at all interfaces (for firewalled setups)
|
||||
rsync --daemon --port $RSYNC_PORT --config "$RSYNC_CONF"
|
||||
|
||||
until check_pid_and_port $RSYNC_PID $RSYNC_PORT
|
||||
do
|
||||
sleep 0.2
|
||||
done
|
||||
|
||||
echo "ready $ADDR/$MODULE"
|
||||
|
||||
# wait for SST to complete by monitoring magic file
|
||||
while [ ! -r "$MAGIC_FILE" ] && check_pid "$RSYNC_PID" && \
|
||||
ps -p $MYSQLD_PID >/dev/null
|
||||
do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if ! ps -p $MYSQLD_PID >/dev/null
|
||||
then
|
||||
wsrep_log_error \
|
||||
"Parent mysqld process (PID:$MYSQLD_PID) terminated unexpectedly."
|
||||
exit 32
|
||||
fi
|
||||
|
||||
if [ -r "$MAGIC_FILE" ]
|
||||
then
|
||||
cat "$MAGIC_FILE" # output UUID:seqno
|
||||
else
|
||||
# this message should cause joiner to abort
|
||||
echo "rsync process ended without creating '$MAGIC_FILE'"
|
||||
fi
|
||||
wsrep_cleanup_progress_file
|
||||
# cleanup_joiner
|
||||
else
|
||||
wsrep_log_error "Unrecognized role: '$WSREP_SST_OPT_ROLE'"
|
||||
exit 22 # EINVAL
|
||||
fi
|
||||
|
||||
exit 0
|
481
scripts/wsrep_sst_xtrabackup.sh.moved
Normal file
481
scripts/wsrep_sst_xtrabackup.sh.moved
Normal file
@ -0,0 +1,481 @@
|
||||
#!/bin/bash -ue
|
||||
# Copyright (C) 2013 Percona Inc
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to the
|
||||
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston
|
||||
# MA 02110-1301 USA.
|
||||
|
||||
#############################################################################################################
|
||||
# This is a reference script for Percona XtraBackup-based state snapshot transfer #
|
||||
# Dependencies: (depending on configuration) #
|
||||
# xbcrypt for encryption/decryption. #
|
||||
# qpress for decompression. Download from http://www.quicklz.com/qpress-11-linux-x64.tar till #
|
||||
# https://blueprints.launchpad.net/percona-xtrabackup/+spec/package-qpress is fixed. #
|
||||
# my_print_defaults to extract values from my.cnf. #
|
||||
# netcat for transfer. #
|
||||
# xbstream/tar for streaming. (and xtrabackup ofc) #
|
||||
# #
|
||||
# Currently only option in cnf is read specifically for SST #
|
||||
# [sst] #
|
||||
# streamfmt=tar|xbstream #
|
||||
# #
|
||||
# Default is tar till lp:1193240 is fixed #
|
||||
# You need to use xbstream for encryption, compression etc., however, #
|
||||
# lp:1193240 requires you to manually cleanup the directory prior to SST #
|
||||
# #
|
||||
#############################################################################################################
|
||||
|
||||
. $(dirname $0)/wsrep_sst_common
|
||||
|
||||
ealgo=""
|
||||
ekey=""
|
||||
ekeyfile=""
|
||||
encrypt=0
|
||||
nproc=1
|
||||
ecode=0
|
||||
XTRABACKUP_PID=""
|
||||
|
||||
sfmt="tar"
|
||||
strmcmd=""
|
||||
declare -a RC
|
||||
|
||||
get_keys()
|
||||
{
|
||||
# There is no metadata in the stream to indicate that it is encrypted
|
||||
# So, if the cnf file on joiner contains 'encrypt' under [xtrabackup] section then
|
||||
# it means encryption is being used
|
||||
if ! my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then
|
||||
return
|
||||
fi
|
||||
if [[ $sfmt == 'tar' ]];then
|
||||
wsrep_log_info "NOTE: Encryption cannot be enabled with tar format"
|
||||
return
|
||||
fi
|
||||
|
||||
wsrep_log_info "Encryption enabled in my.cnf - not supported at the moment - Bug in Xtrabackup - lp:1190343"
|
||||
ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2)
|
||||
ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2)
|
||||
ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2)
|
||||
|
||||
if [[ -z $ealgo ]];then
|
||||
wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
if [[ -z $ekey && ! -r $ekeyfile ]];then
|
||||
wsrep_log_error "FATAL: Either key or keyfile must be readable"
|
||||
exit 3
|
||||
fi
|
||||
encrypt=1
|
||||
}
|
||||
|
||||
read_cnf()
|
||||
{
|
||||
sfmt=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- '--streamfmt' | cut -d= -f2)
|
||||
if [[ $sfmt == 'xbstream' ]];then
|
||||
wsrep_log_info "Streaming with xbstream"
|
||||
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
|
||||
wsrep_log_info "xbstream requires manual cleanup of data directory before SST - lp:1193240"
|
||||
strmcmd="xbstream -x -C ${DATA}"
|
||||
elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
|
||||
strmcmd="xbstream -c ${INFO_FILE} ${IST_FILE}"
|
||||
else
|
||||
wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE"
|
||||
exit 22
|
||||
fi
|
||||
else
|
||||
sfmt="tar"
|
||||
wsrep_log_info "Streaming with tar"
|
||||
wsrep_log_info "Note: Advanced xtrabackup features - encryption,compression etc. not available with tar."
|
||||
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
|
||||
wsrep_log_info "However, xbstream requires manual cleanup of data directory before SST - lp:1193240."
|
||||
strmcmd="tar xfi - -C ${DATA}"
|
||||
elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
|
||||
strmcmd="tar cf - ${INFO_FILE} ${IST_FILE}"
|
||||
else
|
||||
wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE"
|
||||
exit 22
|
||||
fi
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
get_proc()
|
||||
{
|
||||
set +e
|
||||
nproc=$(grep -c processor /proc/cpuinfo)
|
||||
[[ -z $nproc || $nproc -eq 0 ]] && nproc=1
|
||||
set -e
|
||||
}
|
||||
|
||||
cleanup_joiner()
|
||||
{
|
||||
# Since this is invoked just after exit NNN
|
||||
local estatus=$?
|
||||
if [[ $estatus -ne 0 ]];then
|
||||
wsrep_log_error "Cleanup after exit with status:$estatus"
|
||||
fi
|
||||
local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }')
|
||||
if [[ $estatus -ne 0 ]];then
|
||||
wsrep_log_error "Killing nc pid $PID"
|
||||
else
|
||||
wsrep_log_info "Killing nc pid $PID"
|
||||
fi
|
||||
[ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
|
||||
rm -f "$MAGIC_FILE"
|
||||
if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
|
||||
wsrep_log_info "Removing the sst_in_progress file"
|
||||
wsrep_cleanup_progress_file
|
||||
fi
|
||||
}
|
||||
|
||||
check_pid()
|
||||
{
|
||||
local pid_file="$1"
|
||||
[ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1
|
||||
}
|
||||
|
||||
cleanup_donor()
|
||||
{
|
||||
# Since this is invoked just after exit NNN
|
||||
local estatus=$?
|
||||
if [[ $estatus -ne 0 ]];then
|
||||
wsrep_log_error "Cleanup after exit with status:$estatus"
|
||||
fi
|
||||
local pid=$XTRABACKUP_PID
|
||||
if check_pid "$pid"
|
||||
then
|
||||
wsrep_log_error "xtrabackup process is still running. Killing... "
|
||||
kill_xtrabackup
|
||||
fi
|
||||
|
||||
rm -f "$pid"
|
||||
rm -f ${DATA}/${IST_FILE}
|
||||
}
|
||||
|
||||
kill_xtrabackup()
|
||||
{
|
||||
#set -x
|
||||
local PID=$(cat $XTRABACKUP_PID)
|
||||
[ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
|
||||
rm -f "$XTRABACKUP_PID"
|
||||
#set +x
|
||||
}
|
||||
|
||||
# waits ~10 seconds for nc to open the port and then reports ready
|
||||
# (regardless of timeout)
|
||||
wait_for_nc()
|
||||
{
|
||||
local PORT=$1
|
||||
local ADDR=$2
|
||||
local MODULE=$3
|
||||
for i in $(seq 1 50)
|
||||
do
|
||||
netstat -nptl 2>/dev/null | grep '/nc\s*$' | awk '{ print $4 }' | \
|
||||
sed 's/.*://' | grep \^${PORT}\$ >/dev/null && break
|
||||
sleep 0.2
|
||||
done
|
||||
echo "ready ${ADDR}/${MODULE}"
|
||||
}
|
||||
|
||||
INNOBACKUPEX_BIN=innobackupex
|
||||
INNOBACKUPEX_ARGS=""
|
||||
NC_BIN=nc
|
||||
|
||||
for TOOL_BIN in INNOBACKUPEX_BIN NC_BIN ; do
|
||||
if ! which ${!TOOL_BIN} > /dev/null 2>&1
|
||||
then
|
||||
echo "Can't find ${!TOOL_BIN} in the path"
|
||||
exit 22 # EINVAL
|
||||
fi
|
||||
done
|
||||
|
||||
#ROLE=$1
|
||||
#ADDR=$2
|
||||
readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
|
||||
readonly DATA="${WSREP_SST_OPT_DATA}"
|
||||
#CONF=$5
|
||||
|
||||
INFO_FILE="xtrabackup_galera_info"
|
||||
IST_FILE="xtrabackup_ist"
|
||||
|
||||
MAGIC_FILE="${DATA}/${INFO_FILE}"
|
||||
rm -f "${MAGIC_FILE}"
|
||||
|
||||
read_cnf
|
||||
|
||||
if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
|
||||
then
|
||||
trap cleanup_donor EXIT
|
||||
|
||||
NC_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
|
||||
REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
|
||||
|
||||
if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
|
||||
then
|
||||
TMPDIR="/tmp"
|
||||
|
||||
INNOBACKUPEX_ARGS="--galera-info --stream=$sfmt
|
||||
--defaults-file=${WSREP_SST_OPT_CONF}
|
||||
--socket=${WSREP_SST_OPT_SOCKET}"
|
||||
|
||||
if [ "${AUTH[0]}" != "(null)" ]; then
|
||||
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --user=${AUTH[0]}"
|
||||
fi
|
||||
|
||||
if [ ${#AUTH[*]} -eq 2 ]; then
|
||||
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=${AUTH[1]}"
|
||||
else
|
||||
# Empty password, used for testing, debugging etc.
|
||||
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password="
|
||||
fi
|
||||
|
||||
get_keys
|
||||
if [[ $encrypt -eq 1 ]];then
|
||||
if [[ -n $ekey ]];then
|
||||
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key=$ekey"
|
||||
else
|
||||
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key-file=$ekeyfile"
|
||||
fi
|
||||
fi
|
||||
|
||||
wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${NC_PORT}"
|
||||
|
||||
set +e
|
||||
${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \
|
||||
2> ${DATA}/innobackup.backup.log | \
|
||||
${NC_BIN} ${REMOTEIP} ${NC_PORT}
|
||||
|
||||
RC=( "${PIPESTATUS[@]}" )
|
||||
set -e
|
||||
|
||||
if [ ${RC[0]} -ne 0 ]; then
|
||||
wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \
|
||||
"Check ${DATA}/innobackup.backup.log"
|
||||
exit 22
|
||||
elif [ ${RC[1]} -ne 0 ]; then
|
||||
wsrep_log_error "${NC_BIN} finished with error: ${RC[1]}"
|
||||
exit 22
|
||||
fi
|
||||
|
||||
# innobackupex implicitly writes PID to fixed location in ${TMPDIR}
|
||||
XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid"
|
||||
|
||||
|
||||
else # BYPASS
|
||||
wsrep_log_info "Bypassing the SST for IST"
|
||||
STATE="${WSREP_SST_OPT_GTID}"
|
||||
echo "continue" # now server can resume updating data
|
||||
echo "${STATE}" > "${MAGIC_FILE}"
|
||||
echo "1" > "${DATA}/${IST_FILE}"
|
||||
get_keys
|
||||
pushd ${DATA} 1>/dev/null
|
||||
set +e
|
||||
if [[ $encrypt -eq 1 ]];then
|
||||
if [[ -n $ekey ]];then
|
||||
xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
|
||||
else
|
||||
xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
|
||||
fi
|
||||
else
|
||||
$strmcmd | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
|
||||
fi
|
||||
RC=( "${PIPESTATUS[@]}" )
|
||||
set -e
|
||||
popd 1>/dev/null
|
||||
|
||||
for ecode in "${RC[@]}";do
|
||||
if [[ $ecode -ne 0 ]];then
|
||||
wsrep_log_error "Error while streaming data to joiner node: " \
|
||||
"exit codes: ${RC[@]}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
#rm -f ${DATA}/${IST_FILE}
|
||||
fi
|
||||
|
||||
echo "done ${WSREP_SST_OPT_GTID}"
|
||||
|
||||
elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ]
|
||||
then
|
||||
[[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
|
||||
touch $SST_PROGRESS_FILE
|
||||
|
||||
sencrypted=1
|
||||
nthreads=1
|
||||
|
||||
MODULE="xtrabackup_sst"
|
||||
|
||||
rm -f ${DATA}/xtrabackup_*
|
||||
|
||||
ADDR=${WSREP_SST_OPT_ADDR}
|
||||
NC_PORT=$(echo ${ADDR} | awk -F ':' '{ print $2 }')
|
||||
if [ -z "${NC_PORT}" ]
|
||||
then
|
||||
NC_PORT=4444
|
||||
ADDR="$(echo ${ADDR} | awk -F ':' '{ print $1 }'):${NC_PORT}"
|
||||
fi
|
||||
|
||||
wait_for_nc ${NC_PORT} ${ADDR} ${MODULE} &
|
||||
|
||||
trap "exit 32" HUP PIPE
|
||||
trap "exit 3" INT TERM
|
||||
trap cleanup_joiner EXIT
|
||||
|
||||
get_keys
|
||||
set +e
|
||||
if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
|
||||
if [[ -n $ekey ]];then
|
||||
${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey | xbstream -x -C ${DATA}
|
||||
else
|
||||
${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | xbstream -x -C ${DATA}
|
||||
fi
|
||||
else
|
||||
${NC_BIN} -dl ${NC_PORT} | $strmcmd
|
||||
fi
|
||||
RC=( "${PIPESTATUS[@]}" )
|
||||
set -e
|
||||
|
||||
if [[ $sfmt == 'xbstream' ]];then
|
||||
# Special handling till lp:1193240 is fixed"
|
||||
if [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
|
||||
wsrep_log_error "Xbstream failed"
|
||||
wsrep_log_error "Data directory ${DATA} needs to be empty for SST: lp:1193240" \
|
||||
"Manual intervention required in that case"
|
||||
exit 32
|
||||
fi
|
||||
fi
|
||||
|
||||
wait %% # join wait_for_nc thread
|
||||
|
||||
for ecode in "${RC[@]}";do
|
||||
if [[ $ecode -ne 0 ]];then
|
||||
wsrep_log_error "Error while getting data from donor node: " \
|
||||
"exit codes: ${RC[@]}"
|
||||
wsrep_log_error "Data directory ${DATA} needs to be empty for SST:" \
|
||||
"Manual intervention required in that case"
|
||||
exit 32
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -r "${MAGIC_FILE}" ]
|
||||
then
|
||||
# this message should cause joiner to abort
|
||||
wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'"
|
||||
exit 32
|
||||
fi
|
||||
|
||||
if ! ps -p ${WSREP_SST_OPT_PARENT} >/dev/null
|
||||
then
|
||||
wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly."
|
||||
exit 32
|
||||
fi
|
||||
|
||||
if [ ! -r "${IST_FILE}" ]
|
||||
then
|
||||
wsrep_log_info "Proceeding with SST"
|
||||
rebuild=""
|
||||
wsrep_log_info "Removing existing ib_logfile files"
|
||||
rm -f ${DATA}/ib_logfile*
|
||||
|
||||
# Decrypt only if not encrypted in stream.
|
||||
# NOT USED NOW.
|
||||
# Till https://blueprints.launchpad.net/percona-xtrabackup/+spec/add-support-for-rsync-url
|
||||
# is implemented
|
||||
#get_keys
|
||||
if [[ $encrypt -eq 1 && $sencrypted -eq 0 ]];then
|
||||
# Decrypt the files if any
|
||||
find ${DATA} -type f -name '*.xbcrypt' -printf '%p\n' | while read line;do
|
||||
input=$line
|
||||
output=${input%.xbcrypt}
|
||||
|
||||
if [[ -n $ekey ]];then
|
||||
xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey -i $input > $output
|
||||
else
|
||||
xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile -i $input > $output
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $? = 0 ]];then
|
||||
find ${DATA} -type f -name '*.xbcrypt' -delete
|
||||
fi
|
||||
fi
|
||||
|
||||
get_proc
|
||||
|
||||
# Rebuild indexes for compact backups
|
||||
if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then
|
||||
wsrep_log_info "Index compaction detected"
|
||||
nthreads=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--rebuild-threads' | cut -d= -f2)
|
||||
[[ -z $nthreads ]] && nthreads=$nproc
|
||||
wsrep_log_info "Rebuilding with $nthreads threads"
|
||||
rebuild="--rebuild-indexes --rebuild-threads=$nthreads"
|
||||
fi
|
||||
|
||||
if test -n "$(find ${DATA} -maxdepth 1 -name '*.qp' -print -quit)";then
|
||||
|
||||
wsrep_log_info "Compressed qpress files found"
|
||||
|
||||
if [[ ! -x `which qpress` ]];then
|
||||
wsrep_log_error "qpress not found in PATH"
|
||||
exit 22
|
||||
fi
|
||||
|
||||
set +e
|
||||
|
||||
wsrep_log_info "Removing existing ibdata1 file"
|
||||
rm -f ${DATA}/ibdata1
|
||||
|
||||
# Decompress the qpress files
|
||||
wsrep_log_info "Decompression with $nproc threads"
|
||||
find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | xargs -P $nproc -n 2 qpress -d
|
||||
extcode=$?
|
||||
|
||||
set -e
|
||||
|
||||
if [[ $extcode -eq 0 ]];then
|
||||
wsrep_log_info "Removing qpress files after decompression"
|
||||
find ${DATA} -type f -name '*.qp' -delete
|
||||
if [[ $? -ne 0 ]];then
|
||||
wsrep_log_error "Something went wrong with deletion of qpress files. Investigate"
|
||||
fi
|
||||
else
|
||||
wsrep_log_error "Decompression failed. Exit code: $extcode"
|
||||
exit 22
|
||||
fi
|
||||
fi
|
||||
|
||||
wsrep_log_info "Preparing the backup at ${DATA}"
|
||||
|
||||
${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log $rebuild \
|
||||
${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log
|
||||
if [ $? -ne 0 ];
|
||||
then
|
||||
wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log"
|
||||
exit 22
|
||||
fi
|
||||
else
|
||||
wsrep_log_info "${IST_FILE} received from donor: Running IST"
|
||||
fi
|
||||
|
||||
cat "${MAGIC_FILE}" # output UUID:seqno
|
||||
|
||||
#Cleanup not required here since EXIT trap should be called
|
||||
#wsrep_cleanup_progress_file
|
||||
|
||||
else
|
||||
wsrep_log_error "Unrecognized role: ${WSREP_SST_OPT_ROLE}"
|
||||
exit 22 # EINVAL
|
||||
fi
|
||||
|
||||
exit 0
|
@ -9019,13 +9019,11 @@ void wsrep_replication_process(THD *thd)
|
||||
break;
|
||||
}
|
||||
|
||||
if (thd->killed != KILL_CONNECTION)
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_thread_count);
|
||||
wsrep_close_applier(thd);
|
||||
mysql_cond_broadcast(&COND_thread_count);
|
||||
mysql_mutex_unlock(&LOCK_thread_count);
|
||||
}
|
||||
mysql_mutex_lock(&LOCK_thread_count);
|
||||
wsrep_close_applier(thd);
|
||||
mysql_cond_broadcast(&COND_thread_count);
|
||||
mysql_mutex_unlock(&LOCK_thread_count);
|
||||
|
||||
wsrep_return_from_bf_mode(thd, &shadow);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
468
sql/wsrep_utils.cc.moved
Normal file
468
sql/wsrep_utils.cc.moved
Normal file
@ -0,0 +1,468 @@
|
||||
/* Copyright 2010 Codership Oy <http://www.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
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
//! @file declares symbols private to wsrep integration layer
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE // POSIX_SPAWN_USEVFORK flag
|
||||
#endif
|
||||
|
||||
#include <spawn.h> // posix_spawn()
|
||||
#include <unistd.h> // pipe()
|
||||
#include <errno.h> // errno
|
||||
#include <string.h> // strerror()
|
||||
#include <sys/wait.h> // waitpid()
|
||||
|
||||
#include <sql_class.h>
|
||||
#include "wsrep_priv.h"
|
||||
|
||||
extern char** environ; // environment variables
|
||||
|
||||
static wsp::string wsrep_PATH;
|
||||
|
||||
void
|
||||
wsrep_prepend_PATH (const char* path)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while (environ[count])
|
||||
{
|
||||
if (strncmp (environ[count], "PATH=", 5))
|
||||
{
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
char* const old_path (environ[count]);
|
||||
|
||||
if (strstr (old_path, path)) return; // path already there
|
||||
|
||||
size_t const new_path_len(strlen(old_path) + strlen(":") +
|
||||
strlen(path) + 1);
|
||||
|
||||
char* const new_path (reinterpret_cast<char*>(malloc(new_path_len)));
|
||||
|
||||
if (new_path)
|
||||
{
|
||||
snprintf (new_path, new_path_len, "PATH=%s:%s", path,
|
||||
old_path + strlen("PATH="));
|
||||
|
||||
wsrep_PATH.set (new_path);
|
||||
environ[count] = new_path;
|
||||
}
|
||||
else
|
||||
{
|
||||
WSREP_ERROR ("Failed to allocate 'PATH' environment variable "
|
||||
"buffer of size %zu.", new_path_len);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
WSREP_ERROR ("Failed to find 'PATH' environment variable. "
|
||||
"State snapshot transfer may not be working.");
|
||||
}
|
||||
|
||||
namespace wsp
|
||||
{
|
||||
|
||||
#define PIPE_READ 0
|
||||
#define PIPE_WRITE 1
|
||||
#define STDIN_FD 0
|
||||
#define STDOUT_FD 1
|
||||
|
||||
#ifndef POSIX_SPAWN_USEVFORK
|
||||
# define POSIX_SPAWN_USEVFORK 0
|
||||
#endif
|
||||
|
||||
process::process (const char* cmd, const char* type)
|
||||
: str_(cmd ? strdup(cmd) : strdup("")), io_(NULL), err_(EINVAL), pid_(0)
|
||||
{
|
||||
if (0 == str_)
|
||||
{
|
||||
WSREP_ERROR ("Can't allocate command line of size: %zu", strlen(cmd));
|
||||
err_ = ENOMEM;
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == strlen(str_))
|
||||
{
|
||||
WSREP_ERROR ("Can't start a process: null or empty command line.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (NULL == type || (strcmp (type, "w") && strcmp(type, "r")))
|
||||
{
|
||||
WSREP_ERROR ("type argument should be either \"r\" or \"w\".");
|
||||
return;
|
||||
}
|
||||
|
||||
int pipe_fds[2] = { -1, };
|
||||
if (::pipe(pipe_fds))
|
||||
{
|
||||
err_ = errno;
|
||||
WSREP_ERROR ("pipe() failed: %d (%s)", err_, strerror(err_));
|
||||
return;
|
||||
}
|
||||
|
||||
// which end of pipe will be returned to parent
|
||||
int const parent_end (strcmp(type,"w") ? PIPE_READ : PIPE_WRITE);
|
||||
int const child_end (parent_end == PIPE_READ ? PIPE_WRITE : PIPE_READ);
|
||||
int const close_fd (parent_end == PIPE_READ ? STDOUT_FD : STDIN_FD);
|
||||
|
||||
char* const pargv[4] = { strdup("sh"), strdup("-c"), strdup(str_), NULL };
|
||||
if (!(pargv[0] && pargv[1] && pargv[2]))
|
||||
{
|
||||
err_ = ENOMEM;
|
||||
WSREP_ERROR ("Failed to allocate pargv[] array.");
|
||||
goto cleanup_pipe;
|
||||
}
|
||||
|
||||
posix_spawnattr_t attr;
|
||||
err_ = posix_spawnattr_init (&attr);
|
||||
if (err_)
|
||||
{
|
||||
WSREP_ERROR ("posix_spawnattr_init() failed: %d (%s)",
|
||||
err_, strerror(err_));
|
||||
goto cleanup_pipe;
|
||||
}
|
||||
|
||||
err_ = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF |
|
||||
POSIX_SPAWN_USEVFORK);
|
||||
if (err_)
|
||||
{
|
||||
WSREP_ERROR ("posix_spawnattr_setflags() failed: %d (%s)",
|
||||
err_, strerror(err_));
|
||||
goto cleanup_attr;
|
||||
}
|
||||
|
||||
posix_spawn_file_actions_t fact;
|
||||
err_ = posix_spawn_file_actions_init (&fact);
|
||||
if (err_)
|
||||
{
|
||||
WSREP_ERROR ("posix_spawn_file_actions_init() failed: %d (%s)",
|
||||
err_, strerror(err_));
|
||||
goto cleanup_attr;
|
||||
}
|
||||
|
||||
// close child's stdout|stdin depending on what we returning
|
||||
err_ = posix_spawn_file_actions_addclose (&fact, close_fd);
|
||||
if (err_)
|
||||
{
|
||||
WSREP_ERROR ("posix_spawn_file_actions_addclose() failed: %d (%s)",
|
||||
err_, strerror(err_));
|
||||
goto cleanup_fact;
|
||||
}
|
||||
|
||||
// substitute our pipe descriptor in place of the closed one
|
||||
err_ = posix_spawn_file_actions_adddup2 (&fact,
|
||||
pipe_fds[child_end], close_fd);
|
||||
if (err_)
|
||||
{
|
||||
WSREP_ERROR ("posix_spawn_file_actions_addup2() failed: %d (%s)",
|
||||
err_, strerror(err_));
|
||||
goto cleanup_fact;
|
||||
}
|
||||
|
||||
err_ = posix_spawnp (&pid_, pargv[0], &fact, &attr, pargv, environ);
|
||||
if (err_)
|
||||
{
|
||||
WSREP_ERROR ("posix_spawnp(%s) failed: %d (%s)",
|
||||
pargv[2], err_, strerror(err_));
|
||||
pid_ = 0; // just to make sure it was not messed up in the call
|
||||
goto cleanup_fact;
|
||||
}
|
||||
|
||||
io_ = fdopen (pipe_fds[parent_end], type);
|
||||
|
||||
if (io_)
|
||||
{
|
||||
pipe_fds[parent_end] = -1; // skip close on cleanup
|
||||
}
|
||||
else
|
||||
{
|
||||
err_ = errno;
|
||||
WSREP_ERROR ("fdopen() failed: %d (%s)", err_, strerror(err_));
|
||||
}
|
||||
|
||||
cleanup_fact:
|
||||
int err; // to preserve err_ code
|
||||
err = posix_spawn_file_actions_destroy (&fact);
|
||||
if (err)
|
||||
{
|
||||
WSREP_ERROR ("posix_spawn_file_actions_destroy() failed: %d (%s)\n",
|
||||
err, strerror(err));
|
||||
}
|
||||
|
||||
cleanup_attr:
|
||||
err = posix_spawnattr_destroy (&attr);
|
||||
if (err)
|
||||
{
|
||||
WSREP_ERROR ("posix_spawnattr_destroy() failed: %d (%s)",
|
||||
err, strerror(err));
|
||||
}
|
||||
|
||||
cleanup_pipe:
|
||||
if (pipe_fds[0] >= 0) close (pipe_fds[0]);
|
||||
if (pipe_fds[1] >= 0) close (pipe_fds[1]);
|
||||
|
||||
free (pargv[0]);
|
||||
free (pargv[1]);
|
||||
free (pargv[2]);
|
||||
}
|
||||
|
||||
process::~process ()
|
||||
{
|
||||
if (io_)
|
||||
{
|
||||
assert (pid_);
|
||||
assert (str_);
|
||||
|
||||
WSREP_WARN("Closing pipe to child process: %s, PID(%ld) "
|
||||
"which might still be running.", str_, (long)pid_);
|
||||
|
||||
if (fclose (io_) == -1)
|
||||
{
|
||||
err_ = errno;
|
||||
WSREP_ERROR("fclose() failed: %d (%s)", err_, strerror(err_));
|
||||
}
|
||||
}
|
||||
|
||||
if (str_) free (const_cast<char*>(str_));
|
||||
}
|
||||
|
||||
int
|
||||
process::wait ()
|
||||
{
|
||||
if (pid_)
|
||||
{
|
||||
int status;
|
||||
if (-1 == waitpid(pid_, &status, 0))
|
||||
{
|
||||
err_ = errno; assert (err_);
|
||||
WSREP_ERROR("Waiting for process failed: %s, PID(%ld): %d (%s)",
|
||||
str_, (long)pid_, err_, strerror (err_));
|
||||
}
|
||||
else
|
||||
{ // command completed, check exit status
|
||||
if (WIFEXITED (status)) {
|
||||
err_ = WEXITSTATUS (status);
|
||||
}
|
||||
else { // command didn't complete with exit()
|
||||
WSREP_ERROR("Process was aborted.");
|
||||
err_ = errno ? errno : ECHILD;
|
||||
}
|
||||
|
||||
if (err_) {
|
||||
switch (err_) /* Translate error codes to more meaningful */
|
||||
{
|
||||
case 126: err_ = EACCES; break; /* Permission denied */
|
||||
case 127: err_ = ENOENT; break; /* No such file or directory */
|
||||
}
|
||||
WSREP_ERROR("Process completed with error: %s: %d (%s)",
|
||||
str_, err_, strerror(err_));
|
||||
}
|
||||
|
||||
pid_ = 0;
|
||||
if (io_) fclose (io_);
|
||||
io_ = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert (NULL == io_);
|
||||
WSREP_ERROR("Command did not run: %s", str_);
|
||||
}
|
||||
|
||||
return err_;
|
||||
}
|
||||
|
||||
thd::thd (my_bool won) : init(), ptr(new THD)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
ptr->thread_stack= (char*) &ptr;
|
||||
ptr->store_globals();
|
||||
ptr->variables.option_bits&= ~OPTION_BIN_LOG; // disable binlog
|
||||
ptr->variables.wsrep_on = won;
|
||||
ptr->security_ctx->master_access= ~(ulong)0;
|
||||
lex_start(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
thd::~thd ()
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
delete ptr;
|
||||
my_pthread_setspecific_ptr (THR_THD, 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wsp
|
||||
|
||||
extern ulong my_bind_addr;
|
||||
extern uint mysqld_port;
|
||||
|
||||
size_t guess_ip (char* buf, size_t buf_len)
|
||||
{
|
||||
size_t ip_len = 0;
|
||||
|
||||
if (htonl(INADDR_NONE) == my_bind_addr) {
|
||||
WSREP_ERROR("Networking not configured, cannot receive state transfer.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (htonl(INADDR_ANY) != my_bind_addr) {
|
||||
uint8_t* b = (uint8_t*)&my_bind_addr;
|
||||
ip_len = snprintf (buf, buf_len,
|
||||
"%hhu.%hhu.%hhu.%hhu", b[0],b[1],b[2],b[3]);
|
||||
return ip_len;
|
||||
}
|
||||
|
||||
// mysqld binds to all interfaces - try IP from wsrep_node_address
|
||||
if (wsrep_node_address && wsrep_node_address[0] != '\0') {
|
||||
const char* const colon_ptr = strchr(wsrep_node_address, ':');
|
||||
|
||||
if (colon_ptr)
|
||||
ip_len = colon_ptr - wsrep_node_address;
|
||||
else
|
||||
ip_len = strlen(wsrep_node_address);
|
||||
|
||||
if (ip_len >= buf_len) {
|
||||
WSREP_WARN("default_ip(): buffer too short: %zu <= %zd", buf_len, ip_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy (buf, wsrep_node_address, ip_len);
|
||||
buf[ip_len] = '\0';
|
||||
return ip_len;
|
||||
}
|
||||
|
||||
// try to find the address of the first one
|
||||
#if (TARGET_OS_LINUX == 1)
|
||||
const char cmd[] = "ip addr show | grep -E '^\\s*inet' | grep -m1 global |"
|
||||
" awk '{ print $2 }' | sed 's/\\/.*//'";
|
||||
#elif defined(__sun__)
|
||||
const char cmd[] = "/sbin/ifconfig -a | "
|
||||
"/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'";
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
const char cmd[] = "route -nv get 8.8.8.8 | tail -n1 | awk '{print $5}'";
|
||||
#else
|
||||
char *cmd;
|
||||
#error "OS not supported"
|
||||
#endif
|
||||
wsp::process proc (cmd, "r");
|
||||
|
||||
if (NULL != proc.pipe()) {
|
||||
char* ret;
|
||||
|
||||
ret = fgets (buf, buf_len, proc.pipe());
|
||||
|
||||
if (proc.wait()) return 0;
|
||||
|
||||
if (NULL == ret) {
|
||||
WSREP_ERROR("Failed to read output of: '%s'", cmd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
WSREP_ERROR("Failed to execute: '%s'", cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clear possible \n at the end of ip string left by fgets()
|
||||
ip_len = strlen (buf);
|
||||
if (ip_len > 0 && '\n' == buf[ip_len - 1]) {
|
||||
ip_len--;
|
||||
buf[ip_len] = '\0';
|
||||
}
|
||||
|
||||
if (INADDR_NONE == inet_addr(buf)) {
|
||||
if (strlen(buf) != 0) {
|
||||
WSREP_WARN("Shell command returned invalid address: '%s'", buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ip_len;
|
||||
}
|
||||
|
||||
size_t guess_address(char* buf, size_t buf_len)
|
||||
{
|
||||
size_t addr_len = guess_ip (buf, buf_len);
|
||||
|
||||
if (addr_len && addr_len < buf_len) {
|
||||
addr_len += snprintf (buf + addr_len, buf_len - addr_len,
|
||||
":%u", mysqld_port);
|
||||
}
|
||||
|
||||
return addr_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* WSREPXid
|
||||
*/
|
||||
|
||||
#define WSREP_XID_PREFIX "WSREPXid"
|
||||
#define WSREP_XID_PREFIX_LEN MYSQL_XID_PREFIX_LEN
|
||||
#define WSREP_XID_UUID_OFFSET 8
|
||||
#define WSREP_XID_SEQNO_OFFSET (WSREP_XID_UUID_OFFSET + sizeof(wsrep_uuid_t))
|
||||
#define WSREP_XID_GTRID_LEN (WSREP_XID_SEQNO_OFFSET + sizeof(wsrep_seqno_t))
|
||||
|
||||
void wsrep_xid_init(XID* xid, const wsrep_uuid_t* uuid, wsrep_seqno_t seqno)
|
||||
{
|
||||
xid->formatID= 1;
|
||||
xid->gtrid_length= WSREP_XID_GTRID_LEN;
|
||||
xid->bqual_length= 0;
|
||||
memset(xid->data, 0, sizeof(xid->data));
|
||||
memcpy(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN);
|
||||
memcpy(xid->data + WSREP_XID_UUID_OFFSET, uuid, sizeof(wsrep_uuid_t));
|
||||
memcpy(xid->data + WSREP_XID_SEQNO_OFFSET, &seqno, sizeof(wsrep_seqno_t));
|
||||
}
|
||||
|
||||
const wsrep_uuid_t* wsrep_xid_uuid(const XID* xid)
|
||||
{
|
||||
if (wsrep_is_wsrep_xid(xid))
|
||||
return reinterpret_cast<const wsrep_uuid_t*>(xid->data
|
||||
+ WSREP_XID_UUID_OFFSET);
|
||||
else
|
||||
return &WSREP_UUID_UNDEFINED;
|
||||
}
|
||||
|
||||
wsrep_seqno_t wsrep_xid_seqno(const XID* xid)
|
||||
{
|
||||
|
||||
if (wsrep_is_wsrep_xid(xid))
|
||||
{
|
||||
wsrep_seqno_t seqno;
|
||||
memcpy(&seqno, xid->data + WSREP_XID_SEQNO_OFFSET, sizeof(wsrep_seqno_t));
|
||||
return seqno;
|
||||
}
|
||||
else
|
||||
{
|
||||
return WSREP_SEQNO_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int wsrep_is_wsrep_xid(const void* xid_ptr)
|
||||
{
|
||||
const XID* xid= reinterpret_cast<const XID*>(xid_ptr);
|
||||
return (xid->formatID == 1 &&
|
||||
xid->gtrid_length == WSREP_XID_GTRID_LEN &&
|
||||
xid->bqual_length == 0 &&
|
||||
!memcmp(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN));
|
||||
}
|
Reference in New Issue
Block a user