#!/bin/env bash
##Description: run sqlfile or sql stmt

function f_syntax
{
    [ ! -z "$1" ] && echo ">>[$(date "+%Y%m%d.%H%M%S")] $1"
    echo " "
    echo "bash ${ShellName}  [-primaryhostname <hostname>]"
    echo "-standbyhostname <hostname_standby> "
    echo "-checkdbs <test,sync_diff_inspector> "
    echo " "
    echo " #sample:"
    echo " #sh ${ShellName} -hostname node1 -standbyhostname sa-172-16-4-81 -checkdbs test,sync_diff_inspector" 
    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}" "${CheckTabs}" 
    file_suffix=$1
python -c "
import sys,time

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

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 = 4
#split-thread-count = 4
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 = './logs/syncdiff_output_%s'
''' % (primary_ip, tidbpasswd,  standby_ip, tidbpasswd, checktabs_str, file_suffix)

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

with open(config_file, mode='w') as f:
     f.write(config_text)
" "${tidbIp}" "${tidbIp_s}" "${tidbPasswd:-123}" "${file_suffix}" "${CheckTabs}" 
    
    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
ShellName="$(echo $0|awk -F / '{print $NF}')";ShellOption="$@";
WorkDir="$(echo $0|sed s/${ShellName}//g)";[ -z "${WorkDir}" ] && WorkDir=${PWD};cd ${WorkDir};WorkDir=${PWD}
LogDir="${WorkDir%/}/logs";mkdir -p ${LogDir};
RunTs=$(date "+%Y%m%d.%H%M%S")
LogFile="${LogDir}/${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##
port="4000";user="timon";passwd=""
adminusers="root,tidb,timon,repl"
checkpointschema="tidb_binlog"
isswitchback="NO"
p_port=${port};s_port="4100"
###############################################################################
###############################################################################
##Get inopt
[ -z "${ShellOption}" ] && f_syntax;
for inopt in ${ShellOption}
do
    case $(echo $inopt|tr a-z A-Z) in
    -PRIMARYHOSTNAME) CurOpt="-HOSTNAME_P";continue;;
    -SECONDHOSTNAME) CurOpt="-HOSTNAME_S";continue;;
    -CHECKDBS) CurOpt="-CHECKDBS";continue;;
    -HELP|--HELP|-H) f_syntax;;
    -*) CurOpt="";continue;;
    esac
    case "${CurOpt}" in
    -HOSTNAME_P) declare HostName_P="${inopt}";continue;;
    -HOSTNAME_S) declare HostName_S="${inopt}";continue;;
    -CHECKDBS) declare CheckTabs="${inopt}";continue;;
    esac
done

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

if [ "${HostName_P}" != "${HostName}" -a "${HostName_S}" != "${HostName}" ] 
then
    f_PrintLog "Error" "InputHost are ${HostName_P} and ${HostName_S}, but now i am ${HostName}, exit"
    # exit 1
fi

if [ "${HostName_P}" == "${HostName}" ] 
then
    HostRole="PRIMARY"
elif [ "${HostName_S}" == "${HostName}" ]
then
    HostRole="STANDBY"
else
    HostRole="UNKNOWN"
fi


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 4000"| 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 "Error" "Can not find valid tidb node ${tidbIp}:${tidbPort}, the cluster name is ${clsName}"

    tidbDrainerId=$(tiup cluster display ${clsName} 2>/dev/null|awk -v id="${tidbIp%.*}" '{
     if($1!~id && $2=="drainer"){printf "%s",$1;exit}
     }')

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

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

function f_syncdiffmain
{
    #获取脚本执行需要的集群信息
    f_getclusterinfo  

    #获取脚本执行需要的数据库连接信息
    f_gettidbinfo 
    f_PrintLog "Info" "Get ${HostRole} cluster info finished. clsname:${clsName}, clsname_s:${clsName_s}, Ip:${tidbIp}, standbyIp:${tidbIp_s}, drainerId:${tidbDrainerId}"

    if [ -z "${tidbIp_s}" ]
    then
        f_PrintLog "Error" "can not get valid primaryIp:${tidbIp} standbyIp:${tidbIp_s}, exit"
        exit 1
    fi

    #user
    tidbPasswd=$(echo "${passwd}="|base64 -d)

    # syncdiff_config="./syndiff_1.toml"
    # syncdiff_path="/home/tidb/toolkit/tidb-community-toolkit-v6.1.0-linux-amd64"
    file_suffix=${RunTs}
    syncdiff_config="./conf/syndiff_${file_suffix}.toml"
    output_dir="./logs/syncdiff_output_${file_suffix}"
    mkdir -p ./conf
    
    if [ -z "${CheckTabs}" ]
    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}:${tidbPort}"
        CheckTabs=$(mysql -h${tidbIp} -P${tidbPort} -u${user} -p${tidbPasswd:-123} -NBe "${_execsql}")
        f_PrintLog "Info" "run syncdiff with CheckTabs:${CheckTabs}"
    fi

    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
}

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


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