Author: toad
Date: 2008-02-06 20:33:23 +0000 (Wed, 06 Feb 2008)
New Revision: 17611

Added:
   trunk/freenet/src/freenet/node/TimedOutNodesList.java
Modified:
   trunk/freenet/src/freenet/node/AnnounceSender.java
   trunk/freenet/src/freenet/node/CHKInsertSender.java
   trunk/freenet/src/freenet/node/FailureTable.java
   trunk/freenet/src/freenet/node/FailureTableEntry.java
   trunk/freenet/src/freenet/node/NetworkIDManager.java
   trunk/freenet/src/freenet/node/NodeDispatcher.java
   trunk/freenet/src/freenet/node/PeerManager.java
   trunk/freenet/src/freenet/node/RequestSender.java
   trunk/freenet/src/freenet/node/ResettingHTLProbeRequestSender.java
   trunk/freenet/src/freenet/node/SSKInsertSender.java
Log:
Per-node failure tables. Untested. Basically, if we've recently routed a 
specific key to a specific node, and we got a DNF, don't do it again unless we 
have no other option (a bit more complex though). Benefits:
- Significant improvement in security against cancer nodes or nodes which fail 
all requests for a specific key for some other reason.
- Significant improvement in performance for very popular keys (frequently 
requested).

Modified: trunk/freenet/src/freenet/node/AnnounceSender.java
===================================================================
--- trunk/freenet/src/freenet/node/AnnounceSender.java  2008-02-06 20:07:51 UTC 
(rev 17610)
+++ trunk/freenet/src/freenet/node/AnnounceSender.java  2008-02-06 20:33:23 UTC 
(rev 17611)
@@ -115,7 +115,7 @@
                PeerNode next;
             if(onlyNode == null) {
                // Route it
-               next = node.peers.closerPeer(source, nodesRoutedTo, 
nodesNotIgnored, target, true, node.isAdvancedModeEnabled(), -1, null);
+               next = node.peers.closerPeer(source, nodesRoutedTo, 
nodesNotIgnored, target, true, node.isAdvancedModeEnabled(), -1, null, null);
             } else {
                next = onlyNode;
                if(nodesRoutedTo.contains(onlyNode)) {

Modified: trunk/freenet/src/freenet/node/CHKInsertSender.java
===================================================================
--- trunk/freenet/src/freenet/node/CHKInsertSender.java 2008-02-06 20:07:51 UTC 
(rev 17610)
+++ trunk/freenet/src/freenet/node/CHKInsertSender.java 2008-02-06 20:33:23 UTC 
(rev 17611)
@@ -279,7 +279,7 @@
             PeerNode next;
             // Can backtrack, so only route to nodes closer than we are to 
target.
             double nextValue;
-            next = node.peers.closerPeer(source, nodesRoutedTo, 
nodesNotIgnored, target, true, node.isAdvancedModeEnabled(), -1, null);
+            next = node.peers.closerPeer(source, nodesRoutedTo, 
nodesNotIgnored, target, true, node.isAdvancedModeEnabled(), -1, null, null);

             if(next == null) {
                 // Backtrack

Modified: trunk/freenet/src/freenet/node/FailureTable.java
===================================================================
--- trunk/freenet/src/freenet/node/FailureTable.java    2008-02-06 20:07:51 UTC 
(rev 17610)
+++ trunk/freenet/src/freenet/node/FailureTable.java    2008-02-06 20:33:23 UTC 
(rev 17611)
@@ -125,46 +125,6 @@
                }
        }

-       /**
-        * Called when a request is made. Determine whether we should fail the 
request, and add the requestors to the list
-        * of interested nodes.
-        * @param key The key to fetch.
-        * @param htl The HTL it will be fetched at.
-        * @param requestor The node requesting it.
-        * @return True if the request should be failed with an 
FNPRecentlyFailed.
-        */
-       public synchronized boolean shouldFail(Key key, short htl, PeerNode 
requestor) {
-               long now = System.currentTimeMillis();
-               FailureTableEntry entry = (FailureTableEntry) 
entriesByKey.get(key);
-               if(entry == null) {
-                       // Don't know anything about the key
-                       return false;
-               }
-               entry.addRequestor(requestor, now);
-               if(htl > entry.htl) {
-                       // If the HTL is higher this time, let it through
-                       entriesByKey.push(key, entry);
-                       return false;
-               }
-               if(now > entry.timeoutTime) {
-                       // If it's more than 10 minutes since we sent a 
request, let it through
-                       return false;
-               }
-               /*
-                * If the best node available now is closer than the best 
location we have routed to so far, out of those
-                * nodes which are still connected, then accept the request.
-                * 
-                * Note that this means we can route to the same node twice - 
but only if its location improves.
-                */
-               double bestLiveLocDiff = entry.bestLiveLocDiff();
-               
-               PeerNode p = peers.closerPeer(requestor, null, null, 
key.toNormalizedDouble(), true, false, 0, null, bestLiveLocDiff);
-               
-               if(p != null) return false; // there is a better route now / we 
want to retry an old one
-               
-               return true; // kill the request
-       }
-       
        private final class BlockOfferList {
                private BlockOffer[] offers;
                final FailureTableEntry entry;
@@ -477,4 +437,10 @@
        public void onDisconnect(final PeerNode pn) {
                // FIXME do something (off thread if expensive)
        }
+
+       public TimedOutNodesList getTimedOutNodesList(Key key) {
+               synchronized(this) {
+                       return (FailureTableEntry) entriesByKey.get(key);
+               }
+       }
 }

Modified: trunk/freenet/src/freenet/node/FailureTableEntry.java
===================================================================
--- trunk/freenet/src/freenet/node/FailureTableEntry.java       2008-02-06 
20:07:51 UTC (rev 17610)
+++ trunk/freenet/src/freenet/node/FailureTableEntry.java       2008-02-06 
20:33:23 UTC (rev 17611)
@@ -10,7 +10,7 @@
 import freenet.support.Logger;
 import freenet.support.StringArray;

-class FailureTableEntry {
+class FailureTableEntry implements TimedOutNodesList {

        /** The key */
        Key key; // FIXME should this be stored compressed somehow e.g. just 
the routing key?
@@ -475,4 +475,13 @@
                return true;
        }

+       public synchronized long getTimeoutTime(PeerNode peer) {
+               for(int i=0;i<requestedNodes.length;i++) {
+                       if(requestedNodes[i].get() == peer) {
+                               return requestedTimeouts[i];
+                       }
+               }
+               return -1; // not timed out
+       }
+
 }
\ No newline at end of file

Modified: trunk/freenet/src/freenet/node/NetworkIDManager.java
===================================================================
--- trunk/freenet/src/freenet/node/NetworkIDManager.java        2008-02-06 
20:07:51 UTC (rev 17610)
+++ trunk/freenet/src/freenet/node/NetworkIDManager.java        2008-02-06 
20:33:23 UTC (rev 17611)
@@ -100,7 +100,7 @@
                                        if (htl > dawnHtl && 
routedTo.isEmpty()) {
                                                
next=node.peers.getRandomPeer(source);
                                        } else {
-                                               
next=node.peers.closerPeer(source, routedTo, notIgnored, target, true, 
node.isAdvancedModeEnabled(), -1, null);
+                                               
next=node.peers.closerPeer(source, routedTo, notIgnored, target, true, 
node.isAdvancedModeEnabled(), -1, null, null);
                                        }

                                        if (next==null) {

Modified: trunk/freenet/src/freenet/node/NodeDispatcher.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeDispatcher.java  2008-02-06 20:07:51 UTC 
(rev 17610)
+++ trunk/freenet/src/freenet/node/NodeDispatcher.java  2008-02-06 20:33:23 UTC 
(rev 17611)
@@ -566,7 +566,7 @@
                // Forward
                m = preForward(m, htl);
                while(true) {
-                       PeerNode next = node.peers.closerPeer(pn, ctx.routedTo, 
ctx.notIgnored, target, true, node.isAdvancedModeEnabled(), -1, null);
+                       PeerNode next = node.peers.closerPeer(pn, ctx.routedTo, 
ctx.notIgnored, target, true, node.isAdvancedModeEnabled(), -1, null, null);
                        if(logMINOR) Logger.minor(this, "Next: "+next+" 
message: "+m);
                        if(next != null) {
                                // next is connected, or at least has been => 
next.getPeer() CANNOT be null.

Modified: trunk/freenet/src/freenet/node/PeerManager.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerManager.java     2008-02-06 20:07:51 UTC 
(rev 17610)
+++ trunk/freenet/src/freenet/node/PeerManager.java     2008-02-06 20:33:23 UTC 
(rev 17611)
@@ -30,6 +30,7 @@
 import freenet.io.comm.Peer;
 import freenet.io.comm.PeerParseException;
 import freenet.io.comm.ReferenceSignatureVerificationException;
+import freenet.keys.Key;
 import freenet.node.useralerts.PeerManagerUserAlert;
 import freenet.support.Logger;
 import freenet.support.ShortBuffer;
@@ -48,6 +49,7 @@
 public class PeerManager {

        private static boolean logMINOR;
+       private static boolean logDEBUG;

     /** Our Node */
     final Node node;
@@ -108,6 +110,7 @@
     public PeerManager(Node node) {
         Logger.normal(this, "Creating PeerManager");
         logMINOR = Logger.shouldLog(Logger.MINOR, this);
+        logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
                peerNodeStatuses = new HashMap();
                peerNodeStatusesDarknet = new HashMap();
                peerNodeRoutingBackoffReasons = new HashMap();
@@ -359,6 +362,7 @@

     public void addConnectedPeer(PeerNode pn) {
        logMINOR = Logger.shouldLog(Logger.MINOR, this);
+       logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
        if(!pn.isRoutable()) {
                if(logMINOR) Logger.minor(this, "Not ReallyConnected: "+pn);
                return;
@@ -571,6 +575,7 @@
         // reconnect, and they can't do it yet as we are synchronized.
         Vector v = new Vector(connectedPeers.length);
         logMINOR = Logger.shouldLog(Logger.MINOR, this);
+        logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
         for(int i=0;i<myPeers.length;i++) {
             PeerNode pn = myPeers[i];
             if(pn == exclude) continue;
@@ -691,8 +696,8 @@
        return closestDist < nodeDist;
     }

-    public PeerNode closerPeer(PeerNode pn, Set routedTo, Set notIgnored, 
double loc, boolean ignoreSelf, boolean calculateMisrouting, int minVersion, 
Vector addUnpickedLocsTo) {
-       return closerPeer(pn, routedTo, notIgnored, loc, ignoreSelf, 
calculateMisrouting, minVersion, addUnpickedLocsTo, 2.0);
+    public PeerNode closerPeer(PeerNode pn, Set routedTo, Set notIgnored, 
double loc, boolean ignoreSelf, boolean calculateMisrouting, int minVersion, 
Vector addUnpickedLocsTo, Key key) {
+       return closerPeer(pn, routedTo, notIgnored, loc, ignoreSelf, 
calculateMisrouting, minVersion, addUnpickedLocsTo, 2.0, key);
     }

        /**
@@ -704,8 +709,10 @@
         * @param addUnpickedLocsTo Add all locations we didn't choose which we 
could have routed to to 
         * this array. Remove the location of the peer we pick from it.
         * @param maxDistance If a node is further away from the target than 
this distance, ignore it.
+        * @param key The original key, if we have it, and if we want to 
consult with the FailureTable
+        * to avoid routing to nodes which have recently failed for the same 
key.
      */
-    public PeerNode closerPeer(PeerNode pn, Set routedTo, Set notIgnored, 
double target, boolean ignoreSelf, boolean calculateMisrouting, int minVersion, 
Vector addUnpickedLocsTo, double maxDistance) {
+    public PeerNode closerPeer(PeerNode pn, Set routedTo, Set notIgnored, 
double target, boolean ignoreSelf, boolean calculateMisrouting, int minVersion, 
Vector addUnpickedLocsTo, double maxDistance, Key key) {
         PeerNode[] peers;  
         synchronized (this) {
                        peers = connectedPeers;
@@ -715,6 +722,15 @@
         if(!ignoreSelf)
             maxDiff = Location.distance(node.lm.getLocation(), target);

+        /**
+         * Routing order:
+         * - Non-timed-out non-backed-off peers, in order of closeness to the 
target.
+         * - Timed-out, non-backed-off peers, least recently timed out first.
+         * - Non-timed-out backed-off peers, in order of closeness to the 
target.
+         * - Timed out, backed-off peers, least recently timed out first.
+         * - 
+         */
+        
                PeerNode closest = null;
                double closestDistance = Double.MAX_VALUE;

@@ -724,6 +740,19 @@
                PeerNode closestNotBackedOff = null;
                double closestNotBackedOffDistance = Double.MAX_VALUE;

+               PeerNode leastRecentlyTimedOut = null;
+               long timeLeastRecentlyTimedOut = Long.MAX_VALUE;
+               
+               PeerNode leastRecentlyTimedOutBackedOff = null;
+               long timeLeastRecentlyTimedOutBackedOff = Long.MAX_VALUE;
+               
+               TimedOutNodesList entry = null;
+               
+               if(key != null) {
+                       entry = node.failureTable.getTimedOutNodesList(key);
+               }
+               
+               long now = System.currentTimeMillis();
                int count = 0;
         for(int i=0;i<peers.length;i++) {
             PeerNode p = peers[i];
@@ -743,6 +772,10 @@
                if(logMINOR) Logger.minor(this, "Skipping old version: 
"+p.getPeer());
                continue;
             }
+            long timeout = Long.MAX_VALUE;
+            if(entry != null)
+               timeout = entry.getTimeoutTime(p);
+            boolean timedOut = timeout > now;
                        //To help avoid odd race conditions, get the location 
only once and use it for all calculations.
                        double loc = p.getLocation();
             double diff = Location.distance(loc, target);
@@ -754,25 +787,38 @@
                        count++;
             if(logMINOR) Logger.minor(this, "p.loc="+loc+", target="+target+", 
d="+Location.distance(loc, target)+" usedD="+diff+" for "+p.getPeer());
                        boolean chosen=false;
-            if(diff < closestDistance) {
+            if(diff < closestDistance && !timedOut) {
                closestDistance = diff;
                 closest = p;
                                chosen=true;
                 if(logMINOR) Logger.minor(this, "New best: "+diff+" ("+loc+" 
for "+p.getPeer());
             }
                        boolean backedOff=p.isRoutingBackedOff();
-                       if(backedOff && (diff < closestBackedOffDistance)) {
+                       if(backedOff && (diff < closestBackedOffDistance) && 
!timedOut) {
                closestBackedOffDistance = diff;
                 closestBackedOff = p;
                                chosen=true;
                 if(logMINOR) Logger.minor(this, "New best-backed-off: "+diff+" 
("+loc+" for "+p.getPeer());
             }
-                       if(!backedOff && (diff < closestNotBackedOffDistance)) {
+                       if(!backedOff && (diff < closestNotBackedOffDistance) 
&& !timedOut) {
                closestNotBackedOffDistance = diff;
                 closestNotBackedOff = p;
                                chosen=true;
                 if(logMINOR) Logger.minor(this, "New best-not-backed-off: 
"+diff+" ("+loc+" for "+p.getPeer());
             }
+                       if(timedOut) {
+                               if(!backedOff) {
+                                       if(timeout < timeLeastRecentlyTimedOut) 
{
+                                               timeLeastRecentlyTimedOut = 
timeout;
+                                               leastRecentlyTimedOut = p;
+                                       }
+                               } else {
+                                       if(timeout < 
timeLeastRecentlyTimedOutBackedOff) {
+                                               
timeLeastRecentlyTimedOutBackedOff = timeout;
+                                               leastRecentlyTimedOutBackedOff 
= p;
+                                       }
+                               }
+                       }
                if(addUnpickedLocsTo != null && !chosen) {
                        Double d = new Double(loc);
                        // Here we can directly compare double's because they 
aren't processed in any way, and are finite and (probably) nonzero.
@@ -783,8 +829,18 @@

                PeerNode best = closestNotBackedOff;

-               if (best==null)
-                       best = closestBackedOff;
+               if (best==null) {
+                       if(leastRecentlyTimedOut != null) {
+                               best = leastRecentlyTimedOut;
+                               if(logDEBUG) Logger.debug(this, "Using least 
recently timed out peer for key: "+best.shortToString());
+                       } else if(closestBackedOff != null) {
+                               best = closestBackedOff;
+                               if(logDEBUG) Logger.debug(this, "Using best 
backed-off peer for key: "+best.shortToString());
+                       } else if(leastRecentlyTimedOutBackedOff != null) {
+                               best = leastRecentlyTimedOutBackedOff;
+                               if(logDEBUG) Logger.debug(this, "Using least 
recently timed out backed-off peer for key: "+best.shortToString());
+                       }
+               }

                //racy... getLocation() could have changed
        if (calculateMisrouting) {

Modified: trunk/freenet/src/freenet/node/RequestSender.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestSender.java   2008-02-06 20:07:51 UTC 
(rev 17610)
+++ trunk/freenet/src/freenet/node/RequestSender.java   2008-02-06 20:33:23 UTC 
(rev 17611)
@@ -391,7 +391,7 @@

             // Route it
             PeerNode next;
-            next = node.peers.closerPeer(source, nodesRoutedTo, 
nodesNotIgnored, target, true, node.isAdvancedModeEnabled(), -1, null);
+            next = node.peers.closerPeer(source, nodesRoutedTo, 
nodesNotIgnored, target, true, node.isAdvancedModeEnabled(), -1, null, key);

             if(next == null) {
                                if (logMINOR && rejectOverloads>0)

Modified: trunk/freenet/src/freenet/node/ResettingHTLProbeRequestSender.java
===================================================================
--- trunk/freenet/src/freenet/node/ResettingHTLProbeRequestSender.java  
2008-02-06 20:07:51 UTC (rev 17610)
+++ trunk/freenet/src/freenet/node/ResettingHTLProbeRequestSender.java  
2008-02-06 20:33:23 UTC (rev 17611)
@@ -104,7 +104,7 @@

             // Route it
             PeerNode next;
-            next = node.peers.closerPeer(source, nodesRoutedTo, 
nodesNotIgnored, target, true, node.isAdvancedModeEnabled(), -1, null);
+            next = node.peers.closerPeer(source, nodesRoutedTo, 
nodesNotIgnored, target, true, node.isAdvancedModeEnabled(), -1, null, null);

             if(next == null) {
                                if (logMINOR && rejectOverloads>0)

Modified: trunk/freenet/src/freenet/node/SSKInsertSender.java
===================================================================
--- trunk/freenet/src/freenet/node/SSKInsertSender.java 2008-02-06 20:07:51 UTC 
(rev 17610)
+++ trunk/freenet/src/freenet/node/SSKInsertSender.java 2008-02-06 20:33:23 UTC 
(rev 17611)
@@ -136,7 +136,7 @@
             // Can backtrack, so only route to nodes closer than we are to 
target.
             double nextValue;
             synchronized(node.peers) {
-                next = node.peers.closerPeer(source, nodesRoutedTo, 
nodesNotIgnored, target, true, node.isAdvancedModeEnabled(), -1, null);
+                next = node.peers.closerPeer(source, nodesRoutedTo, 
nodesNotIgnored, target, true, node.isAdvancedModeEnabled(), -1, null, null);
                 if(next != null)
                     nextValue = next.getLocation();
                 else

Added: trunk/freenet/src/freenet/node/TimedOutNodesList.java
===================================================================
--- trunk/freenet/src/freenet/node/TimedOutNodesList.java                       
        (rev 0)
+++ trunk/freenet/src/freenet/node/TimedOutNodesList.java       2008-02-06 
20:33:23 UTC (rev 17611)
@@ -0,0 +1,15 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.node;
+
+/**
+ * Interface which returns the time at which the failure table timeout on any 
given node will 
+ * expire for a specific key.
+ * @author toad
+ */
+public interface TimedOutNodesList {
+
+       long getTimeoutTime(PeerNode peer);
+
+}


Reply via email to