• Aucun résultat trouvé

5.2 Cas d’étude et modèle de fautes

5.3.1 Protocole client-serveur

Dans ce protocole duplex simple, nous ne faisons pas l’hypothèse d’un service de com- munication de groupe fournissant la diffusion atomique de message. Ainsi le client s’adresse au serveur primaire et en cas de défaillance de celui-ci s’adresse au serveur secondaire. Nous faisons donc l’hypothèse que les ports de communication du primaire et du secondaire sont connus a priori du client. Rappelons aussi que l’on se place dans un système synchrone, à sa- voir que tout message est reçu dans un intervalle de temps borné en l’absence de crash.

5.3.1.1 Préoccupations transversales coté client

Dans le protocole duplex primary-backup lorsque le serveur primaire défaille, le serveur secondaire prend le relais. Le client qui n’a pas reçu de réponse à sa requête la renvoie. Le se- condaire la reçoit. Le serveur secondaire ne doit alors pas exécuter la requête si elle a déjà été exécutée afin de préserver l’intégrité du système. La requête ne doit être exécutée qu’une seule fois (only once semantics). Pour ce faire, il est nécessaire d’ajouter un numéro de séquence à la requête et un identifiant de client. Grâce à ces informations le serveur secondaire sait si pour un client donné (identifiant client) une requête donnée (numéro de séquence de requête) a déjà été traitée. Du côté client, il est donc nécessaire d’ajouter aux requêtes ces informations sup- plémentaires en plus du nom du service demandé. Ces identifiants sont uniques. De la même manière à la réception de la réponse les informations ajoutées à l’envoie doivent être retirés de la réponse afin que celle-ci soit traitée. Le client doit également gérer la réception des réponses et prendre des décisions en ce qui concerne la disponibilité du serveur. En effet lorsque le client

ne reçoit pas de réponse à une requête après un certain délai, le serveur est considéré comme défaillant. Les requêtes sont alors envoyées au serveur secondaire.

1 Variables du protocole :

2 adresse primaire

3 adresse secondaire

4

5 Boucle client {

6 ajouter numero de sequence de requete

7 ajouter identifiant client

8 envoi de la requete au serveur

9 enregistrement de la requete dans le cache

10 armement du minuteur

11 tant que reponse=null {

12 si ( minuteur∑ 0) { exception }

13 si ( minuteur> 0) { reception de la reponse

14 si ( reponse6= null ) {

15 arret du minuteur ,

16 retirer numero de sequence de reponse

17 }

18 } 19 }

20 traitement de la reponse

21 }

Listing 5.1 – Algorithme exécuté coté client

Toutes les lignes excepté les lignes 8 et 20 du listing5.5sont des préoccupations transver- sales. Il convient donc de les encapsuler dans des aspects afin de les séparer des préoccupations fonctionnelles implémentées par les lignes 8 et 20.

5.3.1.2 Aspects côté client

Les différentes préoccupations transversales identifiées dans le listing5.5peuvent être en- capsulées dans différents aspects.

Les préoccupations des lignes 7 et 16 sont encapsulées dans un aspect dédié à la gestion de l’ajout et de la suppression du numéro de séquence de requête. Cet aspect est nommé ANum- bering contient deux greffons insert et remove dont les rôles sont les suivants :

– ANumbering.insert : ajoute un numéro de séquence à la requête ; – ANumbering.remove : supprime le numéro de séquence de la réponse ;

Celle de la ligne 7 est encapsulée dans un aspect dédié à la gestion des identifiants de client (AIdentifier). Cet aspect contient un greffon dont le rôle est le suivant :

– AIdentifier.insert : ce greffon ajoute l’identifiant du client à la requête avant qu’elle ne soit envoyée.

Un troisième aspect nommé ACacheManager.addIn encapsule les préoccupations transver- sales de la ligne 9. Cet aspect contient un greffon nommé ACacheManager.addIn dont le rôle est le suivant :

– ACacheManager.addIn : ce greffon est chargé de sauvegarder les requêtes envoyées dans une structure de données afin de permettre le renvoi des requêtes pour lesquelles aucune réponse n’a été reçue. Il ajoute dans une structure de données l’identifiant de la requête,

son contenu et un minuteur.

Ce greffon permet le renvoi au serveur secondaire d’une requête pour laquelle il n’y a pas eu de réponse de la part du serveur primaire pour cause de défaillance. Si l’on se réfère au com- portement décrit par les lignes 11 à 19 lors de l’attente de la réponse à une requête, le client vérifie que le temps d’attente imparti pour une requête n’est pas dépassé par le biais du mi- nuteur affecté à la requête ; si ce denier est dépassé une exception est soulevée. Le client passe alors au traitement de la requête suivante dans sa liste de requêtes à traiter. Or il faut renvoyer la requête pour laquelle aucune réponse n’a été reçue du serveur primaire au serveur secondaire. Ce greffon et la structure de données utilisée contribuent à réaliser ce comportement.

Le renvoi de la requête est géré par un aspect nommé ARequestResend. Il encapsule cette préoccupation transversale. Cet aspect contient un greffon nommé ARequestResend.reload dont le rôle est le suivant :

– ARequestResend.reload : est chargé de recharger en tête de liste des requêtes à envoyer la requête envoyée pour laquelle qui n’a pas reçu de réponse.

L’expression de coupe de ARequestResend capture la levée de l’exception liée au dépassement du temps imparti par le minuteur. Le comportement du greffon ARequestResend.reload est décrit dans le listing5.2.

Le greffon ACacheManager.addIn détaillé ci-dessus ajoute dans une structure de données les informations liées à une requête et un objet minuteur. Le minuteur fournit une interface proposant deux opérations :

– start() le minuteur commence le décompte à partir de la valeur avec laquelle il a été ini- tialisé ;

– stop() le décompte du minuteur est arrêté.

Un quatrième aspect (ATimer) est donc dédié la gestion de ce minuteur. Il qui contient deux greffons start et stop. Il encapsule les préoccupations des lignes 10 et 16. Les rôles respectifs de ces greffons sont les suivants :

– ATimer.start : appelle l’interface start() du minuteur référencé dans la structure de don- nées, qui décompte un certain temps au bout duquel la réponse liée à une requête en- voyée au primaire doit être reçue.

– ATimer.stop : arrête le minuteur lorsqu’une réponse pour une requête donnée est reçue. Ces différents aspects sont appliqués autour de deux points de jonction, les méthodes send() et receive(). Chaque aspect effectue une action permettant de composer le comportement at- tendu du client dans le protocole de réplication duplex. Nous reviendrons plus en détail sur la composition de ces aspects dans la section5.4.

1 exception {

2 recuperation de la requete dans le cache

3 changement d adresse serveur

4 retour a la boucle client

5 }