Parsing Engine

danbikel.switchboard
Class AbstractClient

java.lang.Object
  extended by java.rmi.server.RemoteObject
      extended by java.rmi.server.RemoteServer
          extended by danbikel.switchboard.AbstractSwitchboardUser
              extended by danbikel.switchboard.AbstractClient
All Implemented Interfaces:
Client, SwitchboardUser, Serializable, Remote
Direct Known Subclasses:
Parser

public abstract class AbstractClient
extends AbstractSwitchboardUser
implements Client

Provides a convenient default implementation of the Client interface, as well as other convenient utility methods. A subclass need only provide a concrete implementation of the process(Object) method.

N.B.: Subclasses should take care to properly call the AbstractSwitchboardUser.unexportWhenDead method.

A note on fault tolerance: In order to ensure the fault-tolerance of clients, subclasses should ensure that they use socket factories that set the SO_TIMEOUT values of their TCP/IP sockets to some integer greater than 0, by calling the constructors of this class with non-zero timeout arguments, or by providing custom socket factories that provide at least the functionality of TimeoutSocketFactory. Subclasses that use sockets other than TCP/IP sockets should have similar non-infinite timeouts.

See Also:
AbstractSwitchboardUser.unexportWhenDead(), Serialized Form

Nested Class Summary
 
Nested classes/interfaces inherited from class danbikel.switchboard.AbstractSwitchboardUser
AbstractSwitchboardUser.Alive, AbstractSwitchboardUser.SBUserRetry
 
Field Summary
static int defaultNextObjectInterval
           
protected  boolean failover
          Cache of the value of the parameter of the same name in the tolerateFaults(int, int, boolean) or getFaultTolerantServer(int, int, boolean) methods.
protected  boolean faultTolerant
          Indicates whether the server has been wrapped in proxies for fault tolerance, via a call to the tolerateFaults(int, int, boolean) or getFaultTolerantServer(int, int, boolean) method.
protected  int nextObjectInterval
          The interval at which clients should keep pinging the switchboard for more objects after receving null from the SwitchboardRemote.nextObject(int) method.
protected  Random rand
          The pseudorandom number generator used by sleepRandom(int), initialized at construction with a random seed based on the current time.
protected  int retries
          Cache of the value of the parameter of the same name in the tolerateFaults(int, int, boolean) or getFaultTolerantServer(int, int, boolean) methods.
protected  Server server
          The server assigned to this client.
protected  int serverId
          The ID number of the server assigned to this client, cached here for convenience.
protected  int sleepTime
          Cache of the value of the parameter of the same name in the tolerateFaults(int, int, boolean) or getFaultTolerantServer(int, int, boolean) methods.
 
Fields inherited from class danbikel.switchboard.AbstractSwitchboardUser
aliveSynch, aliveTimeout, className, defaultMaxSwitchboardTries, defaultTimeout, dieSynch, id, infiniteTries, maxSwitchboardTries, registered, switchboard, switchboardName, timeout, timeToDie
 
Fields inherited from class java.rmi.server.RemoteObject
ref
 
Constructor Summary
protected AbstractClient()
          Constructs a non-exported AbstractClient object.
protected AbstractClient(int timeout)
          Constructs a new client with the specified timeout, to be set for switchboard-side (RMI client-side) sockets.
protected AbstractClient(int timeout, int port)
          Constructs a new client taking RMI calls on the specified port, with the specified timeout to be set for switchboard-side (RMI client-side) sockets.
protected AbstractClient(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf)
          Constructs a new client taking RMI calls on the specified port and using the specified socket factories.
 
Method Summary
protected  void cleanup()
          Does nothing; called by the default implementation of AbstractSwitchboardUser.unexportWhenDead().
static void disableHttp(Properties props)
           
protected  void getFaultTolerantServer(int retries, int sleepTime, boolean failover)
          Gets a new server and wraps it in proxies that ensure the fault tolerance of calls to that server.
protected  void getServer()
          Unless it is time to die, this method continually tries the switchboard until it can assign this client a server.
protected abstract  Object process(Object obj)
          This is the only purely abstract method of this class, allowing subclasses to focus purely on their job, which is object-processing.
