witam

probuje napisac aplikacje rozproszona przy wykorzystaniu technologii rmi i mam klopot z komunikacja miedzy slave'ami.

na poczatek przedstawie kod:

plik: Islave.java

import java.rmi.*;

public interface Islave extends Remote
{
    void f1() throws RemoteException;
    int sendRow(int[] row, Boolean left) throws RemoteException;
}

./master
plik: Program.java

import java.io.IOException;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Program
{
        static Context namingContext;
        public static void main(String args[])
    {
                String[] slavesAddresses = { args[0], args[1] };
        try
        {
                System.setProperty("java.security.policy", "master.policy");
                        System.setSecurityManager(new RMISecurityManager());
                Master master = new Master();
                    namingContext = new InitialContext();
                        master.sendJobs(slavesAddresses);
        }catch(Exception exc)
        {
                exc.printStackTrace();
        }
    }
}

class Master
{
    public void sendJobs(String[] slavesAddresses)
    {
        int slavesCount = 2;
        Thread[] threads = new Thread[slavesCount];
        for (int i = 0; i < slavesCount; i++)
        {
                        String url = "rmi://" + slavesAddresses[i];
                        try {
                                Islave slave = (Islave) Program.namingContext.lookup(url);
                                SlaveJob sj = new SlaveJob(slave);
                        Thread t = new Thread(sj);
                        threads[i] = t;
                        t.start();
                        } catch (NamingException e) {
                                e.printStackTrace();
                        }
        }
        for (int i = 0; i < slavesCount; i++)
        {
            try {
                                threads[i].join();
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
        }
    }
}
class SlaveJob implements Runnable
{
        Islave slave = null;
       
        public SlaveJob(Islave slave)
        {
                this.slave = slave;
        }

        public void run() {
                try {
                        slave.f1();
                } catch (RemoteException e) {
                        e.printStackTrace();
                }
        }

}

plik: master.policy

grant
{
        permission java.net.SocketPermission
                "*:1024-65535", "accept,connect,resolve";
        permission java.io.FilePermission "<<ALL FILES>>", "read,write";
};

rola mastera jest odnalezenie dwoch slave'ow i zazadanie wykonania przez nie funkcji f1()

./slave
plik: Program.java

import java.io.Console;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Program
{
        static Context namingContext;
        public static void main(String args[])
    {
        Slave slave;
                try {
                        System.setProperty("java.security.policy", "slave.policy");
                        System.setSecurityManager(new RMISecurityManager());
                        slave = new Slave(args[1]);
                        namingContext = new InitialContext();
                        namingContext.bind("rmi://" + args[0], slave);
                } catch (RemoteException e) {
                        e.printStackTrace();
                }
                catch (NamingException e) {
                        e.printStackTrace();
                }
    }
}

class Slave extends UnicastRemoteObject implements Islave
{
    public Slave(String neighborAddress) throws RemoteException {
            if(neighborAddress.contains("slave2"))
                    rightNeighborAddress = neighborAddress;
            else
                    leftNeighborAddress = neighborAddress;
        }

    String leftNeighborAddress = null;
    String rightNeighborAddress = null;
    Islave leftNeighbor = null;
    Islave rightNeighbor = null;
        private int[] leftRow = null;
    private int[] rightRow = null;

    public void f1() throws RemoteException
    {
        int[][] local_matrix = new int[6][10];
       
        if (leftNeighborAddress != null)
        {
            leftRow = new int[10];
            String slave_url = "rmi://" + leftNeighborAddress;
            System.out.println("left slave: " + slave_url);
                        try {
                                leftNeighbor = (Islave) Program.namingContext.lookup(slave_url);
                        } catch (NamingException e) {
                                e.printStackTrace();
                        }
        }
        else
        {
            rightRow = new int[10];
            String slave_url = "rmi://" + rightNeighborAddress;
            System.out.println("right slave: " + slave_url);
                        try {
                    rightNeighbor = (Islave) Program.namingContext.lookup(slave_url);
                        } catch (NamingException e) {
                                e.printStackTrace();
                        }
        }

        for(int p = 0; p < 15; p++)
        {
                for(int i = 0; i < 6; i++)
                        for(int j = 0; j < 10; j++)
                                local_matrix[i][j] = 1;
               
            if (rightNeighbor != null)
            {
                RowSender rowSender = new RowSender(rightNeighbor, local_matrix[5], true);
                    Thread rowSenderThread = new Thread(rowSender);
                    rowSenderThread.start();
                   
                Waiter waiter = new Waiter(rightRow);
                Thread thread = new Thread(waiter);
                thread.start();
                try {
                                        thread.join();
                                } catch (InterruptedException e) {
                                        e.printStackTrace();
                                }
                replaceRow(local_matrix, rightRow, 5);
                rightRow = null;
            }
            else
            {
                RowSender rowSender = new RowSender(leftNeighbor, local_matrix[0], false);
                    Thread rowSenderThread = new Thread(rowSender);
                    rowSenderThread.start();
                   
                    Waiter waiter = new Waiter(leftRow);
                    Thread thread = new Thread(waiter);
                    thread.start();
                    try {
                            thread.join();
                    } catch (InterruptedException e) {
                            e.printStackTrace();
                    }
                replaceRow(local_matrix, leftRow, 0);
                leftRow = null;
            }
        }
    }

