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 ArrayList buffertmp = 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
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);
}
}
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 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
}
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 ArrayList buffertmp = 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