• Aucun résultat trouvé

3.3 Impacts sur la tolérance aux pannes

4.1.4 Équivalence d’exécution

L’utilisation de promesse de requête permet donc d’éviter à l’activité réceptrice de recevoir deux occurrences d’une requête orpheline, et permet aussi d’assurer la cohérence minimum de la réexécution. Nous allons voir dans cette section com-ment les promesses de requête sont utilisées pour assurer les conditions d’équiva-lence de la réexécutionCondition 1 et Condition 2.

La propriété 3.1.2.2 du modèle ASP nous permet de caractériser l’exécution d’une activité uniquement par l’ordre de réception des requêtes sur cette activité. Par exemple, dans la figure 4.7, le contenu de la réponse R1 est une conséquence de l’état représenté par le point de reprise Cn+1

j et du service de Q0puis du service

de Q1. Pour assurer l’équivalence de la réponse dupliquée en cas de réexécution, il faut donc disposer du point de reprise Cn+1

j , ainsi que de l’ordre de réception de Q0 et Q1.

Assurer l’équivalence de la réexécution donnée par la condition 1 revient donc à assurer le même ordre de réception des requêtes, ce qui assure aussi la condi-tion 2. Nous introduisons pour cela l’historique de récepcondi-tion de requête, une liste de promesses de requête qui est associée à un point de reprise. On notera Hn

i l’his-torique de réception associé au point de reprise n de l’activité i : quand l’activité i prend le point de reprise Cin, l’historique Hn

i est ouvert sur l’activité i. Quand un historique est ouvert sur une activité, chaque réception de requête déclenche l’ajout d’une promesse de cette requête à la fin de l’historique ouvert.

Nous utilisons ici le fait que les activités en ASP sont déterministes par mor-ceaux, et que les seuls évènements non déterministes sont les réceptions de re-quêtes. Bien sûr, cette restriction peut être levée puisque le déterminisme par morceaux assure que tous les évènements non déterministes sont observables. En pratique, cela implique que le méta-objet est systématiquement capable d’in-tercepter l’exécution d’un évènement non déterministe, et est donc capable de

4.1 Protocole par point de reprise pour ASP 67 i Cjn+1 j Cin+1 Q0 k Ckn Q1 Ckn+1 R1 X(Q0) X(Q1)

FIG. 4.7 – Le service de Q0doit précéder celui de Q1pour assurer l’équivalence de R1

créer des promesses pour n’importe quel type d’évènement non déterministe. Par exemple, pour des évènements non déterministes de type tirage de valeur aléa-toire, le méta-objet crée à l’exécution de l’évènement une promesse qui contient la valeur obtenue. Ainsi, en cas de réexécution, la promesse de l’évènement peut res-tituer la valeur de l’exécution de référence. Nous introduirons dans le chapitre 5 la généralisation de la promesse pour tout type d’évènement non déterministe, et montrerons que le raisonnement appliqué ici sur les réceptions de requête peut être appliqué sur d’autres types d’évènements non déterministes.

Un historique doit finalement être clos durant l’exécution de référence, c’est-à-dire ne plus ajouter de promesses dans cet historique et l’associer au point de reprise n sur la mémoire stable. Or il faut qu’il contienne suffisamment d’infor-mations pour assurer les conditions 1 et 2. Ces deux conditions sont remplies dès qu’il ne peut plus y avoir ni de messages orphelins ni de messages en transit dans l’état global en cours de création ; il faut donc déterminer le moment à par-tir duquel tous les messages potentiellement orphelins ou en transit ont été reçus. Dans le cas de notre modèle ASP, l’existence d’un rendez-vous sur les com-munications (propriété 3.1.2.1) permet de résoudre simplement ce problème. En effet, ce rendez-vous assure la propriété de futur commun (strong common future) entre deux activités communicantes [CHA 96b] : les évènements exécutés après l’envoi d’un message Mi,j sur une activité i sont exécutés aussi forcément après la réception de ce message par j. En particulier, si un point de reprise est déclenché après l’envoi d’un message, le rendez-vous nous assure que ce point de reprise est pris après que le récepteur du message ait reçu ce message. Donc quand une acti-vité prend un point de reprise, il ne peut pas y avoir dans le système de message envoyé par cette activité mais pas encore reçu, c’est-à-dire de message en transit envoyé par cette activité. Ainsi, lorsque l’état global n est terminé, il ne peut plus

