#!/bin/env bash
##Description: primary stop repl

script_base_name="tidb_fb_primary_stoprepl"


function f_syntax
{
    [ ! -z "$1" ] && echo ">>[$(date "+%Y%m%d.%H%M%S")] $1"
    echo " "
    echo "bash ${ShellName}  [-primaryhostname <hostname>]"
    echo "-standbyhostname <hostname_standby> -backupdb <db_list>"
    echo " "
    echo " #Description:"
    echo " -primaryhostname ,the primary cluster manager host"
    echo " -standbyhostname ,the standby cluster manager host"
    echo " -backupdb ,the databases need to backup, eg: db1,db2,test"
    echo " "
    echo " #sample:"
    echo " #sh ${ShellName} -primaryhostname node1 -standbyhostname sa-172-16-4-81" 
    echo " "
    exit 22
}

function f_PrintLog
{
    _LogFlag=$(echo "$1"|tr "a-z" "A-Z")
    _LogMessage=$2
    [ $(echo "$1"|wc -L) -eq 4 ] && _LogFlag=$(echo "${_LogFlag}_")
    # echo "$(date "+%Y%m%d.%H%M%S"):[${_LogFlag}]:${UserName}@${HostName}:${2}";
    declare LogFile="${LogFile:-"/tmp/${ShellName}.log"}"
    touch "${LogFile}" 2>/dev/null
    if [ -w "${LogFile}" ]
    then
        echo "$(date "+%Y%m%d.%H%M%S"):[${_LogFlag}]:${UserName}@${HostName}:${2}"|tee -a "${LogFile}";
    else
        echo "$(date "+%Y%m%d.%H%M%S"):[${_LogFlag}]:${UserName}@${HostName}:${2}";
    fi

}

###############################################################################
function f_checktidb
{

    f_PrintLog "Info" "Start to run f_checktidb."

    #tidb status
    f_PrintLog "Info" "the Up node list:" 
    echo "${tidbclsinfo}"|awk '{
        if(NF>=8 && $2~"[pd|ti|pr|pu|dr|pr]" && $6~"Up"){printf "%20s %15s %10s\n",$1,$2,$6}
        }'
    
    f_PrintLog "Warn" "the Down node list:" 
    echo "${tidbclsinfo}"|awk '{
        if(NF>=8 && $2~"[pd|ti|pr|pu|dr|pr]" && $6!~"Up"){printf "%20s %15s %10s\n",$1,$2,$6}
        }'

    # drainer_down=$(echo "${tidbclsinfo}" | awk -F: '{
    #     if($1~"binlog_status" && $2!~"On"){gsub("[, ]","",$2);gsub("\"","",$2);printf "%s",$2;exit}
    # }')
    drainer_status=$(tiup cluster display ${clsName}  2>/dev/null |awk -v dip="${tidbDrainerId}" '{
        if($1==dip && $2=="drainer"){printf "%s",$6;exit}
        }')
    
    if [ -n "$(echo "${drainer_status:-Up}" | grep -v "Up")" ]
    then
        f_PrintLog "Error" "drainer status check failed. drainer status is ${tidbDrainerId}:${drainer_status}"
        exit 1
        # [ "${HostRole}" = "PRIMARY" ] && exit 1
    else
        f_PrintLog "Info" "drainer status is ok."
    fi
}

function f_checktidbbinlog
{
    binlog_url=$1

    f_PrintLog "Info" "Start to run f_checktidbbinlog"
    # binlogstatus=$(curl "http://${binlog_url}/info/all")
    # f_formatjson ${binlogstatus}
    binlog_down=$(curl -s "http://${binlog_url}/info/all" | awk -F: '{
        if($1~"binlog_status" && $2!~"On"){gsub("[, ]","",$2);gsub("\"","",$2);printf "%s",$2;exit}
    }')

    binlog_up=$(curl -s "http://${binlog_url}/info/all" | awk -F: '{
        if($1~"binlog_status" && $2~"On"){gsub("[, ]","",$2);gsub("\"","",$2);printf "%s",$2;exit}
    }')
    
    curl -s "http://${binlog_url}/info/all" | awk -F: '
    /^[ "]*ip.*/{gsub("[, ]","",$2);gsub("\"","",$2);ip=$2}
    /^[ "]*listening_port.*/{gsub("[, ]","",$2);gsub("\"","",$2);port=$2}
    /^[ "]*binlog_status.*/{gsub("[, ]","",$2);gsub("\"","",$2);binlog=$2}
    /^[ "]*server_id.*/{TiDB[$2]=tidb;IP[$2]=ip;Port[$2]=port;Binlog[$2]=binlog;}
    END{for(a in TiDB){printf "binlog_status: %s:%s %s\n",IP[a],Port[a],Binlog[a]}}
    '

    if [ "${binlog_down:-On}" = "On" -a "${binlog_up:-Off}" = "On" ]
    then
        f_PrintLog "Info" "binlog_status is ok."
    else
        f_PrintLog "Error" "binlog_status check failed. binlog_status is ${binlog_up}:${binlog_down}"
        exit 1
    fi
}


