Differences between revisions 1 and 4 (spanning 3 versions)
Revision 1 as of 2015-08-13 10:39:29
Size: 90
Editor: lukisi
Comment:
Revision 4 as of 2015-09-05 09:37:04
Size: 16252
Editor: lukisi
Comment:
Deletions are marked like this. Additions are marked like this.
Line 4: Line 4:
== Idea generale == == Requisiti ==
L'utilizzatore del modulo Coordinator inizializza il modulo richiamando il metodo statico ''init'' di !CoordinatorManager. In tale metodo viene anche passata l'istanza di INtkdTasklet per fornire l'implementazione del sistema di tasklet.

Quindi il nodo istanzia il suo !CoordinatorManager passando al costruttore:
 * ''peers_manager''. L'istanza di !PeersManager.
 * ''map''. La mappa delle posizioni libere.

Quando il nodo ha completato la fase di bootstrap, l'utilizzatore del modulo chiama il metodo ''bootstrap_complete'' del !CoordinatorManager.

Quando il nodo considera che la notifica della sua presenza abbia ormai raggiunto tramite ETP tutti i membri del g-nodo in cui è entrato, l'utilizzatore del modulo chiama il metodo ''presence_notified'' del !CoordinatorManager.

== Deliverables ==
Nel costruttore del !CoordinatorManager viene creata una istanza di !CoordinatorService (che descriveremo sotto) e viene registrata nel !PeersManager.

----
Il modulo permette di chiedere ad un vicino del nodo informazioni sui posti liberi nei suoi g-nodi con il metodo ''get_neighbor_map'' di !CoordinatorManager.

Il metodo ha come argomento lo stub per contattare il vicino. Prevede l'eccezione !StubNotWorkingError.

Restituisce una istanza di ICoordinatorNeighborMap.

----
Il modulo permette di chiedere ad un vicino del nodo di prenotare per lui un posto nel suo g-nodo di livello ''l'' con il metodo ''get_reservation'' di !CoordinatorManager.

Il metodo ha come argomento lo stub per contattare il vicino e il livello a cui fare richiesta. Prevede l'eccezione !StubNotWorkingError e l'eccezione !SaturatedGnodeError.

Restituisce una istanza di ICoordinatorReservation.

== Comunicazioni tra vicini ==
Quando il modulo vuole chiedere ad un vicino informazioni sui posti liberi nei suoi g-nodi usa il metodo remoto ''retrieve_neighbor_map''. Non ha argomenti. Non prevede eccezioni, oltre alle solite !StubError e !DeserializeError. Restituisce una istanza di ICoordinatorNeighborMapMessage.

L'interfaccia ICoordinatorNeighborMapMessage è un segnaposto (vuota) esposto dalla libreria intermedia di ZCD che espone il metodo remoto. L'interfaccia ICoordinatorNeighborMap è esposta dal modulo Coordinator e ha i metodi descritti nell'analisi. L'implementazione del metodo remoto crea una istanza della classe !NeighborMap. Questa è una classe serializzabile interna al modulo, che implementa entrambe le interfacce suddette.

----
Quando il modulo vuole chiedere ad un vicino di prenotare per lui un posto nel suo g-nodo di livello ''l'' usa il metodo remoto ''ask_reservation''. Ha come argomento il livello ''l''. Prevede l'eccezione !SaturatedGnodeError, oltre alle solite !StubError e !DeserializeError. Restituisce una istanza di ICoordinatorReservationMessage.

L'interfaccia ICoordinatorReservationMessage è un segnaposto (vuota) esposto dalla libreria intermedia di ZCD che espone il metodo remoto. L'interfaccia ICoordinatorReservation è esposta dal modulo Coordinator e ha i metodi descritti nell'analisi. L'implementazione del metodo remoto crea una istanza della classe Reservation. Questa è una classe serializzabile interna al modulo, che implementa entrambe le interfacce suddette.

== Servizio Coordinator ==
=== Classe server del servizio Coordinator ===
Il modulo deriva da !PeerService la classe !CoordinatorService.

