ParkNPark.client
Class FaultTolerantClientManager

java.lang.Object
  extended by ParkNPark.client.FaultTolerantClientManager
All Implemented Interfaces:
ClientManagerOperations

public class FaultTolerantClientManager
extends Object
implements ClientManagerOperations

Fault tolerant client manager that wraps a remote ClientManager and rolls over to a new primary server in the presence of failures. Note that this class is not multi-thread safe. Multiple threads should synchronize access or wrap this class with a thread-safe delegate.


Nested Class Summary
protected  class FaultTolerantClientManager.BackgroundThread
          Background thread that performs the following actions in a loop continuously: Recover from a fault on the primary server if one was detected by either this thread or by the main thread Refresh the list of servers from the naming service Poke each server serially and, upon fault detection, remove that server from the list of servers.
protected  class FaultTolerantClientManager.ReturnValueOrException
          Return value or an exception along with the return value or the exception object.
 
Field Summary
protected  FaultTolerantClientManager.BackgroundThread backgroundThread
          Our background thread that handles name service interactions, fault detections, and fault recoveries
protected  int clientID
          The server-generated client ID
protected static Method closeClientManager
           
protected static Method enterLot
           
protected  PrintStream err
          Original System.err object instance
protected static Method exitLot
           
protected  ClientManagerFactory factory
          The last-known client manager factory instance
protected  boolean fault
          When true, we are presently processing a fault
protected  LogEntry faultyCallLogEntry
          A logEntry instance to log to when fault is true
protected static Method getClientID
           
protected static Method getCurrentLevel
           
protected static Method getLots
           
protected static Method getMaxLevel
           
protected static Method getMinLevel
           
protected static Method getOtherLotAvailability
           
protected static PrintStream inputEater
          Shared static instance of the input eater output stream wrapped in a PrintStream
private  int interRequestTime
          Time between requests
protected  Logger logger
          Our Logger instance
protected static Method moveDownLevel
           
protected static Method moveUpLevel
           
protected  boolean neverGiveUp
          When true, never give up when trying to contact the server
protected  ClientManager primaryClientManager
          The primary client manager
protected  Object primaryClientManagerLock
          Lock for primaryClientManager, factory, faultyCallLogEntry, systemDown, and fault
protected  int recoveryTimeout
          The wait timeout to use during fault recoveries
protected  int seq
          The latest sequence number from the client
protected  boolean systemDown
          When true, the system is officially down due to no registration of a primary server
protected static String unexpectedException
          Message for unexpected exceptions that arise during remote method calls (non-IDL and non-CORBA exceptions)
 
Constructor Summary
FaultTolerantClientManager(ORB orb, Logger logger, int interRequestTime, boolean neverGiveUp, int detectionTimeout, int recoveryTimeout, PrintStream err)
          Creates a new fault-tolerant client manager that automatically fails over to new primary servers on method call failures
 
Method Summary
protected  FaultTolerantClientManager.ReturnValueOrException callServer(Method method, boolean logAndWait, Object... arguments)
          Calls the given method on the server with the given arguments and returns a ReturnValueOrException object to indicate a normal or exceptional result and contain the return value or the exception object.
 void closeClientManager()
          Closes the client manager and frees server resources associated with it, including the client manager's activation in the server's CORBA portable object adapter.
protected  boolean connectToAnyServer(ClientManager faultyClientManager, LogEntry logEntry)
          Connects to any registered server, which is chosen randomly
 PaddedIntegerSeq enterLot(int seq, int lot)
          Moves the client's car into the lot with the given lot number and returns an array of level numbers that have available spaces
 PaddedVoid exitLot(int seq)
          Removes the client's car from the lot that it is currently in
 PaddedInteger getClientID()
          Returns the client's ID, which can be used in the client manager factory's getExistingClientManager() method
 PaddedInteger getCurrentLevel()
          Returns the car's current level number
 PaddedIntegerSeq getLots()
          Returns an array of valid lot numbers in the system, sorted by the lot number in ascending order
 PaddedInteger getMaxLevel()
          Returns the top level number of the car's current parking lot
 PaddedInteger getMinLevel()
          Returns the bottom level number of the car's current parking lot
 PaddedIntegerSeq getOtherLotAvailability(int lot)
          Returns an array of other lots that have availability, sorted by lot distance such that closer lots are listed first
 void hoseServerDatabaseConnection()
          Hoses the server's database connection.
protected  void interRequestWait()
          Wait for the configured inter-request wait period or, if none is configured, return immediately.
 PaddedInteger moveDownLevel(int seq)
          Moves the car from its present level to the level beneath it
 PaddedInteger moveUpLevel(int seq)
          Moves the car from its present level to the level above it
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

primaryClientManager

protected ClientManager primaryClientManager
The primary client manager


factory

protected ClientManagerFactory factory
The last-known client manager factory instance


fault

protected boolean fault
When true, we are presently processing a fault


systemDown

protected boolean systemDown
When true, the system is officially down due to no registration of a primary server


faultyCallLogEntry

protected LogEntry faultyCallLogEntry
A logEntry instance to log to when fault is true


