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;
+ }
+}