Merging revision from codership-mysql/5.5 (r3928..3968) and

codership-mysql/5.6 (r4021..4065).
- Also contains fixes for some build failures.
This commit is contained in:
Nirbhay Choubey 2014-03-27 16:26:00 -04:00
commit 02ba2bfdb4
57 changed files with 2161 additions and 722 deletions

View File

@ -31,6 +31,9 @@ MACRO (INSTALL_DSYM_DIRECTORIES targets)
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(DEBUG_EXTNAME)
STRING(REGEX REPLACE "/mysqld$" "/mysqld-debug" location ${location})
ENDIF()
IF(type MATCHES "EXECUTABLE" OR type MATCHES "MODULE" OR type MATCHES "SHARED_LIBRARY")
INSTALL(DIRECTORY "${location}.dSYM" DESTINATION ${ARG_DESTINATION} COMPONENT Debuginfo)
ENDIF()

View File

@ -18,12 +18,12 @@
# so WSREP_VERSION is produced regardless
# Set the patch version
SET(WSREP_PATCH_VERSION "9")
SET(WSREP_PATCH_VERSION "10")
# MariaDB addition: Revision number of the last revision merged from
# codership branch visible in @@visible_comment.
# Branch : codership-mysql/5.5
SET(WSREP_PATCH_REVNO "3928") # Should be updated on every merge.
SET(WSREP_PATCH_REVNO "3968") # Should be updated on every merge.
# MariaDB: Obtain patch revision number:
# Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set.

View File

