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