    private void replaceRow(int[][] matrix, int[] row, int nrRow)
    {
        matrix[nrRow] = row;
    }

    public int sendRow(int[] row, Boolean left) throws RemoteException
    {
        if (left)
        {
            if (leftRow == null)
            {
                leftRow = row;
                return 0;//ok
            }
            else
                return -1;
        }
        else
        {
            if (rightRow == null)
            {
                rightRow = row;
                return 0;//ok
            }
            else
                return -1;
        }
    }
}
class Waiter implements Runnable
{
    private int[] row;
    public Waiter(int[] row)
    {
            this.row = row;       
    }
        public void run() {
                while(row == null)
                        ;
        }
}

class RowSender implements Runnable
{
        private Islave reciver;
    private int[] row;
    private Boolean left;
   
    public RowSender(Islave reciver, int[] row, Boolean left)
    {
            this.reciver = reciver;
            this.row = row;       
            this.left = left;
    }
        public void run() {
                int result = -1;
        int attempt_nr = 0;
        while (result != 0)
                        try {
                                attempt_nr++;
                                result = reciver.sendRow(row, left);
                                System.out.print("attempt nr: " + attempt_nr + " to send ");
                                if(left)
                                        System.out.println("left row");
                                else
                                        System.out.println("right row");
                        } catch (RemoteException e) {
                                e.printStackTrace();
                        }
        }
}

plik: slave.policy

grant
{
        permission java.net.SocketPermission
                "*:1024-65535", "accept,connect,resolve";
        permission java.io.FilePermission "<<ALL FILES>>", "read,write";
};

jak widac na aplikacje sklada sie program mastera i slava. uruchamiam jednego mastera i dwa slavy wykonujace dla niego funkcje f1().
slave'y wykonuja jakies tam operacje na macierzy local_matrix (tutaj przypisuja elementom wartosc 1) a nastepnie musza wymienic sie wierszami i tutaj pojawia sie klopot gdyz pomimo utworzenia watkow ktore oczekuja i ktore wysylaja slave'y nie moga wymienic sie miedzy soba wierszami.
idea aplikacji jest zrownoleglenie jej poprzez utworzenie slavow wykonujacych obliczenia na lokalnych macierzach, a nastepnie odsylajacych wyniki obliczen do mastera, jednak w kazdej iteracji slave'y musza sie wymieniac skrajnymi wektorami macierzy - gdyz sa one potrzebne do obliczen slavom wykonujacych operacje na przylegajacych czesciach macierzy.
i tak slave1 wysyla do slave2 swoj prawy wiersz (w tym przypadku o indeksie 5), natomiast slave2 wysyla do slave1 swoj lewy wiersz (czyli wiersz o indeksie 0).
klasa RowSender sluzy do ciaglego probowania przeslania wiersza, poprzez wykorzystanie metody zdalnej drugiego slavea. klasa Waiter aktywnie oczekuje az row na ktory czekamy zostanie przeslany. watek Waiter wiaze nastepnie z watkiem glownym aby kolejna iteracja nie byla wykonywana poki wiersz na ktory oczekujemy nie zostal przeslany.

uruchamianie (na dwoch komputerach)
na pierwszym slavie:
javac ISlave.java Program.java
rmiregistry
java Program 192.168.1.1/slave1 192.168.1.2/slave2

na drugim slavie:
javac ISlave.java Program.java
rmiregistry
java Program 192.168.1.2/slave2 192.168.1.1/slave1

w ./master
rmiregistry
javac Islave.java Program.java
java Program 192.168.1.1/slave1 192.168.1.2/slave2

po uruchomieniu oba slavy nieskutecznie probuja wywolac funkcje sendRow z drugiego slava.

ma ktos pomysl w jakis sposob rozwiazac powyzszy problem?