#!/bin/sh
source /OSM/script/os_load_base.sh
#制作补丁时，修改GProcess、GSuffix、GVersion、GoldProcess、GoldProcessInDisk、Cgroup.
#GProcess：替换的进程全路径名称  GSuffix：补丁二进制的文件名后缀 GLastVisionSuffix:上一个补丁二进制的文件名后缀 GVersion：补丁版本号 Cgroup：该进程所属的Cgroup组名
#GoldProcess：升级组备份的进程名 GoldProcessInDisk:升级组解决部分版本打补丁后内存文件占用较多问题，会将补丁文件移动到盘目录
GProcess=/OSM/bin/ccdb_server
GSuffix=DTS2024010916276V
GLastVisionSuffix=DTS2023081509518
GVersion=SPH060
GoldProcess=/OSM/bin/ccdb_server_origin
GoldProcessInDisk=/OSM/coffer_data/patch_backup/V300R006C61/ccdb_server_origin
Cgroup=ccdb
infra_backup_common_path=/OSM/coffer_data/ccdb/ccdb_patch_backup
infra_component_lib_path=/usr/local/lib/
libcls_mon_client_so_name=libcls_mon_client.so
libcls_mon_client_so_replace_name=libcls_mon_client_DTS2024010916276.so
libpaxos_so_name=libpaxos.so
libpaxos_so_replace_name=libpaxos_DTS2024010916276.so
so_origin_suffix=v300r006c61sph60_origin
so_pre_suffix=v300r006c61sph60_pre
SH_NAME=$(basename $0)

function loopRun()
{
    local counter=0
    while [ $counter -le 5 ]
    do
        ((counter++))
        if [ $counter -gt 3 ];then
            sleep 1
        fi
        
        "$@"
        local cmdRet=$?
        [ ${cmdRet} -eq 0 ] && return 0
        OS_echo "[$SH_NAME] error=${cmdRet}, Failed to run: $*." 
    done

    return 1
}

function do_recover()
{
    L_BACKUP_FILE=$1
    L_LIB_PATH=$2
 
    if [ ! -f ${L_BACKUP_FILE} ]; then
        OS_echo "${SH_NAME} cold patch: ${L_BACKUP_FILE} not exist, recover success"
        return 1
    fi
    
    mv ${L_BACKUP_FILE} ${L_LIB_PATH}
    if [ $? -ne 0 ]; then
        OS_echo "[$SH_NAME] recover mv ${L_BACKUP_FILE} ${L_LIB_PATH} failed"
        return 2
    fi
    
    OS_echo "[$SH_NAME] recover mv ${L_BACKUP_FILE} ${L_LIB_PATH} success"
    return 0
}

function do_recover_so()
{
    do_recover ${infra_backup_common_path}/${libcls_mon_client_so_name}_${so_origin_suffix} ${infra_component_lib_path}/${libcls_mon_client_so_name}
    L_RET=$?
    if [ ${L_RET} -eq 2 ];then
        OS_echo "${SH_NAME} cold patch: rollstart do recover all failed"
        return 1
    fi

    do_recover ${infra_backup_common_path}/${libpaxos_so_name}_${so_origin_suffix} ${infra_component_lib_path}/${libpaxos_so_name}
    L_RET=$?
    if [ ${L_RET} -eq 2 ];then
        OS_echo "${SH_NAME} cold patch: rollstart do recover all failed"
        return 1
    fi
    return 0
}

PATCH_START()
{
    return 0
}

PATCH_END()
{
    return 0
}