primaryClientManagerLock

protected Object primaryClientManagerLock
Lock for primaryClientManager, factory, faultyCallLogEntry, systemDown, and fault


backgroundThread

protected FaultTolerantClientManager.BackgroundThread backgroundThread
Our background thread that handles name service interactions, fault detections, and fault recoveries


seq

protected int seq
The latest sequence number from the client


clientID

protected int clientID
The server-generated client ID


interRequestTime

private int interRequestTime
Time between requests


logger

protected Logger logger
Our Logger instance


neverGiveUp

protected boolean neverGiveUp
When true, never give up when trying to contact the server


recoveryTimeout

protected int recoveryTimeout
The wait timeout to use during fault recoveries


err

protected PrintStream err
Original System.err object instance


getClientID

protected static final Method getClientID

enterLot

protected static final Method enterLot

exitLot

protected static final Method exitLot

getOtherLotAvailability

protected static final Method getOtherLotAvailability

getLots

protected static final Method getLots

moveUpLevel

protected static final Method moveUpLevel

moveDownLevel

protected static final Method moveDownLevel

getCurrentLevel

protected static final Method getCurrentLevel

getMaxLevel

protected static final Method getMaxLevel

getMinLevel

protected static final Method getMinLevel

closeClientManager

protected static final Method closeClientManager

unexpectedException

protected static final String unexpectedException
Message for unexpected exceptions that arise during remote method calls (non-IDL and non-CORBA exceptions)

See Also:
Constant Field Values

inputEater

protected static PrintStream inputEater
Shared static instance of the input eater output stream wrapped in a PrintStream

Constructor Detail

FaultTolerantClientManager

public FaultTolerantClientManager(ORB orb,
                                  Logger logger,
                                  int interRequestTime,
                                  boolean neverGiveUp,
                                  int detectionTimeout,
                                  int recoveryTimeout,
                                  PrintStream err)
                           throws ServiceUnavailableException
Creates a new fault-tolerant client manager that automatically fails over to new primary servers on method call failures

Parameters:
orb - The object request broker instance to use
logger - The Logger instance to write performance data to
interRequestTime - The time to wait between method invocations
neverGiveUp - When true, the client will never give up its attempt to contact the server, even if no primary is registered
detectionTimeout - The wait timeout to use during fault detections
recoveryTimeout - The wait timeout to use during fault recoveries
The - System.err instance to use
Throws:
ServiceUnavailableException - Thrown when a primary server could not be located or contacted
Method Detail

callServer

protected FaultTolerantClientManager.ReturnValueOrException callServer(Method method,
                                                                       boolean logAndWait,
                                                                       Object... arguments)
Calls the given method on the server with the given arguments and returns a ReturnValueOrException object to indicate a normal or exceptional result and contain the return value or the exception object. If server communication or service unavailability exceptions arise, this method will automatically fail over to the new primary after that becomes available. Server communication and service unavailability exceptions are only returned if no primary server is registered

Parameters:
method - The method to call on our client manager on the primary server
logAndWait - When true, this method call will be logged and, after returning from that call, this method will wait for the inter-request time before returning
arguments - The arguments to pass to the given method's parameters
Returns:
A ReturnValueOrException indicating a normal or exceptional result

getClientID

public PaddedInteger getClientID()
                          throws ServiceUnavailableException
Returns the client's ID, which can be used in the client manager factory's getExistingClientManager() method

Specified by:
getClientID in interface ClientManagerOperations
Returns:
The client's ID
Throws:
ServiceUnavailableException - Thrown when the log is closed and the server is shutting down

enterLot

public PaddedIntegerSeq enterLot(int seq,
                                 int lot)
                          throws AlreadyInLotException,
                                 LotNotFoundException,
                                 LotFullException,
                                 ServiceUnavailableException
Moves the client's car into the lot with the given lot number and returns an array of level numbers that have available spaces

Specified by:
enterLot in interface ClientManagerOperations
Parameters:
seq - The latest sequence number of the client
lot - The lot number to enter
Returns:
An array of level numbers that have available spaces [Category: Baseline; Requirements: 1, 2, and 3]
Throws:
AlreadyInLotException - Thrown when the client's car is already in a lot
LotNotFoundException - Thrown if the given lot number is not known to the system
LotFullException - Thrown if the given lot is full
ServiceUnavailableException - Thrown if the database cannot be contacted or if some other reason prevents the car from entering the lot

exitLot

public PaddedVoid exitLot(int seq)
                   throws NotInLotException,
                          NotOnExitLevelException,
                          ServiceUnavailableException
Removes the client's car from the lot that it is currently in

Specified by:
exitLot in interface ClientManagerOperations
Parameters:
seq - The latest sequence number of the client
Throws:
NotInLotException - Thrown if the car is not in a lot
NotOnExitLevelException - Thrown if the car is in a lot but is not on a permitted exit level
ServiceUnavailableException - Thrown if the database cannot be contacted or if some other reason prevents the car from exiting the lot [Category: Baseline; Requirement: 7]

getOtherLotAvailability