@ -22,7 +22,7 @@ extern "C" {
#endif
#ifdef WITH_WSREP
#include <my_sys.h>
typedef int (* wsrep_thd_is_brute_force_fun)(void *);
typedef my_bool (* wsrep_thd_is_brute_force_fun)(void *, my_bool);
typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool);
typedef int (* wsrep_on_fun)(void *);
void wsrep_thr_lock_init(

View File

@ -690,7 +690,7 @@ wsrep_break_lock(
{
if (wsrep_on(data->owner->mysql_thd) &&
wsrep_thd_is_brute_force &&
wsrep_thd_is_brute_force(data->owner->mysql_thd))
wsrep_thd_is_brute_force(data->owner->mysql_thd, TRUE))
{
THR_LOCK_DATA *holder;
@ -715,7 +715,7 @@ wsrep_break_lock(
holder;
holder=holder->next)
{
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd))
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE))
{
wsrep_abort_thd(data->owner->mysql_thd,
holder->owner->mysql_thd, FALSE);
@ -731,7 +731,7 @@ wsrep_break_lock(
holder;
holder=holder->next)
{
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd))
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE))
{
wsrep_abort_thd(data->owner->mysql_thd,
holder->owner->mysql_thd, FALSE);

View File

@ -321,7 +321,13 @@ IF(WIN32)
ENDFOREACH()
ELSE()
IF(WITH_WSREP)
SET(WSREP_BINARIES wsrep_sst_common wsrep_sst_mysqldump wsrep_sst_rsync wsrep_sst_xtrabackup)
SET(WSREP_BINARIES
wsrep_sst_common
wsrep_sst_mysqldump
wsrep_sst_rsync
wsrep_sst_xtrabackup
wsrep_sst_xtrabackup-v2
)
ENDIF()
# On Unix, most of the files end up in the bin directory
SET(BIN_SCRIPTS

View File

@ -28,7 +28,7 @@ case "$1" in
shift
;;
'--auth')
readonly WSREP_SST_OPT_AUTH="$2"
WSREP_SST_OPT_AUTH="$2"
shift
;;
'--bypass')
@ -87,13 +87,21 @@ shift
done
readonly WSREP_SST_OPT_BYPASS
if [ -n "$WSREP_SST_OPT_DATA" ]
# For Bug:1200727
if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then
if [ -z $WSREP_SST_OPT_AUTH -o $WSREP_SST_OPT_AUTH = "(null)" ];then
WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2)
fi
fi
if [ -n "${WSREP_SST_OPT_DATA:-}" ]
then
SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress"
else
SST_PROGRESS_FILE=""
fi
wsrep_log()
{
# echo everything to stderr so that it gets into common error log

View File

@ -67,12 +67,22 @@ check_pid_and_port()
MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete"
rm -rf "$MAGIC_FILE"
SCRIPT_DIR=$(cd "$(dirname "$0")"; pwd -P)
WSREP_LOG_DIR=${WSREP_LOG_DIR:-$($SCRIPT_DIR/my_print_defaults --defaults-file "$WSREP_SST_OPT_CONF" mysqld server mysqld-5.5 \
| grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' | cut -b 29- )}
if [ -n "${WSREP_LOG_DIR:-""}" ]; then
WSREP_LOG_DIR=${WSREP_LOG_DIR:-""}
# if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf
if [ -z "$WSREP_LOG_DIR" ]; then
SCRIPT_DIR="$(cd $(dirname "$0"); pwd -P)"
WSREP_LOG_DIR=$($SCRIPT_DIR/my_print_defaults --defaults-file \
"$WSREP_SST_OPT_CONF" mysqld server mysqld-5.5 \
| grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' \
| cut -b 29- )
fi
if [ -n "$WSREP_LOG_DIR" ]; then
# handle both relative and absolute paths
WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; mkdir -p "$WSREP_LOG_DIR"; cd $WSREP_LOG_DIR; pwd -P)
else
# default to datadir
WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; pwd -P)
fi
@ -158,7 +168,7 @@ then
find . -maxdepth 1 -mindepth 1 -type d -print0 | xargs -I{} -0 -P $count \
rsync --owner --group --perms --links --specials \
--ignore-times --inplace --recursive --delete --quiet \
$WHOLE_FILE_OPT --exclude '*/ib_logfile*' "$WSREP_SST_OPT_DATA"/{}/ \
$WHOLE_FILE_OPT --exclude '*/ib_logfile*' "$WSREP_SST_OPT_DATA"/{}/ \
rsync://$WSREP_SST_OPT_ADDR/{} >&2 || RC=$?
popd >/dev/null
@ -208,8 +218,6 @@ then
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"
@ -217,8 +225,6 @@ pid file = $RSYNC_PID
use chroot = no
read only = no
timeout = 300
uid = $MYUID
gid = $MYGID
[$MODULE]
path = $WSREP_SST_OPT_DATA
[$MODULE-log_dir]

View File

@ -0,0 +1,875 @@
#!/bin/bash -ue
# Copyright (C) 2013 Percona Inc
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston
# MA 02110-1301 USA.
# Documentation: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
# Make sure to read that before proceeding!
. $(dirname $0)/wsrep_sst_common
ealgo=""
ekey=""
ekeyfile=""
encrypt=0
nproc=1
ecode=0
XTRABACKUP_PID=""
SST_PORT=""
REMOTEIP=""
tcert=""
tpem=""
tkey=""
sockopt=""
progress=""
ttime=0
totime=0
lsn=""
incremental=0
ecmd=""
rlimit=""
# Initially
stagemsg="${WSREP_SST_OPT_ROLE}"
cpat=""
speciald=0
ib_home_dir=""
ib_log_dir=""
sfmt="tar"
strmcmd=""
tfmt=""
tcmd=""
rebuild=0
rebuildcmd=""
payload=0
pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' "
pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE "
STATDIR=""
uextra=0
disver=""
scomp=""
sdecomp=""
if which pv &>/dev/null && pv --help | grep -q FORMAT;then
pvopts+=$pvformat
fi
pcmd="pv $pvopts"
declare -a RC
INNOBACKUPEX_BIN=innobackupex
readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
DATA="${WSREP_SST_OPT_DATA}"
INFO_FILE="xtrabackup_galera_info"
IST_FILE="xtrabackup_ist"
MAGIC_FILE="${DATA}/${INFO_FILE}"
# Setting the path for ss and ip
export PATH="/usr/sbin:/sbin:$PATH"
timeit(){
local stage=$1
shift
local cmd="$@"
local x1 x2 took extcode
if [[ $ttime -eq 1 ]];then
x1=$(date +%s)
wsrep_log_info "Evaluating $cmd"
eval "$cmd"
extcode=$?
x2=$(date +%s)
took=$(( x2-x1 ))
wsrep_log_info "NOTE: $stage took $took seconds"
totime=$(( totime+took ))
else
wsrep_log_info "Evaluating $cmd"
eval "$cmd"
extcode=$?
fi
return $extcode
}
get_keys()
{
# $encrypt -eq 1 is for internal purposes only
if [[ $encrypt -ge 2 || $encrypt -eq -1 ]];then
return
fi
if [[ $encrypt -eq 0 ]];then
if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then
wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html "
fi
return
fi
if [[ $sfmt == 'tar' ]];then
wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format"
encrypt=-1
return
fi
wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4"
if [[ -z $ealgo ]];then
wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out"
exit 3
fi
if [[ -z $ekey && ! -r $ekeyfile ]];then
wsrep_log_error "FATAL: Either key or keyfile must be readable"
exit 3
fi
if [[ -z $ekey ]];then
ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile"
else
ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey"
fi
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
ecmd+=" -d"
fi
stagemsg+="-XB-Encrypted"
}
get_transfer()
{
if [[ -z $SST_PORT ]];then
TSST_PORT=4444
else
TSST_PORT=$SST_PORT
fi
if [[ $tfmt == 'nc' ]];then
if [[ ! -x `which nc` ]];then
wsrep_log_error "nc(netcat) not found in path: $PATH"
exit 2
fi
wsrep_log_info "Using netcat as streamer"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
tcmd="nc -dl ${TSST_PORT}"
else
tcmd="nc ${REMOTEIP} ${TSST_PORT}"
fi
else
tfmt='socat'
wsrep_log_info "Using socat as streamer"
if [[ ! -x `which socat` ]];then
wsrep_log_error "socat not found in path: $PATH"
exit 2
fi
if [[ $encrypt -eq 2 || $encrypt -eq 3 ]] && ! socat -V | grep -q WITH_OPENSSL;then
wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer"
encrypt=-1
fi
if [[ $encrypt -eq 2 ]];then
wsrep_log_info "Using openssl based encryption with socat: with crt and pem"
if [[ -z $tpem || -z $tcert ]];then
wsrep_log_error "Both PEM and CRT files required"
exit 22
fi
stagemsg+="-OpenSSL-Encrypted-2"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert"
tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio"
else
wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert"
tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}"
fi
elif [[ $encrypt -eq 3 ]];then
wsrep_log_info "Using openssl based encryption with socat: with key and crt"
if [[ -z $tpem || -z $tkey ]];then
wsrep_log_error "Both certificate and key files required"
exit 22
fi
stagemsg+="-OpenSSL-Encrypted-3"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "Decrypting with certificate $tpem, key $tkey"
tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,key=${tkey},verify=0${sockopt} stdio"
else
wsrep_log_info "Encrypting with certificate $tpem, key $tkey"
tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,key=${tkey},verify=0${sockopt}"
fi
else
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio"
else
tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}"
fi
fi
fi
}
parse_cnf()
{
local group=$1
local var=$2
reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-)
if [[ -z $reval ]];then
[[ -n $3 ]] && reval=$3
fi
echo $reval
}
get_footprint()
{
pushd $WSREP_SST_OPT_DATA 1>/dev/null
payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }')
if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then
# QuickLZ has around 50% compression ratio
# When compression/compaction used, the progress is only an approximate.
payload=$(( payload*1/2 ))
fi
popd 1>/dev/null
pcmd+=" -s $payload"
adjust_progress
}
adjust_progress()
{
if [[ -n $progress && $progress != '1' ]];then
if [[ -e $progress ]];then
pcmd+=" 2>>$progress"
else
pcmd+=" 2>$progress"
fi
elif [[ -z $progress && -n $rlimit ]];then
# When rlimit is non-zero
pcmd="pv -q"
fi
if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then
wsrep_log_info "Rate-limiting SST to $rlimit"
pcmd+=" -L \$rlimit"
fi
}
read_cnf()
{
sfmt=$(parse_cnf sst streamfmt "xbstream")
tfmt=$(parse_cnf sst transferfmt "socat")
tcert=$(parse_cnf sst tca "")
tpem=$(parse_cnf sst tcert "")
tkey=$(parse_cnf sst tkey "")
encrypt=$(parse_cnf sst encrypt 0)
sockopt=$(parse_cnf sst sockopt "")
progress=$(parse_cnf sst progress "")
rebuild=$(parse_cnf sst rebuild 0)
ttime=$(parse_cnf sst time 0)
cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$')
incremental=$(parse_cnf sst incremental 0)
ealgo=$(parse_cnf xtrabackup encrypt "")
ekey=$(parse_cnf xtrabackup encrypt-key "")
ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "")
scomp=$(parse_cnf sst compressor "")
sdecomp=$(parse_cnf sst decompressor "")
# Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
if [[ -z $ealgo ]];then
ealgo=$(parse_cnf sst encrypt-algo "")
ekey=$(parse_cnf sst encrypt-key "")
ekeyfile=$(parse_cnf sst encrypt-key-file "")
fi
rlimit=$(parse_cnf sst rlimit "")
uextra=$(parse_cnf sst use-extra 0)
speciald=$(parse_cnf sst sst-special-dirs 1)
iopts=$(parse_cnf sst inno-backup-opts "")
iapts=$(parse_cnf sst inno-apply-opts "")
impts=$(parse_cnf sst inno-move-opts "")
}
get_stream()
{
if [[ $sfmt == 'xbstream' ]];then
wsrep_log_info "Streaming with xbstream"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
strmcmd="xbstream -x"
else
strmcmd="xbstream -c \${INFO_FILE}"
fi
else
sfmt="tar"
wsrep_log_info "Streaming with tar"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
strmcmd="tar xfi - "
else
strmcmd="tar cf - \${INFO_FILE} "
fi
fi
}
get_proc()
{
set +e
nproc=$(grep -c processor /proc/cpuinfo)
[[ -z $nproc || $nproc -eq 0 ]] && nproc=1
set -e
}
sig_joiner_cleanup()
{
wsrep_log_error "Removing $MAGIC_FILE file due to signal"
rm -f "$MAGIC_FILE"
}
cleanup_joiner()
{
# Since this is invoked just after exit NNN
local estatus=$?
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus"
fi
if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
wsrep_log_info "Removing the sst_in_progress file"
wsrep_cleanup_progress_file
fi
if [[ -n $progress && -p $progress ]];then
wsrep_log_info "Cleaning up fifo file $progress"
rm $progress
fi
if [[ -n ${STATDIR:-} ]];then
[[ -d $STATDIR ]] && rm -rf $STATDIR
fi
}
check_pid()
{
local pid_file="$1"
[ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1
}
cleanup_donor()
{
# Since this is invoked just after exit NNN
local estatus=$?
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus"
fi
if [[ -n $XTRABACKUP_PID ]];then
if check_pid $XTRABACKUP_PID
then
wsrep_log_error "xtrabackup process is still running. Killing... "
kill_xtrabackup
fi
rm -f $XTRABACKUP_PID
fi
rm -f ${DATA}/${IST_FILE}
if [[ -n $progress && -p $progress ]];then
wsrep_log_info "Cleaning up fifo file $progress"
rm $progress
fi
}
kill_xtrabackup()
{
local PID=$(cat $XTRABACKUP_PID)
[ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
rm -f "$XTRABACKUP_PID"
}
setup_ports()
{
if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }')
else
SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }')
fi
}
# waits ~10 seconds for nc to open the port and then reports ready
# (regardless of timeout)
wait_for_listen()
{
local PORT=$1
local ADDR=$2
local MODULE=$3
for i in {1..50}
do
ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break
sleep 0.2
done
if [[ $incremental -eq 1 ]];then
echo "ready ${ADDR}/${MODULE}/$lsn"
else
echo "ready ${ADDR}/${MODULE}"
fi
}
check_extra()
{
local use_socket=1
if [[ $uextra -eq 1 ]];then
if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then
local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2)
if [[ -n $eport ]];then
# Xtrabackup works only locally.
# Hence, setting host to 127.0.0.1 unconditionally.
wsrep_log_info "SST through extra_port $eport"
INNOEXTRA+=" --host=127.0.0.1 --port=$eport "
use_socket=0
else
wsrep_log_error "Extra port $eport null, failing"
exit 1
fi
else
wsrep_log_info "Thread pool not set, ignore the option use_extra"
fi
fi
if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then
INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}"
fi
}
recv_joiner()
{
local dir=$1
local msg=$2
pushd ${dir} 1>/dev/null
set +e
timeit "$msg" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e
popd 1>/dev/null
for ecode in "${RC[@]}";do
if [[ $ecode -ne 0 ]];then
wsrep_log_error "Error while getting data from donor node: " \
"exit codes: ${RC[@]}"
exit 32
fi
done
if [ ! -r "${MAGIC_FILE}" ];then
# this message should cause joiner to abort
wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'"
wsrep_log_info "Contents of datadir"
wsrep_log_info "$(ls -l ${dir}/*)"
exit 32
fi
}
send_donor()
{
local dir=$1
local msg=$2
pushd ${dir} 1>/dev/null
set +e
timeit "$msg" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e
popd 1>/dev/null
for ecode in "${RC[@]}";do
if [[ $ecode -ne 0 ]];then
wsrep_log_error "Error while getting data from donor node: " \
"exit codes: ${RC[@]}"
exit 32
fi
done
}
if [[ ! -x `which innobackupex` ]];then
wsrep_log_error "innobackupex not in path: $PATH"
exit 2
fi
rm -f "${MAGIC_FILE}"
if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then
wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}"
exit 22
fi
read_cnf
setup_ports
get_stream
get_transfer
if ${INNOBACKUPEX_BIN} /tmp --help | grep -q -- '--version-check'; then
disver="--no-version-check"
fi
INNOEXTRA=""
INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log"
INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log"
INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log"
if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
then
trap cleanup_donor EXIT
if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
then
TMPDIR="${TMPDIR:-/tmp}"
if [ "${AUTH[0]}" != "(null)" ]; then
INNOEXTRA+=" --user=${AUTH[0]}"
fi
if [ ${#AUTH[*]} -eq 2 ]; then
INNOEXTRA+=" --password=${AUTH[1]}"
elif [ "${AUTH[0]}" != "(null)" ]; then
# Empty password, used for testing, debugging etc.
INNOEXTRA+=" --password="
fi
get_keys
if [[ $encrypt -eq 1 ]];then
if [[ -n $ekey ]];then
INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey "
else
INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile "
fi
fi
if [[ -n $lsn ]];then
INNOEXTRA+=" --incremental --incremental-lsn=$lsn "
fi
check_extra
wsrep_log_info "Streaming GTID file before SST"
echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}"
ttcmd="$tcmd"
if [[ $encrypt -eq 1 ]];then
if [[ -n $scomp ]];then
tcmd=" $ecmd | $scomp | $tcmd "
else
tcmd=" $ecmd | $tcmd "
fi
elif [[ -n $scomp ]];then
tcmd=" $scomp | $tcmd "
fi
send_donor $DATA "${stagemsg}-gtid"
tcmd="$ttcmd"
if [[ -n $progress ]];then
get_footprint
tcmd="$pcmd | $tcmd"
elif [[ -n $rlimit ]];then
adjust_progress
tcmd="$pcmd | $tcmd"
fi
wsrep_log_info "Sleeping before data transfer for SST"
sleep 10
wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT:-4444}"
if [[ -n $scomp ]];then
tcmd="$scomp | $tcmd"
fi
set +e
timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e
if [ ${RC[0]} -ne 0 ]; then
wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \
"Check ${DATA}/innobackup.backup.log"
exit 22
elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
wsrep_log_error "$tcmd finished with error: ${RC[1]}"
exit 22
fi
# innobackupex implicitly writes PID to fixed location in ${TMPDIR}
XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid"
else # BYPASS FOR IST
wsrep_log_info "Bypassing the SST for IST"
echo "continue" # now server can resume updating data
echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}"
echo "1" > "${DATA}/${IST_FILE}"
get_keys
if [[ $encrypt -eq 1 ]];then
if [[ -n $scomp ]];then
tcmd=" $ecmd | $scomp | $tcmd "
else
tcmd=" $ecmd | $tcmd "
fi
elif [[ -n $scomp ]];then
tcmd=" $scomp | $tcmd "
fi
strmcmd+=" \${IST_FILE}"
send_donor $DATA "${stagemsg}-IST"
fi
echo "done ${WSREP_SST_OPT_GTID}"
wsrep_log_info "Total time on donor: $totime seconds"
elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ]
then
[[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
[[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE
if [[ $speciald -eq 1 ]];then
ib_home_dir=$(parse_cnf mysqld innodb-data-home-dir "")
ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "")
if [[ -z $ib_home_dir && -z $ib_log_dir ]];then
speciald=0
fi
fi
stagemsg="Joiner-Recv"
if [[ ! -e ${DATA}/ibdata1 ]];then
incremental=0
fi
if [[ $incremental -eq 1 ]];then
wsrep_log_info "Incremental SST enabled: NOT SUPPORTED yet"
lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ')
wsrep_log_info "Recovered LSN: $lsn"
fi
sencrypted=1
nthreads=1
MODULE="xtrabackup_sst"
rm -f "${DATA}/${IST_FILE}"
# May need xtrabackup_checkpoints later on
rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile
ADDR=${WSREP_SST_OPT_ADDR}
if [ -z "${SST_PORT}" ]
then
SST_PORT=4444
ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}"
fi
wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} &
trap sig_joiner_cleanup HUP PIPE INT TERM
trap cleanup_joiner EXIT
if [[ -n $progress ]];then
adjust_progress
tcmd+=" | $pcmd"
fi
if [[ $incremental -eq 1 ]];then
BDATA=$DATA
DATA=$(mktemp -d)
MAGIC_FILE="${DATA}/${INFO_FILE}"
fi
get_keys
if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
if [[ -n $sdecomp ]];then
strmcmd=" $sdecomp | $ecmd | $strmcmd"
else
strmcmd=" $ecmd | $strmcmd"
fi
elif [[ -n $sdecomp ]];then
strmcmd=" $sdecomp | $strmcmd"
fi
STATDIR=$(mktemp -d)
MAGIC_FILE="${STATDIR}/${INFO_FILE}"
recv_joiner $STATDIR "${stagemsg}-gtid" 1
if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null
then
wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly."
exit 32
fi
if [ ! -r "${STATDIR}/${IST_FILE}" ]
then
wsrep_log_info "Proceeding with SST"
if [[ $speciald -eq 1 && -d ${DATA}/.sst ]];then
wsrep_log_info "WARNING: Stale temporary SST directory: ${DATA}/.sst from previous SST"
fi
if [[ $incremental -ne 1 ]];then
if [[ $speciald -eq 1 ]];then
wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories"
find $ib_home_dir $ib_log_dir $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+
else
wsrep_log_info "Cleaning the existing datadir"
find $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+
fi
tempdir=$(parse_cnf mysqld log-bin "")
if [[ -n ${tempdir:-} ]];then
binlog_dir=$(dirname $tempdir)
binlog_file=$(basename $tempdir)
if [[ -n ${binlog_dir:-} && $binlog_dir != '.' && $binlog_dir != $DATA ]];then
pattern="$binlog_dir/$binlog_file\.[0-9]+$"
wsrep_log_info "Cleaning the binlog directory $binlog_dir as well"
find $binlog_dir -maxdepth 1 -type f -regex $pattern -exec rm -fv {} 1>&2 \+
rm $binlog_dir/*.index || true
fi
fi
else
wsrep_log_info "Removing existing ib_logfile files"
rm -f ${BDATA}/ib_logfile*
fi
if [[ $speciald -eq 1 ]];then
mkdir -p ${DATA}/.sst
TDATA=${DATA}
DATA="${DATA}/.sst"
fi
MAGIC_FILE="${DATA}/${INFO_FILE}"
recv_joiner $DATA "${stagemsg}-SST" 0
get_proc
# Rebuild indexes for compact backups
if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then
wsrep_log_info "Index compaction detected"
rebuild=1
fi
if [[ $rebuild -eq 1 ]];then
nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc)
wsrep_log_info "Rebuilding during prepare with $nthreads threads"
rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads"
fi
if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then
wsrep_log_info "Compressed qpress files found"
if [[ ! -x `which qpress` ]];then
wsrep_log_error "qpress not found in path: $PATH"
exit 22
fi
if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then
count=$(find ${DATA} -type f -name '*.qp' | wc -l)
count=$(( count*2 ))
if pv --help | grep -q FORMAT;then
pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'"
else
pvopts="-f -s $count -l -N Decompression"
fi
pcmd="pv $pvopts"
adjust_progress
dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d"
else
dcmd="xargs -n 2 qpress -T${nproc}d"
fi
# Decompress the qpress files
wsrep_log_info "Decompression with $nproc threads"
timeit "Joiner-Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd"
extcode=$?
if [[ $extcode -eq 0 ]];then
wsrep_log_info "Removing qpress files after decompression"
find ${DATA} -type f -name '*.qp' -delete
if [[ $? -ne 0 ]];then
wsrep_log_error "Something went wrong with deletion of qpress files. Investigate"
fi
else
wsrep_log_error "Decompression failed. Exit code: $extcode"
exit 22
fi
fi
if [[ $incremental -eq 1 ]];then
# Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues.
INNOAPPLY="${INNOBACKUPEX_BIN} $disver --defaults-file=${WSREP_SST_OPT_CONF} \
--ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log"
fi
wsrep_log_info "Preparing the backup at ${DATA}"
timeit "Xtrabackup prepare stage" "$INNOAPPLY"
if [ $? -ne 0 ];
then
wsrep_log_error "${INNOBACKUPEX_BIN} apply finished with errors. Check ${DATA}/innobackup.prepare.log"
exit 22
fi
if [[ $speciald -eq 1 ]];then
MAGIC_FILE="${TDATA}/${INFO_FILE}"
set +e
rm $TDATA/innobackup.prepare.log $TDATA/innobackup.move.log
set -e
wsrep_log_info "Moving the backup to ${TDATA}"
timeit "Xtrabackup move stage" "$INNOMOVE"
if [[ $? -eq 0 ]];then
wsrep_log_info "Move successful, removing ${DATA}"
rm -rf $DATA
DATA=${TDATA}
else
wsrep_log_error "Move failed, keeping ${DATA} for further diagnosis"
wsrep_log_error "Check ${DATA}/innobackup.move.log for details"
fi
fi
if [[ $incremental -eq 1 ]];then
wsrep_log_info "Cleaning up ${DATA} after incremental SST"
[[ -d ${DATA} ]] && rm -rf ${DATA}
DATA=$BDATA
fi
else
wsrep_log_info "${IST_FILE} received from donor: Running IST"
fi
if [[ ! -r ${MAGIC_FILE} ]];then
wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable"
exit 2
fi
cat "${MAGIC_FILE}" # output UUID:seqno
wsrep_log_info "Total time on joiner: $totime seconds"
fi
exit 0

View File

@ -34,6 +34,11 @@
# lp:1193240 requires you to manually cleanup the directory prior to SST #
# #
#############################################################################################################
# Optional dependencies and options documented here: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
# Make sure to read that before proceeding!
. $(dirname $0)/wsrep_sst_common
@ -44,28 +49,89 @@ encrypt=0
nproc=1
ecode=0
XTRABACKUP_PID=""
SST_PORT=""
REMOTEIP=""
tcert=""
tpem=""
sockopt=""
progress=""
ttime=0
totime=0
lsn=""
incremental=0
ecmd=""
rlimit=""
sfmt="tar"
strmcmd=""
tfmt=""
tcmd=""
rebuild=0
rebuildcmd=""
payload=0
pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' "
pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE "
uextra=0
if which pv &>/dev/null && pv --help | grep -q FORMAT;then
pvopts+=$pvformat
fi
pcmd="pv $pvopts"
declare -a RC
INNOBACKUPEX_BIN=innobackupex
readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
DATA="${WSREP_SST_OPT_DATA}"
INFO_FILE="xtrabackup_galera_info"
IST_FILE="xtrabackup_ist"
MAGIC_FILE="${DATA}/${INFO_FILE}"
# Setting the path for ss and ip
export PATH="/usr/sbin:/sbin:$PATH"
timeit(){
local stage=$1
shift
local cmd="$@"
local x1 x2 took extcode
if [[ $ttime -eq 1 ]];then
x1=$(date +%s)
wsrep_log_info "Evaluating $cmd"
eval "$cmd"
extcode=$?
x2=$(date +%s)
took=$(( x2-x1 ))
wsrep_log_info "NOTE: $stage took $took seconds"
totime=$(( totime+took ))
else
wsrep_log_info "Evaluating $cmd"
eval "$cmd"
extcode=$?
fi
return $extcode
}
get_keys()
{
# There is no metadata in the stream to indicate that it is encrypted
# So, if the cnf file on joiner contains 'encrypt' under [xtrabackup] section then
# it means encryption is being used
if ! my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then
return
if [[ $encrypt -eq 2 ]];then
return
fi
if [[ $sfmt == 'tar' ]];then
wsrep_log_info "NOTE: Encryption cannot be enabled with tar format"
if [[ $encrypt -eq 0 ]];then
if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then
wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html "
fi
return
fi
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 [[ $sfmt == 'tar' ]];then
wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format"
encrypt=0
return
fi
wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4"
if [[ -z $ealgo ]];then
wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out"
@ -76,35 +142,160 @@ get_keys()
wsrep_log_error "FATAL: Either key or keyfile must be readable"
exit 3
fi
encrypt=1
if [[ -z $ekey ]];then
ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile"
else
ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey"
fi
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
ecmd+=" -d"
fi
}
get_transfer()
{
if [[ -z $SST_PORT ]];then
TSST_PORT=4444
else
TSST_PORT=$SST_PORT
fi
if [[ $tfmt == 'nc' ]];then
if [[ ! -x `which nc` ]];then
wsrep_log_error "nc(netcat) not found in path: $PATH"
exit 2
fi
wsrep_log_info "Using netcat as streamer"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
tcmd="nc -dl ${TSST_PORT}"
else
tcmd="nc ${REMOTEIP} ${TSST_PORT}"
fi
else
tfmt='socat'
wsrep_log_info "Using socat as streamer"
if [[ ! -x `which socat` ]];then
wsrep_log_error "socat not found in path: $PATH"
exit 2
fi
if [[ $encrypt -eq 2 ]] && ! socat -V | grep -q OPENSSL;then
wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer"
encrypt=0
fi
if [[ $encrypt -eq 2 ]];then
wsrep_log_info "Using openssl based encryption with socat"
if [[ -z $tpem || -z $tcert ]];then
wsrep_log_error "Both PEM and CRT files required"
exit 22
fi
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert"
tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio"
else
wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert"
tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}"
fi
else
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio"
else
tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}"
fi
fi
fi
}
parse_cnf()
{
local group=$1
local var=$2
reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-)
if [[ -z $reval ]];then
[[ -n $3 ]] && reval=$3
fi
echo $reval
}
get_footprint()
{
pushd $WSREP_SST_OPT_DATA 1>/dev/null
payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }')
if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then
# QuickLZ has around 50% compression ratio
# When compression/compaction used, the progress is only an approximate.
payload=$(( payload*1/2 ))
fi
popd 1>/dev/null
pcmd+=" -s $payload"
adjust_progress
}
adjust_progress()
{
if [[ -n $progress && $progress != '1' ]];then
if [[ -e $progress ]];then
pcmd+=" 2>>$progress"
else
pcmd+=" 2>$progress"
fi
elif [[ -z $progress && -n $rlimit ]];then
# When rlimit is non-zero
pcmd="pv -q"
fi
if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then
wsrep_log_info "Rate-limiting SST to $rlimit"
pcmd+=" -L \$rlimit"
fi
}
read_cnf()
{
sfmt=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- '--streamfmt' | cut -d= -f2)
sfmt=$(parse_cnf sst streamfmt "tar")
tfmt=$(parse_cnf sst transferfmt "socat")
tcert=$(parse_cnf sst tca "")
tpem=$(parse_cnf sst tcert "")
encrypt=$(parse_cnf sst encrypt 0)
sockopt=$(parse_cnf sst sockopt "")
progress=$(parse_cnf sst progress "")
rebuild=$(parse_cnf sst rebuild 0)
ttime=$(parse_cnf sst time 0)
incremental=$(parse_cnf sst incremental 0)
ealgo=$(parse_cnf xtrabackup encrypt "")
ekey=$(parse_cnf xtrabackup encrypt-key "")
ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "")
# Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
if [[ -z $ealgo ]];then
ealgo=$(parse_cnf sst encrypt-algo "")
ekey=$(parse_cnf sst encrypt-key "")
ekeyfile=$(parse_cnf sst encrypt-key-file "")
fi
rlimit=$(parse_cnf sst rlimit "")
uextra=$(parse_cnf sst use_extra 0)
}
get_stream()
{
if [[ $sfmt == 'xbstream' ]];then
wsrep_log_info "Streaming with xbstream"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "xbstream requires manual cleanup of data directory before SST - lp:1193240"
strmcmd="xbstream -x -C ${DATA}"
elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
strmcmd="xbstream -c ${INFO_FILE} ${IST_FILE}"
strmcmd="xbstream -x"
else
wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE"
exit 22
strmcmd="xbstream -c \${INFO_FILE} \${IST_FILE}"
fi
else
sfmt="tar"
wsrep_log_info "Streaming with tar"
wsrep_log_info "Note: Advanced xtrabackup features - encryption,compression etc. not available with tar."
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "However, xbstream requires manual cleanup of data directory before SST - lp:1193240."
strmcmd="tar xfi - -C ${DATA}"
elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
strmcmd="tar cf - ${INFO_FILE} ${IST_FILE}"
else
wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE"
exit 22
strmcmd="tar xfi - --recursive-unlink -h"
else
strmcmd="tar cf - \${INFO_FILE} \${IST_FILE}"
fi
fi
@ -118,6 +309,12 @@ get_proc()
set -e
}
sig_joiner_cleanup()
{
wsrep_log_error "Removing $MAGIC_FILE file due to signal"
rm -f "$MAGIC_FILE"
}
cleanup_joiner()
{
# Since this is invoked just after exit NNN
@ -125,18 +322,14 @@ cleanup_joiner()
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus"
fi
local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }')
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Killing nc pid $PID"
else
wsrep_log_info "Killing nc pid $PID"
fi
[ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
rm -f "$MAGIC_FILE"
if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
wsrep_log_info "Removing the sst_in_progress file"
wsrep_cleanup_progress_file
fi
if [[ -n $progress && -p $progress ]];then
wsrep_log_info "Cleaning up fifo file $progress"
rm $progress
fi
}
check_pid()
@ -152,119 +345,161 @@ cleanup_donor()
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus"
fi
local pid=$XTRABACKUP_PID
if check_pid "$pid"
then
wsrep_log_error "xtrabackup process is still running. Killing... "
kill_xtrabackup
fi
rm -f "$pid"
if [[ -n $XTRABACKUP_PID ]];then
if check_pid $XTRABACKUP_PID
then
wsrep_log_error "xtrabackup process is still running. Killing... "
kill_xtrabackup
fi
rm -f $XTRABACKUP_PID
fi
rm -f ${DATA}/${IST_FILE}
if [[ -n $progress && -p $progress ]];then
wsrep_log_info "Cleaning up fifo file $progress"
rm $progress
fi
}
kill_xtrabackup()
{
#set -x
local PID=$(cat $XTRABACKUP_PID)
[ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
rm -f "$XTRABACKUP_PID"
#set +x
}
setup_ports()
{
if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }')
else
SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }')
fi
}
# waits ~10 seconds for nc to open the port and then reports ready
# (regardless of timeout)
wait_for_nc()
wait_for_listen()
{
local PORT=$1
local ADDR=$2
local MODULE=$3
for i in $(seq 1 50)
for i in {1..50}
do
netstat -nptl 2>/dev/null | grep '/nc\s*$' | awk '{ print $4 }' | \
sed 's/.*://' | grep \^${PORT}\$ >/dev/null && break
ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break
sleep 0.2
done
if [[ $incremental -eq 1 ]];then
echo "ready ${ADDR}/${MODULE}/$lsn"
else
echo "ready ${ADDR}/${MODULE}"
fi
}
INNOBACKUPEX_BIN=innobackupex
INNOBACKUPEX_ARGS=""
NC_BIN=nc
check_extra()
{
local use_socket=1
if [[ $uextra -eq 1 ]];then
if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then
local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2)
if [[ -n $eport ]];then
# Xtrabackup works only locally.
# Hence, setting host to 127.0.0.1 unconditionally.
wsrep_log_info "SST through extra_port $eport"
INNOEXTRA+=" --host=127.0.0.1 --port=$eport "
use_socket=0
else
wsrep_log_error "Extra port $eport null, failing"
exit 1
fi
else
wsrep_log_info "Thread pool not set, ignore the option use_extra"
fi
fi
if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then
INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}"
fi
}
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
if [[ ! -x `which innobackupex` ]];then
wsrep_log_error "innobackupex not in path: $PATH"
exit 2
fi
#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}"
if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then
wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}"
exit 22
fi
read_cnf
setup_ports
get_stream
get_transfer
INNOEXTRA=""
INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log"
INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log"
if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
then
trap cleanup_donor EXIT
NC_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
then
TMPDIR="/tmp"
INNOBACKUPEX_ARGS="--galera-info --stream=$sfmt
--defaults-file=${WSREP_SST_OPT_CONF}
--socket=${WSREP_SST_OPT_SOCKET}"
TMPDIR="${TMPDIR:-/tmp}"
if [ "${AUTH[0]}" != "(null)" ]; then
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --user=${AUTH[0]}"
fi
INNOEXTRA+=" --user=${AUTH[0]}"
fi
if [ ${#AUTH[*]} -eq 2 ]; then
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=${AUTH[1]}"
else
INNOEXTRA+=" --password=${AUTH[1]}"
elif [ "${AUTH[0]}" != "(null)" ]; then
# Empty password, used for testing, debugging etc.
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password="
fi
INNOEXTRA+=" --password="
fi
get_keys
if [[ $encrypt -eq 1 ]];then
if [[ -n $ekey ]];then
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key=$ekey"
INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey "
else
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key-file=$ekeyfile"
INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile "
fi
fi
wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${NC_PORT}"
if [[ -n $lsn ]];then
INNOEXTRA+=" --incremental --incremental-lsn=$lsn "
fi
check_extra
wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT}"
if [[ -n $progress ]];then
get_footprint
tcmd="$pcmd | $tcmd"
elif [[ -n $rlimit ]];then
adjust_progress
tcmd="$pcmd | $tcmd"
fi
set +e
${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \
2> ${DATA}/innobackup.backup.log | \
${NC_BIN} ${REMOTEIP} ${NC_PORT}
RC=( "${PIPESTATUS[@]}" )
timeit "Donor-Transfer" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e
if [ ${RC[0]} -ne 0 ]; then
wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \
"Check ${DATA}/innobackup.backup.log"
exit 22
elif [ ${RC[1]} -ne 0 ]; then
wsrep_log_error "${NC_BIN} finished with error: ${RC[1]}"
elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
wsrep_log_error "$tcmd finished with error: ${RC[1]}"
exit 22
fi
@ -272,7 +507,8 @@ then
XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid"
else # BYPASS
else # BYPASS FOR IST
wsrep_log_info "Bypassing the SST for IST"
STATE="${WSREP_SST_OPT_GTID}"
echo "continue" # now server can resume updating data
@ -282,15 +518,9 @@ then
pushd ${DATA} 1>/dev/null
set +e
if [[ $encrypt -eq 1 ]];then
if [[ -n $ekey ]];then
xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
else
xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
fi
else
$strmcmd | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
tcmd=" $ecmd | $tcmd"
fi
RC=( "${PIPESTATUS[@]}" )
timeit "Donor-IST-Unencrypted-transfer" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e
popd 1>/dev/null
@ -301,69 +531,86 @@ then
exit 1
fi
done
#rm -f ${DATA}/${IST_FILE}
fi
echo "done ${WSREP_SST_OPT_GTID}"
wsrep_log_info "Total time on donor: $totime seconds"
elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ]
then
[[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
touch $SST_PROGRESS_FILE
if [[ ! -e ${DATA}/ibdata1 ]];then
incremental=0
fi
if [[ $incremental -eq 1 ]];then
wsrep_log_info "Incremental SST enabled"
#lsn=$(/pxc/bin/mysqld --defaults-file=$WSREP_SST_OPT_CONF --basedir=/pxc --wsrep-recover 2>&1 | grep -o 'log sequence number .*' | cut -d " " -f 4 | head -1)
lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ')
wsrep_log_info "Recovered LSN: $lsn"
fi
sencrypted=1
nthreads=1
MODULE="xtrabackup_sst"
rm -f ${DATA}/xtrabackup_*
# May need xtrabackup_checkpoints later on
rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile
ADDR=${WSREP_SST_OPT_ADDR}
NC_PORT=$(echo ${ADDR} | awk -F ':' '{ print $2 }')
if [ -z "${NC_PORT}" ]
if [ -z "${SST_PORT}" ]
then
NC_PORT=4444
ADDR="$(echo ${ADDR} | awk -F ':' '{ print $1 }'):${NC_PORT}"
SST_PORT=4444
ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}"
fi
wait_for_nc ${NC_PORT} ${ADDR} ${MODULE} &
wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} &
trap "exit 32" HUP PIPE
trap "exit 3" INT TERM
trap sig_joiner_cleanup HUP PIPE INT TERM
trap cleanup_joiner EXIT
if [[ -n $progress ]];then
adjust_progress
tcmd+=" | $pcmd"
fi
if [[ $incremental -eq 1 ]];then
BDATA=$DATA
DATA=$(mktemp -d)
MAGIC_FILE="${DATA}/${INFO_FILE}"
fi
get_keys
set +e
if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
if [[ -n $ekey ]];then
${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey | xbstream -x -C ${DATA}
else
${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | xbstream -x -C ${DATA}
fi
else
${NC_BIN} -dl ${NC_PORT} | $strmcmd
strmcmd=" $ecmd | $strmcmd"
fi
RC=( "${PIPESTATUS[@]}" )
pushd ${DATA} 1>/dev/null
timeit "Joiner-Recv-Unencrypted" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
popd 1>/dev/null
set -e
if [[ $sfmt == 'xbstream' ]];then
# Special handling till lp:1193240 is fixed"
if [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
wsrep_log_error "Xbstream failed"
wsrep_log_error "Data directory ${DATA} needs to be empty for SST: lp:1193240" \
wsrep_log_error "Data directory ${DATA} may not be empty: lp:1193240" \
"Manual intervention required in that case"
exit 32
fi
fi
wait %% # join wait_for_nc thread
wait %% # join for wait_for_listen thread
for ecode in "${RC[@]}";do
if [[ $ecode -ne 0 ]];then
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
@ -372,43 +619,25 @@ then
then
# this message should cause joiner to abort
wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'"
wsrep_log_info "Contents of datadir"
wsrep_log_info "$(ls -l ${DATA}/**/*)"
exit 32
fi
if ! ps -p ${WSREP_SST_OPT_PARENT} >/dev/null
if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null
then
wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly."
exit 32
fi
if [ ! -r "${IST_FILE}" ]
if [ ! -r "${DATA}/${IST_FILE}" ]
then
wsrep_log_info "Proceeding with SST"
rebuild=""
wsrep_log_info "Removing existing ib_logfile files"
rm -f ${DATA}/ib_logfile*
# Decrypt only if not encrypted in stream.
# NOT USED NOW.
# Till https://blueprints.launchpad.net/percona-xtrabackup/+spec/add-support-for-rsync-url
# is implemented
#get_keys
if [[ $encrypt -eq 1 && $sencrypted -eq 0 ]];then
# Decrypt the files if any
find ${DATA} -type f -name '*.xbcrypt' -printf '%p\n' | while read line;do
input=$line
output=${input%.xbcrypt}
if [[ -n $ekey ]];then
xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey -i $input > $output
else
xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile -i $input > $output
fi
done
if [[ $? = 0 ]];then
find ${DATA} -type f -name '*.xbcrypt' -delete
fi
if [[ $incremental -ne 1 ]];then
rm -f ${DATA}/ib_logfile*
else
rm -f ${BDATA}/ib_logfile*
fi
get_proc
@ -416,33 +645,47 @@ then
# Rebuild indexes for compact backups
if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then
wsrep_log_info "Index compaction detected"
nthreads=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--rebuild-threads' | cut -d= -f2)
[[ -z $nthreads ]] && nthreads=$nproc
wsrep_log_info "Rebuilding with $nthreads threads"
rebuild="--rebuild-indexes --rebuild-threads=$nthreads"
rebuild=1
fi
if test -n "$(find ${DATA} -maxdepth 1 -name '*.qp' -print -quit)";then
if [[ $rebuild -eq 1 ]];then
nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc)
wsrep_log_info "Rebuilding during prepare with $nthreads threads"
rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads"
fi
if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then
wsrep_log_info "Compressed qpress files found"
if [[ ! -x `which qpress` ]];then
wsrep_log_error "qpress not found in PATH"
wsrep_log_error "qpress not found in path: $PATH"
exit 22
fi
set +e
if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then
count=$(find ${DATA} -type f -name '*.qp' | wc -l)
count=$(( count*2 ))
if pv --help | grep -q FORMAT;then
pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'"
else
pvopts="-f -s $count -l -N Decompression"
fi
pcmd="pv $pvopts"
adjust_progress
dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d"
else
dcmd="xargs -n 2 qpress -T${nproc}d"
fi
wsrep_log_info "Removing existing ibdata1 file"
rm -f ${DATA}/ibdata1
# Decompress the qpress files
wsrep_log_info "Decompression with $nproc threads"
find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | xargs -P $nproc -n 2 qpress -d
timeit "Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd"
extcode=$?
set -e
if [[ $extcode -eq 0 ]];then
wsrep_log_info "Removing qpress files after decompression"
find ${DATA} -type f -name '*.qp' -delete
@ -455,10 +698,21 @@ then
fi
fi
wsrep_log_info "Preparing the backup at ${DATA}"
if [[ $incremental -eq 1 ]];then
# Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues.
INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \
--ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log"
fi
wsrep_log_info "Preparing the backup at ${DATA}"
timeit "Xtrabackup prepare stage" "$INNOAPPLY"
if [[ $incremental -eq 1 ]];then
wsrep_log_info "Cleaning up ${DATA} after incremental SST"
[[ -d ${DATA} ]] && rm -rf ${DATA}
DATA=$BDATA
fi
${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log $rebuild \
${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log
if [ $? -ne 0 ];
then
wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log"
@ -468,14 +722,13 @@ then
wsrep_log_info "${IST_FILE} received from donor: Running IST"
fi
if [[ ! -r ${MAGIC_FILE} ]];then
wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable"
exit 2
fi
cat "${MAGIC_FILE}" # output UUID:seqno
#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
wsrep_log_info "Total time on joiner: $totime seconds"
fi
exit 0

View File

@ -385,7 +385,13 @@ const char *ha_partition::table_type() const
// we can do this since we only support a single engine type
return m_file[0]->table_type();
}
#ifdef WITH_WSREP
int ha_partition::wsrep_db_type() const
{
// we can do this since we only support a single engine type
return ha_legacy_type(m_file[0]->ht);
}
#endif /* WITH_WSREP */
/*
Destructor method

View File

@ -1265,6 +1265,7 @@ public:
return h;
}
#ifdef WITH_WSREP
virtual int wsrep_db_type() const;
void wsrep_reset_files()
{
for (uint i=0; i < m_tot_parts; i++)

View File

@ -1148,10 +1148,27 @@ int ha_prepare(THD *thd)
{
if ((err= ht->prepare(ht, thd, all)))
{
#ifdef WITH_WSREP
if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP)
{
error= 1;
/* avoid sending error, if we need to replay */
if (thd->wsrep_conflict_state!= MUST_REPLAY)
{
my_error(ER_LOCK_DEADLOCK, MYF(0), err);
}
}
else
{
/* not wsrep hton, bail to native mysql behavior */
#endif
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
ha_rollback_trans(thd, all);
error=1;
break;
#ifdef WITH_WSREP
}
#endif
}
}
else
@ -1407,16 +1424,25 @@ int ha_commit_trans(THD *thd, bool all)
if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP)
{
error= 1;
/* avoid sending error, if we need to replay */
if (thd->wsrep_conflict_state!= MUST_REPLAY)
switch (err)
{
my_error(ER_LOCK_DEADLOCK, MYF(0), err);
case WSREP_TRX_SIZE_EXCEEDED:
/* give user size exeeded erro from wsrep_api.h */
my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED);
break;
case WSREP_TRX_CERT_FAIL:
case WSREP_TRX_ERROR:
/* avoid sending error, if we need to replay */
if (thd->wsrep_conflict_state!= MUST_REPLAY)
{
my_error(ER_LOCK_DEADLOCK, MYF(0), err);
}
}
}
else
/* not wsrep hton, bail to native mysql behavior */
else
/* not wsrep hton, bail to native mysql behavior */
#endif /* WITH_WSREP */
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
@ -5699,7 +5725,9 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table)
table->s->cached_row_logging_check &&
(thd->variables.option_bits & OPTION_BIN_LOG) &&
#ifdef WITH_WSREP
((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()));
/* applier and replayer should not binlog */
((WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV)) ||
mysql_bin_log.is_open()));
#else
mysql_bin_log.is_open());
#endif
@ -5802,6 +5830,17 @@ static int binlog_log_row(TABLE* table,
bool error= 0;
THD *const thd= table->in_use;
#ifdef WITH_WSREP
/* only InnoDB tables will be replicated through binlog emulation */
if (WSREP_EMULATE_BINLOG(thd) &&
table->file->ht->db_type != DB_TYPE_INNODB &&
!(table->file->ht->db_type == DB_TYPE_PARTITION_DB &&
(((ha_partition*)(table->file))->wsrep_db_type() == DB_TYPE_INNODB)))
// !strcmp(table->file->table_type(), "InnoDB"))
{
return 0;
}
#endif /* WITH_WSREP */
if (check_table_binlog_row_based(thd, table))
{
MY_BITMAP cols;

View File

@ -568,7 +568,7 @@ void thd_binlog_trx_reset(THD * thd)
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
if (cache_mngr) cache_mngr->reset(false, true);
}
}
thd->clear_binlog_table_maps();
}