PATCH_ROLLBACK()
{
    local RETRY_TIMES=0
    local ProcessDir
    
    do_recover_so
    L_RET=$?
    if [ $L_RET -ne 0 ]; then
        OS_echo "${SH_NAME} cold patch: do backup and replace so failed"
        return 1
    fi

    rm -f /OSM/ccdb/close_ccdb_isolate_node
    #新增判断 如果文件大小为0，则拷贝基线进程过来。解决小补丁大小超过1M限制方案。
    if [ -f $GProcess ]; then
        FILE_SIZE=`du -sb $GProcess | awk '{print $1}'`
        while [ $? -ne 0 -a $RETRY_TIMES -lt 3 ]
        do
            ((RETRY_TIMES++))
            OS_echo "[$SH_NAME] Check $GProcess size, times($RETRY_TIMES)."
            sleep 0.1
            FILE_SIZE=`du -sb $GProcess | awk '{print $1}'`
        done
        if [ $FILE_SIZE -eq 0 ]; then
            if [ -f $GoldProcess ]; then
                ProcessDir=$GoldProcess
            fi
            if [ -f $GoldProcessInDisk ]; then
                ProcessDir=$GoldProcessInDisk
            fi
            if [ ! -f $ProcessDir ]; then
                OS_echo "[$SH_NAME] Do not find origin file."
                return 0
            fi
            OS_echo "[$SH_NAME] Local process backup dir is $ProcessDir."
            loopRun install $ProcessDir $GProcess
            if [ $? -ne 0 ]; then
                return 0
            fi
            loopRun chmod 550 $GProcess
            if [ $? -ne 0 ]; then
                return 0
            fi
            OS_echo "[$SH_NAME] The $GProcess size is $FILE_SIZE."
            return 0
        fi

        OS_echo "[$SH_NAME] The $GProcess size is $FILE_SIZE."

    fi

    fileType=$(file $GProcess | awk '{print $2}')
    if [ "$fileType" != "ELF" ]; then
        chmod 775 $GProcess
        tar zxf $GProcess -C /OSM/bin
        L_RET=$?
        if [ $L_RET -ne 0 ]; then
            OS_echo "${SH_NAME} tar $GProcess failed"
            return 1
        fi
        rm -f $GProcess
        mv $GProcess"_"$GLastVisionSuffix $GProcess
        L_RET=$?
        if [ $L_RET -ne 0 ]; then
            OS_echo "${SH_NAME} mv $GProcess"_"$GLastVisionSuffix to $GProcess failed"
            return 1
        fi
    fi
    chmod 550 $GProcess

    #判定该进程是否已经被加载，是否还在运行
    red=$(ps -ww -eo pid,cmd | grep $GProcess | grep -v grep | awk '{print $1}')
    OS_echo "[$SH_NAME] $GProcess oldPid: $red"
    if [ "$red" = "" ]; then
        #进程不在位，只有daemon不在位的情况，同时如果不在位资源利用率也不会太高，此处不考虑，直接返回OK
        return 0
    fi
	
    OS_echo "[$SH_NAME] $GProcess will be killed."
    daemon -s $GProcess
    if [ $? -ne 0 ]; then
        OS_echo "[$SH_NAME] stop $GProcess failed."
        daemon -s $GProcess
        if [ $? -ne 0 ]; then
            OS_echo "[$SH_NAME] stop $GProcess failed again."
            #停进程失败了。直接return 不exit.不影响打补丁。
            return 0
        fi
    fi

    daemon $GProcess "/OSM/bin/cgroup_manage.sh -g $Cgroup"
    
    rednew=$(ps -ww -eo pid,cmd | grep $GProcess | grep -v grep | awk '{print $1}')
    RETRY_TIMES=0
    while [ -z "$rednew" -a $RETRY_TIMES -lt 5 ] || [ $red -eq $rednew -a $RETRY_TIMES -lt 5 ]
    do
        ((RETRY_TIMES++))
        OS_echo "[$SH_NAME] Check $GProcess status, times($RETRY_TIMES)."
        sleep 0.2
        rednew=$(ps -ww -eo pid,cmd | grep $GProcess | grep -v grep | awk '{print $1}')
    done
    
    OS_echo "[$SH_NAME] newPid: $rednew"
    if [ "$rednew" = "" ] || [ $red -eq $rednew ]; then
        OS_echo "[$SH_NAME] $GProcess old pid is $red, new pid is $rednew."
        return 0
    fi
    return 0
}

PATCH_ROLLEND()
{
    return 0
}

L_CMD=$1
case $L_CMD in
    "start") PATCH_START
               L_RET=$?
               ;;
    "end") PATCH_END
               L_RET=$?
               ;;
    "rollstart") PATCH_ROLLBACK
               L_RET=$?
               ;;
    "rollend") PATCH_ROLLEND
               L_RET=$?
               ;;
    *)
        OS_echo "unsupported option."
        L_RET=0
esac
exit $L_RET