PPD - Trabalho Borg
Links relacionados: Programação Paralela e Distribuída
Descrição
Utilizando o sistema abaixo (Borg), desenvolver um novo problema a ser resolvido de forma distribuída, implementando-o em 'Borg.java e acrescente a nova funcionalidade em Borgd.java.
Borg
Borg (apresentado a baixo) é um sistema simples em java, a titulo de aprendizado, para calcular o fatorial de um número. O sistema divide o problema em subproblemas e os distribui em outras maquinas. Cada máquina resolve parte do problema e devolve ao servidor. O sistema é dividido em 3 classes:
Borg.java
Aplicacao que divide o problema em partes, cria quantos processos forem possíveis, conforme o numero de servidores disponíveis.
Na definição dos servidores e portas para conexões podem existir dois servidores em uma mesma maquina. Nesse caso, é necessário especificar portas diferentes para cada um deles.
Neste exercício é apresentado um exemplo de criação de três processos para três servidores. Observa-se que os servidores precisam estar rodando nas máquinas especificadas caso não seja localhost.
1/**
2 * Copyright 2001-2050 Saulo Popov Zambiasi. All rights reserved. Last modified:
3 * 2013/05/21
4 *
5 * Borg
6 *
7 * Divide tarefa em partes, criando um processo para cada servidore requisitado.
8 *
9 * Neste exercicio eh apresentado um exemplo de criacao de tres processos para
10 * três servidores. Quando houver dois servidores rodando na mesma maquina, eh
11 * necessario configurar portas diferentes para cada servidor.
12 *
13 * Exemplo de servidores e portas:
14 *
15 * String[] server = { "localhost", "192.168.1.1", "192.168.1.2" }
16 *
17 * int[] port = { 4400, 4401 , 4400 }
18 */
19
20import java.math.BigDecimal;
21
22public class Borg {
23 static public void main(String[] arguments) {
24 String[] server = { "localhost", "localhost", "localhost" };
25 int[] port = { 4400, 4401, 4402 };
26 int number = 0;
27
28 // Pega o numero passado como parametro para o calculo do fatorial
29 if (arguments.length == 1) {
30 number = Integer.parseInt(arguments[0]);
31 } else {
32 System.out.println("Use: java Borg number");
33 return;
34 }
35 // Divide o numero em partes, cada parte para cada processo
36 int size = (int) (number / server.length);
37 int counter = 1;
38
39 // Criacao dos processos para controlar a comunicacao com os daemons
40 BorgProcess[] ap = new BorgProcess[server.length];
41 for (int i = 0; i < server.length; i++) {
42 try {
43 int start = counter;
44 int end = counter + size;
45 if (end > number)
46 end = number;
47 counter = end + 1;
48 String message = "fatorial " + start + " " + end;
49 // Cria o processo e envia a mensagem para o mesmo
50 ap[i] = new BorgProcess(server[i], port[i], message);
51 } catch (Exception e) {
52 System.out.println("ERRO: " + e.toString());
53 }
54 }
55
56 // Espera o retorno de cada processo e multiplica os resultados.
57 BigDecimal result = new BigDecimal("1");
58 boolean terminou = false;
59 while (!terminou) {
60 terminou = true;
61 for (int i = 0; i < server.length; i++) {
62 if (!ap[i].finished()) {
63 terminou = false;
64 } else if (ap[i].hasResponse()) {
65 result = result
66 .multiply(new BigDecimal(ap[i].getResponse()));
67 }
68 }
69 }
70 // Imprime o resultado na tela.
71 System.out.println("Factorial " + number + "! = " + result);
72 }
73}
BorgProcess.java
Cada um dos processos criados por Borg.java é uma thread e faz uma conexão especifica com cada um servidor em funcionamento.
1/**
2 * Copyright 2001-2050 Saulo Popov Zambiasi. All rights reserved.
3 * Last modified: 2013/03/21
4 *
5 * Borg Process:
6 *
7 * Classe responsavel pela comunicacao de cada processo com um servidor.
8 * Envia uma mensagem e espera seu retorno.
9 */
10
11import java.io.*;
12import java.net.*;
13
14public class BorgProcess implements Runnable {
15 private String server; // IP ou nome do servidor
16 private String message; // Mensagem
17 private String response; // Mensagem recebida;
18 private int port; // Porta da conexao
19 private boolean done; // Trabalho terminado
20 private Thread runner;
21
22 BorgProcess(String server, int port, String message) {
23 this.message = message;
24 this.response = null;
25 this.server = server;
26 this.port = 4400;
27 this.done = false;
28 if (port != 0) {
29 this.port = port;
30 }
31 if (runner == null) {
32 runner = new Thread(this);
33 runner.start();
34 }
35 }
36
37 public void run() {
38 try {
39 // Conexao com o daemon
40 Socket conexao = new Socket(server, port);
41 conexao.setSoTimeout(20000);
42
43 // Envia a mensagem para o servidor
44 System.out.println("borg://" + server + ":" + port + "/send \""
45 + message + "\"");
46 BufferedOutputStream bos = new BufferedOutputStream(
47 conexao.getOutputStream());
48 PrintWriter os = new PrintWriter(bos, false);
49 os.println(message);
50 os.flush();
51 // recebe o resultado do daemon em forma de uma mensagem
52 BufferedReader in = new BufferedReader(new InputStreamReader(
53 conexao.getInputStream()));
54 response = in.readLine();
55 System.out.println("borg://" + server + ":" + port + "/recv \""
56 + response + "\"");
57 conexao.close();
58 } catch (IOException e) {
59 System.out.println("Erro: " + e.getMessage());
60 }
61 done = true;
62 }
63
64 String getResponse() {
65 String out = response;
66 response = null;
67 return out;
68 }
69
70 boolean hasResponse() {
71 return response != null;
72 }
73
74 boolean finished() {
75 return done;
76 }
77}
BorgServer.java
Servidor responsável por executar uma tarefa especifica.
1/**
2 * Copyright 2001-2050 Saulo Popov Zambiasi. All rights reserved.
3 * Last modified: 2013/05/21
4 *
5 * Borg Server: Executa as mensagens recebidas e retorna o resultado
6 */
7
8import java.io.*;
9import java.math.BigDecimal;
10import java.net.*;
11import java.util.*;
12
13public class BorgServer extends Thread {
14 private ServerSocket sock; // Socket do servidor
15
16 // Construtor que inicializa a classe como thread
17 public BorgServer(int port) {
18 super();
19 int serverPort = 4400;
20 if (port != 0)
21 serverPort = port;
22 try {
23 sock = new ServerSocket(serverPort);
24 System.out.println("Borg Server running...");
25 } catch (IOException e) {
26 System.out.println("Erro: " + e.getMessage());
27 System.exit(1);
28 }
29 start();
30 }
31
32 // Mantem o servidor em execucao
33 public void run() {
34 while (true) {
35 // Fica esperando o recebimento de mensagens
36 if (sock == null) {
37 return;
38 }
39 try {
40 Socket conn = sock.accept();
41 // Recebendo mensagem
42 BufferedReader in = new BufferedReader(new InputStreamReader(
43 conn.getInputStream()));
44 String message = in.readLine();
45 System.out.println("borg://" + conn.getInetAddress() + ":"
46 + conn.getPort() + "/recv \"" + message + "\"");
47 // executando a mensagem
48 message = execute(message);
49 // Enviando a resposta
50 BufferedOutputStream bos = new BufferedOutputStream(
51 conn.getOutputStream());
52 PrintWriter os = new PrintWriter(bos, false);
53 System.out.println("borg::/" + conn.getInetAddress() + ":"
54 + conn.getPort() + "/send \"" + message + "\"");
55 os.println(message);
56 os.flush();
57 os.close();
58 conn.close();
59 } catch (IOException e) {
60 System.out.println("Erro: " + e.getMessage());
61 System.exit(1);
62 }
63 }
64 }
65
66 String execute(String msg) {
67 String result = "null";
68 StringTokenizer split = new StringTokenizer(msg, " ");
69 // Verifica o comando, 1a. palavra da mensagem
70 String command = split.nextToken();
71 // Executa o comando de fatorial
72 switch (command) {
73 case "fatorial":
74 int a = Integer.parseInt(split.nextToken());
75 int b = Integer.parseInt(split.nextToken());
76 // long c = 1;
77 BigDecimal c = new BigDecimal("1");
78 for (int i = a; i <= b; i++) {
79 c = c.multiply(new BigDecimal(Integer.toString(i)));
80 }
81 result = c.toString();
82 break;
83 case "somatorio": // Outro exemplo
84 double total = 0;
85 for (int i = 0; i < split.countTokens() - 1; i++) {
86 total += Double.parseDouble(split.nextToken());
87 }
88 result = Double.toString(total);
89 break;
90 }
91 return result;
92 }
93
94 // Programa principal
95 public static void main(String[] arguments) {
96 // Configura a porta, caso passada por parametro.
97 int port = 0;
98 if (arguments.length == 1) {
99 port = Integer.parseInt(arguments[0]);
100 } else if (arguments.length > 1) {
101 System.out.println("Use: java Borgd port");
102 return;
103 }
104 new BorgServer(port);
105 }
106}