net.sf.ehcache.distribution

Class RMICacheManagerPeerListener

public class RMICacheManagerPeerListener extends Object implements CacheManagerPeerListener

A cache server which exposes available cache operations remotely through RMI.

It acts as a Decorator to a Cache. It holds an instance of cache, which is a local cache it talks to.

This class could specify a security manager with code like:

 if (System.getSecurityManager() == null) {
     System.setSecurityManager(new RMISecurityManager());
 }
 
Doing so would require the addition of grant statements in the java.policy file.

Per the JDK documentation: "If no security manager is specified no class loading, by RMI clients or servers, is allowed, aside from what can be found in the local CLASSPATH." The classpath of each instance of this class should have all required classes to enable distribution, so no remote classloading is required or desirable. Accordingly, no security manager is set and there are no special JVM configuration requirements.

This class opens a ServerSocket. The dispose method should be called for orderly closure of that socket. This class has a shutdown hook which calls dispose() as a convenience feature for developers.

Version: $Id: RMICacheManagerPeerListener.java 191 2006-09-03 22:41:48Z gregluck $

Author: Greg Luck

Field Summary
protected MapcachePeers
The cache peers.
protected Integerport
The RMI listener port
protected Statusstatus
status.
Constructor Summary
RMICacheManagerPeerListener(String hostName, Integer port, CacheManager cacheManager, Integer socketTimeoutMillis)
Constructor with full arguments.
Method Summary
voidaddCachePeer(String name, RMICachePeer peer)
Package local method for testing
protected voidassignFreePort(boolean forced)
Assigns a free port to be the listener port.
voidattemptResolutionOfUniqueResourceConflict()
If a conflict is detected in unique resource use, this method signals the listener to attempt automatic resolution of the resource conflict.
protected voidbind(RMICachePeer rmiCachePeer)
Bind a cache peer
protected StringcalculateHostAddress()
Calculates the host address as the default NICs IP address
voiddispose()
Stop the listener.
protected voiddisposeRMICachePeer(RMICachePeer rmiCachePeer)
A template method to dispose an individual RMICachePeer.
ListgetBoundCachePeers()
All of the caches which are listening for remote changes.
protected intgetFreePort()
Gets a free server socket port.
StatusgetStatus()
Returns the listener status.
StringgetUniqueResourceIdentifier()
A listener will normally have a resource that only one instance can use at the same time, such as a port.
voidinit()
protected booleanisDistributed(Ehcache cache)
Determine if the given cache is distributed.
protected String[]listBoundRMICachePeers()
Returns a list of bound objects.
protected RemotelookupPeer(String name)
Returns a reference to the remote object.
voidnotifyCacheAdded(String cacheName)
Called immediately after a cache has been added and activated.
voidnotifyCacheRemoved(String cacheName)
Called immediately after a cache has been disposed and removed.
protected voidpopulateListOfRemoteCachePeers()
Should be called on init because this is one of the last things that should happen on CacheManager startup.
protected voidremoveShutdownHook()
Remove the shutdown hook to prevent leaving orphaned caches around.
protected voidstartRegistry()
Start the rmiregistry.
protected voidunbind(RMICachePeer rmiCachePeer)
Unbinds an RMICachePeer and unexports it.

Field Detail

cachePeers

protected final Map cachePeers
The cache peers. The value is an RMICachePeer.

port

protected Integer port
The RMI listener port

status

protected Status status
status.

Constructor Detail

RMICacheManagerPeerListener

public RMICacheManagerPeerListener(String hostName, Integer port, CacheManager cacheManager, Integer socketTimeoutMillis)
Constructor with full arguments.

Parameters: hostName may be null, in which case the hostName will be looked up. Machines with multiple interfaces should specify this if they do not want it to be the default NIC. port a port in the range 1025 - 65536 cacheManager the CacheManager this listener belongs to socketTimeoutMillis TCP/IP Socket timeout when waiting on response

Method Detail

addCachePeer

void addCachePeer(String name, RMICachePeer peer)
Package local method for testing

assignFreePort

protected void assignFreePort(boolean forced)
Assigns a free port to be the listener port.

Throws: IllegalStateException if the statis of the listener is not STATUS_UNINITIALISED

attemptResolutionOfUniqueResourceConflict

public void attemptResolutionOfUniqueResourceConflict()
If a conflict is detected in unique resource use, this method signals the listener to attempt automatic resolution of the resource conflict.

