1. Um pouco mais sobre o CORBA
3.IDL
A CORBA utiliza a IDL (Interface Definition Language), uma linguagem baseada em C++ que não possui algoritmos nem variáveis, ou seja, é puramente declarativa, e, portanto, é independente da linguagem de programação utilizada para acessá-la. Há padrão de IDL definido pelo OMG para C, C++, Java, TTCN, COBOL, Smalltalk, Ada, Lisp, Python e IDLscript. Possibilita a interoperabilidade entre os diversos sistemas, visto a separação que é definida entre interface e execução. A interface de cada objeto é definida de forma bastante específica, enquanto a sua execução (código fonte e dados) permanece oculta para o resto do sistema.
A partir do arquivo idl ( arquivo de texto ) o compilador cria a classe Evento , arquivos holder e helper além do arquivo POA e Stub , basicamente cada uma tem uma tarefa :

Vamos explicar essa classe parte por parte
Essa classe é o PSD1 por que tirei da implementação da estação 1 , a primeira coisa importante a dizer é que a classe implementa Runnable , isso por que ela vai funcionar como uma thread , alias esse sistema é cheio de threads o que requer muita atenção e cuidados extras , se vc não entende de threads recomento o artigo do GUJ Introdução ao sincronismo e monitores .
A classe também tem vários arraylists b1,b2, b3 é para armazenar as mensagens que chegam das estações , essas mensagens depois vão ser usadas na camada gráfica (GUI) , a mesma coisa acontece com o bufferDelivery que é o buffer onde ocorre a montagem da ordem total de entrega das mensagens segundo os relógios lógicos , na verdade o buffer de delivery é montado na classe servant mas é acessado concorrente mente com a classe PSD , e por isso usamos a classe Semaphore , semáforo são uma das formas de se controlar o acesso concorrente de processos em uma variável no caso o buffer de montagem , isso acontece no nosso projeto por que a medida que as mensagens vão chegando o buffer de delivery é montado e a aplicação vai pegando os valores colocados no buffer , tudo concorrentemente , veja que nesse ponto o complicado não é o sistema distribuído em si mas o acesso concorrente e o uso de varias threads .
Continuando na classe PSD ...
Depois que o servidor estiver funcionando iniciamos uma outra thread que é a thread de montagem do buffer delivery( ms.iniciarMontagem(); ) , essa thread está como uma classe interna do servant logo usamos a referencia ao servant para aciona-la no comando:
O próximo passo é iniciar o emissor de mensagem( Emissor em = new Emissor(args);) , novamente em uma thread (Thread tcliente = new Thread(em); ), ele vai ter o método que possibilita o envio das mensagens . Pelo mesmo motivo do anterior fazemos um join nessa thread , isso por que o emissor deve estar funcionando para que passemos para a próxima etapa do algoritmo que é gerar e enviar os enventos , se o emissor não estiver pronto vamos gerar os eventos e na hora de enviar vai dar erro .
Depois de inicializar o emissor ( também chamado de cliente ) iniciamos uma outra thread de montagem de buffer localmente ou seja , temos uma classe interna em PSD que vai tentar acessar o buffer de delivery conforme ele for montado e dessa forma "puxar"os valores da camada de serviço para a camada de aplicação ( new Thread(new GetBufferDelivery()).start(); ).
Nesse momento estamos com o aplicativo como a figura sugere
Como já estamos prontos para enviar as mensagens , montamos primeiramente um ArrayList com todos os evento , internos e mensagens , cada um segundo a especificação do problema, aqui cabe algumas explicações , o timestamp de cada evento esta zerado por que vai ser atualizado no momento do envio pela classe Emissor utilizando a classe Relógio . O ultimo elemento da lista é um X isso é um evento que não vai atualizar o relógio ele só é um sinalizador que a estação 1 já enviou tudo que tinha para enviar o timestamp dele é 100 para não interferir na hora de ordenar os eventos , na verdade qualquer numero alto serviria nesse caso . Finalmente o For final envia um a um os evento ao emissor , tanto os internos "e"quanto os externos "m", talvez ai a gente tenha perdido pontos no projeto já que um evento externo não precisava ser enviado só atualizado o relógio mas enviamos mesmo assim ....
O restante do código tem métodos gets e sets para as variáveis , um método que pega os semáforos usados nos buffers , um método que limpa todos os buffers ao final da operação para que a estação comece a transmitir tudo novamente, um método para desconectar do servidor de localização de objetos corba, um método utilitário que imprime os valores que estão nos buffers e finalmente a classe interna que puxa concorrentemente os valores do buffer de delivery
Vale a pena comentar o código da classe interna (GetBufferDelivery) , essa classe testa se o buffer de delivery no servant não está vazio , quanto não estiver vazio ela vai no servant e pega um evento no BFDelivery , claro que para isso ela aciona o semáforo correspondente para só ela conseguir acessar o BFD , cada valor puxado é adicionado no BufferDelivery local da classe PSD e também nos buffers individuais de cada emissor ( b1, b2, b3) , o processo termina quando a classe puxar um evento tipo x no BFD do servant .
Por enquanto é isso , nos próximos post vamos ver como funciona o relógio e as demais classes terminando com a classe de GUI , o código completo do PSD1 segue abaixo , até o próximo post.
CODIGO COMPLETO DA CLASSE PSD1
O padrão CORBA é um framework que
permite que aplicações distribuídas em uma rede (local ou mesmo na internet)
comuniquem-se entre si e troquem informações. Estas aplicações podem estar
sendo executadas em diferentes plataformas (Intel, Sun, etc) e sistemas
operacionais (Windows, Linux, Unix, etc) e podem ter sido construídas em
diferentes linguagens de programação.
Utilizando o padrão CORBA é possível ter
aplicações completamente distribuídas, potencialmente com cada pedaço de
software sendo executado em qualquer parte da rede e em qualquer plataforma,
sem que o usuário perceba que isto está acontecendo e sem que o desenvolvedor
precise se preocupar em criar soluções que resolvam os problemas de
interoperabilidade entre os diferentes pedaços da aplicação. Atualmente,
diversas ferramentas já suportam o padrão CORBA, como Delphi 4, JBuilder 2,
Oracle 8i, Cold Fusion e C++ Builder. Uma grande vantagem de CORBA é ser um
padrão diretamente suportado por empresas em todo o mundo e com dezenas de
implementações disponíveis, incluindo algumas gratuitas. Na
prática, essa padronização significa que você não precisa ficar preso a
determinados fornecedores, plataformas ou produtos, como acontece quando são
escolhidas soluções proprietárias.
2. ORB
A arquitetura CORBA define o ORB (Object Request Broker) como um módulo intermediário entre cliente e objeto, sendo responsável em aceitar a requisição do cliente, enviá-la para o objeto competente e, assim que disponível a resposta, entregá-la para o cliente.
3.IDL
A CORBA utiliza a IDL (Interface Definition Language), uma linguagem baseada em C++ que não possui algoritmos nem variáveis, ou seja, é puramente declarativa, e, portanto, é independente da linguagem de programação utilizada para acessá-la. Há padrão de IDL definido pelo OMG para C, C++, Java, TTCN, COBOL, Smalltalk, Ada, Lisp, Python e IDLscript. Possibilita a interoperabilidade entre os diversos sistemas, visto a separação que é definida entre interface e execução. A interface de cada objeto é definida de forma bastante específica, enquanto a sua execução (código fonte e dados) permanece oculta para o resto do sistema.
4.Primeiros passos
A primeira coisa que definimos é que já que o CORBA suporta o paradigma de orientação a objetos , vamos "enviar objetos mensagens" de uma estação para outra , isso vai tornar muito mais fácil o tratamento das mensagens quando elas chegarem nas estações , colocamos enviar objetos entre aspas porque o CORBA não faz exatamente isso, mas vamos explicar isso em momento oportuno.
Definido o formato da mensagem precisamos criar o arquivo IDL (Interface Definition Language), que vai definir como vai acontecer a troca de informação entre as estações , no nosso projeto o arquivo ficou da seguinte forma:
struct Evento{ string tipo; long timestamp; long origem; long ordemEnvio; }; interface Mensagem{ void sendMensagem(in Evento ev); };
Nomeamos o arquivo IDL como Mensagem.idl , o objeto mensagem está espelhado na Struct Evento , como a IDL é baseada em C++ temos que usar structs quando quisermos manipular objetos , nesse caso nosso objeto será Evento e ele terá os seguintes campos :
Depois de definir a struct definimos a interface Mensagem , essa interface será mapeada em diversas classes holder e stubs que mostraremos a seguir , dentro da interface temos um método abstrato sendMensagem ( in Evento ev) ... a escolha do nome do método não foi feliz na verdade ele devia ser mudado para receiveMensagem , quando analisarmos o código vai dar para ver isso melhor ... continuando o in Evento ev significa que o método recebe um Evento ev e que só serve para receber ou seja é um método de entrada de dados ( input ) por isso o in.
O projeto foi todo desenvolvido usando o Netbeans , então criamos um projeto java e um pacote que chamamos de PSD ( projeto de sistemas distribuídos - olha a criatividade ai :-) ) , depois de criar esse projeto criamos o arquivo Mensagem.idl ...
O próximo passo é usar o compilador IDL que vai ler o arquivo e gerar as classes auxiliares necessárias, para isso utilizamos o prompt de comando ou o terminal (no meu caso) , entramos na pasta que contem os arquivos e digitamos o comando: idlj -fall Mensagem.idl ( veja a figura abaixo)
O compilador IDL vai gerar todas as classes auxiliares necessárias ao projeto , veja abaixo como ficou a pasta do projeto depois da compilação do arquivo idl.
- tipo: pode assumir 'e' no caso de evento interno ou 'm' no caso de mensagem sendo enviada para as outras estações.
- timestamp : leva o timestamp indicando o momento ( de acordo com o relógio lógico de lamport) quando o evento ocorreu .
- origem : indica de onde está vindo a mensagem
- ordem de envio : indica a ordem local do evento , 1º , 2º , 3º evento a ocorrer na estação "x" e assim sucessivamente.
Depois de definir a struct definimos a interface Mensagem , essa interface será mapeada em diversas classes holder e stubs que mostraremos a seguir , dentro da interface temos um método abstrato sendMensagem ( in Evento ev) ... a escolha do nome do método não foi feliz na verdade ele devia ser mudado para receiveMensagem , quando analisarmos o código vai dar para ver isso melhor ... continuando o in Evento ev significa que o método recebe um Evento ev e que só serve para receber ou seja é um método de entrada de dados ( input ) por isso o in.
O projeto foi todo desenvolvido usando o Netbeans , então criamos um projeto java e um pacote que chamamos de PSD ( projeto de sistemas distribuídos - olha a criatividade ai :-) ) , depois de criar esse projeto criamos o arquivo Mensagem.idl ...
O próximo passo é usar o compilador IDL que vai ler o arquivo e gerar as classes auxiliares necessárias, para isso utilizamos o prompt de comando ou o terminal (no meu caso) , entramos na pasta que contem os arquivos e digitamos o comando: idlj -fall Mensagem.idl ( veja a figura abaixo)
O compilador IDL vai gerar todas as classes auxiliares necessárias ao projeto , veja abaixo como ficou a pasta do projeto depois da compilação do arquivo idl.
A partir do arquivo idl ( arquivo de texto ) o compilador cria a classe Evento , arquivos holder e helper além do arquivo POA e Stub , basicamente cada uma tem uma tarefa :
- POA : Esta classe abstrata é baseada no esqueleto do servidor. Extende org.omg.PortableServer.Servant, e implementa a interface InvokeHandler e a interface MensagemOperations. A classe de servidor, HelloServant, extende MensagemPOA
- Holder e Helper : implementam operações necessárias a comunicação em corba .
- Stub : é a classe responsável por serializar e deserealizar os objetos no momento da transmissão , o corba na verdade não envia objetos de uma estação para outra , ele envia um streaming de bytes que podem depois ser convertidos para objetos java , com o uso do stubs isso fica transparente para o programandor.
- Operations : Esta interface contém o método sendMessage() . O idlj coloca as operações definidas na interface IDL dentro este arquivo, que é compartilhado por ambos o stubs e esqueletos.