Questa classe è interna al modulo. Contiene questi membri:
 * ''levels''. Intero. Il numero di livelli nella topologia della rete. Gli viene passato nel costruttore.
 * ''peers_manager''. Riferimento al !PeersManager. Gli viene passato nel costruttore.
 * ''retrieve_cache_done''. Booleano, inizializzato a ''False''.
 * ''my_presence_should_be_known''. Booleano, inizializzato a ''False''.
 * ''bookings''. Lista di liste di Booking. Memoria delle prenotazioni. Contiene ''levels'' elementi. L'elemento ''i''-esimo è la lista di prenotazioni attive per il nostro g-nodo di livello ''i''+1. La classe Booking ha una posizione (int ''pos'') e un time-to-live (Timer ''ttl''). E' una classe serializzabile e interna al modulo.
 * ''max_eldership''. Lista di int. Contiene ''levels'' elementi. L'elemento ''i''-esimo dice il valore più alto di progressione già assegnato ad una prenotazione per un nuovo g-nodo di livello ''i'' dentro il nostro g-nodo di livello ''i''+1. Un valore più alto significa che il g-nodo è arrivato dopo, cioè esso è più giovane.

Quando viene chiamato il metodo ''bootstrap_complete'' del !CoordinatorManager, la classe !CoordinatorService fa queste operazioni:
 * Riceve come argomento ''lvl'' il livello del g-nodo appena costituito dal nostro nodo.
 * Se ''lvl'' = ''levels'':
  * Imposta il suo flag ''retrieve_cache_done''.
 * Altrimenti:
  * In una nuova tasklet:
   * Avvia le operazioni di recupero dei record di sua pertinenza. Trattandosi di un servizio non opzionale, non attende l'evento ''!PeersManager.participant_maps_ready''.
   * Costruisce la richiesta ''r'' di tipo "retrieve_cache" dal livello ''lvl''+1 in su.
   * Avvia il primo recupero con il metodo ''!PeersManager.begin_retrieve_cache''
   . Attende l'esito, cioè il booleano restituito, la risposta ''resp'' da interpretare, l'oggetto IPeersContinuation ''cont'' da passare nelle chiamate successive.
   * Se ''resp'' ≠ ''null'':
    * Si accerta che ''resp.bookings.size'' = ''resp.max_eldership.size'' = ''levels - lvl''. Altrimenti emette un warning e ignora questa risposta.
    * Per ''i'' da 0 a ''resp.bookings.size-1'':
     * ''j'' = ''lvl + i''.
     * Per ogni Booking ''b'' ∈ ''resp.bookings[i]'':
      * Se ''b'' ∉ ''bookings[j]'':
       * Aggiungi ''b'' a ''bookings[j]''.
     * Se ''resp.max_eldership[i]'' > ''max_eldership[j]'':
      * ''max_eldership[j]'' = ''resp.max_eldership[i]''.
   * Se l'esito è ''True'':
    * While True:
     * Avvia un altro recupero con il metodo ''!PeersManager.next_retrieve_cache'' passando la IPeersContinuation ''cont''.
     . Attende l'esito, cioè il booleano restituito e la risposta ''resp'' da interpretare.
     * Se ''resp'' ≠ ''null'':
      * In base a ''resp'' modifica i propri membri ''bookings'' e ''max_eldership'', come sopra.
     * Se l'esito è ''False'':
      * Esci dal ciclo.
   * Al termine imposta il suo flag ''retrieve_cache_done''.

Quando viene chiamato il metodo ''presence_notified'' del !CoordinatorManager, la classe !CoordinatorService fa queste operazioni:
 * Imposta il suo flag ''my_presence_should_be_known''.

Il metodo ''is_ready()'' della classe !CoordinatorService si basa sui flag ''retrieve_cache_done'' e ''my_presence_should_be_known''.

==== Metodo reserve ====
Ricordiamo che quando una richiesta ad un servizio peer-to-peer viene ricevuta dall'hash_node viene chiamato il metodo ''exec'' della classe che deriva la !PeerService. Questa riceve una istanza di IPeersRequest e deve restituire una istanza di IPeersResponse.

