Differences between revisions 1 and 2
Revision 1 as of 2015-08-13 10:39:29
Size: 90
Editor: lukisi
Comment:
Revision 2 as of 2015-08-15 17:05:29
Size: 8881
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 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 ''ask_reservation'' di !CoordinatorManager.

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

Questa classe è interna al modulo. Contiene questi membri:
 * ''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. 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'').
 * ''max_eldership''. Lista di int. 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:
 * In una nuova tasklet:
  * Avvia le operazioni di recupero dei record di sua pertinenza con i metodi ''!PeersManager.begin_retrieve_cache'' e ''!PeersManager.next_retrieve_cache''.
  . Trattandosi di un servizio non opzionale, non attende l'evento ''!PeersManager.participant_maps_ready''.
  . E' compito della classe !CoordinatorService costruire la richiesta ''r'' di "recupero records".
  * Ad ogni chiamata che restituisce ''True'' va interpretata la risposta ''resp'' e vanno memorizzati i records di pertinenza. '''TODO''' spiegare cosa va indicato nella richiesta e quali membri vanno memorizzati sulla base della risposta.
  * 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.
 * Atomic on: queste operazioni devono essere eseguite atomicamente, senza permettere la schedulazione di altre tasklet.
 * Verifica che un posto libero esiste nel mio g-nodo di livello ''lvl''. Altrimenti lancia una eccezione.
 * Scegli un posto ''pos''.
 * Segnala il posto come prenotato nella memoria.
 * 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''. Come ''q'' mettiamo 15 (una {{{private const}}} nel codice). Come perfect_tuple il valore ottenuto con il metodo ''perfect_tuple'' della classe !CoordinatorClient. E' compito della classe !CoordinatorService costruire la richiesta ''r'' di "replica prenotazione su ''pos''".
 . Attende l'esito, cioè il booleano restituito, la risposta ''resp'' da interpretare, l'oggetto IPeersContinuation ''cont'' da passare nelle chiamate successive.
 . La risposta ''resp'' dovrebbe essere semplicemente OK. Il booleano restituito è ''False'' solo se si è avuta l'eccezione !NoParticipantsInNetwork.
 * Se l'esito è ''True'':
  * Avvia la seconda replica con il metodo ''!PeersManager.next_replica'' passando la IPeersContinuation.
  . Attende l'esito, cioè il booleano restituito e la risposta ''resp'' da interpretare.
  . La risposta ''resp'' dovrebbe essere semplicemente OK. Il booleano restituito è ''False'' solo se si è avuta l'eccezione !NoParticipantsInNetwork.
  * Se l'esito è ''True'':
   * Avvia una tasklet in cui:
    * While True:
     * Avvia una replica con il metodo ''!PeersManager.next_replica'' passando la IPeersContinuation.
     . Attende l'esito, cioè il booleano restituito e la risposta ''resp'' da interpretare.
     . La risposta ''resp'' dovrebbe essere semplicemente OK. Il booleano restituito è ''False'' se abbiamo completato ''q'' repliche o se si è avuta l'eccezione !NoParticipantsInNetwork.
     * 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.

=== 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'].
 * ''lvl''. Usato se ''name'' = 'reserve'. Un intero che indica il livello in cui riservare un posto.

----
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 !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.
 * ...

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

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 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 ask_reservation di CoordinatorManager.

Servizio Coordinator

Classe server del servizio Coordinator

Il modulo deriva da PeerService la classe CoordinatorService.

Questa classe è interna al modulo. Contiene questi membri:

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

  • max_eldership. Lista di int. 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:

  • In una nuova tasklet:
    • Avvia le operazioni di recupero dei record di sua pertinenza con i metodi PeersManager.begin_retrieve_cache e PeersManager.next_retrieve_cache.

    • Trattandosi di un servizio non opzionale, non attende l'evento PeersManager.participant_maps_ready.

    • E' compito della classe CoordinatorService costruire la richiesta r di "recupero records".

    • Ad ogni chiamata che restituisce True va interpretata la risposta resp e vanno memorizzati i records di pertinenza. TODO spiegare cosa va indicato nella richiesta e quali membri vanno memorizzati sulla base della risposta.

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

  • Atomic on: queste operazioni devono essere eseguite atomicamente, senza permettere la schedulazione di altre tasklet.
  • Verifica che un posto libero esiste nel mio g-nodo di livello lvl. Altrimenti lancia una eccezione.

  • Scegli un posto pos.

  • Segnala il posto come prenotato nella memoria.
  • 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. Come q mettiamo 15 (una private const nel codice). Come perfect_tuple il valore ottenuto con il metodo perfect_tuple della classe CoordinatorClient. E' compito della classe CoordinatorService costruire la richiesta r di "replica prenotazione su pos".

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

  • La risposta resp dovrebbe essere semplicemente OK. Il booleano restituito è False solo se si è avuta l'eccezione NoParticipantsInNetwork.

  • Se l'esito è True:

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

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

    • La risposta resp dovrebbe essere semplicemente OK. Il booleano restituito è False solo se si è avuta l'eccezione NoParticipantsInNetwork.

    • Se l'esito è True:

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

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

          • La risposta resp dovrebbe essere semplicemente OK. Il booleano restituito è False se abbiamo completato q repliche o se si è avuta l'eccezione NoParticipantsInNetwork.

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

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'].

  • lvl. Usato se name = 'reserve'. Un intero che indica il livello in cui riservare un posto.


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

  • ...


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.

  • ...

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