Java tutorial
/* * 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 distribuidos; import Beanstalkd.BeanstalkdClient; import Beanstalkd.BeanstalkdClientImpl; import Beanstalkd.BeanstalkdJob; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED; import java.awt.image.BufferedImageOp; import java.awt.image.ConvolveOp; import java.awt.image.Kernel; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import static java.lang.System.nanoTime; import java.util.ArrayList; import java.util.Iterator; import java.util.concurrent.Semaphore; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import org.apache.commons.lang3.SerializationUtils; /** * * @author david */ public class MyThread extends Thread { private final Nodo nodo; private Grafo grafo; private final long prioridadfija = 100; private final String host = "127.0.0.1"; private final int port = 15000; private final String tubopropio; private String option; private final int idnode; private BeanstalkdClient cliente; private ArrayList<Mensaje> colaInterna = new ArrayList<>(); private volatile Semaphore sem = new Semaphore(1); private long cputime; private String fichero; private final int acontar = Main.contar; // Solo Nodo Raiz private volatile Semaphore EM1 = new Semaphore(1); private volatile Semaphore semtoken = new Semaphore(0); private boolean holding; private int parent; private int deferred; private volatile int[] padres; private volatile int[] inDeficitArray; private volatile int inDeficit = 0; private volatile int outDeficit = 0; private volatile int parentDijkstra = -1; private boolean isTerminated = false; private volatile Semaphore signalDijkstra = new Semaphore(0); private volatile Semaphore EMDijkstra = new Semaphore(1); private volatile Semaphore EMenviarMensaje = new Semaphore(1); private volatile Semaphore semMenu = new Semaphore(1); private volatile Semaphore hayMensaje = new Semaphore(0); private String imagepath; private String newimagepath; public MyThread(Nodo nodo, Grafo grafo) { // Nodo Raiz this.nodo = nodo; this.idnode = nodo.getIdentificador(); this.grafo = grafo; this.tubopropio = "t_" + this.idnode; cliente = new BeanstalkdClientImpl(host, port); this.holding = true; this.parent = this.idnode - 1; this.deferred = -1; } public MyThread(Nodo nodo) { this.nodo = nodo; this.idnode = nodo.getIdentificador(); this.tubopropio = "t_" + this.idnode; cliente = new BeanstalkdClientImpl(host, port); this.holding = false; this.parent = this.idnode - 1; this.deferred = -1; this.inDeficitArray = new int[this.nodo.getNpadres()]; this.padres = new int[this.nodo.getNpadres()]; Iterator iter = this.nodo.getPadres(); int i = 0; while (iter.hasNext()) { this.padres[i] = (int) iter.next(); i++; } } public class sendSignal extends Thread { public sendSignal() { } @Override public void run() { while (true) { sndSignal(); } } } public class MyListenThread extends Thread { private BeanstalkdClient clienteRecepcion; private final int idnode; private final String tubopropio; public MyListenThread(int idnode) { this.idnode = idnode; this.tubopropio = "t_" + this.idnode; this.clienteRecepcion = new BeanstalkdClientImpl(host, port); this.clienteRecepcion.useTube(this.tubopropio); } @Override public void run() { while (true) { Mensaje rcv = recibirMensaje(); switch (rcv.getCabecera()) { case "TOKEN": //System.out.println("Soy "+idnode+" y recibo TOKEN de "+rcv.getEmisor()); semtoken.release(); //Adquiere TOKEN break; case "REQUEST": //System.out.println("Soy "+idnode+" y recibo REQUEST de "+rcv.getEmisor()); this.treatRequest(rcv); break; case "SIGNAL": //System.out.println(idnode + " recibe SIGNAL de " + rcv.getEmisor()); signalDijkstra.release(); try { EMDijkstra.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } outDeficit--; if ((outDeficit == 0) && (idnode == 0)) { System.out.println("Trabajo '" + option + "' terminado al 100% en " + (long) (((long) nanoTime() - (long) cputime)) / (long) 1000000000 + " segundos"); semMenu.release(); } EMDijkstra.release(); break; default: queueMsg(rcv); break; } } } private void treatRequest(Mensaje rcv) { try { EM1.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } int source, originator; source = rcv.getEmisor(); originator = Integer.parseInt(rcv.getContenido()); if (parent == -1) { if (holding) { this.enviarToken(originator); holding = false; } else { deferred = originator; } } else { this.enviarRequest(parent, originator); } parent = source; EM1.release(); } private Mensaje recibirMensaje() { this.clienteRecepcion.useTube(this.tubopropio); this.clienteRecepcion.watch(this.tubopropio); BeanstalkdJob job = this.clienteRecepcion.reserve(null); byte[] obtiene = job.getData(); this.clienteRecepcion.delete(job.getJobId()); Mensaje rcv = (Mensaje) SerializationUtils.deserialize(obtiene); return rcv; } private void enviarMensaje(Mensaje mensaje) { try { EMenviarMensaje.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } String tubo = "t_" + mensaje.getReceptor(); this.clienteRecepcion.useTube(tubo); this.clienteRecepcion.put(prioridadfija, 0, 10, SerializationUtils.serialize(mensaje)); this.clienteRecepcion.useTube("t_" + mensaje.getEmisor()); EMenviarMensaje.release(); } private void enviarToken(int originatorORdeferred) { Mensaje tok = new Mensaje(this.idnode); tok.setReceptor(originatorORdeferred); tok.setCabecera("TOKEN"); //System.out.println("Soy " + idnode + " y envio TOKEN a " + tok.getReceptor()); this.enviarMensaje(tok); } private void enviarRequest(int destinatario, int contenido) { Mensaje pet = new Mensaje(this.idnode); pet.setReceptor(destinatario); pet.setCabecera("REQUEST"); pet.setContenido("" + contenido); this.enviarMensaje(pet); } } @Override public void run() { if (this.idnode == 0) { // Es Raiz inicializaHilos(); MyListenThread mlt = new MyListenThread(this.idnode); mlt.start(); tarea(); } else { MyListenThread mlt = new MyListenThread(this.idnode); mlt.start(); sendSignal ss = new sendSignal(); ss.start(); tarea(); } } private String menu() { System.out.println("----------------------"); System.out.println(); System.out.println("Seleccione una opcin:"); System.out.println(); System.out.println("1. Trabajo de contar"); System.out.println("2. Trabajo de difuminar imagen"); System.out.println(); System.out.println(); BufferedReader b = new BufferedReader(new InputStreamReader(System.in)); int choice = 0; try { choice = Integer.parseInt(b.readLine()); } catch (IOException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } switch (choice) { case 1: return "CONTAR"; case 2: return "IMAGEN"; default: System.out.println("Introduce de nuevo:"); return null; } } private void tarea() { if (this.idnode == 0) { while (true) { try { semMenu.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } String opt = menu(); if (opt != null) { cputime = nanoTime(); switch (opt) { case "CONTAR": crearFichero(Main.pathfichero); this.fichero = Main.pathfichero; contarRaiz(); break; case "IMAGEN": enviarImgRaiz(); break; default: break; } } else { semMenu.release(); } } } else { while (true) { this.isEmpty(); procesarMensaje(this.retrieveMsg()); isTerminated = true; } } } private void procesarMensaje(Mensaje msg) { try { EMDijkstra.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } // dijkstra -> if (parentDijkstra == -1) { parentDijkstra = msg.getEmisor(); System.out.println("Soy " + idnode + " y mi padre es " + parentDijkstra); } int src = -1; int i = 0; while (src == -1) { if (padres[i] == msg.getEmisor()) { src = i; } i++; } inDeficitArray[src]++; inDeficit++; // <- dijkstra EMDijkstra.release(); switch (msg.getCabecera()) { case "Contar": this.fichero = msg.getStr1(); contarNodo(msg); break; case "Imagen": this.imagepath = msg.getStr1(); this.newimagepath = msg.getStr2(); procesarImgNodo(msg); break; default: System.out.println("Soy " + idnode + " WEIRD HEAD MESSAGE -> " + msg.getCabecera()); break; } } private void inicializaHilos() { MyThread hilos[] = new MyThread[this.grafo.getNNodos()]; hilos[0] = null; for (int i = 1; i < this.grafo.getNNodos(); i++) { hilos[i] = new MyThread(this.grafo.getNodo(i)); hilos[i].start(); } } // Tratamiento de la Cola de mensajes local private void queueMsg(Mensaje msg) { try { this.sem.acquire(); } catch (InterruptedException ex) { System.out.println("Interrupted Exception: wait() en queueMsg()"); } this.colaInterna.add(msg); this.sem.release(); this.hayMensaje.release(); } private boolean isEmpty() { try { this.hayMensaje.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } try { this.sem.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } boolean rtn = this.colaInterna.isEmpty(); if (rtn) { this.sem.release(); } return rtn; } private Mensaje retrieveMsg() { Mensaje rtn = this.colaInterna.get(0); this.colaInterna.remove(0); this.sem.release(); return rtn; } // Terminacion distribuida Dijkstra-S private void sndSignal() { try { EMDijkstra.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } if (inDeficit > 1) { int i = 0; boolean found = false; while ((!found) && (i < this.padres.length)) { if ((inDeficitArray[i] > 1) || ((inDeficitArray[i] == 1) && (padres[i] != parentDijkstra))) { Mensaje signal = new Mensaje(this.idnode); signal.setCabecera("SIGNAL"); signal.setReceptor(padres[i]); this.enviarMensaje(signal); inDeficitArray[i]--; inDeficit--; found = true; } i++; } } else if ((inDeficit == 1) && (isTerminated) && (outDeficit == 0)) { System.out.println("Soy " + idnode + " y voy a acabar"); Mensaje signal = new Mensaje(this.idnode); signal.setReceptor(parentDijkstra); signal.setCabecera("SIGNAL"); this.enviarMensaje(signal); int idpadre = -1; for (int i = 0; i < padres.length; i++) { if (padres[i] == parentDijkstra) { idpadre = i; } } inDeficitArray[idpadre] = 0; inDeficit = 0; parentDijkstra = -1; isTerminated = false; //signalDijkstra.release(); } //endlist = true; EMDijkstra.release(); } // Exclusin mutua Nielsen-Mizuno private void preSC() { try { EM1.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } if (!this.holding) { this.enviarRequest(parent, this.idnode); this.parent = -1; try { EM1.release(); semtoken.acquire(); EM1.acquire(); } catch (InterruptedException ex) { System.out.println("Error preSC"); } } holding = false; EM1.release(); } private void postSC() { try { EM1.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } if (deferred != -1) { this.enviarToken(deferred); deferred = -1; } else { holding = true; } EM1.release(); } private void enviarMensaje(Mensaje mensaje) { String tubo = "t_" + mensaje.getReceptor(); this.cliente.useTube(tubo); this.cliente.put(prioridadfija, 0, 10, SerializationUtils.serialize(mensaje)); this.cliente.useTube("t_" + mensaje.getEmisor()); } private void enviarToken(int originatorORdeferred) { Mensaje tok = new Mensaje(this.idnode); tok.setReceptor(originatorORdeferred); tok.setCabecera("TOKEN"); //System.out.println("Soy " + idnode + " y envio TOKEN a " + tok.getReceptor()); this.enviarMensaje(tok); } private void enviarRequest(int destinatario, int contenido) { Mensaje pet = new Mensaje(this.idnode); pet.setReceptor(destinatario); pet.setCabecera("REQUEST"); pet.setContenido("" + contenido); this.enviarMensaje(pet); } // Trabajo Contar -> private void contarRaiz() { Mensaje vamosacontar = new Mensaje(this.idnode); vamosacontar.setCabecera("Contar"); vamosacontar.setContenido("" + this.acontar); vamosacontar.setStr1(this.fichero); int cnt = this.acontar / this.nodo.getNhijos(); int rst = this.acontar % this.nodo.getNhijos(); Iterator it = this.nodo.getHijos(); while (it.hasNext()) { vamosacontar.setReceptor((int) it.next()); vamosacontar.setContenido("" + (cnt + rst)); rst = 0; //System.out.println("Soy la raiz y envio datos a " + vamosacontar.getReceptor()); this.enviarMensaje(vamosacontar); try { EMDijkstra.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } outDeficit++; //DIJKSTRA EMDijkstra.release(); } } private void contarNodo(Mensaje msg) { int peticion = Integer.parseInt(msg.getContenido()); int partes = this.nodo.getNhijos() + 1; int cnt = peticion / partes; int resto = peticion % partes; int micnt = cnt + resto; Mensaje tochild = new Mensaje(this.idnode); tochild.setCabecera("Contar"); tochild.setContenido("" + cnt); tochild.setStr1(this.fichero); Iterator it = this.nodo.getHijos(); while (it.hasNext()) { tochild.setReceptor((int) it.next()); if (parentDijkstra != -1) { this.enviarMensaje(tochild); try { EMDijkstra.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } outDeficit++; //DIJKSTRA EMDijkstra.release(); } } //System.out.println("Soy "+idnode+" y mi outDeficit es "+outDeficit); int resultado = this.contarHasta(micnt); //System.out.println(idnode+" trabajo terminado"); } private int contarHasta(int cantidad) { int decimaparte = cantidad / 10; int resto = cantidad % 10; for (int i = 1; i <= 11; i++) { this.preSC(); if (i <= 10) { aumentarFichero(decimaparte); } else { aumentarFichero(resto); } this.postSC(); } return cantidad; } private static void crearFichero(String pathfichero) { File file = new File(pathfichero); try { if (file.exists()) { file.delete(); } file.createNewFile(); } catch (IOException ex) { System.out.println("Error al crear fichero"); } } private void aumentarFichero(int cantidad) { try { FileInputStream fis = new FileInputStream(this.fichero); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); String linea; int numero = 0; if (br.ready()) { linea = br.readLine(); numero = Integer.parseInt(linea); } br.close(); fis.close(); numero += cantidad; FileOutputStream fos = new FileOutputStream(this.fichero, false); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos)); bw.write("" + numero); bw.close(); fos.close(); } catch (IOException ex) { System.out.println("Error de fichero"); } } // Trabajo Imagen -> private void difuminarTrozo(int x, int y, int w, int h) { preSC(); BufferedImage original = null; BufferedImage nueva = null; try { original = ImageIO.read(new File(imagepath)); nueva = ImageIO.read(new File(newimagepath)); } catch (IOException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } BufferedImage copia = new BufferedImage(original.getWidth(), original.getHeight(), TYPE_BYTE_INDEXED); float[] floats = { 0, 0.125f, 0, 0.125f, 0.5f, 0.125f, 0, 0.125f, 0, }; BufferedImageOp op = new ConvolveOp(new Kernel(3, 3, floats)); op.filter(original, copia); copia = copia.getSubimage(x, y, w, h); Graphics2D g2d = nueva.createGraphics(); g2d.drawImage(copia, x, y, null); //g2d.drawImage(copia, x, y, w, h, null); File output = new File(newimagepath); try { ImageIO.write(nueva, "png", output); } catch (IOException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } postSC(); } private void procesarImgNodo(Mensaje msg) { int filacero = msg.getAux2(); int partes = this.nodo.getNhijos() + 1; int filasporparte = msg.getAux4() / partes; int resto = msg.getAux4() % partes; int miparte = filasporparte + resto; Mensaje tochild = new Mensaje(this.idnode); tochild.setCabecera("Imagen"); tochild.setContenido(""); tochild.setStr1(msg.getStr1()); tochild.setStr2(msg.getStr2()); Iterator it = this.nodo.getHijos(); int y = filacero; while (it.hasNext()) { tochild.setReceptor((int) it.next()); tochild.setAux1(msg.getAux1()); tochild.setAux2(y); tochild.setAux3(msg.getAux3()); tochild.setAux4(filasporparte); if (parentDijkstra != -1) { this.enviarMensaje(tochild); try { EMDijkstra.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } outDeficit++; //DIJKSTRA EMDijkstra.release(); } y += filasporparte; } int miposy = y; //System.out.println("Soy "+idnode+" y mi outDeficit es "+outDeficit); difuminarTrozo(msg.getAux1(), miposy, msg.getAux3(), miparte); } private void enviarImgRaiz() { String imagepath = Main.imagen; String newimagepath = Main.newimagen; BufferedImage original = null; try { original = ImageIO.read(new File(imagepath)); } catch (IOException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } Graphics2D g2d = original.createGraphics(); g2d.setBackground(Color.WHITE); File f = new File(imagepath); try { ImageIO.write(original, "png", f); } catch (IOException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } BufferedImage nueva = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_ARGB); File fn = new File(newimagepath); try { ImageIO.write(nueva, "png", fn); } catch (IOException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } int filacero = 0; int partes = this.nodo.getNhijos(); int filasporparte = nueva.getHeight() / partes; int resto = nueva.getHeight() % partes; Mensaje tochild = new Mensaje(this.idnode); tochild.setCabecera("Imagen"); tochild.setContenido(""); tochild.setStr1(imagepath); tochild.setStr2(newimagepath); Iterator it = this.nodo.getHijos(); int y = filacero; while (it.hasNext()) { tochild.setReceptor((int) it.next()); tochild.setAux1(0); tochild.setAux2(y); tochild.setAux3(nueva.getWidth()); tochild.setAux4(filasporparte + resto); System.out.println("Envio a hijo"); this.enviarMensaje(tochild); try { EMDijkstra.acquire(); } catch (InterruptedException ex) { Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex); } outDeficit++; //DIJKSTRA EMDijkstra.release(); y += filasporparte + resto; resto = 0; } } }