wsrep_sst_xtrabackup.sh 21 KB
Newer Older
1
#!/bin/bash -ue
2
# Copyright (C) 2013 Percona Inc
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#
# 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.

18 19 20 21 22
# 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!



23 24 25

. $(dirname $0)/wsrep_sst_common

26 27 28 29
ealgo=""
ekey=""
ekeyfile=""
encrypt=0
30 31 32
nproc=1
ecode=0
XTRABACKUP_PID=""
33 34 35 36 37 38 39 40 41 42 43 44
SST_PORT=""
REMOTEIP=""
tcert=""
tpem=""
sockopt=""
progress=""
ttime=0
totime=0
lsn=""
incremental=0
ecmd=""
rlimit=""
45 46 47

sfmt="tar"
strmcmd=""
48 49 50 51 52 53 54 55 56 57 58 59 60
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"
61
declare -a RC
62

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
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
}

96 97
get_keys()
{
98 99 100 101 102
    if [[ $encrypt -eq 2 ]];then 
        return 
    fi

    if [[ $encrypt -eq 0 ]];then 
103
        if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then
104 105
            wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html "
        fi
106 107
        return
    fi
108

109
    if [[ $sfmt == 'tar' ]];then
110 111
        wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format"
        encrypt=0
112 113 114
        return
    fi

115
    wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4"
116 117 118 119 120 121 122 123 124 125

    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
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

    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
198
    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-)
199 200 201 202 203 204 205 206 207
    if [[ -z $reval ]];then 
        [[ -n $3 ]] && reval=$3
    fi
    echo $reval
}

get_footprint()
{
    pushd $WSREP_SST_OPT_DATA 1>/dev/null
208
    payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c | awk 'END { print $1 }')
209
    if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then 
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
        # 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
236 237
}

238 239
read_cnf()
{
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
    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()
{
266 267 268
    if [[ $sfmt == 'xbstream' ]];then 
        wsrep_log_info "Streaming with xbstream"
        if [[ "$WSREP_SST_OPT_ROLE"  == "joiner" ]];then
269
            strmcmd="xbstream -x"
270
        else
271
            strmcmd="xbstream -c \${INFO_FILE} \${IST_FILE}"
272 273 274 275 276
        fi
    else
        sfmt="tar"
        wsrep_log_info "Streaming with tar"
        if [[ "$WSREP_SST_OPT_ROLE"  == "joiner" ]];then
277 278 279
            strmcmd="tar xfi - --recursive-unlink -h"
        else
            strmcmd="tar cf - \${INFO_FILE} \${IST_FILE}"
280 281 282 283 284 285 286 287 288 289 290 291 292
        fi

    fi
}

get_proc()
{
    set +e
    nproc=$(grep -c processor /proc/cpuinfo)
    [[ -z $nproc || $nproc -eq 0 ]] && nproc=1
    set -e
}

293 294 295 296 297 298
sig_joiner_cleanup()
{
    wsrep_log_error "Removing $MAGIC_FILE file due to signal"
    rm -f "$MAGIC_FILE"
}

299 300
cleanup_joiner()
{
301 302 303 304 305
    # 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
306
    if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
307
        wsrep_log_info "Removing the sst_in_progress file"
308 309
        wsrep_cleanup_progress_file
    fi
310 311 312 313
    if [[ -n $progress && -p $progress ]];then 
        wsrep_log_info "Cleaning up fifo file $progress"
        rm $progress
    fi
314 315 316 317
}

check_pid()
{
318 319
    local pid_file="$1"
    [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1
320 321
}

322 323 324 325 326 327 328 329
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

330 331 332 333 334 335 336 337 338
    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
339
    rm -f ${DATA}/${IST_FILE}
340 341 342 343 344

    if [[ -n $progress && -p $progress ]];then 
        wsrep_log_info "Cleaning up fifo file $progress"
        rm $progress
    fi
345 346
}

347 348 349 350 351
kill_xtrabackup()
{
    local PID=$(cat $XTRABACKUP_PID)
    [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
    rm -f "$XTRABACKUP_PID"
352 353 354 355 356 357 358 359 360 361 362
}

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
363 364 365 366
}

# waits ~10 seconds for nc to open the port and then reports ready
# (regardless of timeout)
367
wait_for_listen()
368 369 370 371
{
    local PORT=$1
    local ADDR=$2
    local MODULE=$3
372
    for i in {1..50}
373
    do
374
        ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break
375 376
        sleep 0.2
    done
377 378 379
    if [[ $incremental -eq 1 ]];then 
        echo "ready ${ADDR}/${MODULE}/$lsn"
    else 
380
    echo "ready ${ADDR}/${MODULE}"
381
    fi
382 383
}

384 385 386 387
check_extra()
{
    local use_socket=1
    if [[ $uextra -eq 1 ]];then 
388 389
        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)
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
            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
}
408