View File

@ -3096,7 +3096,12 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
{
time_t end_time;
#ifdef WITH_WSREP
thd->wsrep_PA_safe= false;
/*
If Query_log_event will contain non trans keyword (not BEGIN, COMMIT,
SAVEPOINT or ROLLBACK) we disable PA for this transaction.
*/
if (!is_trans_keyword())
thd->wsrep_PA_safe= false;
#endif /* WITH_WSREP */
memset(&user, 0, sizeof(user));
memset(&host, 0, sizeof(host));

View File

@ -22,6 +22,7 @@
#include <mysql/plugin.h>
#include <mysql/service_thd_wait.h>
#include <mysql/psi/mysql_stage.h>
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
@ -34,7 +35,6 @@ extern bool
wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
MDL_ticket *ticket);
#endif /* WITH_WSREP */
#ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key key_MDL_map_mutex;
static PSI_mutex_key key_MDL_wait_LOCK_wait_status;
@ -1480,7 +1480,7 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
DBUG_ASSERT(ticket->get_lock());
#ifdef WITH_WSREP
if ((this == &(ticket->get_lock()->m_waiting)) &&
wsrep_thd_is_brute_force((void *)(ticket->get_ctx()->wsrep_get_thd())))
wsrep_thd_is_BF((void *)(ticket->get_ctx()->wsrep_get_thd()), false))
{
Ticket_iterator itw(ticket->get_lock()->m_waiting);
Ticket_iterator itg(ticket->get_lock()->m_granted);
@ -1491,7 +1491,7 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
while ((waiting= itw++) && !added)
{
if (!wsrep_thd_is_brute_force((void *)(waiting->get_ctx()->wsrep_get_thd())))
if (!wsrep_thd_is_BF((void *)(waiting->get_ctx()->wsrep_get_thd()), true))
{
WSREP_DEBUG("MDL add_ticket inserted before: %lu %s",
wsrep_thd_thread_id(waiting->get_ctx()->wsrep_get_thd()),
@ -1892,7 +1892,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
ticket->is_incompatible_when_granted(type_arg))
#ifdef WITH_WSREP
{
if (wsrep_thd_is_brute_force((void *)(requestor_ctx->wsrep_get_thd())) &&
if (wsrep_thd_is_BF((void *)(requestor_ctx->wsrep_get_thd()),false) &&
key.mdl_namespace() == MDL_key::GLOBAL)
{
WSREP_DEBUG("global lock granted for BF: %lu %s",
@ -1933,7 +1933,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
#ifdef WITH_WSREP
else
{
if (wsrep_thd_is_brute_force((void *)(requestor_ctx->wsrep_get_thd())) &&
if (wsrep_thd_is_BF((void *)(requestor_ctx->wsrep_get_thd()), false) &&
key.mdl_namespace() == MDL_key::GLOBAL)
{
WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s",

View File

@ -76,7 +76,6 @@
#include "wsrep_var.h"
#include "wsrep_thd.h"
#include "wsrep_sst.h"
ulong wsrep_running_threads = 0; // # of currently running wsrep threads
#endif
#include "sql_callback.h"
#include "threadpool.h"
@ -2747,11 +2746,7 @@ static void network_init(void)
@note
For the connection that is doing shutdown, this is called twice
*/
#ifdef WITH_WSREP
void close_connection(THD *thd, uint sql_errno, bool lock)
#else
void close_connection(THD *thd, uint sql_errno)
#endif
{
DBUG_ENTER("close_connection");
@ -2984,7 +2979,11 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
unlink_thd(thd);
/* Mark that current_thd is not valid anymore */
set_current_thd(0);
#ifdef WITH_WSREP
if (put_in_cache && cache_thread() && !thd->wsrep_applier)
#else
if (put_in_cache && cache_thread())
#endif /* WITH_WSREP */
DBUG_RETURN(0); // Thread is reused
/*
@ -3428,10 +3427,21 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused)))
should not be any other mysql_cond_signal() calls.
*/
mysql_mutex_lock(&LOCK_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
/*
Waiting for until mysqld_server_started != 0
to ensure that all server components has been successfully
initialized. This step is mandatory since signal processing
could be done safely only when all server components
has been initialized.
*/
mysql_mutex_lock(&LOCK_server_started);
while (!mysqld_server_started)
mysql_cond_wait(&COND_server_started, &LOCK_server_started);
mysql_mutex_unlock(&LOCK_server_started);
(void) pthread_sigmask(SIG_BLOCK,&set,NULL);
for (;;)
{
int error; // Used when debugging
@ -4879,42 +4889,8 @@ will be ignored as the --log-bin option is not defined.");
}
#endif
#ifdef WITH_WSREP /* WSREP BEFORE SE */
if (!wsrep_recovery)
{
if (opt_bootstrap) // bootsrap option given - disable wsrep functionality
{
wsrep_provider_init(WSREP_NONE);
if (wsrep_init()) unireg_abort(1);
}
else // full wsrep initialization
{
// add basedir/bin to PATH to resolve wsrep script names
char* const tmp_path((char*)alloca(strlen(mysql_home) +
strlen("/bin") + 1));
if (tmp_path)
{
strcpy(tmp_path, mysql_home);
strcat(tmp_path, "/bin");
wsrep_prepend_PATH(tmp_path);
}
else
{
WSREP_ERROR("Could not append %s/bin to PATH", mysql_home);
}
DBUG_ASSERT(!opt_bin_log || opt_bin_logname);
if (wsrep_before_SE())
{
#ifndef EMBEDDED_LIBRARY
set_ports(); // this is also called in network_init() later but we need
// to know mysqld_port now - lp:1071882
#endif /* !EMBEDDED_LIBRARY */
wsrep_init_startup(true);
}
}
}
#endif /* WITH_WSREP */
if (opt_bin_log)
{
/* Reports an error and aborts, if the --log-bin's path
@ -4962,10 +4938,67 @@ a file name for --log-bin-index option", opt_binlog_index_name);
{
opt_bin_logname= my_once_strdup(buf, MYF(MY_WME));
}
#ifdef WITH_WSREP /* WSREP BEFORE SE */
/*
Wsrep initialization must happen at this point, because:
- opt_bin_logname must be known when starting replication
since SST may need it
- SST may modify binlog index file, so it must be opened
after SST has happened
*/
}
if (!wsrep_recovery)
{
if (opt_bootstrap) // bootsrap option given - disable wsrep functionality
{
wsrep_provider_init(WSREP_NONE);
if (wsrep_init()) unireg_abort(1);
}
else // full wsrep initialization
{
// add basedir/bin to PATH to resolve wsrep script names
char* const tmp_path((char*)alloca(strlen(mysql_home) +
strlen("/bin") + 1));
if (tmp_path)
{
strcpy(tmp_path, mysql_home);
strcat(tmp_path, "/bin");
wsrep_prepend_PATH(tmp_path);
}
else
{
WSREP_ERROR("Could not append %s/bin to PATH", mysql_home);
}
if (wsrep_before_SE())
{
set_ports(); // this is also called in network_init() later but we need
// to know mysqld_port now - lp:1071882
wsrep_init_startup(true);
}
}
}
if (opt_bin_log)
{
/*
Variable ln is not defined at this scope. We use opt_bin_logname instead.
It should be the same as ln since
- mysql_bin_log.generate_name() returns first argument if new log name
is not generated
- if new log name is generated, return value is assigned to ln and copied
to opt_bin_logname above
*/
if (mysql_bin_log.open_index_file(opt_binlog_index_name, opt_bin_logname,
TRUE))
{
unireg_abort(1);
}
#else
if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE))
{
unireg_abort(1);
}
#endif /* WITH_WSREP */
}
/* call ha_init_key_cache() on all key caches to init them */
@ -5262,7 +5295,7 @@ pthread_handler_t start_wsrep_THD(void *arg)
thd->thr_create_utime= microsecond_interval_timer();
if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0))
{
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
@ -5285,7 +5318,7 @@ pthread_handler_t start_wsrep_THD(void *arg)
thd->thread_stack= (char*) &thd;
if (thd->store_globals())
{
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
delete thd;
@ -5307,19 +5340,9 @@ pthread_handler_t start_wsrep_THD(void *arg)
++connection_count;
mysql_mutex_unlock(&LOCK_connection_count);
mysql_mutex_lock(&LOCK_thread_count);
wsrep_running_threads++;
mysql_cond_signal(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
processor(thd);
close_connection(thd, 0, 1);
mysql_mutex_lock(&LOCK_thread_count);
wsrep_running_threads--;
mysql_cond_signal(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
close_connection(thd, 0);
// Note: We can't call THD destructor without crashing
// if plugins have not been initialized. However, in most of the
@ -5337,6 +5360,7 @@ pthread_handler_t start_wsrep_THD(void *arg)
// at server shutdown
}
my_thread_end();
if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
{
mysql_mutex_lock(&LOCK_thread_count);
@ -5550,7 +5574,7 @@ void wsrep_close_client_connections(my_bool wait_to_end)
!is_replaying_connection(tmp))
{
WSREP_INFO("killing local connection: %ld",tmp->thread_id);
close_connection(tmp,0,0);
close_connection(tmp,0);
}
#endif
}
@ -6644,11 +6668,7 @@ void create_thread_to_handle_connection(THD *thd)
my_snprintf(error_message_buff, sizeof(error_message_buff),
ER_THD(thd, ER_CANT_CREATE_THREAD), error);
net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL);
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES ,0);
#else
close_connection(thd, ER_OUT_OF_RESOURCES);
#endif /* WITH_WSREP */
mysql_mutex_lock(&LOCK_thread_count);
thd->unlink();
@ -6694,11 +6714,7 @@ static void create_new_thread(THD *thd)
mysql_mutex_unlock(&LOCK_connection_count);
DBUG_PRINT("error",("Too many connections"));
#ifdef WITH_WSREP
close_connection(thd, ER_CON_COUNT_ERROR, 1);
#else
close_connection(thd, ER_CON_COUNT_ERROR);
#endif /* WITH_WSREP */
statistic_increment(denied_connections, &LOCK_status);
delete thd;
statistic_increment(connection_errors_max_connection, &LOCK_status);
@ -7109,11 +7125,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg)
if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) ||
my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC)))
{
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
#else
close_connection(thd, ER_OUT_OF_RESOURCES);
#endif
delete thd;
set_current_thd(0);
continue;
@ -7311,11 +7323,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg)
event_conn_closed)) ||
my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC)))
{
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
#else
close_connection(thd, ER_OUT_OF_RESOURCES);
#endif
errmsg= 0;
goto errorconn;
}