function f_stopnode
{
    f_PrintLog "Info" "Start to run f_stopnode. $1"
    _nodeid=$1
    local _node_status1=$(tiup cluster display ${clsName}  2>/dev/null |awk -v dip="${_nodeid}" '{
        if($1==dip){printf "%s",$6;exit}
        }')

    f_PrintLog "Info" "tiup cluster stop ${clsName} -N${_nodeid} --yes"
    tiup cluster stop ${clsName} -N${_nodeid} --yes
    local _rt_code=$?

    local _node_status2=$(tiup cluster display ${clsName}  2>/dev/null |awk -v dip="${_nodeid}" '{
        if($1==dip){printf "%s",$6;exit}
        }')

    if [ ${_rt_code} -eq 0 -a "${_node_status2}" == "Down" ]
    then
        f_PrintLog "Info" "Node ${_nodeid} stop successfully, status ${_node_status1}->${_node_status2}."
    else
        f_PrintLog "Error" "Node ${_nodeid} stop failed, return code:${_rt_code}, status ${_node_status1}->${_node_status2}."
        exit 1
    fi
}

function f_backfile
{
    _filename=$1
    _filepath="${_filename%/*}/baktmp"
    [ ! -d ${_filepath} ] && mkdir -p "${_filepath}"
    if [ -f "${_filename}" ]
    then
        f_PrintLog "Warn" "file ${_filename} already exists, rename it now!!"
        ls -l ${_filename}
        sleep 1
        mv "${_filename}" "${_filepath}/${_filename##*/}.bak_$(date +%Y%m%d.%H%M%S)"
    fi
}

function f_generate_fb_config
{
    f_PrintLog "Info" "Start to run Script f_generate_fb_config"
    #init cluster parameter

    tidbfbconfig="${TidbHome}/scripts/flashback/cluster_flashback_config.cnf"
    if [ -f "${tidbfbconfig}" ]
    then
        f_backfile "${tidbfbconfig}" 
    fi

    #备集群drainer配置
    scaleDrYaml="${TidbHome}/switchover/${clsName}_scaleout_slave_drainer.yaml"
    if [ "${HostRole}" = "STANDBY" -a -n "${t2tDrId}" ]
    then
        tidbIp_s=${t2tDrId%:*}
        f_PrintLog "Info" "Standby to Primary remote ip and dr:${tidbIp_s} ${t2tDrId}"
    elif [ "${HostRole}" = "STANDBY" -a -f "${scaleDrYaml}" ]
    then
        tidbIp_s=$(awk -F: '{if($1~" host"){gsub(" ","",$2);print $2;exit}}' ${scaleDrYaml} 2>/dev/null)
        f_PrintLog "Info" "Standby to Primary remote ip and yaml:${tidbIp_s} ${scaleDrYaml}"
    fi

    echo "PRIMARYRUNTIME=$(date +%Y%m%d.%H%M%S)"          >> "${tidbfbconfig}"
    echo "PRIMARYHOSTNAME=${HostName}"          >> "${tidbfbconfig}"
    echo "PRIMARYCLUSTERNAME=${clsName}"        >> "${tidbfbconfig}"
    echo "PRIMARYIP=${tidbIp}"                  >> "${tidbfbconfig}"
    echo "PRIMARYPORT=${tidbPort:-4000}"        >> "${tidbfbconfig}"
    echo "STANDBYIP=${tidbIp_s}"                >> "${tidbfbconfig}"

    echo "************************"
    cat "${tidbfbconfig}" 
    echo "************************"
    f_PrintLog "Info" "Config file generate on ${tidbfbconfig}, pls check the context"
    sleep 10

}

