3.2. Una corrispondenza dinamica tra spazi continui e insiemi discreti
3.2.5. Garantire la consistenza degli alberi nel sistema distribuito
Volendo realizzare un sistema totalmente distribuito, abbiamo deciso di non creare un unico nodo del sistema responsabile della gestione degli alberi, bensì di demandare tale responsabilità ad ogni nodo del sistema. Appare evidente quindi la necessità di creare un protocollo che garantisca che tutte le operazioni
Capitolo 3: Trasformare un sistema topic-based in content-based
di modifica degli alberi vengano eseguite all’unisono da tutti gli attori del sistema coinvolti.
Le soluzioni che abbiamo realizzato si basano fondamentalmente sui principi di base del protocollo di commit a due fasi: prima di fare una modifica, l’attore chiede a tutti gli altri interessati se anche loro possono procedere con la stessa modifica; nel caso affermativo, tutti procedono alla modifica (commit), altrimenti nessuno la effettua (abort). Trasportando questo concetto nel nostro sistema, ogni attore, quando vuole modificare il suo albero, lo notifica a tutti gli attori coinvolti; dopodiché o tutti effettuano questa modifica oppure nessuno. La prima cosa da fare per realizzare tale protocollo è capire quali sono le operazioni che vanno a modificare gli alberi: da quanto detto finora, appare evidente che le uniche operazioni sono quelle definite dai protocolli di discretizzazione, ovvero il protocollo di creazione di un nuovo livello (ALGORITMI 1 e 2) e quello di controllo di necessità di un livello (PROTOCOLLO 1).
Il passo successivo è creare un meccanismo che abiliti ogni attore del sistema a decidere se può procedere o meno all’esecuzione di una particolare operazione sull’albero. Riprendendo quanto gi{ detto precedentemente nel paragrafo 3.2.2, ovvero che ogni sottospazio è indipendente da ogni altro, a meno che non ci sia una relazione padre-figlio, abbiamo deciso di creare un meccanismo di locking dell’albero con una granularit{ del singolo nodo, ovvero del singolo sottospazio. Ogni volta che un algoritmo può portare alla modifica di un sottospazio, l’algoritmo deve bloccare il nodo associato prima di procedere acquisendo il lock del nodo; se l’algoritmo riesce ad acquisire il lock, allora procede, altrimenti termina.
Creato il meccanismo di locking dell’albero, vediamo come esso debba essere utilizzato dalle operazioni di modifica precedentemente individuate per garantire una continua consistenza tra gli alberi di ogni attore del sistema Publish-Subscribe distribuito.
Capitolo 3: Trasformare un sistema topic-based in content-based
Per quanto riguarda la creazione di un nuovo livello, quando un attore riceve un evento, e conseguentemente decide di discretizzare (passo 3 dell’algoritmo 1), prima di inviare il messaggio di discretizzazione al resto del sistema, deve acquisire il lock associato al nodo che vuole discretizzare. Se non riesce ad acquisire il lock, e questo significa che il nodo è bloccato da un’altra operazione di modifica, l’algoritmo 1 termina, altrimenti prosegue normalmente. Quando un attore invece riceve un messaggio di richiesta discretizzazione, prima di procedere (passo 1 dell’algoritmo 2), prova ad acquisire il lock per il nodo associato alla richiesta. Se non riesce ad acquisire il lock, allora l’attore invia un messaggio di abort sullo stesso topic dal quale ha ricevuto la richiesta. In questo modo tutti i nodi coinvolti in questa richiesta annullano il processo di discretizzazione, terminando l’esecuzione dell’algoritmo 2. Se invece l’attore riesce ad acquisire il lock, prima di proseguire eseguendo il passo 1 dell’algoritmo 2, attende un tempo pari a 2t, tempo necessario per ricevere eventuali abort da altri attori coinvolti.
Apportando queste modifiche agli algoritmi 1 e 2, siamo sicuri che un’operazione di discretizzazione o viene eseguita da tutti i nodi interessati oppure, se qualche nodo non è in grado di eseguire l’operazione perché sta eseguendo altre operazioni sullo stesso nodo, non viene eseguita da nessuno. Per quanto riguarda invece il protocollo di controllo di necessità di un livello, sia i publisher, prima di eseguire il passo 1 dell’algoritmo 3, sia i subscriber, quando ricevono il primo messaggio contenente la distribuzione degli eventi (passo 3 dell’algoritmo 3), provano ad acquisire il lock su tutti i nodi del livello da controllare, sia tutte le foglie che il padre di queste ultime. Se un attore non riesce ad acquisire i lock su tutto il livello, invia un NOK per tale livello, facendo quindi abortire il controllo anche a tutti gli altri attori coinvolti. Se invece un attore riesce ad acquisire i lock su tutto il livello, allora il protocollo di controllo prosegue normalmente. In questo modo il controllo di un livello, o viene eseguito da tutti gli attori coinvolti, oppure, se qualche attore non può controllare il livello perché sta eseguendo altre operazioni sulle foglie, come ad
Capitolo 3: Trasformare un sistema topic-based in content-based
esempio la creazione di un nuovo livello, il controllo non viene eseguito da nessun attore.
Con l’introduzione di un meccanismo di locking dei nodi e la modifica degli algoritmi precedentemente presentati, siamo quindi riusciti a realizzare un sistema completamente distribuito che mantiene nel tempo la consistenza tra le sue strutture dati, regolando i metodi di accesso ad esse. Con questo abbiamo terminato la presentazione del livello di mapping. Nel paragrafo successivo sarà presentato il livello più esterno dell’architettura, responsabile della definizione dell’interfaccia basata su contenuti. Vedremo inoltre come anche questo livello dovrà necessariamente interfacciarsi con il meccanismo appena presentato per continuare a garantire la consistenza tra gli alberi.