Se il metodo ''exec'' della classe !CoordinatorService viene chiamato con una istanza di !CoordinatorRequest (si veda sotto) che ha il membro ''name'' = 'reserve' allora abbiamo ricevuto una richiesta di "prenota un posto nel tuo g-nodo di livello ''lvl''". Le operazioni da fare sono:
 * Se ci sono problemi a deserializzare gli argomenti viene fatta pervernire una eccezione !DeserializeError. Inclusi errori nei valori accettabili di ''lvl''.
 * Atomic on: queste operazioni devono essere eseguite atomicamente, senza permettere la schedulazione di altre tasklet.
 * Verifica nella mappa ''map'' del !CoordinatorManager quali posizioni sono libere nel livello ''lvl''. Se nessuna posizione risulta libera, lancia una eccezione.
 * Dalla lista ottenuta di posizioni libere, esclude quelle presenti nelle prenotazioni ''bookings(lvl-1)'' del !CoordinatorService. Nello scorrere questa lista, rimuove le istanze di Booking che sono scadute (membro ''ttl''). Se nessuna posizione risulta libera, lancia una eccezione.
 * Scegli una posizione ''pos''.
 * Segnala la prenotazione nella memoria. Cioè crea una istanza di Booking ''pos'' con ''ttl'' a 20 secondi (una {{{private const}}} nel codice) nella lista ''bookings(lvl-1)'' del !CoordinatorService.
 * Incrementa di 1 la ''max_eldership(lvl-1)'' nella memoria.
 * Con i dati in memoria prepara la risposta ''ret'' (pos=pos, eldership=max_eldership(lvl-1))
 * Atomic off.
 * Avvia la prima replica con il metodo ''!PeersManager.begin_replica''. Questi sono gli argomenti:
  . Come ''q'' mettiamo 15 (una {{{private const}}} nel codice).
  . Come perfect_tuple il valore ottenuto con il metodo ''perfect_tuple'' della classe !CoordinatorClient con la chiave ''lvl''.
  . Costruisce la richiesta ''r'' di tipo 'replica_reserve' per la posizione ''pos'' con anzianità ''eldership'' dentro il nostro g-nodo di livello ''lvl''.
 . Attende l'esito, cioè il booleano restituito, la risposta ''resp'' da interpretare, l'oggetto IPeersContinuation ''cont'' da passare nelle chiamate successive.
 . Il booleano restituito è ''False'' solo se si è avuta l'eccezione !NoParticipantsInNetwork. In questo caso si ignora la risposta ''resp''.
 . La risposta ''resp'' dovrebbe essere semplicemente OK, cioè una istanza di !CoordinatorReplicaReserveResponse con i membri a ''null''. Altrimenti va prodotto un warning descrittivo da usare nella fase di debug del modulo; quando il modulo è stabile questa situazione va semplicemente ignorata.
 * Se l'esito è ''True'':
  * Avvia la seconda replica con il metodo ''!PeersManager.next_replica'' passando la IPeersContinuation ''cont''.
  . Attende l'esito, cioè il booleano restituito e la risposta ''resp'' da interpretare.
  . Il booleano restituito è ''False'' solo se si è avuta l'eccezione !NoParticipantsInNetwork. In questo caso si ignora la risposta ''resp''.
  . La risposta ''resp'' dovrebbe essere semplicemente OK. Altrimenti va prodotto un warning descrittivo.
  * Se l'esito è ''True'':
   * Avvia una tasklet in cui:
    * While True:
     * Avvia una replica con il metodo ''!PeersManager.next_replica'' passando la IPeersContinuation ''cont''.
     . Attende l'esito, cioè il booleano restituito e la risposta ''resp'' da interpretare.
     . Il booleano restituito è ''False'' se abbiamo completato ''q'' repliche o se si è avuta l'eccezione !NoParticipantsInNetwork. In questo caso si ignora la risposta ''resp''.
     . La risposta ''resp'' dovrebbe essere semplicemente OK. Altrimenti va prodotto un warning descrittivo.
     * Se l'esito è ''False'':
      * Esci dal ciclo. Termina la tasklet.
 * Completa ''ret'' con (elderships=anzianità dei miei g-nodi da ''lvl'' in su)
 * Restituisce ''ret''.

==== Metodo replica_reserve ====
Se il metodo ''exec'' della classe !CoordinatorService viene chiamato con una istanza di !CoordinatorRequest (si veda sotto) che ha il membro ''name'' = 'replica_reserve' allora abbiamo ricevuto una richiesta di "replica per una prenotazione del posto ''pos'' con anzianità ''eldership'' nel nostro g-nodo di livello ''lvl''". Le operazioni da fare sono:
 * Se ci sono problemi a deserializzare gli argomenti viene fatta pervernire una eccezione !DeserializeError. Inclusi errori nei valori accettabili di ''lvl'' e ''pos''.
 * Atomic on.
 * Segnala la prenotazione nella memoria. Cioè crea una istanza di Booking ''pos'' nella lista ''bookings(lvl-1)'' del !CoordinatorService.
 * Se ''max_eldership(lvl-1)'' < ''eldership'':
  * Imposta ''max_eldership(lvl-1)'' = ''eldership''.
 * Atomic off.
 * Restituisce OK.