View File

@ -55,11 +55,7 @@ typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */
some places */
/* Function prototypes */
void kill_mysql(void);
#ifdef WITH_WSREP
void close_connection(THD *thd, uint sql_errno= 0, bool lock=1);
#else
void close_connection(THD *thd, uint sql_errno= 0);
#endif /* WITH_WSREP */
void handle_connection_in_main_thread(THD *thd);
void create_thread_to_handle_connection(THD *thd);
void delete_running_thd(THD *thd);

View File

@ -4651,6 +4651,22 @@ err_during_init:
DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5););
mysql_mutex_unlock(&rli->run_lock); // tell the world we are done
#ifdef WITH_WSREP
/* if slave stopped due to node going non primary, we set global flag to
trigger automatic restart of slave when node joins back to cluster
*/
if (WSREP_ON && !wsrep_ready)
{
WSREP_INFO("Slave thread stopped because node dropped from cluster");
if (wsrep_restart_slave)
{
WSREP_INFO("wsrep_restart_slave was set and therefore slave will be "
"automatically restarted when node joins back to cluster");
wsrep_restart_slave_activated= TRUE;
}
}
#endif /* WITH_WSREP */
DBUG_LEAVE; // Must match DBUG_ENTER()
my_thread_end();
#ifdef HAVE_OPENSSL

View File