protected  void processObjects()
          Gets objects from the switchboard until there are no more to get, processes them by invoking the process(Object) method and puts the processed objects back to the switchboard, handling any RMI-related errors along the way.
protected  void processObjectsThenDie()
          A convenience method that simply calls processObjects() and then AbstractSwitchboardUser.unexportWhenDead().
protected  void register(String switchboardName)
          Registers this client with the specified switchboard, caching the switchboard to an internal data member.
protected  void reRegister()
          Re-registers this client with the switchboard after a switchboard failure.
 void serverDown(int serverId)
          Currently, this method does nothing, as all server failures can be handled by making the server fault-tolerant.
protected  void setNextObjectInterval()
          Attempts to get the SwitchboardRemote.clientNextObjectInterval setting from the switchboard and set the nextObjectInterval data member to it.
static void setPolicyFile(Class cl, Properties props)
          Calls AbstractSwitchboardUser.setPolicyFile(Class,String) with the specified class and the value of the SwitchboardRemote.clientPolicyFile property obtained from the specified Properties object.
protected static void setPolicyFile(Properties props)
          Calls AbstractSwitchboardUser.setPolicyFile(String) with the value of the SwitchboardRemote.clientPolicyFile property obtained from the specified Properties object.
protected  int sleepRandom(int maxMillis)
          Sleeps for a random interval between 0 and the specified number of milliseconds.
protected  void switchboardFailure()
          A hook that is called by reRegister, so that clients may perform any emergency procedures prior to re-registering and getting a new server.
protected  void tolerateFaults(int retries, int sleepTime, boolean failover)
          Wraps the current server in proxies that ensure the fault tolerance of calls to that server.
 
Methods inherited from class danbikel.switchboard.AbstractSwitchboardUser
alive, die, disableHttp, getAliveTimeout, getSwitchboard, getSwitchboard, getSwitchboard, getSwitchboard, getSwitchboard, getSwitchboard, host, id, nonZeroTimeout, setPolicyFile, setPolicyFile, startAliveThread, unexportWhenDead
 
Methods inherited from class java.rmi.server.RemoteServer
getClientHost, getLog, setLog
 
Methods inherited from class java.rmi.server.RemoteObject
equals, getRef, hashCode, toString, toStub
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface danbikel.switchboard.SwitchboardUser
alive, die, host, id
 

Field Detail

defaultNextObjectInterval

public static final int defaultNextObjectInterval
See Also:
Constant Field Values

nextObjectInterval

protected int nextObjectInterval
The interval at which clients should keep pinging the switchboard for more objects after receving null from the SwitchboardRemote.nextObject(int) method.


server

protected volatile Server server
The server assigned to this client.


serverId

protected volatile int serverId
The ID number of the server assigned to this client, cached here for convenience.


faultTolerant

protected volatile boolean faultTolerant
Indicates whether the server has been wrapped in proxies for fault tolerance, via a call to the tolerateFaults(int, int, boolean) or getFaultTolerantServer(int, int, boolean) method. Initially false.


retries

protected volatile int retries
Cache of the value of the parameter of the same name in the tolerateFaults(int, int, boolean) or getFaultTolerantServer(int, int, boolean) methods. Initially -1.


sleepTime

protected volatile int sleepTime
Cache of the value of the parameter of the same name in the tolerateFaults(int, int, boolean) or getFaultTolerantServer(int, int, boolean) methods. Initially -1.


failover

protected volatile boolean failover
Cache of the value of the parameter of the same name in the tolerateFaults(int, int, boolean) or getFaultTolerantServer(int, int, boolean) methods. Initially false.


rand

protected Random rand
The pseudorandom number generator used by sleepRandom(int), initialized at construction with a random seed based on the current time.

Constructor Detail

AbstractClient

protected AbstractClient()
                  throws RemoteException
Constructs a non-exported AbstractClient object.

Throws:
RemoteException

AbstractClient

protected AbstractClient(int timeout)
                  throws RemoteException
Constructs a new client with the specified timeout, to be set for switchboard-side (RMI client-side) sockets. This constructor must be called by the constructor of a subclass.

Warning: Using a value of 0 for the timeout argument will cause the distributed system implemented by this package to be non-fault-tolerant. Use a timeout value greater than 0 to ensure the fault-tolerance of the distributed computing system.