==== Metodo retrieve_cache ====
Se il metodo ''exec'' della classe !CoordinatorService viene chiamato con una istanza di !CoordinatorRequest (si veda sotto) che ha il membro ''name'' = 'retrieve_cache' allora abbiamo ricevuto una richiesta di "recupera i record delle prenotazioni dal livello ''lvl'' in su", con 0 < ''lvl'' ≤ ''levels''. Le operazioni da fare sono:
 * Se ci sono problemi a deserializzare gli argomenti viene fatta pervernire una eccezione !DeserializeError. Inclusi errori nei valori accettabili di ''lvl''.
 * Prepara ''ret'' con gli elementi da ''lvl''-1 in su della lista ''bookings'' di !CoordinatorService e con gli elementi da ''lvl''-1 in su della lista ''max_eldership'' di !CoordinatorService.
 * Restituisce ''ret''.

=== Classe client del servizio Coordinator ===
Il modulo deriva da !PeerClient la classe !CoordinatorClient.

Ridefinisce il suo metodo ''perfect_tuple''. La chiave che può essere usata per calcolare l'hash_node è un intero ''l'' da 1 a ''levels''. La lista di interi restituita è composta da ''l'' volte il valore 0.

=== Classi serializzabili per le comunicazioni ===
Viene definita la classe interna !CoordinatorRequest. Si tratta di una classe serializzabile che implementa l'interfaccia segnaposto (vuota) IPeersRequest. Serve per tutte le richieste che possono essere fatte al servizio. Tale classe contiene:
 * ''name''. Una stringa che identifica la richiesta. I valori possibili sono: ['reserve', 'retrieve_cache', 'replica_reserve'].
 * ''reserve_lvl''. Usato se ''name'' = 'reserve'. Un intero che indica il livello del g-nodo dentro il quale riservare un posto.
 * ''cache_from_lvl''. Usato se ''name'' = 'retrieve_cache'. Un intero che dice di passare i record da quel livello in su.
 * ''replica_lvl''. Usato se ''name'' = 'replica_reserve'. Un intero che dice il livello del g-nodo dentro il quale è stato prenotato un posto.
 * ''replica_pos''. Usato se ''name'' = 'replica_reserve'. Un intero che dice la posizione della prenotazione.
 * ''replica_eldership''. Usato se ''name'' = 'replica_reserve'. Un intero che dice l'anzianità del posto prenotato.

----
Viene definita la classe interna !CoordinatorReserveResponse. Si tratta di una classe serializzabile che implementa l'interfaccia segnaposto (vuota) IPeersResponse. Serve come risposta solo per la richiesta 'reserve'. Tale classe contiene:
 * ''error_domain''. Una stringa nullable.
 * ''error_code''. Una stringa nullable.
 * ''error_message''. Una stringa nullable. Queste sono tutte a ''null'' se l'esito è buono, mentre sono valorizzate se si vuole indicare una eccezione.
 * ''pos''. Un intero. La posizione assegnata.
 * ''elderships''. Una lista di interi. Le anzianità da ''l''-1 (del g-nodo appena assegnato) fino a ''levels''.

----
Viene definita la classe interna !CoordinatorReplicaReserveResponse. Si tratta di una classe serializzabile che implementa l'interfaccia segnaposto (vuota) IPeersResponse. Serve come risposta solo per la richiesta 'replica_reserve'. Tale classe contiene:
 * ''error_domain''. Una stringa nullable.
 * ''error_code''. Una stringa nullable.
 * ''error_message''. Una stringa nullable. Queste sono tutte a ''null'' se l'esito è buono, mentre sono valorizzate se si vuole indicare una eccezione.

Non ha altri membri da valorizzare se l'esito della replica è positivo.

