Base class for HA-Singleton services.
| Method from org.jboss.ha.singleton.HASingletonSupport Detail: |
public void _stopOldMaster() {
this.log.debug("_stopOldMaster, isMasterNode=" + this.master);
try
{
// since this is a cluster call, all nodes will hear it
// so if the node is not the master, then ignore
if (this.master.compareAndSet(true, false))
{
// notify stopping
this.sendLocalNotification(HASINGLETON_STOPPING_NOTIFICATION);
// stop the singleton
this.stopSingleton();
// notify stopped
this.sendLocalNotification(HASINGLETON_STOPPED_NOTIFICATION);
}
}
catch (Exception ex)
{
this.log.error(
"_stopOldMaster failed. Will still try to start new master. " +
"You need to examine the reason why the old master wouldn't stop and resolve it. " +
"It is bad that the old singleton may still be running while we are starting a new one, " +
"so you need to resolve this ASAP.", ex);
}
}
This method will be invoked twice by the local node
when it stops as well as by the remote |
protected void createService() throws Exception {
super.createService();
if (this.mElectionPolicyMB != null)
{
this.mElectionPolicyMB.setHAPartition(this.getHAPartition());
this.mElectionPolicyMB.setSingletonName(this.getServiceHAName());
}
}
|
public HASingletonElectionPolicy getElectionPolicy() {
return this.mElectionPolicyMB;
}
|
public boolean getRestartOnMerge() {
return this.restartOnMerge;
}
Gets whether this singleton will stop and restart itself if it is the
master and a cluster merge occurs.
A restart allows the service to reset any state that may
have gotten out-of-sync with the rest of the cluster while
the just-merged split was in effect. |
public boolean isMasterNode() {
return this.master.get();
}
|
protected void makeThisNodeMaster() {
try
{
// stop the old master (if there is one) before starting the new one
// ovidiu 09/02/04 - temporary solution for Case 1843, use an asynchronous
// distributed call.
//callMethodOnPartition("_stopOldMaster", new Object[0], new Class[0]);
this.callAsyncMethodOnPartition("_stopOldMaster", new Object[0], new Class[0]);
this.startNewMaster();
}
catch (Exception ex)
{
this.log.error("_stopOldMaster failed. New master singleton will not start.", ex);
}
}
|
public void partitionTopologyChanged(List newReplicants,
int newViewID,
boolean merge) {
boolean isElectedNewMaster;
if (this.mElectionPolicyMB != null)
{
ClusterNode electedNode = this.mElectionPolicyMB.elect();
isElectedNewMaster = electedNode != null ? electedNode.equals(this.getHAPartition().getClusterNode()) : false;
}
else
{
isElectedNewMaster = this.isDRMMasterReplica();
}
this.log.debug("partitionTopologyChanged, isElectedNewMaster=" + isElectedNewMaster
+ ", isMasterNode=" + this.master + ", viewID=" + newViewID);
boolean isMaster = this.master.get();
// if this node is already the master, don't bother electing it again
if (isElectedNewMaster && isMaster)
{
// JBAS-4229
if (this.restartOnMerge && merge)
{
this.restartMaster();
}
}
// just becoming master
else if (isElectedNewMaster && !isMaster)
{
this.makeThisNodeMaster();
}
// transition from master to slave
else if (isMaster)
{
this._stopOldMaster();
}
}
When topology changes, a new master is elected based on the result
of the isDRMMasterReplica() call. |
protected void restartMaster() {
this._stopOldMaster();
this.startNewMaster();
}
|
public void setElectionPolicy(HASingletonElectionPolicy mb) {
this.mElectionPolicyMB = mb;
}
|
public void setRestartOnMerge(boolean restartOnMerge) {
this.restartOnMerge = restartOnMerge;
}
Sets whether this singleton will stop and restart itself if it is the
master and a cluster merge occurs?
A restart allows the service to reset any state that may
have gotten out-of-sync with the rest of the cluster while
the just-merged split was in effect. |
protected void startNewMaster() {
this.log.debug("startNewMaster, isMasterNode=" + this.master);
this.master.set(true);
// notify starting
this.sendLocalNotification(HASINGLETON_STARTING_NOTIFICATION);
// start new master
this.startSingleton();
// notify started
this.sendLocalNotification(HASINGLETON_STARTED_NOTIFICATION);
}
|
public void startSingleton() {
this.log.debug("startSingleton() : elected for master singleton node");
// Extending classes will implement the singleton logic here
}
Extending classes should override this method and implement the custom
singleton logic. Only one node in the cluster is the active master.
If the current node is elected for master, this method is invoked.
When another node is elected for master for some reason, the
stopSingleton() method is invokded.
When the extending class is a stateful singleton, it will
usually use putDistributedState() and getDistributedState() to save in
the cluster environment information that will be needed by the next node
elected for master should the current master node fail. |
public void stopSingleton() {
this.log.debug("stopSingleton() : another node in the partition (if any) is elected for master");
// Extending classes will implement the singleton logic here
}
Extending classes should override this method and implement the custom
singleton logic. Only one node in the cluster is the active master.
If the current node is master and another node is elected for master, this
method is invoked. |