Author: toad
Date: 2006-08-12 20:55:25 +0000 (Sat, 12 Aug 2006)
New Revision: 10050
Modified:
trunk/freenet/src/freenet/node/NodeClientCore.java
trunk/freenet/src/freenet/node/RequestStarterGroup.java
trunk/freenet/src/freenet/node/ThrottleWindowManager.java
trunk/freenet/src/freenet/support/SimpleFieldSet.java
trunk/freenet/src/freenet/support/math/BootstrappingDecayingRunningAverage.java
Log:
write load limiting data to disk every minute
Modified: trunk/freenet/src/freenet/node/NodeClientCore.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeClientCore.java 2006-08-12 19:54:58 UTC
(rev 10049)
+++ trunk/freenet/src/freenet/node/NodeClientCore.java 2006-08-12 20:55:25 UTC
(rev 10050)
@@ -186,6 +186,9 @@
public void start(Config config) throws NodeInitException {
+
+ requestStarters.start();
+
// TMCI
try{
TextModeClientInterfaceServer.maybeCreate(node, config);
Modified: trunk/freenet/src/freenet/node/RequestStarterGroup.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestStarterGroup.java 2006-08-12
19:54:58 UTC (rev 10049)
+++ trunk/freenet/src/freenet/node/RequestStarterGroup.java 2006-08-12
20:55:25 UTC (rev 10050)
@@ -1,10 +1,19 @@
package freenet.node;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
import freenet.client.async.ClientRequestScheduler;
import freenet.config.Config;
import freenet.config.SubConfig;
import freenet.crypt.RandomSource;
import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;
import freenet.support.math.BootstrappingDecayingRunningAverage;
public class RequestStarterGroup {
@@ -18,6 +27,7 @@
final RequestStarter sskRequestStarter;
final MyRequestThrottle sskInsertThrottle;
final RequestStarter sskInsertStarter;
+ final File nodeDir;
public final ClientRequestScheduler chkFetchScheduler;
public final ClientRequestScheduler chkPutScheduler;
@@ -27,6 +37,8 @@
RequestStarterGroup(Node node, NodeClientCore core, int portNumber,
RandomSource random, Config config) {
SubConfig schedulerConfig = new SubConfig("node.scheduler",
config);
+ this.nodeDir = node.nodeDir;
+
throttleWindow = new ThrottleWindowManager(2.0);
chkRequestThrottle = new MyRequestThrottle(throttleWindow,
5000, "CHK Request");
chkRequestStarter = new RequestStarter(core,
chkRequestThrottle, "CHK Request starter ("+portNumber+")",
node.requestOutputThrottle, node.requestInputThrottle,
node.localChkFetchBytesSentAverage, node.localChkFetchBytesReceivedAverage);
@@ -55,7 +67,15 @@
sskInsertStarter.start();
schedulerConfig.finishedInitialization();
+
}
+
+ public void start() {
+ ThrottlePersister persister = new ThrottlePersister();
+ Thread t = new Thread(persister, "Throttle data persister
thread");
+ t.setDaemon(true);
+ t.start();
+ }
public class MyRequestThrottle implements BaseRequestThrottle {
@@ -87,6 +107,12 @@
public String toString() {
return "rtt: "+roundTripTime.currentValue()+"
_s="+throttleWindow.currentValue();
}
+
+ public SimpleFieldSet exportFieldSet() {
+ SimpleFieldSet fs = new SimpleFieldSet();
+ fs.put("RoundTripTime", roundTripTime.exportFieldSet());
+ return fs;
+ }
}
public BaseRequestThrottle getCHKRequestThrottle() {
@@ -105,5 +131,87 @@
return sskInsertThrottle;
}
+ // FIXME convert these kind of threads to Checkpointed's and implement
a handler
+ // using the PacketSender/Ticker. Would save a few threads.
+ class ThrottlePersister implements Runnable {
+
+ public void run() {
+ while(true) {
+ try {
+ persistThrottle();
+ } catch (Throwable t) {
+ Logger.error(this, "Caught "+t, t);
+ }
+ try {
+ Thread.sleep(60*1000);
+ } catch (InterruptedException e) {
+ // Maybe it's time to wake up?
+ }
+ }
+ }
+
+ }
+
+ public void persistThrottle() {
+ SimpleFieldSet fs = persistToFieldSet();
+ File target = new File(nodeDir, "throttle.dat");
+ File tmp = new File(nodeDir, "throttle.dat.tmp");
+ try {
+ FileOutputStream fos = new FileOutputStream(tmp);
+ // FIXME common pattern, reuse it.
+ BufferedOutputStream bos = new
BufferedOutputStream(fos);
+ OutputStreamWriter osw = new OutputStreamWriter(bos,
"UTF-8");
+ try {
+ fs.writeTo(osw);
+ } catch (IOException e) {
+ try {
+ fos.close();
+ tmp.delete();
+ return;
+ } catch (IOException e1) {
+ // Ignore
+ }
+ }
+ try {
+ osw.close();
+ } catch (IOException e) {
+ // Huh?
+ Logger.error(this, "Caught while closing: "+e,
e);
+ return;
+ }
+ // Try an atomic rename
+ if(!tmp.renameTo(target)) {
+ // Not supported on some systems (Windows)
+ if(!target.delete()) {
+ if(target.exists()) {
+ Logger.error(this, "Could not
delete "+target+" - check permissions");
+ }
+ }
+ if(!tmp.renameTo(target)) {
+ Logger.error(this, "Could not rename
"+tmp+" to "+target+" - check permissions");
+ }
+ }
+ } catch (FileNotFoundException e) {
+ Logger.error(this, "Could not store throttle data to
disk: "+e, e);
+ return;
+ } catch (UnsupportedEncodingException e) {
+ Logger.error(this, "Unsupported encoding: UTF-8 !!!!:
"+e, e);
+ }
+
+ }
+
+ /**
+ * Persist the throttle data to a SimpleFieldSet.
+ */
+ private SimpleFieldSet persistToFieldSet() {
+ SimpleFieldSet fs = new SimpleFieldSet();
+ fs.put("ThrottleWindow", throttleWindow.exportFieldSet());
+ fs.put("CHKRequestThrottle",
chkRequestThrottle.exportFieldSet());
+ fs.put("SSKRequestThrottle",
sskRequestThrottle.exportFieldSet());
+ fs.put("CHKInsertThrottle", chkInsertThrottle.exportFieldSet());
+ fs.put("SSKInsertThrottle", sskInsertThrottle.exportFieldSet());
+ return fs;
+ }
+
}
Modified: trunk/freenet/src/freenet/node/ThrottleWindowManager.java
===================================================================
--- trunk/freenet/src/freenet/node/ThrottleWindowManager.java 2006-08-12
19:54:58 UTC (rev 10049)
+++ trunk/freenet/src/freenet/node/ThrottleWindowManager.java 2006-08-12
20:55:25 UTC (rev 10050)
@@ -1,6 +1,7 @@
package freenet.node;
import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;
public class ThrottleWindowManager {
@@ -39,4 +40,13 @@
+ _simulatedWindowSize + ", d:"
+ (((float) _droppedPackets / (float)
_totalPackets)) + "="+_droppedPackets+"/"+_totalPackets;
}
+
+ public SimpleFieldSet exportFieldSet() {
+ SimpleFieldSet fs = new SimpleFieldSet();
+ fs.put("Type", "ThrottleWindowManager");
+ fs.put("TotalPackets", _totalPackets);
+ fs.put("DroppedPackets", _droppedPackets);
+ fs.put("SimulatedWindowSize", _simulatedWindowSize);
+ return fs;
+ }
}
Modified: trunk/freenet/src/freenet/support/SimpleFieldSet.java
===================================================================
--- trunk/freenet/src/freenet/support/SimpleFieldSet.java 2006-08-12
19:54:58 UTC (rev 10049)
+++ trunk/freenet/src/freenet/support/SimpleFieldSet.java 2006-08-12
20:55:25 UTC (rev 10050)
@@ -208,6 +208,10 @@
put(key, Boolean.toString(b));
}
+ public void put(String key, double windowSize) {
+ put(key, Double.toString(windowSize));
+ }
+
/**
* Write the contents of the SimpleFieldSet to a Writer.
* @param osr
Modified:
trunk/freenet/src/freenet/support/math/BootstrappingDecayingRunningAverage.java
===================================================================
---
trunk/freenet/src/freenet/support/math/BootstrappingDecayingRunningAverage.java
2006-08-12 19:54:58 UTC (rev 10049)
+++
trunk/freenet/src/freenet/support/math/BootstrappingDecayingRunningAverage.java
2006-08-12 20:55:25 UTC (rev 10050)
@@ -5,6 +5,7 @@
import java.io.IOException;
import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;
/**
@@ -140,4 +141,14 @@
public synchronized long countReports() {
return reports;
}
+
+ public SimpleFieldSet exportFieldSet() {
+ SimpleFieldSet fs = new SimpleFieldSet();
+ fs.put("Type", "BootstrappingDecayingRunningAverage");
+ fs.put("CurrentValue", currentValue);
+ fs.put("Reports", reports);
+ fs.put("Zeros", zeros);
+ fs.put("Ones", ones);
+ return fs;
+ }
}