y avoir dans le système de message ni orphelin ni en transit. En effet, s’il existe encore :

– un message orphelin, c’est que l’activité réceptrice n’a pas encore pris le point de reprise n,

– un message en transit, c’est que l’activité émettrice n’a pas encore pris le point de reprise n.

Dans ces deux cas, l’état global n ne serait pas terminé. Finalement, les histo-riques n sur les activités peuvent être clos à partir du moment où la dernière activité à prendre le point de reprise n stocke ce point de reprise en mémoire stable. Pour déclencher la clôture des historiques, nous utilisons un message non fonctionnel, noté Mgs

n , qui indique à son récepteur que l’état global n est terminé et donc que l’historique n peut être clos. La dernière activité qui a stocké son point de reprise n sur la mémoire stable est chargée d’envoyer le message Mgs

n à toutes les activités du système. On note que ce message est non fonctionnel, et n’est donc pas pris en compte par le protocole.

La clôture des historiques doit correspondre à une coupe cohérente de l’exécu-tion. En effet, si une requête est orpheline dans la coupe formée par la clôture des historiques, une activité peut se bloquer en attente infinie sur une promesse. Prenons le cas de la figure 4.8 : la requête Q2 est orpheline dans la coupe formée par les clôtures, notées ♦. En cas de réexécution depuis la ligne de recouvrement n, le contenu mais aussi l’envoi lui-même du message Q2 est conditionné entre autre par l’ordre de service, donc de réception, des requêtes Q0et Q1. Or, ces deux réceptions ne font pas partie de l’historique du point de reprise Cn

k, donc l’ordre de réception n’est pas assuré ; la réexécution peut être différente de l’exécution de référence. Dans ce cas, l’envoi de Q2 peut ne pas avoir lieu, et l’activité j resterait infiniment en attente par nécessite sur la promesse de requête de Q2.

i Cn j j Cn i Q1 k Ckn Q0 Q2 X(Q0) X(Q1) Q3

4.1 Protocole par point de reprise pour ASP 69

Nous appliquons le protocole proposé par Briatico dans [BRI 84] pour assurer la cohérence de la clôture des historiques : chaque message est estampillé avec l’index du dernier historique clos de l’émetteur du message. Lorsqu’une activité reçoit un message estampillé avec une valeur n supérieure à l’index du dernier historique clos localement, alors elle clôt l’historique n avant de prendre en compte le message. On peut ici directement appliquer cette solution, puisque contraire-ment aux points de reprise, les clôtures d’historiques peuvent être déclenchées à n’importe quel moment.

En pratique, la clôture d’historique nous permet aussi de journaliser sur la mémoire stable tous les messages en transit en une seule fois. En effet, un état global devient recouvrable, donc utilisable pour une reprise de l’application, à par-tir du moment où l’historique nécessaire est associé à chaque point de reprise le constituant. Donc, il n’est pas utile de journaliser en mémoire stable les messages identifiés en transit tant que l’historique n’est pas clos. En pratique, ces messages sont journalisés dans la mémoire volatile du récepteur, puis envoyé en une seule fois sur la mémoire stable avec l’historique. Les réponses sont placés dans le jour-nal Rn

i prévu à cet effet, mais il n’est pas nécessaire d’avoir un journal pour les requêtes : les requêtes en transit sont placées directement dans l’historique. En effet, il existe par définition une place dans l’historique pour tous les messages en transit, puisque l’historique se ferme lorsqu’il n’y a plus de message en transit. Ainsi, lors de la réexécution depuis un point de reprise, les requêtes en transit n’ont pas besoin d’être réémises ; elles sont déjà dans la queue des requêtes en attente de l’activité.