Author: toad
Date: 2007-07-13 17:18:29 +0000 (Fri, 13 Jul 2007)
New Revision: 14078
Modified:
trunk/freenet/src/freenet/node/OpennetManager.java
trunk/freenet/src/freenet/node/RequestHandler.java
trunk/freenet/src/freenet/support/LRUQueue.java
Log:
Full LRU, temporarily reduce max opennet peers to 5.
Modified: trunk/freenet/src/freenet/node/OpennetManager.java
===================================================================
--- trunk/freenet/src/freenet/node/OpennetManager.java 2007-07-13 16:26:20 UTC
(rev 14077)
+++ trunk/freenet/src/freenet/node/OpennetManager.java 2007-07-13 17:18:29 UTC
(rev 14078)
@@ -13,6 +13,7 @@
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.Vector;
import freenet.io.comm.Peer;
import freenet.io.comm.PeerParseException;
@@ -36,15 +37,19 @@
/** Our peers. PeerNode's are promoted when they successfully fetch a
key. Normally we take
* the bottom peer, but if that isn't eligible to be dropped, we
iterate up the list. */
private final LRUQueue peersLRU;
+ /** Time at which last dropped a peer */
+ private long timeLastDropped;
// FIXME make this configurable
- static final int MAX_PEERS = 30;
+ static final int MAX_PEERS = 5;
/** Chance of resetting path folding (for plausible deniability) is 1
in this number. */
static final int RESET_PATH_FOLDING_PROB = 20;
/** Don't re-add a node until it's been up and disconnected for at
least this long */
static final int DONT_READD_TIME = 60*1000;
/** Don't drop a node until it's at least this old */
static final int DROP_ELIGIBLE_TIME = 300*1000;
+ /** Every DROP_CONNECTED_TIME, we may drop a peer even though it is
connected */
+ static final int DROP_CONNECTED_TIME = 10*60*1000;
public OpennetManager(Node node, NodeCryptoConfig opennetConfig) throws
NodeInitException {
this.node = node;
@@ -177,17 +182,86 @@
Logger.error(this, "Not adding "+pn.userToString()+" to
opennet list as already there");
return false;
}
- if(!wantPeer()) {
- Logger.error(this, "Not adding "+pn.userToString()+" to
opennet list as don't want it");
- return false;
+ return wantPeer(pn);
+ }
+
+ public boolean wantPeer(PeerNode nodeToAddNow) {
+ synchronized(this) {
+ if(peersLRU.size() < MAX_PEERS) {
+ if(nodeToAddNow != null) {
+ Logger.error(this, "Added opennet peer
"+nodeToAddNow+" as opennet peers list not full");
+ peersLRU.push(nodeToAddNow);
+ }
+ return true;
+ }
}
- return node.peers.addPeer(pn); // False = already in peers list
+ Vector dropList = new Vector();
+ boolean ret = true;
+ synchronized(this) {
+ while(peersLRU.size() < MAX_PEERS - (nodeToAddNow ==
null ? 0 : 1)) {
+ PeerNode toDrop;
+ toDrop = peerToDrop();
+ if(toDrop == null) {
+ ret = false;
+ break;
+ }
+ peersLRU.remove(toDrop);
+ dropList.add(toDrop);
+ }
+ if(!dropList.isEmpty())
+ timeLastDropped = System.currentTimeMillis();
+ if(nodeToAddNow != null) {
+ if(!node.peers.addPeer(nodeToAddNow)) {
+ // Can't add it, already present (some
sort of race condition)
+ PeerNode readd = (PeerNode)
dropList.remove(dropList.size()-1);
+ peersLRU.pushLeast(readd);
+ ret = false;
+ Logger.error(this, "Could not add
opennet peer "+nodeToAddNow+" because already in list");
+ } else {
+ Logger.error(this, "Added opennet peer
"+nodeToAddNow+" after clearing "+dropList.size()+" items");
+ }
+ }
+ }
+ if(dropList != null) {
+ for(int i=0;i<dropList.size();i++) {
+ OpennetPeerNode pn = (OpennetPeerNode)
dropList.get(i);
+ Logger.error(this, "Dropping LRU opennet peer:
"+pn);
+ node.peers.disconnect(pn);
+ }
+ }
+ return ret;
}
- public boolean wantPeer() {
- // FIXME implement LRU !!!
- if(node.peers.getOpennetPeers().length >= MAX_PEERS) return
false;
- return true;
+ synchronized PeerNode peerToDrop() {
+ if(peersLRU.size() < MAX_PEERS) {
+ // Don't drop any peers
+ return null;
+ } else {
+ // Do we want it?
+ OpennetPeerNode[] peers = (OpennetPeerNode[])
peersLRU.toArray(new OpennetPeerNode[peersLRU.size()]);
+ for(int i=0;i<peers.length;i++) {
+ OpennetPeerNode pn = peers[i];
+ if(pn == null) continue;
+ if(!pn.isDroppable()) continue;
+ if(!pn.isConnected()) {
+ if(Logger.shouldLog(Logger.MINOR, this))
+ Logger.minor(this, "Possibly
dropping opennet peer "+pn+" as is disconnected");
+ return pn;
+ }
+ }
+ if(System.currentTimeMillis() - timeLastDropped <
DROP_CONNECTED_TIME)
+ return null;
+ for(int i=0;i<peers.length;i++) {
+ OpennetPeerNode pn = peers[i];
+ if(pn == null) continue;
+ if(!pn.isDroppable()) continue;
+ if(Logger.shouldLog(Logger.MINOR, this))
+ Logger.minor(this, "Possibly dropping
opennet peer "+pn+" "+
+
(System.currentTimeMillis() - timeLastDropped)+" ms since last dropped peer");
+ return pn;
+ }
+ }
+ return null;
}
public synchronized void onSuccess(OpennetPeerNode pn) {
Modified: trunk/freenet/src/freenet/node/RequestHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestHandler.java 2007-07-13 16:26:20 UTC
(rev 14077)
+++ trunk/freenet/src/freenet/node/RequestHandler.java 2007-07-13 17:18:29 UTC
(rev 14078)
@@ -272,7 +272,7 @@
private void finishOpennetNoRelay() {
OpennetManager om = node.getOpennet();
if(om != null) {
- if(om.wantPeer()) {
+ if(om.wantPeer(null)) {
Message msg =
DMT.createFNPOpennetConnectDestination(uid, new
ShortBuffer(om.crypto.myCompressedFullRef()));
try {
source.sendAsync(msg, null, 0, this);
Modified: trunk/freenet/src/freenet/support/LRUQueue.java
===================================================================
--- trunk/freenet/src/freenet/support/LRUQueue.java 2007-07-13 16:26:20 UTC
(rev 14077)
+++ trunk/freenet/src/freenet/support/LRUQueue.java 2007-07-13 17:18:29 UTC
(rev 14078)
@@ -2,7 +2,11 @@
import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.Iterator;
+import freenet.node.OpennetPeerNode;
+import freenet.node.PeerNode;
+
public class LRUQueue {
/*
@@ -34,6 +38,21 @@
}
/**
+ * push to bottom (least recently used position)
+ */
+ public void pushLeast(Object obj) {
+ QItem insert = (QItem)hash.get(obj);
+ if (insert == null) {
+ insert = new QItem(obj);
+ hash.put(obj,insert);
+ } else {
+ list.remove(insert);
+ }
+
+ list.push(insert);
+ }
+
+ /**
* @return Least recently pushed Object.
*/
public final synchronized Object pop() {
@@ -95,6 +114,32 @@
return hash.keySet().toArray();
}
+ public Object[] toArray(Object[] array) {
+ return hash.keySet().toArray(array);
+ }
+
+ public synchronized Object[] toArrayOrdered() {
+ Object[] array = new Object[list.size()];
+ int x = 0;
+ for(Enumeration e =
list.reverseElements();e.hasMoreElements();) {
+ array[x++] = e.nextElement();
+ }
+ return array;
+ }
+
+ /**
+ * Warning, this will not reallocate unlike the toArray(Object[]) on
java class library functions.
+ * FIXME fix that.
+ * @param array The array to fill in
+ */
+ public synchronized Object[] toArrayOrdered(Object[] array) {
+ int x = 0;
+ for(Enumeration e =
list.reverseElements();e.hasMoreElements();) {
+ array[x++] = e.nextElement();
+ }
+ return array;
+ }
+
public synchronized boolean isEmpty() {
return hash.isEmpty();
}