Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » cluster » mcast » [javadoc | source]
    1   /*
    2    * Copyright 1999,2004-2005 The Apache Software Foundation.
    3    * 
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    * 
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    * 
   10    * Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   
   17   package org.apache.catalina.cluster.mcast;
   18   
   19   import java.util.Properties;
   20   
   21   import javax.management.MBeanServer;
   22   import javax.management.ObjectName;
   23   
   24   import org.apache.catalina.Cluster;
   25   import org.apache.catalina.Container;
   26   import org.apache.catalina.cluster.Member;
   27   import org.apache.catalina.cluster.MembershipListener;
   28   import org.apache.catalina.cluster.MembershipService;
   29   import org.apache.catalina.cluster.tcp.SimpleTcpCluster;
   30   import org.apache.catalina.core.StandardHost;
   31   import org.apache.catalina.util.StringManager;
   32   import org.apache.commons.modeler.Registry;
   33   
   34   /**
   35    * A <b>membership</b> implementation using simple multicast.
   36    * This is the representation of a multicast membership service.
   37    * This class is responsible for maintaining a list of active cluster nodes in the cluster.
   38    * If a node fails to send out a heartbeat, the node will be dismissed.
   39    *
   40    * FIXME i18n messages
   41    * 
   42    * @author Peter Rossbach
   43    * @author Filip Hanik
   44    * @version $Revision: 304032 $, $Date: 2005-07-27 11:11:55 -0400 (Wed, 27 Jul 2005) $
   45    */
   46   
   47   
   48   public class McastService implements MembershipService,MembershipListener {
   49   
   50       private static org.apache.commons.logging.Log log =
   51           org.apache.commons.logging.LogFactory.getLog( McastService.class );
   52   
   53       /**
   54        * The string manager for this package.
   55        */
   56       protected StringManager sm = StringManager.getManager(Constants.Package);
   57   
   58       /**
   59        * The descriptive information about this implementation.
   60        */
   61       private static final String info = "McastService/2.0";
   62   
   63       /**
   64        * The implementation specific properties
   65        */
   66       protected Properties properties = new Properties();
   67       /**
   68        * A handle to the actual low level implementation
   69        */
   70       protected McastServiceImpl impl;
   71       /**
   72        * A membership listener delegate (should be the cluster :)
   73        */
   74       protected MembershipListener listener;
   75       /**
   76        * The local member
   77        */
   78       protected McastMember localMember ;
   79       private int mcastSoTimeout;
   80       private int mcastTTL;
   81   
   82       /**
   83        * my cluster
   84        */
   85       private SimpleTcpCluster cluster;
   86   
   87       /**
   88        * Transmitter Mbean name
   89        */
   90       private ObjectName objectName;
   91   
   92       private Registry registry;
   93   
   94       /**
   95        * Create a membership service.
   96        */
   97       public McastService() {
   98           properties.setProperty("mcastClusterDomain", "catalina");
   99       }
  100   
  101       /**
  102        * Return descriptive information about this implementation and the
  103        * corresponding version number, in the format
  104        * <code>&lt;description&gt;/&lt;version&gt;</code>.
  105        */
  106       public String getInfo() {
  107           return (info);
  108       }
  109       
  110       /**
  111        * Transmitter ObjectName
  112        * 
  113        * @param name
  114        */
  115       public void setObjectName(ObjectName name) {
  116           objectName = name;
  117       }
  118   
  119       public ObjectName getObjectName() {
  120           return objectName;
  121       }
  122   
  123       /**
  124        *
  125        * @param properties
  126        * <BR/>All are required<BR />
  127        * 1. mcastPort - the port to listen to<BR>
  128        * 2. mcastAddress - the mcast group address<BR>
  129        * 3. mcastClusterDomain - the mcast cluster domain<BR>
  130        * 4. bindAddress - the bind address if any - only one that can be null<BR>
  131        * 5. memberDropTime - the time a member is gone before it is considered gone.<BR>
  132        * 6. msgFrequency - the frequency of sending messages<BR>
  133        * 7. tcpListenPort - the port this member listens to<BR>
  134        * 8. tcpListenHost - the bind address of this member<BR>
  135        * @exception java.lang.IllegalArgumentException if a property is missing.
  136        */
  137       public void setProperties(Properties properties) {
  138           hasProperty(properties,"mcastPort");
  139           hasProperty(properties,"mcastAddress");
  140           hasProperty(properties,"mcastClusterDomain");
  141           hasProperty(properties,"memberDropTime");
  142           hasProperty(properties,"msgFrequency");
  143           hasProperty(properties,"tcpListenPort");
  144           hasProperty(properties,"tcpListenHost");
  145           this.properties = properties;
  146       }
  147   
  148       /**
  149        * Return the properties, see setProperties
  150        */
  151       public Properties getProperties() {
  152           return properties;
  153       }
  154   
  155       /*
  156        * configured in cluster
  157        * 
  158        * @see org.apache.catalina.cluster.ClusterSender#setCatalinaCluster(org.apache.catalina.cluster.tcp.SimpleTcpCluster)
  159        */
  160       public void setCatalinaCluster(SimpleTcpCluster cluster) {
  161           this.cluster = cluster;
  162   
  163       }
  164   
  165       /**
  166        * Return the cluster for this membership service
  167        */
  168       public Cluster getCatalinaCluster() {
  169           return cluster ;
  170       }
  171   
  172       /**
  173        * Return the local member name
  174        */
  175       public String getLocalMemberName() {
  176           return localMember.toString() ;
  177       }
  178    
  179       /**
  180        * Return the local member
  181        */
  182       public Member getLocalMember() {
  183           localMember.setMemberAliveTime(System.currentTimeMillis()-impl.getServiceStartTime());
  184           return localMember;
  185       }
  186       
  187       /**
  188        * Sets the local member properties for broadcasting
  189        */
  190       public void setLocalMemberProperties(String listenHost, int listenPort) {
  191           properties.setProperty("tcpListenHost",listenHost);
  192           properties.setProperty("tcpListenPort",String.valueOf(listenPort));
  193       }
  194       
  195       public void setMcastAddr(String addr) {
  196           properties.setProperty("mcastAddress", addr);
  197       }
  198   
  199       public String getMcastAddr() {
  200           return properties.getProperty("mcastAddress");
  201       }
  202   
  203       public void setMcastBindAddress(String bindaddr) {
  204           properties.setProperty("mcastBindAddress", bindaddr);
  205       }
  206   
  207       public String getMcastBindAddress() {
  208           return properties.getProperty("mcastBindAddress");
  209       }
  210   
  211       public void setMcastClusterDomain(String clusterDomain) {
  212           properties.setProperty("mcastClusterDomain", clusterDomain);
  213       }
  214   
  215       public String getMcastClusterDomain() {
  216           return properties.getProperty("mcastClusterDomain");
  217       }
  218   
  219       public void setMcastPort(int port) {
  220           properties.setProperty("mcastPort", String.valueOf(port));
  221       }
  222   
  223       public int getMcastPort() {
  224           String p = properties.getProperty("mcastPort");
  225           return new Integer(p).intValue();
  226       }
  227       
  228       public void setMcastFrequency(long time) {
  229           properties.setProperty("msgFrequency", String.valueOf(time));
  230       }
  231   
  232       public long getMcastFrequency() {
  233           String p = properties.getProperty("msgFrequency");
  234           return new Long(p).longValue();
  235       }
  236   
  237       public void setMcastDropTime(long time) {
  238           properties.setProperty("memberDropTime", String.valueOf(time));
  239       }
  240   
  241       public long getMcastDropTime() {
  242           String p = properties.getProperty("memberDropTime");
  243           return new Long(p).longValue();
  244       }
  245   
  246       /**
  247        * Check if a required property is available.
  248        * @param properties The set of properties
  249        * @param name The property to check for
  250        */
  251       protected void hasProperty(Properties properties, String name){
  252           if ( properties.getProperty(name)==null) throw new IllegalArgumentException("Required property \""+name+"\" is missing.");
  253       }
  254   
  255       /**
  256        * Start broadcasting and listening to membership pings
  257        * @throws java.lang.Exception if a IO error occurs
  258        */
  259       public void start() throws java.lang.Exception {
  260           start(1);
  261           start(2);
  262           registerMBean();
  263       }
  264       
  265       public void start(int level) throws java.lang.Exception {
  266           if ( impl != null ) {
  267               impl.start(level);
  268               return;
  269           }
  270           String host = getProperties().getProperty("tcpListenHost");
  271           String domain = getProperties().getProperty("mcastClusterDomain");
  272           int port = Integer.parseInt(getProperties().getProperty("tcpListenPort"));
  273           String name = "tcp://"+host+":"+port;
  274           if ( localMember == null ) {
  275               localMember = new McastMember(name, domain, host, port, 100);
  276           } else {
  277               localMember.setName(name);
  278               localMember.setDomain(domain);
  279               localMember.setHost(host);
  280               localMember.setPort(port);
  281               localMember.setMemberAliveTime(100);
  282           }
  283           java.net.InetAddress bind = null;
  284           if ( properties.getProperty("mcastBindAddress")!= null ) {
  285               bind = java.net.InetAddress.getByName(properties.getProperty("mcastBindAddress"));
  286           }
  287           int ttl = -1;
  288           int soTimeout = -1;
  289           if ( properties.getProperty("mcastTTL") != null ) {
  290               try {
  291                   ttl = Integer.parseInt(properties.getProperty("mcastTTL"));
  292               } catch ( Exception x ) {
  293                   log.error("Unable to parse mcastTTL="+properties.getProperty("mcastTTL"),x);
  294               }
  295           }
  296           if ( properties.getProperty("mcastSoTimeout") != null ) {
  297               try {
  298                   soTimeout = Integer.parseInt(properties.getProperty("mcastSoTimeout"));
  299               } catch ( Exception x ) {
  300                   log.error("Unable to parse mcastSoTimeout="+properties.getProperty("mcastSoTimeout"),x);
  301               }
  302           }
  303   
  304           impl = new McastServiceImpl((McastMember)localMember,Long.parseLong(properties.getProperty("msgFrequency")),
  305                                       Long.parseLong(properties.getProperty("memberDropTime")),
  306                                       Integer.parseInt(properties.getProperty("mcastPort")),
  307                                       bind,
  308                                       java.net.InetAddress.getByName(properties.getProperty("mcastAddress")),
  309                                       ttl,
  310                                       soTimeout,
  311                                       this);
  312   
  313           impl.start(level);
  314   		long memberwait = (Long.parseLong(properties.getProperty("msgFrequency"))*4);
  315           if(log.isInfoEnabled())
  316               log.info("Sleeping for "+memberwait+" secs to establish cluster membership");
  317           Thread.sleep(memberwait);
  318   
  319       }
  320   
  321    
  322       /**
  323        * Stop broadcasting and listening to membership pings
  324        */
  325       public void stop() {
  326           try  {
  327               if ( impl != null) impl.stop();
  328           } catch ( Exception x)  {
  329               log.error("Unable to stop the mcast service.",x);
  330           }
  331           impl = null;
  332           unregisterMBean();
  333       }
  334   
  335       /**
  336        * register mbean descriptor for package mcast 
  337        * @throws Exception
  338        */
  339       protected void initMBeans() throws Exception {
  340         if(registry == null) {
  341           registry = Registry.getRegistry(null, null);
  342           registry.loadMetadata(this.getClass().getResourceAsStream(
  343               "mbeans-descriptors.xml"));
  344         }
  345       }
  346       
  347       /**
  348        * register MBeans for Membership
  349        *
  350        */
  351       protected void registerMBean() {
  352           if (cluster != null) {
  353               ObjectName clusterName = cluster.getObjectName();
  354               try {
  355                   MBeanServer mserver = cluster.getMBeanServer();
  356                   initMBeans();
  357                   Container container = cluster.getContainer();
  358                   String name = clusterName.getDomain() + ":type=ClusterMembership";
  359                   if (container instanceof StandardHost) {
  360                       name += ",host=" + clusterName.getKeyProperty("host");
  361                   }
  362                   ObjectName mcastName = new ObjectName(name);
  363                   if (mserver.isRegistered(mcastName)) {
  364                       if (log.isWarnEnabled())
  365                           log.warn(sm.getString(
  366                                   "cluster.mbean.register.allready", mcastName));
  367                       return;
  368                   }
  369                   setObjectName(mcastName);
  370                   mserver.registerMBean(cluster.getManagedBean(this),
  371                           getObjectName());
  372                   if (log.isInfoEnabled())
  373                       log.info("membership mbean registered (" + mcastName + ")");
  374               } catch (Exception e) {
  375                   log.warn("membership mbean creation failed (" + clusterName + ")" ,e);
  376               }
  377           }
  378       }
  379   
  380       /**
  381        * unregister MBeans for Membership
  382        *
  383        */
  384       protected void unregisterMBean() {
  385           if (cluster != null && getObjectName() != null) {
  386               try {
  387                   MBeanServer mserver = cluster.getMBeanServer();
  388                   mserver.unregisterMBean(getObjectName());
  389               } catch (Exception e) {
  390                   log.error(e);
  391               }
  392           }
  393       }
  394   
  395       /**
  396        * Return all the members by name
  397        */
  398       public String[] getMembersByName() {
  399           Member[] currentMembers = getMembers();
  400           String [] membernames ;
  401           if(currentMembers != null) {
  402               membernames = new String[currentMembers.length];
  403               for (int i = 0; i < currentMembers.length; i++) {
  404                   membernames[i] = currentMembers[i].toString() ;
  405               }
  406           } else
  407               membernames = new String[0] ;
  408           return membernames ;
  409       }
  410    
  411       /**
  412        * Return the member by name
  413        */
  414       public Member findMemberByName(String name) {
  415           Member[] currentMembers = getMembers();
  416           for (int i = 0; i < currentMembers.length; i++) {
  417               if (name.equals(currentMembers[i].toString()))
  418                   return currentMembers[i];
  419           }
  420           return null;
  421       }
  422    
  423       /**
  424        * Return all the members
  425        */
  426       public Member[] getMembers() {
  427           if ( impl == null || impl.membership == null ) return null;
  428           return impl.membership.getMembers();
  429       }
  430       /**
  431        * Add a membership listener, this version only supports one listener per service,
  432        * so calling this method twice will result in only the second listener being active.
  433        * @param listener The listener
  434        */
  435       public void addMembershipListener(MembershipListener listener) {
  436           this.listener = listener;
  437       }
  438       /**
  439        * Remove the membership listener
  440        */
  441       public void removeMembershipListener(){
  442           listener = null;
  443       }
  444   
  445       public void memberAdded(Member member) {
  446           if ( listener!=null ) listener.memberAdded(member);
  447       }
  448   
  449       /**
  450        * Callback from the impl when a new member has been received
  451        * @param member The member
  452        */
  453       public void memberDisappeared(Member member)
  454       {
  455           if ( listener!=null ) listener.memberDisappeared(member);
  456       }
  457   
  458       public int getMcastSoTimeout() {
  459           return mcastSoTimeout;
  460       }
  461       public void setMcastSoTimeout(int mcastSoTimeout) {
  462           this.mcastSoTimeout = mcastSoTimeout;
  463           properties.setProperty("mcastSoTimeout", String.valueOf(mcastSoTimeout));
  464       }
  465       public int getMcastTTL() {
  466           return mcastTTL;
  467       }
  468       public void setMcastTTL(int mcastTTL) {
  469           this.mcastTTL = mcastTTL;
  470           properties.setProperty("mcastTTL", String.valueOf(mcastTTL));
  471       }
  472   
  473       /**
  474        * Simple test program
  475        * @param args Command-line arguments
  476        * @throws Exception If an error occurs
  477        */
  478       public static void main(String args[]) throws Exception {
  479   		if(log.isInfoEnabled())
  480               log.info("Usage McastService hostname tcpport");
  481           McastService service = new McastService();
  482           java.util.Properties p = new java.util.Properties();
  483           p.setProperty("mcastPort","5555");
  484           p.setProperty("mcastAddress","224.10.10.10");
  485           p.setProperty("mcastClusterDomain","catalina");
  486           p.setProperty("bindAddress","localhost");
  487           p.setProperty("memberDropTime","3000");
  488           p.setProperty("msgFrequency","500");
  489           p.setProperty("tcpListenPort",args[1]);
  490           p.setProperty("tcpListenHost",args[0]);
  491           service.setProperties(p);
  492           service.start();
  493           Thread.sleep(60*1000*60);
  494       }
  495   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » cluster » mcast » [javadoc | source]