• Non ci sono risultati.

La classe Nodo è la classe astratta che implementa i metodi e le strutture dati di base comuni a tutti i nodi della griglia, siano essi Committenti o Rappresentanti. E’ una delle classi principali della libreria in quanto implementa il funzionamento dei due soggetti primari coinvolti nel deployment. Si è riuscito a raccogliere quasi tutte le azioni, caratteristiche e comportamenti di Committenti e Rappresentanti in quest’unica classe agevolando moltissimo lo sviluppo e il debugging, nonché la logica dell’applicazione. La principale differenza tra Committente e Rappresentante è data dal fatto che il Committente è un nodo non permanente della griglia e che quindi si aggancia alla stessa per la sola durata della sessione di deployment (che può eventualmente coinvolgere più deployment successivi). Per tale motivo le informazioni per comunicare con il Committente non sono incluse nel file XML che descrive la topologia della griglia e per lo stesso motivo il Committente non ha alcun idNodo (proprio perché temporaneo).

dopo che il Rappresentante ha ricevuto un nuovo messaggio di inizio deployment (NewJob) con anche le informazioni per contattare il Committente. Alla ricezione di tale messaggio il Rappresentante mantiene delle strutture dati in memoria che gli consentono di contattare tutti i nodi coinvolti nel deployment e quindi anche il Committente.

Ogni rappresentante può gestire in parallelo più deployment da parte di uno o più Committenti.

Tra le strutture dati più importanti della classe Nodo troviamo:

 cacheBlocchi (tipo Cache): la cache contenente i blocchi dei file  commInfo (tipo CommInfo): le informazioni di rete necessarie

per essere contattati

 msgServer (tipo MsgServer): il server di Ascolto per la ricezione dei messaggi dagli altri nodi

 hashNodi: una struttura dati ad accesso veloce (Hashtable) con chiave idNodo contenente oggetti di tipo NodoVirtuale utilizzati per l’invio dei messaggi al nodo associato alla chiave.

 semaforoThread (tipo Semaforo): un semaforo utilizzato per limitare in base al numero di CPU dell’host il numero massimo di thread che elaborano file e blocchi in parallelo.

 doingCpuIntensiveTasks: nell’attuale implementazione tale variabile viene settata solo dal nodo Committente quando si è in fasi di calcolo che richiedono utilizzo intensivo della CPU come ad esempio quando è in esecuzione l’algoritmo di ottimizzazione e distribuzione dei blocchi. Viene testata dall’algoritmo di ottimizzazione della cache per far si che entri in funzione senza sottrarre risorse di calcolo più importanti per altri task.

la creazione delle cartelle dei blocchi temporanei, l’allocazione della cache (previa verifica della possibilità di allocare lo spazio richiesto in memoria), la lettura delle informazioni sugli altri nodi della Griglia tramite il parsing di un apposito file XML e infine l’avvio del server di ascolto dei messaggi.

 startMsgServer: effettua l’avvio del server di ascolto dei messaggi. In base al protocollo utilizzato dal nodo viene avviato un server ad hoc che si occupa di gestire quel tipo di messaggi; nella libreria viene ad esempio fornita l’implementazione di un server TCP. L’aggiunta di nuovi server richiede semplicemente l’aggiunta di una riga di codice in startMsgServer e l’implementazione del server estendendo la classe astratta MsgServer.

 send: effettua l’invio di un messaggio ad un nodo in modalità bloccante. A partire dall’id del nodo si recupera da hashNodi l’oggetto di tipo NodoVirtuale ad esso associato. Successivamente l’invio del messaggio avviene invocando il metodo send di tale oggetto. Al completamento della richiesta viene ritornato l’oggetto di tipo MsgResponse.

 asyncSend: il funzionamento è come quello del metodo send ma in modalità non bloccante. Subito dopo aver invocato il metodo viene ritornato un oggetto di tipo MsgResponseAsync e l’esecuzione della send prosegue in parallelo. In qualsiasi momento è possibile testare il completamento dell’operazione e recuperare il messaggio di risposta MsgResponse o l’eventuale eccezione catturata.

 broadcast: effettua l’invio del messaggio specificato in modalità bloccante a tutti i nodi conosciuti della rete tramite l’apposito metodo della classe AsyncSendManager

 elaboraMsg: questo è un metodo astratto che richiede

implementazioni ad hoc nelle sottoclassi Committente e Rappresentante.

 richiediThread / rilasciaThread: metodi utilizzati per richiedere l’attivazione di un nuovo Thread (o il rilascio di quello utilizzato) per effettuare l’elaborazione di un file limitando il numero massimo di Thread utilizzabili. La limitazione viene impostata prendendo in considerazione il numero di CPU del sistema per evitare in tal modo un eccessivo numero di context switch. I due metodi non fanno altro che fare la P e la V sul semaforo inizializzato al limite appena discusso.

 setFileRimanentiDaProcessare / segnalaFineElaborazioneFile / attendiFineElaborazioneFiles: metodi utilizzati per effettuare in parallelo l’elaborazione di più file e testarne poi il completamento.

 elaboraComandiComuni: metodo utilizzato per la gestione dei messaggi di tipo Command che invocano l’esecuzione di comandi remoti comuni sia al Committente che al Rappresentante.

 elaborazioneCpuIntensiveInCorso: metodo utilizzato per

verificare se il sistema sta sfruttando intensamente la/le CPU. Non esistendo un metodo portabile in Java per avere dati quali la percentuale di CPU utilizzata oppure il carico di sistema istantaneo viene utilizzato un espediente che approssima questo stato in base alle risorse utilizzate dai thread della libreria. In particolare tale metodo ritorna true se il numero di thread in esecuzione per l’elaborazione dei file (calcolo blocchi, calcolo chiavi SHA1, compressione blocchi, ricostruzione file…) è maggiore di un numero predeterminato (es. una percentuale del numero massimo di thread consentiti) oppure se la variabile doingCpuIntensiveTasks della classe Nodo ha valore true.

Questo metodo viene utilizzato in particolare dal metodo di ottimizzazione della Cache che testa appunto se ci sono operazioni in corso che richiedono molta cpu; in tal caso evita di

Memory.