Parameters:
timeout - the time in milliseconds before client-side (switchboard-side) sockets used for this remote object time out; a value of 0 specifies infinite timeout, which is dangerous
Throws:
RemoteException

AbstractClient

protected AbstractClient(int timeout,
                         int port)
                  throws RemoteException
Constructs a new client taking RMI calls on the specified port, with the specified timeout to be set for switchboard-side (RMI client-side) sockets. This constructor must be called by the constructor of a subclass.

Warning: Using a value of 0 for the timeout argument will cause the distributed system implemented by this package to be non-fault-tolerant. Use a timeout value greater than 0 to ensure the fault-tolerance of the distributed computing system.

Parameters:
timeout - the time in milliseconds before client-side (switchboard-side) sockets used for this remote object time out; a value of 0 specifies infinite timeout, which is dangerous
port - the port on which this remote object is to receive remote method invocations
Throws:
RemoteException

AbstractClient

protected AbstractClient(int port,
                         RMIClientSocketFactory csf,
                         RMIServerSocketFactory ssf)
                  throws RemoteException
Constructs a new client taking RMI calls on the specified port and using the specified socket factories. This constructor must be called by the constructor of a subclass.

Warning: Custom socket factories should ensure that their sockets have some sort of timeout mechanism (such as implemented for TCP/IP sockets by TimeoutSocketFactory). If sockets do not time out, then the distributed system implemented by this package will not be fault-tolerant.

Parameters:
port - the port on which this remote object is to receive remote method invocations
Throws:
RemoteException
Method Detail

setPolicyFile

protected static void setPolicyFile(Properties props)
Calls AbstractSwitchboardUser.setPolicyFile(String) with the value of the SwitchboardRemote.clientPolicyFile property obtained from the specified Properties object.

Parameters:
props - the Properties object from which to obtain the value of the SwitchboardRemote.clientPolicyFile property

setPolicyFile

public static void setPolicyFile(Class cl,
                                 Properties props)
Calls AbstractSwitchboardUser.setPolicyFile(Class,String) with the specified class and the value of the SwitchboardRemote.clientPolicyFile property obtained from the specified Properties object.

Parameters:
props - the Properties object from which to obtain the value of the SwitchboardRemote.clientPolicyFile property

disableHttp

public static void disableHttp(Properties props)

getFaultTolerantServer

protected void getFaultTolerantServer(int retries,
                                      int sleepTime,
                                      boolean failover)
                               throws RemoteException
Gets a new server and wraps it in proxies that ensure the fault tolerance of calls to that server. The proxies used are implemented via the Failover and SBUserRetry classes.

Each time a call is made to this method, the parameter values are cached in this object, in the retries, sleepTime and failover data members. This allows the reRegister() method to properly re-wrap a new server when it gets one after a switchboard failure.

Parameters:
retries - the number of times to re-try the server in the event of failure; a value of Retry.retryIndefinitely will cause the proxy to re-try indefinitely
sleepTime - the time, in milliseconds, to sleep between retries
failover - indicates whether to wrap the server in a failover proxy
Throws:
RemoteException

tolerateFaults

protected void tolerateFaults(int retries,
                              int sleepTime,
                              boolean failover)
Wraps the current server in proxies that ensure the fault tolerance of calls to that server. Each time a call is made to this method, the parameter values are cached in this object, in the retries, sleepTime and failover data members. This allows the reRegister() method to properly re-wrap a new server when it gets one after a switchboard failure. If this method is called with retries == 0 and failover == false, then it simply returns, having done no proxy wrapping.

N.B.: This method re-assigns the protected data member server. If subclasses have cached a reference to the server in a local data member, they should override this method such that this implementation is called (super.tolerateFaults(...)) and then the server re-cached, as shown in the following example code:

 public class MyClient extends AbstractClient {
   // local reference to the server of a type implemented
   // by the actual (concrete) servers in a particular distributed system
   private MyServerInterface server;

   protected void tolerateFaults(int retries, int sleepTime,
                                 boolean failover) throws RemoteException {
     super.tolerateFaults(retries, sleepTime, failover);
     server = (MyServerInterface)super.server;
   }
   ...
 }
 

