FileDocCategorySizeDatePackage
ClusterPartition.javaAPI DocJBoss 4.2.118872Fri Jul 13 20:52:38 BST 2007org.jboss.ha.framework.server

ClusterPartition

public class ClusterPartition extends org.jboss.system.ServiceMBeanSupport implements ClusterPartitionMBean
Management Bean for Cluster HAPartitions. It will start a JGroups channel and initialize the ReplicantManager and DistributedStateService.
author
Bill Burke.
author
Sacha Labourey.
version
$Revision: 62947 $

Fields Summary
public static final String
JGROUPS_JMX_DOMAIN
public static final String
CHANNEL_JMX_ATTRIBUTES
public static final String
PROTOCOL_JMX_ATTRIBUTES
protected String
partitionName
protected String
jgProps
protected HAPartitionImpl
partition
protected boolean
deadlock_detection
protected boolean
allow_sync_events
protected org.jgroups.jmx.JChannelFactoryMBean
multiplexer
protected String
stackName
protected org.jgroups.JChannel
channel
protected org.jgroups.debug.Debugger
debugger
protected boolean
use_debugger
protected String
nodeName
protected InetAddress
nodeAddress
protected long
state_transfer_timeout
Number of milliseconds to wait until state has been transferred. Increase this value for large states 0 = wait forever
protected long
method_call_timeout
protected boolean
channelRegistered
protected boolean
protocolsRegistered
Constructors Summary
Methods Summary
protected HAPartitionImplcreatePartition()
Extension point meant for test cases; instantiates the HAPartitionImpl. Test cases can instantiate their own subclass of HAPartitionImpl.

      HAPartitionImpl result = new HAPartitionImpl(partitionName, channel, deadlock_detection, getServer());
      result.setStateTransferTimeout(this.state_transfer_timeout);
      result.setMethodCallTimeout(this.method_call_timeout);
      return result;
   
protected voidcreateService()

      log.debug("Creating JGroups JChannel");

      if (stackName != null && multiplexer != null)
      {
         this.channel = (JChannel) multiplexer.createMultiplexerChannel(stackName, getPartitionName());
      }
      else
      {
         this.channel = new org.jgroups.JChannel(jgProps);
         // JBAS-4406 Hack to register the channel
         registerChannelInJmx();
      }
      
      if(use_debugger && debugger == null)
      {
         debugger=new Debugger(channel);
         debugger.start();
      }
      channel.setOpt(Channel.AUTO_RECONNECT, Boolean.TRUE);
      channel.setOpt(Channel.AUTO_GETSTATE, Boolean.TRUE);
      
      log.debug("Creating HAPartition");
      partition = createPartition();
      
      // JBAS-2769 Init partition in create
      log.debug("Initing HAPartition: " + partition);
      partition.init();
      log.debug("HAPartition initialized");
      
   
protected voiddestroyService()

      log.debug("Destroying ClusterPartition: " + partitionName);
      partition.destroyPartition();
      // JBAS-4406 Hack
      unregisterChannelFromJmx();
      log.debug("Destroyed ClusterPartition: " + partitionName);
   
protected java.lang.StringgenerateUniqueNodeName()

      // we first try to find a simple meaningful name:
      // 1st) "local-IP:JNDI_PORT" if JNDI is running on this machine
      // 2nd) "local-IP:JMV_GUID" otherwise
      // 3rd) return a fully GUID-based representation
      //

      // Before anything we determine the local host IP (and NOT name as this could be
      // resolved differently by other nodes...)

      // But use the specified node address for multi-homing

      String hostIP = null;
      InetAddress address = ServerConfigUtil.fixRemoteAddress(nodeAddress);
      if (address == null)
      {
         log.debug ("unable to create a GUID for this cluster, check network configuration is correctly setup (getLocalHost has returned an exception)");
         log.debug ("using a full GUID strategy");
         return new VMID().toString();
      }
      else
      {
         hostIP = address.getHostAddress();
      }

      // 1st: is JNDI up and running?
      //
      try
      {
         AttributeList al = this.server.getAttributes(NamingServiceMBean.OBJECT_NAME,
                                      new String[] {"State", "Port"});

         int status = ((Integer)((Attribute)al.get(0)).getValue()).intValue();
         if (status == ServiceMBean.STARTED)
         {
            // we can proceed with the JNDI trick!
            int port = ((Integer)((Attribute)al.get(1)).getValue()).intValue();
            return hostIP + ":" + port;
         }
         else
         {
            log.debug("JNDI has been found but the service wasn't started so we cannot " +
                      "be entirely sure we are the only one that wants to use this PORT " +
                      "as a GUID on this host.");
         }

      }
      catch (InstanceNotFoundException e)
      {
         log.debug ("JNDI not running here, cannot use this strategy to find a node GUID for the cluster");
      }
      catch (ReflectionException e)
      {
         log.debug ("JNDI querying has returned an exception, cannot use this strategy to find a node GUID for the cluster");
      }

      // 2nd: host-GUID strategy
      //
      String uid = new UID().toString();
      return hostIP + ":" + uid;
   
