Presentazione del progetto di: Reti di calcolatori L-S Matteo Corbelli Sommario Obiettivi Descrizione del Sistema Implementazione Conclusioni Obiettivi Realizzazione un’infrastruttura per la locazione di file nel distribuito Assegnamento di una chiave per ogni file Ricerca per tale chiave del nodo responsabile e allocazione Implementazione delle operazioni di gestione dei nodi del sistema Join Leave Architettura del Sistema L’architettura è quella di un anello “identifier circle” La posizione di un nodo è data dall’identificativo assegnatole dalla funzione hash Ogni chiave k viene assegnata al primo nodo il cui identificativo è uguale o segue k nello spazio degli identificativi Struttura di un nodo Ogni nodo ha la seguente struttura • Successore • Predecessore • Finger Table: tabella di m elementi (serve per l’efficienza dell’algoritmo) • Vettore delle chiavi di cui il nodo è responsabile I-esimo elemento della finger table Finger[i].start = (n+2i-1)mod 2m Finger[i].interval = [finger[i].start,finger[i+1].start) Finger[i].node = primo nodo maggiore o uguale a finger[i].start Funzionalità del Sistema Locazione di una chiave Join di un nodo n Leave di un nodo Locazione di una chiave Ogni id di una chiave k viene assegnato al nodo successore successor(k) Le richieste possono essere passate lungo l’anello attraverso i successori Utilizzo delle Finger Table Cosa succede se il nodo n non conosce il successore di k? Es. nodo 3 vuole trovare successor(1) Inefficienza (potrebbe richiedere di esplorare tutto l’anello) Implementazione della locazione Allocazione di un dato, con identificativo keyId, attraverso l’indirizzo di un nodo n della rete conosciuto Richiesta find_successor_key(keyId) al nodo n per trovare il successore di keyId n restituisce l’i-esimo finger per cui keyId appartiene a finger[i].interval a cui inoltrare una nuova richista redirect_request(n.finger[i]) Caso 1: keyId non compreso tra l’id del nodo e l’id del suo successore Caso 2: keyId compreso tra l’id del nodo e l’id del suo successore 1. n restituisce il successore find(n.successor) 2. viene effettuato sul nodo restituito il trasferimento del dato transfer(keyId) Join di un nodo n Ogni nodo n che entra nel sistema deve eseguire tre fasi: 1. 2. 3. Inizializzare predecessore, successore e Finger Table Aggiornare Finger Table, successori e predecessori per riflettere l’aggiunta di n Notificare a livello software più alto in modo che si possa trasferire lo stato associato alle chiavi di cui il nodo n ora è responsabile Implementazione del Join Inizializzazione predecessore, successore e Finger Table da parte del nodo con identificativo nodeId attraverso il nodo conosciuto n 1. 2. 3. 4. 5. 6. Richiesta find_predecessor(nodeId) al nodo n per trovare il predecessore di nodeId Ricezione del nodo che precede e del suo successore find(n, n.successor) Inizializzazione del predecessore a n e del successore a n.successor Aggiornamento del predecessore set_successor(this) Anticipati per Aggiornamento del successore set_predecessor(this) evitare overhead di comunicazione Inizializzazione della Finger Table n controlla se l’i-esimo finger è anche l’i+1-esimo finger corretto, per ogni i. Questo avviene quando finger[i].interval non contiene alcun nodo, e quindi finger[i].node >= finger[i+1].start Implementazione del Join Aggiornamento delle Finger Table dei nodi del sistema Il nodo n diventerà l’i-esimo finger del nodo p se e solo se: 1. p precede n di almeno 2i-1 Calcola id=n-2i-1 e ricerca il suo predecessore find_predecessor(id) 2. l’i-esimo finger del nodo p succede n Verifica positiva 1. Modifica dell’i-esimo finger 2. Restituzione del predecessore (iterazione dell’operazione) Verifica negativa 1. Terminazione Al nodo restituito invia la richiesta di aggiornamento update_finger_table(this,i) Il nodo verifica se l’i-esimo finger deve essere modificato (l’id del nuovo nodo è compreso tra il proprio id e quello dell’i-esimo finger) Implementazione del Join Notifica per il trasferimento di file 1. Connessione al successore (attuale responsabile di tutte le chiavi che potrebbero migrare nel nodo n) update_vector_key(this.id) 2. Il successore per ogni chiave che detiene verifica se è ancora sotto la sua responsabilità o meno 3. In caso non sia più suo compito tenere la chiave si passa al trasferimento transfer(keyId) Leave di nodo e implementazione Ogni nodo n quando lascia il sistema deve: 1. Rimuovere se stesso da successore e predecessore di altri nodi set_predecessor(this.successor) set_successor(this.predecessor) 2. Rimuovere i riferimenti a se dalle Finger Table (procedura simile a quella di aggiornamento) delete_me_from_finger_table(this.id,i,this.successor) 3. Trasferimento di tutti i propri dati al successore transfer_key(keyId) Conclusioni E’ stato sviluppato un sistema per la locazione di file nel distribuito Sviluppi Futuri 1. Tolleranza alla caduta di un nodo non volontaria 2. Implementazione di un algoritmo meno invasivo ma più efficiente in cui le finger table non vengono aggiornate ad ogni join ma ad istanti di tempo