##---------------------------------------------------------------------------- ## Script : semaphore.lib ## Module Puppet : gnc-script_core_dtsi ## Auteur : Emmanuel Confrere ## Date : 16-06-2016 ## Version : 3.1.0 ## Objet : Gestion de l execution parallel d un shell. ## ## Fonction : fct_unique_exec [nom] [occurences] [mode] ## fct_libere_exec [nom] ## ## [nom] : Mot alphabetique quelconque identifiant la ressource. ## [nom] ne peut pas prendre pour valeur "wait" ou "nowait". ## ## [occurence] : Nombre d execution parallel (Par defaut 1). ## ## [mode] : "wait" (par defaut) ou "nowait". ## ## Rem : Tous les parametres sont facultatif, mais doivent etre presentes dans l'ordre. ## ## Detail : Cette librairie gere les acces concurrent a une portion de code Bash. ## Deux fonctions sont utilisees : ## - fct_unique_exec : Positionne des semaphores et controle la disponibilite. ## - fct_libere_exec : Supprime des semaphores ## ## La fonction fct_unique_exec(), si appelee sans l argument [nom] et/ou [occurences], ## doit etre positionee en debut de script juste apres le chargement du fichier ## ${NC_EXPL_CONF}/init.conf sinon elle peut etre placee a n importe quel endroit dans le code. ## ## Elle positionne une semaphore pour proteger d une execution concurrente. ## Ensuite elle controle la disponibilite de la ressource et selon le [mode] utilise ## "wait ou "nowait", attend sa liberation ou sort immediatement en erreur. ## ## La semaphore est liberee automatiquement par l appel a la fonction fct_erreur(), sauf si [nom] a ete ## utilisee - fct_erreur() appelle la fonction fct_libere_exec() -. ## ## L utilisation avec [nom] implique OBLIGATOIREMENT de liberer la semaphore en appelant ## explicitement fct_libere_exec [nom] dans le script ayant appele fct_unique_exec(). ## ## [occurences] fixe le nb d execution concurrente qui peuvent etre executer en parallel ## cette valeur est fixe par defaut avec ${SH_CPT_SEMAPHORE} qui vaut 1 si non ## surcharger par le script. ## ## [mode] fixe le comportement de sortie de la fonction fct_unique_exec(). ## Par defaut le mode est fixe a "wait" mais il est possible de demander de ne pas ## attendre et de renvoyer le code erreur 1 en possitionnant la valeur du mode a "nowait". ## ## Les variables SH_FICSEM, SH_PROG et SH_CPT_SEMAPHORE sont initialisees dans le ## fichier ${NC_EXPL_CONF}/init.conf (comme toute les variables SH_*). ## SH_CPT_SEMAPHORE vaut 1 par defaut et peut etre surcharge dans le fichier ## de configuration du script. # ---------------------------------------------------------------------------- # Mise a jour : # 1.0.0 - Emmanuel Confrere - Creation # 1.0.1 - Daniel Frochtmann - Parallelisation de traitement # 1.0.2 - Emmanuel Confrere - Ajout de commentaire # 2.0.0 - Emmanuel Confrere - Debug (Ne fonctionnais pas si plus de 2 occurance) # Refonte complete. On se base maintenant sur une liste de PID # 2.1.0 - Emmanuel Confrere - Evo : prise en charge du nb d occurences actives # 3.0.0 10-02-2016 - Emmanuel Confrere - Evo : Integration au socle DTSI # 3.0.1 17-03-2016 - Emmanuel Confrere - Evo : Ajout d information de debug # 3.1.0 16-06-2017 - Emmanuel Confrere - Evo : Ajout de l option "mode" # Attente progressive # Reformulation de l aide. ##---------------------------------------------------------------------------- function fct_unique_exec() { local NOM=$1 local OCCURENCES=$2 local MODE=$3 local PID=$$ local WAITING=2 local ELIGIBLE=0 local ELIGIBILITE=0 local FICSEM="" # -- Marquage fct_message -debug 0 " Nom:${NOM} Occ:${OCCURENCES} mode:${MODE} PID:${PID}" # -- Fixer le nombre maxi d'occurences actives [ "${OCCURENCES}" = "nowait" -o "${OCCURENCES}" = "wait" ] && MODE=${OCCURENCES} && OCCURENCES=${SH_CPT_SEMAPHORE} || (( ${OCCURENCES} )) || OCCURENCES=${SH_CPT_SEMAPHORE} # -- Identification de la ressource [ "${NOM}" = "nowait" -o "${NOM}" = "wait" ] && MODE=${NOM} && NOM="" (( ${NOM} )) && OCCURENCES=${NOM} && NOM="" [ -n "${NOM}" ] && FICSEM=`echo ${SH_FICSEM}|sed "s/\.sem$/_${NOM}\.sem/"` || FICSEM=${SH_FICSEM} echo "${PID}" >> ${FICSEM} # -- Fixer le mode d execution [ "${MODE}" = "nowait" ] && MODE=1 || MODE=0 # -- On controle l occupation de la ressource # -- Le process est-il eligible pour continuer l execution # -- 0 : Non # -- 1 : Oui ELIGIBLE=`head -${OCCURENCES} ${FICSEM}|grep -cw "${PID}"` # -- Dans le cas ou le process n est pas eligible mais que le mode est nowait # -- on ne passera pas dans la boucle d attente et on doit par consequent # -- enleve le process de la liste d attente. fct_message -debug 1 " Stack 1 - Nom:${NOM} Occ~:${OCCURENCES} Mode:${MODE} Eligible:${ELIGIBLE}" (( ${MODE} & ( ${MODE} ^ ${ELIGIBLE} ) )) && fct_libere_exec "@${NOM}@${PID}" if (( ! (${MODE} | ${ELIGIBLE}) )) then # -- La resource est en cours d utilisation, on attend sa liberation... fct_message -color cyan "Une ou plusieurs occurrences du script ${SH_PROG} est en cours d execution..." fct_message -nolog -color cyan " - Nombre d occurances actives : ${OCCURENCES}" fct_message -nolog -color blanc " .\c" while (( ! ${ELIGIBLE} )) do fct_message -nolog -color cyan ".\c" sleep ${WAITING} (( WAITING++ )) ELIGIBLE=`head -${OCCURENCES} ${FICSEM}|grep -cw "${PID}"` ELIGIBILITE=`grep -cw "${PID}" ${FICSEM}` (( ! ${ELIGIBILITE} )) && echo "${PID}" >> ${FICSEM} CPID=`head -1 ${FICSEM}` [ ! -d /proc/${CPID} ] && fct_libere_exec "@${NOM}@${CPID}" done fct_message -nolog -color vert "." fi return $(( ${MODE} & ( ${MODE} ^ ${ELIGIBLE} ) )) } typeset -Ffx fct_unique_exec # -------------------------------------------------------------------------------------------------------------- function fct_libere_exec() { # Objet : Signaler la fin d execution unique d un script shell # # Syntaxe : fct_libere_exec # local NOM=$1 local PID=$$ local FICSEM # -- Marquage fct_message -debug 0 " Nom:${NOM} PID:${PID}" [ "${NOM:0:1}" = "@" ] && PID=${NOM##*@} && NOM=${NOM%@*} && NOM=${NOM#@} [ -n "${NOM}" ] && FICSEM=`echo ${SH_FICSEM}|sed "s/\.sem$/_${NOM}\.sem/"` || FICSEM=${SH_FICSEM} if [ -f ${FICSEM} ] then cat ${FICSEM}|grep -wv "${PID}" > ${FICSEM}.tmp mv ${FICSEM}.tmp ${FICSEM} [ ! -s ${FICSEM} ] && rm ${FICSEM} fi } typeset -Ffx fct_libere_exec