public booleangetAllowSynchronousMembershipNotifications()

      return allow_sync_events;
   
public java.util.VectorgetCurrentView()
Return the list of member nodes that built from the current view

return
A Vector Strings representing the host:port values of the nodes

      return partition.getCurrentView();
   
public booleangetDeadlockDetection()

      return deadlock_detection;
   
public org.jboss.ha.framework.interfaces.HAPartitiongetHAPartition()

      return this.partition;      
   
public java.lang.StringgetJGroupsVersion()

      return Version.version + "( " + Version.cvs + ")";
   
public longgetMethodCallTimeout()

      return method_call_timeout;
   
public org.jgroups.jmx.JChannelFactoryMBeangetMultiplexer()

      return multiplexer;
   
public java.lang.StringgetMultiplexerStack()

      return stackName;
   
public java.lang.StringgetName()

      return partitionName;
   
public java.net.InetAddressgetNodeAddress()

      return nodeAddress;
   
public java.lang.StringgetNodeName()
Uniquely identifies this node. MUST be unique accros the whole cluster! Cannot be changed once the partition has been started

      return this.nodeName;
   
protected javax.management.ObjectNamegetObjectName(javax.management.MBeanServer server, javax.management.ObjectName name)

      return name == null ? OBJECT_NAME : name;
   
public java.lang.StringgetPartitionName()


   // Static --------------------------------------------------------
   
   // Constructors --------------------------------------------------
   
   // Public --------------------------------------------------------
   
   // ClusterPartitionMBean implementation ----------------------------------------------
   
     
   
      return partitionName;
   
public java.lang.StringgetPartitionProperties()

      // The channel knows best
      if (channel != null)
         return channel.getProperties();
      
      if (multiplexer == null && stackName == null)
         return jgProps;
      
      // We are configured for the multiplexer but don't know
      // the details of the stack yet
      return null;
   
public longgetStateTransferTimeout()

      return state_transfer_timeout;
   
protected voidregisterChannelInJmx()

      if (server != null)
      {
         try
         {
            String protocolPrefix = JGROUPS_JMX_DOMAIN + ":" + PROTOCOL_JMX_ATTRIBUTES + getPartitionName();
            JmxConfigurator.registerProtocols(server, channel, protocolPrefix);
            protocolsRegistered = true;
            
            String name = JGROUPS_JMX_DOMAIN + ":" + CHANNEL_JMX_ATTRIBUTES + getPartitionName();
            JmxConfigurator.registerChannel(channel, server, name);
            channelRegistered = true;
         }
         catch (Exception e)
         {
            log.error("Caught exception registering channel in JXM", e);
         }
      }
   
public voidsetAllowSynchronousMembershipNotifications(boolean allowSync)

      this.allow_sync_events = allowSync;
   
public voidsetDeadlockDetection(boolean doit)

      deadlock_detection = doit;
   
public voidsetMethodCallTimeout(long timeout)

      this.method_call_timeout=timeout;
   
public voidsetMultiplexer(org.jgroups.jmx.JChannelFactoryMBean muxFactory)

      this.multiplexer = muxFactory;
   
public voidsetMultiplexerStack(java.lang.String stackName)

      this.stackName = stackName;
   
public voidsetNodeAddress(java.net.InetAddress address)

      this.nodeAddress = address;
   
public voidsetNodeName(java.lang.String node)

      if (this.getState() == ServiceMBean.CREATED ||
          this.getState() == ServiceMBean.STARTED ||
          this.getState() == ServiceMBean.STARTING)
      {
         throw new Exception ("Node name cannot be changed once the partition has been started");
      }
      else
      {
         this.nodeName = node;
      }
   
