|
@@ -0,0 +1,164 @@
|
|
|
+/**
|
|
|
+ * 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);
|
|
|
+ }
|
|
|
+}
|