== La classe Map ==
Rappresenta una mappa di oggetti generici (''dataclass'') con uno spazio di levels x gsize. Cioè 4 x 256.
Ricorda che il livello 0 contiene l'id dei singoli nodi, mentre il livello 3 contiene l'id dei gnodi più vasti. Il livello 4 non si specifica, consisterebbe in un unico gnodo che contiene l'intero dominio di IPv4.
Ogni spazio viene creato usando il costruttore dataclass con i parametri lvl e id, così che l'oggetto che rappresenta un nodo nella mappa può avere l'informazione di dove si trova nella mappa (al momento la [[../ClasseRouteNode|classe RouteNode]] non ne fa uso).<
>
La ''dataclass'' deve avere il metodo {{{is_free}}} per dire se lo spazio in questione è usato o no.<
>
E' possibile segnalare la presenza di un nuovo nodo nella mappa. Si fa con il metodo {{{node_add}}}. In questo momento viene emesso il signal {{{NODE_NEW}}}.<
>
E' possibile anche rimuovere un elemento dalla mappa. Si fa con il metodo {{{node_del}}}. In questo caso viene anche emesso il signal {{{NODE_DELETED}}}.<
>
E' possibile anche resettare un intero livello o l'intera mappa senza far emettere alcun segnale ({{{map_reset}}}, {{{level_reset}}}). Questa tecnica è usata dopo aver fatto un re-hook in un diverso gnodo e aver reimpostato il nuovo IP su tutti i Nic attivi (vedi la [[../ClasseHook|classe Hook]]).
Inoltre la classe Map tiene traccia del numero di nodi presenti di ogni livello, cioè il numero di spazi per cui {{{is_free() = False}}}. Lo memorizza nel membro {{{node_nb[lvl]}}}.
<
>
Oltre ad avere questo numero immediatamente pronto nel membro {{{node_nb[lvl]}}}, e come controparte il numero di nodi liberi calcolati come differenza nel metodo {{{free_nodes_nb(lvl)}}}, la classe fornisce anche il metodo {{{free_nodes_list(lvl)}}} che restituisce l'elenco degli {{{id}}} dei nodi liberi di livello {{{lvl}}}.
<
>
Importante: questi dati tengono conto anche del fatto che in IPv4 alcuni indirizzi non sono validi, tipo 192.168.* o 224.* etc.
Nella classe Map l'attributo {{{me}}} memorizza il proprio spazio, cioè il proprio Netsukuku-IP (abbreviato {{{nip}}}).
<
>
Un nip è indicato nella forma di una sequenza di ID per i vari livelli dallo 0 al più alto.
<
>
{{{ self.me = [1,1,168,192]}}}
<
>
Notare che il primo elemento della sequenza è il livello 0 (l'id del singolo nodo)
<
>
Un altro modo di rappresentare uno spazio nella mappa è un intero, detto semplicemente {{{ip}}}, dato dal calcolo 192*256^3^+168*256^2^+1*256^1^+1*256^0^.
<
>
Per convertire tra le 2 notazioni si possono usare i metodi {{{ip_to_nip}}} e {{{nip_to_ip}}}.
Per descrivere le altre funzionalità, supponiamo di avere a disposizione un altro indirizzo nella variabile {{{nip}}}.
<
>
{{{ nip = [2,2,168,192]}}}
Il metodo {{{is_in_level}}} ci dice se un certo nodo o gnodo appartiene allo stesso nostro gnodo di livello x.
In questo caso {{{self.is_in_level(nip,0)}}} darebbe {{{False}}};<
>
invece {{{self.is_in_level(nip,1)}}} darebbe {{{True}}}.
Il metodo {{{nip_cmp}}} dice di 2 Netsukuku-IP quale sia il primo livello differente. La ricerca parte dall'ultimo elemento delle sequenze (levels -1). Tra i 2 nip citati prima
<
>
{{{ nip_cmp(self.me, nip)}}}
<
>
dovrebbe restituire 1.
Il metodo {{{lvlid_to_nip(lvl, id)}}} partendo da lvl e id guarda nella mappa e restituisce il nip equivalente. Lo fa partendo dal proprio nip (self.me) sostituendo il livello lvl con id e azzerando i livelli sotto lvl.
=== pack e merge ===
La classe {{{Map}}} fornisce un metodo '''map_data_pack''' che restituisce in una struttura tutti i dati della mappa (tranne le dimensioni {{{levels}}} e {{{gsize}}} che sono considerate note a priori).
<
>
Per la precisione si tratta di una tupla di 3 elementi: il proprio NIP, una copia della lista di liste di oggetti ''dataclass'', una copia della lista del numero di oggetti non liberi.
<
>
''Notare'' che, per passare questa struttura ad un metodo remotable occorre che la classe usata come ''dataclass'' sia registrata come serializable con il [[../ModuloRencode|modulo rencode]].
Inoltre fornisce il metodo '''map_data_merge''' che usa come argomento una struttura dati dello stesso formato prodotto da {{{map_data_pack}}}.
<
>
Questo metodo verifica a quale livello sia il gnodo comune fra il suo attributo {{{me}}} e quello della mappa ricevuta. Lo fa con {{{nip_cmp}}} che ritorna il primo livello differente. I valori della mappa ricevuta il cui indice è maggiore o uguale a questo livello (ottenuto con {{{nip_cmp}}}) rappresentano gli stessi nodi per me e per il nodo della mappa ricevuta. Quelli inferiori rappresentano nodi diversi e non hanno significato per me.
<
>
Una volta stabilito quali valori della mappa ricevuta sono significativi per me, il metodo {{{map_data_merge}}} valorizza la mia mappa con i '''soli''' nodi della mappa ricevuta e resetta i livelli sottostanti.
<
>
In realtà il nome merge può essere fuorviante: non significa che i vecchi dati della propria mappa rimangono. Rimane solo il vecchio NIP e gli altri dati provenienti dall'altra mappa (di norma ricevuta da un nodo remoto) diventano significativi in quanto riferiti al nostro NIP.
<
>
E' usato nella classe {{{MapP2P}}}, derivata di {{{Map}}}, quando la classe {{{P2PAll}}} (vedi il [[../ModuloP2P|modulo P2P]]) recupera la mappa dei partecipanti da un suo nodo vicino attraverso il metodo remotable {{{pid_getall}}}.
<
>
Un'altra classe derivata di {{{Map}}}, la classe {{{MapCache}}} del [[../ModuloCoord|modulo coord]], dichiara remotable lo stesso metodo {{{map_data_merge}}} e la classe {{{Coord}}} lo usa per passare i dati da un Coordinator Node al suo successore.