mirror of https://github.com/apache/jclouds.git
make it explicit we are not going to retry on a general sftp failure
This commit is contained in:
parent
d5caa414b1
commit
0b60ccf5ac
|
@ -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.instanceOf;
|
||||||
import static com.google.common.base.Predicates.or;
|
import static com.google.common.base.Predicates.or;
|
||||||
import static com.google.common.base.Throwables.getCausalChain;
|
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 static com.google.common.collect.Iterables.any;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -53,7 +52,6 @@ import org.jclouds.util.Strings2;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.io.Closeables;
|
import com.google.common.io.Closeables;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.jcraft.jsch.ChannelExec;
|
import com.jcraft.jsch.ChannelExec;
|
||||||
|
@ -296,8 +294,9 @@ public class JschSshClient implements SshClient {
|
||||||
@Override
|
@Override
|
||||||
public Void create() throws Exception {
|
public Void create() throws Exception {
|
||||||
sftp = acquire(sftpConnection);
|
sftp = acquire(sftpConnection);
|
||||||
|
InputStream is = checkNotNull(contents.getInput(), "inputstream for path %s", path);
|
||||||
try {
|
try {
|
||||||
sftp.put(checkNotNull(contents.getInput(), "inputstream for path %s", path), path);
|
sftp.put(is, path);
|
||||||
} finally {
|
} finally {
|
||||||
Closeables.closeQuietly(contents);
|
Closeables.closeQuietly(contents);
|
||||||
clear();
|
clear();
|
||||||
|
@ -318,20 +317,29 @@ public class JschSshClient implements SshClient {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean shouldRetry(Exception from) {
|
boolean shouldRetry(Exception from) {
|
||||||
final String rootMessage = getRootCause(from).getMessage();
|
|
||||||
if (rootMessage == null)
|
|
||||||
return false;
|
|
||||||
return any(getCausalChain(from), retryPredicate)
|
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
|
@Override
|
||||||
public boolean apply(String input) {
|
public boolean apply(final String input) {
|
||||||
return rootMessage.indexOf(input) != -1;
|
return any(getCausalChain(from), new Predicate<Throwable>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Throwable arg0) {
|
||||||
|
return arg0.getMessage() != null && arg0.getMessage().indexOf(input) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private void backoffForAttempt(int retryAttempt, String message) {
|
private void backoffForAttempt(int retryAttempt, String message) {
|
||||||
backoffLimitedRetryHandler.imposeBackoffExponentialDelay(200L, 2, retryAttempt, sshRetries, message);
|
backoffLimitedRetryHandler.imposeBackoffExponentialDelay(200L, 2, retryAttempt, sshRetries, message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,9 @@ import org.testng.annotations.Test;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
import com.jcraft.jsch.ChannelSftp;
|
||||||
import com.jcraft.jsch.JSchException;
|
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("io error", new IOException("socket closed")));
|
||||||
assert ssh.shouldRetry(new JSchException("connect error", new ConnectException("problem")));
|
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: invalid data"));
|
||||||
assert ssh.shouldRetry(new JSchException("Session.connect: java.net.SocketException: Connection reset"));
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue