Recent Changes - Search:

Distributed Computing

This website demonstrates using wikis as teaching and learning tool.

The course instructor is also happy to share the teaching materials here with those who find it readable.

Distributed Computing with Java RMI

A Distributed Computing Tutorial by Steven Choy


Introduction

Java RMI provides a simple and direct model for distributed computing with Java objects. The objective of this tutorial is to allow you to practise programming RMI for distributed computing applications. Our main concern is on the programming aspect of distributing computing, not on the distributed computing problems themselves. Therefore, we select a fairly simple problem, rather than a good but complex one that can fully reveal the real power of distributing computing.

You will apply the Java RMI system to implement a distributed computation of pi (π).

Background Knowledge

Computation of pi:

The application is to compute the value of pi (π) to the specified number of digits after the decimal point. For example, the following shows you the value of pi to 1000 decimal points:

  3.141592653589793238462643383279502884197169399375105820974944592307816406286208
  99862803482534211706798214808651328230664709384460955058223172535940812848111745
  02841027019385211055596446229489549303819644288109756659334461284756482337867831
  65271201909145648566923460348610454326648213393607260249141273724587006606315588
  17488152092096282925409171536436789259036001133053054882046652138414695194151160
  94330572703657595919530921861173819326117931051185480744623799627495673518857527
  24891227938183011949129833673362440656643086021394946395224737190702179860943702
  77053921717629317675238467481846766940513200056812714526356082778577134275778960
  91736371787214684409012249534301465495853710507922796892589235420199561121290219
  60864034418159813629774771309960518707211349999998372978049951059731732816096318
  59502445945534690830264252230825334468503526193118817101000313783875288658753320
  83814206171776691473035982534904287554687311595628638823537875937519577818577805
  321712268066130019278766111959092164201989

One method to compute pi is to use Machin's formula:

  pi = 4‧ [4‧arctan(1/5) – arctan(1/239)]

This method requires computation of arc tangent to sufficient precision. The following power series can be applied to compute the value of an arc tangent:

  arctan(x) = x – (x^3)/3 + (x^5)/5 + (x^7)/7 + (x^9)/9 + ...

A class for computing arc tangent:

To make use of the computation server, we create the following class for computing arc tangent to the specified number of digits after the decimal point.

import java.math.*;

public class InvArctan implements Softbot {

        private int inverseX;
        private int digits;
        private BigDecimal result;

        public InvArctan(int inverseX, int digits) {
                this.inverseX = inverseX;
                this.digits = digits;
        }

        public BigDecimal getResult() {
                return result;
        }


        public void execute()
        {
                BigDecimal ONE = BigDecimal.valueOf(1);
                BigDecimal ZERO = BigDecimal.valueOf(0);
                int roundingMode = BigDecimal.ROUND_HALF_EVEN;
                BigDecimal invX, invX2, numer, term;
                invX = BigDecimal.valueOf(inverseX);
                invX2 = BigDecimal.valueOf(inverseX * inverseX);
                numer = ONE.divide(invX, digits, roundingMode);

                result = numer;
                int i = 1;
                do {
                        numer = numer.divide(invX2, digits, roundingMode);
                        int denom = 2 * i + 1;
                        term = numer.divide(BigDecimal.valueOf(denom),
                                       digits, roundingMode);
                        if ((i % 2) != 0) {
                        result = result.subtract(term);
                        } else {
                                result = result.add(term);
                        }
                        i++;
                        } while (term.compareTo(ZERO) != 0);
        }
}

The following show you how to use this class to calculate the value of arctan(1/5) to 100 digits after the decimal point:

  InvArctan arctan1_5_object = new InvArctan(5,100);

  arctan1_5_object.execute();

  BigDecimal arctan1_5 = arctan1_5_object.getResult();

Computation of pi with the InvArctan class:

The following code shows you how to use InvArctan class to compute pi to 1000 (just an example) digits after the decimal point:

// number of digits for pi
  int digits = 1000;
  // number of digits for arctan
  int scale = digits + 5;
  InvArctan a1_5 = new InvArctan(5,scale);
  InvArctan a1_239 = new InvArctan(239,scale);
  a1_5.execute();
  a1_239.execute();

  // Calculation of pi using Machin's formula
  BigDecimal arctan1_5 = a1_5.getResult();
  BigDecimal arctan1_239 = a1_239.getResult();
  BigDecimal ONE = BigDecimal.valueOf(1);
  BigDecimal ZERO = BigDecimal.valueOf(0);
  BigDecimal FOUR = BigDecimal.valueOf(4);
  BigDecimal pi = arctan1_5.multiply(FOUR).subtract(arctan1_239).multiply(FOUR);
  pi = pi.setScale(digits,BigDecimal.ROUND_HALF_UP);
  System.out.println(pi);

Your Tasks

Task 1: Write the Remote Interface

Write a remote interface named RMIComputeEngine that specifies a method named getAndRunIt. This method is able to accept any object that implements the Softbot interface and return the same type of object to the caller. The Softbot interface specifies only one method: void execute().

import java.io.Serializable;

public interface Softbot extends Serializable {
    public void execute();
}
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RMIComputeEngine extends Remote
{
        public Softbot getAndRunIt (Softbot sb) throws RemoteException;

}

Task 2: Write the Remote Object.

Write a class named RMIComputeEngineImpl that implements the interface RMIComputeEngine. In writing this class, remember to do the following:

  • Declare that this class will implement the remote interface RMIComputeEngine.
  • Define the constructor.
  • Provide an implementation of the getAndRunIt method.
  • Write a static main method that handles the security manager, the remote object, and the RMI remote object registry.
