/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.jvnet.glassfish.comms.clb.core.sip;
import com.ericsson.ssa.container.datacentric.DataCentricUtilHolder;
import com.ericsson.ssa.sip.SipApplicationSessionBase;
import com.ericsson.ssa.sip.SipServletMessageImpl;
import com.sun.enterprise.admin.event.AdminEventListenerRegistry;
import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.config.ConfigException;
import com.sun.enterprise.config.serverbeans.Cluster;
import com.sun.enterprise.config.serverbeans.ClusterHelper;
import com.sun.enterprise.config.serverbeans.ServerHelper;
import com.sun.enterprise.config.serverbeans.ServerRef;
import com.sun.enterprise.ee.cms.core.GroupHandle;
import com.sun.enterprise.ee.cms.spi.MemberStates;
import com.sun.enterprise.server.ServerContext;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.glassfish.comms.api.datacentric.DataCentricUtil;
import org.jvnet.glassfish.comms.clb.core.util.ConsistentHash;
import org.jvnet.glassfish.comms.clb.core.util.LoadbalancerUtil;
import org.jvnet.glassfish.comms.gms.GMSEventListener;
import org.jvnet.glassfish.comms.gms.GMSEventListenerException;
import org.jvnet.glassfish.comms.util.LogUtil;
import java.util.List;
import java.util.Vector;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jvnet.glassfish.comms.admin.event.extensions.clb.ClusterChangeEvent;
import org.jvnet.glassfish.comms.admin.event.extensions.clb.ClusterChangeEventListener;
import org.jvnet.glassfish.comms.clb.admin.ClusterChangeEventListenerImpl;
import org.jvnet.glassfish.comms.gms.EventListener;
import javax.servlet.sip.SipApplicationSession;
import javax.servlet.sip.SipServletMessage;
import com.sun.enterprise.Switch;
import com.sun.enterprise.admin.server.core.AdminService;
import com.sun.enterprise.config.serverbeans.AvailabilityService;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.ConvergedLbConfig;
import com.sun.enterprise.config.serverbeans.ConvergedLoadBalancer;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.ElementProperty;
import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import org.jvnet.glassfish.comms.clb.core.util.LoadFactorTask;
import org.jvnet.glassfish.comms.clb.core.util.LoadFactorManager;
import org.jvnet.glassfish.comms.clb.core.util.LoadFactorChangeEventListener;
public class DataCentricUtilImpl implements DataCentricUtil,
LoadFactorChangeEventListener {
private static Logger logger = LogUtil.CLB_LOGGER.getLogger();
private static DataCentricUtil original;
private static final DataCentricUtilImpl instance = new DataCentricUtilImpl();
private String clusterName;
private DCUIGMSEventListenerImpl gmsEventListenerImpl;
private ConsistentHash<String, ServerInstance> idealHash;
private ConsistentHash<String, ServerInstance> actualHash;
private ConsistentHash<String, ServerInstance> failoverHash;
private ConsistentHash<String, ServerInstance> clbHash;
private Map<String, ServerInstance> instancesMap =
new ConcurrentHashMap<String, ServerInstance>();
private Map<String, ServerInstance> instanceClusterMap =
new ConcurrentHashMap<String, ServerInstance>();
private String localInstanceName;
private volatile String localBeKey;
private static final LoadFactorManager repository =
LoadFactorManager.getInstance();
//validation will be done after 5000 milliseconds
private static final long VALIDATION_WAIT_TIME = 5000L;
private static final Timer timer = Switch.getSwitch().getTimer();
private TimerTask timerTask;
private DataCentricUtilImpl() {
}
private void init() {
try {
initHash();
} catch (GMSEventListenerException e) {
logger.log(Level.SEVERE, "clb.dcu_initialiation_failed",
e.getMessage());
if(logger.isLoggable(Level.FINE)){
logger.log(Level.FINE, "clb.caught_an_exception", e);
}
} catch (ConfigException e) {
logger.log(Level.SEVERE, "clb.dcu_initialiation_failed",
e.getMessage());
if(logger.isLoggable(Level.FINE)){
logger.log(Level.FINE, "clb.caught_an_exception", e);
}
}
}
public static void install() {
original = DataCentricUtilHolder.getInstance();
instance.init();
DataCentricUtilHolder.setInstance(instance);
}
public static void deinstall() {
instance.cleanup();
DataCentricUtilHolder.setInstance(original);
}
public boolean isDataCentricEnabled() {
return true;
}
public String getActualServerInstance(String key) {
if(key == null){
if(logger.isLoggable(Level.FINER)){
logger.log(Level.FINER,
"clb.sip.actual_server_instance_lookup_using_null_key");
}
throw new IllegalArgumentException("Null key provided to " +
"lookup actual server instance");
}
String serverInstance;
if (actualHash == null) {
serverInstance = localInstanceName;
} else {
serverInstance = actualHash.get(key).getName();
}
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "State of actualHash: " + actualHash + "; key = " + key + "; server=" + serverInstance);
}
return serverInstance;
}
/**
* Returns instance that will be selected by CLB to service request with
* provided key. This will take into account properties load-increase-factor
* and load-factor-increase-period-in-seconds for recovered instance.
*
* @param key bekey associated with the request
* @return instance that will be selected by CLB to service request with
* provided key
*/
public String getCLBServerInstance(String key) {
if(key == null){
if(logger.isLoggable(Level.FINER)){
logger.log(Level.FINER,
"clb.sip.clb_server_instance_lookup_using_null_key");
}
throw new IllegalArgumentException("Null key provided to " +
"lookup CLB server instance");
}
String serverInstance = null;
if (clbHash == null) {
serverInstance = localInstanceName;
} else {
ServerInstance instanceObj = clbHash.get(key);
if(instanceObj != null)
serverInstance = instanceObj.getName();
}
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "State of clbHash: " +
clbHash + "; key = " + key + "; server=" + serverInstance);
}
return serverInstance;
}
/**
* Returns instance that will be selected by CLB to service request with
* provided key in case current instance handling that request fails. The
* instance returned by this API can be used as replication partner for that
* particular session.
*
* @param key bekey associated with the request
* @return instance that will be selected by CLB to service request with
* provided key in case current instance handling that request fails
*/
public String getFailoverServerInstance(String key) {
if(key == null){
if(logger.isLoggable(Level.FINER)){
logger.log(Level.FINER,
"clb.sip.failover_server_instance_lookup_using_null_key");
}
throw new IllegalArgumentException("Null key provided to " +
"lookup failover server instance");
}
String serverInstance = null;
if (failoverHash == null) {
serverInstance = localInstanceName;
} else {
ServerInstance instanceObj = failoverHash.get(key);
if(instanceObj != null)
serverInstance = instanceObj.getName();
}
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "State of failoverHash: " +
failoverHash + "; key = " + key + "; server=" + serverInstance);
}
return serverInstance;
}
public String getIdealServerInstance(String key) {
if(key == null){
if(logger.isLoggable(Level.FINER)){
logger.log(Level.FINER,
"clb.sip.ideal_server_instance_lookup_using_null_key");
}
throw new IllegalArgumentException("Null key provided to " +
"lookup ideal server instance");
}
String serverInstance;
if (idealHash == null) {
serverInstance = localInstanceName;
} else {
serverInstance = idealHash.get(key).getName();
}
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "State of idealHash: " + idealHash + "; key = " + key + "; server=" + serverInstance);
}
return serverInstance;
}
public boolean isLocal(String key) {
String serverInstance = getActualServerInstance(key);
boolean result = localInstanceName.equals(serverInstance);
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Result = " + result);
}
return result;
}
public String getLocalKey() {
// TODO the localBeKey must be set to null when a server instance is added to the cluster
if (localBeKey == null) {
for (int i = 0; i < 10000; i++) {
String idealInstance = getIdealServerInstance("" + i);
if (localInstanceName.equals(idealInstance)) {
localBeKey = "" + i;
break;
}
}
if (localBeKey == null) {
throw new RuntimeException("Could not generate a local back-end key.");
}
}
return localBeKey;
}
public String getApplicationKey(SipApplicationSession sas) {
return ((SipApplicationSessionBase) sas).getBeKey();
}
public String getConsistentHashKey(SipServletMessage message) {
return ((SipServletMessageImpl)message).getBeKey();
}
private void setProperties() {
ConvergedLbConfig clbConfig = null;
try {
ConfigContext ctx = AdminService.getAdminService().
getAdminContext().getAdminConfigContext();
ServerContext sc = com.sun.enterprise.server.ondemand.
OnDemandServer.getServerContext();
ConfigContext instanceConfigContext = sc.getConfigContext();
Config instanceConfig = ServerBeansFactory.
getConfigBean(instanceConfigContext);
AvailabilityService haService = instanceConfig.
getAvailabilityService();
ConvergedLoadBalancer clb = haService.getConvergedLoadBalancer();
String clbConfigName = clb.getConvergedLbConfigName();
clbConfig = ((Domain) ctx.getRootConfigBean()).
getConvergedLbConfigs().getConvergedLbConfigByName(
clbConfigName);
} catch (Exception ex) {
logger.log(Level.WARNING,
"clb.configexception_will_getting_instance_config",
ex.toString());
if(logger.isLoggable(Level.FINE)){
logger.log(Level.FINE,"clb.caught_an_exception", ex);
}
return;
}
ElementProperty[] elementProperties=
clbConfig.getElementProperty();
HashMap<String, String> propertiesMap = new HashMap<String, String>();
for(int i=0; i < elementProperties.length; i++){
propertiesMap.put(elementProperties[i].getName(),
elementProperties[i].getValue());
}
repository.setProperties(propertiesMap);
}
private void initHash() throws GMSEventListenerException, ConfigException {
//TBD: Create a admin listener to listen to properties change event
//and reset these properties
setProperties();
ServerContext sc = com.sun.enterprise.server.ondemand.OnDemandServer.getServerContext();
ConfigContext instanceConfigContext = sc.getConfigContext();
localInstanceName = sc.getInstanceName();
if (ServerHelper.isServerClustered(instanceConfigContext, localInstanceName)) {
Cluster cluster = ClusterHelper.getClusterForInstance(instanceConfigContext, localInstanceName);
clusterName = cluster.getName();
if (clusterName != null) {
gmsEventListenerImpl = new DCUIGMSEventListenerImpl(clusterName);
registerAdminEventListener();
}
ServerRef[] serverRefs = cluster.getServerRef();
idealHash = new ConsistentHash<String, ServerInstance>(1024, "DCU_IdealHash");
actualHash = new ConsistentHash<String, ServerInstance>(1024, "DCU_ActualHash");
clbHash = new ConsistentHash<String, ServerInstance>(1024, "DCU_CLBHash");
failoverHash =
new ConsistentHash<String, ServerInstance>(1024, "DCU_FailoverHash");
List<String> healthyInstances = null;
if (gmsEventListenerImpl != null) {
healthyInstances = getHealthyInstances();
}
for (int i = 0; i < serverRefs.length; i++) {
String serverName = serverRefs[i].getRef();
ServerInstance serverInstance = new ServerInstance(clusterName, serverName);
serverInstance.setEnabled(serverRefs[i].isLbEnabled());
if ((healthyInstances != null) && healthyInstances.contains(serverName)) {
serverInstance.setHealthy(true);
} else {
serverInstance.setHealthy(false);
}
instancesMap.put(serverName, serverInstance);
instanceClusterMap.put(serverInstance.toString(),
serverInstance);
idealHash.addNode(serverInstance, false);
if (serverInstance.isEnabled() && serverInstance.isHealthy()) {
actualHash.addNode(serverInstance, false);
clbHash.addNode(serverInstance, false);
if(!serverInstance.getName().equals(localInstanceName)){
failoverHash.addNode(serverInstance, false);
}
}
}
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Setting up idealHash");
}
idealHash.setup();
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Setting up actualHash");
}
actualHash.setup();
clbHash.setup();
failoverHash.setup();
logger.log(Level.INFO,
"clb.healthy_instances_in_dcu_view_at_startup",
new Object[]{clusterName, healthyInstances.toString()});
}
}
public List<String> getHealthyInstances() {
final int INITIAL_CAPACITY = 10;
final int INCREMENTAL = 5;
Vector healthyInstances = new Vector(INITIAL_CAPACITY,INCREMENTAL);
final long startTime = System.currentTimeMillis();
GroupHandle groupHandle = gmsEventListenerImpl.getGroupManagementService().getGroupHandle();
List<String> coreMembers = groupHandle.getCurrentCoreMembers();
for (String core : coreMembers) {
//Changing such that threshold of 6 seconds and
//timeout of 0 seconds is used. This will ensure value
//is returned from maintained GMS state cache.
//These values will later be used as default and this
//change will be reverted back
MemberStates state = groupHandle.getMemberState(core,
6000L, 0L);
if (state == MemberStates.ALIVEANDREADY
|| state == MemberStates.READY) {
healthyInstances.add(core);
} else if (state == MemberStates.UNKNOWN) {
MemberStates pollState = groupHandle.getMemberState(core, 6000L, 3000L);
if ( pollState == MemberStates.ALIVEANDREADY || pollState == MemberStates.READY) {
healthyInstances.add(core);
} else {
long duration = System.currentTimeMillis() - startTime;
if (logger.isLoggable(Level.FINER)) {
logger.finer("DCU getHealthyInstances: getMemberState(" + core + ", 6 secs, 3 secs) hb only state=" + state +
" poll state=" + pollState + " getHealthyInstances current duration(in ms)=" + duration);
}
}
}
}
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "clb.gms_module_core_members", new Object[] {
clusterName, groupHandle.getAllCurrentMembers().toString()
});
logger.log(Level.FINE, "clb.gms_module_core_current_members", new Object[] {
clusterName, coreMembers.toString()
});
logger.log(Level.FINE, "clb.gms_module_current_healthy_members", new Object[] {
clusterName, healthyInstances.toString() });
}
return healthyInstances;
}
public void cleanup() {
gmsEventListenerImpl.cleanup();
}
/**
* Register admin event listener to listen for instance addition
* deletion and update event
*/
private void registerAdminEventListener() {
EventListener action = new DCUIClusterChangeEventListener();
ClusterChangeEventListener clusterChangeEventListener =
new ClusterChangeEventListenerImpl(clusterName, action);
AdminEventListenerRegistry.registerEventListener(
ClusterChangeEvent.eventType, clusterChangeEventListener,
ClusterChangeEventListener.class);
}
public void updateLoadFactor(String instanceName,
double currFactor){
ServerInstance serverInstance = instanceClusterMap.get(instanceName);
if(instance != null){
clbHash.addNode(serverInstance, currFactor, true);
}
}
private static class ServerInstance {
private String clusterName;
private String name;
private boolean healthy;
private boolean enabled;
public ServerInstance(String clusterName, String name) {
super();
this.clusterName = clusterName;
this.name = name;
}
public String getClusterName() {
return clusterName;
}
public String getName() {
return name;
}
@Override
public String toString() {
return LoadbalancerUtil.getServerString(clusterName, name);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + ((clusterName == null) ? 0 : clusterName.hashCode());
result = (prime * result) + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ServerInstance other = (ServerInstance) obj;
if (clusterName == null) {
if (other.clusterName != null) {
return false;
}
} else if (!clusterName.equals(other.clusterName)) {
return false;
}
if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
}
return true;
}
public boolean isHealthy() {
return healthy;
}
public boolean isEnabled() {
return enabled;
}
public void setHealthy(boolean healthy) {
this.healthy = healthy;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
class DCUIGMSEventListenerImpl extends GMSEventListener {
public DCUIGMSEventListenerImpl(String clusterName) throws GMSEventListenerException {
super(clusterName);
}
public void onRecovery(String clusterName, String instanceName,
boolean isClusterStartup) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "clb.recieved_recovery_notification_for_instance", new Object[] {
instanceName, clusterName, isClusterStartup
});
}
ServerInstance serverInstance = instancesMap.get(instanceName);
if (serverInstance == null) {
return;
}
synchronized (serverInstance) {
if (serverInstance.isHealthy()) {
return;
}
serverInstance.setHealthy(true);
if (!serverInstance.isEnabled()) {
return;
}
}
actualHash.addNode(serverInstance, true);
boolean createdAddTask = false;
if(!isClusterStartup){
LoadFactorTask task = repository.createAddTask(
serverInstance.toString());
if(task != null){
task.addListener(DataCentricUtilImpl.this);
createdAddTask = true;
}
}
if(!createdAddTask){
clbHash.addNode(serverInstance, true);
}
if(!serverInstance.getName().equals(localInstanceName)){
failoverHash.addNode(serverInstance, true);
}
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Setting up actualHash after recovery of " + clusterName + "/" + instanceName);
}
Iterator<EventListener> iter =
DataCentricUtilHolder.getEventListeners().iterator();
while(iter.hasNext()){
EventListener listener = iter.next();
listener.onRecovery(clusterName, instanceName, isClusterStartup);
}
createTimerTaskForValidation();
}
public void onFailure(String clusterName, String instanceName,
boolean isClusterShutdown) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "clb.recieved_failure_notification_for_instance", new Object[] {
instanceName, clusterName, isClusterShutdown
});
}
if(!isClusterShutdown){
ServerInstance serverInstance = instancesMap.get(instanceName);
if (serverInstance == null) {
return;
}
synchronized (serverInstance) {
if (!serverInstance.isHealthy()) {
return;
}
serverInstance.setHealthy(false);
if (!serverInstance.isEnabled()) {
return;
}
}
actualHash.removeNode(serverInstance, true);
clbHash.removeNode(serverInstance, true);
LoadFactorTask task = repository.getAddTask(serverInstance.toString());
if(task != null){
task.removeListener(DataCentricUtilImpl.this);
}
if(!serverInstance.getName().equals(localInstanceName)){
failoverHash.removeNode(serverInstance, true);
}
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Setting up actualHash after failure of " + clusterName + "/" + instanceName);
}
Iterator<EventListener> iter =
DataCentricUtilHolder.getEventListeners().iterator();
while(iter.hasNext()){
EventListener listener = iter.next();
listener.onFailure(clusterName, instanceName, isClusterShutdown);
}
createTimerTaskForValidation();
}
}
private void validateDCUAndGMSSync(String clusterName){
Collection<ServerInstance> serverInstances =
instancesMap.values();
List<String> healthyInstancesInGMS = getHealthyInstances();
List<String> healthyInstancesInDCU = new ArrayList<String>();
for(ServerInstance instance:serverInstances){
if(instance.isHealthy()){
healthyInstancesInDCU.add(instance.getName());
}
}
logger.log(Level.INFO, "clb.healthy_instances_in_gms_view",
new Object[]{clusterName,
healthyInstancesInGMS.toString()});
logger.log(Level.INFO, "clb.healthy_instances_in_dcu_view",
new Object[]{clusterName,
healthyInstancesInDCU.toString()});
if(healthyInstancesInDCU.containsAll(healthyInstancesInGMS)
&& healthyInstancesInGMS.containsAll(healthyInstancesInDCU)){
logger.log(Level.INFO, "clb.dcu_gms_view_in_sync",
new Object[]{clusterName});
}
else{
logger.log(Level.SEVERE, "clb.dcu_gms_view_not_in_sync",
new Object[]{clusterName});
}
}
private synchronized void createTimerTaskForValidation(){
//If timerTask exists, cancel it
if(timerTask != null){
if(timerTask.cancel())
timer.purge();
}
//Create a new timer Task and schedule it
timerTask = new TimerTask(){
public void run(){
validateDCUAndGMSSync(clusterName);
}
};
timer.schedule(timerTask, VALIDATION_WAIT_TIME);
}
}
class DCUIClusterChangeEventListener implements EventListener{
public DCUIClusterChangeEventListener(){
}
public void onAdd(String clusterName, String instanceName, boolean lbEnabled) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "clb.recieved_notification_for_instance_addition", new Object[] {
instanceName, clusterName, lbEnabled
});
}
//Don't do anything is instance already exist
//This should not happen in any case
//Just added to guard against it
if(instancesMap.containsKey(instanceName))
return;
ServerInstance instance = new ServerInstance(clusterName, instanceName);
instance.setEnabled(lbEnabled);
//Add instance to instancesMap
instancesMap.put(instanceName, instance);
instanceClusterMap.put(instance.toString(), instance);
//Add new instance to idealHash
idealHash.addNode(instance, true);
//localBeKey should be reset as new instance
//which will change key distribution
localBeKey = null;
Iterator<EventListener> iter =
DataCentricUtilHolder.getEventListeners().iterator();
while(iter.hasNext()){
EventListener listener = iter.next();
listener.onAdd(clusterName, instanceName, lbEnabled);
}
}
public void onDelete(String clusterName, String instanceName) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "clb.recieved_notification_for_instance_deletion", new Object[] {
instanceName, clusterName
});
}
//Remove instance from instancesMap
ServerInstance instance = instancesMap.remove(instanceName);
//Don't do anything is instance does not exist
//This should not happen in any case
//Just added to guard against it
if(instance == null)
return;
instanceClusterMap.remove(instance.toString());
//Remove instance from idealHash
idealHash.removeNode(instance, true);
Iterator<EventListener> iter =
DataCentricUtilHolder.getEventListeners().iterator();
while(iter.hasNext()){
EventListener listener = iter.next();
listener.onDelete(clusterName, instanceName);
}
}
public void onDisable(String clusterName, String instanceName) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "clb.recieved_disable_notification_for_instance", new Object[] {
instanceName, clusterName
});
}
ServerInstance serverInstance = instancesMap.get(instanceName);
if (serverInstance == null) {
return;
}
synchronized (serverInstance) {
if (!serverInstance.isEnabled()) {
return;
}
serverInstance.setEnabled(false);
if (!serverInstance.isHealthy()) {
return;
}
}
actualHash.removeNode(serverInstance, true);
clbHash.removeNode(serverInstance, true);
if(!serverInstance.getName().equals(localInstanceName)){
failoverHash.removeNode(serverInstance, true);
}
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Setting up actualHash after disable of " + clusterName + "/" + instanceName);
}
Iterator<EventListener> iter =
DataCentricUtilHolder.getEventListeners().iterator();
while(iter.hasNext()){
EventListener listener = iter.next();
listener.onDisable(clusterName, instanceName);
}
}
public void onEnable(String clusterName, String instanceName) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "clb.recieved_enable_notification_for_instance", new Object[] {
instanceName, clusterName
});
}
ServerInstance serverInstance = instancesMap.get(instanceName);
if (serverInstance == null) {
return;
}
synchronized (serverInstance) {
if (serverInstance.isEnabled()) {
return;
}
serverInstance.setEnabled(true);
if (!serverInstance.isHealthy()) {
return;
}
}
actualHash.addNode(serverInstance, true);
clbHash.addNode(serverInstance, true);
if(!serverInstance.getName().equals(localInstanceName)){
failoverHash.addNode(serverInstance, true);
}
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Setting up actualHash after enable of " + clusterName + "/" + instanceName);
}
Iterator<EventListener> iter =
DataCentricUtilHolder.getEventListeners().iterator();
while(iter.hasNext()){
EventListener listener = iter.next();
listener.onEnable(clusterName, instanceName);
}
}
public void onRecovery(String clusterName, String instanceName,
boolean isClusterStartup) {
//Cluster change event listerner will never provide
//instance recovery event
throw new UnsupportedOperationException();
}
public void onFailure(String clusterName, String instanceName,
boolean isClusterShutdown) {
//Cluster change event listerner will never provide
//instance failure event
throw new UnsupportedOperationException();
}
}
}