6 Realizzazione del sistema

Come già detto precedentemente questo lavoro si occupa dell’interrogazione di una rete di database di cui non sono note né la topologia né il numero dei server collegati. Con queste limitazioni si è ritenuto opportuno non implementare nessun meccanismo di gestione della duplicazione delle informazioni, per questo motivo tutti gli inserimenti e le modifiche vengono fatti solo su database locale senza interferire con gli altri nodi della rete. Il sistema realizzato non è un vero e proprio sistema distribuito ma piuttosto un modello per la realizzazione di ricerche distribuite.

Supponiamo di avere una rete di 6 nodi con lo stesso tipo di applicativo che necessita di interagire con un database locale [fig.6.1]. In questo caso ogni database locale al sito condividerà la stessa struttura dati con gli altri database. Si vuole realizzare un meccanismo che consenta di vedere tutto l’insieme dei dati disponibili sui vari siti partendo da una conoscenza minima della struttura della rete, ad esempio l’individuazione di due soli altri nodi. Questo sistema deve intercettare la query al database locale, interrogare il database ed eventualmente instradare la query sui siti restanti.

Fig. 6.1 Possibile mappatura della rete

 

 

Nel gestire una maglia di questo tipo il problema principale consiste nel prevenire il realizzarsi di cicli nel routing delle query, semplificando, è necessario che un sito venga visitato e risponda una sola volta. Più che da esigenze di non duplicazione che potrebbero essere gestite direttamente sul client di destinazione, questo requisito è dato da problemi di occupazione di banda sulla rete; infatti con l’approccio ad agenti gran parte della complessità del problema è spostato sul canale di comunicazione e cioè sulla rete stessa. Esempi di cicli sulla rete sono dati dagli anelli S1-S2 e S2-S3-S4, ecc.

Altro problema che nasce è quello di gestire la profondità della ricerca o meglio il fatto che le risposte devono pervenire entro un certo tempo che di norma è dell’ordine dei minuti. A volte è infatti più importante che il sistema risponda entro un certo tempo e che dia una risposta di query insoddisfatta piuttosto che riesca a reperire i dati e che questi arrivino dopo un tempo di attesa troppo elevato.

L’ultimo punto da affrontare riguarda la gestione dei casi di errore, ad esempio è possibile infatti che un server della rete si fermi, oppure che il tale database non sia disponibile sul server contattato e così via.

Riassumendo i punti essenziali sono i seguenti:

 

Data la scarsità di informazioni che si conoscono riguardo i server componenti la rete si è ritenuto opportuno realizzare un tool di descrizione remota dei database presenti sui vari server; detto tool si collega ad un server specificato dall’utente, stabilisce quali sono i database a cui si può accedere e, una volta selezionato quello opportuno, ne da una descrizione all’utente.

 

 

 

6.1 Analisi del problema

Dai requisiti del sistema risulta evidente che è necessario predisporre un’architettura di terzo livello che gestisca l’interazione dell’utente/applicazione con i DBMS presenti sulla rete.

A differenza di una normale architettura di secondo livello [fig. 6.1.1] dove client utente e server DBMS interagiscono direttamente tra loro, in un architettura di terzo livello [fig. 6.1.2] le richieste vengono filtrate da un sistema intermedio che controlla gli accessi al DBMS.

 

 

Fig. 6.1.1 Architettura di secondo livello

 

 

 

 

 

 

Fig. 6.1.2 Architettura di terzo livello

In un’architettura di terzo livello il sistema intermedio è in grado di intercettare le query provenienti dal client utente, o da altre fonti, proporla al server DBMS e se necessario inviarla al sistema intermedio di altri nodi della rete.

La struttura finale del sistema risulta quindi essere composta tre componenti:

Sono state individuate due possibili soluzioni al problema: una classica che si base sul modello delle interazioni client/server ed una che utilizza la tecnologia degli agenti mobili.

Il fatto di utilizzare Java come linguaggio di sviluppo ha imposto l’utilizzo di JDBC come mezzo di connessione con il server DBMS. JDBC è un insieme di classi fornite con il Java Development Kit (JDK) a partire dalla versione 1.1, che assicurano a Java la possibilità di collegarsi a qualsiasi DBMS di cui sia disponibili un driver JDBC o ODBC (quindi tutto il mondo Windows).

