153 lines
7.1 KiB
Plaintext
153 lines
7.1 KiB
Plaintext
|
##----------------------------------------------------------------------------
|
||
|
## 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 "<lib:fct_unique_exec> 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 "<lib:fct_unique_exec> 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 occurrence du script ${SH_PROG} est en cours d execution..."
|
||
|
fct_message -nolog -color cyan " - Nombre d occurance active : ${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 "<lib:fct_libere_exec> 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
|