#!/bin/env bash
##Description: run syncdiff
script_run_role="PRIMARY,STANDBY"
script_base_name="tidb_so_primary_syncdiff"

function f_syntax
{
    [ ! -z "$1" ] && echo ">>[$(date "+%Y%m%d.%H%M%S")] $1"
    echo " "
    echo "bash ${ShellName}  [-primaryhostname <hostname>]"
    echo "-standbyhostname <hostname_standby> -syncdifftabs <tab_list>"
    echo " "
    echo " #Description:"
    echo " -primaryhostname ,the primary cluster manager host"
    echo " -standbyhostname ,the standby cluster manager host"
    echo " -syncdifftabs ,the tables need to backup, eg: db1.t*,db2.t2,test.*"
    echo " "
    echo " #sample:"
    echo " #sh ${ShellName} -primaryhostname node1 -standbyhostname sa-172-16-4-81 -syncdifftabs db1.t*,db2.t2,test.*" 
    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}";
}

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

function f_generateconfig
{
    f_PrintLog "Info" "Start to run f_generateconfig."
    echo "${tidbIp}" "${tidbIp_s}" "${tidbPasswd:-123}" "${file_suffix}" "${syncdifftabs}" 
    file_suffix=$1
python -c "
import sys,time

args = sys.argv
primary_ip = args[1]
standby_ip = args[2]
tidbpasswd = args[3]
filedir = args[4]
file_suffix = args[5]
check_tabs = args[6]

tabs_lst = check_tabs.split(',')
tabs2_lst = []
for tab in tabs_lst:
    if '.' not in tab:
        tab = tab + '.*'
    tabs2_lst.append('\"%s\"' %(tab) )
checktabs_str = ','.join(tabs2_lst)

config_text = '''
# Sync Diff Configuration.
######################### Global config #########################
check-thread-count = 64
#split-thread-count = 64
export-fix-sql = true
check-struct-only = false

######################### Tables config #########################
[data-sources]
[data-sources.tidb_primary] 
    host = '%s'
    port = 4000
    user = 'timon'
    password = '%s'

[data-sources.tidb_slave]
    host = '%s'
    port = 4000
    user = 'timon'
    password = '%s'

[task]
    source-instances = ['tidb_primary']
    target-instance = 'tidb_slave'
    target-check-tables = [%s]
    output-dir = '%s/syncdiff_output_%s'
''' % (primary_ip, tidbpasswd,  standby_ip, tidbpasswd, checktabs_str, filedir, file_suffix)

config_file='%s/syndiff_%s.toml' %(filedir, file_suffix)

with open(config_file, mode='w') as f:
     f.write(config_text)
" "${tidbIp}" "${tidbIp_s}" "${tidbPasswd:-123}" "${base_dir}" "${file_suffix}" "${syncdifftabs}" 
    
    f_PrintLog "Info" "run sync diff f_generateconfig finished, pls check ${syncdiff_config}"
    ls -l ${syncdiff_config:-1}
    cat ${syncdiff_config:-1}
}

function f_runsyncdiff
{
    f_PrintLog "Info" "Start to run f_runsyncdiff."
    configfile=$1

    f_PrintLog "Info" "Start to run syncdiff. sync_diff_inspector --config ${configfile}"
    sync_diff_inspector --config ${configfile}
    return $?
}

###############################################################################
##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}/switchover/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="tidblogin"
adminusers="root,tidb,timon,repl"
checkpointschema="tidb_binlog"
backupdir="/data2/tidbbackup"
user="timon"
tidbsoconfig="${TidbHome}/switchover/cluster_switchover.config"
[ -f ${tidbsoconfig} ] && source ${tidbsoconfig}
###############################################################################
###############################################################################
##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) CurOpt="-HOSTNAME_P";continue;;
    -STANDBYHOSTNAME) CurOpt="-HOSTNAME_S";continue;;
    -SYNCDIFFTABS) CurOpt="-SYNCDIFFTABS";continue;;
    -HELP|--HELP|-H) f_syntax;;
    -*) CurOpt="";continue;;
    esac
    case "${CurOpt}" in
    -HOSTNAME_P) declare primaryhostname="${inopt}";continue;;
    -HOSTNAME_S) declare standbyhostname="${inopt}";continue;;
    -SYNCDIFFTABS) declare syncdifftabs="${inopt}";continue;;
    esac
