com.cisco.oss.foundation.loadbalancer.AbstractLoadBalancerStrategy.java Source code

Java tutorial

Introduction

Here is the source code for com.cisco.oss.foundation.loadbalancer.AbstractLoadBalancerStrategy.java

Source

/*
 * Copyright 2015 Cisco Systems, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.cisco.oss.foundation.loadbalancer;

import com.cisco.oss.foundation.configuration.ConfigurationFactory;
import com.google.common.collect.Lists;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.remoting.RemoteAccessException;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.nio.channels.UnresolvedAddressException;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * This Class is the abstract implementation of the load balancing strategy.
 *
 * @author Yair Ogen
 */
public abstract class AbstractLoadBalancerStrategy<S extends ClientRequest> implements LoadBalancerStrategy<S> {

    protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractLoadBalancerStrategy.class);

    static {
        try {
            Configuration configuration = ConfigurationFactory.getConfiguration();
        } catch (Exception e) {
            LOGGER.error("Can't assign service Directory host and port properties: {}", e, e);
        }
    }
    public static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private static final long serialVersionUID = -4787963395573781601L;
    protected List<InternalServerProxy> serverProxies;
    long waitingTime;
    String clientName;
    long retryDelay;
    int numberOfAttempts;
    private String serviceName = "UNKNOWN";

    public AbstractLoadBalancerStrategy(String serviceName, boolean serviceDirectoryEnabled, long waitingTime,
            String clientName, long retryDelay, int numberOfAttempts) {
        this.serviceName = serviceName;
        this.waitingTime = waitingTime;
        this.clientName = clientName;
        this.retryDelay = retryDelay;
        this.numberOfAttempts = numberOfAttempts;

    }

    public String getServiceName() {
        return serviceName;
    }

    public Throwable handleException(final String apiName, final InternalServerProxy serverProxy,
            final Throwable throwable) {

        // if the caught exception is of timeout nature, audit and throw a new
        // RequestTimeoutException directly to the client
        handleTimeout(apiName, throwable);

        // in these cases only, throw the exception to the caller:
        // 1. if the exception is instanceof NoActiveServersIOException - used
        // in UDP support.
        // 2. if not instanceof RemoteAccessException and not instanceof
        // IOException - in these cases continue trying with the next servers.
        String hostPort = serverProxy != null ? " at [" + serverProxy.getHost() + ":" + serverProxy.getPort() + "]"
                : "";
        String errorMessage = "Failed to invoke  '" + apiName + "' " + hostPort;
        String warnMessage = "Error occurred while invoking '" + apiName + "' " + hostPort;

        if (throwable instanceof UnresolvedAddressException) {
            LOGGER.debug("retrying in special case of 'UnresolvedAddressException'");
        } else {

            //         final boolean firstInChain = ConfigurationFactory.getConfiguration().getBoolean(LoadBalancerConstants.DEFAULT_FIRST_IN_CHAIN);

            // don't try and find another active server if:
            // 1. the exception you caught is NoActiveServersDeadEndException
            // 2. the exception you caught is NoActiveServersIOException
            // 3. the exception you caught is (not RemoteAccessException) and
            // (not IOException) and (not NoActiveServersException but is
            // firstInChain)
            // if you caught NoActiveServersException but you are NOT
            // firstInChain - then throw back error and don't try to reconnect
            if (throwable instanceof NoActiveServersDeadEndException
                    || throwable instanceof NoActiveServersIOException
                    || (!(throwable instanceof RemoteAccessException)
                            && !(throwable instanceof NoActiveServersException)
                            && !(throwable instanceof IOException)
                            && (throwable.getCause() != null && throwable.getCause().getCause() != null
                                    && !(throwable.getCause().getCause() instanceof IOException))
                            && (throwable.getCause() != null && !(throwable.getCause() instanceof IOException))
                            || (/*!firstInChain &&*/ throwable instanceof NoActiveServersException))) {
                LOGGER.error(errorMessage, throwable);
                throw new ClientException(throwable.toString(), throwable);
            }
        }

        if (LOGGER.isDebugEnabled()) {
            LOGGER.warn(warnMessage + "(attempt " + serverProxy.getCurrentNumberOfAttempts() + ", will retry in "
                    + serverProxy.getRetryDelay() + " milliseconds)", throwable);
        } else {
            LOGGER.warn(warnMessage + "(attempt " + serverProxy.getCurrentNumberOfAttempts() + ", will retry in "
                    + serverProxy.getRetryDelay() + " milliseconds)");
        }

        serverProxy.processFailureAttempt();

        if (serverProxy.getCurrentNumberOfAttempts() >= serverProxy.getMaxNumberOfAttempts()) {
            serverProxy.passivate();
        }

        return throwable;
    }

    private void handleTimeout(final String apiName, final Throwable throwable) {
        if (throwable instanceof RequestTimeoutException) {
            throw (RequestTimeoutException) throwable;
        } else if (throwable instanceof SocketTimeoutException
                || (throwable != null && throwable.getMessage() != null
                        && (throwable.getMessage().contains("Inactivity timeout passed during read operation")
                                || (throwable.getCause() instanceof SocketTimeoutException)))) {

            final RequestTimeoutException requestTimeoutException = new RequestTimeoutException(
                    "Error occurred while invoking the api: " + apiName, throwable.getCause());

            LOGGER.warn(requestTimeoutException.toString(), requestTimeoutException);

            throw requestTimeoutException;
        }
    }

    public void handleNullserverProxy(final String apiName, final Throwable lastCaugtException) {

        final String causedBy = lastCaugtException != null ? ("\"Caused by: " + lastCaugtException) : "\"";
        final NoActiveServersException noActiveServersException = new NoActiveServersException(
                "No active servers were found in the server proxies list. API: \"" + apiName + "\"." + causedBy,
                lastCaugtException);

        if (this instanceof FailOverStrategy) {
            FailOverStrategy failOverStrategy = (FailOverStrategy) this;
            failOverStrategy.lastActive = null;
        }

        throw noActiveServersException;

    }

    public List<InternalServerProxy> getServerProxies() {
        return serverProxies;
    }

    @Override
    public void setServerProxies(final List<InternalServerProxy> serverProxies) {
        this.serverProxies = serverProxies;
    }

    private InternalServerProxy createInternalServerProxy(String host, int port) {
        final InternalServerProxy internalServerProxy = new InternalServerProxy(waitingTime, clientName);
        internalServerProxy.setRetryDelay(retryDelay);
        internalServerProxy.setMaxNumberOfAttempts(numberOfAttempts);
        internalServerProxy.setHost(host);
        internalServerProxy.setPort(port);
        return internalServerProxy;
    }

}