6.2 Soluzione con gli agenti mobili

Ricapitolando questo tipo di soluzione prevede la realizzazione di un client di interfaccia in grado di recuperare le richieste dell’utente e generi l’agente mobile relativo, di un server che si occupi di intercettare gli agenti provenienti dal client locale o dai vari server remoti e ne garantisca l’esecuzione in un conteso sicuro, ed infine un agente mobile per ogni funzionalità del sistema.

In una situazione ottimale il sistema risulta essere costituito da vari nodi su cui girano un client, un server di esecuzione degli agenti ed un DBMS; il server locale in questo caso non è altro che quello che normalmente viene utilizzato dall’applicativo client, cioè il collegamento che permette al applicativo cliente di navigare sulla rete delle informazioni dei vari server [fig. 6.2.1].

 


 

Fig. 6.2.1 Situazione ottimale

 

Anche se l’ambito normale è quello appena descritto, il sistema ammette che vi siano un diverso numero di client rispetto a quello dei server; teoricamente nel caso in cui ci fossero più client che server [fig.6.2.2] dovremmo essere in una condizione di conflitto dato che sicuramente più di un client sarebbe associato ad un unico server, ma dal punto di vista pratico tutti i server dispongono di un modulo multi-thread che permette di attivare più connessioni contemporaneamente. È chiari che più client si riferiscono allo stesso server più agenti rimarranno in stato di attesa e di conseguenza le prestazioni del nodo ne risentirebbero, ma questa situazione si verificherebbe solo in condizioni di traffico elevato e dipenderebbero dalle caratteristiche dell’hardware a disposizione.

 

Fig. 6.2.2 Situazione con più client
 

L’ultimo caso è quello più favorevole, esistono cioè più server che client, in questa situazione non vi sono problemi di criticità tranne il fatto che potrebbe risultare poco conveniente diffondere le richieste su più server magari utilizzando un numero minore di DBMS, a meno che non si presenti un alta criticità delle query da eseguire. Altro caso sarebbe quello di distribuire le informazioni in più DBMS di quelli necessari, in quanto potrebbero nascere dei problemi di gestione dei database.

Prima di vedere i dettagli dei tre componenti software già citati è necessario dare uno sguardo alle classi messe a disposizione dal tool di gestione degli agenti mobili e vederne le modalità di utilizzo. Un elenco dettagliato di tutte le classi presenti nel tool ed una descrizione più approfondita sono riportati in appendice a questo lavoro.

Vi sono quattro diversi tipi di classi, una finalizzata allo sviluppo di agenti, una allo sviluppo di server, una destinata agli eventi che possono essere scatenati dagli elementi del sistema ed infine l’ultima destinata a classi di utilità quali ad esempio una classe che permette di organizzare le informazioni in una lista ordinabile secondo una chiave numerica o una stringa.

 

6.2.1 Server o contesto di esecuzione

Ogni server è un oggetto autonomo e ha delle proprietà specifiche che devono essere messe a disposizione dei vari agenti che si susseguono e vengono eseguito nel suo contesto. Queste proprietà sono scritte in un file di testo il cui nome viene passato come parametro all’avvio del programma stesso, in questo modo risulta molto semplice cambiare le varie proprietà. È semplice sviluppare un’interfaccia che permetta controllare dette proprietà e che ne permetta la modifica senza passare per un programma di editor di file di testo.

Le proprietà in questo caso sono la stringa di formattazione della richiesta di collegamento al database, il nome del drive JDBC che consente il collegamento al DBMS, i server che sono autorizzati a far eseguire agenti nel contesto di esecuzione locale, e così via; ogni singolo robot progettato per scopi diversi utilizzerà proprietà diverse.

È evidente che per garantire l’accesso agli agenti al database locale è necessario fare in modo che dette proprietà vengano messe a disposizione, perciò si è pensato di realizzare il metodo della classe Agent setServerProperties che permette di inizializzare le proprietà dell’agente.

Un’altra caratteristica necessaria è quella di poter fare in modo che l’agente possa istanziare e mantenere delle variabili proprietarie con la possibilità di indirizzamento delle stesse da parte di altri robot, per ciò si è ritenuto opportuno predisporre una struttura di contenimento di dette variabili che deve comunque essere passata ai robot tramite il metodo setServerVariables della classe Agent.