409 410 411 412
if [[ ! -x `which innobackupex` ]];then 
    wsrep_log_error "innobackupex not in path: $PATH"
    exit 2
fi
413 414 415

rm -f "${MAGIC_FILE}"

416 417 418 419 420
if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then 
    wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}"
    exit 22
fi

421
read_cnf
422 423 424 425 426 427 428
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"
429

430 431
if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
then
432
    trap cleanup_donor EXIT
433 434 435

    if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
    then
436
        TMPDIR="${TMPDIR:-/tmp}"
437 438

        if [ "${AUTH[0]}" != "(null)" ]; then
439 440
           INNOEXTRA+=" --user=${AUTH[0]}"
       fi
441 442

        if [ ${#AUTH[*]} -eq 2 ]; then
443 444
           INNOEXTRA+=" --password=${AUTH[1]}"
        elif [ "${AUTH[0]}" != "(null)" ]; then
445
           # Empty password, used for testing, debugging etc.
446 447
           INNOEXTRA+=" --password="
        fi
448

449
        get_keys
450 451
        if [[ $encrypt -eq 1 ]];then
            if [[ -n $ekey ]];then
452
                INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey "
453
            else 
454
                INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile "
455 456 457
            fi
        fi

458 459 460
        if [[ -n $lsn ]];then 
                INNOEXTRA+=" --incremental --incremental-lsn=$lsn "
        fi
461

462 463 464
        check_extra

        wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT}"
465

466 467 468 469 470 471 472 473 474 475
        if [[ -n $progress ]];then 
            get_footprint
            tcmd="$pcmd | $tcmd"
        elif [[ -n $rlimit ]];then 
            adjust_progress
            tcmd="$pcmd | $tcmd"
        fi

        set +e
        timeit "Donor-Transfer" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
476 477 478 479 480 481
        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
482 483
        elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then 
          wsrep_log_error "$tcmd finished with error: ${RC[1]}"
484 485 486
          exit 22
        fi

487 488 489
        # innobackupex implicitly writes PID to fixed location in ${TMPDIR}
        XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid"

490

491 492
    else # BYPASS FOR IST

493
        wsrep_log_info "Bypassing the SST for IST"
494 495 496 497
        STATE="${WSREP_SST_OPT_GTID}"
        echo "continue" # now server can resume updating data
        echo "${STATE}" > "${MAGIC_FILE}"
        echo "1" > "${DATA}/${IST_FILE}"
498
        get_keys
499 500
        pushd ${DATA} 1>/dev/null
        set +e
501
        if [[ $encrypt -eq 1 ]];then
502
            tcmd=" $ecmd | $tcmd"
503
        fi
504
        timeit "Donor-IST-Unencrypted-transfer" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
505 506 507 508 509 510 511 512 513 514
        set -e
        popd 1>/dev/null

        for ecode in "${RC[@]}";do 
            if [[ $ecode -ne 0 ]];then 
                wsrep_log_error "Error while streaming data to joiner node: " \
                                "exit codes: ${RC[@]}"
                exit 1
            fi
        done
515 516 517
    fi

    echo "done ${WSREP_SST_OPT_GTID}"
518
    wsrep_log_info "Total time on donor: $totime seconds"
519 520 521

elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ]
then
522
    [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
523 524
    touch $SST_PROGRESS_FILE

525 526 527 528 529 530 531 532 533 534 535
    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

536
    sencrypted=1
537
    nthreads=1
538

539 540
    MODULE="xtrabackup_sst"

541 542
    # May need xtrabackup_checkpoints later on
    rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info  ${DATA}/xtrabackup_logfile
543 544

    ADDR=${WSREP_SST_OPT_ADDR}
545
    if [ -z "${SST_PORT}" ]
546
    then
547 548
        SST_PORT=4444
        ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}"
