/*
* Copyright (c) 2008-2014 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.security.helpers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Arrays;
import java.io.IOException;
import com.emc.storageos.svcs.errorhandling.resources.APIException;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;
public class ServiceClientRetryFilter extends ClientFilter {
private static final Logger log = LoggerFactory
.getLogger(ServiceClientRetryFilter.class);
private int maxRetries;
private int retryInterval;
public ServiceClientRetryFilter(int maxRetries, int retryInterval) {
log.info("filter created");
if (maxRetries < 0 || retryInterval < 0) {
throw new IllegalArgumentException("Invalid request retries specified.");
}
this.maxRetries = maxRetries;
this.retryInterval = retryInterval;
}
@Override
public ClientResponse handle(ClientRequest clientRequest)
throws ClientHandlerException {
int i = 0;
Throwable cause = null;
int sleepMs = 0;
while (i < maxRetries) {
i++;
try {
ClientResponse response = getNext().handle(clientRequest);
ClientResponse.Status status = response.getClientResponseStatus();
if (status == ClientResponse.Status.UNAUTHORIZED) {
log.error("401 Unauthorized, Please check the secret_key and certificate_chain.");
throw APIException.unauthorized.requestNotAuthorized();
}
if (status != ClientResponse.Status.SERVICE_UNAVAILABLE) {
return response;
}
log.info("remote service is unavailable req={} status={}", clientRequest.getURI(), status);
} catch (ClientHandlerException e) {
StackTraceElement[] stackTrace = e.getStackTrace();
log.info("jersey client error. StackTrace=" + Arrays.toString(stackTrace));
Class clazz = e.getCause().getClass();
if (clazz == ConnectException.class) {
log.info("connection failed: {}", clientRequest.getURI().toString());
} else if (clazz == NoRouteToHostException.class) {
log.info("no route to host: {}", clientRequest.getURI().toString());
} else if (clazz == SocketException.class) {
log.info("socket exception: {}", clientRequest.getURI().toString());
} else if (clazz == SocketTimeoutException.class) {
log.info("socket timeout exception: {}", clientRequest.getURI().toString());
} else if (clazz == IOException.class) {
log.info("IO exception: {}", clientRequest.getURI().toString());
} else {
cause = e;
break;
}
cause = e;
}
sleepMs = (i - 1) * retryInterval;
log.info("request failed, retry {} times", i);
if (sleepMs > 0) {
try {
Thread.sleep(sleepMs);
} catch (InterruptedException ignore) {
log.error("Unexpected Error", ignore);
}
}
}
throw new ClientHandlerException("Request retries limit exceeded.", cause);
}
}