blob: 85bd5981997bc5ff360b1be3f0540a3c39b2231b [file] [log] [blame]
/**
* 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 javax.security.sasl.SaslException;
import org.apache.hadoop.ipc.RemoteException;
import org.apache.hadoop.ipc.StandbyException;
class UnreliableImplementation implements UnreliableInterface {
private int failsOnceInvocationCount,
failsOnceWithValueInvocationCount,
failsOnceIOExceptionInvocationCount,
failsOnceRemoteExceptionInvocationCount,
failsTenTimesInvocationCount,
failsWithSASLExceptionTenTimesInvocationCount,
succeedsOnceThenFailsCount,
succeedsOnceThenFailsIdempotentCount,
succeedsTenTimesThenFailsCount;
private String identifier;
private TypeOfExceptionToFailWith exceptionToFailWith;
public static enum TypeOfExceptionToFailWith {
UNRELIABLE_EXCEPTION,
STANDBY_EXCEPTION,
IO_EXCEPTION,
REMOTE_EXCEPTION
}
public UnreliableImplementation() {
this(null);
}
public UnreliableImplementation(String identifier) {
this(identifier, TypeOfExceptionToFailWith.UNRELIABLE_EXCEPTION);
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public UnreliableImplementation(String identifier,
TypeOfExceptionToFailWith exceptionToFailWith) {
this.identifier = identifier;
this.exceptionToFailWith = exceptionToFailWith;
}
@Override
public void alwaysSucceeds() {
// do nothing
}
@Override
public void alwaysFailsWithFatalException() throws FatalException {
throw new FatalException();
}
@Override
public void alwaysFailsWithRemoteFatalException() throws RemoteException {
throw new RemoteException(FatalException.class.getName(), "Oops");
}
@Override
public void failsOnceThenSucceeds() throws UnreliableException {
if (failsOnceInvocationCount++ == 0) {
throw new UnreliableException();
}
}
@Override
public boolean failsOnceThenSucceedsWithReturnValue() throws UnreliableException {
if (failsOnceWithValueInvocationCount++ == 0) {
throw new UnreliableException();
}
return true;
}
@Override
public void failsOnceWithIOException() throws IOException {
if (failsOnceIOExceptionInvocationCount++ == 0) {
throw new IOException("test exception for failsOnceWithIOException");
}
}
@Override
public void failsOnceWithRemoteException() throws RemoteException {
if (failsOnceRemoteExceptionInvocationCount++ == 0) {
throw new RemoteException(IOException.class.getName(),
"test exception for failsOnceWithRemoteException");
}
}
@Override
public void failsTenTimesThenSucceeds() throws UnreliableException {
if (failsTenTimesInvocationCount++ < 10) {
throw new UnreliableException();
}
}
@Override
public void failsWithSASLExceptionTenTimes() throws SaslException {
if (failsWithSASLExceptionTenTimesInvocationCount ++ < 10) {
throw new SaslException();
}
}
@Override
public String succeedsOnceThenFailsReturningString()
throws UnreliableException, IOException, StandbyException {
if (succeedsOnceThenFailsCount++ < 1) {
return identifier;
} else {
throwAppropriateException(exceptionToFailWith, identifier);
return null;
}
}
@Override
public String succeedsTenTimesThenFailsReturningString()
throws UnreliableException, IOException, StandbyException {
if (succeedsTenTimesThenFailsCount++ < 10) {
return identifier;
} else {
throwAppropriateException(exceptionToFailWith, identifier);
return null;
}
}
@Override
public String succeedsOnceThenFailsReturningStringIdempotent()
throws UnreliableException, StandbyException, IOException {
if (succeedsOnceThenFailsIdempotentCount++ < 1) {
return identifier;
} else {
throwAppropriateException(exceptionToFailWith, identifier);
return null;
}
}
@Override
public String failsIfIdentifierDoesntMatch(String identifier)
throws UnreliableException, StandbyException, IOException {
if (this.identifier.equals(identifier)) {
return identifier;
} else {
String message = "expected '" + this.identifier + "' but received '" +
identifier + "'";
throwAppropriateException(exceptionToFailWith, message);
return null;
}
}
@Override
public void nonIdempotentVoidFailsIfIdentifierDoesntMatch(String identifier)
throws UnreliableException, StandbyException, IOException {
if (this.identifier.equals(identifier)) {
return;
} else {
String message = "expected '" + this.identifier + "' but received '" +
identifier + "'";
throwAppropriateException(exceptionToFailWith, message);
}
}
@Override
public String toString() {
return getClass().getSimpleName() + "[" + identifier + "]";
}
private static void throwAppropriateException(TypeOfExceptionToFailWith eType,
String message) throws UnreliableException, StandbyException, IOException {
switch (eType) {
case STANDBY_EXCEPTION:
throw new StandbyException(message);
case UNRELIABLE_EXCEPTION:
throw new UnreliableException(message);
case IO_EXCEPTION:
throw new IOException(message);
case REMOTE_EXCEPTION:
throw new RemoteException(IOException.class.getName(), message);
default:
throw new RuntimeException(message);
}
}
}