public voidsetPartitionConfig(org.w3c.dom.Element config)
Convert a list of elements to the JG property string

      StringBuffer buffer = new StringBuffer();
      NodeList stack = config.getChildNodes();
      int length = stack.getLength();
      for(int s = 0; s < length; s ++)
      {
         Node node = stack.item(s);
         if( node.getNodeType() != Node.ELEMENT_NODE )
            continue;

         Element tag = (Element) node;
         String protocol = tag.getTagName();
         buffer.append(protocol);
         NamedNodeMap attrs = tag.getAttributes();
         int attrLength = attrs.getLength();
         if( attrLength > 0 )
            buffer.append('(");
         for(int a = 0; a < attrLength; a ++)
         {
            Attr attr = (Attr) attrs.item(a);
            String name = attr.getName();
            String value = attr.getValue();
            buffer.append(name);
            buffer.append('=");
            buffer.append(value);
            if( a < attrLength-1 )
               buffer.append(';");
         }
         if( attrLength > 0 )
            buffer.append(')");
         buffer.append(':");
      }
      // Remove the trailing ':'
      buffer.setLength(buffer.length()-1);
      this.jgProps = buffer.toString();
      log.debug("Setting JGProps from xml to: "+jgProps);
   
public voidsetPartitionName(java.lang.String newName)

      partitionName = newName;
   
public voidsetPartitionProperties(java.lang.String newProps)

      jgProps = newProps;
   
public voidsetStateTransferTimeout(long timeout)

      this.state_transfer_timeout=timeout;
   
public java.lang.StringshowHistory()

      StringBuffer buff = new StringBuffer();
      Vector data = new Vector (this.partition.history);
      for (java.util.Iterator row = data.iterator(); row.hasNext();)
      {
         String info = (String) row.next();
         buff.append(info).append("\n");
      }
      return buff.toString();
   
public java.lang.StringshowHistoryAsXML()

      StringBuffer buff = new StringBuffer();
      buff.append("<events>\n");
      Vector data = new Vector (this.partition.history);
      for (java.util.Iterator row = data.iterator(); row.hasNext();)
      {
         buff.append("   <event>\n      ");
         String info = (String) row.next();
         buff.append(info);
         buff.append("\n   </event>\n");
      }
      buff.append("</events>\n");
      return buff.toString();
   
public voidstartChannelDebugger()

      startChannelDebugger(false);
   
public voidstartChannelDebugger(boolean accumulative)

      if(debugger == null)
      {
         debugger=new Debugger(this.channel, accumulative);
         debugger.start();
      }
   
protected voidstartService()

      // We push the independant name in the protocol stack
      // before it is connected to the cluster
      //
      if (this.nodeName == null || "".equals(this.nodeName))
         this.nodeName = generateUniqueNodeName ();

      java.util.HashMap staticNodeName = new java.util.HashMap();
      staticNodeName.put("additional_data", this.nodeName.getBytes());
      
      // JBAS-4258 -- invoke via reflection to allow upgrade to JGroups 2.5
      Class[] paramTypes = new Class[]{org.jgroups.Event.class};
      Method downMethod = JChannel.class.getDeclaredMethod("down", paramTypes);
      Object[] params = { new org.jgroups.Event(org.jgroups.Event.CONFIG, staticNodeName) };
      downMethod.invoke(channel, params);

      this.channel.getProtocolStack().flushEvents(); // temporary fix for JG bug (808170) TODO: REMOVE ONCE JGROUPS IS FIXED

      log.debug("Starting ClusterPartition: " + partitionName);
      channel.connect(partitionName);
      
      try
      {
         log.debug("Starting channel");
         partition.startPartition();

         log.debug("Started ClusterPartition: " + partitionName);         
      }
      catch (Exception e)
      {
         log.debug("Caught exception after channel connected; closing channel -- " + e.getLocalizedMessage());
         channel.disconnect();
         throw e;
      }
   
public voidstopChannelDebugger()

      if(debugger != null)
      {
         // debugger.stop(); // uncomment when new JGroups version is available
         debugger=null;
      }
   
protected voidstopService()

      stopChannelDebugger();
      log.debug("Stopping ClusterPartition: " + partitionName);
      partition.closePartition();
      log.debug("Stopped ClusterPartition: " + partitionName);
   
protected voidunregisterChannelFromJmx()

      ObjectName on = null;
      if (channelRegistered)
      {          
         // Unregister the channel itself
         try
         {
            on = new ObjectName(JGROUPS_JMX_DOMAIN + ":" + CHANNEL_JMX_ATTRIBUTES + getPartitionName());
            server.unregisterMBean(on);
         }
         catch (Exception e)
         {
            if (on != null)
               log.error("Caught exception unregistering channel at " + on, e);
            else
               log.error("Caught exception unregistering channel", e);
         }
      }
      
      if (protocolsRegistered)
      {
         // Unregister the protocols
         try
         {
            on = new ObjectName(JGROUPS_JMX_DOMAIN + ":*," + PROTOCOL_JMX_ATTRIBUTES + getPartitionName());
            Set mbeans=server.queryNames(on, null);
            if(mbeans != null) {
                for(Iterator it=mbeans.iterator(); it.hasNext();) {
                    server.unregisterMBean((ObjectName)it.next());
                }
            }
         }
         catch (Exception e)
         {
            if (on != null)
               log.error("Caught exception unregistering protocols at " + on, e);
            else
               log.error("Caught exception unregistering protocols", e);
         }
      }