import java.rmi.*;
import java.rmi.server.*;

public class RMIComputeEngineImpl extends UnicastRemoteObject
        implements RMIComputeEngine
{
        public RMIComputeEngineImpl () throws RemoteException { }

        public Softbot getAndRunIt (Softbot sb) {

                sb.execute();
                return sb;
        }

        public static void main(String[] args) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new RMISecurityManager());
        }

        String name = "ComputeEngine";
        try {
            RMIComputeEngineImpl computeEngine = new RMIComputeEngineImpl();
            Naming.rebind(name, computeEngine);
            System.out.println("ComputeEngine bound");
        } catch (Exception e) {
            System.err.println("ComputeEngine exception: " +
                               e.getMessage());
            e.printStackTrace();
        }
    }
}

Task 3: Write the RMI Client

Create a RMI client program for the computation of pi using the Machin's formula.

Write a class named RMIClient_ComputePi to test the implementation and the deployment of RMIComputeEngine. Just write a static main method that computes pi using the Machin's formula. Invoke two RMIComputeEngine objects for the computation of inverse arc tangent. The main method also allows a user to specify the host that runs the RMIComputeEngine objects.

import java.rmi.*;
import java.rmi.Naming;
import java.math.*;

public class RMIClient_ComputePi {

public static void main (String[] args) throws Exception {

        int digits = 1000;

        if (args.length < 1)
                throw new IllegalArgumentException
                                        ("Syntax: RMIClient_ComputePi <hostname> <digits>");

        if (args.length == 2) {
                try
                {
                        digits = Integer.parseInt(args[1]);
                } catch (Exception ignore) { }
        }

        if (System.getSecurityManager() == null) {
                System.setSecurityManager(new RMISecurityManager());
        }

        RMIComputeEngine computeEngine =
                (RMIComputeEngine) Naming.lookup("//" + args[0] + "/ComputeEngine");

        RMIComputeEngine computeEngine2 =
                (RMIComputeEngine) Naming.lookup("//" + args[0] + "/ComputeEngine");


        int scale = digits + 5;

        InvArctan a1_5 = new InvArctan(5, scale);
        InvArctan a1_239 = new InvArctan(239, scale);

        a1_5 = (InvArctan)computeEngine.getAndRunIt(a1_5);
        a1_239 = (InvArctan)computeEngine2.getAndRunIt(a1_239);

        BigDecimal arctan1_5 = a1_5.getResult();
        BigDecimal arctan1_239 = a1_239.getResult();

        BigDecimal ONE = BigDecimal.valueOf(1);
        BigDecimal ZERO = BigDecimal.valueOf(0);
        BigDecimal FOUR = BigDecimal.valueOf(4);

        BigDecimal pi = arctan1_5.multiply(FOUR).subtract(
                                                arctan1_239).multiply(FOUR);
        pi = pi.setScale(digits,BigDecimal.ROUND_HALF_UP);

        System.out.println(pi);

}
}

Compiling, Testing and Running

  • Create a directory for the source codes, say it c:\mt368f\rmi.
  • Have all the required source files ready: Softbot.java, RMIComputeEngine.java, InvArctan.java, RMIComputeEngineImpl.java, RMIClient_ComputePi.java
  • Complie all the source code to Java classes.
Path = C:\Program Files\Java\jdk1.5.0_08\bin
set CLASSPATH=.;C:\Program Files\Java\jdk1.5.0_08\lib;
javac *.java
rmic RMIComputeEngineImpl
  • Make a text file named java.policy with the following content
grant {
   permission java.net.SocketPermission
        "*:1024-65535", "connect,accept";
};

You can follow the following steps in testing your implemented components of distributed computation of pi.

  • Create a directory for the server program, say it c:\mt368f\rmi\server.
  • Create a directory for the client program, say it c:\mt368f\rmi\client.
  • Copy the following files to the server directory:
Softbot.class, RMIComputeEngine.class, RMIComputeEngineImpl.class, InvArctan.class, java.policy
  • Copy the following files to the client directory:
Softbot.class, RMIComputeEngine.class, InvArctan.class, RMIClient_ComputePi.class, RMIComputeEngineImpl_Stub.class, java.policy.
  • Open a DOS command and run rmiregistry.
  • Starts the server by typing the following in a DOS command:
C:\mt368f\rmi\server>java -Djava.security.policy=java.policy RMIComputeEngineImpl
  • Starts the client by typing the following in a DOS command:
C:\mt368f\rmi\client>java -Djava.security.policy=java.policy RMIClient_ComputePi localhost

More experiemnts

  • Remove the InvArctan.class from the sever side. Run the rmiregistry, then the remote object, and then the RMI client. What will you see?
  • Now, revise the java.policy file at the client side as follows
grant {
   permission java.net.SocketPermission
        "*:1024-65535", "connect,accept";
   permission java.io.FilePermission
        "c:\\mt368f\\rmi\\client\\-", "read";
};
The above "java.policy" is used to specify that the server is allowed to automatically download any class file sit in the client side. In our application, the server needs to download InvArctan.class from the client side.
  • Run the rmiregistry, then the remote object, and then the RMI client. What will you see?
  • Run the client with the following command:
java -Djava.rmi.server.codebase=file:/c:\mt368f\rmi\client/ -Djava.security.policy=java.policy RMIClient_ComputePi localhost

Edit - History - Print - Recent Changes - Search
Page last modified on September 14, 2010, at 06:01 PM