@ -8945,7 +8945,7 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use,
#ifdef WITH_WSREP
{
signalled|= mysql_lock_abort_for_thread(thd, thd_table);
if (thd && WSREP(thd) && wsrep_thd_is_brute_force((void *)thd))
if (thd && WSREP(thd) && wsrep_thd_is_BF((void *)thd, true))
{
WSREP_DEBUG("remove_table_from_cache: %llu",
(unsigned long long) thd->real_id);

View File

@ -66,6 +66,7 @@
#include "lock.h"
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
#endif
#include "sql_connect.h"
@ -958,6 +959,10 @@ extern "C" void wsrep_thd_awake(THD *thd, my_bool signal)
mysql_mutex_unlock(&LOCK_wsrep_replaying);
}
}
extern "C" int wsrep_thd_retry_counter(THD *thd)
{
return(thd->wsrep_retry_counter);
}
extern int
wsrep_trx_order_before(void *thd1, void *thd2)
@ -2129,7 +2134,19 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
(e.g. see partitioning code).
*/
if (!thd_table->needs_reopen())
#ifdef WITH_WSREP
{
signalled|= mysql_lock_abort_for_thread(this, thd_table);
if (this && WSREP(this) && wsrep_thd_is_BF((void *)this, FALSE))
{
WSREP_DEBUG("remove_table_from_cache: %llu",
(unsigned long long) this->real_id);
wsrep_abort_thd((void *)this, (void *)in_use, FALSE);
}
}
#else
signalled|= mysql_lock_abort_for_thread(this, thd_table);
#endif
}
mysql_mutex_unlock(&in_use->LOCK_thd_data);
}

View File

@ -1102,11 +1102,7 @@ bool setup_connection_thread_globals(THD *thd)
{
if (thd->store_globals())
{
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
#else
close_connection(thd, ER_OUT_OF_RESOURCES);
#endif
statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0));
return 1; // Error
@ -1351,11 +1347,7 @@ void do_handle_one_connection(THD *thd_arg)
if (MYSQL_CALLBACK_ELSE(thd->scheduler, init_new_connection_thread, (), 0))
{
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
#else
close_connection(thd, ER_OUT_OF_RESOURCES);
#endif
statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0));
return;
@ -1413,13 +1405,9 @@ void do_handle_one_connection(THD *thd_arg)
thd->wsrep_query_state= QUERY_EXITING;
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
#endif
end_thread:
#ifdef WITH_WSREP
close_connection(thd, 0, 1);
#else
close_connection(thd);
#endif
end_thread:
close_connection(thd);
if (thd->userstat_running)
update_global_user_stats(thd, create_user, time(NULL));

View File

@ -820,11 +820,7 @@ void do_handle_bootstrap(THD *thd)
if (my_thread_init() || thd->store_globals())
{
#ifndef EMBEDDED_LIBRARY
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
#else
close_connection(thd, ER_OUT_OF_RESOURCES);
#endif /* WITH_WSREP */
#endif
thd->fatal_error();
goto end;
@ -2736,7 +2732,9 @@ mysql_execute_command(THD *thd)
if (trans_commit_implicit(thd))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("implicit commit failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
/* Release metadata locks acquired in this transaction. */
@ -4758,7 +4756,9 @@ end_with_restore_list:
if (trans_begin(thd, lex->start_transaction_opt))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("BEGIN failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
my_ok(thd);
@ -4776,7 +4776,9 @@ end_with_restore_list:
if (trans_commit(thd))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("COMMIT failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
thd->mdl_context.release_transactional_locks();
@ -4802,9 +4804,9 @@ end_with_restore_list:
if (WSREP(thd)) {
if (thd->wsrep_conflict_state == NO_CONFLICT ||
thd->wsrep_conflict_state == REPLAYING)
thd->wsrep_conflict_state == REPLAYING)
{
my_ok(thd);
my_ok(thd);
}
} else {
#endif /* WITH_WSREP */
@ -4828,7 +4830,9 @@ end_with_restore_list:
if (trans_rollback(thd))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("rollback failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
thd->mdl_context.release_transactional_locks();
@ -4850,7 +4854,7 @@ end_with_restore_list:
#ifdef WITH_WSREP
if (WSREP(thd)) {
if (thd->wsrep_conflict_state == NO_CONFLICT) {
my_ok(thd);
my_ok(thd);
}
} else {
#endif /* WITH_WSREP */
@ -5375,7 +5379,9 @@ create_sp_error:
if (trans_xa_commit(thd))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("XA commit failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
thd->mdl_context.release_transactional_locks();
@ -5391,7 +5397,9 @@ create_sp_error:
if (trans_xa_rollback(thd))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("XA rollback failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
thd->mdl_context.release_transactional_locks();
@ -7930,7 +7938,7 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
#ifdef WITH_WSREP
if (((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx)) &&
!wsrep_thd_is_brute_force((void *)tmp))
!wsrep_thd_is_BF((void *)tmp, true))
#else
if ((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx))

View File

@ -763,6 +763,19 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
if (check_one_table_access(thd, DROP_ACL, first_table))
DBUG_RETURN(TRUE);
#ifdef WITH_WSREP
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
if ((!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, first_table)) &&
wsrep_to_isolation_begin(
thd, first_table->db, first_table->table_name, NULL)
)
{
WSREP_WARN("ALTER TABLE isolation failure");
DBUG_RETURN(TRUE);
}
#endif /* WITH_WSREP */
if (open_tables(thd, &first_table, &table_counter, 0))
DBUG_RETURN(true);

View File

@ -455,6 +455,12 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
{
bool hton_can_recreate;
#ifdef WITH_WSREP
if (WSREP(thd) && wsrep_to_isolation_begin(thd,
table_ref->db,
table_ref->table_name, NULL))
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
if (lock_table(thd, table_ref, &hton_can_recreate))
DBUG_RETURN(TRUE);
@ -531,12 +537,6 @@ bool Sql_cmd_truncate_table::execute(THD *thd)
if (check_one_table_access(thd, DROP_ACL, first_table))
DBUG_RETURN(res);
#ifdef WITH_WSREP
if (WSREP(thd) && wsrep_to_isolation_begin(thd,
first_table->db,
first_table->table_name, NULL))
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
if (! (res= truncate_table(thd, first_table)))
my_ok(thd);
DBUG_RETURN(res);

View File

@ -3314,7 +3314,9 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type)
{
thd->variables.option_bits&= ~OPTION_AUTOCOMMIT;
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("autocommit, MDL TRX lock released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
return true;
}
/*
@ -4646,6 +4648,10 @@ static Sys_var_mybool Sys_wsrep_load_data_splitting(
"transaction after every 10K rows inserted",
GLOBAL_VAR(wsrep_load_data_splitting),
CMD_LINE(OPT_ARG), DEFAULT(TRUE));
static Sys_var_mybool Sys_wsrep_restart_slave(
"wsrep_restart_slave", "Should MySQL slave be restarted automatically, when node joins back to cluster",
GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
#endif /* WITH_WSREP */
static bool fix_host_cache_size(sys_var *, THD *, enum_var_type)

View File

@ -55,8 +55,8 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len)
wsrep_max_ws_size, total_length);
goto error;
}
uchar* tmp = (uchar *)my_realloc(*buf, total_length,
MYF(MY_ALLOW_ZERO_PTR));
uchar* tmp = (uchar *)my_realloc(*buf, total_length, MYF(0));
if (!tmp)
{
WSREP_ERROR("could not (re)allocate buffer: %zu + %u",
@ -72,7 +72,7 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len)
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
{
WSREP_ERROR("failed to initialize io-cache");
WSREP_WARN("failed to initialize io-cache");
goto cleanup;
}
@ -166,19 +166,19 @@ static int wsrep_write_cache_once(wsrep_t* const wsrep,
{
WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
wsrep_max_ws_size, total_length);
err = WSREP_TRX_SIZE_EXCEEDED;
goto cleanup;
}
if (total_length > allocated)
{
size_t const new_size(heap_size(total_length));
uchar* tmp = (uchar *)my_realloc(heap_buf, new_size,
MYF(MY_ALLOW_ZERO_PTR));
uchar* tmp = (uchar *)my_realloc(heap_buf, new_size, MYF(0));
if (!tmp)
{
WSREP_ERROR("could not (re)allocate buffer: %zu + %u",
allocated, length);
err = WSREP_SIZE_EXCEEDED;
err = WSREP_TRX_SIZE_EXCEEDED;
goto cleanup;
}
@ -233,7 +233,7 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep,
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
{
WSREP_ERROR("failed to initialize io-cache");
return WSREP_TRX_ROLLBACK;
return WSREP_TRX_ERROR;
}
int err(WSREP_OK);
@ -254,7 +254,7 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep,
{
WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
wsrep_max_ws_size, total_length);
err = WSREP_SIZE_EXCEEDED;
err = WSREP_TRX_SIZE_EXCEEDED;
goto cleanup;
}
@ -349,3 +349,59 @@ int wsrep_binlog_savepoint_rollback(THD *thd, void *sv)
int rcode = binlog_hton->savepoint_rollback(binlog_hton, thd, sv);
return rcode;
}
void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache)
{
char filename[PATH_MAX]= {0};
int len= snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld.log",
wsrep_data_home_dir, thd->thread_id,
(long long)wsrep_thd_trx_seqno(thd));
size_t bytes_in_cache = 0;
// check path
if (len >= PATH_MAX)
{
WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len);
return ;
}
// init cache
my_off_t const saved_pos(my_b_tell(cache));
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
{
WSREP_ERROR("failed to initialize io-cache");
return ;
}
// open file
FILE* of = fopen(filename, "wb");
if (!of)
{
WSREP_ERROR("Failed to open file '%s': %d (%s)",
filename, errno, strerror(errno));
goto cleanup;
}
// ready to write
bytes_in_cache= my_b_bytes_in_cache(cache);
if (unlikely(bytes_in_cache == 0)) bytes_in_cache = my_b_fill(cache);
if (likely(bytes_in_cache > 0)) do
{
if (my_fwrite(of, cache->read_pos, bytes_in_cache,
MYF(MY_WME | MY_NABP)) == (size_t) -1)
{
WSREP_ERROR("Failed to write file '%s'", filename);
goto cleanup;
}
cache->read_pos= cache->read_end;
} while ((cache->file >= 0) && (bytes_in_cache= my_b_fill(cache)));
if(cache->error == -1)
{
WSREP_ERROR("RBR inconsistent");
goto cleanup;
}
cleanup:
// init back
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
{
WSREP_ERROR("failed to reinitialize io-cache");
}
// close file
if (of) fclose(of);
}

View File

@ -50,4 +50,7 @@ int wsrep_binlog_close_connection(THD* thd);
int wsrep_binlog_savepoint_set(THD *thd, void *sv);
int wsrep_binlog_savepoint_rollback(THD *thd, void *sv);
/* Dump replication buffer to disk without intermediate buffer */
void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache);
#endif /* WSREP_BINLOG_H */

View File

@ -303,19 +303,6 @@ check_opts (int const argc, const char* const argv[], struct opt opts[])
}
}
long long query_cache_size, query_cache_type;
if ((err = get_long_long (opts[QUERY_CACHE_SIZE], &query_cache_size, 10)))
return err;
if ((err = get_long_long (opts[QUERY_CACHE_TYPE], &query_cache_type, 10)))
return err;
if (0 != query_cache_size && 0 != query_cache_type)
{
WSREP_ERROR ("Query cache is not supported (size=%lld type=%lld)",
query_cache_size, query_cache_type);
rcode = EINVAL;
}
bool locked_in_memory;
err = get_bool (opts[LOCKED_IN_MEMORY], &locked_in_memory);
if (err) { WSREP_ERROR("get_bool error: %s", strerror(err)); return err; }

View File

@ -134,7 +134,7 @@ wsrep_close_connection(handlerton* hton, THD* thd)
- certification test or an equivalent. As a result,
the current transaction just rolls back
Error codes:
WSREP_TRX_ROLLBACK, WSREP_TRX_ERROR
WSREP_TRX_CERT_FAIL, WSREP_TRX_SIZE_EXCEEDED, WSREP_TRX_ERROR
- a post-certification failure makes this server unable to
commit its own WS and therefore the server must abort
*/
@ -155,14 +155,7 @@ static int wsrep_prepare(handlerton *hton, THD *thd, bool all)
!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
(thd->variables.wsrep_on && !wsrep_trans_cache_is_empty(thd)))
{
switch (wsrep_run_wsrep_commit(thd, hton, all))
{
case WSREP_TRX_OK:
break;
case WSREP_TRX_ROLLBACK:
case WSREP_TRX_ERROR:
DBUG_RETURN(1);
}
DBUG_RETURN (wsrep_run_wsrep_commit(thd, hton, all));
}
DBUG_RETURN(0);
}
@ -330,7 +323,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all)
WSREP_INFO("innobase_commit, abort %s",
(thd->query()) ? thd->query() : "void");
}
DBUG_RETURN(WSREP_TRX_ROLLBACK);
DBUG_RETURN(WSREP_TRX_CERT_FAIL);
}
mysql_mutex_lock(&LOCK_wsrep_replaying);
@ -381,7 +374,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all)
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
WSREP_DEBUG("innobase_commit abort after replaying wait %s",
(thd->query()) ? thd->query() : "void");
DBUG_RETURN(WSREP_TRX_ROLLBACK);
DBUG_RETURN(WSREP_TRX_CERT_FAIL);
}
thd->wsrep_query_state = QUERY_COMMITTING;
@ -394,7 +387,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all)
rcode = wsrep_write_cache(wsrep, thd, cache, &data_len);
if (WSREP_OK != rcode) {
WSREP_ERROR("rbr write fail, data_len: %zu, %d", data_len, rcode);
DBUG_RETURN(WSREP_TRX_ROLLBACK);
DBUG_RETURN(WSREP_TRX_SIZE_EXCEEDED);
}
}
@ -517,7 +510,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all)
}
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
DBUG_RETURN(WSREP_TRX_ROLLBACK);
DBUG_RETURN(WSREP_TRX_CERT_FAIL);
case WSREP_CONN_FAIL:
WSREP_ERROR("connection failure");

View File

