INT-3212: Fix Failed Tests From CI Builds

JIRA: https://jira.springsource.org/browse/INT-3212

INT-3212 Fix Failing TCP Test

TcpNioConnections can deadlock when a fixed thread pool is being used.
The deadlock is detected after 60 seconds, but the test case failed
after 20 seconds - before the deadlock was detected.

Change the test to use a cached thread pool instead.

Also, increase concurrency by using threading in the test server
so each socket is handled on a separate thread.

Enchance connectionId to include both local and remote ports to
aid debugging.

Some minor formatting corrections.
This commit is contained in:
Artem Bilan
2013-11-20 18:58:45 +02:00
committed by Gary Russell
parent 6b50c49efe
commit 405fce672b
8 changed files with 61 additions and 28 deletions

View File

@@ -125,6 +125,7 @@ public abstract class AbstractConnectionFactory extends IntegrationObjectSupport
this.port = port;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
@@ -413,6 +414,7 @@ public abstract class AbstractConnectionFactory extends IntegrationObjectSupport
*/
public abstract void close();
@Override
public void start() {
if (logger.isInfoEnabled()) {
logger.info("started " + this);
@@ -438,6 +440,7 @@ public abstract class AbstractConnectionFactory extends IntegrationObjectSupport
/**
* Stops the server.
*/
@Override
public void stop() {
this.active = false;
this.close();
@@ -547,7 +550,6 @@ public abstract class AbstractConnectionFactory extends IntegrationObjectSupport
else {
if (logger.isWarnEnabled()) {
logger.warn("Timing out TcpNioConnection " +
this.port + " : " +
connection.getConnectionId());
}
connection.publishConnectionExceptionEvent(new SocketTimeoutException("Timing out connection"));
@@ -581,16 +583,19 @@ public abstract class AbstractConnectionFactory extends IntegrationObjectSupport
connection = (TcpNioConnection) key.attachment();
connection.setLastRead(System.currentTimeMillis());
this.taskExecutor.execute(new Runnable() {
@Override
public void run() {
try {
connection.readPacket();
} catch (Exception e) {
}
catch (Exception e) {
if (connection.isOpen()) {
logger.error("Exception on read " +
connection.getConnectionId() + " " +
e.getMessage());
connection.close();
} else {
}
else {
logger.debug("Connection closed");
}
}
@@ -633,6 +638,7 @@ public abstract class AbstractConnectionFactory extends IntegrationObjectSupport
throw new UnsupportedOperationException("Nio server factory must override this method");
}
@Override
public int getPhase() {
return 0;
}
@@ -641,10 +647,12 @@ public abstract class AbstractConnectionFactory extends IntegrationObjectSupport
* We are controlled by the startup options of
* the bound endpoint.
*/
@Override
public boolean isAutoStartup() {
return false;
}
@Override
public void stop(Runnable callback) {
stop();
callback.run();
@@ -688,6 +696,7 @@ public abstract class AbstractConnectionFactory extends IntegrationObjectSupport
this.removeClosedConnectionsAndReturnOpenConnectionIds();
}
@Override
public boolean isRunning() {
return this.active;
}

View File

@@ -118,15 +118,18 @@ public abstract class TcpConnectionSupport implements TcpConnection {
this.hostAddress = inetAddress.getHostAddress();
if (lookupHost) {
this.hostName = inetAddress.getHostName();
} else {
}
else {
this.hostName = this.hostAddress;
}
}
int port = socket.getPort();
this.connectionId = this.hostName + ":" + port + ":" + UUID.randomUUID().toString();
int localPort = socket.getLocalPort();
this.connectionId = this.hostName + ":" + port + ":" + localPort + ":" + UUID.randomUUID().toString();
try {
this.soLinger = socket.getSoLinger();
} catch (SocketException e) { }
}
catch (SocketException e) { }
this.applicationEventPublisher = applicationEventPublisher;
if (connectionFactoryName != null) {
this.connectionFactoryName = connectionFactoryName;

View File

@@ -35,6 +35,7 @@ import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -805,21 +806,39 @@ public class TcpSendingMessageHandlerTests extends AbstractTcpChannelAdapterTest
final Semaphore semaphore = new Semaphore(0);
final AtomicBoolean done = new AtomicBoolean();
final List<Socket> serverSockets = new ArrayList<Socket>();
Executors.newSingleThreadExecutor().execute(new Runnable() {
final ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Runnable() {
@Override
public void run() {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port, 100);
latch.countDown();
for (int i = 0; i < 100; i++) {
Socket socket = server.accept();
final Socket socket = server.accept();
serverSockets.add(socket);
semaphore.release();
byte[] b = new byte[9];
readFully(socket.getInputStream(), b);
b = ("Reply" + i + "\r\n").getBytes();
socket.getOutputStream().write(b);
socket.close();
final int j = i;
exec.execute(new Runnable() {
@Override
public void run() {
semaphore.release();
byte[] b = new byte[9];
try {
readFully(socket.getInputStream(), b);
b = ("Reply" + j + "\r\n").getBytes();
socket.getOutputStream().write(b);
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
socket.close();
}
catch (IOException e) { }
}
}
});
}
server.close();
} catch (Exception e) {
@@ -836,7 +855,7 @@ public class TcpSendingMessageHandlerTests extends AbstractTcpChannelAdapterTest
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.setSingleUse(true);
ccf.setTaskExecutor(Executors.newFixedThreadPool(100));
ccf.setTaskExecutor(Executors.newCachedThreadPool());
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);

View File

@@ -2,7 +2,7 @@ log4j.rootCategory=WARN, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%c{1} [%t] : %m%n
log4j.appender.stdout.layout.ConversionPattern=%d %c{1} [%t] : %m%n
log4j.category.org.springframework.integration=WARN
log4j.category.org.springframework.integration.ip=WARN