/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package algoritmoricartagrawala;
import java.io.IOException;
import static java.lang.Math.random;
import static java.lang.StrictMath.random;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
/**
*
* @author giovanne.gaspareto
*/
public class AlgoritmoRicartAgrawala {
static InetAddress grupo;
static MulticastSocket s;
static DatagramPacket msg;
static DatagramPacket recv;
private static Scanner keyboard;
static boolean executarProcesso = true;
static boolean aguardaPermissaoRegiaoCritica = false;
static boolean regiaoCritica = false;
static final String GROUP_IP = "224.0.0.1";
static final int MULTICAST_PORT = 2000;
static int IDProcesso = 0;
static String mensagem = "";
static int numeroProcessosGrupo = 0;
static int tempoRandom = 0;
static int idProcessoNaRegiaoCritica = 0;
static int idRecebido = 0;
static int proximo = 0;
static final String OK_STRING = "ok";
static final String DESCONECTAR_STRING = "q";
static final String DIVISOR_STRING = ";";
static final String GRUPO_COMPLETO_STRING = "gc";
static final String EXISTE_PROCESSO_REGIAO_CRITICA = "regiao critica";
static final String REQUISICAO_REG_CRITICA_STRING = "rc";
static final String SAINDO_REGIAO_CRITICA_STRING = "sc";
static final String ENTROU_REGIAO_CRITICA_STRING = "ec";
static final int NOVO_MEMBRO = 1;
static final int GRUPO_COMPLETO = 2;
static final int REQUISICAO_REG_CRITICA = 3;
static final int SAINDO_REGIAO_CRITICA = 4;
static final int ENTROU_REGIAO_CRITICA = 5;
static List<Integer> listaEsperaRegiaoCritica = new ArrayList<Integer>(); //lista com IDs dos processos aguardando pela regiao critica
public static String receiveMessageGroup(){
byte[] buf=new byte[1000];
recv=new DatagramPacket(buf, buf.length);
try {
s.setSoTimeout(10);
s.setLoopbackMode(false);
// System.out.println("timeout no recevei sem nada: " + s.getSoTimeout());
s.receive(recv);
byte[] dest=new byte[recv.getLength()];
System.arraycopy(recv.getData(), 0, dest, 0, dest.length);
String mensagemRecebida = new String(recv.getData(),recv.getOffset(),recv.getLength());
// System.err.println("Mensagen recebida: "+ mensagemRecebida);
return mensagemRecebida;
} catch (SocketTimeoutException ex) {
// Logger.getLogger(ProcessoSender.class.getName()).log(Level.SEVERE, null, ex);
return "x;0;0";
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "x;0;0";
}
}
public static void sendMessageGroup(String msgStr) {
msg=new DatagramPacket(msgStr.getBytes(), msgStr.length(),grupo, 2000);
// System.out.println("Enviando mensagem para o grupo ...");
try {
s.send(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//Funcao de configuracao
public static void setUp() {
try {
System.setProperty("java.net.preferIPv4Stack", "true"); // somente pra mac no wifi
grupo=InetAddress.getByName(GROUP_IP);
s=new MulticastSocket(MULTICAST_PORT);
System.err.println("Entrando no grupo ...");
s.joinGroup(grupo);
System.err.println("Ok.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static int geraRandomEntre(int min, int max){
Random rn = new Random();
return rn.nextInt(max-min+1)+min;
}
/**
* @param args the command line arguments
*/
public static int trataMensagem(String mensagemRecebida, DatagramPacket PacketLider){
String[] partes = mensagemRecebida.split(DIVISOR_STRING);
String operacao = partes[0];
String mensagem = partes[1];
idRecebido = Integer.parseInt(mensagem);
if(operacao.equals(OK_STRING)){
return NOVO_MEMBRO;
}
else if(operacao.equals(GRUPO_COMPLETO_STRING)){
return GRUPO_COMPLETO;
}else if(operacao.equals(REQUISICAO_REG_CRITICA_STRING)){
return REQUISICAO_REG_CRITICA;
}else if(operacao.equals(SAINDO_REGIAO_CRITICA_STRING)){
idProcessoNaRegiaoCritica = 0;
return SAINDO_REGIAO_CRITICA;
}else if(operacao.equals(ENTROU_REGIAO_CRITICA_STRING)){
idProcessoNaRegiaoCritica = Integer.parseInt(mensagem);
return ENTROU_REGIAO_CRITICA;
}
return -1;
}
public static void defineIDProcesso(){
keyboard = new Scanner(System.in);
System.out.println("Informe o ID deste processo: ");
IDProcesso = keyboard.nextInt();
}
public static void lerGrupoTrataMensagem(){
switch(trataMensagem(receiveMessageGroup(),recv)){//só cria timer apos estar de fato atuando na regiao critica, so acontecera quando receber um ok que o processo anterior liberou ela
//ler mensagens ate receber ok que a regiao critica esta livre
case REQUISICAO_REG_CRITICA:
//Recebeu uma requisicao de regiao critica, todos atualizam a lista de espera
listaEsperaRegiaoCritica.add(idRecebido);
proximo = listaEsperaRegiaoCritica.get(0);
if(proximo == IDProcesso && idProcessoNaRegiaoCritica == 0){ //é o primeiro da fila e nao ha nenhum processo na regiao critica
aguardaPermissaoRegiaoCritica = false;
regiaoCritica = true;
}
break;
case SAINDO_REGIAO_CRITICA:
//verificar se seu proprio ID é o proximo a entrar na regiao critica, se for, envia que entrou e inicia timer, senao salva o id de quem entrou
proximo = listaEsperaRegiaoCritica.get(0);
System.out.println("[Processo "+ IDProcesso + "] Proximo da lista: " + proximo);
if(proximo == IDProcesso){
aguardaPermissaoRegiaoCritica = false; //este processo é o proximo da fila, sai do loop de espera espera
//sendMessageGroup(ENTROU_REGIAO_CRITICA_STRING + DIVISOR_STRING + IDProcesso); //avisa outros processos que esta entrando
regiaoCritica = true;
}
break;
case ENTROU_REGIAO_CRITICA:
//se idProcesso = idProcessoNaRegiaoCritica, significa que pode entrar. aguardaPermissaoRegiaoCritica = false, regiaoCritica = true
// remove ID do processo que entrou da lista de espera
listaEsperaRegiaoCritica.remove(0);
break;
}
}
public static void lerGrupoRegiaoNaoCritica(){
switch(trataMensagem(receiveMessageGroup(),recv)){//só cria timer apos estar de fato atuando na regiao critica, so acontecera quando receber um ok que o processo anterior liberou ela
//ler mensagens ate receber ok que a regiao critica esta livre
case REQUISICAO_REG_CRITICA:
//Recebeu uma requisicao de regiao critica, todos atualizam a lista de espera
listaEsperaRegiaoCritica.add(idRecebido);
break;
case ENTROU_REGIAO_CRITICA:
//se idProcesso = idProcessoNaRegiaoCritica, significa que pode entrar. aguardaPermissaoRegiaoCritica = false, regiaoCritica = true
// remove ID do processo que entrou da lista de espera
// if(IDProcesso != idRecebido){ //somente se for outro processo lendo que alguem entrou. Se for o proprio processo, ele ja se removeu da lista ao avaliar que era o proximo
listaEsperaRegiaoCritica.remove(0);
break;
}
}
public static void aguardaMembrosDoGrupo(){
while(numeroProcessosGrupo<3){
switch(trataMensagem(receiveMessageGroup(),recv)){
case NOVO_MEMBRO:
numeroProcessosGrupo ++;
System.out.println("Novo processo Conectado ao Grupo!");
break;
case GRUPO_COMPLETO:
numeroProcessosGrupo = 3;
break;
default:
// System.out.println("Case Default da espera grupo");
break;
}
}
sendMessageGroup(GRUPO_COMPLETO_STRING+DIVISOR_STRING+IDProcesso);
}
public static void main(String[] args) {
setUp();
defineIDProcesso();
sendMessageGroup(OK_STRING+DIVISOR_STRING+IDProcesso);
aguardaMembrosDoGrupo();
System.out.println("Grupo completo! Iniciar execucao.");
tempoRandom = geraRandomEntre(2,16);
//tempoRandom = 3;
TimerProcessos timerAleatorio = new TimerProcessos(tempoRandom);
System.out.println("[Processo " + IDProcesso + "] Entrando na regiao nao critica por " + tempoRandom + "s");
while(executarProcesso){
if(timerAleatorio.shouldCreate){
//passou o tempo, entra ou sai da regiao critica
if(aguardaPermissaoRegiaoCritica){//se estava na critica, agora nao esta mais
aguardaPermissaoRegiaoCritica = false;
tempoRandom = geraRandomEntre(2,16);
}else{//se estava fora, agora fica na critica
aguardaPermissaoRegiaoCritica = true;
}
}
if(aguardaPermissaoRegiaoCritica){
//fazer coisas da regiao critica
System.out.println("[Processo " + IDProcesso + "] Aguardando entrada na regiao critica!");
//Notifica a todos que deseja estar na regiao critica
sendMessageGroup(REQUISICAO_REG_CRITICA_STRING + DIVISOR_STRING + IDProcesso);
while(aguardaPermissaoRegiaoCritica){
lerGrupoTrataMensagem();
}
sendMessageGroup(ENTROU_REGIAO_CRITICA_STRING + DIVISOR_STRING + IDProcesso); //avisa outros processos que esta entrando na regiao critica
//Iniciar timer da regiao critica
timerAleatorio.cancelTimer();
timerAleatorio = new TimerProcessos(tempoRandom);
System.err.println("[Processo " + IDProcesso + "] Entrando na regiao critica! Tempo dentro da regiao: " + tempoRandom + "s");
regiaoCritica = true;
while(regiaoCritica){
//verifica timer, muda regiaoCritica para false apos fim do timer
if(timerAleatorio.shouldCreate){
regiaoCritica = false;
//Inicia timer da regiao nao critica
timerAleatorio.cancelTimer();
tempoRandom = geraRandomEntre(2,16);
timerAleatorio = new TimerProcessos(tempoRandom);
}
lerGrupoTrataMensagem();
//Ainda ler grupo, para atualizar lista de espera
}
System.err.println("[Processo " + IDProcesso + "]Fim da regiao critica!");
sendMessageGroup(SAINDO_REGIAO_CRITICA_STRING + DIVISOR_STRING + IDProcesso); //notifica que saiu da regiao critica
System.out.println("[Processo " + IDProcesso + "] Executando na regiao nao critica por " + tempoRandom + "s");
}else{
//fazer coisas da regiao nao critica
//Ler grupo para atualizar controle de quem esta na regiao critica e atualizar a lista de espera
lerGrupoRegiaoNaoCritica();
}
}
System.exit(0);
}
}
Comments
0 B
|👍
/👎