Author: toad
Date: 2005-11-18 01:11:36 +0000 (Fri, 18 Nov 2005)
New Revision: 7553

Added:
   trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java
Modified:
   trunk/freenet/src/freenet/node/RequestSender.java
   trunk/freenet/src/freenet/node/Version.java
Log:
189:
Doh.

Modified: trunk/freenet/src/freenet/node/RequestSender.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestSender.java   2005-11-18 01:04:54 UTC 
(rev 7552)
+++ trunk/freenet/src/freenet/node/RequestSender.java   2005-11-18 01:11:36 UTC 
(rev 7553)
@@ -91,7 +91,7 @@
                 // RNF
                 // Would be DNF if arrived with no HTL
                 // But here we've already routed it and that's been rejected.
-                finish(ROUTE_NOT_FOUND);
+                finish(ROUTE_NOT_FOUND, null);
                 return;
             }

@@ -108,7 +108,7 @@

             if(next == null) {
                 // Backtrack
-                finish(ROUTE_NOT_FOUND);
+                finish(ROUTE_NOT_FOUND, null);
                 return;
             }
             Logger.minor(this, "Routing insert to "+next);
@@ -151,7 +151,7 @@
             if(msg == null) {
                 // Timeout
                 // Treat as FNPRejectOverloadd
-                finish(REJECTED_OVERLOAD);
+                finish(REJECTED_OVERLOAD, next);
                 return;
             }

@@ -163,7 +163,7 @@
             if(msg.getSpec() == DMT.FNPRejectedOverload) {
                 // Failed. Propagate back to source.
                 // Source will reduce send rate.
-                finish(REJECTED_OVERLOAD);
+                finish(REJECTED_OVERLOAD, next);
                 return;
             }

@@ -186,12 +186,12 @@

             if(msg == null) {
                 // Timeout. Treat as FNPRejectOverload.
-                finish(REJECTED_OVERLOAD);
+                finish(REJECTED_OVERLOAD, next);
                 return;
             }

             if(msg.getSpec() == DMT.FNPDataNotFound) {
-                finish(DATA_NOT_FOUND);
+                finish(DATA_NOT_FOUND, next);
                 return;
             }

@@ -203,7 +203,7 @@
             }

             if(msg.getSpec() == DMT.FNPRejectedOverload) {
-                finish(REJECTED_OVERLOAD);
+                finish(REJECTED_OVERLOAD, next);
                 return;
             }

@@ -234,15 +234,15 @@
                         block = new CHKBlock(data, headers, key);
                     } catch (CHKVerifyException e1) {
                         Logger.normal(this, "Got data but verify failed: "+e1, 
e1);
-                        finish(VERIFY_FAILURE);
+                        finish(VERIFY_FAILURE, next);
                         return;
                     }
                     node.store(block);
-                    finish(SUCCESS);
+                    finish(SUCCESS, next);
                     return;
                 } catch (RetrievalException e) {
                     Logger.normal(this, "Transfer failed: "+e, e);
-                    finish(TRANSFER_FAILED);
+                    finish(TRANSFER_FAILED, next);
                     return;
                 }
             } finally {
@@ -295,16 +295,19 @@
         }            
     }

