#!/bin/bash

source /OSM/script/os_load_base.sh
#制作补丁时，修改GProcess和Cgroup和GoldProcess即可.
#GProcess：替换的进程全路径名称 Cgroup：该进程所属的Cgroup组名 GoldProcess：升级组备份的进程名
GProcess=/OSM/bin/perf
GoldProcess=/OSM/bin/perf_origin
#GoldProcessInDisk:升级组解决部分版本打补丁后内存文件占用较多问题，会将补丁文件移动到盘目录
GoldProcessInDisk=/OSM/coffer_data/patch_backup/V300R006C61/perf_origin
Cgroup=omm_perf
FLAG=0
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 restartProcess()
{
    local RETRY_TIMES=0
    local ProcessDir
	
    #新增判断 如果文件大小为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 [ ! $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 1
            fi
            loopRun chmod 550 $GProcess
            if [ $? -ne 0 ]; then
                return 1
            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

    if [ $FLAG -eq 1 ]; then 
        chmod 775 $GProcess
        mv $GProcess $GProcess.tgz
        tar zxf $GProcess.tgz -C /OSM/bin
        chmod 550 $GProcess
        rm -f $GProcess.tgz
    fi

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

    return 0
}

function PATCH_START()
{
    return 
}
function PATCH_END()
{
    FLAG=1
    restartProcess
    return
}

function PATCH_ROLLSTART()
{
    return
}

function PATCH_ROLLEND()
{
    red=$(file $GProcess | awk '{print $2}')
    if [ "$red" = "ELF" ]; then
        FLAG=0
        OS_echo "[$SH_NAME] $GProcess FLAG 0."
    else
        FLAG=1
        OS_echo "[$SH_NAME] $GProcess FLAG 1."
    fi

    restartProcess
    return
}

#start：打补丁前需要执行的操作，脚本的执行时间点在替换文件前
#end：打补丁后需要执行的操作，脚本的执行时间点在替换文件后
#rollstart：回滚补丁时需要执行的操作，脚本的执行时间点在文件被恢复之前。
#rollend：回滚补丁时需要执行的操作，脚本的执行时间点在文件被恢复之后。
#PATCH_CLOSE_SWITCH:先读取性能统计开关的状态，将其值保存到switch中,并关闭性能统计开关
#PATCH_OPEN_SWITCH:如果用户之前是打开状态，将其开关打开
OS_echo "[$SH_NAME] $GProcess: command is ($1)."
L_CMD=$1
case $L_CMD in
    "start") 
        PATCH_START
        ;;
    "end") 
        PATCH_END
        ;;
    "rollstart") 
        PATCH_ROLLSTART
        ;;
    "rollend") 
        PATCH_ROLLEND
        ;;
    *)
        OS_echo "[$SH_NAME] unsupported option."
esac
exit 0

