10000 Rewrite UDP/TCP clients to use NIO and built-in worker threads · dnsjava/dnsjava@629f2eb · GitHub
[go: up one dir, main page]

Skip to content

Commit 629f2eb

Browse files
committed
Rewrite UDP/TCP clients to use NIO and built-in worker threads
Closes #25 Closes #41 Closes #74
1 parent 4867139 commit 629f2eb

13 files changed

+1025
-661
lines changed

src/main/java/org/xbill/DNS/Client.java

Lines changed: 60 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,69 +4,89 @@
44

55
import java.io.IOException;
66
import java.net.SocketAddress;
7-
import java.net.SocketTimeoutException;
8-
import java.nio.channels.SelectableChannel;
97
import java.nio.channels.SelectionKey;
108
import java.nio.channels.Selector;
9+
import java.util.List;
10+
import java.util.Set;
11+
import java.util.concurrent.CopyOnWriteArrayList;
1112
import lombok.extern.slf4j.Slf4j;
1213
import org.xbill.DNS.utils.hexdump;
1314

1415
@Slf4j
1516
class Client {
16-
17-
protected long endTime;
18-
protected SelectionKey key;
19-
2017
/** Packet logger, if available. */
2118
private static PacketLogger packetLogger = null;
2219

23-
protected Client(SelectableChannel channel, long endTime) throws IOException {
24-
boolean done = false;
25-
Selector selector = null;
26-
this.endTime = endTime;
27-
try {
28-
selector = Selector.open();
29-
channel.configureBlocking(false);
30-
key = channel.register(selector, SelectionKey.OP_READ);
31-
done = true;
32-
} finally {
33-
if (!done && selector != null) {
34-
selector.close();
35-
}
36-
if (!done) {
37-
channel.close();
38-
}
20+
private static volatile boolean run;
21+
private static Thread selectorThread;
22+
private static List<Runnable> timeoutTasks = new CopyOnWriteArrayList<>();
23+
static Selector selector;
24+
25+
protected interface KeyProcessor {
26+
void processReadyKey(SelectionKey key);
27+
}
28+
29+
protected static void start() throws IOException {
30+
if (run) {
31+
return;
32+
}
33+
34+
run = true;
35+
selector = Selector.open();
36+
selectorThread = new Thread(Client::runSelector);
37+
selectorThread.setDaemon(true);
38+
selectorThread.setName("dnsjava NIO selector");
39+
selectorThread.start();
40+
}
41+
42+
protected static void close() throws Exception {
43+
if (!run) {
44+
return;
3945
}
46+
47+
run = false;
48+
timeoutTasks.clear();
49+
selector.wakeup();
50+
selector.close();
51+
selectorThread.join();
4052
}
4153

42-
protected static void blockUntil(SelectionKey key, long endTime) throws IOException {
43-
long timeout = endTime - System.currentTimeMillis();
44-
int nkeys = 0;
45-
if (timeout > 0) {
46-
nkeys = key.selector().select(timeout);
47-
} else if (timeout == 0) {
48-
nkeys = key.selector().selectNow();
54+
private static void runSelector() {
55+
while (run) {
56+
try {
57+
if (selector.select(100) == 0) {
58+
timeoutTasks.forEach(Runnable::run);
59+
continue;
60+
}
61+
62+
processReadyKeys();
63+
} catch (IOException e) {
64+
log.error("A selection operation failed", e);
65+
}
4966
}
50-
if (nkeys == 0) {
51-
throw new SocketTimeoutException();
67+
}
68+
69+
static void addSelectorTimeoutTask(Runnable r) {
70+
timeoutTasks.add(r);
71+
}
72+
73+
private static void processReadyKeys() {
74+
Set<SelectionKey> keys = selector.selectedKeys();
75+
for (SelectionKey key : keys) {
76+
KeyProcessor t = (KeyProcessor) key.attachment();
77+
t.processReadyKey(key);
5278
}
5379
}
5480

55-
protected static void verboseLog(
56-
String prefix, SocketAddress local, SocketAddress remote, byte[] data) {
57-
if (log.isDebugEnabled()) {
58-
log.debug(hexdump.dump(prefix, data));
81+
static void verboseLog(String prefix, SocketAddress local, SocketAddress remote, byte[] data) {
82+
if (log.isTraceEnabled()) {
83+
log.trace(hexdump.dump(prefix, data));
5984
}
6085
if (packetLogger != null) {
6186
packetLogger.log(prefix, local, remote, data);
6287
}
6388
}
6489

65-
void cleanup() throws IOException {
66-
key.selector().close();
67-
key.channel().close();
68-
}
69-
7090
static void setPacketLogger(PacketLogger logger) {
7191
packetLogger = logger;
7292
}

0 commit comments

Comments
 (0)
0