/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.hadoop.io.retry; import java.io.IOException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.ipc.RemoteException; import com.google.protobuf.ServiceException; public class RetryUtils { public static final Log LOG = LogFactory.getLog(RetryUtils.class); /** * Return the default retry policy set in conf. * * If the value retryPolicyEnabledKey is set to false in conf, * use TRY_ONCE_THEN_FAIL. * * Otherwise, get the MultipleLinearRandomRetry policy specified in the conf * and then * (1) use multipleLinearRandomRetry for * - remoteExceptionToRetry, or * - IOException other than RemoteException, or * - ServiceException; and * (2) use TRY_ONCE_THEN_FAIL for * - non-remoteExceptionToRetry RemoteException, or * - non-IOException. * * * @param conf * @param retryPolicyEnabledKey conf property key for enabling retry * @param defaultRetryPolicyEnabled default retryPolicyEnabledKey conf value * @param retryPolicySpecKey conf property key for retry policy spec * @param defaultRetryPolicySpec default retryPolicySpecKey conf value * @param remoteExceptionToRetry The particular RemoteException to retry * @return the default retry policy. */ public static RetryPolicy getDefaultRetryPolicy( Configuration conf, String retryPolicyEnabledKey, boolean defaultRetryPolicyEnabled, String retryPolicySpecKey, String defaultRetryPolicySpec, final Class<? extends Exception> remoteExceptionToRetry ) { final RetryPolicy multipleLinearRandomRetry = getMultipleLinearRandomRetry( conf, retryPolicyEnabledKey, defaultRetryPolicyEnabled, retryPolicySpecKey, defaultRetryPolicySpec ); if (LOG.isDebugEnabled()) { LOG.debug("multipleLinearRandomRetry = " + multipleLinearRandomRetry); } if (multipleLinearRandomRetry == null) { //no retry return RetryPolicies.TRY_ONCE_THEN_FAIL; } else { return new RetryPolicy() { @Override public RetryAction shouldRetry(Exception e, int retries, int failovers, boolean isMethodIdempotent) throws Exception { if (e instanceof ServiceException) { //unwrap ServiceException final Throwable cause = e.getCause(); if (cause != null && cause instanceof Exception) { e = (Exception)cause; } } //see (1) and (2) in the javadoc of this method. final RetryPolicy p; if (e instanceof RemoteException) { final RemoteException re = (RemoteException)e; p = remoteExceptionToRetry.getName().equals(re.getClassName())? multipleLinearRandomRetry: RetryPolicies.TRY_ONCE_THEN_FAIL; } else if (e instanceof IOException || e instanceof ServiceException) { p = multipleLinearRandomRetry; } else { //non-IOException p = RetryPolicies.TRY_ONCE_THEN_FAIL; } if (LOG.isDebugEnabled()) { LOG.debug("RETRY " + retries + ") policy=" + p.getClass().getSimpleName() + ", exception=" + e); } LOG.info("RETRY " + retries + ") policy=" + p.getClass().getSimpleName() + ", exception=" + e); return p.shouldRetry(e, retries, failovers, isMethodIdempotent); } @Override public String toString() { return "RetryPolicy[" + multipleLinearRandomRetry + ", " + RetryPolicies.TRY_ONCE_THEN_FAIL.getClass().getSimpleName() + "]"; } }; } } /** * Return the MultipleLinearRandomRetry policy specified in the conf, * or null if the feature is disabled. * If the policy is specified in the conf but the policy cannot be parsed, * the default policy is returned. * * Retry policy spec: * N pairs of sleep-time and number-of-retries "s1,n1,s2,n2,..." * * @param conf * @param retryPolicyEnabledKey conf property key for enabling retry * @param defaultRetryPolicyEnabled default retryPolicyEnabledKey conf value * @param retryPolicySpecKey conf property key for retry policy spec * @param defaultRetryPolicySpec default retryPolicySpecKey conf value * @return the MultipleLinearRandomRetry policy specified in the conf, * or null if the feature is disabled. */ public static RetryPolicy getMultipleLinearRandomRetry( Configuration conf, String retryPolicyEnabledKey, boolean defaultRetryPolicyEnabled, String retryPolicySpecKey, String defaultRetryPolicySpec ) { final boolean enabled = conf.getBoolean(retryPolicyEnabledKey, defaultRetryPolicyEnabled); if (!enabled) { return null; } final String policy = conf.get(retryPolicySpecKey, defaultRetryPolicySpec); final RetryPolicy r = RetryPolicies.MultipleLinearRandomRetry.parseCommaSeparatedString( policy); return (r != null) ? r : RetryPolicies.MultipleLinearRandomRetry.parseCommaSeparatedString( defaultRetryPolicySpec); } }