----
Viene definita la classe interna !CoordinatorRetrieveCacheResponse. Si tratta di una classe serializzabile che implementa l'interfaccia segnaposto (vuota) IPeersResponse. Serve come risposta solo per la richiesta 'retrieve_cache'. Tale classe contiene:
 * ''error_domain''. Una stringa nullable.
 * ''error_code''. Una stringa nullable.
 * ''error_message''. Una stringa nullable. Queste sono tutte a ''null'' se l'esito è buono, mentre sono valorizzate se si vuole indicare una eccezione.
 * ''bookings''. Lista di liste di Booking. Essendo questa la risposta ad una richiesta di record per i livelli da ''lvl'' in su, l'elemento ''i''-esimo di questa lista va assegnato al membro ''bookings[i + lvl]'' della nostra memoria.
 * ''max_eldership''. Lista di int. L'elemento ''i''-esimo va assegnato al membro ''max_eldership[i + lvl]'' della nostra memoria.

----
Viene definita la classe interna !CoordinatorUnknownRequestResponse. Si tratta di una classe serializzabile che implementa l'interfaccia segnaposto (vuota) IPeersResponse. Serve come risposta per le richieste che non sono state riconosciute dall'implementazione del server. Tale classe non contiene nulla.

Modulo Coordinator - Dettagli Tecnici

Requisiti

L'utilizzatore del modulo Coordinator inizializza il modulo richiamando il metodo statico init di CoordinatorManager. In tale metodo viene anche passata l'istanza di INtkdTasklet per fornire l'implementazione del sistema di tasklet.

Quindi il nodo istanzia il suo CoordinatorManager passando al costruttore:

  • peers_manager. L'istanza di PeersManager.

  • map. La mappa delle posizioni libere.

Quando il nodo ha completato la fase di bootstrap, l'utilizzatore del modulo chiama il metodo bootstrap_complete del CoordinatorManager.

Quando il nodo considera che la notifica della sua presenza abbia ormai raggiunto tramite ETP tutti i membri del g-nodo in cui è entrato, l'utilizzatore del modulo chiama il metodo presence_notified del CoordinatorManager.

Deliverables

Nel costruttore del CoordinatorManager viene creata una istanza di CoordinatorService (che descriveremo sotto) e viene registrata nel PeersManager.


Il modulo permette di chiedere ad un vicino del nodo informazioni sui posti liberi nei suoi g-nodi con il metodo get_neighbor_map di CoordinatorManager.

Il metodo ha come argomento lo stub per contattare il vicino. Prevede l'eccezione StubNotWorkingError.

Restituisce una istanza di ICoordinatorNeighborMap.


Il modulo permette di chiedere ad un vicino del nodo di prenotare per lui un posto nel suo g-nodo di livello l con il metodo get_reservation di CoordinatorManager.

Il metodo ha come argomento lo stub per contattare il vicino e il livello a cui fare richiesta. Prevede l'eccezione StubNotWorkingError e l'eccezione SaturatedGnodeError.

Restituisce una istanza di ICoordinatorReservation.

Comunicazioni tra vicini

Quando il modulo vuole chiedere ad un vicino informazioni sui posti liberi nei suoi g-nodi usa il metodo remoto retrieve_neighbor_map. Non ha argomenti. Non prevede eccezioni, oltre alle solite StubError e DeserializeError. Restituisce una istanza di ICoordinatorNeighborMapMessage.

L'interfaccia ICoordinatorNeighborMapMessage è un segnaposto (vuota) esposto dalla libreria intermedia di ZCD che espone il metodo remoto. L'interfaccia ICoordinatorNeighborMap è esposta dal modulo Coordinator e ha i metodi descritti nell'analisi. L'implementazione del metodo remoto crea una istanza della classe NeighborMap. Questa è una classe serializzabile interna al modulo, che implementa entrambe le interfacce suddette.


Quando il modulo vuole chiedere ad un vicino di prenotare per lui un posto nel suo g-nodo di livello l usa il metodo remoto ask_reservation. Ha come argomento il livello l. Prevede l'eccezione SaturatedGnodeError, oltre alle solite StubError e DeserializeError. Restituisce una istanza di ICoordinatorReservationMessage.

L'interfaccia ICoordinatorReservationMessage è un segnaposto (vuota) esposto dalla libreria intermedia di ZCD che espone il metodo remoto. L'interfaccia ICoordinatorReservation è esposta dal modulo Coordinator e ha i metodi descritti nell'analisi. L'implementazione del metodo remoto crea una istanza della classe Reservation. Questa è una classe serializzabile interna al modulo, che implementa entrambe le interfacce suddette.