L’ultimo metodo di inizializzazione della classe Agent è setListAgents che è utilizzato per settare la lista degli agenti presenti, questo è necessario nel caso si vogliano utilizzare le caratteristiche di mail-message tra i vari robot presenti sul server. Non ho ritenuto opportuno realizzare un metodo generico dato che è sempre possibile voler spedire un messaggio ad un insieme di agenti presenti e non a tutti.

Il conteso di esecuzione, o server, si ottiene estendendo la classe ServerAgents e l’interfaccia AgentListener e implementando dei metodi precisi [fig. 6.2.1.1]. La super-classe ServerAgents contiene un’insieme di metodi di base per il trattamento degli agenti, mentre l’interfaccia AgentListener si occupa dell’intercettazione degli eventi scatenati dai robot.

 

Fig. 6.2.1.1 Rappresentazione ad oggetti (formalismo OMT) del server

 

Il metodo identify è quello che si occupa di identificare il robot, prende come input l’agente da controllare e presenta in uscita un valore booleano. Tramite la ridefinizione di questo metodo è possibile personalizzare il server in modo che utilizzi un procedimento di identificazione proprietario che verifichi tutte le caratteristiche necessarie che il robot deve avere per poter essere eseguito sul server. Nel nostro caso il metodo restituisce sempre true per cui tutti gli agenti vengono eseguiti, in ambito accademico questo è del tutto lecito ma in un sistema reale è necessario fare delle verifiche almeno sul server di provenienza.

Il vero nucleo del server è però il metodo startAgent che ha la funzione di far partire il robot una volta che è stato intercettato. Detto metodo deve richiamare il metodo identify, dopo di che procede verificando se l’agente ha qualche evento da lanciare, nel caso in cui sia presente l’agente viene eseguito immediatamente. Nel caso in cui non vi siano eventi presenti il robot viene inizializzato tramite una chiamata ai tre metodi dell’agente setServerProperties, setServerVariables e setListAgents che sono necessari rispettivamente per accedere alle proprietà del server, alle variabili presenti sul server mantenute dagli agenti presenti e una lista di tutti i robot presenti nel sistema.

L’altro metodo che deve essere implementato è handleAgentEvent che tratta la risposta agli eventi lanciati dai robot. Esistono tre tipi di eventi predefiniti: AGENT_ANSWER o di risposta, AGENT_ERROR o di errore ed infine AGENT_SERVICE o di servizio. Bisogna specificare in questo metodo le azioni da compiere per trattare correttamente i vari tipo di evento, in questo caso ad esempio essendo il programma un demone e non generando agenti è impossibile che tratti agenti di risposta e così se si verifica l’intercettazione di detto evento si è verificato sicuramente un errore e ne viene data comunicazione. Nel caso si sia intercettato un evento di errore viene stampato tale errore, mentre se si cattura un evento di servizio viene verificato che tipo di servizio, nella fattispecie si controlla si controlla se è un’istanza di ActivateServer e se è così si stampa l’URL del server attivato.

Il metodo main non fa altro che istanziare un oggetto MyServerAgents e farlo partire gestendo le Eccezioni.

6.2.2 Client e interfaccia utente

Si è deciso di dividere il client in due sezioni: l’area di contesto e l’interfaccia utente.

L’area di contesto è quella che si occupa di intercettare gli agenti che provengono dai server della rete e di farli eseguire, questa parte risulta molto simile a quella già trattata per il server. Sono state apportate delle variazioni al metodo che si occupa di far partire gli agenti e precisamente sono stati scartati gli agenti che non devono lanciare eventi; altro metodo modificato è quello che si occupa della gestione degli eventi a cui è stato aggiunto il supporto per il trattamento degli eventi di risposta.

L’interfaccia utente si occupa di intercettare i vari tipi di eventi provenienti dalla GUI e del trattamento degli stessi. L’interfaccia grafica è stata progettata utilizzando quattro pannelli principali due sempre attivi e due mutuamente esclusivi. I pannelli comuni sono quello dedicato al reperimento della password e della login che saranno utilizzate per la connessione con il database remoto, e quello dove vi sono i bottoni per inviare l’agente opportuno e per cancellare l’area di lavoro. Gli altri due pannelli sono particolari per le funzionalità che svolgono e sono stati resi mutuamente esclusivi utilizzando il principio delle schede per passare da una scheda all’altra si utilizzano due bottoni che sono localizzati sopra la scheda attiva.

