[jboss-cvs] JBossAS SVN: r67692 - in projects/cluster/ha-server-api/trunk: src and 8 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sat Dec 1 10:39:45 EST 2007


Author: bstansberry at jboss.com
Date: 2007-12-01 10:39:45 -0500 (Sat, 01 Dec 2007)
New Revision: 67692

Added:
   projects/cluster/ha-server-api/trunk/src/
   projects/cluster/ha-server-api/trunk/src/main/
   projects/cluster/ha-server-api/trunk/src/main/java/
   projects/cluster/ha-server-api/trunk/src/main/java/org/
   projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/
   projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/
   projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/
   projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/
   projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/ClusterNode.java
   projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/DistributedReplicantManager.java
   projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/DistributedState.java
   projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/HAPartition.java
   projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/server/
   projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/server/HATarget.java
Log:
Create cluster/ha-server-api subproject

Copied: projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/ClusterNode.java (from rev 67689, trunk/cluster/src/main/org/jboss/ha/framework/interfaces/ClusterNode.java)
===================================================================
--- projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/ClusterNode.java	                        (rev 0)
+++ projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/ClusterNode.java	2007-12-01 15:39:45 UTC (rev 67692)
@@ -0,0 +1,43 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.ha.framework.interfaces;
+
+import java.net.InetAddress;
+import java.io.Serializable;
+
+/**
+ * Abstract identifier for a member of an @{link HAPartition}.
+ *
+ * @author  Brian Stansberry
+ * @version $Revision$
+ */
+public interface ClusterNode
+   extends Comparable, Cloneable, Serializable
+{
+   String getName();
+
+   String getJGName();
+
+   InetAddress getIpAddress();
+   
+   int getPort();
+}

Copied: projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/DistributedReplicantManager.java (from rev 67689, trunk/cluster/src/main/org/jboss/ha/framework/interfaces/DistributedReplicantManager.java)
===================================================================
--- projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/DistributedReplicantManager.java	                        (rev 0)
+++ projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/DistributedReplicantManager.java	2007-12-01 15:39:45 UTC (rev 67692)
@@ -0,0 +1,147 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.ha.framework.interfaces;
+
+import org.jboss.ha.framework.interfaces.DistributedReplicantManager.ReplicantListener;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Collection;
+
+/** 
+ *
+ * DistributedReplicantManager is a service on top of HAPartition that provides a
+ * cluster-wide distributed state which is node-specific. The DistributedReplicantManager (DRM) 
+ * service provides a <String key, Serializable replicant> tuple map.  Each node in the cluster
+ * stores its own data for a given key.  This data is replicated so that reading values for a key
+ * is always performed locally.  
+ * 
+ *   @author  <a href="mailto:bill at burkecentral.com">Bill Burke</a>.
+ *   @author  <a href="mailto:sacha.labourey at cogito-info.ch">Sacha Labourey</a>.
+ *   @version $Revision$
+ *
+ * <p><b>Revisions:</b><br>
+ * <p><b>2001/10/31: marcf</b>
+ * <ol>
+ *   <li>DRM is no longer remote
+ * </ol>
+ * <p><b>2002/08/23: Sacha Labourey</b>
+ * <ol>
+ *   <li>added isMasterReplica
+ * </ol>
+ */
+public interface DistributedReplicantManager
+{
+   /**
+    * When a particular key in the DistributedReplicantManager table gets modified, all listeners
+    * will be notified of replicant changes for that key.
+    */
+   public interface ReplicantListener
+   {
+      /**
+       * Callback called when the content/list of replicant for a given replicant key has changed
+       * @param key The name of the key of the replicant that has changed
+       * @param newReplicants The list of new replicants for the give replicant key.
+       *                      This list will be in a consistent order on all
+       *                      cluster nodes on which the current viewId is
+       *                      in effect
+       * @param newReplicantsViewId The new replicant view id corresponding to this change
+       */      
+      public void replicantsChanged(String key, List newReplicants, int newReplicantsViewId);
+   }
+
+   /**
+    * Subscribe a new listener {@link ReplicantListener} for replicant changes
+    * @param key Name of the replicant, must be identical cluster-wide for all identical replicants
+    * @param subscriber The subscribing {@link ReplicantListener}
+    */   
+   public void registerListener(String key, ReplicantListener subscriber);
+   /**
+    * Unsubscribe a listener {@link ReplicantListener} that had subscribed for replicant changes
+    * @param key Name of the replicant, must be identical cluster-wide for all identical replicants
+    * @param subscriber The unsubscribing {@link ReplicantListener}
+    */   
+   public void unregisterListener(String key, ReplicantListener subscriber);
+
+   // State binding methods
+   //
+
+   /**
+    * Add a replicant, it will be attached to this cluster node
+    * @param key Replicant name. All replicas around the cluster must use the same key name.
+    * @param replicant Local data of the replicant, that is, any serializable data
+    * @throws Exception Thrown if a cluster communication problem occurs
+    */
+   public void add(String key, Serializable replicant) throws Exception;
+
+   /**
+    * Remove the entire key from the ReplicationService
+    * @param key Name of the replicant
+    * @throws Exception Thrown if a cluster communication problem occurs
+    */
+   public void remove(String key) throws Exception;
+
+   /**
+    * Lookup the replicant attached to this cluster node
+    * @param key The name of the replicant
+    * @return The local replicant for the given key name
+    */   
+   public Serializable lookupLocalReplicant(String key);
+
+   /**
+    * Return a list of all replicants.
+    * @param key The replicant name
+    * @return A list of serialized replicants available around the cluster 
+    *         for the given key. This list will be in the same order in all 
+    *         nodes in the cluster.
+    */
+   public List lookupReplicants(String key);
+
+   /**
+    * Return a list of all replicants node names.
+    * @param key The replicant name
+    * @return A list of the node names of cluster nodes that have made available
+    *         a replicant for the given key. This list will be in the same 
+    *         order in all nodes in the cluster.
+    */
+   public List lookupReplicantsNodeNames(String key);
+
+   /**
+    * Return a list of all services that have at least one replicant.
+    * @return A collection of service names (String)
+    */
+   public Collection getAllServices ();
+
+   /**
+    * Returns an id corresponding to the current view of this set of replicants.
+    * @param key The replicant name
+    * @return A view id (doesn't grow sequentially)
+    */
+   public int getReplicantsViewId(String key);
+   
+   /**
+    * Indicates if the current node is the master replica for this given key.
+    * @param key The replicant name
+    * @return True if this node is the master
+    */
+   public boolean isMasterReplica (String key);
+
+}