Servizio Coordinator

Classe server del servizio Coordinator

Il modulo deriva da PeerService la classe CoordinatorService.

Questa classe è interna al modulo. Contiene questi membri:

  • levels. Intero. Il numero di livelli nella topologia della rete. Gli viene passato nel costruttore.

  • peers_manager. Riferimento al PeersManager. Gli viene passato nel costruttore.

  • retrieve_cache_done. Booleano, inizializzato a False.

  • my_presence_should_be_known. Booleano, inizializzato a False.

  • bookings. Lista di liste di Booking. Memoria delle prenotazioni. Contiene levels elementi. L'elemento i-esimo è la lista di prenotazioni attive per il nostro g-nodo di livello i+1. La classe Booking ha una posizione (int pos) e un time-to-live (Timer ttl). E' una classe serializzabile e interna al modulo.

  • max_eldership. Lista di int. Contiene levels elementi. L'elemento i-esimo dice il valore più alto di progressione già assegnato ad una prenotazione per un nuovo g-nodo di livello i dentro il nostro g-nodo di livello i+1. Un valore più alto significa che il g-nodo è arrivato dopo, cioè esso è più giovane.

Quando viene chiamato il metodo bootstrap_complete del CoordinatorManager, la classe CoordinatorService fa queste operazioni:

  • Riceve come argomento lvl il livello del g-nodo appena costituito dal nostro nodo.

  • Se lvl = levels:

    • Imposta il suo flag retrieve_cache_done.

  • Altrimenti:
    • In una nuova tasklet:
      • Avvia le operazioni di recupero dei record di sua pertinenza. Trattandosi di un servizio non opzionale, non attende l'evento PeersManager.participant_maps_ready.

      • Costruisce la richiesta r di tipo "retrieve_cache" dal livello lvl+1 in su.

      • Avvia il primo recupero con il metodo PeersManager.begin_retrieve_cache

      • Attende l'esito, cioè il booleano restituito, la risposta resp da interpretare, l'oggetto IPeersContinuation cont da passare nelle chiamate successive.

      • Se respnull:

        • Si accerta che resp.bookings.size = resp.max_eldership.size = levels - lvl. Altrimenti emette un warning e ignora questa risposta.

        • Per i da 0 a resp.bookings.size-1:

          • j = lvl + i.

          • Per ogni Booking bresp.bookings[i]:

            • Se bbookings[j]:

              • Aggiungi b a bookings[j].

          • Se resp.max_eldership[i] > max_eldership[j]:

            • max_eldership[j] = resp.max_eldership[i].

      • Se l'esito è True:

        • While True:
          • Avvia un altro recupero con il metodo PeersManager.next_retrieve_cache passando la IPeersContinuation cont.

          • Attende l'esito, cioè il booleano restituito e la risposta resp da interpretare.

          • Se respnull:

            • In base a resp modifica i propri membri bookings e max_eldership, come sopra.

          • Se l'esito è False:

            • Esci dal ciclo.
      • Al termine imposta il suo flag retrieve_cache_done.

Quando viene chiamato il metodo presence_notified del CoordinatorManager, la classe CoordinatorService fa queste operazioni:

  • Imposta il suo flag my_presence_should_be_known.

Il metodo is_ready() della classe CoordinatorService si basa sui flag retrieve_cache_done e my_presence_should_be_known.

Metodo reserve

Ricordiamo che quando una richiesta ad un servizio peer-to-peer viene ricevuta dall'hash_node viene chiamato il metodo exec della classe che deriva la PeerService. Questa riceve una istanza di IPeersRequest e deve restituire una istanza di IPeersResponse.

