Distinguiamo le classi utilizzate nel codice in:
1. Managers, utilizzati per gestire determinate funzioni dell’applicazione. Tra questi distinguiamo:
• il TestManager, il quale si occupa di memorizzare la mappa relativa alla relazione tra numero di messaggi e l’hitratio corrispondente, informazioni necessarie in fase di test di accuratezza dell’algoritmo.
• il DelaunayCorrectnessManager, il quale si occupa di controllare la correttezza della triangolazione di Delaunay distribuita tramite il metodo checkNeighborsFi- les(String oracoloFile, String neighborDistrFile), il quale riceve in input due file xml rappresentanti i vicini di un nodo n per l’oracolo e per l’algoritmo e restitui- sce il numero di differenze tra questi due file. Un esempio della struttura adottata dall’xml è: <?xml version=" 1 . 0 " ?> <Node Nodo=" 3 "> <C o o r d i n a t e s>8 0 9 , 4 2 4 3</ C o o r d i n a t e s> <N e i g h b o u r s> <Neighbour>9 8 2 , 4 0 2 4</ Neighbour> <Neighbour>1 0 4 5 , 4 7 1 5</ Neighbour> <Neighbour>7 6 9 , 4 4 3 8</ Neighbour> <Neighbour>7 1 7 , 4 1 7 3</ Neighbour> <Neighbour>6 6 1 , 4 4 4 5</ Neighbour> </ N e i g h b o u r s> </Node>
• il NearestNeighborCorrectnessManager, utilizzato per verificare la correttezza del calcolo del nearest neighbor per ogni nodo nel caso in cui al tempo t in cui avviene questo calcolo la triangolazione di Delaunay non sia corretta (non garantendo quindi che il greedy routing funzioni).
• il PointsManager, il quale è incaricato di effettuare lo scanning del file dei nodi in input e crearne un Array di DTPoint. Tali punti verranno assegnati ai nodi della rete in fase di inizializzazione del protocollo InetInitializer.
2. Inizializzatori, protocolli con lo scopo di inizializzare la rete prima dell’esecuzione del- l’algoritmo. L’unico inizializzatore utilizzato è InetInitializer, il quale ha lo scopo di assegnare ai vari nodi della rete le coordinate (X, Y) salvate dal PointsManager nel vettore di DTPoints utilizzando il protocollo InetCoordinates.
3. Controlli, utilizzati per effettuare determinate operazioni su tutti i nodi della rete a determinati cicli. In questo caso, ho utilizzato i controlli di PeerSim per implementare il churn della rete e l’inserzione dei nodi. Il controllo relativo all’inserimento dei nodi nella rete permette di settare una variabile di istanza per definire il numero di nodi che effettuano la fase di join in modo concorrente. Tale variabile, se settata a 1, definisce
un inserimento dei nodi sequenziale, con lo scopo di poter effettuare test su nodi che effettuano delle join sequenziali nella rete. I controlli utilizzati sono:
• il NodeInsertionControl, che memorizza la variabile N U M _CON CU RREN CY utilizzata per impostare il grado di concorrenza utilizzato per l’inserimento dei nodi nella rete, e finché sono presenti nuovi nodi da aggiungere alla rete permette a questi di effettuare la Join, inviando il messaggio opportuno al bootstrapNode. • il LeaveControl, il quale si occupa della simulazione del churn della rete: esso
permette l’uscita e l’entrata dei nodi all’interno della rete utilizzando le seguenti costanti:
(a) J OIN _P ROBABILIT Y , la quale definisce la probabilità che un nodo n non attivo nella rete ha di effettuare la join.
(b) LEAV E_P ROBABILIT Y , la quale definisce la probabilità che un nodo n arrivo nella rete ha di effettuare la leave.
Inoltre, la classe LeaveControl permette il controllo del numero di nodi che escono dalla rete direttamente dal file di configurazione di PeerSim utilizzando la variabile privata numN odesT oLeave.
• il PeriodicTimer, controllo che simula il timer del protocollo di manutenzione scaduto. Ogni volta che il metodo execute() di tale controllo viene invocato, il metodo timerExpired() della classe ACEP rotocol viene eseguito.
• il CheckDeadNodesControl, il quale si occupa della simulazione del timer scaduto per i nodi ai quali si era fatta richiesta di vicini in fase di manutenzione.
4. Osservatori, i quali osservano determinati valori per i nodi della rete. Le classi imple- mentate tra gli osservatori sono:
• la classe CoordinatesObs, la quale in fase di inizializzazione stampa i valori delle coordinate dei nodi che effettueranno la join nella rete.
• la classe AccuracyObserver, la quale si occupa di stampare nei files numMessagesFi- le.txt e accuracyValuesFile.txt i valori hitRatio e numero di messaggi memorizzati nelle strutture dati del TestManager. Tali files verranno utilizzati come raccolta dei dati per la stampa dei grafici in fase sperimentale.
• la classe NeighborsObserver, che ha il compito di stampare su files xml i vicini di ogni nodo, i quali sono utilizzati dal DelaunayCorrectnessManager per effettuare il test di correttezza della triangolazione di Delaunay distribuita calcolata. 5. Protocolli, che implementano l’algoritmo vero e proprio. Questi saranno descritti nei
5.3.1 DTTransport e DDTNode
La classe DT T rasport implementa il protocollo T ransport di PeerSim. In particolare, la classe ReliableT ransport di PeerSim definisce un protocollo di trasporto affidabile, che co- munque consente di impostare eventuali ritardi tramite valori numerici definiti nel file di configurazione.
La classe DT T rasport estende la classe che definisce il protocollo affidabile di trasporto di PeerSim, ed inoltre richiama l’istanza condivisa della classe T estM anager per incrementare il contatore dei messaggi inviati ogni volta che il metodo send() viene invocato. Questo viene utilizzato in fase di test.
La classe DDT N ode estende la classe GeneralN ode di PeerSim e viene utilizzata per model- lare i nodi della rete. Essa fornisce le interfacce pubbliche compareT o() e isBootstrapN ode(), la prima utilizzata per confrontare due nodi e l’altra per verificare se il nodo corrente è il nodo di bootstrap (utilizzato in fase di join).
Figura 5.1: Classe DDTNode.java
5.3.2 Messaggi
Per la simulazione è stata implementata una classe per ogni messaggio descritto all’interno del paper di Lee [21]. In più, sono stati implementati i nuovi messaggi descritti nel capitolo precedente per New ACE. In particolare, i messaggi implementati per l’algoritmo originale ACE sono:
• Delete • JoinQuery • JoinAnswer
• Leave
• NeighborNotification • NeighborSetReply • NeighborSetRequest • Remove
I messaggi utilizzati nell’implementazione di New ACE sono: • Delete • JoinQuery • JoinAnswer • Leave • NeighborReply • NeighborRequest • Acknowledge • Remove
Al fine di evitare codice duplicato e utilizzare degli identificatori per determinare il tipo di messaggio ricevuto, tutte queste classi estendono la classe AceEvent, la quale rappresenta un messaggio generico utilizzato nell’algoritmo ACE e ne permette l’identificazione tramite l’utilizzo di un tipo enumerato. La figura 5.2 descrive l’implementazione della classe.
Figura 5.2: La classe AceEvent
5.3.3 GreedyNearestNeighbor
La classe GreedyN earestN eighbor implementa il protocollo utilizzato per trovare il vici- no più vicino dei nodi nella rete utilizzando l’algoritmo greedy. Attraverso tale protocol- lo sono inviati i messaggi J oinQuery e J oinAnswer. Le azioni che ogni nodo compie alla ricezione di tali messaggi sono definiti nei metodi privati processJ oinQueryEvent e processJ oinAnsweEvent.
Figura 5.3: Diagramma di flusso alla ricezione del messaggio di JoinQuery per la classe GreedyNearestNeighbor
La Figura 5.3 descrive il comportamento della classe GreedyNearestNeighbor nel momen- to in cui viene invocato il metodo processJ oinQueryEvent(): se il nodo contenitore del protocollo (che riceve il messaggio) è il nodo di bootstrap, viene simulato l’avvio dell’algorit- mo greedy per trovare il nodo più vicino scegliendo un nodo a caso nella rete e inoltrandogli il messaggio J oinQuery() ricevuto. Se non ci sono nodi nella rete (il nodo di bootstrap ne è consapevole), allora viene comunicato al nodo entrante che è il primo nodo della rete, me- diante l’invio di un messaggio J oinAnswer(null).
Se il nodo contenitore c del protocollo non è il nodo di bootstrap, allora cerca tra i suoi vicini un nodo v più vicino al nodo entrante: se esiste un nodo w più vicino di c a v, c inoltra il messaggio J oinQuery() ricevuto a w, altrimenti significa che c è il nodo più vicino a v, quindi risponde con un messaggio J oinAnswer(c).
Alla ricezione di un messaggio JoinAnswer, il nodo contenitore setta la propria vista locale e invia al nodo più vicino un messaggio N eighborRequest() sul protocollo ACEP rotocol.
5.3.4 ACELinkable
ACELinkable implementa la vista dei nodi della classe DT N ode nella simulazione. Essa fornisce le seguenti istanze:
• neighbors, di tipo ArrayList < DDT N ode >, utilizzata per memorizzare la lista dei vicini nella triangolazione di Delaunay. Da tale lista sono presi i dati per stampare i
files xml utilizzati in fase di test.
• candidateSet, di tipo ArrayList < DDT N ode >, utilizzata per memorizzare la Can- didate Set.
• querriedN eighbors, di tipo ArrayList < DDT N ode >, non utilizzata in New ACE ma usata per effettuare dei confronti di accuratezza tra ACE e New ACE.
• receivedAnswers, di tipo LinkedHashM ap < DDT N ode, Boolean >, utilizzata per tener traccia dei nodi da cui si è ricevuta risposta dopo che è stato invocato il protocollo di manutenzione, in modo da eliminare eventuali nodi usciti dalla rete.
Oltre ai metodi getter e setter, la classe fornisce il metodo getM utualN eighbors(N ode w), il quale restituisce i nodi vicini in comune tra w e il nodo corrente.
5.3.5 ACEProtocol
La classe ACEP rotocol implementa l’interfaccia EDP rotocol di PeerSim e rappresenta l’im- plementazione dell’intero algoritmo ACE, poiché a parte i messaggi JoinQuery() e JoinAn- swer() intercetta e gestisce tutti gli altri messaggi inviati.
La classe implementa i metodi che gestiscono la ricezione dei messaggi in ACE originale e New ACE. Tali metodi sono invocati tramite il metodo processEvent(), definito nell’interfac- cia EDProtocol di PeerSim, il quale simula la ricezione di un messaggio tramite il protocollo di Trasporto utilizzato nella simulazione.
Oltre a questi metodi, la cui implementazione segue fedelmente la descrizione del Capitolo 3, la classe ACEProtocol fornisce una serie di metodi che vanno menzionati:
• il metodo periodicT imerExpired(), invocato dalla classe periodicTimer per la simula- zione dello scadere del timer periodico che invoca l’esecuzione del protocollo di manu- tenzione;
• i metodi ausiliari privati che permettono di ricavare i nodi vicini di un nodo dalla triangolazione di Delaunay vista come un insieme di triangoli e un insieme di archi, tra i quali:
– il metodo computeNeighborsInDelaunayTriangulationForNodeAndPoints(), con pa- rametri u e candidateSet, il quale ha il compito di aggiornare la triangolazione di Delaunay locale del nodo u utilizzando candidateSet e di restituire la lista di vicini di u;
– il metodo computeSetOfTriangleThatContainsNButDontContainsAnyQuerriedNo- de(), con parametri u e querriedN odes, il quale ha il compito di calcolare la lista di triangoli che contengono il nodo u ma non contengono alcun nodo nella lista querriedN odes
5.3.6 InetCoordinates
La classe InetCoordinates rappresenta il protocollo che gestisce le coordinate geografiche assegnate ai nodi: in particolare, le variabili di istanza implementate sono:
• la variabile x, di tipo BigInteger, per la memorizzazione della latitudine associata al nodo contenitore;
• la variabile y, di tipo BigInteger, per la memorizzazione della longitudine associata al nodo contenitore.