done

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


function f_readandcheckconfig
{

    f_PrintLog "Info" "Start to run f_readandcheckconfig."
    #
    [ -f ${tidbsoconfig} ] && source ${tidbsoconfig} 
    appusers="${PRIMARYAPPUSERS}"
    tidbPasswd=$(echo "${PASSWD}="|base64 -d)
    tidbIp="${PRIMARYIP}"
    tidbIp_s="${STANDBYIP}"
    tidbPort="${PRIMARYPORT}"
    clsName="${PRIMARYCLUSTERNAME}"
    clsName_s="${STANDBYCLUSTERNAME}"
    tidbDrainerId="${PRIMARYT2TDRAINER%,*}"
    backupdir="${BACKUPDIR:-/tidbbackup}"
    
    f_PrintLog "Info" "Get ${HostRole} cluster info finished. clsname:${clsName}, clsname_s:${clsName_s}, Ip:${tidbIp}, standbyIp:${tidbIp_s}, drainerId:${tidbDrainerId}"

    f_PrintLog "Info" "Check config hostname and cluster name."
    clsNamelocal=$(tiup cluster list 2>/dev/null|awk '{if($3~"v" && $4~"tiup"){printf "%s\n",$1;exit}}') 
    if [ -z "${clsNamelocal}" ]
    then
        f_PrintLog "Error" "Can not find valid cluster name using:tiup cluster list"
        exit 1
    else
        f_PrintLog "Info" "Find valid local cluster: ${clsNamelocal}"
        tiup cluster display ${clsNamelocal} 
    fi

    if [ "${HostRole}" = "PRIMARY" -a "${clsName}" != "${clsNamelocal}" ]
    then
        f_PrintLog "Error" "Check config clsname failed, PRIMARY CLUSTERNAME: ${clsName} != ${clsNamelocal}, exit!!!"
        exit 1
    elif [ "${HostRole}" = "PRIMARY" -a "${PRIMARYHOSTNAME}" != "${HostName}" ]
    then
        f_PrintLog "Error" "Check config hostname failed, PRIMARY HOSTNAME: ${PRIMARYHOSTNAME} != ${HostName}, exit!!!"
        exit 1
    elif [ "${HostRole}" = "STANDBY" -a "${clsName_s}" != "${clsNamelocal}" ]
    then
        f_PrintLog "Error" "Check config clsname failed, STANDBY CLUSTERNAME: ${clsName_s} != ${clsNamelocal}, exit!!!"
        exit 1
    elif [ "${HostRole}" = "STANDBY" -a "${STANDBYHOSTNAME}" != "${HostName}" ]
    then
        f_PrintLog "Error" "Check config hostname failed, STANDBY HOSTNAME: ${STANDBYHOSTNAME} != ${HostName}, exit!!!"
        exit 1
    fi
}


