• Nenhum resultado encontrado

Uma Visão Geral da Aplicação GRAM

5.5 IMPLEMENTAÇÃO DO GRAM

5.5.2 Uma Visão Geral da Aplicação GRAM

A aplicação GRAM é composta de dois programas separados: um servidor e um agente. O servidor representa a estrutura da plataforma AVM. A sua função principal é receber os agentes, executar suas tarefas e enviar-los a uma outra estação vizinha.

143

5.5.2.1 O SERVIDOR OU PLATAFORMA AVM

Ela é instalada em todos as estações do ambiente de gerenciamento do GRAM e possui diversas características funcionais que podem ser utilzadas dependendo da complexidade das tarefas especificadas pelos agentes (seção 5.4.2.3). Essas características são apresentadas em 4 pacotes: java.rmi, java.rmi.server, java.rmi.dgc, java.rmi.registry. Junto com elas, são definidas cerca de 25 interfaces e classes. A boa noticia é que mais da metade desses elementos não precisa ser reescrita e nem compreendida a cada implementação de uma nova aplicação GRAM. Na especificação de nossa aplicação teste, para implementar a migração de um agente, foram definidas duas interfaces e uma classe.

Figura 5.11: Interface Gráfica do Menu Enviar Agentes

Figura 5.12: Interface Gráfiga do Menu de Visualização dos resultados 5.5.2.1.1 AS INTERFACES

As duas interfaces definidas são as seguintes: a interface Monitoração para o servidor e a interface Leitura para o agente. A Monitoração estabelece a conexão entre as entidades

144

servidor e agente definindo, uma visão deste sobre a classe servidor instânciada ou objeto remoto. Enquanto a Leitura, ela inicia a execução da tarefa do agente.

A interface Monitoração define dois métodos que podem ser invocados remotamente pelos agentes para submeter suas tarefas ao servidor. Os métodos são os seguintes: o

recebeAgente (Leitura t) e o meEnvia ( Leitura t, String host). A tranformação dessas operações em

metodos remotos é especificada na Monitoração pela clausura Monitoração extends Remote. A função do metodo recebeAgente (Leitura t ) é receber a partir da sua invocação a tarefa do agente que é passado por valor ou copie e executar-la no servidor. O metodo meEnvia (Leitura t, String host ) recepciona a tarefa do agente e envia-la para a proxima estação aonde será executada. Para garantir um processo de chamado remoto confiável, um mecanismo de controle de erros e exeções foi definido para cada metodo através da clausura throws

RemoteException. Segue abaixo a estrutura de implementação da interface Monitoração. package monitoração;

import java.rmi.Remote;

import java.rmi.RemoteException;

public interface Monitoração extends Remote {

void recebeAgente(Leitura t) throws RemoteException; void meEnvia(Leitura t, String host) throws RemoteException; }

A segunda interface apresentada define o tipo Leitura. Esse tipo é usado como argumento para os dois metodos da interface Monitoração para passar por valor a tarefa do agente. A interface Leitura define um único metodo, init(Monitoração server ) que executa a função de leitura do conteudo de um arquivo e se estende a interface java.rmi.serialization para tranportar o código do Agente ou objeto local byte por byte entre duas estações. A Leitura possui a seguinte especificação:

Package monitoração; Import java..io.Serializable;

Public interface Leitura extends Serializable { Void init(Monitoração server); }

145

A classe servidor ou MonitoraçãoServidor é utilizada para implementar os métodos remotos definidos na interface Monitoração e demais outros métodos como: o main (String[]args ) e o MonitoraçãoServidor ( ).

O metodo main( ) inicializa a classe MonitorçãoServidor. A sua função principal é criar e instalar um gerente de segurança, instanciar a classe MonitoraçãoServidor para tornar-la disponível para a classe Agente e registrar os metodos a serem invocados pelos agentes. A criação e instalação do gerente de segurança é o primeiro comando executado pelo main( ). Ele protege os recursos da estação que suporta a classe servidor contra agentes móveis indevidos determinando assim, os arquivos do sistema que podem ser acessados ou qualquer outras operações que serão executadas. Depois desta operação, uma instançia da classe

MonitoraçãoServidor é criada para preparar-a a receber chamada vindo do agente. A estrutura

deste comando é: Monitoração servidor = new MonitoraçãoServidor ( ). Para que as chamadas dos metodos remotos possam ser realizadas pelos agentes, cada um desses metodos são referênciados por nome no objeto remoto. A referênciação é feita pelo metodo

Naming.rebind(name, servidor). O primeiro argumento deste metodo identifica a estação

(nome e número de porta) que suporta o objeto remoto MonitoraçãoServidor e o segundo, é o nome de referência do metodo remoto.

O metodo MonitoraçãoServidor( ) é o construtor da classe servidor. Ele realiza a inicialização do objeto MonitoraçãoServidor. Todo objeto têm um construtor e ele tem sempre o mesmo nome que a classe.

Os metodos recebeAgente ( Leitura t ) e meEnvia(Leitura t, String host ) são considerados os metodos remotos de nossa aplicação GRAM. O primeiro executa a tarefa do agente através do metodo init (this), e o segundo envia esta tarefa para estação destino onde será executada. Nesta operação a estação é localizada por intermédio do metodo

N aming.Lookup (nome). Uma vez encontrada o host, a operação obj.recebeAgente (t ) que está no

objeto remoto MonitoraçãoServidor na estação inicial é invocada para transferir a tarefa do agente ao seu ponto destino onde será executado. É neste processo que acontece a migração do agente. Este procedimento pode prosseguir enquanto existe uma estação para a migração do agente. A implementação completa da classe MonitoraçãoServidor é apresentada no anexo I.

5.5.2.2 CLASSES DO AGENTE

Essa classe é responsável pela especificação das tarefas do agente. Nela são definidas as funções do agente, a lista de estações a ser visitada pelo agente durante a sua fase

146

de migração, o comando de localização da proxima estação e a invocação dos metodos remotos.

Na implementação da aplicação de teste do GRAM, duas classes foram definidas para representar o agente: a classe Ler que implementa a tarefa de Leitura e, a classe

ExecutarLer que inicia a migração do agente.

A classe Ler define a lista de estações visitadas, os nomes dos arquivos a serem lidos, o metodo construtor Ler( String home) para inicialização da classe e metodo init (Monitoração server ) que implementa a tarefa de leitura. É neste metodo que é feita o controle da migração do agente. O trecho de código a seguir define o mecanismo de controle:

if (!home.equals(hosts[indice])) { try {

indice++;

server.meEnvia(this, hosts[indice]); }catch(Exception e) {

System.out.println("Erro me enviando. Ler.java"); }

} else {

System.out.println(" ");

System.out.println("Estou em casa. Passei em:"); System.out.println(" ");

for (int j=0; j<hosts.length; j++) { System.out.println(hosts[j]);

}

A estrutura deste programa compara antes da migração do agente o nome de sua estação origem com a estação destino. Se os dois nomes são iguais, então o agente está no seu ponto de partida. Caso não for, o agente migra para a proxima estação atraves da chamada server.meEnvia(this, hosts[indice])

A classe ExecutarLer procova a primeira migração do agente. As outras migrações são especificadas dentro do classe Ler.

A estrutura completa da duas classes é apresentada no anexo II.