###############################################################################
##Init##
export LANG=en_US
TidbHome=$(awk -F: -v un="tidb" '{if($1==un){print $6;exit}}' /etc/passwd 2>/dev/null)
NumProc=$(awk '/^processor[ |\t]*:/{c++}END{print c}' /proc/cpuinfo 2>/dev/null)
ShellName="$(echo $0|awk -F / '{print $NF}')";ShellOption="$@";
WorkDir="$(echo $0|sed s/${ShellName}//g)";[ -z "${WorkDir}" ] && WorkDir=${PWD};cd ${WorkDir};WorkDir=${PWD}
LogDir="${TidbHome}/scripts/flashback/logs";mkdir -p ${LogDir};
RunTs=$(date "+%Y%m%d.%H%M%S")
LogFile="${LogDir}/${script_base_name}_${ShellName}.${RunTs}.log";
Shellcksum=$(cksum ${WorkDir%/}/${ShellName} 2>/dev/null|awk '{printf "%d",$1}')
declare -i UserID=$(id -u);declare UserName=$(whoami);declare HostName=$(hostname);
###############################################################################
##TiDB Var##
locallogin=""
adminusers=""
checkpointschema=""
nobackupdatabase="INFORMATION_SCHEMA,METRICS_SCHEMA,PERFORMANCE_SCHEMA,mysql,tidb_binlog"
backupdir=""
user=""
tidbfbconfig="${TidbHome}/scripts/flashback/cluster_flashback_config.cnf"
[ -f ${tidbfbconfig} ] && source ${tidbfbconfig}
###############################################################################
###############################################################################
##Get inopt
# [ -z "${ShellOption}" -a -z "${primaryhostname}" -a -z "${standbyhostname}" ] && f_syntax;
for inopt in ${ShellOption}
do
    case $(echo $inopt|tr a-z A-Z) in
    -PRIMARYHOSTNAME|-HOSTNAME) CurOpt="-HOSTNAME_P";continue;;
    -STANDBYHOSTNAME) CurOpt="-HOSTNAME_S";continue;;
    -HELP|--HELP|-H) f_syntax;;
    -*) CurOpt="";continue;;
    esac
    case "${CurOpt}" in
    -HOSTNAME_P) declare primaryhostname="${inopt}";continue;;
    -HOSTNAME_S) declare standbyhostname="${inopt}";continue;;
    esac
done

f_PrintLog "Info" "Start to run Script ${ShellName}, the Shellcksum is ${Shellcksum}"
f_PrintLog "Info" "Script Options:${ShellOption}"

###############################################################################

