KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ha > singleton > HASingletonSupport


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22 package org.jboss.ha.singleton;
23
24 import java.util.List JavaDoc;
25
26 import javax.management.Notification JavaDoc;
27
28 import org.jboss.ha.jmx.HAServiceMBeanSupport;
29
30 /**
31  * Base class for HA-Singleton services.
32  *
33  * @author <a HREF="mailto:ivelin@apache.org">Ivelin Ivanov</a>
34  * @author <a HREF="mailto:scott.stark@jboss.org">Scott Stark</a>
35  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
36  * @version $Revision: 46010 $
37  */

38 public class HASingletonSupport extends HAServiceMBeanSupport
39    implements HASingletonMBean, HASingleton
40 {
41    // Private Data --------------------------------------------------
42

43    private boolean isMasterNode = false;
44    private HASingletonElectionPolicyMBean mElectionPolicyMB = null;
45
46    // Constructors --------------------------------------------------
47

48    /**
49     * Default CTOR
50     */

51    public HASingletonSupport()
52    {
53       // empty
54
}
55
56    // Attributes ----------------------------------------------------
57

58    /**
59     * @jmx:managed-attribute
60     *
61     * @return true if this cluster node has the active mbean singleton, false otherwise
62     */

63    public boolean isMasterNode()
64    {
65       return isMasterNode;
66    }
67
68    /**
69     * @see HASingletonSupportMBean#setHASingletonElectionPolicyMBean(HASingletonElectionPolicyMBean)
70     */

71    public void setHASingletonElectionPolicyMBean(HASingletonElectionPolicyMBean mb)
72    {
73       this.mElectionPolicyMB = mb;
74    }
75    
76    /**
77     * @see HASingletonSupportMBean#getHASingletonElectionPolicyMBean()
78     */

79    public HASingletonElectionPolicyMBean getHASingletonElectionPolicyMBean()
80    {
81       return this.mElectionPolicyMB;
82    }
83
84    // Public --------------------------------------------------------
85

86    /**
87     * Extending classes should override this method and implement the custom
88     * singleton logic. Only one node in the cluster is the active master.
89     * If the current node is elected for master, this method is invoked.
90     * When another node is elected for master for some reason, the
91     * stopSingleton() method is invokded.
92     * <p>
93     * When the extending class is a stateful singleton, it will
94     * usually use putDistributedState() and getDistributedState() to save in
95     * the cluster environment information that will be needed by the next node
96     * elected for master should the current master node fail.
97     *
98     * @see HASingleton
99     */

100    public void startSingleton()
101    {
102       if (log.isDebugEnabled())
103          log.debug("startSingleton() : elected for master singleton node");
104
105       // Extending classes will implement the singleton logic here
106
}
107
108    /**
109     * Extending classes should override this method and implement the custom
110     * singleton logic. Only one node in the cluster is the active master.
111     * If the current node is master and another node is elected for master, this
112     * method is invoked.
113     *
114     * @see HASingleton
115     */

116    public void stopSingleton()
117    {
118       if (log.isDebugEnabled())
119          log.debug("stopSingleton() : another node in the partition (if any) is elected for master");
120       
121       // Extending classes will implement the singleton logic here
122
}
123
124
125    /**
126     * When topology changes, a new master is elected based on the result
127     * of the isDRMMasterReplica() call.
128     *
129     * @see HAServiceMBeanSupport#partitionTopologyChanged(List, int)
130     * @see DistributedReplicantManager#isMasterReplica(String);
131     */

132    public void partitionTopologyChanged(List JavaDoc newReplicants, int newViewID)
133    {
134       boolean isElectedNewMaster;
135       if (this.mElectionPolicyMB != null)
136          isElectedNewMaster = this.mElectionPolicyMB.isElectedMaster(this.getPartition());
137       else
138          isElectedNewMaster = isDRMMasterReplica();
139       
140       if (log.isDebugEnabled())
141       {
142          log.debug("partitionTopologyChanged, isElectedNewMaster=" + isElectedNewMaster
143             + ", isMasterNode=" + isMasterNode + ", viewID=" + newViewID);
144       }
145
146       // if this node is already the master, don't bother electing it again
147
if (isElectedNewMaster && isMasterNode)
148       {
149          return;
150       }
151       // just becoming master
152
else if (isElectedNewMaster && !isMasterNode)
153       {
154          makeThisNodeMaster();
155       }
156       // transition from master to slave
157
else if (isMasterNode == true)
158       {
159          _stopOldMaster();
160       }
161    }
162
163    /**
164     * This method will be invoked twice by the local node
165     * when it stops as well as by the remote
166     */

167    public void _stopOldMaster()
168    {
169       log.debug("_stopOldMaster, isMasterNode=" + isMasterNode);
170       
171       try
172       {
173          // since this is a cluster call, all nodes will hear it
174
// so if the node is not the master, then ignore
175
if (isMasterNode == true)
176          {
177             isMasterNode = false;
178             
179             // notify stopping
180
sendLocalNotification(HASINGLETON_STOPPING_NOTIFICATION);
181             
182             // stop the singleton
183
stopSingleton();
184             
185             // notify stopped
186
sendLocalNotification(HASINGLETON_STOPPED_NOTIFICATION);
187          }
188       }
189       catch (Exception JavaDoc ex)
190       {
191          log.error(
192             "_stopOldMaster failed. Will still try to start new master. " +
193             "You need to examine the reason why the old master wouldn't stop and resolve it. " +
194             "It is bad that the old singleton may still be running while we are starting a new one, " +
195             "so you need to resolve this ASAP.", ex);
196       }
197    }
198
199    // Protected -----------------------------------------------------
200

201    protected void makeThisNodeMaster()
202    {
203       try
204       {
205          // stop the old master (if there is one) before starting the new one
206

207          // ovidiu 09/02/04 - temporary solution for Case 1843, use an asynchronous
208
// distributed call.
209
//callMethodOnPartition("_stopOldMaster", new Object[0], new Class[0]);
210
callAsyncMethodOnPartition("_stopOldMaster", new Object JavaDoc[0], new Class JavaDoc[0]);
211
212          isMasterNode = true;
213          
214          // notify starting
215
sendLocalNotification(HASINGLETON_STARTING_NOTIFICATION);
216
217          // start new master
218
startSingleton();
219          
220          // notify started
221
sendLocalNotification(HASINGLETON_STARTED_NOTIFICATION);
222       }
223       catch (Exception JavaDoc ex)
224       {
225          log.error("_stopOldMaster failed. New master singleton will not start.", ex);
226       }
227    }
228    
229    // Private -------------------------------------------------------
230

231    private void sendLocalNotification(String JavaDoc type)
232    {
233       Notification JavaDoc n = new Notification JavaDoc(type, this, getNextNotificationSequenceNumber());
234       super.sendNotificationToLocalListeners(n);
235    }
236 }
237
Popular Tags