Poiché l’interfaccia grafica funziona sulla base degli eventi per gestire tutte le funzionalità è necessario intercettarli in modo da discriminare le varie situazioni nei due casi di cui si parlava sopra. Cosa fondamentale e comune ad entrambe le funzionalità è che per far partire l’agente è necessario completare le varie sezioni completamente e selezionare il bottone invia, dopo di che sarà selezionato il robot opportuno e sarà inviato a tutti i nodi di cui si conosce il riferimento.

Le due funzionalità del programma sono la ricerca distribuita in rete della query intercettata e la descrizione di un database remoto.

Nel primo caso ci si trova di fronte un pannello che consente di impostare il nome del database a cui ci si riferisce, la query da ricercare, il fatto che si voglia fare uso o meno delle transazioni, il tempo massimo entro cui deve pervenire la risposta e una parte dedicata al trattamento delle risposte [fig.6.2.2.1].

Fig. 6.2.2.1 Tool di interrogazione remota

Nel caso del tool di descrizione remota invece abbiamo una schermata che permette di scegliere uno dei server attivi, scegliere un database tra quelli possibili ed un’area per il trattamento delle risposte [fig.6.2.2.2]. Per determinare quali server e quali database essi mettono a disposizione si utilizza un agente che automaticamente viene inviato su tutti i siti disponibili nel momento in cui si accede a tale funzione. Dato che non c’è un tempo limite entro cui i vari server devono rispondere ci si trova a gestire una situazione dinamica che può variare di continuo, è infatti possibile che, mentre si sta aspettando il robot con la descrizione del database remoto, arrivi l’agente che contiene l’indirizzo di un server lontano e che questo venga accodato agli indirizzi che si possono scegliere.

 

 

 

Fig.6.2.2.2 Tool di descrizione remota

Dato che anche il client non è altro che un contesto di esecuzione specializzato non si discosta molto dal discorso fatto per il server, anche esso estende la super-classe ServerAgents e implementa l’interfaccia AgentListener, ma in più implementa anche l’interfaccia MouseListener ed ItemListener dato che essendo un’interfaccia grafica deve intercettare vari tipo di evento. Oltre a ciò il client risulta composto dall’oggetto FormPanel che rappresenta l’interfaccia grafica [fig.6.2.2.3].

 

 

 

Fig. 6.2.2.3 Rappresentazione ad oggetti (formalismo OMT) del client

Anche questa volta il metodo startAgent viene sovrascritto, ma in questo caso vengono fatti partire solo gli agenti di errore, servizio e risposta dato che l’applicazione client non deve processare agenti che non rientrano in dette categorie. Il metodo procede all’identificazione dell’agente tramite identify (restituisce sempre true) e poi verifica che il robot abbia degli eventi da lanciare, se supera i due controlli viene fatto partire.

È necessario che handleAgentEvent processi anche gli eventi di risposta, e che sia in grado di discriminare che tipo di robot ha lanciato tale evento; è per questo motivo che si effettua un controllo sull’agente che scatena l’evento, dopo di che si procede al suo trattamento. Se è un gente di ricerca si controlla che esso sia ancora valido e poi si aggiunge la risposta nel field opportuno del pannello di ricerca; mentre se siamo alle prese con un robot che si occupa della descrizione del database la risposta viene aggiunta al field del pannello del tool di descrizione; infine se si tratta di una gente che ricerca dei server attivi, il suo contenuto viene aggiunto alla lista opportuna del pannello di descrizione.

Il metodo mouseClicked viene ridefinito in modo che intercetti gli eventi di avvenuta pressione sui bottoni view ed deliver, per far ciò si effettua un controllo sull’oggetto che ha scatenato l’evento. Una volta individuato l’oggetto si richiama un metodo opportuno a seconda del tipo di bottone premuto. Nel caso in cui il bottone sorgente sia deliver viene richiamato un metodo che in base alla funzionalità attiva in quel momento sceglie il robot da inviare, mentre se il sorgente è view viene mandato in broadcast l’agente che si occupa di individuare i server attivi.

