#!/bin/bash

#-----------------------------------------------------------
# $Id: execute.sh 127 2009-06-17 21:21:10Z rosiere $
#-----------------------------------------------------------

#-----[ global variable ]-----------------------------------

#-----[ lock ]----------------------------------------------
function lock ()
{
    lockfile -1 ${1};
}

#-----[ unlock ]--------------------------------------------
function unlock ()
{
    rm -f ${1};
}

#-----[ my_date ]-------------------------------------------
function my_date ()
{
    date +"%F %T";
}

#-----[ execute_usage ]-------------------------------------
function execute_usage ()
{
    echo "Usage     : ${0} path_work file_cmd file_cpt file_cpu id";
    echo "Arguments : ";
    echo " * path_work  : directory to execute command";
    echo " * file_cmd   : list of command";
    echo " * file_cpt   : file with the index of next command to execute";
    echo " * file_cpu   : tmp file to stock the current index";
    echo " * id         : identification";
    exit;
}

#-----[ execute_test_usage ]--------------------------------
function execute_test_usage ()
{
    if test ${#} -ne 5; then
	execute_usage;
    fi;

    if test ! -d ${1}; then
        echo "Directory ${1} is invalid";
    fi;
}

#-----[ execute ]-------------------------------------------
function execute ()
{
    # test_usage
    execute_test_usage ${*};

    local -a COMMAND;
    local -i CPT_OLD;
    local -i CPT;
    local    PATH_WORK=${1};
    local    FILE_CMD=${2};
    local    FILE_CPT=${3};
    local    FILE_CPU=${4};
    local    ID=${5};
    local    LOCK_CPT="${PATH_WORK}/.lock-cpt";
    local    LOCK_CPU="${PATH_WORK}/.lock-cpu";
    local    OUTPUT_FILE_INFO="distexe.info";
    local    OUTPUT_FILE_CMD="distexe.command";
    local    OUTPUT_FILE_OUT="distexe.output";

#   echo "  * {"$(my_date)"} <${ID}> pid is $$";

    # Init CPT if this thread is the first
    lock   ${LOCK_CPT};
    if test ! -s ${FILE_CPT}; then
        echo "  * {"$(my_date)"} <${ID}> create counter file ${FILE_CPT}";
	echo "0" > ${FILE_CPT};
    fi;
    unlock ${LOCK_CPT};

    # read, line by line, the command file and write in array
    CPT=0;

    while read line; do
	COMMAND[${CPT}]="${line}";
	CPT=$((${CPT}+1));
    done < ${FILE_CMD};

    local -i NB_DIGIT=0;
    local -i x=${#COMMAND[*]};

    while test ${x} -ne 0; do
        NB_DIGIT=$((${NB_DIGIT} + 1));
        x=$((${x} / 10));
    done;

    echo "  * {"$(my_date)"} <${ID}> is ready";

    # infinite loop
    CPT_OLD=0;
    CPT=0;

    while test 1; do
	# Take a number
	CPT_OLD=${CPT};

        # Read the index, and increase
	lock   ${LOCK_CPT};
	CPT=$(cat ${FILE_CPT});
	echo "$((${CPT}+1))" > ${FILE_CPT};
	unlock ${LOCK_CPT};

        # test if this number is valid
	if test ${CPT} -ge ${#COMMAND[*]}; then
	    CPT=${#COMMAND[*]};
	fi;

	# test if between the cpt_old and cpt, there are a synchronisation command

#	local -i CPT_SYNC=${CPT}_OLD;
#
#	while test ${CPT}_SYNC -lt ${CPT}; do
#	    if test -z "${COMMAND[${CPT}_SYNC]}"; then
#		echo "  * {"$(my_date)"} <${ID}> synchronisation [${CPT}_SYNC]";
#	    fi;
#	    CPT_SYNC=$((${CPT}_SYNC+1));
#	done;

	# test if this number is valid
	if test ${CPT} -eq ${#COMMAND[*]}; then
	    break;
	fi;

	# Test if command is empty !
	if test ! -z "${COMMAND[${CPT}]}"; then
            local NUM=$(printf %.${NB_DIGIT}d ${CPT});

#	    echo "  * {"$(my_date)"} <${ID}> execute command [${NUM}] : ${COMMAND[${CPT}]}";
	    echo "  * {"$(my_date)"} <${ID}> command [${NUM}] : execute";
	    local PATH_CURRENT=${PWD};

            cd    ${PATH_WORK}        &> /dev/null;
	    mkdir "Task_${NUM}"       &> /dev/null;
	    cd    "Task_${NUM}"       &> /dev/null;
            echo "id   : ${ID}"        >  ${OUTPUT_FILE_INFO};
            echo "host : ${HOSTNAME}" >>  ${OUTPUT_FILE_INFO};
            echo "pid  : $$"          >>  ${OUTPUT_FILE_INFO};
            echo "date : "$(my_date)  >>  ${OUTPUT_FILE_INFO};
	    echo "#!/bin/bash"         >  ${OUTPUT_FILE_CMD};
	    echo 'source ${HOME}/.bashrc;' >>  ${OUTPUT_FILE_CMD};
	    echo "${COMMAND[${CPT}]}" >>  ${OUTPUT_FILE_CMD};
	    chmod +x                      ${OUTPUT_FILE_CMD};
	    ./${OUTPUT_FILE_CMD}      &>  ${OUTPUT_FILE_OUT};
	    cd    ${PATH_CURRENT}     &> /dev/null;
	    echo "  * {"$(my_date)"} <${ID}> command [${NUM}] : done";
	fi;
    done;

    echo "  * {"$(my_date)"} <${ID}> is done";

    lock   ${LOCK_CPU};
    CPT=$(cat ${FILE_CPU});    # read  the      index
    CPT=$((${CPT}-1));
    echo "${CPT}" > ${FILE_CPU}; # write the next index
    unlock ${LOCK_CPU};
    
    if test ${CPT} -eq 0; then
	echo "  * {"$(my_date)"} <${ID}> All task is executed on this host";
	rm ${FILE_CPU};
    fi;
}

#-----[ Corps ]---------------------------------------------
execute ${*};
