/**
* Licensed to Cloudera, Inc. under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Cloudera, Inc. 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 com.cloudera.util;
/**
* Wraps the retry logic associated with a BackoffPolicy to
* save having to write driver code.
*/
public class RetryHarness {
Retryable retry;
BackoffPolicy policy;
Exception lastException = null;
boolean throwOnFailure = false;
volatile boolean abort = false;
public RetryHarness(Retryable retry, BackoffPolicy policy) {
this.retry = retry;
this.policy = policy;
retry.setHarness(this);
}
public RetryHarness(Retryable retry, BackoffPolicy policy, boolean throwOnFailure) {
this.retry = retry;
this.policy = policy;
this.throwOnFailure = throwOnFailure;
retry.setHarness(this);
}
/**
* Returns the last exception thrown by the Retryable (or null if there was
* none)
*/
public Exception getLastException() {
return lastException;
}
/**
* Calls doTry on a Retryable until either it succeeds or the backoff policy
* fails.
*/
public boolean attempt() throws Exception {
boolean success = false;
abort = false;
policy.reset();
while (!abort && !policy.isFailed()) {
policy.waitUntilRetryOk();
try {
if (policy.isRetryOk()) {
success = retry.doTry();
if (success) {
return true;
}
}
} catch (Exception e) {
lastException = e;
}
policy.backoff();
}
if (throwOnFailure && lastException != null) {
throw lastException;
}
return false;
}
public void doAbort() {
abort = true;
}
}