4.2 Syntaxe et sémantique du langage
4.2.9 Déclaration de variables et gestion de l'aléatoire
La gestion du hasard se fait à l'aide de variables aléatoires. Ces variables sont
initial-isées à l'aide de fonctions aléatoires de bibliothèques extérieures ou de fonctions aléatoires
prédénies. Elles sont ensuite utilisées dans les gardes des règles. Il existe deux façons de
déclarer et d'initialiser les variables (aléatoires ou non) :
Daemon test
{ // Ici nb_g1 est initialise avec la valeur 500
int nb_g1 = FAIL_SIZE (G1) ; }
Group G1
{ size = 500 ;
daemon = test ; }
Fig. 4.25 La taille d'un tableau de machines.
déclaration globale dans un automate :
Lorsqu'une variable est déclarée globalement dans un automate, elle est initialisée
lors du lancement de l'automate. Cette variable est visible et utilisable par tous
les noeuds de l'automate. La déclaration et l'utilisation de variable globale se fait
comme dans l'exemple de la gure 4.26
Daemon Mesto
{ int wait_msg = 0 ;
node 1 :
?msg && wait_msg==25 -> wait_msg = 0 ; goto 2 ;
?msg && wait_msg<>25 -> wait_msg = wait_msg + 1 ;
node 2 :
?msg -> !kill_random, goto 1 ; }
Fig. 4.26 Les variables globales.
Dans cet exemple, l'automate nommé Mesto attend 25 messages msg et diuse le
message kill_random lorsqu'il reçoit de nouveau le message msg (donc au 26ième
message msg) et il recommence cette procédure indéniment.
déclaration locale dans un automate :
Lorsqu'une variable est déclarée localement dans un automate, elle est initialisée
quand l'automate se positionne pour la première fois dans ce noeud et qu'il passe
d'un autre noeud à ce noeud (en fait, les variables locales ne sont pas réinitialisées
lors de récursion sur un même noeud). Ces variables ne sont visibles que dans le
noeud où elles sont déclarées. La déclaration et l'utilisation de variables locales se
font comme dans l'exemple de la gure 4.27.
Daemon Mesto
{ node 1 :
int wait_msg = 0 ;
?msg && wait_msg==25 -> goto 2 ;
?msg && wait_msg<>25 -> wait_msg = wait_msg + 1 ;
node 2 :
?msg -> !kill_random, goto 1 ; }
Fig. 4.27 Les variables locales.
en utilisant des variables locales.
Remarque 2 : lorsque les noeuds ne sont pas spéciés, toutes les variables sont des
variables globales comme dans l'exemple de la gure 4.28.
Daemon Mesto
{ int wait_msg = 0 ;
?msg && wait_msg<>26 -> wait_msg = wait_msg + 1 ;
?msg && wait_msg==26 -> !kill_random, wait_msg = 0 ; }
Fig. 4.28 Les variables dans un automate sans n÷uds.
Cet exemple correspond au même exemple que précédemment mais en n'utilisant
pas de noeuds dans l'automate.
déclaration et utilisation d'une variable aléatoire :
l'utilisateur peut utiliser dans ses actions, ou pour initialiser une variable, le résultat
de la fonction prédénie FAIL_RANDOM(min, max) qui renvoie un entier aléatoire
uniforme compris dans [min, max]. Il peut aussi fournir d'autres fonctions dont il
peut vouloir se servir via une bibliothèque dynamique. La gure 4.29 présente un
exemple d'utilisation d'une variable aléatoire.
Daemon random_halt
{ int rand = FAIL_RANDOM(0,10) ;
?fail_or_not && rand == 4 -> halt ; }
Fig. 4.29 Les variables aléatoires.
A la réception d'un message fail_or_not , l'automate random_halt fait
crasher le programme testé suivant la valeur de la variable aléatoire rand .
Remarque : on ne peut pas faire appel à une fonction dans une garde. Il faut
initialiser une variable avec cette fonction puis l'utiliser dans la garde. Cette mesure
est prise pour éviter certains problèmes sémantiques liés à l'implantation.
Utilisation de bibliothèques dynamiques
L'utilisateur peut vouloir utiliser des fonctions d'une bibliothèque dynamique. Par
exemple pour calculer une variable aléatoire en utilisant une fonction aléatoire d'une
bibliothèque dynamique. Pour cela il doit donner la signature de cette fonction ainsi que
le nom de la bibliothèque où elle se trouve comme dans l'exemple de la gure 4.30.
/* declaration d'une fonction nommee "mon_hazard" prennant en entree
deux entiers et retournant un entier. Cette fonction fait partie
de la bibliotheque "libutils.so" */
function int mon_hasard(int, int) in library "libutils.so" ;
/* si a la reception de "fail_or_not", mon_hasard(3, 400) renvoi 4,
alors arret denitif de l'application testee. */
Daemon Adv1
{ int rand = mon_hasard(3, 400) ;
?fail_or_not && rand == 4 -> halt ; }
Fig. 4.30 Les bibliothèques dynamiques.
Utilisation de la commande always
La commande always permet de forcer l'initialisation d'une variable pendant la
récur-sion sur un même noeud (après une suite d'actions) comme le montre la gure 4.31.
Dans cet exemple, au bout de x secondes (x étant une variable aléatoire uniforme
com-prise entre 10 et 20), l'automate coucou diuse le message faire_1 ou faire_2
selon la valeur de la variable aléatoire rand (la valeur de cette variable étant obtenue
grâce à la fonction mon_hasard de la bibliothèque externe libutils.so). Une fois le
mes-sage envoyé, la valeur du minuteur est recalculée et le minuteur est réarmé.
function int mon_hasard(int, int) in library "libutils.so" ;
Daemon coucou
{ // le temps global est en millisecondes
always time_g timer = FAIL_RANDOM(10,20) ;
always rand = mon_hazard(3, 400) ;
timer && rand >= 100 -> !faire_1 ;
timer && rand < 100 -> !faire_2 ; }
Fig. 4.31 Utilisation de la commande always.
Initialisations gardées
Il est possible de dénir une règle gardée comme faisant partie de l'initialisation. La
syntaxe pour la dénition de telles règles est présentée dans l'exemple de la gure 4.32.
Daemon toto
{ int rand = FAIL_RANDOM(1,10) ;
// Denition d'une regle gardee initiale :
init rand == 4 -> halt ; }
Fig. 4.32 Les initialisations gardées.
Dans cet exemple, à son initialisation, l'automate tire un nombre aléatoirement et
crashe ou non suivant la valeur de ce nombre.
Remarque 1 : ce type de règle ne sera testé que lors de l'initialisation.
Remarque 2 IMPORTANTE : les restrictions sur les entités des gardes pour ce type de
règle (règle initiale) sont diérentes des restrictions pour les règles standards (voir la
section 4.2.11 introduisant les restrictions sur les gardes).
Dans le document
INJECTION DE FAUTES DANS LES SYSTEMES DISTRIBUES
(Page 62-66)