make it explicit we are not going to retry on a general sftp failure

This commit is contained in:
Adrian Cole 2011-07-23 15:33:50 +10:00
parent d5caa414b1
commit 0b60ccf5ac
2 changed files with 38 additions and 10 deletions

View File

@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.base.Predicates.or;
import static com.google.common.base.Throwables.getCausalChain;
import static com.google.common.base.Throwables.getRootCause;
import static com.google.common.collect.Iterables.any;
import java.io.IOException;
@ -53,7 +52,6 @@ import org.jclouds.util.Strings2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.io.Closeables;
import com.google.inject.Inject;
import com.jcraft.jsch.ChannelExec;
@ -244,7 +242,7 @@ public class JschSshClient implements SshClient {
public void throwChannelNotOpenExceptionOrPropagate(String channel, JSchException e) throws JSchException {
if (e.getMessage().indexOf("channel is not opened") != -1)
throw new ChannelNotOpenException(String.format("(%s) channel %s is not open", toString() , channel), e);
throw new ChannelNotOpenException(String.format("(%s) channel %s is not open", toString(), channel), e);
}
class GetConnection implements Connection<Payload> {
@ -296,8 +294,9 @@ public class JschSshClient implements SshClient {
@Override
public Void create() throws Exception {
sftp = acquire(sftpConnection);
InputStream is = checkNotNull(contents.getInput(), "inputstream for path %s", path);
try {
sftp.put(checkNotNull(contents.getInput(), "inputstream for path %s", path), path);
sftp.put(is, path);
} finally {
Closeables.closeQuietly(contents);
clear();
@ -318,18 +317,27 @@ public class JschSshClient implements SshClient {
@VisibleForTesting
boolean shouldRetry(Exception from) {
final String rootMessage = getRootCause(from).getMessage();
if (rootMessage == null)
return false;
return any(getCausalChain(from), retryPredicate)
|| Iterables.any(Splitter.on(",").split(retryableMessages), new Predicate<String>() {
|| any(Splitter.on(",").split(retryableMessages), causalChainHasMessageContaining(from));
}
@VisibleForTesting
Predicate<String> causalChainHasMessageContaining(final Exception from) {
return new Predicate<String>() {
@Override
public boolean apply(final String input) {
return any(getCausalChain(from), new Predicate<Throwable>() {
@Override
public boolean apply(String input) {
return rootMessage.indexOf(input) != -1;
public boolean apply(Throwable arg0) {
return arg0.getMessage() != null && arg0.getMessage().indexOf(input) != -1;
}
});
}
};
}
private void backoffForAttempt(int retryAttempt, String message) {

View File

@ -32,7 +32,9 @@ import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
/**
*
@ -64,6 +66,8 @@ public class JschSshClientTest {
assert ssh.shouldRetry(new JSchException("io error", new IOException("socket closed")));
assert ssh.shouldRetry(new JSchException("connect error", new ConnectException("problem")));
assert ssh.shouldRetry(new IOException("channel %s is not open", new NullPointerException()));
assert ssh.shouldRetry(new IOException("channel %s is not open", new NullPointerException(null)));
}
@ -72,4 +76,20 @@ public class JschSshClientTest {
assert ssh.shouldRetry(new JSchException("Session.connect: invalid data"));
assert ssh.shouldRetry(new JSchException("Session.connect: java.net.SocketException: Connection reset"));
}
public void testDoNotRetryOnGeneralSftpError() {
// http://sourceforge.net/mailarchive/forum.php?thread_name=CAARMrHVhASeku48xoAgWEb-nEpUuYkMA03PoA5TvvFdk%3DjGKMA%40mail.gmail.com&forum_name=jsch-users
assert !ssh.shouldRetry(new SftpException(ChannelSftp.SSH_FX_FAILURE, new NullPointerException().toString()));
}
public void testCausalChainHasMessageContaining() {
assert ssh.causalChainHasMessageContaining(
new JSchException("Session.connect: java.io.IOException: End of IO Stream Read")).apply(
" End of IO Stream Read");
assert ssh.causalChainHasMessageContaining(new JSchException("Session.connect: invalid data")).apply(
" invalid data");
assert ssh.causalChainHasMessageContaining(
new JSchException("Session.connect: java.net.SocketException: Connection reset")).apply("java.net.Socket");
assert !ssh.causalChainHasMessageContaining(new NullPointerException()).apply(" End of IO Stream Read");
}
}