org.codice.solr.factory.impl.SolrHttpRequestRetryHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.solr.factory.impl.SolrHttpRequestRetryHandler.java

Source

/**
 * Copyright (c) Codice Foundation
 *
 * <p>This is free software: you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation, either version 3 of
 * the License, or any later version.
 *
 * <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details. A copy of the GNU Lesser General Public
 * License is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 */
package org.codice.solr.factory.impl;

import com.google.common.annotations.VisibleForTesting;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import javax.net.ssl.SSLException;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.time.DurationFormatUtils;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Retry handler for Solr Http requests sent through Http clients.
 *
 * <p>This retry handler will attempt to retry for a maximum of about 2 minutes before failing.
 */
class SolrHttpRequestRetryHandler implements HttpRequestRetryHandler {
    // 30 with 11 retries will make the total attempt last around 2 minutes
    private static final long TIME_FACTOR = 30L;

    private static final int MAX_RETRY_COUNT = 11;

    private static final Logger LOGGER = LoggerFactory.getLogger(SolrHttpRequestRetryHandler.class);

    private final String coreName;

    private final long timeFactor;

    private final int maxRetryCount;

    /**
     * Constructs a retry handler for the specified Solr core.
     *
     * @param coreName the name of the core for which to create a retry handler
     * @throws IllegalArgumentException if <code>coreName</code> is <code>null</code>
     */
    public SolrHttpRequestRetryHandler(String coreName) {
        this(coreName, TIME_FACTOR, MAX_RETRY_COUNT);
    }

    @VisibleForTesting
    SolrHttpRequestRetryHandler(String coreName, long timeFactor, int maxRetryCount) {
        Validate.notNull(coreName, "invalid null core");
        this.coreName = coreName;
        this.timeFactor = timeFactor;
        this.maxRetryCount = maxRetryCount;
    }

    @Override
    @SuppressWarnings("squid:S2274" /* this method is designed to be called from within a loop controlled by the HttpClient*/)
    public boolean retryRequest(IOException e, int retryCount, HttpContext httpContext) {
        LOGGER.debug("Solr({}): Http client connection #{} failed", coreName, retryCount, e);
        if (e instanceof InterruptedIOException) {
            LOGGER.debug("Solr({}): Http client connection I/O interrupted.", coreName);
            Thread.currentThread().interrupt();
            return false;
        }
        if (e instanceof UnknownHostException) {
            LOGGER.warn("Solr({}): Http Client unknown host.", coreName);
        }
        if (e instanceof SSLException) {
            LOGGER.warn("Solr({}): Http client SSL handshake exception", coreName);
        }
        if (retryCount > maxRetryCount) {
            return false;
        }
        try {
            final long waitTime = (long) Math.pow(2, retryCount) * timeFactor;

            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Solr({}): Http client connection failed, waiting {} before retrying.", coreName,
                        DurationFormatUtils.formatDurationHMS(waitTime));
            }
            synchronized (this) {
                wait(waitTime);
            }
        } catch (InterruptedException ie) {
            LOGGER.debug("Solr({}): Http client interrupted while waiting.", coreName);
            Thread.currentThread().interrupt();
            return false;
        }
        return true;
    }
}