-    private void finish(int code) {
+    private void finish(int code, PeerNode next) {
         Logger.minor(this, "finish("+code+")");
         if(status != NOT_FINISHED)
                throw new IllegalStateException("finish() called with "+code+" 
when was already "+status);
         status = code;

-        if(status == REJECTED_OVERLOAD)
+        if(status == REJECTED_OVERLOAD) {
                node.getRequestThrottle().requestRejectedOverload();
-        else if(status == SUCCESS || status == ROUTE_NOT_FOUND || status == 
DATA_NOT_FOUND || status == VERIFY_FAILURE)
+               next.rejectedOverload();
+        } else if(status == SUCCESS || status == ROUTE_NOT_FOUND || status == 
DATA_NOT_FOUND || status == VERIFY_FAILURE) {
                
node.getRequestThrottle().requestCompleted(System.currentTimeMillis() - 
startTime);
+               next.didNotRejectOverload();
+        }

         synchronized(this) {
             notifyAll();

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2005-11-18 01:04:54 UTC (rev 
7552)
+++ trunk/freenet/src/freenet/node/Version.java 2005-11-18 01:11:36 UTC (rev 
7553)
@@ -20,10 +20,10 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       public static final int buildNumber = 188;
+       public static final int buildNumber = 189;

        /** Oldest build of Fred we will talk to */
-       public static final int lastGoodBuild = 188;
+       public static final int lastGoodBuild = 189;

        /** The highest reported build of fred */
        public static int highestSeenBuild = buildNumber;

Added: trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java
===================================================================
--- trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java      
2005-11-18 01:04:54 UTC (rev 7552)
+++ trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java      
2005-11-18 01:11:36 UTC (rev 7553)
@@ -0,0 +1,234 @@
+package freenet.support.math;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.BitSet;
+
+import freenet.support.HexUtil;
+import freenet.support.Logger;
+
+/**
+ * Simple running average for binary (0.0/1.0) values.
+ * Keeps the last 1000 values and generates a probability of
+ * the next value being 1.0.
+ * @author amphibian
+ * Created on May 14, 2004
+ */
+public class SimpleBinaryRunningAverage implements RunningAverage {
+
+    public Object clone() {
+        return new SimpleBinaryRunningAverage(this);
+    }
+    
+       static final int MAGIC = 0x4281;
+       
+       final int maximumSize;
+       int totalZeros;
+       int totalOnes;
+       int index;
+       long totalReported;
+       final double defaultValue;
+       final BitSet ba;
+       boolean logDEBUG;
+
+       private final int baSize() {
+               return Math.min((int)totalReported, maximumSize);
+       }
+       
+       public SimpleBinaryRunningAverage(int maxSize, double start) {
+               maximumSize = maxSize;
+               ba = new BitSet(maxSize);
+               totalZeros = totalOnes = index = 0;
+               totalReported = 0;
+               if(start < 0.0 || start > 1.0) {
+                   Logger.error(this, "Illegal default value: "+start+" on 
"+this,
+                           new Exception("debug"));
+                   start = Math.max(1.0, Math.min(0.0, start));
+               }
+               defaultValue = start;
+               logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
+       }
+       
+       public synchronized double currentValue() {
+           if(totalZeros < 0 || totalOnes < 0) {
+               Logger.error(this, "Argh in currentValue(): "+this,
+                       new Exception("debug"));
+               calculateTotalOnesZeros();
+           }
+               if(totalZeros == 0 && totalOnes == 0)
+                       return defaultValue;
+               return ((double)totalOnes) / (double)(totalZeros + totalOnes);
+       }
+       
+       public void report(double d) {
+               report(convert(d));
+       }
+       
+       public void report(long d) {
+               report((double)d);
+       }
+       
+       public synchronized void report(boolean value) {
+               if(logDEBUG)
+                       Logger.debug(this, "Reporting: "+value+" on "+this);
+               totalReported++;
+               if(totalReported > maximumSize) {
+                       // Remove the value, that is to be overwritten, from 
the calculations 
+                       boolean valueOverwriting = ba.get(index);
+                       if(valueOverwriting)
+                               totalOnes--;
+                       else
+                               totalZeros--;
+               }
+               ba.set(index, value);
+               index++;
+               if(index >= maximumSize) index = 0;
+               if(value)
+                       totalOnes++;
+               else
+                       totalZeros++;
+               if(logDEBUG)
+                       Logger.debug(this, "Reported: "+value+" on "+this);
+           if(totalZeros < 0 || totalOnes < 0) {
+               Logger.error(this, "Argh in report("+value+"): "+this,
+                       new Exception("debug"));
+               calculateTotalOnesZeros();
+           }
+       }
+       
+       // Compute what the resulting average -would be- if (value) were
+       // reported, WITHOUT ACTUALLY UPDATING THE STATE OF THIS OBJECT.
+       public double valueIfReported(boolean value) {
+               int to, tz;
+               synchronized(this) {
+                       to = totalOnes;
+                       tz = totalZeros;
+                       if( (totalReported+1) > maximumSize ) {
+                               // account for the bit that would be dropped
+                               boolean valueOverwriting = ba.get(index);
+                               if(valueOverwriting)
+                                       to--;
+                               else
+                                       tz--;
+                       }
+               }
+               if(value)
+                       to++;
+               else
+                       tz++;
+               return ((double)to) / (double)(tz + to);
+       }
+       
+       public String extraToString() {
+               return Integer.toString(totalZeros) + " 0s, "+
+                       totalOnes + " 1s, "+(totalZeros+totalOnes)+
+                       " total";
+       }
+       
+       public String toString() {
+               return super.toString() + " ("+extraToString()+")"+
+                       ", init="+defaultValue+", index="+index+", 
totalReported="+
+                       totalReported;
+       }
+       
+       public synchronized void writeDataTo(DataOutputStream out) throws 
IOException {
+               out.writeInt(MAGIC); // magic for this class
+               out.writeInt(1);
+               out.writeInt(baSize());
+               out.writeInt(index);
+               out.writeLong(totalReported);
+               out.write(HexUtil.bitsToBytes(ba, baSize()));
+       }
+       
+       public SimpleBinaryRunningAverage(int maxSize, DataInputStream dis) 
throws IOException {
+               logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
+               int magic = dis.readInt();
+               if(magic != MAGIC) throw new IOException("Invalid magic 
"+magic+" should be "+MAGIC+" - format change?");
+               int ver = dis.readInt();
+               if(ver != 1)
+                   throw new IOException("Invalid version: "+ver);
+               int size = dis.readInt();
+               if(size < 0) throw new IOException("Invalid size "+size);
+               if(size > maxSize) throw new IOException("Too big "+size);
+               index = dis.readInt();
+               if(index > size) throw new IOException("Invalid index");
+               totalReported = dis.readLong();
+               if(totalReported < 0) throw new IOException("Negative 
totalReported");
+               if(totalReported < size) throw new IOException("Invalid 
totalReported: "+totalReported+", size: "+size);
+               ba = new BitSet(maxSize);
+               maximumSize = maxSize;
+               byte[] b = new byte[HexUtil.countBytesForBits(size)];
+               dis.read(b);
+               HexUtil.bytesToBits(b, ba, size);
+               calculateTotalOnesZeros();
+               defaultValue = 0.5; // not used
+               if(logDEBUG)
+                       Logger.debug(this, "Created: "+this+" from "+dis);
+       }
+
+    public SimpleBinaryRunningAverage(SimpleBinaryRunningAverage a) {
+        this.ba = (BitSet) a.ba.clone();
+        this.defaultValue = a.defaultValue;
+        this.index = a.index;
+        this.maximumSize = a.maximumSize;
+        this.totalOnes = a.totalOnes;
+        this.totalReported = a.totalReported;
+        this.totalZeros = a.totalZeros;
+    }
+
+       private void calculateTotalOnesZeros() {
+               StringBuffer sb = new StringBuffer();
+               int tones = 0;
+               int tzeros = 0;
+               for(int i=0;i<baSize();i++) {
+                       if(ba.get(i)) {
+                               tones++;
+                               sb.append('1');
+                       } else {
+                               tzeros++;
+                               sb.append('0');
+                       }
+               }
+               totalOnes = tones;
+               totalZeros = tzeros;
+               if(Logger.shouldLog(Logger.DEBUG, this))
+                       Logger.debug(this, "Returning: "+totalZeros+" zeros, 
"+totalOnes+
+                                       " ones, binary: "+sb.toString());
+       }
+
+       protected String checkOnesZeros() {
+           StringBuffer sb = new StringBuffer();
+               int tones = 0;
+               int tzeros = 0;
+               for(int i=0;i<baSize();i++) {
+                       if(ba.get(i)) {
+                               tones++;
+                               sb.append('1');
+                       } else {
+                               tzeros++;
+                               sb.append('0');
+                       }
+               }
+               return "bits: " + sb.toString() + "counted " + tones + " ones 
and " + tzeros + " zeros"; 
+       }
+       
+       public int getDataLength() {
+               return 4 + 4 + 4 + 4 + 8 + HexUtil.countBytesForBits(baSize());
+       }
+
+       public boolean convert(double d) {
+               if(d > 1.0 || d < 0.0) throw new 
IllegalArgumentException("invalid : "+d);
+               if(d > 0.9) return true;
+               if(d < 0.1) return false;
+               throw new IllegalArgumentException("not one or other extreme!");
+       }
+       
+       public double valueIfReported(double d) {
+               return valueIfReported(convert(d));
+       }
+
+    public long countReports() {
+        return totalReported;
+    }
+}


Reply via email to