Parameters:
retries - the number of times to re-try the server in the event of failure; a value of Retry.retryIndefinitely will cause the proxy to re-try indefinitely
sleepTime - the time, in milliseconds, to sleep between retries
failover - indicates whether to wrap the server in a failover proxy
See Also:
server

switchboardFailure

protected void switchboardFailure()
A hook that is called by reRegister, so that clients may perform any emergency procedures prior to re-registering and getting a new server. This default implementation does nothing.


reRegister

protected void reRegister()
                   throws RemoteException
Re-registers this client with the switchboard after a switchboard failure. First, this method calls switchboardFailure(). Next, it calls register(java.lang.String) to perform the actual re-acquiring of the switchboard and re-registering of this client. Finally, it gets a new server (via getServer()) and, if the previous server was fault-tolerant, calls tolerateFaults(int, int, boolean) with the same settings that were previously used.

Specified by:
reRegister in class AbstractSwitchboardUser
Throws:
RemoteException
See Also:
faultTolerant, retries, sleepTime, failover

register

protected void register(String switchboardName)
                 throws RemoteException,
                        MalformedURLException
Registers this client with the specified switchboard, caching the switchboard to an internal data member. After registering, this client will have a valid ID number assigned to it. This method will not return until a switchboard stub has been obtained from the bootstrap registry and this client is successfully registered.

Parameters:
switchboardName - the name of the switchboard in the bootstrap registry
Throws:
RegistrationException - if this client could not be registered
RemoteException
MalformedURLException

setNextObjectInterval

protected void setNextObjectInterval()
Attempts to get the SwitchboardRemote.clientNextObjectInterval setting from the switchboard and set the nextObjectInterval data member to it. If there is a remote method failure or if the property is not in the switchboard's settings, this method silently leaves the nextObjectInterval unchanged.


serverDown

public void serverDown(int serverId)
                throws RemoteException
Currently, this method does nothing, as all server failures can be handled by making the server fault-tolerant.

Specified by:
serverDown in interface Client
Throws:
RemoteException
See Also:
tolerateFaults(int, int, boolean)

getServer

protected void getServer()
                  throws RemoteException
Unless it is time to die, this method continually tries the switchboard until it can assign this client a server.

N.B.: This method re-assigns the protected data member server. If subclasses have cached a reference to the server in a local data member, they should override this method such that this implementation is called (super.getServer()) and then the server re-cached, as shown in the following example code:

 public class MyClient extends AbstractClient {
   // local reference to the server of a type implemented
   // by the actual (concrete) servers in a particular distributed system
   private MyServerInterface server;

   protected void getServer() throws RemoteException {
     super.getServer();
     server = (MyServerInterface)super.server;
   }
   ...
 }
 

Throws:
RemoteException
See Also:
server

sleepRandom

protected int sleepRandom(int maxMillis)
Sleeps for a random interval between 0 and the specified number of milliseconds.

Parameters:
maxMillis - the maximum number of milliseconds this method will cause the current thread to sleep
Returns:
the number of milliseconds that this method tried to cause the current thread to sleep (may be less if an InterruptedException was thrown during the sleep call)

cleanup

protected void cleanup()
Description copied from class: AbstractSwitchboardUser
Does nothing; called by the default implementation of AbstractSwitchboardUser.unexportWhenDead(). If a subclass has additional cleanup to be done prior to unexporting, this method should be overridden.

Overrides:
cleanup in class AbstractSwitchboardUser

process

protected abstract Object process(Object obj)
                           throws RemoteException
This is the only purely abstract method of this class, allowing subclasses to focus purely on their job, which is object-processing.

Parameters:
obj - the object to be processed
Returns:
the processed object, or null if the object was unable to be processed
Throws:
RemoteException

processObjectsThenDie

protected void processObjectsThenDie()
                              throws RemoteException
A convenience method that simply calls processObjects() and then AbstractSwitchboardUser.unexportWhenDead().

Throws:
RemoteException

processObjects

protected void processObjects()
                       throws RemoteException
Gets objects from the switchboard until there are no more to get, processes them by invoking the process(Object) method and puts the processed objects back to the switchboard, handling any RMI-related errors along the way.

Throws:
RemoteException
See Also:
SwitchboardRemote.clientNextObjectInterval, SwitchboardRemote.nextObject(int)

Parsing Engine

Author: Dan Bikel.