Copied: projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/DistributedState.java (from rev 67689, trunk/cluster/src/main/org/jboss/ha/framework/interfaces/DistributedState.java)
===================================================================
--- projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/DistributedState.java	                        (rev 0)
+++ projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/DistributedState.java	2007-12-01 15:39:45 UTC (rev 67692)
@@ -0,0 +1,203 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.ha.framework.interfaces;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+/**
+ * DistributedState is a service on top of HAPartition that provides a
+ * cluster-wide distributed state. The DistributedState (DS) service
+ * provides a &lt;String category, Serializable key, Serializable value&gt; tuple
+ * map. Thus, any service, application, container, ... can request its own DS
+ * "private space" by working* in its own category (a string name).
+ * You work in a category like a Dictionary: you set values by key within a
+ * category. Each time a value is added/modified/removed, the modification
+ * is made cluster-wide, on all other nodes.
+ * Reading values is always made locally (no network access!)
+ * Objects can also subscribe to DS events to be notified when values are
+ * modified/removed/added in a particular category.
+ *
+ * @author <a href="mailto:sacha.labourey at cogito-info.ch">Sacha Labourey</a>.
+ * @author Scott.Stark at jboss.org
+ * @version $Revision$
+ * @see HAPartition
+ */
+public interface DistributedState
+{
+   /**
+    * When a particular key in a category of the DistributedState service gets
+    * modified, all listeners will be notified of DS changes for that category.
+    * @deprecated use the DSListenerEx instead
+    */
+   public interface DSListener
+   {
+      /**
+       * Called whenever a key has been added or modified in the category the called object
+       * has subscribed in.
+       * @param category The category of the modified/added entry
+       * @param key The key that has been added or had its value modified
+       * @param value The new value of the key
+       * @param locallyModified Whether the change was made from this node
+       */
+      public void valueHasChanged (String category, String key,
+         Serializable value, boolean locallyModified);
+      /**
+       * Called whenever a key has been removed from a category the called object had
+       * subscribed in.
+       * @param category The category under which a key has been removed
+       * @param key The key that has been removed
+       * @param previousContent The previous content of the key that has been removed
+       * @param locallyModified Whether the removal was made from this node
+       */
+      public void keyHasBeenRemoved (String category, String key,
+         Serializable previousContent, boolean locallyModified);
+   }
+
+   /** A generalization of the DSListener that supports the Serializable key
+    * type. When a particular key in a category of the DistributedState service
+    * gets modified, all listeners will be notified of DS changes for that
+    * category.
+    */
+   public interface DSListenerEx
+   {
+      /**
+       * Called whenever a key has been added or modified in the category the called object
+       * has subscribed in.
+       * @param category The category of the modified/added entry
+       * @param key The key that has been added or had its value modified
+       * @param value The new value of the key
+       * @param locallyModified Whether the change was made from this node
+       */
+      public void valueHasChanged (String category, Serializable key,
+         Serializable value, boolean locallyModified);
+      /**
+       * Called whenever a key has been removed from a category the called object had
+       * subscribed in.
+       * @param category The category under which a key has been removed
+       * @param key The key that has been removed
+       * @param previousContent The previous content of the key that has been removed
+       * @param locallyModified Whether the removal was made from this node
+       */
+      public void keyHasBeenRemoved (String category, Serializable key,
+         Serializable previousContent, boolean locallyModified);
+   }
+
+   /**
+    * Subscribes to receive {@link DistributedState.DSListenerEx} events
+    * @param category Name of the private-space to watch for
+    * @param subscriber Object that will receive callbacks.
+    */
+   public void registerDSListenerEx (String category, DSListenerEx subscriber);
+   /**
+    * Unsubscribes from {@link DistributedState.DSListenerEx} events
+    * @param category Name of the private-space dictionary currently observed
+    * @param subscriber Object currently observing this category
+    */
+   public void unregisterDSListenerEx (String category, DSListenerEx subscriber);
+
+   /**
+    * Subscribes to receive {@link DistributedState.DSListener} events
+    * @param category Name of the private-space to watch for
+    * @param subscriber Object that will receive callbacks.
+    */
+   public void registerDSListener (String category, DSListener subscriber);
+   /**
+    * Unsubscribes from {@link DistributedState.DSListener} events
+    * @param category Name of the private-space dictionary currently observed
+    * @param subscriber Object currently observing this category
+    */
+   public void unregisterDSListener (String category, DSListener subscriber);
+
+   // State binding methods
+   //
+   /**
+    * Associates a value to a key in a specific category
+    * @param category Name of the private naming-space
+    * @param key Name of the data to set
+    * @param value Value of the data to set
+    * @throws Exception If a network exception occurs
+    */
+   public void set (String category, Serializable key, Serializable value)
+      throws Exception;
+
+   /**
+    * Same as set(String, String) but caller can choose if the call is made
+    * synchronously or asynchronously. By default, calls are asynchronous.
+    * @param category Name of the private naming-space
+    * @param key Name of the data to set
+    * @param value Value of the data to set
+    * @param asynchronousCall True if the call should be asynchronous
+    * @throws Exception If a network exception occurs
+    */
+   public void set (String category, Serializable key, Serializable value,
+      boolean asynchronousCall) throws Exception;
+
+   /**
+    * Read in a value associated to a key in the given category. Read is performed locally.
+    * @param category Name of the private naming-space
+    * @param key The key of the value to read
+    * @return The value of the key in the given category
+    */
+   public Serializable get (String category, Serializable key);
+   
+   /**
+    * Return a list of all categories. Call managed locally: no network access.
+    * @return A collection of String representing the existing categories in the DS service.
+    */
+   public Collection getAllCategories ();
+   
+   /**
+    * Return a list of all keys in a category. Call managed locally: no network access.
+    * @param category The category under which to look for keys
+    * @return A collection of all keys in the give category
+    */
+   public Collection getAllKeys (String category);
+
+   /**
+    * Return a list of all values in a category. Call managed locally: no network access.
+    * @param category The category name under which to look for values
+    * @return A collection of all values in the give category
+    */
+   public Collection getAllValues (String category);
+
+   /**
+    * Remove the key from the ReplicationService in the given category
+    * @param category Name of the category
+    * @param key Key to be removed
+    * @return The value of the removed key
+    * @throws Exception if a network exception occurs while removing the entry.
+    */
+   public Serializable remove (String category, Serializable key) throws Exception;
+   
+   /**
+    * Same as remove(String, String) but caller can choose if the call is made
+    * synchronously or asynchronously. By default, calls are asynchronous.
+    * @param category Name of the category
+    * @param key Key to be removed
+    * @param asynchronousCall True if the call should be asynchronous
+    * @return The value of the removed key
+    * @throws Exception if a network exception occurs while removing the entry.
+    */
+   public Serializable remove (String category, Serializable key,
+      boolean asynchronousCall) throws Exception;
+}

