Update of /cvsroot/freenet/freenet/src/freenet/node/rt
In directory sc8-pr-cvs1:/tmp/cvs-serv13668/src/freenet/node/rt

Modified Files:
        NGRouting.java NGRoutingTable.java StandardNodeEstimator.java 
        NodeEstimator.java StandardNodeEstimatorFactory.java 
Log Message:
6333: Implement exponential backoff.

Index: NGRouting.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/rt/NGRouting.java,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -w -r1.27 -r1.28
--- NGRouting.java      13 Nov 2003 16:18:55 -0000      1.27
+++ NGRouting.java      13 Nov 2003 20:49:54 -0000      1.28
@@ -73,7 +73,8 @@
            count++;
            lastTime = System.currentTimeMillis();
            NodeReference ref = last.reference();
-           if(desperate || freeConn(ref.getIdentity())) {
+           if((desperate || freeConn(ref.getIdentity())) &&
+                       (!last.isBackedOff())) {
                hasSearchFailed = false;
                lastTime = System.currentTimeMillis();
                logDEBUG = Core.logger.shouldLog(Logger.DEBUG,this);

Index: NGRoutingTable.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/rt/NGRoutingTable.java,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -w -r1.39 -r1.40
--- NGRoutingTable.java 13 Nov 2003 02:16:58 -0000      1.39
+++ NGRoutingTable.java 13 Nov 2003 20:49:54 -0000      1.40
@@ -377,10 +377,12 @@
                int triedNodes = 0;
                long totalConnectAttempts = 0;
                long totalConnectSuccesses = 0;
+               int backedOffNodes = 0;
                synchronized(this) {
                        Enumeration elements = estimators.elements();
                        while(elements.hasMoreElements()) {
                                NodeEstimator e = 
(NodeEstimator)(elements.nextElement());
+                               if(e.isBackedOff()) backedOffNodes++;
                                NodeReference ref = e.reference();
                                if(ref == null) {
                                        if(shouldLog)
@@ -414,16 +416,17 @@
                props[1] = new Integer(triedNodes);
                props[2] = new Integer(connectedNodes);
                props[3] = new Integer(successNodes);
-               props[4] = new Long(totalConnectAttempts);
-               props[5] = new Long(totalConnectSuccesses);
-               props[6] = new Float(pLegitDNF);
-               props[7] = new Float(pSemiLegitDNF);
-               props[8] = Long.toString(lowestEstimatedSearchTime)+"ms";
-               props[9] = Long.toString(lowestEstimatedDNFTime)+"ms";
+               props[4] = new Integer(backedOffNodes);
+               props[5] = new Long(totalConnectAttempts);
+               props[6] = new Long(totalConnectSuccesses);
+               props[7] = new Float(pLegitDNF);
+               props[8] = new Float(pSemiLegitDNF);
+               props[9] = Long.toString(lowestEstimatedSearchTime)+"ms";
+               props[10] = Long.toString(lowestEstimatedDNFTime)+"ms";
 
-               props[10] = new 
String(globalEstimator.getHTMLReportingTool().lowestString(TimeEstimator.TIME)); 
-               props[11] = new 
String(globalEstimator.getHTMLReportingTool().highestString(TimeEstimator.TIME));
-               props[12] = getClass().getName();
+               props[11] = new 
String(globalEstimator.getHTMLReportingTool().lowestString(TimeEstimator.TIME)); 
+               props[12] = new 
String(globalEstimator.getHTMLReportingTool().highestString(TimeEstimator.TIME));
+               props[13] = getClass().getName();
                StringMap sm = new SimpleStringMap(TABLE_PROPERTIES, props);
                // FIXME!
                StringMap[] refs = new StringMap[refInfos.size()];
@@ -435,8 +438,8 @@
        
        private final static String[] TABLE_PROPERTIES 
         = {"Number of node references", "Attempted to contact node references",
-                  "Contacted node references",
-                  "Connections with Successful Transfers", "Connection Attempts",
+                  "Contacted node references", "Connections with Successful 
Transfers", 
+           "Backed off nodes", "Connection Attempts", 
                   "Successful Connections", "Probability of legitimate DNF",
                   "Worse guess probability of legitimate DNF",
            "Lowest max estimated search time", "Lowest max estimated DNF time",

Index: StandardNodeEstimator.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/rt/StandardNodeEstimator.java,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -w -r1.38 -r1.39
--- StandardNodeEstimator.java  13 Nov 2003 16:14:51 -0000      1.38
+++ StandardNodeEstimator.java  13 Nov 2003 20:49:54 -0000      1.39
@@ -15,6 +15,7 @@
 import freenet.Core;
 import freenet.FieldSet;
 import freenet.Key;
+import freenet.crypt.RandomSource;
 import freenet.node.Main;
 import freenet.node.NodeReference;
 import freenet.support.DataObjectPending;
@@ -52,6 +53,12 @@
        int successes = 0;
        boolean needConnection;
        long lastEstimate = -1;
+       // Variables for exponential backoff on SearchFailed
+       long enteredBackoffTime = -1;
+       int defaultBackoffPeriod = 1000;
+       int currentBackoffPeriod = defaultBackoffPeriod;
+       RandomSource random;
+       long lastPartialSuccessTime;
        
        public FieldSet toFieldSet() {
                FieldSet fs = new FieldSet();
@@ -75,9 +82,10 @@
                                                                 RoutingMemory mem, 
RunningAverageFactory raf,
                                                                 TimeEstimatorFactory 
rtef, 
                                                                 DataObjectPending dop,
-                                                                boolean 
needConnection) throws IOException {
+                                                                boolean 
needConnection, RandomSource rand) throws IOException {
                Core.logger.log(this, "Serializing in StandardNodeEstimator",
                                                Logger.MINOR);
+               this.random = rand;
                this.ngrt = ngrt;
                this.ref = ref;
                this.mem = mem;
@@ -136,7 +144,7 @@
                                                                 TimeEstimatorFactory 
rtef, Key k,
                                                                 double 
initTransferRate, 
                                                                 boolean 
needConnection, double maxPDNF,
-                                                                long maxSearchTime, 
long maxDNFTime) {
+                                                                long maxSearchTime, 
long maxDNFTime, RandomSource rand) {
                if(Core.logger.shouldLog(Logger.MINOR, this))
                        Core.logger.log(this, "New node in routing table 
(StandardNodeEstimator impl) for  "+
                                        ref+" ("+ngrt+"), details:"+"mem = "+mem+", 
key="+k+", initTransferRate="+
@@ -326,12 +334,38 @@
        }
        
        public void searchFailed(long time) {
+               // QueryRejected or timeout
                rpSearchFailed.report(1);
                rtSearchFailed.report(time);
                boolean logDEBUG = Core.logger.shouldLog(Logger.DEBUG,this);
                if(logDEBUG) Core.logger.log(this, "Search failed in "+time+"ms on 
"+ref,
                                                new Exception("debug"), Logger.DEBUG);
-               lastAccessedTime = System.currentTimeMillis();
+               long now = System.currentTimeMillis();
+               lastAccessedTime = now;
+               // Exponential backoff
+               synchronized(this) {
+                       if(enteredBackoffTime + currentBackoffPeriod > now) {
+                               // Ignore, already backed off
+                               if(logDEBUG)
+                                       Core.logger.log(this, "Ignored a searchFailed 
because already backed off on "+this,
+                                                       Logger.DEBUG);
+                       } else {
+                               if(lastPartialSuccessTime > enteredBackoffTime) {
+                                       // We have had a transfer/DNF since we backed 
off
+                                       // Reset the backoff
+                                       currentBackoffPeriod = defaultBackoffPeriod;
+                               } else {
+                                       // Hasn't been a transfer/DNF in the meantime 
+                                       currentBackoffPeriod = currentBackoffPeriod +
+                                               random.nextInt(currentBackoffPeriod);
+                                       if(currentBackoffPeriod > Integer.MAX_VALUE/2)
+                                               currentBackoffPeriod = 
Integer.MAX_VALUE/2;
+                               }
+                               enteredBackoffTime = now;
+                               Core.logger.log(this, "Backing off "+this+" for 
"+currentBackoffPeriod+
+                                               "ms", Logger.MINOR);
+                       }
+               }
        }
        
        public void transferFailed(Key key, long time, long size) {
@@ -347,7 +381,7 @@
                if(logDEBUG) Core.logger.log(this, "Transfer failed in "+time+"ms ("+
                                                size+" bytes) on "+ref, new 
Exception("debug"), 
                                                Logger.DEBUG);
-               lastAccessedTime = System.currentTimeMillis();
+               lastAccessedTime = lastPartialSuccessTime = System.currentTimeMillis();
        }
        
        public void dataNotFound(Key key, long searchTime, int htl) {
@@ -360,7 +394,7 @@
                etDNF.reportTime(key, searchTime/htl);
                if(logDEBUG) Core.logger.log(this, "Data Not Found in "+searchTime+"ms 
on "+ref,
                                                new Exception("debug"), Logger.DEBUG);
-               lastAccessedTime = System.currentTimeMillis();
+               lastAccessedTime = lastPartialSuccessTime = System.currentTimeMillis();
        }
        
        public void transferSucceeded(Key key, long searchTime, int htl,
@@ -372,7 +406,8 @@
                synchronized(this) {
                        successes++;
                }
-               lastSuccessTime = System.currentTimeMillis();
+               lastSuccessTime = lastPartialSuccessTime = lastAccessedTime = 
+                       System.currentTimeMillis();
                epDNFGivenNotSearchFailed.
                        reportProbability(key, 0);
                rpDNF.report(0.0);
@@ -384,7 +419,6 @@
                                                " bytes per second", rate > 100000 ? 
Logger.NORMAL : Logger.DEBUG);
                        etTransferRate.reportTransferRate(key, rate*0.001); // convert 
to bytes per millisecond
                }
-               lastAccessedTime = System.currentTimeMillis();
        }
        
        public int getDataLength() {
@@ -467,7 +501,8 @@
          "Search died probability", "Transfer died probability", 
          "Search died time", 
          "Open Outbound Connections", "Open Inbound Connections",
-         "Minimum Transfer Rate", "Maximum Transfer Rate" };
+         "Minimum Transfer Rate", "Maximum Transfer Rate",
+         "Backed Off Until", "Backoff Length"};
        
        static class MyComparableStringMap 
            extends SimpleStringMap implements ComparableStringMap {
@@ -537,6 +572,13 @@
                TimeEstimator.HTMLReportTool reportTool = 
etTransferRate.getHTMLReportingTool();
                values[18] = reportTool.lowestString(TimeEstimator.TRANSFER_RATE);
                values[19] = reportTool.highestString(TimeEstimator.TRANSFER_RATE);
+               long backoffUntil = enteredBackoffTime + currentBackoffPeriod;
+               if(backoffUntil > now) {
+                       values[20] = new Long(backoffUntil - now);
+               } else {
+                       values[20] = new Long(0);
+               }
+               values[21] = new Integer(currentBackoffPeriod);
                return new MyComparableStringMap(values);
        }
        
@@ -918,5 +960,15 @@
                return 
                        (long)reportTool.convertFromRaw(etDNF.highestRaw(),
                                TimeEstimator.TIME);
+       }
+       
+       /* (non-Javadoc)
+        * @see freenet.node.rt.NodeEstimator#isBackedOff()
+        */
+       public boolean isBackedOff() {
+               long now = System.currentTimeMillis();
+               if(enteredBackoffTime + currentBackoffPeriod > now)
+                       return true;
+               else return false;
        }
 }

Index: NodeEstimator.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/rt/NodeEstimator.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -w -r1.16 -r1.17
--- NodeEstimator.java  13 Nov 2003 12:02:52 -0000      1.16
+++ NodeEstimator.java  13 Nov 2003 20:49:54 -0000      1.17
@@ -127,4 +127,9 @@
         * Write to a FieldSet for FNP transfer. Leave out anything unsuitable for 
transfer. 
         */
        abstract public FieldSet toFieldSet();
+
+       /**
+        * @return Whether we are currently backed off
+        */
+       abstract public boolean isBackedOff();
 }

Index: StandardNodeEstimatorFactory.java
===================================================================
RCS file: 
/cvsroot/freenet/freenet/src/freenet/node/rt/StandardNodeEstimatorFactory.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -w -r1.6 -r1.7
--- StandardNodeEstimatorFactory.java   13 Nov 2003 02:16:58 -0000      1.6
+++ StandardNodeEstimatorFactory.java   13 Nov 2003 20:49:54 -0000      1.7
@@ -6,6 +6,7 @@
 import freenet.Core;
 import freenet.FieldSet;
 import freenet.Key;
+import freenet.crypt.RandomSource;
 import freenet.node.NodeReference;
 import freenet.support.DataObjectPending;
 import freenet.support.Logger;
@@ -18,19 +19,22 @@
     NGRoutingTable ngrt;
     final RunningAverageFactory raf;
     final TimeEstimatorFactory rtef;
+    final RandomSource rand;
     
     public StandardNodeEstimatorFactory(NGRoutingTable ngrt,
                                                                                
RunningAverageFactory raf,
-                                                                               
TimeEstimatorFactory rtef) {
+                                                                               
TimeEstimatorFactory rtef, RandomSource rand) {
                this.ngrt = ngrt;
                this.raf = raf;
                this.rtef = rtef;
+               this.rand = rand;
     }
     
        public StandardNodeEstimatorFactory(RunningAverageFactory raf,
-                                                                               
TimeEstimatorFactory rtef) {
+                                                                               
TimeEstimatorFactory rtef, RandomSource rand) {
                this.raf = raf;
                this.rtef = rtef;
+               this.rand = rand;
     }
     
        
@@ -45,7 +49,7 @@
                                                                long maxSearchTime, 
long maxDNFTime) {
                // Create completely new NodeEstimator for the identity
        NodeEstimator ne = new StandardNodeEstimator(ngrt, ref, mem, e, raf, rtef, 
null,
-                                                                                rate, 
needConnection, maxPDNF, maxSearchTime, maxDNFTime);
+                                                                                rate, 
needConnection, maxPDNF, maxSearchTime, maxDNFTime, rand);
        if(Core.logger.shouldLog(Logger.DEBUG, this))
                Core.logger.log(this, "Created new NodeEstimator from scratch: "+ne, 
Logger.DEBUG);
        return ne;
@@ -58,14 +62,14 @@
                // Hrrm
                // Serialize in from the DOP
                return new StandardNodeEstimator(ngrt, ref, mem, raf, rtef, e,
-                                                                                
needConnection);
+                                                                                
needConnection, rand);
     }
     
     public NodeEstimator create(RoutingMemory mem, NodeReference ref,
                                                                FieldSet e, Key k, 
double rate, boolean needConnection, double maxPDNF,
                                                                long maxSearchTime, 
long maxDNFTime) {
                NodeEstimator ne = new StandardNodeEstimator(ngrt, ref, mem, e, raf, 
rtef, k, rate,
-                                                                                
needConnection, maxPDNF, maxSearchTime, maxDNFTime);
+                                                                                
needConnection, maxPDNF, maxSearchTime, maxDNFTime, rand);
                if(Core.logger.shouldLog(Logger.DEBUG, this))
                        Core.logger.log(this, "Created new NodeEstimator from scratch: 
"+ne, Logger.DEBUG);
                return ne;

_______________________________________________
cvs mailing list
[EMAIL PROTECTED]
http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/cvs

Reply via email to