#!/bin/bash

#-----------------------------------------------------------
# $Id: distexe_execute_n.sh 138 2010-05-12 17:34:01Z rosiere $
#-----------------------------------------------------------

#-----[ global variable ]-----------------------------------
declare -i TRAP=0;

#-----[ distexe_execute_n_usage ]---------------------------
function distexe_execute_n_usage ()
{
    echo "Usage     : ${0} path_work file_cmd file_cpt file_host lock_host prefix_file_process sleep [ nb_process ]";
    echo "Arguments : ";
    echo " * path_work           : directory to execute command";
    echo " * file_cmd            : list of command";
    echo " * file_cpt            : file to control";
    echo " * file_host           ; file host";
    echo " * lock_host           ; file lock host";
    echo " * prefix_file_process : prefix of process's file";
    echo " * sleep               : time in second to sleep";
    echo " * nb_process          : number of process (default (and maximum) is the number of processor)";
    echo "";
    echo "Note      : ";
    echo " * This script, for each command, create a directory : Task_X (X is the number of command), and execute the command in this directory.";
    echo " * Two file is generate : \"output\" is the output of the execution, and \"command\" is the command lunch.";
#   echo " * A command empty (no command on a line of file) is a synchronisation with all process"
    echo " * Don't forgot the final end of line (else the last command is not executed)";
    echo "";
    exit;
}

#-----[ distexe_execute_n_test_usage ]----------------------
function distexe_execute_n_test_usage ()
{
    if test ${#} -ne 7 -a ${#} -ne 8; then
	distexe_execute_n_usage;
    fi;

    if test -z "${MORPHEO_SCRIPT}"; then
        echo "Environment variable MORPHEO_SCRIPT is not set";
        distexe_execute_n_usage;
    fi;

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

    if test ! -f ${2}; then
	echo "File \"${2}\" don't exist";
	distexe_execute_n_usage;
    fi;

    if test ! -s ${2}; then
	echo "File \"${2}\" is empty";
	distexe_execute_n_usage;
    fi;
}

#-----[ distexe_execute_n_wait_end ]------------------------
function distexe_execute_n_wait_end ()
{
    while true; do

        nb_file=$(ls -1 ${PREFIX_FILE_PROCESS}* 2>/dev/null| wc -l);

        if test ${nb_file} -eq 0; then
            break;
        fi;

        # wait (to not have 100% cpu)
        sleep ${SLEEP};
    done;

    ${MORPHEO_SCRIPT}/lock.sh   ${LOCK_HOST};
    rm -f ${FILE_HOST};
    ${MORPHEO_SCRIPT}/unlock.sh ${LOCK_HOST};
}

#-----[ distexe_execute_n_no_trap ]-------------------------
function distexe_execute_n_no_trap()
{
    TRAP=1;
}

#-----[ distexe_execute_n_trap ]----------------------------
function distexe_execute_n_trap ()
{
#    echo "  * {"$(${MORPHEO_SCRIPT}/date.sh)"} <${HOSTNAME}> Trap signal detected";
#    echo "  * {"$(${MORPHEO_SCRIPT}/date.sh)"} <${HOSTNAME}> 1111111111111111 Trap signal detected 1111111111111111";

    local -a files_process=($(ls ${PREFIX_FILE_PROCESS}* 2>/dev/null));
    local -i nb_files_process=${#files_process[*]};
    
    if test ${nb_files_process} -ne 0; then
        for file_process in ${files_process[*]}; do
                        # ssh can not set yet pid in file_process
            local -i nb_word=0;
            while test ${nb_word} -eq 0; do
                nb_word=$(echo ${file_process} |wc -m);
            done;

            ${MORPHEO_SCRIPT}/lock.sh   ${LOCK_PROCESS};

            if test -f ${file_process}; then
                pid=$(cat ${file_process});

                #ps aux | grep distexe;

                kill -s SIGINT ${pid};
            fi;

            ${MORPHEO_SCRIPT}/unlock.sh ${LOCK_PROCESS};
        done;
    fi;

#    echo "  * {"$(${MORPHEO_SCRIPT}/date.sh)"} <${HOSTNAME}> 2222222222222222 Trap signal detected 2222222222222222";

    distexe_execute_n_wait_end;

#    echo "  * {"$(${MORPHEO_SCRIPT}/date.sh)"} <${HOSTNAME}> 3333333333333333 Trap signal detected 3333333333333333";

    exit 1;
}

#-----[ distexe_execute_n_main ]----------------------------
function distexe_execute_n ()
{
    trap distexe_execute_n_no_trap INT TERM;

    local -i NB_PROCESS=$(${MORPHEO_SCRIPT}/nb_cpu.sh);
    local -i CPT;
    local    PATH_WORK=${1};
    local    FILE_CMD=${2};
    local    FILE_CPT=${3};
    local    FILE_HOST=${4};
    local    LOCK_HOST=${5};
    local    PREFIX_FILE_PROCESS="${6}${HOSTNAME}-";
    local    LOCK_PROCESS="${PREFIX_FILE_PROCESS}lock";
    local -i SLEEP=${7};
    echo $$ > ${FILE_HOST};

    distexe_execute_n_test_usage ${*};

    if test ${#} -eq 8; then
	if test ${8} -lt ${NB_PROCESS}; then
	    NB_PROCESS=${8};
	fi;    
    fi;

    echo "  * {"$(${MORPHEO_SCRIPT}/date.sh)"} <${HOSTNAME}> ${NB_PROCESS} process";

    local -i IT_NB_PROCESS=1;
    local -i PID=$$;

    # create the same number of thread that processor
    while test ${IT_NB_PROCESS} -le ${NB_PROCESS}; do
        local FILE_CPU=${PREFIX_FILE_PROCESS}${IT_NB_PROCESS};

        touch ${FILE_CPU};
	${MORPHEO_SCRIPT}/distexe_execute.sh ${PATH_WORK} ${FILE_CMD} ${FILE_CPT} ${FILE_CPU} ${LOCK_PROCESS} "${HOSTNAME}-${IT_NB_PROCESS}" &
	IT_NB_PROCESS=$((${IT_NB_PROCESS}+1));

	if test "$$" -ne ${PID}; then
	    break;
	fi;
    done

    echo "  * {"$(${MORPHEO_SCRIPT}/date.sh)"} <${HOSTNAME}> all process working";

    trap distexe_execute_n_trap INT TERM;

    if test ${TRAP} -eq 1; then
        distexe_execute_n_trap;
    fi;

    # Wait end ok all Task
    distexe_execute_n_wait_end;
}

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