ehcache

net.sf.ehcache.distribution
Class RMICacheManagerPeerListener

java.lang.Object
  extended by net.sf.ehcache.distribution.RMICacheManagerPeerListener
All Implemented Interfaces:
CacheManagerPeerListener, CacheManagerEventListener

public class RMICacheManagerPeerListener
extends java.lang.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 611 2008-05-05 23:12:52Z gregluck $
Author:
Greg Luck

Field Summary
protected  java.util.Map cachePeers
          The cache peers.
protected  java.lang.Integer port
          The RMI listener port
protected  Status status
          status.
 
Constructor Summary
RMICacheManagerPeerListener(java.lang.String hostName, java.lang.Integer port, java.lang.Integer remoteObjectPort, CacheManager cacheManager, java.lang.Integer socketTimeoutMillis)
          Constructor with full arguments.
 
Method Summary
(package private)  void addCachePeer(java.lang.String name, RMICachePeer peer)
          Package local method for testing
protected  void assignFreePort(boolean forced)
          Assigns a free port to be the listener port.
 void attemptResolutionOfUniqueResourceConflict()
          If a conflict is detected in unique resource use, this method signals the listener to attempt automatic resolution of the resource conflict.
protected  void bind(java.lang.String peerName, RMICachePeer rmiCachePeer)
          Bind a cache peer
protected  java.lang.String calculateHostAddress()
          Calculates the host address as the default NICs IP address
 void dispose()
          Stop the listener.
protected  void disposeRMICachePeer(RMICachePeer rmiCachePeer)
          A template method to dispose an individual RMICachePeer.
 java.util.List getBoundCachePeers()
          All of the caches which are listening for remote changes.
protected  int getFreePort()
          Gets a free server socket port.
 Status getStatus()
          Returns the listener status.
 java.lang.String getUniqueResourceIdentifier()
          A listener will normally have a resource that only one instance can use at the same time, such as a port.
 void init()
          Call to start the listeners and do any other required initialisation.
protected  boolean isDistributed(Ehcache cache)
          Determine if the given cache is distributed.
protected  java.lang.String[] listBoundRMICachePeers()
          Returns a list of bound objects.
protected  java.rmi.Remote lookupPeer(java.lang.String name)
          Returns a reference to the remote object.
 void notifyCacheAdded(java.lang.String cacheName)
          Called immediately after a cache has been added and activated.
 void notifyCacheRemoved(java.lang.String cacheName)
          Called immediately after a cache has been disposed and removed.
protected  void populateListOfRemoteCachePeers()
          Should be called on init because this is one of the last things that should happen on CacheManager startup.
protected  void startRegistry()
          Start the rmiregistry.
protected  void stopRegistry()
          Stop the rmiregistry if it was started by this class.
protected  void unbind(RMICachePeer rmiCachePeer)
          Unbinds an RMICachePeer and unexports it.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

cachePeers

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


status

protected Status status
status.


port

protected java.lang.Integer port
The RMI listener port

Constructor Detail

RMICacheManagerPeerListener

public RMICacheManagerPeerListener(java.lang.String hostName,
                                   java.lang.Integer port,
                                   java.lang.Integer remoteObjectPort,
                                   CacheManager cacheManager,
                                   java.lang.Integer socketTimeoutMillis)
                            throws java.net.UnknownHostException
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
remoteObjectPort - the port number on which the remote objects bound in the registry receive calls. This defaults to a free port if not specified.
cacheManager - the CacheManager this listener belongs to
socketTimeoutMillis - TCP/IP Socket timeout when waiting on response
Throws:
java.net.UnknownHostException
Method Detail

assignFreePort

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

Throws:
java.lang.IllegalStateException - if the statis of the listener is not Status.STATUS_UNINITIALISED

calculateHostAddress

protected java.lang.String calculateHostAddress()
                                         throws java.net.UnknownHostException
Calculates the host address as the default NICs IP address

Throws:
java.net.UnknownHostException

getFreePort

protected int getFreePort()
                   throws java.lang.IllegalArgumentException
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:
java.lang.IllegalArgumentException

init

public void init()
          throws CacheException
Call to start the listeners and do any other required initialisation. init should also handle any work to do with the caches that are part of the initial configuration.

Specified by:
init in interface CacheManagerEventListener
Throws:
CacheException - - all exceptions are wrapped in CacheException

bind

protected void bind(java.lang.String peerName,
                    RMICachePeer rmiCachePeer)
             throws java.lang.Exception
Bind a cache peer

Parameters:
rmiCachePeer -
Throws:
java.lang.Exception

listBoundRMICachePeers

protected java.lang.String[] listBoundRMICachePeers()
                                             throws CacheException
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
Throws:
CacheException

lookupPeer

protected java.rmi.Remote lookupPeer(java.lang.String name)
                              throws CacheException
Returns a reference to the remote object.

Parameters:
name - the name of the cache e.g. sampleCache1
Throws:
CacheException

populateListOfRemoteCachePeers

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

Throws:
java.rmi.RemoteException

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

startRegistry

protected void startRegistry()
                      throws java.rmi.RemoteException
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"

Throws:
java.rmi.RemoteException

stopRegistry

protected void stopRegistry()
                     throws java.rmi.RemoteException
Stop the rmiregistry if it was started by this class.

Throws:
java.rmi.RemoteException

dispose

public void dispose()
             throws CacheException
Stop the listener. It

Specified by:
dispose in interface CacheManagerEventListener
Throws:
CacheException - - all exceptions are wrapped in CacheException

disposeRMICachePeer

protected void disposeRMICachePeer(RMICachePeer rmiCachePeer)
                            throws java.lang.Exception
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:
java.lang.Exception - thrown if something goes wrong

unbind

protected void unbind(RMICachePeer rmiCachePeer)
               throws java.lang.Exception
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:
java.lang.Exception

getBoundCachePeers

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

Specified by:
getBoundCachePeers in interface CacheManagerPeerListener
Returns:
a list of RMICachePeer objects. The list if not live

getStatus

public Status getStatus()
Returns the listener status.

Specified by:
getStatus in interface CacheManagerEventListener
Returns:
the status at the point in time the method is called

getUniqueResourceIdentifier

public java.lang.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.

Specified by:
getUniqueResourceIdentifier in interface CacheManagerPeerListener
Returns:
a String identifier for the resource

attemptResolutionOfUniqueResourceConflict

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

Specified by:
attemptResolutionOfUniqueResourceConflict in interface CacheManagerPeerListener
Throws:
java.lang.IllegalStateException - if the statis of the listener is not Status.STATUS_UNINITIALISED
CacheException

notifyCacheAdded

public void notifyCacheAdded(java.lang.String cacheName)
                      throws CacheException
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.STATUS_UNINITIALISED to Status.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

Specified by:
notifyCacheAdded in interface CacheManagerEventListener
Parameters:
cacheName - the name of the Cache the operation relates to
Throws:
CacheException
See Also:
CacheEventListener

notifyCacheRemoved

public void notifyCacheRemoved(java.lang.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.

Specified by:
notifyCacheRemoved in interface CacheManagerEventListener
Parameters:
cacheName - the name of the Cache the operation relates to

addCachePeer

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


ehcache