deliverTransactionQuery è il metodo che si occupa dell’invio dell’agente di ricerca sui server collegati, esso determina il tempo di validità del robot e ne inizializza i valori in modo che si riferisca ai dati del pannello di ricerca, dopo di che trasmette in broadcast a tutti i server l’agente appena istanziato.

Gli eventi degli altri bottoni vengono gestiti direttamente dalla GUI e dai pannelli opportuni.

6.2.3 Agenti

Sono stati sviluppati due tipi diversi di agenti di ricerca SearchQuery e TransactionQuery, il primo segue esattamente le specifiche che sono state proposte, mentre il secondo ha una principio di comportamento leggermente diverso ed in più può utilizzare le transazioni.

Entrambe gli agenti seguono comunque lo stesso schema di ereditarietà, estendono entrambi la classe Agent ed implementano le interfacce Cloneable e Serializzable [fig. 6.2.3.1].

 

Fig. 6.2.3.1 Rappresentazione ad oggetti (formalismo OMT) agente generico

La specializzazione dei due agenti è specificata nel metodo executeJob.

6.2.3.1 SearchQuery

Essenzialmente questo agente una volta eseguito apre una connessione con il DBMS gli propone la query e se ha avuto successo torna al client che l’ha generato. In caso la risposta del database sia nulla il robot migra sui server collegati all’ambiente di esecuzione, mentre se si verificassero degli errori automaticamente l’agente ritornerebbe alla stazione sorgente e qui genererebbe un evento di errore. Esistono vari tipi di errore: quelli derivanti dalla connessione con il DBMS locale che ad esempio potrebbe non condividere la struttura del database che si voleva interrogare o ad esempio quelli derivanti dalla migrazione del robot su altre piattaforme di esecuzione, ad esempio il server di destinazione non è attivo.

Il robot ha un tempo di vita prestabilito che è determinane per il controllo della profondità della ricerca, questo tempo di vita viene impostato dall’utente.

6.2.3.2 TransactionQuery

Una volta trasferito sul server di riferimento ed aver completato la fase di inizializzazione il robot procede e si trasferisce sui server collegati, dopo di che stabilisce una connessione con il DBMS locale e propone la query, a questo punto viene aspetta la risposta, ritorna al client padre e genera un evento risposta. Chiaramente sarà compito del client garantire che l’evento generato venga trattato regolarmente, nel caso in esame i dati dell’agente di risposta vengono accodati nel field delle risposte. Nel caso sia attivo il supporto per le transazioni il comportamento cambia significativamente. Anche il tempo di vita di questo robot viene impostato dall’utente.

Dato che si è stabilito che le operazione di inserimento e modifica del database devono essere fatte solo sul server di riferimento il robot non migra sui server collegati. L’utilizzo delle transazioni in java si ottiene specificando che la proprietà autocommit della connessione deve essere false, a questo punto tutte le query che vengono inviate sulla connessione vengono trattate come un’unica transazione che termina nel momento in cui venga inviato al DBMS un COMMIT o un ROLLBACK che rispettivamente confermano o revocano le operazioni fino a quel momento arrivate. Risulta evidente che è necessario mantenere attiva la connessione con il DBMS e riferirsi sempre a essa anche con gli agenti successivi a quello attivo, questo si ottiene conservando il riferimento alla connessione nell’area di memoria condivisa del server.

Essenzialmente il robot verifica se esiste una connessione attiva nell’area comune, verifica che la transazione gli appartenga, nel caso essa si quella cercata recupera il riferimento alla connessione; se non trova nessuna connessione ne richiede una al DBMS locale. Quando ha ottenuto la connessione propone la query al DBMS, avuta la risposta può effettuare il COMMIT, il ROLLBACK o memorizzare il riferimento della connessione. Dopo un COMMIT o un ROLLBACK il riferimento alla connessione viene tolto dalla memoria.

Dato che potrebbero sorgere degli imprevisti sarà a carico del server verificare periodicamente che non rimangano connessioni aperte per troppo tempo, questo avviene tramite un meccanismo di timing che consente di controllare le strutture di memoria predisposte per la gestione delle transazioni ad intervalli regolari.

Nel caso vi sia qualche errore durante l’esecuzione del robot sul server esso migra immediatamente al client e fa partire un evento di errore.

6.2.3.3 FindServers

