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

Source Code of org.jvnet.glassfish.comms.clb.core.ClusterHealthMonitor$CHMGMSEventListenerImpl

/*
* 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;

import org.jvnet.glassfish.comms.gms.GMSEventListener;
import com.sun.enterprise.ee.cms.core.GroupHandle;
import com.sun.enterprise.ee.cms.spi.MemberStates;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Logger;
import org.jvnet.glassfish.comms.clb.admin.CLBConfigurator;

import org.jvnet.glassfish.comms.util.LogUtil;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;
import org.jvnet.glassfish.comms.gms.GMSEventListenerException;

import com.sun.enterprise.Switch;
import java.util.Timer;
import java.util.TimerTask;

/**
*
* @author kshitiz
*/
public class ClusterHealthMonitor{
    private static final Logger _logger = LogUtil.CLB_LOGGER.getLogger();
    private String clusterName;
    private CHMGMSEventListenerImpl gmsEventListenerImpl;
   
    //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;   

    /** Creates a new instance of ServerHealthMonitor */
    public ClusterHealthMonitor(String clusterName)
        throws CLBRuntimeException {
        this.clusterName = clusterName;
        try {
            gmsEventListenerImpl = new CHMGMSEventListenerImpl(clusterName);
        } catch (GMSEventListenerException ex) {
            throw new CLBRuntimeException(ex);
        }
    }

