Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreutarass2009-12-14 18:21:26 +0000
committereutarass2009-12-14 18:21:26 +0000
commit80f3c11be6435ed1b429e0020d7637d2e2fab2cc (patch)
treed72f13244646fa35dfd2cd2679a9026802143d90
parent5e05cc24fe8303d8fc01747f61e155d63f2aabd3 (diff)
downloadorg.eclipse.tcf-80f3c11be6435ed1b429e0020d7637d2e2fab2cc.tar.gz
org.eclipse.tcf-80f3c11be6435ed1b429e0020d7637d2e2fab2cc.tar.xz
org.eclipse.tcf-80f3c11be6435ed1b429e0020d7637d2e2fab2cc.zip
TCF Core: fixed: calling InetAddress.getByName() from dispatch thread can block TCF dispatch for long time in case of lame DNS server.
Now discovery uses separate thread to perform DNS lookup.
-rw-r--r--plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java114
1 files changed, 103 insertions, 11 deletions
diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java
index 952731ffb..98c6d68bd 100644
--- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java
+++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java
@@ -141,12 +141,26 @@ public class LocatorService implements ILocator {
}
}
+ private static class AddressCacheItem {
+ final String host;
+ InetAddress address;
+ long time_stamp;
+ boolean used;
+
+ AddressCacheItem(String host) {
+ this.host = host;
+ }
+ }
+
+ private static final HashMap<String,AddressCacheItem> addr_cache = new HashMap<String,AddressCacheItem>();
+ private static boolean addr_request;
+
private static LocalPeer local_peer;
private DatagramSocket socket;
private long last_master_packet_time;
- private Thread timer_thread = new Thread() {
+ private final Thread timer_thread = new Thread() {
public void run() {
while (true) {
try {
@@ -162,13 +176,59 @@ public class LocatorService implements ILocator {
return;
}
catch (Throwable x) {
- Protocol.log("Unhandled exception in TCF discovery listening thread", x);
+ Protocol.log("Unhandled exception in TCF discovery timer thread", x);
}
}
}
};
- private Thread input_thread = new Thread() {
+ private Thread dns_lookup_thread = new Thread() {
+ public void run() {
+ while (true) {
+ try {
+ long time;
+ HashSet<AddressCacheItem> set = null;
+ synchronized (addr_cache) {
+ if (!addr_request) addr_cache.wait(DATA_RETENTION_PERIOD);
+ time = System.currentTimeMillis();
+ for (Iterator<AddressCacheItem> i = addr_cache.values().iterator(); i.hasNext();) {
+ AddressCacheItem a = i.next();
+ if (a.time_stamp + DATA_RETENTION_PERIOD * 10 < time) {
+ if (a.used) {
+ if (set == null) set = new HashSet<AddressCacheItem>();
+ set.add(a);
+ }
+ else {
+ i.remove();
+ }
+ }
+ }
+ addr_request = false;
+ }
+ if (set != null) {
+ for (AddressCacheItem a : set) {
+ InetAddress addr = null;
+ try {
+ addr = InetAddress.getByName(a.host);
+ }
+ catch (UnknownHostException x) {
+ }
+ synchronized (addr_cache) {
+ a.address = addr;
+ a.time_stamp = time;
+ a.used = false;
+ }
+ }
+ }
+ }
+ catch (Throwable x) {
+ Protocol.log("Unhandled exception in TCF discovery DNS lookup thread", x);
+ }
+ }
+ }
+ };
+
+ private final Thread input_thread = new Thread() {
public void run() {
for (;;) {
DatagramSocket socket = LocatorService.this.socket;
@@ -232,10 +292,13 @@ public class LocatorService implements ILocator {
socket.setBroadcast(true);
input_thread.setName("TCF Locator Receiver");
timer_thread.setName("TCF Locator Timer");
+ dns_lookup_thread.setName("TCF Locator DNS Lookup");
input_thread.setDaemon(true);
timer_thread.setDaemon(true);
+ dns_lookup_thread.setDaemon(true);
input_thread.start();
timer_thread.start();
+ dns_lookup_thread.start();
listeners.add(new LocatorListener() {
public void peerAdded(IPeer peer) {
@@ -327,6 +390,33 @@ public class LocatorService implements ILocator {
}
}
+ private InetAddress getInetAddress(String host) {
+ if (host == null || host.length() == 0) return null;
+ synchronized (addr_cache) {
+ AddressCacheItem i = addr_cache.get(host);
+ if (i == null) {
+ i = new AddressCacheItem(host);
+ char ch = host.charAt(0);
+ if (ch == '[' || ch == ':' || ch >= '0' && ch <= '9') {
+ try {
+ i.address = InetAddress.getByName(host);
+ }
+ catch (UnknownHostException e) {
+ }
+ i.time_stamp = System.currentTimeMillis();
+ }
+ else {
+ /* InetAddress.getByName() can cause long delay - delegate to background thread */
+ addr_request = true;
+ addr_cache.notify();
+ }
+ addr_cache.put(host, i);
+ }
+ i.used = true;
+ return i.address;
+ }
+ }
+
private void refresh_timer() {
long time = System.currentTimeMillis();
/* Cleanup slave table */
@@ -472,7 +562,8 @@ public class LocatorService implements ILocator {
private void sendPeerInfo(IPeer peer, InetAddress addr, int port) {
Map<String,String> attrs = peer.getAttributes();
- if (attrs.get(IPeer.ATTR_IP_HOST) == null) return;
+ InetAddress peer_addr = getInetAddress(attrs.get(IPeer.ATTR_IP_HOST));
+ if (peer_addr == null) return;
if (attrs.get(IPeer.ATTR_IP_PORT) == null) return;
try {
out_buf[4] = CONF_PEER_INFO;
@@ -486,7 +577,6 @@ public class LocatorService implements ILocator {
out_buf[i++] = 0;
}
- InetAddress peer_addr = InetAddress.getByName(attrs.get(IPeer.ATTR_IP_HOST));
for (SubNet subnet : subnets) {
if (peer instanceof RemotePeer) {
if (socket.getLocalPort() != DISCOVEY_PORT) return;
@@ -567,7 +657,7 @@ public class LocatorService implements ILocator {
i += bt.length;
out_buf[i++] = 0;
for (Slave y : slaves) {
- if (!n.contains(y.address)) continue;
+ if (!n.contains(y.address)) continue;
if (y.last_req_slaves_time + DATA_RETENTION_PERIOD < time) continue;
socket.send(new DatagramPacket(out_buf, i, y.address, y.port));
}
@@ -689,9 +779,8 @@ public class LocatorService implements ILocator {
}
String id = map.get(IPeer.ATTR_ID);
if (id == null) throw new Exception("Invalid peer info: no ID");
- String peer_host = map.get(IPeer.ATTR_IP_HOST);
- if (peer_host == null) return;
- InetAddress peer_addr = InetAddress.getByName(peer_host);
+ InetAddress peer_addr = getInetAddress(map.get(IPeer.ATTR_IP_HOST));
+ if (peer_addr == null) return;
for (SubNet subnet : subnets) {
if (!subnet.contains(peer_addr)) continue;
IPeer peer = peers.get(id);
@@ -734,8 +823,11 @@ public class LocatorService implements ILocator {
int port = Integer.parseInt(s.substring(port0, port1));
if (port != DISCOVEY_PORT) {
String host = s.substring(host0, host1);
- long time = time0 != time1 ? Long.parseLong(s.substring(time0, time1)) : System.currentTimeMillis();
- addSlave(InetAddress.getByName(host), port, time);
+ InetAddress addr = getInetAddress(host);
+ if (addr != null) {
+ long time = time0 != time1 ? Long.parseLong(s.substring(time0, time1)) : System.currentTimeMillis();
+ addSlave(addr, port, time);
+ }
}
}
}

Back to the top