Se il metodo exec della classe CoordinatorService viene chiamato con una istanza di CoordinatorRequest (si veda sotto) che ha il membro name = 'reserve' allora abbiamo ricevuto una richiesta di "prenota un posto nel tuo g-nodo di livello lvl". Le operazioni da fare sono:

  • Se ci sono problemi a deserializzare gli argomenti viene fatta pervernire una eccezione DeserializeError. Inclusi errori nei valori accettabili di lvl.

  • Atomic on: queste operazioni devono essere eseguite atomicamente, senza permettere la schedulazione di altre tasklet.
  • Verifica nella mappa map del CoordinatorManager quali posizioni sono libere nel livello lvl. Se nessuna posizione risulta libera, lancia una eccezione.

  • Dalla lista ottenuta di posizioni libere, esclude quelle presenti nelle prenotazioni bookings(lvl-1) del CoordinatorService. Nello scorrere questa lista, rimuove le istanze di Booking che sono scadute (membro ttl). Se nessuna posizione risulta libera, lancia una eccezione.

  • Scegli una posizione pos.

  • Segnala la prenotazione nella memoria. Cioè crea una istanza di Booking pos con ttl a 20 secondi (una private const nel codice) nella lista bookings(lvl-1) del CoordinatorService.

  • Incrementa di 1 la max_eldership(lvl-1) nella memoria.

  • Con i dati in memoria prepara la risposta ret (pos=pos, eldership=max_eldership(lvl-1))

  • Atomic off.
  • Avvia la prima replica con il metodo PeersManager.begin_replica. Questi sono gli argomenti:

    • Come q mettiamo 15 (una private const nel codice).

    • Come perfect_tuple il valore ottenuto con il metodo perfect_tuple della classe CoordinatorClient con la chiave lvl.

    • Costruisce la richiesta r di tipo 'replica_reserve' per la posizione pos con anzianità eldership dentro il nostro g-nodo di livello lvl.

  • Attende l'esito, cioè il booleano restituito, la risposta resp da interpretare, l'oggetto IPeersContinuation cont da passare nelle chiamate successive.

  • Il booleano restituito è False solo se si è avuta l'eccezione NoParticipantsInNetwork. In questo caso si ignora la risposta resp.

  • La risposta resp dovrebbe essere semplicemente OK, cioè una istanza di CoordinatorReplicaReserveResponse con i membri a null. Altrimenti va prodotto un warning descrittivo da usare nella fase di debug del modulo; quando il modulo è stabile questa situazione va semplicemente ignorata.

  • Se l'esito è True:

    • Avvia la seconda replica con il metodo PeersManager.next_replica passando la IPeersContinuation cont.

    • Attende l'esito, cioè il booleano restituito e la risposta resp da interpretare.

    • Il booleano restituito è False solo se si è avuta l'eccezione NoParticipantsInNetwork. In questo caso si ignora la risposta resp.

    • La risposta resp dovrebbe essere semplicemente OK. Altrimenti va prodotto un warning descrittivo.

    • Se l'esito è True:

      • Avvia una tasklet in cui:
        • While True:
          • Avvia una replica con il metodo PeersManager.next_replica passando la IPeersContinuation cont.

          • Attende l'esito, cioè il booleano restituito e la risposta resp da interpretare.

          • Il booleano restituito è False se abbiamo completato q repliche o se si è avuta l'eccezione NoParticipantsInNetwork. In questo caso si ignora la risposta resp.

          • La risposta resp dovrebbe essere semplicemente OK. Altrimenti va prodotto un warning descrittivo.

          • Se l'esito è False:

            • Esci dal ciclo. Termina la tasklet.
  • Completa ret con (elderships=anzianità dei miei g-nodi da lvl in su)

  • Restituisce ret.

Metodo replica_reserve

Se il metodo exec della classe CoordinatorService viene chiamato con una istanza di CoordinatorRequest (si veda sotto) che ha il membro name = 'replica_reserve' allora abbiamo ricevuto una richiesta di "replica per una prenotazione del posto pos con anzianità eldership nel nostro g-nodo di livello lvl". Le operazioni da fare sono:

  • Se ci sono problemi a deserializzare gli argomenti viene fatta pervernire una eccezione DeserializeError. Inclusi errori nei valori accettabili di lvl e pos.

  • Atomic on.
  • Segnala la prenotazione nella memoria. Cioè crea una istanza di Booking pos nella lista bookings(lvl-1) del CoordinatorService.

  • Se max_eldership(lvl-1) < eldership:

    • Imposta max_eldership(lvl-1) = eldership.

  • Atomic off.
  • Restituisce OK.

Metodo retrieve_cache

