Java tutorial
/** * 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.hadoop.conf.Configuration; import org.apache.hadoop.io.retry.RetryPolicies.MultipleLinearRandomRetry; import org.apache.hadoop.ipc.RemoteException; import com.google.protobuf.ServiceException; import org.apache.hadoop.ipc.RetriableException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RetryUtils { public static final Logger LOG = LoggerFactory.getLogger(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 String remoteExceptionToRetry) { final RetryPolicy multipleLinearRandomRetry = getMultipleLinearRandomRetry(conf, retryPolicyEnabledKey, defaultRetryPolicyEnabled, retryPolicySpecKey, defaultRetryPolicySpec); LOG.debug("multipleLinearRandomRetry = {}", multipleLinearRandomRetry); if (multipleLinearRandomRetry == null) { //no retry return RetryPolicies.TRY_ONCE_THEN_FAIL; } else { return new WrapperRetryPolicy((MultipleLinearRandomRetry) multipleLinearRandomRetry, remoteExceptionToRetry); } } private static final class WrapperRetryPolicy implements RetryPolicy { private MultipleLinearRandomRetry multipleLinearRandomRetry; private String remoteExceptionToRetry; private WrapperRetryPolicy(final MultipleLinearRandomRetry multipleLinearRandomRetry, final String remoteExceptionToRetry) { this.multipleLinearRandomRetry = multipleLinearRandomRetry; this.remoteExceptionToRetry = remoteExceptionToRetry; } @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 RetriableException || RetryPolicies.getWrappedRetriableException(e) != null) { // RetriableException or RetriableException wrapped p = multipleLinearRandomRetry; } else if (e instanceof RemoteException) { final RemoteException re = (RemoteException) e; p = re.getClassName().equals(remoteExceptionToRetry) ? 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; } LOG.debug("RETRY {}) policy={}", retries, p.getClass().getSimpleName(), e); return p.shouldRetry(e, retries, failovers, isMethodIdempotent); } /** * remoteExceptionToRetry is ignored as part of equals since it does not * affect connection failure handling. */ @Override public boolean equals(final Object obj) { if (obj == this) { return true; } else { return (obj instanceof WrapperRetryPolicy) && this.multipleLinearRandomRetry .equals(((WrapperRetryPolicy) obj).multipleLinearRandomRetry); } } /** * Similarly, remoteExceptionToRetry is ignored as part of hashCode since it * does not affect connection failure handling. */ @Override public int hashCode() { return multipleLinearRandomRetry.hashCode(); } @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); } }