Copied: projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/HAPartition.java (from rev 67689, trunk/cluster/src/main/org/jboss/ha/framework/interfaces/HAPartition.java)
===================================================================
--- projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/HAPartition.java	                        (rev 0)
+++ projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/interfaces/HAPartition.java	2007-12-01 15:39:45 UTC (rev 67692)
@@ -0,0 +1,360 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.ha.framework.interfaces;
+
+import java.io.Serializable;
+import java.util.Vector;
+import java.util.ArrayList;
+
+/** 
+ *   HAPartition is an abstraction of the communication framework, providing access
+ *   to clustered services such as Distributed State, Distributed Replicant Manager
+ *   and RPC.
+ *  
+ *   @author  <a href="mailto:bill at burkecentral.com">Bill Burke</a>.
+ *   @author  <a href="mailto:sacha.labourey at cogito-info.ch">Sacha Labourey</a>.
+ *   @version $Revision$
+ *
+ * <p><b>Revisions:</b><br>
+ * <p><b>28.07.2002 - Sacha Labourey:</b>
+ * <ul>
+ * <li> Added network-partition merge callback for listeners</li>
+ * </ul>
+ */
+
+public interface HAPartition
+{
+   // *******************************
+   // *******************************
+   // Partition information accessors
+   // *******************************
+   // *******************************
+   //
+   /**
+    * Return the name of this node in the current partition. The name is
+    * dynamically determined by the partition. The name will be the String
+    * returned by <code>getClusterNode().getName()</code>.
+    * 
+    * @return The node name
+    * 
+    * @see #getClusterNode()
+    */   
+   public String getNodeName();
+   /**
+    * The name of the partition. Either set when creating the partition
+    * (MBEAN definition) or uses the default name
+    * @return Name of the current partition
+    */   
+   public String getPartitionName();
+
+   /**
+    * Accessor to the DistributedReplicantManager (DRM) that is linked to this partition.
+    * @return the DistributedReplicantManager
+    */   
+   public DistributedReplicantManager getDistributedReplicantManager();
+   /**
+    * Accessor to the DistributedState (DS) that is linked to this partition.
+    * @return the DistributedState service
+    */   
+   public DistributedState getDistributedStateService ();
+
+   // ***************************
+   // ***************************
+   // RPC multicast communication
+   // ***************************
+   // ***************************
+   //
+   /**
+    * The partition receives RPC calls from other nodes in the cluster and demultiplexes
+    * them, according to a service name, to a particular service. Consequently, each
+    * service must first subscribe with a particular service name in the partition. The subscriber
+    * does not need to implement any specific interface: the call is handled
+    * dynamically through reflection.
+    * @param serviceName Name of the subscribing service (demultiplexing key)
+    * @param handler object to be called when receiving a RPC for its key.
+    */   
+   public void registerRPCHandler(String serviceName, Object handler);
+   
+   /**
+    * The partition receives RPC calls from other nodes in the cluster and demultiplexes
+    * them, according to a service name, to a particular service. Consequently, each
+    * service must first subscribe with a particular service name in the partition. The subscriber
+    * does not need to implement any specific interface: the call is handled
+    * dynamically through reflection.
+    * In cases where the client is using a scoped classloader, the client will need to provide a 
+    * reference to the classloader if the service's RPC calls use custom parameter or response object types. 
+    * @param serviceName Name of the subscribing service (demultiplexing key)
+    * @param handler object to be called when receiving a RPC for its key.
+    * @param classloader ClassLoader to be used when marshalling and unmarshalling RPC requests and responses.
+    */   
+   public void registerRPCHandler(String serviceName, Object handler, ClassLoader classloader);
+   
+   /**
+    * Unregister the service from the partition
+    * @param serviceName Name of the service key (on which the demultiplexing occurs)
+    * @param subscriber The target object that unsubscribes
+    */   
+   public void unregisterRPCHandler(String serviceName, Object subscriber);
+
+   // Called only on all members of this partition on all nodes
+   //
+   /**
+    * Invoke a synchronous RPC call on all nodes of the partition/cluster
+    * @param serviceName Name of the target service name on which calls are de-multiplexed
+    * @param methodName name of the Java method to be called on remote services
+    * @param args array of Java Object representing the set of parameters to be
+    * given to the remote method
+    * @param types The types of the parameters
+    * @param excludeSelf indicates if the RPC must also be made on the current
+    * node of the partition or only on remote nodes
+    * @throws Exception Throws if a communication exception occurs
+    * @return an array of responses from remote nodes
+    */
+   public ArrayList callMethodOnCluster(String serviceName, String methodName,
+         Object[] args, Class[] types, boolean excludeSelf) throws Exception;
+
+   /**
+    * Invoke a asynchronous RPC call on all nodes of the partition/cluster. The
+    * call will return immediately and will not wait for the nodes to answer. Thus
+    * no answer is available.
+    * @param serviceName Name of the target service name on which calls are de-multiplexed
+    * @param methodName name of the Java method to be called on remote services
+    * @param args array of Java Object representing the set of parameters to be
+    * given to the remote method
+    * @param types The types of the parameters
+    * @param excludeSelf indicates if the RPC must also be made on the current
+    * node of the partition or only on remote nodes
+    * @throws Exception Throws if a communication exception occurs
+    */   
+   public void callAsynchMethodOnCluster (String serviceName, String methodName,
+         Object[] args, Class[] types, boolean excludeSelf) throws Exception;
+
+   /**
+    * Calls method on Cluster coordinator node only.  The cluster coordinator node is the first node to join the
+    * cluster or the first node in the current cluster view.
+    * @param serviceName Name of the target service name on which calls are de-multiplexed
+    * @param methodName name of the Java method to be called on remote services
+    * @param args array of Java Object representing the set of parameters to be
+    * given to the remote method
+    * @param types The types of the parameters
+    * @param excludeSelf indicates if the RPC will be made on the current node even if the current node
+    * is the coordinator
+    * @throws Exception Throws if a communication exception occurs
+    * @return an array of responses from remote nodes
+    */
+   public ArrayList callMethodOnCoordinatorNode(String serviceName, String methodName,
+             Object[] args, Class[] types, boolean excludeSelf) throws Exception;
+
+    /**
+     * Calls method synchrounously on target node only.
+     * @param serviceName Name of the target service name on which calls are de-multiplexed
+     * @param methodName name of the Java method to be called on remote services
+     * @param args array of Java Object representing the set of parameters to be
+     * given to the remote method
+     * @param types The types of the parameters
+     * node of the partition or only on remote nodes
+     * @param targetNode is the target of the call
+     * @return the value returned by the target method
+     * @throws Exception Throws if a communication exception occurs
+     */
+   public Object callMethodOnNode(String serviceName, String methodName,
+           Object[] args, Class[] types, long methodTimeout, ClusterNode targetNode) throws Throwable;
+
+   /**
+     * Calls method on target node only.
+     * @param serviceName Name of the target service name on which calls are de-multiplexed
+     * @param methodName name of the Java method to be called on remote services
+     * @param args array of Java Object representing the set of parameters to be
+     * given to the remote method
+     * @param types The types of the parameters
+     * node of the partition or only on remote nodes
+     * @param targetNode is the target of the call
+     * @return none
+     * @throws Exception Throws if a communication exception occurs
+     */
+   public void callAsyncMethodOnNode(String serviceName, String methodName,
+           Object[] args, Class[] types, long methodTimeout, ClusterNode targetNode) throws Throwable;
+
+   // *************************
+   // *************************
+   // State transfer management
+   // *************************
+   // *************************
+   //
+   
+   /**
+    * State management is highly important for clustered services. Consequently, services that wish to manage their state
+    * need to subscribe to state transfer events. When a service is started on a cluster node, state is pushed from another node to the  
+    * new node.  When another node starts, the node may be asked to provide its state to initialise the newly started node.
+    */   
+   public interface HAPartitionStateTransfer
+   {
+      /**
+       * Called when a new node needs to be initialized. This is called on any existing node to determine a current state for this service.
+       * @return A serializable representation of the state
+       */      
+      public Serializable getCurrentState ();
+      /**
+       * This callback method is called when a new service starts on a new node; the state that it should hold is transfered to it through this callback.
+       * @param newState The serialized representation of the state of the new service.
+       */      
+      public void setCurrentState(Serializable newState);
+   }
+   
+   /**
+    * Register a service that will participate in state transfer protocol and receive callbacks
+    * @param serviceName Name of the service that subscribes for state transfer events. This name must be identical for all identical services in the cluster.
+    * @param subscriber Object implementing {@link HAPartitionStateTransfer} and providing or receiving state transfer callbacks
+    */   
+   public void subscribeToStateTransferEvents (String serviceName, HAPartition.HAPartitionStateTransfer subscriber);
+   /**
+    * Unregister a service from state transfer callbacks.
+    * @param serviceName Name of the service that participates in the state transfer protocol
+    * @param subscriber Service implementing the state transfer callback methods
+    */   
+   public void unsubscribeFromStateTransferEvents (String serviceName, HAPartition.HAPartitionStateTransfer subscriber);
+
+   // *************************
+   // *************************
+   // Group Membership listeners
+   // *************************
+   // *************************
+   //
+   /**
+    * When a new node joins the cluster or an existing node leaves the cluster
+    * (or simply dies), membership events are raised.
+    *
+    */   
+   public interface HAMembershipListener
+   {
+      /** Called when a new partition topology occurs. This callback is made
+       * using the JG protocol handler thread and so you cannot execute new
+       * cluster calls that need this thread. If you need to do that implement
+       * the asynchronous version of the listener interface.
+       *
+       * @param deadMembers A list of nodes that have died since the previous view
+       * @param newMembers A list of nodes that have joined the partition since the previous view
+       * @param allMembers A list of nodes that built the current view
+       */      
+      public void membershipChanged(Vector deadMembers, Vector newMembers, Vector allMembers);
+   }
+
+   /** A tagging interface for HAMembershipListener callbacks that will
+    * be performed in a thread separate from the JG protocol handler thread.
+    * The ordering of view changes is preserved, but listeners are free to
+    * execute cluster calls.
+    */
+   public interface AsynchHAMembershipListener extends HAMembershipListener
+   {
+      // Nothing new
+   }
+   
+   /** Extends HAMembershipListener to receive notification when a network-partition merge occurs.
+    */
+   public interface HAMembershipExtendedListener extends HAPartition.HAMembershipListener
+   {
+      /** Extends HAMembershipListener to receive a specific callback when a
+       * network-partition merge occurs. The same restriction on interaction
+       * with the JG protocol stack applies.
+       *
+       * @param deadMembers A list of nodes that have died since the previous view
+       * @param newMembers A list of nodes that have joined the partition since the previous view
+       * @param allMembers A list of nodes that built the current view
+       * @param originatingGroups A list of nodes that were previously partioned and that are now merged
+       */      
+      public void membershipChangedDuringMerge(Vector deadMembers, Vector newMembers,
+            Vector allMembers, Vector originatingGroups);
+   }
+
+   /** A tagging interface for HAMembershipExtendedListener callbacks that will
+    * be performed in a thread separate from the JG protocol handler thread.
+    * The ordering of view changes is preserved, but listeners are free to
+    * execute cluster calls.
+    */
+   public interface AsynchHAMembershipExtendedListener extends HAMembershipExtendedListener
+   {
+      // Nothing new
+   }
+
+   /**
+    * Subscribes to receive {@link HAMembershipListener} events.
+    * @param listener The membership listener object
+    */   
+   public void registerMembershipListener(HAMembershipListener listener);
+   /**
+    * Unsubscribes from receiving {@link HAMembershipListener} events.
+    * @param listener The listener wishing to unsubscribe
+    */   
+   public void unregisterMembershipListener(HAMembershipListener listener);
+   /**
+    * Returns whether this partition will synchronously notify any 
+    * HAMembershipListeners of membership changes using the calling thread
+    * from the underlying <code>ClusterPartition</code>.
+    * 
+    * @return <code>true</code> if registered listeners that don't implement
+    *         <code>AsynchHAMembershipExtendedListener</code> or
+    *         <code>AsynchHAMembershipListener</code> will be notified
+    *         synchronously of membership changes; <code>false</code> if
+    *         those listeners will be notified asynchronously.  Default
+    *         is <code>false</code>.
+    */
+   public boolean getAllowSynchronousMembershipNotifications();
+   /**
+    * Sets whether this partition will synchronously notify any 
+    * HAMembershipListeners of membership changes using the calling thread
+    * from the underlying <code>ClusterPartition</code>.
+    * 
+    * @param allowSync  <code>true</code> if registered listeners that don't 
+    *         implement <code>AsynchHAMembershipExtendedListener</code> or
+    *         <code>AsynchHAMembershipListener</code> should be notified
+    *         synchronously of membership changes; <code>false</code> if
+    *         those listeners can be notified asynchronously.  Default
+    *         is <code>false</code>.
+    */
+   public void setAllowSynchronousMembershipNotifications(boolean allowSync);
+
+   /**
+    * Each time the partition topology changes, a new view is computed. A view is a list of members,
+    * the first member being the coordinator of the view. Each view also has a distinct identifier.
+    * @return The identifier of the current view
+    */   
+   public long getCurrentViewId();
+   /**
+    * Return the list of member nodes that built the current view i.e., the current partition.
+    * @return An array of Strings containing the node names
+    */   
+   public Vector getCurrentView ();
+
+   /**
+    * Return the member nodes that built the current view i.e., the current partition.
+    * @return   An array of ClusterNode listing the current members of the partition.
+    *           This array will be in the same order in all nodes in the cluster that
+    *           have received the current view.
+    */
+   public ClusterNode[] getClusterNodes ();
+
+   /**
+    * Return member node for the current cluster node.
+    * @return ClusterNode containing the current node name
+    */
+   public ClusterNode getClusterNode ();
+}
\ No newline at end of file