Lo scopo di questo agente è quello di rilevare tutti i server che sono attivi sulla rete in uno specifico momento e identificare i database disponibili su ogni sito. Il tempo di vita del robot è illimitato, questo gli consente di scorrere su tutta la rete e di individuare tutti i nodi che la compongono. Come tutti gli agenti il fatto che un nodo venga visitato più di una volta è garantito da una struttura che tiene conto dei robot che hanno visitato il server; i robot vengono eliminati periodicamente dopo un certo tempo definito nelle proprietà di sistema che di norma è di poco superiore al tempo di propagazione massimo della rete.

Essenzialmente una volta che il robot è giunto su di un server migra immediatamente su server collegati dopo di che richiede i nomi di tutti i database disponibili e li memorizza in un vettore, a questo punto l’agente ritorna al client di partenza.

Una volta arrivato a destinazione il robot genera un evento di risposta che viene trattato dal client.

6.2.3.4 DatabaseDescription

Il robot in questione ha il compito di richiedere le informazioni necessarie per descrivere un database selezionato dall’utente, per espletare tale compito non gli è richiesto di migrare su altri server al di fuori di quello preselezionato. Visto che non c’è la necessità di controllare i livelli ricerca il robot non ha un tempo di vita.

Il principio di funzionamento è semplicissimo, il robot viene trasferito su server di destinazione , qui stabilisce una connessione con il DBMS e tramite il driver JDBC recupera le informazioni sul database impostato dall’utente. Una volta recuperati i dati esso torna alla volta del client dove genera un evento risposta che sarà intercettato dal destinatario stesso.

6.2.3.5 ActivateServer

Si tratta di un agente di servizio che fa parte del tool per la progettazione di sistemi ad agenti mobili, ha la funzione di avvertire dell’avvenuta attivazione di un server.

Viene inviato dal server stesso al momento della sua attivazione ed è inviato a tutti nodi ad esso collegati, giunto a destinazione il robot genererà un evento di servizio che verrà trattato direttamente dal nodi di destinazione. L’agente non migra per tutta la rete ma si ferma ai nodi direttamente collegati al server attivato; un diverso comportamento si può ottenere riscrivendo il metodo executeJob.

 

 

6.2.4 Tolleranza agli errori

Attualmente il sistema gode di una buona tolleranza agli errori anche se è possibile migliorarla attraverso l’aggiunta di componenti specifiche e di restrizioni nella strutturazione della maglia dei collegamenti. Una possibile aggiunta al sistema potrebbe essere quella di fare in modo che gli agenti indirizzati ad un server che in un dato momento non è attivo gli siano rispediti appena arriva la comunicazione di avvenuta attivazione.

Mi spiego meglio, attualmente la fase di migrazione degli agenti da un sistema all’altro avviene scorrendo uno alla volta gli elementi della lista dei nodi disponibili sul server, per ogni entri della stessa viene richiamato il metodo di migrazione dell’agente che provvede a trasferire una copia dell’agente sul sistema remoto selezionato, nel caso in cui il server remoto non sia attivo il comando di trasferimento genera un’eccezione che viene ignorata. Se ora si considera una serie di nodi collegati con uno non attivo ci si accorge che su tutti i robot arrivano su tutti i server ad esso collegati. Quello che si vuole ottenere è che nel momento in cui il server da comunicazione dell’avvenuta attivazione tutti i robot ancora "vivi" che precedentemente devono essere stati memorizzati in un’area di memoria ben definita vengano trasferiti al loro destinatario.

Questo si può ottenere in due modi: tenendo una lista dei robot non inviati e di tutti i nodi non attivi su ogni server, oppure mantenendo solo la lista degli agenti non inviati e modificare ActivateServer in modo che si faccia carico del recupero dei robot.

Nel primo caso la lista dei siti non attivi verrà percorsa periodicamente e verrà verificata l’avvenuta attivazione dei vari siti, dopo di che verranno spediti i robot memorizzati. Questa soluzione ha lo svantaggio evidente di non si essere in grado di inviare i robot in attesa subito dopo l’attivazione del server, dato che il timer di controllo avrà una certa cadenza stabilita e controllerà lo stato del server solo ad intervalli ben precisi. A questo inconveniente si potrebbe si può rimediare facendo in modo che il timer abbia cadenza molto ravvicinata, ma ciò impone un grande sacrificio in termini di risorse.

