Not sure how this is as far as correct ways to fix things, but the
attached patch is one potential way to fix the problems which we've been
having with excessive connections being opened all the time on recent
builds.
Applies to 6205 code.
Impliments a BlackListQueue by modifying LRUQueue to include times and a
clean function. The BlackListQueue is currently set to blackList a node
for 60 seconds if it's connection has suddenly and unexpectedly died.
On my node this seems to massively reduce the number of cyclic
connections being opened. In order to make this work, I also had to fix
tcpAddress.hashCode() and by proxy therefor Peer.hashCode() they could
have different values for the same peer depending on how the
constructors were called. I'm not sure why upstream nodes are so often
repeatedly allowing an incoming connection to complete and then dumping
it, but with this patch, that behaviour no longer punishes the network
so much.
--Brandon
Index: src/freenet/ConnectionHandler.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/ConnectionHandler.java,v
retrieving revision 1.159
diff -u -r1.159 ConnectionHandler.java
--- src/freenet/ConnectionHandler.java 20 Sep 2003 19:58:59 -0000 1.159
+++ src/freenet/ConnectionHandler.java 22 Sep 2003 02:05:04 -0000
@@ -1246,6 +1246,7 @@
public void queuedClose() {
logDEBUG = Core.logger.shouldLog(Logger.DEBUG,this);
if(logDEBUG) logDEBUG("Queued close", true);
+ ocm.blackList(peer);
terminate();
if(logDEBUG) logDEBUG("Terminated in queuedClose()");
}
Index: src/freenet/OpenConnectionManager.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/OpenConnectionManager.java,v
retrieving revision 1.106
diff -u -r1.106 OpenConnectionManager.java
--- src/freenet/OpenConnectionManager.java 19 Sep 2003 17:18:04 -0000 1.106
+++ src/freenet/OpenConnectionManager.java 22 Sep 2003 02:05:04 -0000
@@ -53,6 +53,8 @@
private Object openConnsSync = new Object();
private final LRUQueue lru = new LRUQueue();
+ // Queue of blacklisted peers
+ private final LRUQueue blq = new LRUQueue(60000,100);
private int maxConnections = -1;
private boolean logDEBUG = true;
@@ -318,6 +320,11 @@
}
}
+ public void blackList(Peer p){
+ Core.logger.log(this, "blackListing " + p, Logger.DEBUG);
+ blq.push(p);
+ }
+
/**
* Creates a new Connection which is started and added.
* @param c The Core to connect from
@@ -340,24 +347,36 @@
boolean updatedRefcount = false;
boolean weStarted = false;
+ blq.clean();
+ Core.logger.log(this, "Current blackListQueue size: " + blq.size() +
+ ", Checking " + p,
+ Logger.DEBUG);
+ if ( blq.containsKey(p) ) {
+ Core.logger.log(this, "Attempted to open connection for blackListed " +
+ p,Logger.DEBUG);
+ ConnectFailedException e =
+ new ConnectFailedException(p.getAddress(),
+ p.getIdentity(),
+ "BlackListed",
+ true);
+ Core.logger.log(this, "Failed to connect: " + e, Logger.DEBUG);
+ throw e;
+ }
try {
synchronized(connectionJobs) {
- while(ct == null || ct.done) {
- ct = (ConnectionJob)(connectionJobs.get(p));
- if(ct != null && ct.done) {
- if(connectionJobs.get(p) == ct) {
- connectionJobs.remove(p);
- continue;
- }
- }
- break;
- }
- if(ct != null) {
- Core.logger.log(this, "Got "+ct+", waiting on
it",
- Logger.DEBUG);
- updatedRefcount = true;
- ct.incRefcount();
- } else {
+ if ( ( ct = (ConnectionJob)connectionJobs.get(p) ) != null ) {
+ if ( ct.done ) {
+ connectionJobs.remove(p);
+ ct = null;
+ } else {
+ Core.logger.log(this, "Got "+ct+", waiting on it",
+ Logger.DEBUG);
+ updatedRefcount = true;
+ ct.incRefcount();
+ }
+ }
+
+ if(ct == null) {
weStarted = true;
ct = new ConnectionJob(c, p);
connectionJobs.put(p, ct);
Index: src/freenet/Peer.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/Peer.java,v
retrieving revision 1.3
diff -u -r1.3 Peer.java
--- src/freenet/Peer.java 12 Sep 2003 01:52:25 -0000 1.3
+++ src/freenet/Peer.java 22 Sep 2003 02:05:04 -0000
@@ -58,7 +58,7 @@
}
public int hashCode() {
- return id.hashCode() ^ addr.hashCode();
+ return id.hashCode() ^ addr.hashCode();
}
public String toString() {
Index: src/freenet/support/LRUQueue.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/LRUQueue.java,v
retrieving revision 1.4
diff -u -r1.4 LRUQueue.java
--- src/freenet/support/LRUQueue.java 10 Sep 2003 19:45:28 -0000 1.4
+++ src/freenet/support/LRUQueue.java 22 Sep 2003 02:05:05 -0000
@@ -5,6 +5,11 @@
public class LRUQueue {
+ private long maxQueueTimeMillis=60000;
+ private int maxQueueElements=100;
+ private final DoublyLinkedListImpl list = new DoublyLinkedListImpl();
+ private final Hashtable hash = new Hashtable();
+
/*
* I've just converted this to using the DLList and Hashtable
* this makes it Hashtable time instead of O(N) for push and
@@ -12,9 +17,14 @@
* push is by far the most done operation, this should be an
* overall improvement.
*/
- private final DoublyLinkedListImpl list = new DoublyLinkedListImpl();
- private final Hashtable hash = new Hashtable();
+ public LRUQueue() {
+ }
+ public LRUQueue(long maxQueueTimeMillis,int maxQueueElements) {
+ this.maxQueueTimeMillis = maxQueueTimeMillis;
+ this.maxQueueElements = maxQueueElements;
+ }
+
/**
* push()ing an object that is already in
* the queue moves that object to the most
@@ -28,10 +38,29 @@
hash.put(obj,insert);
} else {
list.remove(insert);
+ insert.lastTouchedTimeMillis = System.currentTimeMillis();
}
list.unshift(insert);
- }
+ }
+
+ /* This method should only be used by those interested in limiting an object's
+ * time in the LRUQueue, it will clean out any objects who have been in the
+ * queue for longer than maxQueueTimeMillis
+ */
+ public final synchronized void clean() {
+ while ( list.size() > maxQueueElements ) {
+ hash.remove(((QItem)list.pop()).obj);
+ }
+ while ( list.size() > 0 &&
+ System.currentTimeMillis() >
((QItem)list.tail()).lastTouchedTimeMillis + maxQueueTimeMillis ) {
+ hash.remove(((QItem)list.pop()).obj);
+ }
+ }
+
+ public final synchronized boolean containsKey(Object obj) {
+ return hash.containsKey(obj);
+ }
// Least recently pushed Object.
public final synchronized Object pop() {
@@ -68,9 +97,11 @@
private static class QItem extends DoublyLinkedListImpl.Item {
public Object obj;
+ public long lastTouchedTimeMillis;
public QItem(Object obj) {
this.obj = obj;
+ lastTouchedTimeMillis = System.currentTimeMillis();
}
}
}
Index: src/freenet/transport/tcpAddress.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/transport/tcpAddress.java,v
retrieving revision 1.15
diff -u -r1.15 tcpAddress.java
--- src/freenet/transport/tcpAddress.java 12 Sep 2003 01:52:26 -0000 1.15
+++ src/freenet/transport/tcpAddress.java 22 Sep 2003 02:05:05 -0000
@@ -65,7 +65,8 @@
this.host = host;
if(host!=null) {
valname = host.getHostAddress();
- hashCode = port ^ host.hashCode() ^ valname.hashCode();
+
+ hashCode = port ^ valname.hashCode();//host.hashCode() ^
valname.hashCode();
} else {
hashCode = port;
valname = "";
@@ -82,8 +83,8 @@
hostName = hostname;
host = null;
//doDeferredLookup();
- hashCode = port ^ hostname.hashCode();
valname = hostname;
+ hashCode = port ^ valname.hashCode();
}
/**
@@ -105,7 +106,7 @@
throw new BadAddressException(""+e);
}
setPort(Integer.parseInt(str.substring(colon + 1)));
- hashCode = port ^ host.hashCode();
+ hashCode = port ^ valname.hashCode();
}
public final void doDeferredLookup() throws UnknownHostException {
_______________________________________________
Devl mailing list
[EMAIL PROTECTED]
http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/devl