Copied: projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/server/HATarget.java (from rev 67689, trunk/cluster/src/main/org/jboss/ha/framework/server/HATarget.java)
===================================================================
--- projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/server/HATarget.java	                        (rev 0)
+++ projects/cluster/ha-server-api/trunk/src/main/java/org/jboss/ha/framework/server/HATarget.java	2007-12-01 15:39:45 UTC (rev 67692)
@@ -0,0 +1,251 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.ha.framework.server;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import org.jboss.ha.framework.interfaces.DistributedReplicantManager;
+import org.jboss.ha.framework.interfaces.DistributedReplicantManager.ReplicantListener;
+import org.jboss.ha.framework.interfaces.HAPartition;
+import org.jboss.logging.Logger;
+import java.io.Serializable;
+
+/** 
+ * This class is a holder and manager of replicants.
+ * It manages lists of replicated objects and changes the list as the HAPartition
+ * notifies it.
+ *
+ * @author bill at burkecentral.com
+ * @version $Revision$
+ *
+ * <p><b>Revisions:</b><br>
+ * <p><b>2002/01/13: Bill Burke</b>
+ * <ol>
+ *   <li>Initial revision
+ * </ol>
+ */
+public class HATarget
+   implements ReplicantListener
+{
+   public static final int DISABLE_INVOCATIONS = 0;
+   public static final int MAKE_INVOCATIONS_WAIT = 1;
+   public static final int ENABLE_INVOCATIONS = 2;
+   
+   protected String replicantName;
+   protected ArrayList replicants = new ArrayList();
+   protected HAPartition partition = null;
+   protected Logger log;
+   protected int clusterViewId = 0;
+   protected Serializable target;
+   protected int allowInvocationsStatus = 0;
+   protected CountDownLatch latch = null;
+   
+   public HATarget(HAPartition partition, 
+		   String replicantName,
+		   Serializable target,
+         int allowInvocations) 
+      throws Exception
+   {
+      this.replicantName = replicantName;      
+      this.target = target;      
+      init ();
+      setInvocationsAuthorization (allowInvocations);
+      updateHAPartition(partition);
+   }
+   
+   public void init() throws Exception
+   {
+      this.log = Logger.getLogger(this.getClass());
+   }
+
+   public String toString()
+   {
+      StringBuffer buffer = new StringBuffer(super.toString());
+      buffer.append('{');
+      buffer.append("replicantName="+replicantName);
+      buffer.append("partition="+partition.getPartitionName());
+      buffer.append("clusterViewId="+clusterViewId);
+      buffer.append("allowInvocationsStatus="+allowInvocationsStatus);
+      buffer.append("replicants="+replicants);
+      buffer.append('}');
+      return buffer.toString();
+   }
+
+   public long getCurrentViewId()
+   {
+      return (long)clusterViewId;
+   }
+   
+   public void destroy()
+   {
+      try
+      {
+         this.cleanExistenceInCurrentHAPartition();
+         
+         // maybe some threads are blocked: we let them go here:
+         //
+         setInvocationsAuthorization (HATarget.DISABLE_INVOCATIONS);
+      } 
+      catch (Exception e)
+      {
+         log.error("failed to destroy", e);
+      }
+   }
+ 
+   // After this call, the HATarget can still be queried for view change, etc. but
+   // the local node is no more part of the cluster: temporary state
+   //
+   public void disable()
+   {
+      try
+      {
+         if (this.partition != null)
+         {
+            log.debug ("Disabled called on HATarget");
+            this.partition.getDistributedReplicantManager().remove (this.replicantName);         
+         }      
+      } 
+      catch (Exception e)
+      {
+         log.error("failed to disable", e);
+      }
+   }
+   
+   public ArrayList getReplicants()
+   {
+      return replicants;
+   }
+   
+   public void updateHAPartition(HAPartition partition) throws Exception
+   {
+      cleanExistenceInCurrentHAPartition();
+      
+      this.partition = partition;
+      DistributedReplicantManager drm = partition.getDistributedReplicantManager();
+      drm.registerListener(this.replicantName, this);
+      drm.add(this.replicantName, this.target);
+   }
+
+   public synchronized void setInvocationsAuthorization (int status)
+   {
+      if (this.allowInvocationsStatus == status)
+      {
+         // we don't release and reget a latch if two identical calls are performed
+         //
+         log.debug ("Invocation authorization called with no-op");
+      }
+      else
+      {
+         // CRITICAL CODE! DONT CHANGE ORDER WITHOUT THINKING ABOUT RACE CONDITIONS
+         //
+         if (status == MAKE_INVOCATIONS_WAIT)
+         {
+            log.debug ("Invocation authorization called: MAKE_INVOCATIONS_WAIT");
+            latch = new CountDownLatch(1);
+            this.allowInvocationsStatus = status;
+         } 
+         else
+         {
+            log.debug ("Invocation authorization called: " +
+               ((status==ENABLE_INVOCATIONS)?"ENABLE_INVOCATIONS":"DISABLE_INVOCATIONS") );
+            this.allowInvocationsStatus = status;
+            releaseCurrentLatch();
+         }         
+      }
+   }
+   
+   public boolean invocationsAllowed () throws InterruptedException
+   {
+      if (this.allowInvocationsStatus == ENABLE_INVOCATIONS)
+         return true;
+      else if (this.allowInvocationsStatus == DISABLE_INVOCATIONS)
+         return false;
+      else if (this.allowInvocationsStatus == MAKE_INVOCATIONS_WAIT)
+      {
+         latch.await();
+         
+         // if we arrive here, it means that the status has been changed, so
+         // we check for the decision:
+         //
+         if (this.allowInvocationsStatus == ENABLE_INVOCATIONS)
+            return true;
+         else
+            return false;         
+      }    
+      else
+         return false;
+   }
+   
+   protected void releaseCurrentLatch ()
+   {
+      if (latch != null)
+      {
+         latch.countDown();
+         latch = null;
+      }
+   }
+   
+   public HAPartition getAssociatedPartition ()
+   {
+       return this.partition;
+   }
+   
+   // DistributedReplicantManager.ReplicantListener implementation ------------
+      
+   public void replicantsChanged(String key, List newReplicants, int newReplicantsViewId)
+   {
+      if (log.isDebugEnabled())
+         log.debug("replicantsChanged '" + replicantName + 
+                   "' to " + (newReplicants==null? "0 (null)" : Integer.toString (newReplicants.size() ) ) + 
+                   " (intra-view id: " + newReplicantsViewId + ")");
+      
+      synchronized(replicants)
+      {
+         // client has reference to replicants so it will automatically get
+         // updated
+         replicants.clear();
+         if (newReplicants != null)
+            replicants.addAll(newReplicants);
+         
+         this.clusterViewId = newReplicantsViewId;
+      }
+      
+   }
+   
+   protected void cleanExistenceInCurrentHAPartition()
+   {
+      if (this.partition != null)
+      {
+         try
+         {
+            DistributedReplicantManager drm = partition.getDistributedReplicantManager();
+            drm.unregisterListener(this.replicantName, this);
+            drm.remove(this.replicantName);         
+         } 
+         catch (Exception e)
+         {
+            log.error("failed to clean existence in current ha partition", e);
+         }
+      }    
+   }
+}




More information about the jboss-cvs-commits mailing list