L'ensemble des scripts et bibliothèques bash utilisés pour maintenir l'infrastructure du Tetalab. Ce socle Bash est une version légère et adaptée du socle Bash essentiellement développé par Emmanuel Confrère, éminent DBA Calédonien.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

153 lines
7.1 KiB

##----------------------------------------------------------------------------
## 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 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 "<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