549 550
    fi

551
    wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} &
552

553
    trap sig_joiner_cleanup HUP PIPE INT TERM
554 555
    trap cleanup_joiner EXIT

556 557 558 559 560 561 562 563 564 565 566
    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

567
    get_keys
568
    set +e
569
    if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
570
        strmcmd=" $ecmd | $strmcmd"
571
    fi
572 573 574 575 576

    pushd ${DATA} 1>/dev/null
    timeit "Joiner-Recv-Unencrypted" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
    popd 1>/dev/null 

577 578
    set -e

579 580 581 582
    if [[ $sfmt == 'xbstream' ]];then 
        # Special handling till lp:1193240 is fixed"
        if [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then 
            wsrep_log_error "Xbstream failed"
583
            wsrep_log_error "Data directory ${DATA} may not be empty: lp:1193240" \
584 585 586 587 588
                            "Manual intervention required in that case"
            exit 32
        fi
    fi

589
    wait %% # join for wait_for_listen thread
590

591 592
    for ecode in "${RC[@]}";do 
        if [[ $ecode -ne 0 ]];then 
593
            wsrep_log_error "Error while getting data from donor node: " \
594 595 596 597
                            "exit codes: ${RC[@]}"
            exit 32
        fi
    done
598 599 600 601 602

    if [ ! -r "${MAGIC_FILE}" ]
    then
        # this message should cause joiner to abort
        wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'"
603 604
        wsrep_log_info "Contents of datadir" 
        wsrep_log_info "$(ls -l ${DATA}/**/*)"
605 606 607
        exit 32
    fi

608
    if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null
609
    then
610
        wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." 
611 612 613
        exit 32
    fi

614
    if [ ! -r "${DATA}/${IST_FILE}" ]
615
    then
616
        wsrep_log_info "Proceeding with SST"
617
        wsrep_log_info "Removing existing ib_logfile files"
618 619 620 621
        if [[ $incremental -ne 1 ]];then 
            rm -f ${DATA}/ib_logfile*
        else
            rm -f ${BDATA}/ib_logfile*
622 623
        fi

624 625
        get_proc

626 627 628
        # Rebuild indexes for compact backups
        if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then 
            wsrep_log_info "Index compaction detected"
629
            rebuild=1
630 631
        fi

632 633 634 635 636 637 638
        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
639 640 641 642

            wsrep_log_info "Compressed qpress files found"

            if [[ ! -x `which qpress` ]];then 
643
                wsrep_log_error "qpress not found in path: $PATH"
644 645 646
                exit 22
            fi

647 648 649 650 651 652 653 654 655 656 657 658 659 660
            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
661 662 663 664 665

            wsrep_log_info "Removing existing ibdata1 file"
            rm -f ${DATA}/ibdata1

            # Decompress the qpress files 
666
            wsrep_log_info "Decompression with $nproc threads"
667
            timeit "Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd"
668 669 670 671 672 673 674 675 676 677 678 679 680 681
            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

682 683 684 685 686 687
        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

688
        wsrep_log_info "Preparing the backup at ${DATA}"
689 690 691 692 693 694 695
        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
696

697 698
        if [ $? -ne 0 ];
        then
699
            wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log" 
700 701
            exit 22
        fi
702
    else 
703
        wsrep_log_info "${IST_FILE} received from donor: Running IST"
704 705
    fi

706 707 708 709
    if [[ ! -r ${MAGIC_FILE} ]];then
        wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable"
        exit 2
    fi
710

711 712
    cat "${MAGIC_FILE}" # output UUID:seqno
    wsrep_log_info "Total time on joiner: $totime seconds"
713 714 715
fi

exit 0