Package org.jvnet.glassfish.comms.clb.core.sip

Source Code of org.jvnet.glassfish.comms.clb.core.sip.DataCentricUtilImpl

/*
* 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();
        }       
    }
}
TOP

Related Classes of org.jvnet.glassfish.comms.clb.core.sip.DataCentricUtilImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.