Differences between revisions 4 and 5
Revision 4 as of 2015-09-05 09:37:04
Size: 16252
Editor: lukisi
Comment:
Revision 5 as of 2015-09-16 14:15:20
Size: 15909
Editor: lukisi
Comment:
Deletions are marked like this. Additions are marked like this.
Line 7: Line 7:
Quindi il nodo istanzia il suo !CoordinatorManager passando al costruttore: Quando il nodo ha completato la fase di bootstrap, il nodo istanzia il suo !CoordinatorManager passando al costruttore:
Line 10: Line 10:

Quando il nodo ha completato la fase di bootstrap, l'utilizzatore del modulo chiama il metodo ''bootstrap_complete'' del !CoordinatorManager.
Line 54: Line 52:
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:
Quando viene chiamato il metodo ''presence_notified'' del !CoordinatorManager, la classe !CoordinatorService fa queste operazioni:
 * ''level_new_gnode'' = ''peers_manager.level_new_gnode''.
 * Se ''level_new_gnode'' ≠ ''levels'':
Line 61: Line 57:
   * Costruisce la richiesta ''r'' di tipo "retrieve_cache" dal livello ''lvl''+1 in su.    * __'''TODO'''__ rivedere tutto.
* Costruisce la richiesta ''r'' di tipo "retrieve_cache" dal livello ''level_new_gnode''+1 in su.
Line 65: Line 62:
    * Si accerta che ''resp.bookings.size'' = ''resp.max_eldership.size'' = ''levels - lvl''. Altrimenti emette un warning e ignora questa risposta.     * Si accerta che ''resp.bookings.size'' = ''resp.max_eldership.size'' = ''levels - level_new_gnode''. Altrimenti emette un warning e ignora questa risposta.
Line 67: Line 64:
     * ''j'' = ''lvl + i''.      * ''j'' = ''level_new_gnode + i''.
Line 81: Line 78:
   * Al termine imposta il suo flag ''retrieve_cache_done''.  * Imposta il suo flag ''retrieve_cache_started''.
Line 83: Line 80:
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''.
Il metodo ''is_ready()'' della classe !CoordinatorService si basa sul flag ''retrieve_cache_started''.

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.

Quando il nodo ha completato la fase di bootstrap, il nodo istanzia il suo CoordinatorManager passando al costruttore:

  • peers_manager. L'istanza di PeersManager.

  • map. La mappa delle posizioni libere.

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 presence_notified del CoordinatorManager, la classe CoordinatorService fa queste operazioni:

  • level_new_gnode = peers_manager.level_new_gnode.

  • Se level_new_gnodelevels:

    • 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.

      • TODO rivedere tutto.

      • Costruisce la richiesta r di tipo "retrieve_cache" dal livello level_new_gnode+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 - level_new_gnode. Altrimenti emette un warning e ignora questa risposta.

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

          • j = level_new_gnode + 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.
  • Imposta il suo flag retrieve_cache_started.

Il metodo is_ready() della classe CoordinatorService si basa sul flag retrieve_cache_started.

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)