function f_getclusterinfo
{
    f_PrintLog "Info" "Start to run f_getclusterinfo."
    # clsname,connip,connport,dbsize,dbs,userlist,drainernode,backupdir,repluser
    clsName=$(tiup cluster list 2>/dev/null|awk '{if($3~"v" && $4~"tiup"){printf "%s\n",$1;exit}}') 
    if [ -z "${clsName}" ]
    then
        f_PrintLog "Error" "Can not find valid cluster name using:tiup cluster list"
        exit 1
    fi
    f_PrintLog "Info" "find valid cluster name is ${clsName}"
    tiup cluster display ${clsName} 

    tidbclsinfo=$(tiup cluster display ${clsName} 2>/dev/null)
    IPList=$(ip a |awk '/^[1-9]/{gsub(":","",$2);en=$2}
     /^[ |\t]*inet /{gsub(".*:","",$2);gsub("/.*","",$2);if(en!~"^lo")N[$2]=en}
     END{for(ip in N){printf "%s\n",ip}}')
    tidbProc=$(ps -ef | grep "tidb-server -P 4"| grep -v grep)
    tidbPort=$(echo ${tidbProc}|awk -F"-P" '{print $2}'|awk '{printf "%d",$1}')
    tidbIp=$(echo ${tidbProc}|awk -F"--advertise-address=" '{print $2}'|awk '{printf "%s",$1}')

    tidbNodeId=$(tiup cluster display ${clsName} 2>/dev/null|awk -v id="${tidbIp}:${tidbPort}" '{
     if($1==id && $2=="tidb" && $6=="Up" ){printf "%s",$1;exit}
     }')

    [ -z "${tidbNodeId}" ] && f_PrintLog "Warn" "Can not find valid tidb node ${tidbIp}:${tidbPort}, the cluster name is ${clsName}"

    #根据drainerid是否等于tidbid判断drainer归属
    tidb_urls=$(tiup cluster display ${clsName} 2>/dev/null|awk '{if($2=="tidb"){gsub(":.*","",$1);printf "%s ",$1}}')
    dr_urls=$(tiup cluster display ${clsName} 2>/dev/null|awk '{if($2=="drainer"){printf "%s,%s ",$1,$6}}')
    for drid in ${dr_urls}
    do
        _localflag=$(echo ${tidb_urls} |grep -w ${drid%:*})
        _Upflag=$(echo ${drid} |grep -w "Up")
        if [ -z "${_localflag}" ]
        then
            drainerRemote="${drainerRemote}${drid}"
            [ -n "${_Upflag}" ] && drainerRemoteUp="${drainerRemoteUp}${drid}"
            f_PrintLog "Info" "Find a remote drainer ${drid}, drainerRemote:${drainerRemote}"
        else
            drainerLocal="${drainerLocal}${drid}"
            [ -n "${_Upflag}" ] && drainerLocalUp="${drainerLocalUp}${drid}"
            f_PrintLog "Info" "Find a locale drainer ${drid}, drainerLocal:${drainerLocal}"
        fi
    done

    _drCt=$(echo ${drainerRemote}|awk -F: '{print NF}')
    if [ ${_drCt} -gt 2 ]
    then
        f_PrintLog "Error" "The remote drainer count is ${_drCt}, exit!!!"
        exit 1
    fi

    t2fDrId=${drainerLocal}
    t2tDrId=${drainerRemote}
    tidbDrainerId=${drainerRemote%,*}
    drainerRemote=${drainerRemoteUp}

    if [ -z "${tidbDrainerId}" ] 
    then
        f_PrintLog "Warn" "Can not find valid drainer node, the cluster name is ${clsName}"
    else
        tidbIp_s=${tidbDrainerId%:*}
    fi

    adminusers_sql=$(echo "${adminusers}"|sed "s/,/','/g")
    _execsql="select group_concat(concat(user,'@',host) SEPARATOR ',') from  mysql.user where user not in ('${adminusers_sql}')"
    f_PrintLog "Info" "START TO RUN SQL:${_execsql}, DBinfo ${tidbIp}:${tidbPort}"
    appUsers=$(mysql --login-path=${locallogin:-tidblogin} -NBe "${_execsql}")

    f_PrintLog "Info" "Get ${HostRole} cluster info finished. clsname:${clsName}, Ip:${tidbIp}, Port:${tidbPort}, remote drainerId:${tidbDrainerId}, standbyIp:${tidbIp_s}, appUser:${appUsers}"
}

function f_checkrepl_main
{
    f_PrintLog "Info" "Start to run f_checkrepl_main."
    #check tidb
    tidbclsinfo=$(tiup cluster display ${clsName}  2>/dev/null)
    f_checktidb ${clsName}

    
    #check binlog status
    tidburl=$(echo "${tidbclsinfo}"|awk '{
        if(NF>=8 && $2=="tidb" && $6=="Up" ){gsub(".*/","",$4);printf "%s:%s\n",$3,$4;exit}
        }')
    if [ -z "${tidburl}" ] 
    then
        f_PrintLog "Error" "Failed to check tidb binlog status. tidburl is null!!!"
        exit 1
    else
        f_PrintLog "Info" "Start to check tidb binlog status. tidburl: http://${tidburl}/info/all "
        f_checktidbbinlog ${tidburl}
    fi

}

function f_stoprepl_main
{
    f_PrintLog "Info" "Start to run f_stoprepl_main."
    f_PrintLog "Info" "Cluster status before stop..."
    tiup cluster display ${clsName}  2>/dev/null

    f_stopnode "${tidbDrainerId}"


    f_PrintLog "Info" "Cluster status after stop..."
    tiup cluster display ${clsName}  2>/dev/null
}


function f_fb_config_main
{
    f_PrintLog "Info" "Start to run f_fb_config_main."
    
    f_generate_fb_config

    f_PrintLog "Info" "tiup cluster exec ${clsName} -N${tidbDrainerId} --command mkdir -p ${TidbHome}/scripts/flashback"
    tiup cluster exec ${clsName} -N${tidbIp_s} --command "mkdir -p ${TidbHome}/scripts/flashback"

    f_PrintLog "Info" "iup cluster push ${clsName} -N${tidbDrainerId} ${tidbfbconfig} ${tidbfbconfig}"
    tiup cluster push ${clsName} -N${tidbIp_s} "${tidbfbconfig}" "${tidbfbconfig}" 
}


###################
####    Main   ####
###################
function f_fb_primary_stoprepl_main
{
    #判断集群为主集群
    f_getclusterinfo
    f_PrintLog "Info" "Get cluster info finished. clsname:${clsName}, Ip:${tidbIp}, Port:${tidbPort}, remote drainerId:${tidbDrainerId}, standbyIp:${tidbIp_s}, appUser:${appUsers}"
    
    #主节点binlog状态正常
    f_checkrepl_main 
    
    #停止主备复制
    f_stoprepl_main

    #切换配置文件
    f_fb_config_main

    f_PrintLog "Succ" "Run function f_fb_primary_stoprepl_main finish!"
    f_PrintLog "Info" "Successful to run Script ${ShellName} on ${HostName}, script_base_name ${script_base_name}."
}


 
f_fb_primary_stoprepl_main
# exit ${PIPESTATUS[0]} 