Se il metodo exec della classe CoordinatorService viene chiamato con una istanza di CoordinatorRequest (si veda sotto) che ha il membro name = 'retrieve_cache' allora abbiamo ricevuto una richiesta di "recupera i record delle prenotazioni dal livello lvl in su", con 0 < lvllevels. Le operazioni da fare sono:

  • Se ci sono problemi a deserializzare gli argomenti viene fatta pervernire una eccezione DeserializeError. Inclusi errori nei valori accettabili di lvl.

  • Prepara ret con gli elementi da lvl-1 in su della lista bookings di CoordinatorService e con gli elementi da lvl-1 in su della lista max_eldership di CoordinatorService.

  • Restituisce ret.

Classe client del servizio Coordinator

Il modulo deriva da PeerClient la classe CoordinatorClient.

Ridefinisce il suo metodo perfect_tuple. La chiave che può essere usata per calcolare l'hash_node è un intero l da 1 a levels. La lista di interi restituita è composta da l volte il valore 0.

Classi serializzabili per le comunicazioni

Viene definita la classe interna CoordinatorRequest. Si tratta di una classe serializzabile che implementa l'interfaccia segnaposto (vuota) IPeersRequest. Serve per tutte le richieste che possono essere fatte al servizio. Tale classe contiene:

  • name. Una stringa che identifica la richiesta. I valori possibili sono: ['reserve', 'retrieve_cache', 'replica_reserve'].

  • reserve_lvl. Usato se name = 'reserve'. Un intero che indica il livello del g-nodo dentro il quale riservare un posto.

  • cache_from_lvl. Usato se name = 'retrieve_cache'. Un intero che dice di passare i record da quel livello in su.

  • replica_lvl. Usato se name = 'replica_reserve'. Un intero che dice il livello del g-nodo dentro il quale è stato prenotato un posto.

  • replica_pos. Usato se name = 'replica_reserve'. Un intero che dice la posizione della prenotazione.

  • replica_eldership. Usato se name = 'replica_reserve'. Un intero che dice l'anzianità del posto prenotato.


Viene definita la classe interna CoordinatorReserveResponse. Si tratta di una classe serializzabile che implementa l'interfaccia segnaposto (vuota) IPeersResponse. Serve come risposta solo per la richiesta 'reserve'. Tale classe contiene:

  • error_domain. Una stringa nullable.

  • error_code. Una stringa nullable.

  • error_message. Una stringa nullable. Queste sono tutte a null se l'esito è buono, mentre sono valorizzate se si vuole indicare una eccezione.

  • pos. Un intero. La posizione assegnata.

  • elderships. Una lista di interi. Le anzianità da l-1 (del g-nodo appena assegnato) fino a levels.


Viene definita la classe interna CoordinatorReplicaReserveResponse. Si tratta di una classe serializzabile che implementa l'interfaccia segnaposto (vuota) IPeersResponse. Serve come risposta solo per la richiesta 'replica_reserve'. Tale classe contiene:

  • error_domain. Una stringa nullable.

  • error_code. Una stringa nullable.

  • error_message. Una stringa nullable. Queste sono tutte a null se l'esito è buono, mentre sono valorizzate se si vuole indicare una eccezione.

Non ha altri membri da valorizzare se l'esito della replica è positivo.


Viene definita la classe interna CoordinatorRetrieveCacheResponse. Si tratta di una classe serializzabile che implementa l'interfaccia segnaposto (vuota) IPeersResponse. Serve come risposta solo per la richiesta 'retrieve_cache'. Tale classe contiene:

  • error_domain. Una stringa nullable.

  • error_code. Una stringa nullable.

  • error_message. Una stringa nullable. Queste sono tutte a null se l'esito è buono, mentre sono valorizzate se si vuole indicare una eccezione.

  • bookings. Lista di liste di Booking. Essendo questa la risposta ad una richiesta di record per i livelli da lvl in su, l'elemento i-esimo di questa lista va assegnato al membro bookings[i + lvl] della nostra memoria.

  • max_eldership. Lista di int. L'elemento i-esimo va assegnato al membro max_eldership[i + lvl] della nostra memoria.


Viene definita la classe interna CoordinatorUnknownRequestResponse. Si tratta di una classe serializzabile che implementa l'interfaccia segnaposto (vuota) IPeersResponse. Serve come risposta per le richieste che non sono state riconosciute dall'implementazione del server. Tale classe non contiene nulla.

Netsukuku/ita/docs/ModuloCoordinator/DettagliTecnici (last edited 2015-12-02 09:12:54 by lukisi)