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();
        }


Reply via email to