提交 a1f890af authored 作者: Thomas Mueller's avatar Thomas Mueller

A workaround for a Windows socket problem has been implemented.

上级 43c91a62
......@@ -18,7 +18,8 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>The Recover tool did not convert correctly convert CLOB data with non-ASCII characters.
<ul><li>A workaround for a Windows socket problem has been implemented. Thanks a lot to Sergi Vladykin.
</li><li>The Recover tool did not convert correctly convert CLOB data with non-ASCII characters.
</li><li>Tools: the method run(String... args) has been renamed to runTool(String... args)
so it can't be confused with run().
</li><li>Server.startWebServer(Connection) was not working as expected.
......
......@@ -496,6 +496,14 @@ public class SysProperties {
*/
public static final boolean SHARE_LINKED_CONNECTIONS = getBooleanSetting("h2.shareLinkedConnections", true);
/**
* System property <code>h2.socketConnectRetry</code> (default: 16).<br />
* The number of times to retry opening a socket. Windows sometimes fails
* to open a socket, see bug
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213296
*/
public static final int SOCKET_CONNECT_RETRY = getIntSetting("h2.socketConnectRetry", 16);
/**
* System property <code>h2.socketConnectTimeout</code> (default: 2000).<br />
* The timeout in milliseconds to connect to a server.
......
......@@ -102,7 +102,7 @@ public class NetUtils {
* @return the socket
*/
public static Socket createSocket(InetAddress address, int port, boolean ssl) throws IOException {
for (;;) {
for (int i = 0;; i++) {
try {
if (ssl) {
return SecureSocketFactory.createSocket(address, port);
......@@ -112,9 +112,17 @@ public class NetUtils {
SysProperties.SOCKET_CONNECT_TIMEOUT);
return socket;
} catch (BindException e) {
// Workaround for Windows problem with frequent connections:
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213296
// trying to connect again
if (i >= SysProperties.SOCKET_CONNECT_RETRY) {
throw e;
}
// wait a bit and retry
try {
// sleep at most 256 ms
long sleep = Math.min(256, i * i);
Thread.sleep(sleep);
} catch (InterruptedException e2) {
// ignore
}
}
}
}
......
/**
*
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: Sergi Vladykin
*/
package org.h2.test.unit;
......@@ -9,126 +12,114 @@ import java.net.Socket;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.h2.engine.Constants;
import org.h2.test.TestBase;
import org.h2.util.NetUtils;
/**
* Test the network utilities.
*
* @author Sergi Vladykin
*/
public class TestNetUtils extends TestBase {
private static final int PORT = 9111;
/**
* @param args
* Run just this test.
*
* @param a ignored
*/
public static void main(String[] args) throws Exception {
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
@Override
public void test() throws Exception {
testFrequentConnections(false);
testFrequentConnections(true);
testFrequentConnections(false, 1000);
testFrequentConnections(true, 100);
testFrequentConnections(false, 1000);
testFrequentConnections(true, 100);
}
private void testFrequentConnections(boolean ssl) throws Exception {
final ServerSocket serverSock = NetUtils.createServerSocket(Constants.DEFAULT_TCP_PORT, ssl);
private void testFrequentConnections(boolean ssl, int count) throws Exception {
final ServerSocket serverSocket = NetUtils.createServerSocket(PORT, ssl);
final AtomicInteger counter = new AtomicInteger(count);
Thread serverThread = new Thread() {
@Override
public void run() {
while (!isInterrupted()) {
try {
Socket socket = serverSock.accept();
Socket socket = serverSocket.accept();
System.out.println("opened " + counter);
socket.close();
} catch (Exception e) {
// ignore
}
}
System.out.println("stopped ");
}
};
serverThread.start();
// System.out.println("Server started.");
AtomicInteger counter = new AtomicInteger();
try {
Set<ConnectWorker> workers = new HashSet<ConnectWorker>();
for (int i = 0; i < 10; i++) {
workers.add(new ConnectWorker(ssl, workers, counter));
for (int i = 0; i < 1; i++) {
workers.add(new ConnectWorker(ssl, counter));
}
// ensure the server is started
Thread.sleep(100);
for (ConnectWorker worker : workers) {
worker.start();
}
// System.out.println("Workers started.");
Exception exception = null;
for (ConnectWorker worker : workers) {
worker.join();
if (exception == null) {
exception = worker.getException();
// if (exception != null) {
// System.out.println("Exception set.");
// }
}
Exception e = worker.getException();
if (e != null) {
e.printStackTrace();
}
// System.out.println("All joined.");
if (exception != null) {
throw exception;
}
} finally {
serverThread.interrupt();
try {
serverSock.close();
serverSocket.close();
} catch (Exception e) {
// ignore
}
// System.out.println("Server stopped.");
serverThread.interrupt();
serverThread.join();
}
}
/**
*
* A worker thread to test connecting.
*/
private class ConnectWorker extends Thread {
private static final int MAX_CONNECT_COUNT = 10000;
private final boolean ssl;
private final Set<ConnectWorker> workers;
private final AtomicInteger counter;
private Exception exception;
private volatile Exception exception;
public ConnectWorker(boolean ssl, Set<ConnectWorker> workers, AtomicInteger counter) {
public ConnectWorker(boolean ssl, AtomicInteger counter) {
this.ssl = ssl;
this.workers = workers;
this.counter = counter;
}
@Override
public void run() {
try {
while (!isInterrupted() && counter.incrementAndGet() < MAX_CONNECT_COUNT) {
Socket sock = NetUtils.createSocket("127.0.0.1", Constants.DEFAULT_TCP_PORT, ssl);
// System.out.println(COUNTER.get());
while (!isInterrupted() && counter.decrementAndGet() > 0) {
Socket socket = NetUtils.createLoopbackSocket(PORT, ssl);
try {
sock.close();
socket.close();
} catch (IOException e) {
// ignore
}
}
} catch (Exception e) {
this.exception = e;
for (ConnectWorker worker : workers) {
worker.interrupt();
}
exception = new Exception("count: " + counter, e);
}
}
/**
* @return the exception
*/
public Exception getException() {
return exception;
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论