User: slaboure
Date: 01/08/19 11:33:53
Added: src/main/org/jboss/ha HAConfigEntry.java HAConfigNode.java
HAConfigNodeImpl.java HAConfigServer.java
HAConfigServerMBean.java HARemoteInfo.java
HARemoteInfoImpl.java HASmallConfigEntries.java
Log:
First import of sources for HA support for EJB (only used by SLSB for now)
Revision Changes Path
1.1 jbossmx/src/main/org/jboss/ha/HAConfigEntry.java
Index: HAConfigEntry.java
===================================================================
/*
* JBoss, the OpenSource J2EE WebOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ha;
import java.util.*;
import JavaGroups.*;
import JavaGroups.Common.Trace;
import java.io.IOException;
import java.util.Hashtable;
import org.jboss.ejb.plugins.jrmp.interfaces.ContainerRemote;
/**
* Config entry for JBoss HA config server
*
* @see HAConfigNode, HAConfigServer
* @author <a href="mailto:[EMAIL PROTECTED]">Sacha Labourey</a>
* @version $Revision: 1.1 $
*
* <p><b>Revisions:</b>
*
* <p><b>20010819 Sacha Labourey:</b>
* <ul>
* <li> First import of sources
* </ul>
*/
public class HAConfigEntry
implements java.io.Externalizable
{
public ContainerRemote targetContainer;
public String node;
public Hashtable jndiServerProps;
public JavaGroups.Address javaGropupsNodeName;
//public Properties other; // not used yet
public HAConfigEntry ()
{
super ();
}
public HAConfigEntry (ContainerRemote target, String node, Properties props)
{
super ();
this.targetContainer = target;
this.node = node;
this.javaGropupsNodeName = null;
//this.other = props;
}
public String toString ()
{
return node + " : " + jndiServerProps +((javaGropupsNodeName!=null)? " : " +
javaGropupsNodeName.toString () : "") + " (" + targetContainer + ")";
}
/**
* Externalize this instance.
*
* If this instance lives in a different VM than its container
* invoker, the remote interface of the container invoker is
* not externalized.
*/
public void writeExternal (java.io.ObjectOutput out)
throws IOException
{
out.writeUTF (node);
out.writeObject (jndiServerProps);
out.writeObject (javaGropupsNodeName);
out.writeObject (targetContainer);
}
/**
* Un-externalize this instance.
*
* If this instance is deserialized in the same VM as its container
* invoker, the remote interface of the container invoker is
* restored by looking up the name in the invokers map.
*/
public void readExternal (java.io.ObjectInput in)
throws IOException, ClassNotFoundException
{
node = in.readUTF ();
jndiServerProps = (Hashtable)in.readObject ();
javaGropupsNodeName = (JavaGroups.Address)in.readObject ();
targetContainer = (ContainerRemote)in.readObject ();
}
}
1.1 jbossmx/src/main/org/jboss/ha/HAConfigNode.java
Index: HAConfigNode.java
===================================================================
/*
* JBoss, the OpenSource J2EE WebOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ha;
import java.util.Vector;
import org.jboss.ejb.plugins.jrmp.interfaces.ContainerRemote;
import java.util.Hashtable;
/**
* Interface describing a node
*
* @see HAConfigNodeImpl
* @author <a href="mailto:[EMAIL PROTECTED]">Sacha Labourey</a>
* @version $Revision: 1.1 $
*
* <p><b>Revisions:</b>
*
* <p><b>20010819 Sacha Labourey:</b>
* <ul>
* <li> First import of sources
* </ul>
*/
public interface HAConfigNode
{
public interface HAEventsCallbackable
{
void beanReplicaModified (java.util.Vector newValue);
}
public static final String REMOTE_TYPE = "remote";
public static final String HOME_TYPE = "home";
public void init (String cluster, String node, String haConnection, long
normalDelay, long deathDelay);
public void start ()
throws Exception;
public void stop ();
public void setNormalDelay (long normalDelay);
public void setDeathDelay (long deathDelay);
public long getNormalDelay ();
public long getDeathDelay ();
public void registerContainer (HAEventsCallbackable source, String application,
String beanname, String type, HAConfigEntry settings);
public void unregisterContainer (String application, String beanname, String
type);
public Vector getReplicateContainers (String application, String beanname, String
type);
public String getHaAppPath (String application, String beanname, String type);
public String getNodeName ();
public String getPresentation ();
public HASmallConfigEntries getSmallConfigEntriesForApp (String path);
public Hashtable getLocalJndiProps ();
}
1.1 jbossmx/src/main/org/jboss/ha/HAConfigNodeImpl.java
Index: HAConfigNodeImpl.java
===================================================================
/*
* JBoss, the OpenSource J2EE WebOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ha;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.io.Serializable;
import javax.naming.Context;
import JavaGroups.DistributedTree;
import JavaGroups.DistributedTree.DistributedTreeListener;
import JavaGroups.Address;
import JavaGroups.Common.Trace;
import org.jboss.logging.Logger;
import org.jboss.ejb.plugins.jrmp.interfaces.ContainerRemote;
/**
* Config server for JBoss HA implementation
*
* @see HAConfigNode
* @author <a href="mailto:[EMAIL PROTECTED]">Sacha Labourey</a>
* @version $Revision: 1.1 $
*
* <p><b>Revisions:</b>
*
* <p><b>20010819 Sacha Labourey:</b>
* <ul>
* <li> First import of sources
* </ul>
*/
public class HAConfigNodeImpl implements HAConfigNode
{
public interface HAEventsCallbackable
{
void beanReplicaModified (java.util.Vector newValue);
}
public static final String REMOTE_TYPE = "remote";
public static final String HOME_TYPE = "home";
public static final String CONFIG_ENTRY = "*config*";
// Constants -----------------------------------------------------
final String defConnection
="UDP(mcast_addr=224.100.100.200;mcast_port=4567;ip_ttl=31;trace=true):" +
"PING(timeout=3000;num_initial_members=10):" +
"FD(trace=true;timeout=5000):" +
"VERIFY_SUSPECT(trace=false;timeout=1500):" +
//"pbcast.PBCAST(desired_avg_gossip=5000;dynamic=true;mcast_gossip=true;" +
// "gc_lag=50;max_queue=40;trace=true;shun=false):" +
// "DISCARD(down=0.1;trace=true):" +
"pbcast.NAKACK(trace=true):" +
"UNICAST(timeout=5000;min_wait_time=2000):" +
"FRAG:" +
"pbcast.GMS:" +
//"pbcast.GMS(initial_mbrs_timeout=4000;join_timeout=5000;join_retry_timeout=2000;" +
//"trace=true;shun=false;print_local_addr=false):" +
"pbcast.STATE_TRANSFER(trace=true)";
/*
final String defConnection
="UDP(mcast_addr=224.100.100.200;mcast_port=4567):PING(num_initial_members=2;timeout=3000):FD:"
+
// "DISCARD(down=0.1):" + // this is for discarding of 10% of the up messages !
"pbcast.PBCAST(gossip_interval=5000;gc_lag=50):" +
"UNICAST:" +
"FRAG:" +
"pbcast.GMS:" +
"pbcast.STATE_TRANSFER(trace=true)";
*/
private final String JNDI_PROVIDER_PREFIX = "jnp";
private final String JNDI_PORT_NUMBER = "1099"; // read it from JMX config in a
next version
// Attributes ----------------------------------------------------
String clusterName = null;
String escClusterName = null;
DistributedTree beans = null;
String nodeName = null;
String haConnection = null;
java.util.Hashtable callbacks = null;
JavaGroups.Address javaGropupsNodeName = null;
EventDispatcher dispatcher = null;
Hashtable jndiProps = null;
long proxyNormalRefresh = 30000;
long proxyDeathRefresh = 5000;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
public HAConfigNodeImpl ()
{
super();
}
// Public --------------------------------------------------------
public void init (String cluster, String node, String haConnection, long
normalDelay, long deathDelay)
{
// set local values from our MBEAN service
//
this.clusterName = cluster;
this.escClusterName = escapeChars (cluster);
this.nodeName = node;
this.proxyDeathRefresh = deathDelay;
this.proxyNormalRefresh = normalDelay;
this.callbacks = new java.util.Hashtable ();
if (haConnection == null) // JavaGroups connection string
this.haConnection = this.defConnection;
else
this.haConnection = haConnection;
// determine the URL of the locally used
}
public void start ()
throws Exception
{
try
{
// We need to remember the name of our JNDI server URL. This is not a good
way to do it: we should
// directly get this from the config... To be improved
//
jndiProps = new Hashtable (2);
jndiProps.put (Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
jndiProps.put (Context.PROVIDER_URL, java.net.InetAddress.getLocalHost
().getHostName ()+ ":" + JNDI_PORT_NUMBER);
// This is the main distributed tree we use for sharing HA info. In the
future, configuration such as
// refresh delay (proxyDeathRefresh and proxyNormalRefresh) should also be
shared this way.
//
beans = new DistributedTree ("JBossHA", haConnection);
// we want to be informed about any update of the shared tree ...
//
dispatcher = new EventDispatcher ();
beans.AddDistributedTreeListener (dispatcher);
// ... and membership composition (to clean dead entries)
//
beans.AddMembershipListener (dispatcher);
beans.Start ();
// we also remember our JavaGroups name
//
this.javaGropupsNodeName = (Address)beans.GetLocalAddress ();
} catch (Exception e)
{ e.printStackTrace (); }
}
public void setNormalDelay (long normalDelay)
{
this.proxyNormalRefresh = normalDelay;
}
public void setDeathDelay (long deathDelay)
{
this.proxyDeathRefresh = deathDelay;
}
public long getNormalDelay ()
{
return this.proxyNormalRefresh;
}
public long getDeathDelay ()
{
return this.proxyDeathRefresh;
}
public void stop ()
{
beans = null;
}
public void registerContainer (HAConfigNode.HAEventsCallbackable source, String
application, String beanname, String type, HAConfigEntry settings)
{
if (beans != null)
try
{
String builtName = this.buildKey (application, beanname, type);
settings.node = this.nodeName;
settings.jndiServerProps = this.jndiProps;
settings.javaGropupsNodeName = this.javaGropupsNodeName;
this.addEntry (builtName, settings);
// Store local container reference responsible for this app name
//
synchronized (callbacks)
{ callbacks.put (builtName, source); }
}
catch (Exception e)
{e.printStackTrace (); }
else
Logger.debug ("registerContainer: called while distributed hashtable
unavailble!");
}
public void unregisterContainer (String application, String beanname, String type)
{
if (beans != null)
try
{
String builtName = this.buildKey (application, beanname, type);
synchronized (callbacks)
{ callbacks.remove (builtName); }
this.removeEntry (builtName, nodeName);
}
catch (Exception e)
{e.printStackTrace (); }
else
Logger.debug ("unregisterContainer: called while distributed hashtable
unavailble!");
}
public Vector getReplicateContainers (String application, String beanname, String
type)
{
String builtName = this.buildKey (application, beanname, type);
return this.getReplicateContainers (builtName);
}
public String getNodeName ()
{
return this.nodeName;
}
public String getPresentation ()
{
try
{
StringBuffer result = new StringBuffer ();
result.append ("/");
return getPresentation (result, "/", 1, "").toString ();
}
catch (Exception e)
{
e.printStackTrace ();
}
return "";
}
// this creates a list of targets as small as possible (i.e. without any
unusefull data)
// (used to update proxies)
//
public HASmallConfigEntries getSmallConfigEntriesForApp (String path)
{
java.util.Vector data = this.getReplicateContainers (path);
int size = data.size ();
HASmallConfigEntries result = new HASmallConfigEntries ();
result.containers = new ContainerRemote [size];
result.jndiProps = new Hashtable[size];
for (int i=0; i < size; i++)
{
HAConfigEntry entry = (HAConfigEntry)data.elementAt (i);
result.containers[i] = entry.targetContainer;
result.jndiProps[i] = entry.jndiServerProps;
}
result.delayForRefresh = this.proxyNormalRefresh;
result.delayForResynchAfterDeath = this.proxyDeathRefresh;
return result;
}
public Hashtable getLocalJndiProps ()
{
return this.jndiProps;
}
public String getHaAppPath (String application, String beanname, String type)
{
return this.buildKey (application, beanname, type);
}
// ************************** private
**********************************************************
private String escapeChars (String source)
{
java.text.StringCharacterIterator strIter = new
java.text.StringCharacterIterator (source);
StringBuffer dest = new StringBuffer (source.length ());
for(char c = strIter.first (); c != java.text.CharacterIterator.DONE; c =
strIter.next ())
dest.append ( ((c=='/')? '*' : c ) );
return dest.toString ();
}
private StringBuffer getPresentation (StringBuffer result, String name, int
level, String spaces)
{
try
{
java.util.Vector sons = beans.GetChildrenNames (name);
int nbSons = sons.size ();
Object value = null;
String fqn = null;
for (int i=0; i<nbSons; i++)
{
result.append ("\n").append (spaces).append ("\\--- ").append
(sons.elementAt (i)).append (" ");
fqn = name + "/" + sons.elementAt (i);
value = beans.Get (fqn);
if (value != null)
result.append (value.toString ());
getPresentation (result, fqn, level + 1, spaces + " ");
}
}
catch (Exception e)
{
e.printStackTrace ();
}
return result;
}
private Vector getReplicateContainers (String builtName)
{
Vector result = null;
if (beans != null)
result = this.getEntries (builtName);
else
{
Logger.debug ("getReplicateContainers: called while distributed hashtable
unavailble!");
result = new Vector ();
}
return result;
}
private HAConfigNode.HAEventsCallbackable getLocalListenerForApp (String app)
{
synchronized (callbacks)
{
return (HAConfigNode.HAEventsCallbackable)callbacks.get (app);
}
}
// Private -----------------------------------------------------
private String buildKey (String app, String bean, String type)
{
return "/" + escClusterName + "/" + escapeChars (app) + "/" + escapeChars
(bean) + "/" + escapeChars (type);
}
private String buildConfigKey (String key)
{ // not used for now...
return "/" + escClusterName + "/" + CONFIG_ENTRY + "/" + escapeChars (key);
}
private void removeEntry (String key, String node)
{
try
{
String completePath = key + "/" + node;
if (beans.Exists (completePath))
{
beans.Remove (completePath);
// check if this is the last entry => cleanup
//
if (beans.GetChildrenNames (key).size () == 0)
beans.Remove (key);
}
}
catch (Exception e)
{ e.printStackTrace (); }
}
private void addEntry (String key, HAConfigEntry settings)
{
try
{
String completePath = key + "/" + settings.node;
beans.Add (completePath, settings);
}
catch (Exception e)
{ e.printStackTrace (); }
}
private Vector getEntries (String key)
{
java.util.Vector result = new java.util.Vector ();
try
{
java.util.Vector sons = beans.GetChildrenNames (key);
int nbSons = sons.size ();
for (int i=0; i<nbSons; i++)
result.add (beans.Get (key + "/" + (String)sons.elementAt (i)));
}
catch (Exception e)
{
e.printStackTrace ();
}
return result;
}
//
***************************************************************************************
// ********************** INNER CLASS (THREAD THAT DISPATCHES EVENTS)
********************
//
***************************************************************************************
class EventDispatcher
implements Runnable, DistributedTree.DistributedTreeListener,
DistributedTree.MembershipListener
{
private java.util.Vector events = new java.util.Vector (20);
private Thread dispatcherThread = null;
private volatile boolean threadSuspended = false;
public EventDispatcher ()
{
super ();
dispatcherThread = new Thread (this);
dispatcherThread.setDaemon (true);
dispatcherThread.setName ("HAConfigCallbacks");
dispatcherThread.start ();
}
public void run ()
{
while (true)
{
try
{
if (threadSuspended)
{
synchronized(this)
{
threadSuspended = (events.size () <= 0);
while (threadSuspended)
wait ();
}
}
} catch (InterruptedException e)
{ }
// dispatch events
//
try
{
if (events.size () > 0)
{
EventEntry anEvent = null;
synchronized (events)
{
anEvent = (EventEntry)events.remove (0);
}
// get concerned container
//
if (anEvent.eventType == EventEntry.VIEW_CHANGE_EVENT)
cleanTreeAfterDeath (anEvent.members);
else
{
HAConfigNode.HAEventsCallbackable cr = getLocalListenerForApp
(anEvent.app);
if (cr != null)
cr.beanReplicaModified (getReplicateContainers
(anEvent.app));
}
}
else
threadSuspended = true;
} catch (Exception e)
{e.printStackTrace (); }
}
}
public void addNodeAddedEvent (String fqn, Serializable content)
{
java.util.Vector splitName = getSplitName (fqn);
if (splitName.size () == 5)
{
String clusterName = (String)splitName.elementAt (0);
String appName = (String)splitName.elementAt (1);
String beanName = (String)splitName.elementAt (2);
String typeName = (String)splitName.elementAt (3);
String concernedNode = (String)splitName.elementAt (4);
// only keep events from same cluster but originating from a different
node
//
if (!nodeName.equalsIgnoreCase (concernedNode) &&
clusterName.equalsIgnoreCase (escClusterName))
//we only propagate events for which we are not concerned
//
{
Logger.debug ("Event will be forwarded : " + concernedNode + ", " +
clusterName );
EventEntry entry = new EventEntry ();
entry.eventType = EventEntry.ADD_EVENT;
entry.node = concernedNode;
entry.app = buildKey (appName, beanName, typeName);
entry.contentBefore = content;
synchronized (events)
{
events.add (entry);
}
wakeUpThread ();
}
else
Logger.debug ("... event not forwarded locally.");
}
else
Logger.debug ("... event not forwarded locally.");
}
public void addNodeModifiedEvent (String fqn, Serializable contentBefore,
Serializable contentAfter)
{
java.util.Vector splitName = getSplitName (fqn);
Logger.debug ("Modify Event : " + fqn);
if (splitName.size () == 5)
{
String clusterName = (String)splitName.elementAt (0);
String appName = (String)splitName.elementAt (1);
String beanName = (String)splitName.elementAt (2);
String typeName = (String)splitName.elementAt (3);
String concernedNode = (String)splitName.elementAt (4);
if (!nodeName.equalsIgnoreCase (concernedNode) &&
clusterName.equalsIgnoreCase (escClusterName))
//we only propagate events for which we are not concerned
//
{
EventEntry entry = new EventEntry ();
entry.eventType = EventEntry.MODIFY_EVENT;
entry.node = concernedNode;
entry.app = buildKey (appName, beanName, typeName);
entry.contentBefore = contentBefore;
entry.contentAfter = contentAfter;
synchronized (events)
{
events.add (entry);
}
wakeUpThread ();
}
else
Logger.debug ("... event not forwarded locally.");
}
else
Logger.debug ("... event not forwarded locally.");
}
public void addNodeRemovedEvent (String fqn)
{
java.util.Vector splitName = getSplitName (fqn);
Logger.debug ("Remove Event : " + fqn);
// we may add a check here: if size == 1 and this is for a node for
// which we still have a son, there is a problem. Maybe usefull during
debugging
//
if (splitName.size () == 5)
{
String clusterName = (String)splitName.elementAt (0);
String appName = (String)splitName.elementAt (1);
String beanName = (String)splitName.elementAt (2);
String typeName = (String)splitName.elementAt (3);
String concernedNode = (String)splitName.elementAt (4);
if (!nodeName.equalsIgnoreCase (concernedNode) &&
clusterName.equalsIgnoreCase (escClusterName))
//we only propagate events for which we are not concerned
//
{
EventEntry entry = new EventEntry ();
entry.eventType = EventEntry.REMOVE_EVENT;
entry.node = concernedNode;
entry.app = buildKey (appName, beanName, typeName);
synchronized (events)
{
events.add (entry);
}
wakeUpThread ();
}
else
Logger.debug ("... event not forwarded locally.");
}
else
Logger.debug ("... event not forwarded locally.");
}
private synchronized void wakeUpThread ()
{
if (threadSuspended)
{
threadSuspended = false;
this.notify ();
}
}
private java.util.Vector getSplitName (String nodeName)
{
StringTokenizer tokens = null;
java.util.Vector names = new java.util.Vector (5);
if(nodeName != null)
{
tokens = new StringTokenizer (nodeName, "/");
while(tokens.hasMoreTokens ())
names.add (tokens.nextToken ());
}
return names;
}
private void cleanTreeAfterDeath (Vector addresses)
{
// we check if our containers are concerned about this change
//
Hashtable staticCopy = null; // need to be optimized...
synchronized (callbacks)
{ staticCopy = new Hashtable (callbacks); }
Logger.debug ("Number of dead replicats: " + addresses.size ());
for (Enumeration e = staticCopy.keys () ; e.hasMoreElements () ;)
{
String path = (String)e.nextElement ();
Vector replicas = getReplicateContainers (path);
for (int i=0; i<replicas.size (); i++)
{
HAConfigEntry aReplica = (HAConfigEntry)replicas.elementAt (i);
// ***********************
if (addresses.contains (aReplica.javaGropupsNodeName))
{
Logger.debug ("Because of a death, we suppress this replica from
our list: " + aReplica.toString ());
removeEntry (path, aReplica.node);
// we do not inform our container because has the removing will be
propagated, we will receive such
// information in a few time...
}
}
}
}
public void NodeAdded (String fqn,Serializable element)
{
addNodeAddedEvent (fqn, element);
}
public void NodeRemoved (String fqn)
{
addNodeRemovedEvent (fqn);
}
public void NodeModified (String fqn,Serializable old_element,Serializable
new_element)
{
addNodeModifiedEvent (fqn, old_element, new_element);
}
public void ViewChange (Vector new_mbrs,Vector old_mbrs)
{
Logger.log ("Information", "View changed message received : " + new_mbrs +
", old members : " + old_mbrs);
if (old_mbrs.size () > 0)
{
EventEntry entry = new EventEntry ();
entry.eventType = EventEntry.VIEW_CHANGE_EVENT;
entry.members = old_mbrs;
synchronized (events)
{
events.add (entry);
}
wakeUpThread ();
}
}
// **************************************
// **** our internal event structure ****
// **************************************
class EventEntry implements Serializable
{
static public final int ADD_EVENT = 1;
static public final int MODIFY_EVENT = 2;
static public final int REMOVE_EVENT = 3;
static public final int VIEW_CHANGE_EVENT = 4;
public int eventType = 0;
public String node = null;
public String app = null;
public Serializable contentBefore = null;
public Serializable contentAfter = null;
public Vector members = null;
}
}
}
1.1 jbossmx/src/main/org/jboss/ha/HAConfigServer.java
Index: HAConfigServer.java
===================================================================
/*
* JBoss, the OpenSource J2EE WebOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ha;
import javax.naming.InitialContext;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.naming.Name;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.NameNotFoundException;
import org.jboss.naming.NonSerializableFactory;
import org.jboss.util.ServiceMBeanSupport;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RMISecurityManager;
/**
* MBean interface for an High Availability (HA) config server.
*
* @see HAConfigServerMBean
* @author <a href="mailto:[EMAIL PROTECTED]">Sacha Labourey</a>
* @version $Revision: 1.1 $
*
* <p><b>Revisions:</b>
*
* <p><b>20010819 Sacha Labourey:</b>
* <ul>
* <li> First import of sources
* </ul>
*/
public class HAConfigServer
extends ServiceMBeanSupport
implements HAConfigServerMBean
{
// Constants -----------------------------------------------------
// Attributes ----------------------------------------------------
private String _clusterName = null;
private String _nodeName = null;
private String _javaGroupsSettings = null;
private String _jndiName = null;
private String m_bindName = null;
private HAConfigNode node = null;
private HARemoteInfoImpl externalHA = null;
private long _normalDelay = 30000;
private long _deathDelay = 5000;
private final String SERVICE_NAME = "HA Config Server Service";
protected final static int ANONYMOUS_PORT = 0;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
public HAConfigServer ()
{
super ();
}
// Public --------------------------------------------------------
public String listCurrentEntries ()
throws Exception
{
return "<pre>" + node.getPresentation () + "</pre>"; // as ugly as it is
usefull. Should be improved.
}
public String getName ()
{
return SERVICE_NAME;
}
public void setClusterName (String cluster)
{_clusterName = cluster; }
public String getClusterName ()
{return _clusterName; }
public void setNodeName (String node)
{_nodeName = node; }
public String getNodeName ()
{ return _nodeName; }
public void setJavaGroupsSettings (String settings)
{_javaGroupsSettings = settings; }
public String getJavaGroupsSettings ()
{ return _javaGroupsSettings ; }
public void setProxyRefreshDelay (long delayInMs)
{
_normalDelay = delayInMs;
if (this.node != null)
// If my node service already exists, update it
//
this.node.setNormalDelay (_normalDelay);
}
public long getProxyRefreshDelay ()
{return _normalDelay; }
public void setProxyRefreshDelayAfterTargetDeath (long delayInMs)
{
_deathDelay = delayInMs;
if (this.node != null)
// If my node service already exists, update it
//
this.node.setDeathDelay (_deathDelay);
}
public long getProxyRefreshDelayAfterTargetDeath ()
{ return _deathDelay; }
protected void initService ()
throws Exception
{
// some init data may be missing: we complete them here...
//
if (_nodeName == null)
_nodeName = java.net.InetAddress.getLocalHost ().getHostAddress ();
if (_clusterName == null)
_clusterName = "DEFAULT_CLUSTER";
this.node = new HAConfigNodeImpl ();
this.node.init (_clusterName, _nodeName, _javaGroupsSettings, _normalDelay,
_deathDelay);
this.node.start ();
if (_jndiName == null)
{_jndiName = "java:/HAConfigServer";}
bind (this.node, _jndiName);
}
protected void destroyService ()
{
this.node = null;
}
public void startService ()
throws Exception
{
if (System.getSecurityManager () == null)
{ System.setSecurityManager (new RMISecurityManager ());}
externalHA = new HARemoteInfoImpl (this.node);
//UnicastRemoteObject.exportObject(this.node, ANONYMOUS_PORT);
java.util.Hashtable props = new java.util.Hashtable (2);
// This MUST be improved: we need to get from the system, the *true*
// location of the naming service. The NS may not even be a org.jnp NS
//
props.put ("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.put ("java.naming.provider.url",
"localhost:1099");
Context ctx = new InitialContext (props);
bind (ctx, "/HA/HAConfigServer", externalHA);
}
public void stopService ()
{
this.node.stop ();
try
{
UnicastRemoteObject.unexportObject (externalHA, true);
unbind (m_bindName);
unbind ("/HA/HAConfigServer");
} catch (Exception e)
{}
}
// Private -----------------------------------------------------
// Both bind and unbind methods copied from org.jboss.mail.MailService (Simone
Bordet).
//
private void bind (HAConfigNode nodeService, String where) throws NamingException
{
Context ctx = new InitialContext ();
m_bindName = where;
// Ah ! Session isn't serializable, so we use a helper class
NonSerializableFactory.bind (m_bindName, nodeService);
// The helper class NonSerializableFactory uses address type nns, we go on to
// use the helper class to bind the HAConfigNode object in JNDI
StringRefAddr addr = new StringRefAddr ("nns", m_bindName);
Reference ref = new Reference (HAConfigNode.class.getName (), addr,
NonSerializableFactory.class.getName (), null);
bind (ctx, where, ref);
log.log ("HAConfigService Service '" + where + "' bound to " + m_bindName);
}
// This method is used to bind a smaller view of the HA Service used by proxies
to update their view
// of available containers. We have an internal and external view of the HA
service such that
// internal services do not have to mess up with RemoteExceptions
//
private void bind (Context ctx, String name, Object val)
throws NamingException
{
// Bind val to name in ctx, and make sure that all intermediate contexts exist
Name n = ctx.getNameParser ("").parse (name);
while (n.size () > 1)
{
String ctxName = n.get (0);
try
{
ctx = (Context)ctx.lookup (ctxName);
} catch (NameNotFoundException e)
{
ctx = ctx.createSubcontext (ctxName);
}
n = n.getSuffix (1);
}
ctx.bind (n.get (0), val);
}
private void unbind (String where) throws NamingException
{
if (where != null)
{
new InitialContext ().unbind (where);
NonSerializableFactory.unbind (where);
log.log ("HAConfigService service '" + _jndiName + "' removed from JNDI");
}
}
}
1.1 jbossmx/src/main/org/jboss/ha/HAConfigServerMBean.java
Index: HAConfigServerMBean.java
===================================================================
/*
* JBoss, the OpenSource J2EE WebOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ha;
/**
* MBean interface for an High Availability (HA) config server.
*
* @see HAConfigServer
* @author <a href="mailto:[EMAIL PROTECTED]">Sacha Labourey</a>
* @version $Revision: 1.1 $
*
* <p><b>Revisions:</b>
*
* <p><b>20010819 Sacha Labourey:</b>
* <ul>
* <li> First import of sources
* </ul>
*/
public interface HAConfigServerMBean
extends org.jboss.util.ServiceMBean
{
// Constants -----------------------------------------------------
public static final String OBJECT_NAME = "JBossHA:service=HAConfig";
// Public --------------------------------------------------------
/**
* Set logical name of the group of JBoss instance sharing beans for HA
*/
public void setClusterName (String cluster);
/**
* Get logical name of the group of JBoss instance sharing beans for HA
*/
public String getClusterName ();
/**
* Set logical name of the current instance of JBoss
*/
public void setNodeName (String node);
/**
* Get logical name of the current instance of JBoss
*/
public String getNodeName ();
/**
* Set communication properties for JavaGroups communication
*/
public void setJavaGroupsSettings (String settings);
/**
* Get communication properties for JavaGroups communication
*/
public String getJavaGroupsSettings ();
/**
* Set the delay frequency to which the proxy should update its containers list
*/
public void setProxyRefreshDelay (long delayInMs);
/**
* Get the delay to which the proxies currently update their targets list
*/
public long getProxyRefreshDelay ();
/**
* Set the delay frequency to which the proxy should update its containers list
* after one of its container has died
*/
public void setProxyRefreshDelayAfterTargetDeath (long delayInMs);
/**
* Get the delay to which the proxies currently update their targets list
* after one of its container has died
*/
public long getProxyRefreshDelayAfterTargetDeath ();
/**
* Return the list of currently replicated bean in this cluster
*/
public String listCurrentEntries ()
throws Exception;
// Private -----------------------------------------------------
}
1.1 jbossmx/src/main/org/jboss/ha/HARemoteInfo.java
Index: HARemoteInfo.java
===================================================================
/*
* JBoss, the OpenSource J2EE WebOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ha;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.jboss.ha.HASmallConfigEntries;
/**
* This interface exports an external view of the HA service i.e. only
* operations that need to be used from the outside. For now, only
* the proxies have such a need. One (small) advantage is that internal
* usage does not requires to catch RemoteException.
*
* @see HARemoteInfoImpl
* @author <a href="mailto:[EMAIL PROTECTED]">Sacha Labourey</a>
* @version $Revision: 1.1 $
*
* <p><b>Revisions:</b>
*
* <p><b>20010819 Sacha Labourey:</b>
* <ul>
* <li> First import of sources
* </ul>
*/
public interface HARemoteInfo extends Remote
{
public HASmallConfigEntries getSmallConfigEntriesForApp (String appName)
throws RemoteException;
}
1.1 jbossmx/src/main/org/jboss/ha/HARemoteInfoImpl.java
Index: HARemoteInfoImpl.java
===================================================================
/*
* JBoss, the OpenSource J2EE WebOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ha;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* External view of the HA service i.e. only
* operations that need to be used from the outside. For now, only
* the proxies have such a need. One (small) advantage is that internal
* usage does not requires to catch RemoteException.
*
* @see HARemoteInfo
* @author <a href="mailto:[EMAIL PROTECTED]">Sacha Labourey</a>
* @version $Revision: 1.1 $
*
* <p><b>Revisions:</b>
*
* <p><b>20010819 Sacha Labourey:</b>
* <ul>
* <li> First import of sources
* </ul>
*/
public class HARemoteInfoImpl extends UnicastRemoteObject implements HARemoteInfo
{
/** Creates new HARemoteInfoImpl */
public HARemoteInfoImpl () throws java.rmi.RemoteException
{
super ();
}
public HARemoteInfoImpl (HAConfigNode master) throws java.rmi.RemoteException
{
super ();
this.master = master;
}
public HASmallConfigEntries getSmallConfigEntriesForApp (String appName) throws
RemoteException
{
return master.getSmallConfigEntriesForApp (appName);
}
protected HAConfigNode master = null;
}
1.1 jbossmx/src/main/org/jboss/ha/HASmallConfigEntries.java
Index: HASmallConfigEntries.java
===================================================================
/*
* JBoss, the OpenSource J2EE WebOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ha;
import org.jboss.ejb.plugins.jrmp.interfaces.ContainerRemote;
import java.util.Hashtable;
/**
* Efficiencly transmit HA information with the proxy
*
* @see
* @author <a href="mailto:[EMAIL PROTECTED]">Sacha Labourey</a>
* @version $Revision: 1.1 $
*
* <p><b>Revisions:</b>
*
* <p><b>20010819 Sacha Labourey:</b>
* <ul>
* <li> First import of sources
* </ul>
*/
public class HASmallConfigEntries extends java.lang.Object implements
java.io.Serializable
{
public ContainerRemote[] containers = null;
public Hashtable[] jndiProps = null;
public long delayForRefresh = 30000; // 30 sec.
public long delayForResynchAfterDeath = 5000; // 5 seconds
/** Creates new HASmallConfigEntries */
public HASmallConfigEntries ()
{}
public int size ()
{
return ( (jndiProps==null)? 0 : jndiProps.length );
}
public ContainerRemote[] getContainers ()
{ return containers; }
public Hashtable[] getJndiProps ()
{ return jndiProps; }
}
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development