function f_primary_syncdiff_main
{
    f_PrintLog "Info" "Start to run Script ${ShellName} on ${HostName}, script_base_name ${script_base_name}."

    if [ -f ${tidbsoconfig} ] 
    then
        f_PrintLog "Info" "Start to buildin config variables, ${tidbsoconfig}."
        source ${tidbsoconfig}
        curdt=$(date +%Y%m%d)
        if [ -z $(echo ${PRIMARYRUNTIME} | grep ${curdt}) ]
        then
            f_PrintLog "Error" "Invalid config file, RUNTIME:${PRIMARYRUNTIME}, ${tidbsoconfig}."
            exit 1
        fi
    else
        f_PrintLog "Error" "Can not find valid config, ${tidbsoconfig}, exit"
        exit 1
    fi 

    #local var
    localProc=$(ps -ef | grep "tidb-server -P 4000"| grep -v grep)
    localPort=$(echo ${localProc}|awk -F"-P" '{print $2}'|awk '{printf "%d",$1}')
    localIp=$(echo ${localProc}|awk -F"--advertise-address=" '{print $2}'|awk '{printf "%s",$1}')
    tidbIpLocal="${localIp}"

    #check script var
    #check host role
    if [ "${primaryhostname}" != "${HostName}" -a "${standbyhostname}" != "${HostName}" ] 
    then
        f_PrintLog "Error" "InputHost are ${primaryhostname} and ${standbyhostname}, but now i am ${HostName}, exit"
        # exit 1
    fi
    
    if [ "${primaryhostname}" = "${HostName}" ] 
    then
        HostRole="PRIMARY"
    elif [ "${standbyhostname}" = "${HostName}" ]
    then
        HostRole="STANDBY"
    else
        HostRole="UNKNOWN"
    fi
    
    if [ "${PRIMARYHOSTNAME}" != "${HostName}" -a "${STANDBYHOSTNAME}" != "${HostName}" ]
    then
        f_PrintLog "Info" "Current hostname is ${HostName}, the script need to run on  ${PRIMARYHOSTNAME}, quit"
        exit 0
    fi

    file_suffix=${RunTs}
    syncdiff_config="${TidbHome}/switchover/syncdiff/syndiff_${file_suffix}.toml"
    output_dir="${TidbHome}/switchover/syncdiff/syncdiff_output_${file_suffix}"
    base_dir="${TidbHome}/switchover/syncdiff"
    mkdir -p "${base_dir}"
    
    #获取脚本执行需要的集群信息
    f_readandcheckconfig  
    f_PrintLog "Info" "Get ${HostRole} cluster info finished. clsname:${clsName}, clsname_s:${clsName_s}, Ip:${tidbIp}, standbyIp:${tidbIp_s}, drainerId:${tidbDrainerId}"
    f_PrintLog "Info" "Get ${HostRole} cluster info finished. clsname:${clsName}, backupdir:${backupdir}, Ip:${tidbIp}"
    
    if [ "${HostRole}" = "STANDBY" ]
    then
        f_PrintLog "Info" "Script ${script_base_name} need to run on PRIMARY node, but hostrole: ${HostRole}, quit."
        exit 0
    fi

    if [ -z "${syncdifftabs}" ]
    then
        _execsql="select group_concat(distinct table_schema SEPARATOR ',') from  information_schema.tables where table_schema not in ('PERFORMANCE_SCHEMA','METRICS_SCHEMA','INFORMATION_SCHEMA','mysql','tidb_binlog')"
        f_PrintLog "Info" "START TO RUN SQL:${_execsql}, DBinfo ${tidbIp}"
        syncdifftabs=$(mysql --login-path=tidblogin -NBe "${_execsql}")
        f_PrintLog "Info" "run syncdiff with SyncTabs:${syncdifftabs}"
    fi

    f_PrintLog "Info" "Start to run syncdiff with SyncTabs:${syncdifftabs}"
    f_generateconfig "${file_suffix}"
    f_runsyncdiff "${syncdiff_config}"  
    _rt_code=$?

    [ -f "${output_dir}/summary.txt" ] && tail -20 ${output_dir}/summary.txt

    if [ ${_rt_code} -eq 0 ]
    then
        f_PrintLog "Info" "f_runsyncdiff finish, pls check summary log at ${output_dir}/summary.txt !"    
    else
        f_PrintLog "Error" "f_runsyncdiff failed, return ${_rt_code}, pls check summary log at ${output_dir}/summary.txt !!!"
        exit 1
    fi

    f_PrintLog "Info" "Successful to run Script ${ShellName} on ${HostName}, script_base_name ${script_base_name}."
    exit 0
}

###################
####    Main   ####
###################


f_primary_syncdiff_main | tee -a ${LogFile}
exit ${PIPESTATUS[0]} 