    public List<String> getHealthyInstances() {
        final int INITIAL_CAPACITY = 10;
        final int INCREMENTAL = 5;
        Vector healthyInstances = new Vector(INITIAL_CAPACITY,INCREMENTAL);
        GroupHandle groupHandle = gmsEventListenerImpl.
            getGroupManagementService().getGroupHandle();
        final long startTime = System.currentTimeMillis();
        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("CLB 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;
    }

    private ServerInstance getServerInstance(String clusterName,
        String instanceName, boolean isHttp) {
        Controller controller;
        if(isHttp)
            controller = CLBConfigurator.getInstance().
                    getHttpControllerInitializer().getController();
        else
            controller = CLBConfigurator.getInstance().
                    getSipControllerInitializer().getController();
        if(controller == null)
            return null;
        return controller.getInstance(clusterName, instanceName);
    }

    public String getClusterName() {
        return clusterName;
    }

    public void cleanup() {
        gmsEventListenerImpl.cleanup();
    }
   
    /*
    class PingThread extends Thread {
        private ServerInstance httpInstance;
        private ServerInstance sipInstance;
       
        private final int maxRetryCount = 10;
        private final long sleepBetweenRetry = 5000L;

        PingThread(ServerInstance httpInstance, ServerInstance sipInstance) {
            this.httpInstance = httpInstance;
            this.sipInstance = sipInstance;
        }

        public void run() {
            pingHttpEndPoint();
        }

        private void pingHttpEndPoint() {
            EndPoint endPoint;
            endPoint = httpInstance.getEndPoint(CLBConstants.HTTP_PROTOCOL);

            if (endPoint == null) {
                endPoint = httpInstance.getEndPoint(CLBConstants.HTTPS_PROTOCOL);
            }

            if (endPoint == null) {
                _logger.log(Level.SEVERE,
                        "clb.no_endpoint_to_ping",
                        new Object[]{httpInstance.getName(), clusterName});
            }

            sendHttpRequest(endPoint);
        }

        private void sendHttpRequest(EndPoint endPoint) {
            String request = "HEAD / HTTP/1.1\r\n" + "Host: " +
                endPoint.getHost() + ":" + endPoint.getPort() + "\r\n" +
                "Proxy-ping: true\r\n\r\n";
            int count = 0;

            while (count < maxRetryCount) {
                count++;

                try {
                    Socket socket = new Socket();
                    socket.connect(endPoint.getSocketAddress());

                    OutputStream outputStream = socket.getOutputStream();
                    outputStream.write(request.getBytes());
                    outputStream.flush();

                    BufferedReader reader = new BufferedReader(new InputStreamReader(
                                socket.getInputStream()));
                    String line = reader.readLine();

                    if (line != null) {
                        int index = line.indexOf(" ");

                        if (index > -1) {
                            int next = line.indexOf(" ", index + 1);

                            if (next > -1) {
                                int statusCode = Integer.valueOf(line.substring(index +
                                            1, next));

                                if ((statusCode >= 100) && (statusCode <= 499)) {
                                    if(_logger.isLoggable(Level.FINE))
                                        _logger.log(Level.FINE,
                                                "clb.ping_request_successful",
                                                new Object[]{httpInstance.getName(), clusterName});
                                    httpInstance.markAsHealthy();
                                    sipInstance.markAsHealthy();
                                }
                            }
                        }
                    }

                    try {
                        socket.close();
                    } catch (IOException ex) {
                        if(_logger.isLoggable(Level.FINE))
                            _logger.log(Level.FINE,
                                    "clb.caught_an_exception",
                                    ex);
                    }

                    if (httpInstance.isHealthy()) {
                        break;
                    }

                    _logger.log(Level.SEVERE,
                            "clb.ping_request_unsuccessful",
                            new Object[]{ httpInstance.getName(), clusterName, line});
                } catch (UnknownHostException ex) {
                    _logger.log(Level.SEVERE,
                            "clb.cannot_open_connection",
                            new Object[]{httpInstance.getName(), clusterName,
                            endPoint.getHost(), endPoint.getPort()});
                    if(_logger.isLoggable(Level.FINE))
                        _logger.log(Level.FINE,
                                "clb.caught_an_exception",
                                ex);

                    break;
                } catch (IOException ex) {
                    if(_logger.isLoggable(Level.FINE))
                        _logger.log(Level.FINE,
                                "clb.caught_an_exception",
                                ex);
                }

                try {
                    Thread.sleep(sleepBetweenRetry);
                } catch (InterruptedException ex) {
                    if(_logger.isLoggable(Level.FINE))
                        _logger.log(Level.FINE,
                                "clb.caught_an_exception",
                                ex);
                }
            }

            if (!httpInstance.isHealthy()) {
                _logger.log(Level.SEVERE,
                        "clb.cannot_mark_instance_healthy",
                        new Object[]{httpInstance.getName(), clusterName});
            }
        }
    }
    */
  
    class CHMGMSEventListenerImpl extends GMSEventListener{

        public CHMGMSEventListenerImpl(String clusterName) throws GMSEventListenerException {
            super(clusterName, !CLBConfigurator.getInstance().isSelfLoadbalanced());
        }

        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});
            }

            /* Commented ping thread mechanism as it is not needed after
             * JoinedAndReadyNotification. However keeping it as a place-holder.
            ServerInstance httpInstance = getServerInstance(clusterName, instanceName, true);
            ServerInstance sipInstance = getServerInstance(clusterName, instanceName, false);
            PingThread pingThread = new PingThread(httpInstance, sipInstance);
            pingThread.start();
             */
            ServerInstance instance = getServerInstance(clusterName, instanceName, true);
            if (instance != null) {
                instance.markAsHealthy(isClusterStartup);
            }
            instance = getServerInstance(clusterName, instanceName, false);
            if (instance != null) {
                instance.markAsHealthy(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});
            }

            ServerInstance instance = getServerInstance(clusterName, instanceName, true);
            if (instance != null) {
                instance.markAsUnhealthy(isClusterShutdown);
            }
            instance = getServerInstance(clusterName, instanceName, false);
            if (instance != null) {
                instance.markAsUnhealthy(isClusterShutdown);
                if(!isClusterShutdown){
                    createTimerTaskForValidation();
                }
            }
        }
       
        private void validateCLBAndGMSSync(String clusterName){
            ServerCluster cluster = CLBConfigurator.getInstance().
                    getHttpControllerInitializer().getController().
                    getCluster(clusterName);
            Collection<ServerInstance> serverInstances =
                    cluster.getAllInstances();
           
            List<String> healthyInstancesInGMS = getHealthyInstances();
            List<String> healthyInstancesInCLB = new ArrayList<String>();
            for(ServerInstance instance:serverInstances){
                if(instance.isHealthy()){
                    healthyInstancesInCLB.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_clb_view",
                        new Object[]{clusterName,
                        healthyInstancesInCLB.toString()});
           
            if(healthyInstancesInCLB.containsAll(healthyInstancesInGMS)
                    && healthyInstancesInGMS.containsAll(healthyInstancesInCLB)){
                _logger.log(Level.INFO, "clb.clb_gms_view_in_sync",
                        new Object[]{clusterName});
            }
            else{
                _logger.log(Level.SEVERE, "clb.clb_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(){
                    validateCLBAndGMSSync(clusterName);
                }
            };
            timer.schedule(timerTask, VALIDATION_WAIT_TIME);
        }

        /*
        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 instance = getServerInstance(clusterName, instanceName, true);
            if (instance != null) {
                instance.disableInstance();
            }
            instance = getServerInstance(clusterName, instanceName, false);
            if (instance != null) {
                instance.disableInstance();
            }
        }

        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 instance = getServerInstance(clusterName, instanceName, true);
            if (instance != null) {
                instance.enableInstance();
            }
            instance = getServerInstance(clusterName, instanceName, false);
            if (instance != null) {
                instance.enableInstance();
            }
        }
        */
    }
}
TOP

Related Classes of org.jvnet.glassfish.comms.clb.core.ClusterHealthMonitor$CHMGMSEventListenerImpl

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.