@ -26,6 +26,7 @@
#include <cstdio>
#include <cstdlib>
#include "log_event.h"
#include <slave.h>
wsrep_t *wsrep = NULL;
my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface
@ -63,7 +64,10 @@ ulong wsrep_mysql_replication_bundle = 0;
my_bool wsrep_desync = 0; // desynchronize the node from the
// cluster
my_bool wsrep_load_data_splitting = 1; // commit load data every 10K intervals
my_bool wsrep_restart_slave = 0; // should mysql slave thread be
// restarted, if node joins back
my_bool wsrep_restart_slave_activated = 0; // node has dropped, and slave
// restart will be needed
/*
* End configuration options
*/
@ -126,7 +130,7 @@ static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) {
sql_print_error("WSREP: %s", msg);
break;
case WSREP_LOG_DEBUG:
if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg);
sql_print_information ("[Debug] WSREP: %s", msg);
default:
break;
}
@ -407,14 +411,32 @@ void wsrep_ready_wait ()
static void wsrep_synced_cb(void* app_ctx)
{
WSREP_INFO("Synchronized with group, ready for connections");
bool signal_main= false;
if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
if (!wsrep_ready)
{
wsrep_ready= TRUE;
mysql_cond_signal (&COND_wsrep_ready);
signal_main= true;
}
local_status.set(WSREP_MEMBER_SYNCED);
mysql_mutex_unlock (&LOCK_wsrep_ready);
if (signal_main)
{
wsrep_SE_init_grab();
// Signal mysqld init thread to continue
wsrep_sst_complete (&local_uuid, local_seqno, false);
// and wait for SE initialization
wsrep_SE_init_wait();
}
if (wsrep_restart_slave_activated)
{
WSREP_INFO("MySQL slave restart");
wsrep_restart_slave_activated= FALSE;
init_slave();
}
}
static void wsrep_init_position()
@ -495,7 +517,18 @@ int wsrep_init()
wsrep_ready_set(TRUE);
wsrep_inited= 1;
global_system_variables.wsrep_on = 0;
return 0;
wsrep_init_args args;
args.options = (wsrep_provider_options) ?
wsrep_provider_options : "";
rcode = wsrep->init(wsrep, &args);
if (rcode)
{
DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode));
WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode);
free(wsrep);
wsrep = NULL;
}
return rcode;
}
else
{
@ -651,7 +684,7 @@ void wsrep_init_startup (bool first)
{
if (wsrep_init()) unireg_abort(1);
wsrep_thr_lock_init(wsrep_thd_is_brute_force, wsrep_abort_thd,
wsrep_thr_lock_init(wsrep_thd_is_BF, wsrep_abort_thd,
wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on);
/* Skip replication start if no cluster address */
@ -1358,6 +1391,13 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE);
DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED);
if (thd->global_read_lock.can_acquire_protection())
{
WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lu",
thd->query(), thd->thread_id);
return -1;
}
if (wsrep_debug && thd->mdl_context.has_locks())
{
WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu",

View File

@ -96,6 +96,8 @@ extern my_bool wsrep_replicate_myisam;
extern my_bool wsrep_log_conflicts;
extern ulong wsrep_mysql_replication_bundle;
extern my_bool wsrep_load_data_splitting;
extern my_bool wsrep_restart_slave;
extern my_bool wsrep_restart_slave_activated;
enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU };
@ -158,6 +160,7 @@ extern "C" char * wsrep_thd_query(THD *thd);
extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
extern "C" void wsrep_thd_awake(THD *thd, my_bool signal);
extern "C" int wsrep_thd_retry_counter(THD *thd);
extern void wsrep_close_client_connections(my_bool wait_to_end);
@ -232,8 +235,9 @@ extern void wsrep_ready_wait();
enum wsrep_trx_status {
WSREP_TRX_OK,
WSREP_TRX_ROLLBACK,
WSREP_TRX_ERROR,
WSREP_TRX_CERT_FAIL, /* certification failure, must abort */
WSREP_TRX_SIZE_EXCEEDED, /* trx size exceeded */
WSREP_TRX_ERROR, /* native mysql error */
};
extern enum wsrep_trx_status
@ -274,6 +278,7 @@ extern rpl_sidno wsrep_sidno;
#endif /* GTID_SUPPORT */
extern my_bool wsrep_preordered_opt;
#ifdef HAVE_PSI_INTERFACE
extern PSI_mutex_key key_LOCK_wsrep_ready;
extern PSI_mutex_key key_COND_wsrep_ready;
extern PSI_mutex_key key_LOCK_wsrep_sst;
@ -288,7 +293,7 @@ extern PSI_mutex_key key_LOCK_wsrep_replaying;
extern PSI_cond_key key_COND_wsrep_replaying;
extern PSI_mutex_key key_LOCK_wsrep_slave_threads;
extern PSI_mutex_key key_LOCK_wsrep_desync;
#endif /* HAVE_PSI_INTERFACE */
struct TABLE_LIST;
int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
const TABLE_LIST* table_list);

View File

@ -51,9 +51,11 @@ extern const char wsrep_defaults_file[];
#define WSREP_SST_OPT_GTID "--gtid"
#define WSREP_SST_OPT_BYPASS "--bypass"
#define WSREP_SST_MYSQLDUMP "mysqldump"
#define WSREP_SST_RSYNC "rsync"
#define WSREP_SST_SKIP "skip"
#define WSREP_SST_MYSQLDUMP "mysqldump"
#define WSREP_SST_RSYNC "rsync"
#define WSREP_SST_SKIP "skip"
#define WSREP_SST_XTRABACKUP "xtrabackup"
#define WSREP_SST_XTRABACKUP_V2 "xtrabackup-v2"
#define WSREP_SST_DEFAULT WSREP_SST_RSYNC
#define WSREP_SST_ADDRESS_AUTO "AUTO"
#define WSREP_SST_AUTH_MASK "********"
@ -231,7 +233,13 @@ void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid,
}
else
{
WSREP_WARN("Nobody is waiting for SST.");
/* This can happen when called from wsrep_synced_cb().
At the moment there is no way to check there
if main thread is still waiting for signal,
so wsrep_sst_complete() is called from there
each time wsrep_ready changes from FALSE -> TRUE.
*/
WSREP_DEBUG("Nobody is waiting for SST.");
}
mysql_mutex_unlock (&LOCK_wsrep_sst);
}
@ -315,6 +323,33 @@ static char* my_fgets (char* buf, size_t buf_len, FILE* stream)
return ret;
}
/*
Generate opt_binlog_opt_val for sst_donate_other(), sst_prepare_other().
Returns zero on success, negative error code otherwise.
String containing binlog name is stored in param ret if binlog is enabled
and GTID mode is on, otherwise empty string. Returned string should be
freed with my_free().
*/
static int generate_binlog_opt_val(char** ret)
{
DBUG_ASSERT(ret);
*ret= NULL;
if (opt_bin_log)
{
assert(opt_bin_logname);
*ret= strcmp(opt_bin_logname, "0") ?
my_strdup(opt_bin_logname, MYF(0)) : my_strdup("", MYF(0));
}
else
{
*ret= my_strdup("", MYF(0));
}
if (!*ret) return -ENOMEM;
return 0;
}
static void* sst_joiner_thread (void* a)
{
sst_thread_arg* arg= (sst_thread_arg*) a;
@ -409,21 +444,32 @@ static ssize_t sst_prepare_other (const char* method,
ssize_t cmd_len= 1024;
char cmd_str[cmd_len];
const char* sst_dir= mysql_real_data_home;
const char* binlog_opt= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? WSREP_SST_OPT_BINLOG : "") : "");
const char* binlog_opt_val= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? opt_bin_logname : "") : "");
const char* binlog_opt= "";
char* binlog_opt_val= NULL;
int ret= snprintf (cmd_str, cmd_len,
"wsrep_sst_%s "
WSREP_SST_OPT_ROLE" 'joiner' "
WSREP_SST_OPT_ADDR" '%s' "
WSREP_SST_OPT_AUTH" '%s' "
WSREP_SST_OPT_DATA" '%s' "
WSREP_SST_OPT_CONF" '%s' "
WSREP_SST_OPT_PARENT" '%d'"
" %s '%s' ",
method, addr_in, (sst_auth_real) ? sst_auth_real : "",
sst_dir, wsrep_defaults_file, (int)getpid(),
binlog_opt, binlog_opt_val);
int ret;
if ((ret= generate_binlog_opt_val(&binlog_opt_val)))
{
WSREP_ERROR("sst_prepare_other(): generate_binlog_opt_val() failed: %d",
ret);
return ret;
}
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG;
ret= snprintf (cmd_str, cmd_len,
"wsrep_sst_%s "
WSREP_SST_OPT_ROLE" 'joiner' "
WSREP_SST_OPT_ADDR" '%s' "
WSREP_SST_OPT_AUTH" '%s' "
WSREP_SST_OPT_DATA" '%s' "
WSREP_SST_OPT_CONF" '%s' "
WSREP_SST_OPT_PARENT" '%d'"
" %s '%s' ",
method, addr_in, (sst_auth_real) ? sst_auth_real : "",
sst_dir, wsrep_defaults_file, (int)getpid(),
binlog_opt, binlog_opt_val);
my_free(binlog_opt_val);
if (ret < 0 || ret >= cmd_len)
{
@ -933,8 +979,9 @@ wait_signal:
else
{
WSREP_ERROR("Failed to read from: %s", proc.cmd());
proc.wait();
}
if (err && proc.error()) err= proc.error();
if (!err && proc.error()) err= proc.error();
}
else
{
@ -958,6 +1005,8 @@ wait_signal:
return NULL;
}
static int sst_donate_other (const char* method,
const char* addr,
const char* uuid,
@ -966,25 +1015,34 @@ static int sst_donate_other (const char* method,
{
ssize_t cmd_len = 4096;
char cmd_str[cmd_len];
const char* binlog_opt= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? WSREP_SST_OPT_BINLOG : "") : "");
const char* binlog_opt_val= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? opt_bin_logname : "") : "");
const char* binlog_opt= "";
char* binlog_opt_val= NULL;
int ret= snprintf (cmd_str, cmd_len,
"wsrep_sst_%s "
WSREP_SST_OPT_ROLE" 'donor' "
WSREP_SST_OPT_ADDR" '%s' "
WSREP_SST_OPT_AUTH" '%s' "
WSREP_SST_OPT_SOCKET" '%s' "
WSREP_SST_OPT_DATA" '%s' "
WSREP_SST_OPT_CONF" '%s' "
" %s '%s' "
WSREP_SST_OPT_GTID" '%s:%lld'"
"%s",
method, addr, sst_auth_real, mysqld_unix_port,
mysql_real_data_home, wsrep_defaults_file,
binlog_opt, binlog_opt_val,
uuid, (long long) seqno,
bypass ? " "WSREP_SST_OPT_BYPASS : "");
int ret;
if ((ret= generate_binlog_opt_val(&binlog_opt_val)))
{
WSREP_ERROR("sst_donate_other(): generate_binlog_opt_val() failed: %d",ret);
return ret;
}
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG;
ret= snprintf (cmd_str, cmd_len,
"wsrep_sst_%s "
WSREP_SST_OPT_ROLE" 'donor' "
WSREP_SST_OPT_ADDR" '%s' "
WSREP_SST_OPT_AUTH" '%s' "
WSREP_SST_OPT_SOCKET" '%s' "
WSREP_SST_OPT_DATA" '%s' "
WSREP_SST_OPT_CONF" '%s' "
" %s '%s' "
WSREP_SST_OPT_GTID" '%s:%lld'"
"%s",
method, addr, sst_auth_real, mysqld_unix_port,
mysql_real_data_home, wsrep_defaults_file,
binlog_opt, binlog_opt_val,
uuid, (long long) seqno,
bypass ? " "WSREP_SST_OPT_BYPASS : "");
my_free(binlog_opt_val);
if (ret < 0 || ret >= cmd_len)
{
@ -1049,7 +1107,10 @@ void wsrep_SE_init_grab()
void wsrep_SE_init_wait()
{
mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init);
while (SE_initialized == false)
{
mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init);
}
mysql_mutex_unlock (&LOCK_wsrep_sst_init);
}

View File

@ -472,31 +472,53 @@ void wsrep_create_rollbacker()
}
}
extern "C"
int wsrep_thd_is_brute_force(void *thd_ptr)
{
/*
Brute force:
Appliers and replaying are running in REPL_RECV mode. TOI statements
in TOTAL_ORDER mode. Locally committing transaction that has got
past wsrep->pre_commit() without error is running in LOCAL_COMMIT mode.
Everything else is running in LOCAL_STATE and should not be considered
brute force.
*/
if (thd_ptr) {
switch (((THD *)thd_ptr)->wsrep_exec_mode) {
case LOCAL_STATE: return 0;
case REPL_RECV: return 1;
case TOTAL_ORDER: return 2;
case LOCAL_COMMIT: return 3;
}
DBUG_ASSERT(0);
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync)
{
my_bool status = FALSE;
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = ((thd->wsrep_exec_mode == REPL_RECV) ||
(thd->wsrep_exec_mode == TOTAL_ORDER));
if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
return 0;
return status;
}
extern "C"
my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync)
{
bool status = FALSE;
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = ((thd->wsrep_exec_mode == REPL_RECV) ||
(thd->wsrep_exec_mode == TOTAL_ORDER) ||
(thd->wsrep_exec_mode == LOCAL_COMMIT));
if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
return status;
}
extern "C"
my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync)
{
bool status = FALSE;
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = (thd->wsrep_exec_mode == LOCAL_STATE);
if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
return status;
}
int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal)
{
THD *victim_thd = (THD *) victim_thd_ptr;

View File

@ -24,9 +24,13 @@ void wsrep_replay_transaction(THD *thd);
void wsrep_create_appliers(long threads);
void wsrep_create_rollbacker();
extern "C" int wsrep_thd_is_brute_force(void *thd_ptr);
extern "C" int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr,
int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr,
my_bool signal);
extern my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
//extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync);
extern "C" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync);
extern "C" int wsrep_thd_in_locking_session(void *thd_ptr);
#endif /* WSREP_THD_H */

View File

