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

Reply via email to