Throws: IllegalStateException if the statis of the listener is not STATUS_UNINITIALISED

bind

protected void bind(RMICachePeer rmiCachePeer)
Bind a cache peer

Parameters: rmiCachePeer

calculateHostAddress

protected String calculateHostAddress()
Calculates the host address as the default NICs IP address

Throws: UnknownHostException

dispose

public void dispose()
Stop the listener. It

disposeRMICachePeer

protected void disposeRMICachePeer(RMICachePeer rmiCachePeer)
A template method to dispose an individual RMICachePeer. This consists of:
  1. Unbinding the peer from the naming service
  2. Unexporting the peer
Override to specialise behaviour

Parameters: rmiCachePeer the cache peer to dispose of

Throws: Exception thrown if something goes wrong

getBoundCachePeers

public List getBoundCachePeers()
All of the caches which are listening for remote changes.

Returns: a list of RMICachePeer objects. The list if not live

getFreePort

protected int getFreePort()
Gets a free server socket port.

Returns: a number in the range 1025 - 65536 that was free at the time this method was executed

Throws: IllegalArgumentException

getStatus

public Status getStatus()
Returns the listener status.

getUniqueResourceIdentifier

public String getUniqueResourceIdentifier()
A listener will normally have a resource that only one instance can use at the same time, such as a port. This identifier is used to tell if it is unique and will not conflict with an existing instance using the resource.

Returns: a String identifier for the resource

init

public void init()
{@inheritDoc }

isDistributed

protected boolean isDistributed(Ehcache cache)
Determine if the given cache is distributed.

Parameters: cache the cache to check

Returns: true if a CacheReplicator is found in the listeners

listBoundRMICachePeers

protected String[] listBoundRMICachePeers()
Returns a list of bound objects.

This should match the list of cachePeers i.e. they should always be bound

Returns: a list of String representations of RMICachePeer objects

lookupPeer

protected Remote lookupPeer(String name)
Returns a reference to the remote object.

Parameters: name the name of the cache e.g. sampleCache1

notifyCacheAdded

public void notifyCacheAdded(String cacheName)
Called immediately after a cache has been added and activated.

Note that the CacheManager calls this method from a synchronized method. Any attempt to call a synchronized method on CacheManager from this method will cause a deadlock.

Note that activation will also cause a CacheEventListener status change notification from STATUS_UNINITIALISED to STATUS_ALIVE. Care should be taken on processing that notification because:

The calling method will block until this method returns.

Repopulates the list of cache peers and rebinds the list. This method should be called if a cache is dynamically added

Parameters: cacheName the name of the Cache the operation relates to

See Also: CacheEventListener

notifyCacheRemoved

public void notifyCacheRemoved(String cacheName)
Called immediately after a cache has been disposed and removed. The calling method will block until this method returns.

Note that the CacheManager calls this method from a synchronized method. Any attempt to call a synchronized method on CacheManager from this method will cause a deadlock.

Note that a CacheEventListener status changed will also be triggered. Any attempt from that notification to access CacheManager will also result in a deadlock.

Parameters: cacheName the name of the Cache the operation relates to

populateListOfRemoteCachePeers

protected void populateListOfRemoteCachePeers()
Should be called on init because this is one of the last things that should happen on CacheManager startup.

removeShutdownHook

protected void removeShutdownHook()
Remove the shutdown hook to prevent leaving orphaned caches around. This is called by dispose AFTER the status has been set to shutdown.

startRegistry

protected void startRegistry()
Start the rmiregistry.

The alternative is to use the rmiregistry binary, in which case:

  1. rmiregistry running
  2. -Djava.rmi.server.codebase="file:///Users/gluck/work/ehcache/build/classes/ file:///Users/gluck/work/ehcache/lib/commons-logging-1.0.4.jar"
There appears to be no way to stop an rmiregistry. We check to see if one if already "there" before we create a new one.

Throws: RemoteException

unbind

protected void unbind(RMICachePeer rmiCachePeer)
Unbinds an RMICachePeer and unexports it.

We unbind from the registry first before unexporting. Unbinding first removes the very small possibility of a client getting the object from the registry while we are trying to unexport it.

This method may take up to 4 seconds to complete, if we are having trouble unexporting the peer.

Parameters: rmiCachePeer the bound and exported cache peer

Throws: Exception