La seconda soluzione consiste nel modificare l’agente di ActivateServer in modo che sia esso stesso a recuperare i robot in attesa. Per fare ciò occorre che all’atto della migrazione degli agenti quelli che sollevano l’eccezione "server non attivo" vengano memorizzati nell’area di memoria del server che è comune a tutti i robot. A questo punto quando il nodo viene riattivato ActivateServer viene trasferito a tutti i server collegati, qui i robot preleverà gli agenti dall’area di memoria comune e li trasferirà al nodo sorgente. Questa soluzione ha lo svantaggio di dover imporre delle restrizione nella costruzione della rete, infatti perché questa architettura funzioni è necessario che tutti i nodi che si desidera collegare abbiano un doppio link [fig.6.2.4.1].

 

 

Fig. 6.2.4.1 Possibile mappatura rete

 

6.3 Realizzazione del sistema con tecnologia client/server

Anche in questo caso c’è l’esigenza di sviluppare due tipi di applicazioni: un client ed un server [fig.6.3.1].

Il client ha le seguenti funzioni:

Le azioni che il server deve compiere si articolano in:
Fig.6.3.1 Architettura del sistema


Fig. 6.3.2 Architettura del server

In questo tipo di soluzione l’interazione tra il sistema locale e quello remoto è gestito tramite dei protocolli di comunicazione che discriminano le diverse situazioni in che si possono presentare.

Il modulo di input intercetta le query provenienti dai siti distribuiti e dal client locale e le immette nella lista delle query da processare, oltre alla stringa SQL è necessario memorizzare anche l’indirizzo del client richiedente ed il livello di profondità della ricerca richiesto [fig. 6.3.2].

Il modulo di amministrazione richiede al gestore delle liste la prossima query da processare, verifica che essa non sia nella lista delle richieste già processate e la passa al modulo di interrogazione locale. A questo punto se la query ha avuto successo la risposta viene inviata al modulo di risposta che la invierà al destinatario, altrimenti viene passata al modulo di interrogazione remota che si occuperà dell’instradamento della query a tutti i siti collegati..

Tutte le operazioni che si svolgo sulle liste vengono fatte tramite il modulo di gestione delle liste che ha il compito di mantenere ordinate le liste e di eliminarne gli elementi trascorso un certo periodo di tempo impostato dall’amministratore del sistema. Il fatto di mantenere le query processate il una lista ha una doppia funzione:

6.5 Problemi di implementazione

I problemi di implementazione che sono stati riscontrati riguardano soprattutto aspetti particolari di implementazione delle classi Java quali ad esempio la serializzazione degli oggetti e loro portabilità.

6.5.1 Serializzazione

La serializzazione è una tecnica che permette di trasferire gli oggetti da un Java Virtual Machines (JVM) ad un’altra.

Per rendere una classe esportabile è necessario che quella classe, e tutte le classi da cui è formata, implementino l’interfaccia Serializzable.

In questo lavoro si sono utilizzate le classi che fanno parte del package sql che però non implementano detta interfaccia. Sostanzialmente è stato progettato un agente mobile che arriva sul server locale si collega ed interroga il DBMS, recupera i risultati e ritorna al conteso di partenza. I risultati vengono dati da un oggetto istanza della classe ResultSet che fa parte del package sql e come tale non implementa l’interfaccia Serializzable, è evidente che nel momento in cui l’agente viene trasferito da un contesto all’altro la JVM non permette che l’istanza di ResultSet venga trasferita.

Per ovviare a questo problema mi sono trovato costretto ad implementare una classe MyResultSet che viene creata sulla base di un oggetto ResultSet e ne memorizza i dati principali.

La stessa cosa si è verificata con le classi DatabaseMetaData e ReultSetMetaData, classi che restituiscono rispettivamente la descrizione del database che si sta utilizzando e dei risultati che si sono ottenuti dopo l’esecuzione di una query.

6.5.2 Portabilità

Si sono riscontrati problemi di portabilità del sistema nel momento in cui si è passati da Unix a Windows95, mentre non vi sono stati problemi con Linux.

I problemi sono derivati dall’utilizzo delle classi relative alla gestione dei calendari, che vengono utilizzate per verificare il tempo di validità di un agente.