@ -321,6 +321,10 @@ thd::~thd ()
/* Returns INADDR_NONE, INADDR_ANY, INADDR_LOOPBACK or something else */
unsigned int wsrep_check_ip (const char* const addr)
{
#if 0
if (addr && 0 == strcasecmp(addr, MY_BIND_ALL_ADDRESSES)) return INADDR_ANY;
#endif
unsigned int ret = INADDR_NONE;
struct addrinfo *res, hints;
@ -362,7 +366,6 @@ unsigned int wsrep_check_ip (const char* const addr)
}
extern char* my_bind_addr_str;
extern uint mysqld_port;
size_t wsrep_guess_ip (char* buf, size_t buf_len)
{

View File

@ -331,7 +331,16 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
bool wsrep_on_saved= thd->variables.wsrep_on;
thd->variables.wsrep_on= false;
/* stop replication is heavy operation, and includes closing all client
connections. Closing clients may need to get LOCK_global_system_variables
at least in MariaDB.
Note: releasing LOCK_global_system_variables may cause race condition, if
there can be several concurrent clients changing wsrep_provider
*/
mysql_mutex_unlock(&LOCK_global_system_variables);
wsrep_stop_replication(thd);
mysql_mutex_lock(&LOCK_global_system_variables);
if (wsrep_start_replication())
{

View File

@ -1207,8 +1207,8 @@ innobase_srv_conc_enter_innodb(
trx_t* trx) /*!< in: transaction handle */
{
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) return;
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return;
#endif /* WITH_WSREP */
if (srv_thread_concurrency) {
if (trx->n_tickets_to_enter_innodb > 0) {
@ -1245,8 +1245,8 @@ innobase_srv_conc_exit_innodb(
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) return;
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return;
#endif /* WITH_WSREP */
/* This is to avoid making an unnecessary function call. */
@ -3534,11 +3534,6 @@ innobase_commit_low(
/*================*/
trx_t* trx) /*!< in: transaction handle */
{
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
}
#ifdef WITH_WSREP
THD* thd = (THD*)trx->mysql_thd;
const char* tmp = 0;
@ -3556,7 +3551,10 @@ innobase_commit_low(
#endif /* WSREP_PROC_INFO */
}
#endif /* WITH_WSREP */
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
}
#ifdef WITH_WSREP
if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); }
#endif /* WITH_WSREP */
@ -5608,7 +5606,7 @@ wsrep_innobase_mysql_sort(
tmp_length = charset->coll->strnxfrm(charset, str, str_length,
str_length, tmp_str, tmp_length, 0);
/**/
DBUG_ASSERT(tmp_length == str_length);
DBUG_ASSERT(tmp_length <= str_length);
break;
}
@ -7294,7 +7292,9 @@ ha_innobase::write_row(
|| sql_command == SQLCOM_CREATE_INDEX
#ifdef WITH_WSREP
|| (wsrep_on(user_thd) && wsrep_load_data_splitting &&
sql_command == SQLCOM_LOAD)
sql_command == SQLCOM_LOAD &&
!thd_test_options(
user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
#endif /* WITH_WSREP */
|| sql_command == SQLCOM_DROP_INDEX)
&& num_write_row >= 10000) {
@ -7304,7 +7304,6 @@ ha_innobase::write_row(
wsrep_thd_query(user_thd));
}
#endif /* WITH_WSREP */
/* ALTER TABLE is COMMITted at every 10000 copied rows.
The IX table lock for the original table has to be re-issued.
As this method will be called on a temporary table where the
@ -7343,7 +7342,8 @@ no_commit:
{
case WSREP_TRX_OK:
break;
case WSREP_TRX_ROLLBACK:
case WSREP_TRX_SIZE_EXCEEDED:
case WSREP_TRX_CERT_FAIL:
case WSREP_TRX_ERROR:
DBUG_RETURN(1);
}
@ -7367,7 +7367,8 @@ no_commit:
{
case WSREP_TRX_OK:
break;
case WSREP_TRX_ROLLBACK:
case WSREP_TRX_SIZE_EXCEEDED:
case WSREP_TRX_CERT_FAIL:
case WSREP_TRX_ERROR:
DBUG_RETURN(1);
}
@ -7490,9 +7491,10 @@ no_commit:
#ifdef WITH_WSREP
/* workaround for LP bug #355000, retrying the insert */
case SQLCOM_INSERT:
if (wsrep_on(current_thd) &&
auto_inc_inserted &&
wsrep_drupal_282555_workaround &&
if (wsrep_on(current_thd) &&
auto_inc_inserted &&
wsrep_drupal_282555_workaround &&
wsrep_thd_retry_counter(current_thd) == 0 &&
!thd_test_options(current_thd,
OPTION_NOT_AUTOCOMMIT |
OPTION_BEGIN)) {
@ -9620,6 +9622,13 @@ ha_innobase::wsrep_append_keys(
} else {
ut_a(table->s->keys <= 256);
uint i;
bool hasPK= false;
for (i=0; i<table->s->keys && !hasPK; ++i) {
KEY* key_info = table->key_info + i;
if (key_info->flags & HA_NOSAME) hasPK = true;
}
for (i=0; i<table->s->keys; ++i) {
uint len;
char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
@ -9640,14 +9649,11 @@ ha_innobase::wsrep_append_keys(
table->s->table_name.str,
key_info->name);
}
if (key_info->flags & HA_NOSAME ||
if (!hasPK || key_info->flags & HA_NOSAME ||
((tab &&
dict_table_get_referenced_constraint(tab, idx)) ||
(!tab && referenced_by_foreign_key()))) {
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
len = wsrep_store_key_val_for_row(
table, i, key0, key_info->key_length,
record0, &is_null);
@ -9656,6 +9662,10 @@ ha_innobase::wsrep_append_keys(
thd, trx, table_share, table,
keyval0, len+1, shared);
if (rcode) DBUG_RETURN(rcode);
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
}
else
{
@ -16853,6 +16863,7 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno)
}
/*******************************************************************//**
This function is used to kill one transaction in BF. */
int
wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
const trx_t * const bf_trx,

View File

@ -291,7 +291,7 @@ UNIV_INTERN
int
wsrep_innobase_kill_one_trx(void *thd_ptr,
const trx_t *bf_trx, trx_t *victim_trx, ibool signal);
extern "C" int wsrep_thd_is_brute_force(void *thd_ptr);
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
int wsrep_trx_order_before(void *thd1, void *thd2);
void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length);

View File

@ -894,7 +894,6 @@ lock_trx_has_rec_x_lock(
record */
#define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created
by other transaction */
#define WSREP_BF 8192
#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK
# error
#endif

View File

@ -979,47 +979,6 @@ lock_rec_has_to_wait(
&& !lock_mode_compatible(static_cast<enum lock_mode>(
LOCK_MODE_MASK & type_mode),
lock_get_mode(lock2))) {
#ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */
if (for_locking &&
wsrep_thd_is_brute_force(trx->mysql_thd) &&
wsrep_thd_is_brute_force(lock2->trx->mysql_thd)) {
if (wsrep_debug) {
fprintf(stderr, "\n BF-BF lock conflict \n");
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict\n");
lock_rec_print(stderr, lock2);
abort();
} else {
if (wsrep_debug) {
fprintf(stderr,
"BF conflict, modes: %lu %lu\n",
type_mode,
lock2->type_mode);
#ifdef OUT
fprintf(stderr,
"seqnos %llu %llu\n",
(long long)wsrep_thd_trx_seqno(
trx->mysql_thd),
(long long)wsrep_thd_trx_seqno(
lock2->trx->mysql_thd));
#endif
}
return FALSE;
}
}
#endif /* WITH_WSREP */
/* We have somewhat complex rules when gap type record locks
cause waits */
@ -1069,6 +1028,44 @@ lock_rec_has_to_wait(
return(FALSE);
}
#ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */
if (for_locking &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE) &&
wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) {
if (wsrep_debug) {
fprintf(stderr, "\n BF-BF lock conflict \n");
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict\n");
lock_rec_print(stderr, lock2);
abort();
} else {
/* if lock2->index->n_uniq <=
lock2->index->n_user_defined_cols
operation is on uniq index
*/
if (wsrep_debug) fprintf(stderr,
"BF conflict, modes: %lu %lu, "
"idx: %s-%s n_uniq %u n_user %u\n",
type_mode, lock2->type_mode,
lock2->index->name,
lock2->index->table_name,
lock2->index->n_uniq,
lock2->index->n_user_defined_cols);
return FALSE;
}
}
#endif /* WITH_WSREP */
return(TRUE);
}
@ -1626,17 +1623,16 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */
#ifdef WITH_WSREP
static
void
static void
wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(lock->trx));
my_bool bf_this = wsrep_thd_is_brute_force(trx->mysql_thd);
my_bool bf_other = wsrep_thd_is_brute_force(lock->trx->mysql_thd);
my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE);
if ((bf_this && !bf_other) ||
(bf_this && bf_other && wsrep_trx_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) {
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
if (wsrep_debug)
fprintf(stderr, "WSREP: BF victim waiting\n");
@ -1930,11 +1926,6 @@ lock_rec_create(
lock->trx = trx;
lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(trx->mysql_thd)) {
lock->type_mode |= WSREP_BF;
}
#endif /* WITH_WSREP */
lock->index = index;
lock->un_member.rec_lock.space = space;
@ -1954,12 +1945,12 @@ lock_rec_create(
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
lock_t *hash = (lock_t *)c_lock->hash;
lock_t *prev = NULL;
while (hash &&
wsrep_thd_is_brute_force(((lock_t *)hash)->trx->mysql_thd) &&
wsrep_thd_is_BF(((lock_t *)hash)->trx->mysql_thd, TRUE) &&
wsrep_trx_order_before(
((lock_t *)hash)->trx->mysql_thd,
trx->mysql_thd)) {
@ -2363,11 +2354,6 @@ lock_rec_lock_fast(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
@ -2386,8 +2372,7 @@ lock_rec_lock_fast(
#else
lock = lock_rec_create(
mode, block, heap_no, index, trx, FALSE);
#endif
#endif /* WITH_WSREP */
}
status = LOCK_REC_SUCCESS_CREATED;
} else {
@ -2455,11 +2440,6 @@ lock_rec_lock_slow(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
@ -2569,19 +2549,8 @@ lock_rec_lock(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == 0);
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) {
mode |= WSREP_BF;
}
#endif
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
/* We try a simplified and faster subroutine for the most
@ -4025,17 +3994,19 @@ lock_deadlock_select_victim(
if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) {
/* The joining transaction is 'smaller',
choose it as the victim and roll it back. */
#ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd)) {
return(ctx->start);
}
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(ctx->wait_lock->trx);
else
#endif /* WITH_WSREP */
return(ctx->start);
}
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd))
if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE))
return(ctx->start);
else
else
#endif /* WITH_WSREP */
return(ctx->wait_lock->trx);
}
@ -4167,7 +4138,7 @@ lock_deadlock_search(
ctx->too_deep = TRUE;
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->start->mysql_thd))
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(ctx->wait_lock->trx->id);
else
#endif /* WITH_WSREP */
@ -4190,7 +4161,7 @@ lock_deadlock_search(
ctx->too_deep = TRUE;
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->start->mysql_thd))
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(lock->trx->id);
else
#endif /* WITH_WSREP */
@ -4313,7 +4284,7 @@ lock_deadlock_check_and_resolve(
ut_a(victim_trx_id == trx->id);
#ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(ctx.start->mysql_thd))
if (!wsrep_thd_is_BF(ctx.start->mysql_thd, TRUE))
{
#endif /* WITH_WSREP */
if (!srv_read_only_mode) {
@ -4409,7 +4380,7 @@ lock_table_create(
UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock);
} else {
@ -6489,7 +6460,7 @@ lock_rec_convert_impl_to_expl(
if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))
#ifdef WITH_WSREP
&& !wsrep_thd_is_brute_force(impl_trx->mysql_thd)
&& !wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)
/* BF-BF conflict is possible if advancing into
lock_rec_other_has_conflicting*/
#endif /* WITH_WSREP */

View File

@ -184,6 +184,28 @@ lock_wait_table_reserve_slot(
return(NULL);
}
#ifdef WITH_WSREP
/*********************************************************************//**
check if lock timeout was for priority thread,
as a side effect trigger lock monitor
@return false for regular lock timeout */
static ibool
wsrep_is_BF_lock_timeout(
/*====================*/
trx_t* trx) /* in: trx to check for lock priority */
{
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(srv_monitor_event);
return TRUE;
}
return FALSE;
}
#endif /* WITH_WSREP */
/***************************************************************//**
Puts a user OS thread to wait for a lock to be released. If an error
occurs during the wait trx->error_state associated with thr is
@ -375,9 +397,15 @@ lock_wait_suspend_thread(
if (lock_wait_timeout < 100000000
&& wait_time > (double) lock_wait_timeout) {
#ifdef WITH_WSREP
if (!wsrep_is_BF_lock_timeout(trx)) {
#endif /* WITH_WSREP */
trx->error_state = DB_LOCK_WAIT_TIMEOUT;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
MONITOR_INC(MONITOR_TIMEOUT);
}
@ -461,8 +489,13 @@ lock_wait_check_and_cancel(
if (trx->lock.wait_lock) {
ut_a(trx->lock.que_state == TRX_QUE_LOCK_WAIT);
#ifdef WITH_WSREP
if (!wsrep_is_BF_lock_timeout(trx)) {
#endif /* WITH_WSREP */
lock_cancel_waiting_and_release(trx->lock.wait_lock);
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
}
lock_mutex_exit();

View File

@ -1926,9 +1926,6 @@ row_ins_scan_sec_index_for_duplicate(
mem_heap_t* offsets_heap)
/*!< in/out: memory heap that can be emptied */
{
#ifdef WITH_WSREP
trx_t* trx = thr_get_trx(thr);
#endif
ulint n_unique;
int cmp;
ulint n_fields_cmp;
@ -1997,16 +1994,8 @@ row_ins_scan_sec_index_for_duplicate(
if (flags & BTR_NO_LOCKING_FLAG) {
/* Set no locks when applying log
in online table rebuild. */
#ifdef WITH_WSREP
/* slave applier must not get duplicate error */
} else if (allow_duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
} else if (allow_duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
duplicates ( REPLACE, LOAD DATAFILE REPLACE,
@ -2016,6 +2005,10 @@ row_ins_scan_sec_index_for_duplicate(
lock_type, block, rec, index, offsets, thr);
} else {
#ifdef WITH_WSREP
/* appliers don't need dupkey checks */
if (!wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0))
#endif /* WITH_WSREP */
err = row_ins_set_shared_rec_lock(
lock_type, block, rec, index, offsets, thr);
}
@ -2211,13 +2204,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@ -2262,13 +2249,7 @@ duplicate:
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for

View File

@ -373,6 +373,8 @@ wsrep_row_upd_check_foreign_constraints(
trx = thr_get_trx(thr);
/* TODO: make native slave thread bail out here */
rec = btr_pcur_get_rec(pcur);
ut_ad(rec_offs_validate(rec, index, offsets));

View File

@ -2409,27 +2409,6 @@ suspend_thread:
OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
}
#ifdef WITH_WSREP_TODO
/*********************************************************************//**
check if lock timeout was for priority thread,
as a side effect trigger lock monitor
@return false for regular lock timeout */
static ibool
wsrep_is_BF_lock_timeout(
/*====================*/
srv_slot_t* slot) /* in: lock slot to check for lock priority */
{
if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) &&
wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(lock_sys->timeout_event);
return TRUE;
}
return FALSE;
}
#endif /* WITH_WSREP_TODO */
/*********************************************************************//**
Check if purge should stop.
@return true if it should shutdown. */

View File

@ -178,7 +178,12 @@ trx_sys_flush_max_trx_id(void)
mtr_t mtr;
trx_sysf_t* sys_header;
#ifndef WITH_WSREP
/* wsrep_fake_trx_id violates this assert
* Copied from trx_sys_get_new_trx_id
*/
ut_ad(mutex_own(&trx_sys->mutex));
#endif /* WITH_WSREP */
if (!srv_read_only_mode) {
mtr_start(&mtr);

View File

@ -1437,8 +1437,8 @@ innobase_srv_conc_enter_innodb(
trx_t* trx) /*!< in: transaction handle */
{
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) return;
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return;
#endif /* WITH_WSREP */
if (srv_thread_concurrency) {
if (trx->n_tickets_to_enter_innodb > 0) {
@ -1475,8 +1475,8 @@ innobase_srv_conc_exit_innodb(
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) return;
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return;
#endif /* WITH_WSREP */
/* This is to avoid making an unnecessary function call. */
@ -3967,11 +3967,6 @@ innobase_commit_low(
/*================*/
trx_t* trx) /*!< in: transaction handle */
{
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
}
#ifdef WITH_WSREP
THD* thd = (THD*)trx->mysql_thd;
const char* tmp = 0;
@ -3989,7 +3984,10 @@ innobase_commit_low(
#endif /* WSREP_PROC_INFO */
}
#endif /* WITH_WSREP */
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
}
#ifdef WITH_WSREP
if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); }
#endif /* WITH_WSREP */
@ -6054,7 +6052,7 @@ wsrep_innobase_mysql_sort(
tmp_length = charset->coll->strnxfrm(charset, str, str_length,
str_length, tmp_str, tmp_length, 0);
/**/
DBUG_ASSERT(tmp_length == str_length);
DBUG_ASSERT(tmp_length <= str_length);
break;
}
@ -7755,7 +7753,6 @@ ha_innobase::write_row(
wsrep_thd_query(user_thd));
}
#endif /* WITH_WSREP */
/* ALTER TABLE is COMMITted at every 10000 copied rows.
The IX table lock for the original table has to be re-issued.
As this method will be called on a temporary table where the
@ -7794,7 +7791,8 @@ no_commit:
{
case WSREP_TRX_OK:
break;
case WSREP_TRX_ROLLBACK:
case WSREP_TRX_SIZE_EXCEEDED:
case WSREP_TRX_CERT_FAIL:
case WSREP_TRX_ERROR:
DBUG_RETURN(1);
}
@ -7818,10 +7816,12 @@ no_commit:
{
case WSREP_TRX_OK:
break;
case WSREP_TRX_ROLLBACK:
case WSREP_TRX_SIZE_EXCEEDED:
case WSREP_TRX_CERT_FAIL:
case WSREP_TRX_ERROR:
DBUG_RETURN(1);
}
if (binlog_hton->commit(binlog_hton, user_thd, 1))
DBUG_RETURN(1);
wsrep_post_commit(user_thd, TRUE);
@ -7949,9 +7949,10 @@ no_commit:
#ifdef WITH_WSREP
/* workaround for LP bug #355000, retrying the insert */
case SQLCOM_INSERT:
if (wsrep_on(current_thd) &&
auto_inc_inserted &&
wsrep_drupal_282555_workaround &&
if (wsrep_on(current_thd) &&
auto_inc_inserted &&
wsrep_drupal_282555_workaround &&
wsrep_thd_retry_counter(current_thd) == 0 &&
!thd_test_options(current_thd,
OPTION_NOT_AUTOCOMMIT |
OPTION_BEGIN)) {
@ -7963,8 +7964,7 @@ no_commit:
error= DB_SUCCESS;
wsrep_thd_set_conflict_state(
current_thd, MUST_ABORT);
innobase_srv_conc_exit_innodb(
prebuilt->trx);
innobase_srv_conc_exit_innodb(prebuilt->trx);
/* jump straight to func exit over
* later wsrep hooks */
goto func_exit;
@ -10133,6 +10133,13 @@ ha_innobase::wsrep_append_keys(
} else {
ut_a(table->s->keys <= 256);
uint i;
bool hasPK= false;
for (i=0; i<table->s->keys && !hasPK; ++i) {
KEY* key_info = table->key_info + i;
if (key_info->flags & HA_NOSAME) hasPK = true;
}
for (i=0; i<table->s->keys; ++i) {
uint len;
char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
@ -10153,14 +10160,11 @@ ha_innobase::wsrep_append_keys(
table->s->table_name.str,
key_info->name);
}
if (key_info->flags & HA_NOSAME ||
if (!hasPK || key_info->flags & HA_NOSAME ||
((tab &&
dict_table_get_referenced_constraint(tab, idx)) ||
(!tab && referenced_by_foreign_key()))) {
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
len = wsrep_store_key_val_for_row(
table, i, key0, key_info->key_length,
record0, &is_null);
@ -10169,6 +10173,10 @@ ha_innobase::wsrep_append_keys(
thd, trx, table_share, table,
keyval0, len+1, shared);
if (rcode) DBUG_RETURN(rcode);
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
}
else
{
@ -17759,6 +17767,7 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno)
}
/*******************************************************************//**
This function is used to kill one transaction in BF. */
int
wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
const trx_t * const bf_trx,

View File

@ -290,7 +290,7 @@ UNIV_INTERN
int
wsrep_innobase_kill_one_trx(void *thd_ptr,
const trx_t *bf_trx, trx_t *victim_trx, ibool signal);
extern "C" int wsrep_thd_is_brute_force(void *thd_ptr);
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
int wsrep_trx_order_before(void *thd1, void *thd2);
void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length);

View File

@ -906,7 +906,6 @@ lock_trx_has_rec_x_lock(
record */
#define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created
by other transaction */
#define WSREP_BF 8192
#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK
# error
#endif

View File

@ -55,7 +55,6 @@ extern my_bool wsrep_debug;
extern my_bool wsrep_log_conflicts;
#include "ha_prototypes.h"
#endif
/* Restricts the length of search we will do in the waits-for
graph of transactions */
#define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
@ -981,47 +980,6 @@ lock_rec_has_to_wait(
&& !lock_mode_compatible(static_cast<enum lock_mode>(
LOCK_MODE_MASK & type_mode),
lock_get_mode(lock2))) {
#ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */
if (for_locking &&
wsrep_thd_is_brute_force(trx->mysql_thd) &&
wsrep_thd_is_brute_force(lock2->trx->mysql_thd)) {
if (wsrep_debug) {
fprintf(stderr, "\n BF-BF lock conflict \n");
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict\n");
lock_rec_print(stderr, lock2);
abort();
} else {
if (wsrep_debug) {
fprintf(stderr,
"BF conflict, modes: %lu %lu\n",
type_mode,
lock2->type_mode);
#ifdef OUT
fprintf(stderr,
"seqnos %llu %llu\n",
(long long)wsrep_thd_trx_seqno(
trx->mysql_thd),
(long long)wsrep_thd_trx_seqno(
lock2->trx->mysql_thd));
#endif
}
return FALSE;
}
}
#endif /* WITH_WSREP */
/* We have somewhat complex rules when gap type record locks
cause waits */
@ -1071,6 +1029,44 @@ lock_rec_has_to_wait(
return(FALSE);
}
#ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */
if (for_locking &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE) &&
wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) {
if (wsrep_debug) {
fprintf(stderr, "\n BF-BF lock conflict \n");
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict\n");
lock_rec_print(stderr, lock2);
abort();
} else {
/* if lock2->index->n_uniq <=
lock2->index->n_user_defined_cols
operation is on uniq index
*/
if (wsrep_debug) fprintf(stderr,
"BF conflict, modes: %lu %lu, "
"idx: %s-%s n_uniq %u n_user %u\n",
type_mode, lock2->type_mode,
lock2->index->name,
lock2->index->table_name,
lock2->index->n_uniq,
lock2->index->n_user_defined_cols);
return FALSE;
}
}
#endif /* WITH_WSREP */
return(TRUE);
}
@ -1578,8 +1574,7 @@ lock_rec_has_expl(
static
void
lock_rec_discard(lock_t* in_lock);
#endif /* WITH_WSREP */
#endif
#ifdef UNIV_DEBUG
/*********************************************************************//**
Checks if some other transaction has a lock request in the queue.
@ -1629,17 +1624,16 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */
#ifdef WITH_WSREP
static
void
static void
wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(lock->trx));
my_bool bf_this = wsrep_thd_is_brute_force(trx->mysql_thd);
my_bool bf_other = wsrep_thd_is_brute_force(lock->trx->mysql_thd);
my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE);
if ((bf_this && !bf_other) ||
(bf_this && bf_other && wsrep_trx_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) {
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
if (wsrep_debug)
fprintf(stderr, "WSREP: BF victim waiting\n");
@ -1933,11 +1927,6 @@ lock_rec_create(
lock->trx = trx;
lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(trx->mysql_thd)) {
lock->type_mode |= WSREP_BF;
}
#endif /* WITH_WSREP */
lock->index = index;
lock->un_member.rec_lock.space = space;
@ -1957,12 +1946,12 @@ lock_rec_create(
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
lock_t *hash = (lock_t *)c_lock->hash;
lock_t *prev = NULL;
while (hash &&
wsrep_thd_is_brute_force(((lock_t *)hash)->trx->mysql_thd) &&
wsrep_thd_is_BF(((lock_t *)hash)->trx->mysql_thd, TRUE) &&
wsrep_trx_order_before(
((lock_t *)hash)->trx->mysql_thd,
trx->mysql_thd)) {
@ -2376,11 +2365,6 @@ lock_rec_lock_fast(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
@ -2468,11 +2452,6 @@ lock_rec_lock_slow(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
@ -2582,19 +2561,8 @@ lock_rec_lock(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == 0);
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) {
mode |= WSREP_BF;
}
#endif
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
/* We try a simplified and faster subroutine for the most
@ -4040,17 +4008,19 @@ lock_deadlock_select_victim(
if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) {
/* The joining transaction is 'smaller',
choose it as the victim and roll it back. */
#ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd))
return(ctx->start);
else
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(ctx->wait_lock->trx);
else
#endif /* WITH_WSREP */
return(ctx->start);
}
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd))
if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE))
return(ctx->start);
else
else
#endif /* WITH_WSREP */
return(ctx->wait_lock->trx);
}
@ -4182,7 +4152,7 @@ lock_deadlock_search(
ctx->too_deep = TRUE;
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->start->mysql_thd))
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(ctx->wait_lock->trx->id);
else
#endif /* WITH_WSREP */
@ -4205,7 +4175,7 @@ lock_deadlock_search(
ctx->too_deep = TRUE;
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->start->mysql_thd))
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(lock->trx->id);
else
#endif /* WITH_WSREP */
@ -4328,7 +4298,7 @@ lock_deadlock_check_and_resolve(
ut_a(victim_trx_id == trx->id);
#ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(ctx.start->mysql_thd))
if (!wsrep_thd_is_BF(ctx.start->mysql_thd, TRUE))
{
#endif /* WITH_WSREP */
if (!srv_read_only_mode) {
@ -4426,7 +4396,7 @@ lock_table_create(
UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock);
} else {
@ -6531,7 +6501,7 @@ lock_rec_convert_impl_to_expl(
if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))
#ifdef WITH_WSREP
&& !wsrep_thd_is_brute_force(impl_trx->mysql_thd)
&& !wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)
/* BF-BF conflict is possible if advancing into
lock_rec_other_has_conflicting*/
#endif /* WITH_WSREP */

View File

@ -184,6 +184,28 @@ lock_wait_table_reserve_slot(
return(NULL);
}
#ifdef WITH_WSREP
/*********************************************************************//**
check if lock timeout was for priority thread,
as a side effect trigger lock monitor
@return false for regular lock timeout */
static ibool
wsrep_is_BF_lock_timeout(
/*====================*/
trx_t* trx) /* in: trx to check for lock priority */
{
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(srv_monitor_event);
return TRUE;
}
return FALSE;
}
#endif /* WITH_WSREP */
/***************************************************************//**
Puts a user OS thread to wait for a lock to be released. If an error
occurs during the wait trx->error_state associated with thr is
@ -375,9 +397,15 @@ lock_wait_suspend_thread(
if (lock_wait_timeout < 100000000
&& wait_time > (double) lock_wait_timeout) {
#ifdef WITH_WSREP
if (!wsrep_is_BF_lock_timeout(trx)) {
#endif /* WITH_WSREP */
trx->error_state = DB_LOCK_WAIT_TIMEOUT;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
MONITOR_INC(MONITOR_TIMEOUT);
}
@ -461,8 +489,13 @@ lock_wait_check_and_cancel(
if (trx->lock.wait_lock) {
ut_a(trx->lock.que_state == TRX_QUE_LOCK_WAIT);
#ifdef WITH_WSREP
if (!wsrep_is_BF_lock_timeout(trx)) {
#endif /* WITH_WSREP */
lock_cancel_waiting_and_release(trx->lock.wait_lock);
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
}
lock_mutex_exit();

View File

@ -1938,9 +1938,6 @@ row_ins_scan_sec_index_for_duplicate(
mem_heap_t* offsets_heap)
/*!< in/out: memory heap that can be emptied */
{
#ifdef WITH_WSREP
trx_t* trx = thr_get_trx(thr);
#endif
ulint n_unique;
int cmp;
ulint n_fields_cmp;
@ -2009,16 +2006,7 @@ row_ins_scan_sec_index_for_duplicate(
if (flags & BTR_NO_LOCKING_FLAG) {
/* Set no locks when applying log
in online table rebuild. */
#ifdef WITH_WSREP
/* slave applier must not get duplicate error */
} else if (allow_duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
} else if (allow_duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@ -2029,6 +2017,10 @@ row_ins_scan_sec_index_for_duplicate(
lock_type, block, rec, index, offsets, thr);
} else {
#ifdef WITH_WSREP
/* appliers don't need dupkey checks */
if (!wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0))
#endif /* WITH_WSREP */
err = row_ins_set_shared_rec_lock(
lock_type, block, rec, index, offsets, thr);
}
@ -2224,13 +2216,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@ -2275,13 +2261,7 @@ duplicate:
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for

View File

@ -375,6 +375,8 @@ wsrep_row_upd_check_foreign_constraints(
trx = thr_get_trx(thr);
/* TODO: make native slave thread bail out here */
rec = btr_pcur_get_rec(pcur);
ut_ad(rec_offs_validate(rec, index, offsets));

View File

@ -2998,27 +2998,6 @@ suspend_thread:
OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
}
#ifdef WITH_WSREP_TODO
/*********************************************************************//**
check if lock timeout was for priority thread,
as a side effect trigger lock monitor
@return false for regular lock timeout */
static ibool
wsrep_is_BF_lock_timeout(
/*====================*/
srv_slot_t* slot) /* in: lock slot to check for lock priority */
{
if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) &&
wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(lock_sys->timeout_event);
return TRUE;
}
return FALSE;
}
#endif /* WITH_WSREP_TODO */
/*********************************************************************//**
Check if purge should stop.
@return true if it should shutdown. */

View File

@ -178,7 +178,12 @@ trx_sys_flush_max_trx_id(void)
mtr_t mtr;
trx_sysf_t* sys_header;
#ifndef WITH_WSREP
/* wsrep_fake_trx_id violates this assert
* Copied from trx_sys_get_new_trx_id
*/
ut_ad(mutex_own(&trx_sys->mutex));
#endif /* WITH_WSREP */
if (!srv_read_only_mode) {
mtr_start(&mtr);

View File

@ -1174,6 +1174,7 @@ echo "=====" >> $STATUS_HISTORY
%attr(755, root, root) %{_bindir}/wsrep_sst_rsync
%attr(755, root, root) %{_bindir}/wsrep_sst_rsync_wan
%attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup
%attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup-v2
%endif
%attr(755, root, root) %{_sbindir}/mysqld

View File

@ -137,7 +137,11 @@ typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *);
typedef uint64_t wsrep_trx_id_t; //!< application transaction ID
typedef uint64_t wsrep_conn_id_t; //!< application connection ID
typedef int64_t wsrep_seqno_t; //!< sequence number of a writeset, etc.
#ifdef __cplusplus
typedef bool wsrep_bool_t;
#else
typedef _Bool wsrep_bool_t; //!< should be the same as standard (C99) bool
#endif /* __cplusplus */
/*! undefined seqno */
#define WSREP_SEQNO_UNDEFINED (-1)

View File

@ -20,11 +20,13 @@
#include <errno.h>
#include <stdbool.h>
#include <string.h>
/*! Dummy backend context. */
typedef struct wsrep_dummy
{
wsrep_log_cb_t log_fn;
char* options;
} wsrep_dummy_t;
/* Get pointer to wsrep_dummy context from wsrep_t pointer */
@ -42,6 +44,10 @@ typedef struct wsrep_dummy
static void dummy_free(wsrep_t *w)
{
WSREP_DBUG_ENTER(w);
if (WSREP_DUMMY(w)->options)
{
free(WSREP_DUMMY(w)->options);
}
free(w->ctx);
w->ctx = NULL;
}
@ -49,8 +55,15 @@ static void dummy_free(wsrep_t *w)
static wsrep_status_t dummy_init (wsrep_t* w,
const struct wsrep_init_args* args)
{
WSREP_DUMMY(w)->log_fn = args->logger_cb;
WSREP_DBUG_ENTER(w);
WSREP_DUMMY(w)->log_fn = args->logger_cb;
if (args->options)
{
char* options = malloc(strlen(args->options) + 1);
if (options == NULL) return WSREP_WARNING;
strcpy(options, args->options);
WSREP_DUMMY(w)->options = options;
}
return WSREP_OK;
}
@ -61,16 +74,41 @@ static uint64_t dummy_capabilities (wsrep_t* w __attribute__((unused)))
static wsrep_status_t dummy_options_set(
wsrep_t* w,
const char* conf __attribute__((unused)))
const char* conf)
{
char* options = NULL;
WSREP_DBUG_ENTER(w);
// concatenate config string with ';'
options = WSREP_DUMMY(w)->options;
if (options == NULL)
{
options = malloc(strlen(conf) + 1);
if (options == NULL)
{
return WSREP_WARNING;
}
strcpy(options, conf);
} else {
int opt_len = strlen(options);
char* p = realloc(options,
opt_len + 1 + // ';'
strlen(conf) + 1); // \0
if (p == NULL)
{
return WSREP_WARNING;
}
p[opt_len] = ';';
strcpy(p + opt_len + 1, conf);
options = p;
}
WSREP_DUMMY(w)->options = options;
return WSREP_OK;
}
static char* dummy_options_get (wsrep_t* w)
{
WSREP_DBUG_ENTER(w);
return NULL;
return WSREP_DUMMY(w)->options;
}
static wsrep_status_t dummy_connect(
@ -385,6 +423,7 @@ int wsrep_dummy_loader(wsrep_t* w)
// initialize private context
WSREP_DUMMY(w)->log_fn = NULL;
WSREP_DUMMY(w)->options = NULL;
return 0;
}