Laboratorio di Sistemi Distribuiti Leonardo Mariani ELECTION ALGORITHMS In molti sistemi distribuiti un processo deve agire da (o svolgere un ruolo particolare) per gli altri processi. Spesso non è importante quale processo assuma il ruolo di, ma è importante che ce ne sia sempre uno. Gli Election Algorithms sono usati per eleggere un nuovo quando il attuale smente di funzionare. In questa esercitazione implementeremo due algoritmi (Bully Algorithm e Ring Algorithm) usando Java RMI. Attività preliminare (per entrambi gli algoritmi): - creare un file di configurazione con l elenco dei calcolatori disponibili ed il loro numero IP. Ogni calcolatore è indicato attraverso un identificatore numerico univoco che è dato dall ultima cifra del numero IP. - il calcolatore con il valore dell ID più grande è il (convenzione che viene rispettata anche dopo il fallimento del ) Bully Algorithm StartUp: - leggere la lista di calcolatori dal file di configurazione e memorizzare il
- registrare l oggetto remoto che si interfaccia con gli altri processi nell object registry, usare bully come identificatore - recuperare un reference remoto per ogni calcolatore del sistema (se un oggetto remoto non è temporaneamente disponibile aspettare indefinitamente che lo diventi) Running: - inviare un ping() al ad intervalli di tempo fissati Thread.sleep(ms) - Ricezione Ping: rispondi con return - Eccezione nell invio del ping (fallimento del ) => Attiva fase di elezione Elezione: - inviare un elect() a tutti i calcolatori con identificatore superiore al proprio o ricezione di almeno una risposta => non fare nulla, non sei tu il prossimo o ricezione di nessuna risposta => vai alla fase di coordinazione, sei il prossimo - Ricezione election: rispondi con return, ed invia un messaggio di elect() a tutti i calcolatori con identificatore superiore al proprio Coordinazione: - inviare coordinator(this) a tutti i calcolatori per informarli dell identità del nuovo - Ricezione coordinator(): aggiorna l identità del attuale, rimuovi i calcolatori con identificatore maggiore del dalla lista dei calcolatori del sistema INTERFACCIA DI UN BULLYSERVER: package bullyalgorithm.interfaces; import java.rmi.remote; import java.rmi.remoteexception; public interface BullyServerInterface extends Remote{ public void ping() throws RemoteException; public void elect()throws RemoteException; public void coordinator(bullyserverinterface bs) throws RemoteException; public String getname() throws RemoteException;
Ring Algorithm StartUp: - leggere la lista di calcolatori dal file di configurazione e memorizzare il - registrare l oggetto remoto che si interfaccia con gli altri processi nell object registry, usare ring come identificatore - recuperare un reference remoto per ogni calcolatore del sistema (se un oggetto remoto non è temporaneamente disponibile aspettare indefinitamente che lo diventi) - i nodi sono ordinati in base al loro identificatore Running: - inviare un ping() al ad intervalli di tempo fissati Thread.sleep(ms) - Ricezione Ping: rispondi con return - Eccezione nell invio del ping (fallimento del ) => Attiva fase di elezione Elezione: - inviare un messaggio di election(em) al nodo successivo (se il nodo successivo non risponde provare con quello che segue, si faccia l ipotesi che esista sempre almeno un nodo che risponde) con dentro proprio ID - Ricezione Election: controllare se il proprio ID è nel messaggio, o No -> aggiungere il proprio id al messaggio ed inoltrarlo o SI -> vai alla fase di coordinazione, il messaggio ha già fatto un giro Coordinazione: - invia messaggio coordinator(cm), cm è ottenuto copiando il contenuto del messaggio em - Ricezione Coordinator: il è il nodo di massimo identificatore contenuto in cm o se il è nuovo -> memorizzare l identità del nuovo, aggiornare il set di computer disponibili, ed inoltrare il messaggio al nodo successivo o se il non è nuovo -> il messaggio ha compiuto un giro e quindi deve essere scartato ELECTION MESSAGE: package ringalgorithm.messages; import java.util.enumeration; import java.util.vector; public class ElectionMessage implements java.io.serializable{
private Vector nodes; public void addnodeid(string id) { nodes.add(id); public Enumeration getnodelist() { return nodes.elements(); public boolean existnodeid(string id) { return (nodes.indexof(id)!=-1); COORDINATOR MESSAGE package ringalgorithm.messages; import java.util.enumeration; import java.util.vector; public class CoordinatorMessage implements java.io.serializable{ private Vector nodes; public CoordinatorMessage(ElectionMessage em) { Enumeration e = em.getnodelist(); while (e.hasmoreelements()) { nodes.add(e.nextelement()); public Enumeration getnodelist() { return nodes.elements(); public String getmaxid() { if (nodes.size()<=0) return null; int maxid = -1; Enumeration e = getnodelist(); while (e.hasmoreelements()) { int value = Integer.parseInt((String)e.nextElement()); if (value > maxid) maxid = value; return String.valueOf(maxId); RING SERVER: package ringalgorithm.interfaces;
import java.rmi.remote; import java.rmi.remoteexception; public interface RingServerInterface extends Remote{ public void ping() throws RemoteException; public void elect(electionmessage em)throws RemoteException; public void coordinator(coordinatormessage cm) throws RemoteException; public String getname() throws RemoteException; COLLAUDO DEGLI ALGORITMI: Operazione preliminare: inserire delle istruzioni di output che stampano l elenco dei nodi del sistema e l identità del ogni volta che sono modificati. Esecuzioni: - Inserire valori differenti dell intervallo di ping per i vari calcolatori. Dopo lo startup il arresta il processo. Verificare che il nuovo sia selezionato opportunamente. - Inserire in tutti i calcolatori lo stesso intervallo di ping (scegliere un valore piccolo). Dopo lo startup il arresta il processo. Verificare che il nuovo sia selezionato opportunamente. - Far fallire il primo, eleggere quindi il successivo. Arrestare il appena eletto e verificare che si ottenga un nuovo. Continuare così fino a che non sopravvivono solamente due calcolatori. - Dopo lo startup arrestare i due nodi che non sono coordinatori con identificatore più alto. A questo punto arrestare il e verificare che il nuovo sia eletto correttamente.