public PaddedIntegerSeq getOtherLotAvailability(int lot)
                                         throws LotNotFoundException,
                                                ServiceUnavailableException
Returns an array of other lots that have availability, sorted by lot distance such that closer lots are listed first

Specified by:
getOtherLotAvailability in interface ClientManagerOperations
Parameters:
lot - The lot to get lot distances from
Returns:
An array of other lots that have availability [Category: Baseline; Requirement: 4]
Throws:
LotNotFoundException - Thrown if the given lot number is not known to the system
ServiceUnavailableException - Thrown if the database cannot be contacted or if some other reason prevents the system from discovering the availability of other lots

getLots

public PaddedIntegerSeq getLots()
                         throws ServiceUnavailableException
Returns an array of valid lot numbers in the system, sorted by the lot number in ascending order

Specified by:
getLots in interface ClientManagerOperations
Returns:
An array of valid lot numbers in the system [Category: Baseline; Requirement: 12]
Throws:
ServiceUnavailableException - Thrown if the database cannot be contacted or if some other reason prevents the system from discovering the its defined lots

moveUpLevel

public PaddedInteger moveUpLevel(int seq)
                          throws NotInLotException,
                                 AtTopLevelException,
                                 ServiceUnavailableException
Moves the car from its present level to the level above it

Specified by:
moveUpLevel in interface ClientManagerOperations
Parameters:
seq - The latest sequence number of the client
Returns:
The level number that the client's car is now on [Category: Baseline; Requirement: 6]
Throws:
NotInLotException - Thrown if the car is not in a lot
AtTopLevelException - Thrown if the car is already on the highest level
ServiceUnavailableException - Thrown if the database cannot be contacted or if some other reason prevents the car from moving to the next highest level

moveDownLevel

public PaddedInteger moveDownLevel(int seq)
                            throws NotInLotException,
                                   AtBottomLevelException,
                                   ServiceUnavailableException
Moves the car from its present level to the level beneath it

Specified by:
moveDownLevel in interface ClientManagerOperations
Parameters:
seq - The latest sequence number of the client
Returns:
The level number that the client's car is now on [Category: Baseline; Requirement: 6]
Throws:
NotInLotException - Thrown if the car is not in a lot
AtTopLevelException - Thrown if the car is already on the lowest level
ServiceUnavailableException - Thrown if the database cannot be contacted or if some other reason prevents the car from moving to the lower level
AtBottomLevelException

getCurrentLevel

public PaddedInteger getCurrentLevel()
                              throws NotInLotException,
                                     ServiceUnavailableException
Returns the car's current level number

Specified by:
getCurrentLevel in interface ClientManagerOperations
Returns:
The car's current level number [Category: Baseline; Requirement: 6]
Throws:
NotInLotException - Thrown if the car is not in a lot
ServiceUnavailableException - Thrown if the database cannot be contacted or if some other reason prevents the system from returning the car's current level

getMaxLevel

public PaddedInteger getMaxLevel()
                          throws NotInLotException,
                                 ServiceUnavailableException
Returns the top level number of the car's current parking lot

Specified by:
getMaxLevel in interface ClientManagerOperations
Returns:
The top level number of the car's current parking lot [Category: Baseline; Requirement: 6]
Throws:
NotInLotException - Thrown if the car is not in a lot
ServiceUnavailableException - Thrown if the database cannot be contacted or if some other reason prevents the system from returning the current lot's highest level

getMinLevel

public PaddedInteger getMinLevel()
                          throws NotInLotException,
                                 ServiceUnavailableException
Returns the bottom level number of the car's current parking lot

Specified by:
getMinLevel in interface ClientManagerOperations
Returns:
The bottom level number of the car's current parking lot [Category: Baseline; Requirement: 6]
Throws:
NotInLotException - Thrown if the car is not in a lot
ServiceUnavailableException - Thrown if the database cannot be contacted or if some other reason prevents the system from returning the current lot's lowest level

closeClientManager

public void closeClientManager()
                        throws ServiceUnavailableException
Closes the client manager and frees server resources associated with it, including the client manager's activation in the server's CORBA portable object adapter. AFter calling this method, you should not use this FaultTolerantClientManager instance again

Specified by:
closeClientManager in interface ClientManagerOperations
Throws:
ServiceUnavailableException - Thrown if the database cannot be contacted or if some other reason prevents the system from closing the client manager. The client manager remains open if this exception gets thrown

interRequestWait

protected void interRequestWait()
Wait for the configured inter-request wait period or, if none is configured, return immediately. Note that interrupting the calling Thread will cause this method to return immediately after being interrupted


hoseServerDatabaseConnection

public void hoseServerDatabaseConnection()
Hoses the server's database connection. This is primarily used for fault injection


connectToAnyServer

protected boolean connectToAnyServer(ClientManager faultyClientManager,
                                     LogEntry logEntry)
Connects to any registered server, which is chosen randomly

Parameters:
faultyClientManager - The ClientManager that was deemed to be faulty, or null if no ClientManager is faulty
logEntry - The LogEntry object to write performance data to when not null
Returns:
True when a connection with a server was successfully established or false if a server connection could not be established