Na camada de aplicação colocamos uma classe apenas chamada PSD , ela vai ativar na camada de serviço as classes de servidor e emissor como a figura abaixo :
Acima da PSD temos a camada de GUI ( Graphical User Interface ) que foge do escopo do artigo mas que deve ser mostrada no ultimo post , na camada de servico temos as seguintes classes:
Servidor : aciona o servidor da aplicação e publica o objeto no servidor de nomes
Emissor : recebe os eventos do PSD
Relógio : implementação do relógio lógico de lamport , acessado tanto pela classe servant quanto pelo emissor.
Servant: esse é o servidor propriamente dito , ele vai receber as mensagens e montar o buffer de delivery das 3 estações .
Acima da PSD temos a camada de GUI ( Graphical User Interface ) que foge do escopo do artigo mas que deve ser mostrada no ultimo post , na camada de servico temos as seguintes classes:
Servidor : aciona o servidor da aplicação e publica o objeto no servidor de nomes
Emissor : recebe os eventos do PSD
Relógio : implementação do relógio lógico de lamport , acessado tanto pela classe servant quanto pelo emissor.
Servant: esse é o servidor propriamente dito , ele vai receber as mensagens e montar o buffer de delivery das 3 estações .
5. Classe PSD ( camada de aplicação ) :
Vamos explicar essa classe parte por parte
package psd8; import java.util.ArrayList; import java.util.concurrent.Semaphore; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author Joao */ public class PSD1 implements Runnable{ /** * @param args the command line arguments */ boolean imprimiu = false; private ArrayListbuffertmp = new ArrayList (); ServidorMensagem servm; MensagemServant ms = new MensagemServant(); private static ArrayList b1 = new ArrayList (); private static ArrayList b2 = new ArrayList (); private static ArrayList b3 = new ArrayList (); private static ArrayList bufferDelivery = new ArrayList (); private static boolean bufferNaoMontado = true; private static Semaphore semBD ; private static boolean terminar = false;
Essa classe é o PSD1 por que tirei da implementação da estação 1 , a primeira coisa importante a dizer é que a classe implementa Runnable , isso por que ela vai funcionar como uma thread , alias esse sistema é cheio de threads o que requer muita atenção e cuidados extras , se vc não entende de threads recomento o artigo do GUJ Introdução ao sincronismo e monitores .
A classe também tem vários arraylists b1,b2, b3 é para armazenar as mensagens que chegam das estações , essas mensagens depois vão ser usadas na camada gráfica (GUI) , a mesma coisa acontece com o bufferDelivery que é o buffer onde ocorre a montagem da ordem total de entrega das mensagens segundo os relógios lógicos , na verdade o buffer de delivery é montado na classe servant mas é acessado concorrente mente com a classe PSD , e por isso usamos a classe Semaphore , semáforo são uma das formas de se controlar o acesso concorrente de processos em uma variável no caso o buffer de montagem , isso acontece no nosso projeto por que a medida que as mensagens vão chegando o buffer de delivery é montado e a aplicação vai pegando os valores colocados no buffer , tudo concorrentemente , veja que nesse ponto o complicado não é o sistema distribuído em si mas o acesso concorrente e o uso de varias threads .
Continuando na classe PSD ...
public void run() { this.iniciar(); } public void iniciar( ){
Esse método run deve ser implementado em cada classe que implemente Runnable quando a thead desse processo começar a rodar é esse método run que vai rodar primeiro , no nosso programa ele chama o método iniciar ...
Inicialmente o psd inicializa o relógio lógico ( Relogio.initRelogio(); ) que deve começar com timestamp = 0 e ir avançando conforme os eventos internos e mensagens ocorrem , logo depois o psd instanciá a classe Servidor que é responsável por publicar o objeto remoto no servidor de objetos corba ( falamos dele daqui a pouco) , o servidor é instanciado atravez de uma thread , o comando tservidor.join(); obriga a thread atual aguardar a finalização da thread do servidor , isso é necessário por que logo mais vamos chamar o emissor e não podemos começar a emitir as mensagens sem que o servidor esteja "no ar ".
public void iniciar(){ String[] args=null; Relogio.initRelogio();//inicia o relógio logico de Lamport //instancia um servidor que ira publicar as mensagens e criar o servant servm = new ServidorMensagem(args); Thread tservidor = new Thread(servm); tservidor.setName("Thread do servidor"); tservidor.start(); try { tservidor.join(); //aguarda aqui até a thread do servidor teminar isso é necessario //para que não se tente rodar a thread cliente antes de registar //os objetos no servidor de nomes } catch (InterruptedException ex) { Logger.getLogger(PSD1.class.getName()).log(Level.SEVERE, null, ex); } //iniciar o montador de bufferFinal ms.iniciarMontagem(); Emissor em = new Emissor(args); Thread tcliente = new Thread(em); tcliente.setName("Thread do cliente"); tcliente.start(); try { tcliente.join(); //aguarda o cliente terminar de transmitir a mensagem } catch (InterruptedException ex) { Logger.getLogger(PSD1.class.getName()).log(Level.SEVERE, null, ex); } //já pronto para enviar mensagens //thread para acesso ao buffer de delivery no servant new Thread(new GetBufferDelivery()).start(); //String _tipo, int _timestamp, int _origem, int _ordemEnvio ArrayListlista = new ArrayList (); Evento e1 = new Evento("e",0, 1,1); lista.add(e1); Evento e2 = new Evento("m",0, 1,2); lista.add(e2); Evento e3 = new Evento("m",0, 1,3); lista.add(e3); Evento e4 = new Evento("e",0, 1,4); lista.add(e4); Evento e5 = new Evento("m",0, 1,5); lista.add(e5); Evento e6 = new Evento("m",0, 1,6); lista.add(e6); Evento e7 = new Evento("x",100, 1,7); lista.add(e7); //enviar eventos for (Evento ev : lista) { em.enviarMensagem(ev); } }
Inicialmente o psd inicializa o relógio lógico ( Relogio.initRelogio(); ) que deve começar com timestamp = 0 e ir avançando conforme os eventos internos e mensagens ocorrem , logo depois o psd instanciá a classe Servidor que é responsável por publicar o objeto remoto no servidor de objetos corba ( falamos dele daqui a pouco) , o servidor é instanciado atravez de uma thread , o comando tservidor.join(); obriga a thread atual aguardar a finalização da thread do servidor , isso é necessário por que logo mais vamos chamar o emissor e não podemos começar a emitir as mensagens sem que o servidor esteja "no ar ".
Depois que o servidor estiver funcionando iniciamos uma outra thread que é a thread de montagem do buffer delivery( ms.iniciarMontagem(); ) , essa thread está como uma classe interna do servant logo usamos a referencia ao servant para aciona-la no comando:
O próximo passo é iniciar o emissor de mensagem( Emissor em = new Emissor(args);) , novamente em uma thread (Thread tcliente = new Thread(em); ), ele vai ter o método que possibilita o envio das mensagens . Pelo mesmo motivo do anterior fazemos um join nessa thread , isso por que o emissor deve estar funcionando para que passemos para a próxima etapa do algoritmo que é gerar e enviar os enventos , se o emissor não estiver pronto vamos gerar os eventos e na hora de enviar vai dar erro .
Depois de inicializar o emissor ( também chamado de cliente ) iniciamos uma outra thread de montagem de buffer localmente ou seja , temos uma classe interna em PSD que vai tentar acessar o buffer de delivery conforme ele for montado e dessa forma "puxar"os valores da camada de serviço para a camada de aplicação ( new Thread(new GetBufferDelivery()).start(); ).
Nesse momento estamos com o aplicativo como a figura sugere
Como já estamos prontos para enviar as mensagens , montamos primeiramente um ArrayList com todos os evento , internos e mensagens , cada um segundo a especificação do problema, aqui cabe algumas explicações , o timestamp de cada evento esta zerado por que vai ser atualizado no momento do envio pela classe Emissor utilizando a classe Relógio . O ultimo elemento da lista é um X isso é um evento que não vai atualizar o relógio ele só é um sinalizador que a estação 1 já enviou tudo que tinha para enviar o timestamp dele é 100 para não interferir na hora de ordenar os eventos , na verdade qualquer numero alto serviria nesse caso . Finalmente o For final envia um a um os evento ao emissor , tanto os internos "e"quanto os externos "m", talvez ai a gente tenha perdido pontos no projeto já que um evento externo não precisava ser enviado só atualizado o relógio mas enviamos mesmo assim ....
O restante do código tem métodos gets e sets para as variáveis , um método que pega os semáforos usados nos buffers , um método que limpa todos os buffers ao final da operação para que a estação comece a transmitir tudo novamente, um método para desconectar do servidor de localização de objetos corba, um método utilitário que imprime os valores que estão nos buffers e finalmente a classe interna que puxa concorrentemente os valores do buffer de delivery
public void desconectar(){ servm.unbindNoServidor(); } public void getSemaforos(){ semBD = MensagemServant.getSemBD(); } public static void insertValorB1(Evento e) { b1.add(e); } public static void insertValorB2(Evento e) { b2.add(e); } public static void insertValorB3(Evento e) { b3.add(e); } public static void insertValorbufferDelivery(Evento e) { bufferDelivery.add(e); } //metodos para uso da Interface grafica public static ArrayListgetB1() { return b1; } public static ArrayList getB2() { return b2; } public static ArrayList getB3() { return b3; } public static ArrayList getBufferDelivery() { return bufferDelivery; } public static boolean isBufferNaoMontado() { return bufferNaoMontado; } public static void imprimirDadosPSD(){ System.out.println("Imprimindo buffer de Delivery no PSD!!!!!!!!"); System.out.println("Tamanho do Buffer:"+ bufferDelivery.size() ); for (Evento ev : bufferDelivery) { System.out.println( ev.tipo +ev.ordemEnvio + ev.origem +":" + ev.timestamp +","+ev.origem ); } System.out.println("Imprimindo Buffer 1:"); for (Evento ev : b1) { System.out.println( ev.tipo +ev.ordemEnvio + ev.origem +":" + ev.timestamp +","+ev.origem ); } System.out.println("Imprimindo Buffer 2:"); for (Evento ev : b2) { System.out.println( ev.tipo +ev.ordemEnvio + ev.origem +":" + ev.timestamp +","+ev.origem ); } System.out.println("Imprimindo Buffer 3:"); for (Evento ev : b3) { System.out.println( ev.tipo +ev.ordemEnvio + ev.origem +":" + ev.timestamp +","+ev.origem ); } bufferNaoMontado = false; } public void limparBuffers(){ b1.removeAll(b1); b2.removeAll(b2); b3.removeAll(b3); bufferDelivery.removeAll(bufferDelivery); bufferNaoMontado = true; terminar = false; } public class GetBufferDelivery implements Runnable{ public void run() { getSemaforos(); while(true){ if(ms.getTamanhoBufferDelivery() != 0 ){ // puxar elemento por elemento try { semBD.acquire(); } catch (InterruptedException ex) { Logger.getLogger(PSD1.class.getName()).log(Level.SEVERE, null, ex); } Evento e = ms.getValorNoBufferDelivery(); if(e.tipo.compareToIgnoreCase("x")==0){ terminar = true; //termina thread e nao adiciona eventos nos buffers }else{ bufferDelivery.add(e); if (e.origem == 1) { b1.add(e); } else if (e.origem == 2) { b2.add(e); } else if (e.origem == 3){ b3.add(e); } } semBD.release(); } if(terminar){ imprimirDadosPSD(); break; } }//fim do while }
Vale a pena comentar o código da classe interna (GetBufferDelivery) , essa classe testa se o buffer de delivery no servant não está vazio , quanto não estiver vazio ela vai no servant e pega um evento no BFDelivery , claro que para isso ela aciona o semáforo correspondente para só ela conseguir acessar o BFD , cada valor puxado é adicionado no BufferDelivery local da classe PSD e também nos buffers individuais de cada emissor ( b1, b2, b3) , o processo termina quando a classe puxar um evento tipo x no BFD do servant .
Por enquanto é isso , nos próximos post vamos ver como funciona o relógio e as demais classes terminando com a classe de GUI , o código completo do PSD1 segue abaixo , até o próximo post.
CODIGO COMPLETO DA CLASSE PSD1
package psd8; import java.util.ArrayList; import java.util.concurrent.Semaphore; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author Joao */ public class PSD1 implements Runnable{ /** * @param args the command line arguments */ boolean imprimiu = false; private ArrayListbuffertmp = new ArrayList (); ServidorMensagem servm; MensagemServant ms = new MensagemServant(); private static ArrayList b1 = new ArrayList (); private static ArrayList b2 = new ArrayList (); private static ArrayList b3 = new ArrayList (); private static ArrayList bufferDelivery = new ArrayList (); private static boolean bufferNaoMontado = true; private static Semaphore semBD ; private static boolean terminar = false; public void run() { this.iniciar(); } public void iniciar(){ String[] args=null; Relogio.initRelogio();//inicia o relogio logico de Lamport servm = new ServidorMensagem(args); Thread tservidor = new Thread(servm); tservidor.setName("Thread do servidor"); tservidor.start(); try { tservidor.join(); //aguarda aqui até a thread do servidor teminar isso é necessario //para que não se tente rodar a thread cliente antes de registar //os objetos no servidor de nomes } catch (InterruptedException ex) { Logger.getLogger(PSD1.class.getName()).log(Level.SEVERE, null, ex); } //iniciar o montador de bufferFinal ms.iniciarMontagem(); Emissor em = new Emissor(args); Thread tcliente = new Thread(em); tcliente.setName("Thread do cliente"); tcliente.start(); try { tcliente.join(); //aguarda o cliente terminar de transmitir a mensagem } catch (InterruptedException ex) { Logger.getLogger(PSD1.class.getName()).log(Level.SEVERE, null, ex); } //já pronto para enviar mensagens //thread para acesso ao buffer de delivery no servant new Thread(new GetBufferDelivery()).start(); //String _tipo, int _timestamp, int _origem, int _ordemEnvio ArrayList lista = new ArrayList (); Evento e1 = new Evento("e",0, 1,1); lista.add(e1); Evento e2 = new Evento("m",0, 1,2); lista.add(e2); Evento e3 = new Evento("m",0, 1,3); lista.add(e3); Evento e4 = new Evento("e",0, 1,4); lista.add(e4); Evento e5 = new Evento("m",0, 1,5); lista.add(e5); Evento e6 = new Evento("m",0, 1,6); lista.add(e6); Evento e7 = new Evento("x",100, 1,7); lista.add(e7); //enviar eventos for (Evento ev : lista) { em.enviarMensagem(ev); } } public void desconectar(){ servm.unbindNoServidor(); } public void getSemaforos(){ semBD = MensagemServant.getSemBD(); } public static void insertValorB1(Evento e) { b1.add(e); } public static void insertValorB2(Evento e) { b2.add(e); } public static void insertValorB3(Evento e) { b3.add(e); } public static void insertValorbufferDelivery(Evento e) { bufferDelivery.add(e); } //metodos para uso da Interface grafica public static ArrayList getB1() { return b1; } public static ArrayList getB2() { return b2; } public static ArrayList getB3() { return b3; } public static ArrayList getBufferDelivery() { return bufferDelivery; } public static boolean isBufferNaoMontado() { return bufferNaoMontado; } public static void imprimirDadosPSD(){ System.out.println("Imprimindo buffer de Delivery no PSD!!!!!!!!"); System.out.println("Tamanho do Buffer:"+ bufferDelivery.size() ); for (Evento ev : bufferDelivery) { System.out.println( ev.tipo +ev.ordemEnvio + ev.origem +":" + ev.timestamp +","+ev.origem ); } System.out.println("Imprimindo Buffer 1:"); for (Evento ev : b1) { System.out.println( ev.tipo +ev.ordemEnvio + ev.origem +":" + ev.timestamp +","+ev.origem ); } System.out.println("Imprimindo Buffer 2:"); for (Evento ev : b2) { System.out.println( ev.tipo +ev.ordemEnvio + ev.origem +":" + ev.timestamp +","+ev.origem ); } System.out.println("Imprimindo Buffer 3:"); for (Evento ev : b3) { System.out.println( ev.tipo +ev.ordemEnvio + ev.origem +":" + ev.timestamp +","+ev.origem ); } bufferNaoMontado = false; } public void limparBuffers(){ b1.removeAll(b1); b2.removeAll(b2); b3.removeAll(b3); bufferDelivery.removeAll(bufferDelivery); bufferNaoMontado = true; terminar = false; } public class GetBufferDelivery implements Runnable{ public void run() { getSemaforos(); while(true){ if(ms.getTamanhoBufferDelivery() != 0 ){ // puxar elemento por elemento try { semBD.acquire(); } catch (InterruptedException ex) { Logger.getLogger(PSD1.class.getName()).log(Level.SEVERE, null, ex); } Evento e = ms.getValorNoBufferDelivery(); if(e.tipo.compareToIgnoreCase("x")==0){ terminar = true; //termina thread e nao adiciona eventos nos buffers }else{ bufferDelivery.add(e); if (e.origem == 1) { b1.add(e); } else if (e.origem == 2) { b2.add(e); } else if (e.origem == 3){ b3.add(e); } } semBD.release(); } if(terminar){ imprimirDadosPSD(); break; } }//fim do while } } }
Gostei muito, continue escrevendo!
ResponderExcluir