Author: toad
Date: 2006-02-21 02:31:47 +0000 (Tue, 21 Feb 2006)
New Revision: 8078
Added:
trunk/freenet/src/freenet/config/
trunk/freenet/src/freenet/config/BooleanCallback.java
trunk/freenet/src/freenet/config/BooleanOption.java
trunk/freenet/src/freenet/config/Config.java
trunk/freenet/src/freenet/config/FilePersistentConfig.java
trunk/freenet/src/freenet/config/IntCallback.java
trunk/freenet/src/freenet/config/IntOption.java
trunk/freenet/src/freenet/config/InvalidConfigValueException.java
trunk/freenet/src/freenet/config/LongCallback.java
trunk/freenet/src/freenet/config/LongOption.java
trunk/freenet/src/freenet/config/Option.java
trunk/freenet/src/freenet/config/OptionFormatException.java
trunk/freenet/src/freenet/config/ShortCallback.java
trunk/freenet/src/freenet/config/ShortOption.java
trunk/freenet/src/freenet/config/StringCallback.java
trunk/freenet/src/freenet/config/StringOption.java
trunk/freenet/src/freenet/config/SubConfig.java
trunk/freenet/src/freenet/node/LoggingConfigHandler.java
Removed:
trunk/freenet/src/freenet/config/BooleanCallback.java
trunk/freenet/src/freenet/config/BooleanOption.java
trunk/freenet/src/freenet/config/Config.java
trunk/freenet/src/freenet/config/FilePersistentConfig.java
trunk/freenet/src/freenet/config/IntCallback.java
trunk/freenet/src/freenet/config/IntOption.java
trunk/freenet/src/freenet/config/InvalidConfigValueException.java
trunk/freenet/src/freenet/config/LongCallback.java
trunk/freenet/src/freenet/config/LongOption.java
trunk/freenet/src/freenet/config/Option.java
trunk/freenet/src/freenet/config/OptionFormatException.java
trunk/freenet/src/freenet/config/ShortCallback.java
trunk/freenet/src/freenet/config/ShortOption.java
trunk/freenet/src/freenet/config/StringCallback.java
trunk/freenet/src/freenet/config/StringOption.java
trunk/freenet/src/freenet/config/SubConfig.java
Modified:
trunk/freenet/src/freenet/clients/http/FproxyToadlet.java
trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
trunk/freenet/src/freenet/io/comm/UdpSocketManager.java
trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java
trunk/freenet/src/freenet/node/CPUAdjustingSwapRequestInterval.java
trunk/freenet/src/freenet/node/LocationManager.java
trunk/freenet/src/freenet/node/Node.java
trunk/freenet/src/freenet/node/PeerManager.java
trunk/freenet/src/freenet/node/PeerNode.java
trunk/freenet/src/freenet/node/StaticSwapRequestInterval.java
trunk/freenet/src/freenet/node/SwapRequestInterval.java
trunk/freenet/src/freenet/node/TestnetHandler.java
trunk/freenet/src/freenet/node/TextModeClientInterface.java
trunk/freenet/src/freenet/node/Version.java
trunk/freenet/src/freenet/node/fcp/AllDataMessage.java
trunk/freenet/src/freenet/node/fcp/ClientGetMessage.java
trunk/freenet/src/freenet/node/fcp/ClientHelloMessage.java
trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java
trunk/freenet/src/freenet/node/fcp/DataFoundMessage.java
trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
trunk/freenet/src/freenet/node/fcp/FCPServer.java
trunk/freenet/src/freenet/node/fcp/FinishedCompressionMessage.java
trunk/freenet/src/freenet/node/fcp/GenerateSSKMessage.java
trunk/freenet/src/freenet/node/fcp/GetFailedMessage.java
trunk/freenet/src/freenet/node/fcp/IdentifierCollisionMessage.java
trunk/freenet/src/freenet/node/fcp/NodeHelloMessage.java
trunk/freenet/src/freenet/node/fcp/ProtocolErrorMessage.java
trunk/freenet/src/freenet/node/fcp/PutFailedMessage.java
trunk/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java
trunk/freenet/src/freenet/node/fcp/SSKKeypairMessage.java
trunk/freenet/src/freenet/node/fcp/SimpleProgressMessage.java
trunk/freenet/src/freenet/node/fcp/StartedCompressionMessage.java
trunk/freenet/src/freenet/node/fcp/URIGeneratedMessage.java
trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java
trunk/freenet/src/freenet/store/FreenetStore.java
trunk/freenet/src/freenet/support/Fields.java
trunk/freenet/src/freenet/support/FileLoggerHook.java
trunk/freenet/src/freenet/support/Logger.java
trunk/freenet/src/freenet/support/LoggerHook.java
trunk/freenet/src/freenet/support/LoggerHookChain.java
trunk/freenet/src/freenet/support/SimpleFieldSet.java
trunk/freenet/src/snmplib/SNMPStarter.java
Log:
450:
Initial draft of config support.
Merged from branches/config.
New invocation: java -cp ... freenet.node.Node <config filename>
New datastore format, believed to be back-compatible. If it's not, tough. Lifts
2GB and 64TB limits.
Modified: trunk/freenet/src/freenet/clients/http/FproxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FproxyToadlet.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/clients/http/FproxyToadlet.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -9,7 +9,14 @@
import freenet.client.FetchException;
import freenet.client.FetchResult;
import freenet.client.HighLevelSimpleClient;
+import freenet.config.BooleanCallback;
+import freenet.config.Config;
+import freenet.config.IntCallback;
+import freenet.config.InvalidConfigValueException;
+import freenet.config.SubConfig;
import freenet.keys.FreenetURI;
+import freenet.node.Node;
+import freenet.node.RequestStarter;
import freenet.support.Bucket;
import freenet.support.HTMLEncoder;
import freenet.support.Logger;
@@ -63,4 +70,74 @@
this.writeReply(ctx, 200, "text/html", "OK", notSupported);
}
+
+ static class FproxyEnabledCallback implements BooleanCallback {
+
+ final Node node;
+
+ FproxyEnabledCallback(Node n) {
+ this.node = n;
+ }
+
+ public boolean get() {
+ return node.getFproxy() != null;
+ }
+ public void set(boolean val) throws InvalidConfigValueException
{
+ if(val == get()) return;
+ throw new InvalidConfigValueException("Cannot change
fproxy enabled/disabled after startup");
+ }
+ }
+
+ static final int DEFAULT_FPROXY_PORT = 8888;
+
+ static class FproxyPortCallback implements IntCallback {
+
+ final Node node;
+
+ FproxyPortCallback(Node n) {
+ this.node = n;
+ }
+
+ public int get() {
+ SimpleToadletServer f = node.getToadletContainer();
+ if(f == null) return DEFAULT_FPROXY_PORT;
+ return f.port;
+ }
+
+ public void set(int port) throws InvalidConfigValueException {
+ if(port != get())
+ throw new InvalidConfigValueException("Cannot
change fproxy port number on the fly");
+ }
+ }
+
+ public static void maybeCreateFproxyEtc(Node node, Config config)
throws IOException {
+
+ SubConfig fproxyConfig = new SubConfig("fproxy", config);
+
+ fproxyConfig.register("enabled", true, 1, true, "Enable
fproxy?", "Whether to enable fproxy and related HTTP services",
+ new FproxyEnabledCallback(node));
+
+ boolean fproxyEnabled = fproxyConfig.getBoolean("enabled");
+
+ if(!fproxyEnabled) {
+ fproxyConfig.finishedInitialization();
+ return;
+ }
+
+ fproxyConfig.register("port", DEFAULT_FPROXY_PORT, 2, true,
"Fproxy port number", "Fproxy port number",
+ new FproxyPortCallback(node));
+
+ int port = fproxyConfig.getInt("port");
+
+ SimpleToadletServer server = new SimpleToadletServer(port);
+ node.setToadletContainer(server);
+ FproxyToadlet fproxy = new
FproxyToadlet(node.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS));
+ node.setFproxy(fproxy);
+ server.register(fproxy, "/", false);
+ fproxyConfig.finishedInitialization();
+ System.out.println("Starting fproxy on port "+(port));
+ }
+
+
+
}
Modified: trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -9,8 +9,15 @@
import java.util.Iterator;
import java.util.LinkedList;
+import freenet.config.BooleanCallback;
+import freenet.config.Config;
+import freenet.config.InvalidConfigValueException;
+import freenet.config.SubConfig;
+import freenet.node.Node;
+import freenet.node.RequestStarter;
import freenet.support.FileLoggerHook;
import freenet.support.Logger;
+import freenet.support.FileLoggerHook.IntervalParseException;
public class SimpleToadletServer implements ToadletContainer, Runnable {
@@ -54,7 +61,7 @@
return null;
}
- public static void main(String[] args) throws IOException {
+ public static void main(String[] args) throws IOException,
IntervalParseException {
File logDir = new File("logs-toadlettest");
logDir.mkdir();
FileLoggerHook logger = new FileLoggerHook(true, new File(logDir,
"test-1111").getAbsolutePath(),
Copied: trunk/freenet/src/freenet/config (from rev 8077,
branches/config/src/freenet/config)
Deleted: trunk/freenet/src/freenet/config/BooleanCallback.java
===================================================================
--- branches/config/src/freenet/config/BooleanCallback.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/config/BooleanCallback.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -1,22 +0,0 @@
-package freenet.config;
-
-/**
- * A callback to be called when a config value of integer type changes.
- * Also reports the current value.
- */
-public interface BooleanCallback {
-
- /**
- * Get the current, used value of the config variable.
- */
- boolean get();
-
- /**
- * Set the config variable to a new value.
- * @param val The new value.
- * @throws InvalidConfigOptionException If the new value is invalid for
- * this particular option.
- */
- void set(boolean val) throws InvalidConfigValueException;
-
-}
Copied: trunk/freenet/src/freenet/config/BooleanCallback.java (from rev 8077,
branches/config/src/freenet/config/BooleanCallback.java)
Deleted: trunk/freenet/src/freenet/config/BooleanOption.java
===================================================================
--- branches/config/src/freenet/config/BooleanOption.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/config/BooleanOption.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,52 +0,0 @@
-package freenet.config;
-
-public class BooleanOption extends Option {
-
- final boolean defaultValue;
- final BooleanCallback cb;
- private boolean currentValue;
-
- public BooleanOption(SubConfig conf, String optionName, boolean
defaultValue, int sortOrder,
- boolean expert, String shortDesc, String longDesc,
BooleanCallback cb) {
- super(conf, optionName, sortOrder, expert, shortDesc, longDesc);
- this.defaultValue = defaultValue;
- this.cb = cb;
- this.currentValue = defaultValue;
- }
-
- /** Get the current value. This is the value in use if we have finished
- * initialization, otherwise it is the value set at startup (possibly
the default). */
- public boolean getValue() {
- if(config.hasFinishedInitialization())
- return currentValue = cb.get();
- else return currentValue;
- }
-
- public void setValue(String val) throws InvalidConfigValueException {
- if(val.equalsIgnoreCase("true") || val.equalsIgnoreCase("yes"))
{
- set(true);
- } else if(val.equalsIgnoreCase("false") ||
val.equalsIgnoreCase("no")) {
- set(false);
- } else
- throw new OptionFormatException("Unrecognized boolean:
"+val);
- }
-
- public void set(boolean b) throws InvalidConfigValueException {
- cb.set(b);
- currentValue = b;
- }
-
- public String getValueString() {
- return Boolean.toString(getValue());
- }
-
- public void setInitialValue(String val) throws
InvalidConfigValueException {
- if(val.equalsIgnoreCase("true") || val.equalsIgnoreCase("yes"))
{
- currentValue = true;
- } else if(val.equalsIgnoreCase("false") ||
val.equalsIgnoreCase("no")) {
- currentValue = false;
- } else
- throw new OptionFormatException("Unrecognized boolean:
"+val);
- }
-
-}
Copied: trunk/freenet/src/freenet/config/BooleanOption.java (from rev 8077,
branches/config/src/freenet/config/BooleanOption.java)
Deleted: trunk/freenet/src/freenet/config/Config.java
===================================================================
--- branches/config/src/freenet/config/Config.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/config/Config.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,40 +0,0 @@
-package freenet.config;
-
-import java.io.IOException;
-import java.util.HashMap;
-
-/** Global configuration object for a node. SubConfig's register here.
- * Handles writing to a file etc.
- */
-public class Config {
-
- protected final HashMap configsByPrefix;
-
- public Config() {
- configsByPrefix = new HashMap();
- }
-
- public void register(SubConfig sc) {
- synchronized(this) {
- if(configsByPrefix.containsKey(sc.prefix))
- throw new IllegalArgumentException("Already
registered "+sc.prefix+": "+sc);
- configsByPrefix.put(sc.prefix, sc);
- }
- }
-
- /** Write current config to disk
- * @throws IOException */
- public void store() {
- // Do nothing
- }
-
- /** Finished initialization */
- public void finishedInit() {
- // Do nothing
- }
-
- public void onRegister(SubConfig config, Option o) {
- // Do nothing
- }
-
-}
Copied: trunk/freenet/src/freenet/config/Config.java (from rev 8077,
branches/config/src/freenet/config/Config.java)
Deleted: trunk/freenet/src/freenet/config/FilePersistentConfig.java
===================================================================
--- branches/config/src/freenet/config/FilePersistentConfig.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/config/FilePersistentConfig.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -1,129 +0,0 @@
-package freenet.config;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.Iterator;
-
-import freenet.support.Logger;
-import freenet.support.SimpleFieldSet;
-import freenet.support.io.LineReadingInputStream;
-
-/**
- * Global Config object which persists to a file.
- *
- * Reads the config file into a SimpleFieldSet when created.
- * During init, SubConfig's are registered, and fed the relevant parts of the
SFS.
- * Once initialization has finished, we check whether there are any options
remaining.
- * If so, we complain about them.
- * And then we write the config file back out.
- */
-public class FilePersistentConfig extends Config {
-
- final File filename;
- final File tempFilename;
- private SimpleFieldSet origConfigFileContents;
-
- public FilePersistentConfig(File f) throws IOException {
- this.filename = f;
- this.tempFilename = new File(f.getPath()+".tmp");
- if(f.exists()) {
- if(!f.canWrite()) {
- Logger.error(this, "Warning: Cannot write to
config file!");
- System.err.println("Warning: Cannot write to
config file.");
- }
- if(f.canRead()) {
- try {
- initialLoad();
- } catch (FileNotFoundException e) {
- System.err.println("No config file
found, creating new: "+f);
- } // Other IOE's indicate a more serious
problem.
- } else {
- throw new IOException("Cannot read config
file");
- }
- } else {
- System.err.println("No config file found, creating new:
"+f);
- }
- }
-
- /** Load the config file into a SimpleFieldSet.
- * @throws IOException */
- private void initialLoad() throws IOException {
- FileInputStream fis = new FileInputStream(filename);
- LineReadingInputStream lis = new LineReadingInputStream(fis);
- origConfigFileContents = new SimpleFieldSet(lis, 4096, 256,
true);
- }
-
- public void register(SubConfig sc) {
- super.register(sc);
- if(origConfigFileContents != null) {
- SimpleFieldSet sfs =
origConfigFileContents.subset(sc.prefix);
- Logger.minor(this, "Registering "+sc+": "+sfs);
- // Set all the options
- if(sfs != null)
- sc.setOptions(sfs);
- }
- }
-
- /**
- * Finished initialization. So any remaining options must be invalid.
- */
- public void finishedInit() {
- if(origConfigFileContents == null) return;
- Iterator i = origConfigFileContents.keyIterator();
- while(i.hasNext()) {
- String key = (String) i.next();
- Logger.error(this, "Unknown option: "+key+"
(value="+origConfigFileContents.get(key));
- }
- }
-
- public void store() {
- try {
- innerStore();
- } catch (IOException e) {
- String err = "Cannot store config: "+e;
- Logger.error(this, err, e);
- System.err.println(err);
- e.printStackTrace();
- }
- }
-
- public void innerStore() throws IOException {
- SimpleFieldSet fs = exportFieldSet();
- Logger.minor(this, "fs = "+fs);
- FileOutputStream fos = new FileOutputStream(tempFilename);
- BufferedWriter bw = new BufferedWriter(new
OutputStreamWriter(fos));
- fs.writeTo(bw);
- bw.close();
- tempFilename.renameTo(filename);
- }
-
- private SimpleFieldSet exportFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet(true);
- SubConfig[] configs;
- synchronized(this) {
- configs = (SubConfig[])
configsByPrefix.values().toArray(new SubConfig[configsByPrefix.size()]);
- }
- for(int i=0;i<configs.length;i++) {
- SimpleFieldSet scfs = configs[i].exportFieldSet();
- fs.put(configs[i].prefix, scfs);
- }
- return fs;
- }
-
- public void onRegister(SubConfig config, Option o) {
- if(origConfigFileContents == null) return;
- String name =
config.prefix+SimpleFieldSet.MULTI_LEVEL_CHAR+o.name;
- String val = origConfigFileContents.get(name);
- if(val == null) return;
- try {
- o.setInitialValue(val);
- } catch (InvalidConfigValueException e) {
- Logger.error(this, "Could not parse config option
"+name+": "+e, e);
- }
- }
-}
Copied: trunk/freenet/src/freenet/config/FilePersistentConfig.java (from rev
8077, branches/config/src/freenet/config/FilePersistentConfig.java)
Deleted: trunk/freenet/src/freenet/config/IntCallback.java
===================================================================
--- branches/config/src/freenet/config/IntCallback.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/config/IntCallback.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,22 +0,0 @@
-package freenet.config;
-
-/**
- * A callback to be called when a config value of integer type changes.
- * Also reports the current value.
- */
-public interface IntCallback {
-
- /**
- * Get the current, used value of the config variable.
- */
- int get();
-
- /**
- * Set the config variable to a new value.
- * @param val The new value.
- * @throws InvalidConfigOptionException If the new value is invalid for
- * this particular option.
- */
- void set(int val) throws InvalidConfigValueException;
-
-}
Copied: trunk/freenet/src/freenet/config/IntCallback.java (from rev 8077,
branches/config/src/freenet/config/IntCallback.java)
Deleted: trunk/freenet/src/freenet/config/IntOption.java
===================================================================
--- branches/config/src/freenet/config/IntOption.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/config/IntOption.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,63 +0,0 @@
-package freenet.config;
-
-import freenet.support.Fields;
-
-/** Integer config variable */
-public class IntOption extends Option {
-
- final int defaultValue;
- final IntCallback cb;
- private int currentValue;
- // Cache it mostly so that we can keep SI units
- private String cachedStringValue;
-
- public IntOption(SubConfig conf, String optionName, int defaultValue,
String defaultValueString,
- int sortOrder, boolean expert, String shortDesc, String
longDesc, IntCallback cb) {
- super(conf, optionName, sortOrder, expert, shortDesc, longDesc);
- this.defaultValue = defaultValue;
- this.cb = cb;
- this.currentValue = defaultValue;
- this.cachedStringValue = defaultValueString;
- }
-
- public IntOption(SubConfig conf, String optionName, String
defaultValueString,
- int sortOrder, boolean expert, String shortDesc, String
longDesc, IntCallback cb) {
- super(conf, optionName, sortOrder, expert, shortDesc, longDesc);
- this.defaultValue = Fields.parseInt(defaultValueString);
- this.cb = cb;
- this.currentValue = defaultValue;
- this.cachedStringValue = defaultValueString;
- }
-
- /** Get the current value. This is the value in use if we have finished
- * initialization, otherwise it is the value set at startup (possibly
the default). */
- public int getValue() {
- if(config.hasFinishedInitialization()) {
- int val = cb.get();
- if(currentValue != val) {
- currentValue = val;
- cachedStringValue = null;
- }
- }
- return currentValue;
- }
-
- public void setValue(String val) throws InvalidConfigValueException {
- int x = Fields.parseInt(val);
- cb.set(x);
- cachedStringValue = val;
- currentValue = x;
- }
-
- public void setInitialValue(String val) {
- int x = Fields.parseInt(val);
- cachedStringValue = val;
- currentValue = x;
- }
-
- public String getValueString() {
- if(cachedStringValue != null) return cachedStringValue;
- return Integer.toString(getValue());
- }
-
-}
Copied: trunk/freenet/src/freenet/config/IntOption.java (from rev 8077,
branches/config/src/freenet/config/IntOption.java)
Deleted: trunk/freenet/src/freenet/config/InvalidConfigValueException.java
===================================================================
--- branches/config/src/freenet/config/InvalidConfigValueException.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/config/InvalidConfigValueException.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -1,16 +0,0 @@
-package freenet.config;
-
-/**
- * Thrown when the node refuses to set a config variable to a particular
- * value because it is invalid. Just because this is not thrown does not
- * necessarily mean that there are no problems with the value defined,
- * it merely means that there are no immediately detectable problems with
- * it.
- */
-public class InvalidConfigValueException extends Exception {
-
- public InvalidConfigValueException(String msg) {
- super(msg);
- }
-
-}
Copied: trunk/freenet/src/freenet/config/InvalidConfigValueException.java (from
rev 8077, branches/config/src/freenet/config/InvalidConfigValueException.java)
Deleted: trunk/freenet/src/freenet/config/LongCallback.java
===================================================================
--- branches/config/src/freenet/config/LongCallback.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/config/LongCallback.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,22 +0,0 @@
-package freenet.config;
-
-/**
- * A callback to be called when a config value of long type changes.
- * Also reports the current value.
- */
-public interface LongCallback {
-
- /**
- * Get the current, used value of the config variable.
- */
- long get();
-
- /**
- * Set the config variable to a new value.
- * @param val The new value.
- * @throws InvalidConfigOptionException If the new value is invalid for
- * this particular option.
- */
- void set(long val) throws InvalidConfigValueException;
-
-}
Copied: trunk/freenet/src/freenet/config/LongCallback.java (from rev 8077,
branches/config/src/freenet/config/LongCallback.java)
Deleted: trunk/freenet/src/freenet/config/LongOption.java
===================================================================
--- branches/config/src/freenet/config/LongOption.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/config/LongOption.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,63 +0,0 @@
-package freenet.config;
-
-import freenet.support.Fields;
-
-/** Long config variable */
-public class LongOption extends Option {
-
- final long defaultValue;
- final LongCallback cb;
- private long currentValue;
- // Cache it mostly so that we can keep SI units
- private String cachedStringValue;
-
- public LongOption(SubConfig conf, String optionName, long defaultValue,
String defaultValueString,
- int sortOrder, boolean expert, String shortDesc, String
longDesc, LongCallback cb) {
- super(conf, optionName, sortOrder, expert, shortDesc, longDesc);
- this.defaultValue = defaultValue;
- this.cb = cb;
- this.currentValue = defaultValue;
- this.cachedStringValue = defaultValueString;
- }
-
- public LongOption(SubConfig conf, String optionName, String
defaultValueString,
- int sortOrder, boolean expert, String shortDesc, String
longDesc, LongCallback cb) {
- super(conf, optionName, sortOrder, expert, shortDesc, longDesc);
- this.defaultValue = Fields.parseLong(defaultValueString);
- this.cb = cb;
- this.currentValue = defaultValue;
- this.cachedStringValue = defaultValueString;
- }
-
- /** Get the current value. This is the value in use if we have finished
- * initialization, otherwise it is the value set at startup (possibly
the default). */
- public long getValue() {
- if(config.hasFinishedInitialization()) {
- long val = cb.get();
- if(currentValue != val) {
- currentValue = val;
- cachedStringValue = null;
- }
- }
- return currentValue;
- }
-
- public void setValue(String val) throws InvalidConfigValueException {
- long x = Fields.parseLong(val);
- cb.set(x);
- cachedStringValue = val;
- currentValue = x;
- }
-
- public String getValueString() {
- if(cachedStringValue != null) return cachedStringValue;
- return Long.toString(getValue());
- }
-
- public void setInitialValue(String val) throws
InvalidConfigValueException {
- long x = Fields.parseLong(val);
- cachedStringValue = val;
- currentValue = x;
- }
-
-}
Copied: trunk/freenet/src/freenet/config/LongOption.java (from rev 8077,
branches/config/src/freenet/config/LongOption.java)
Deleted: trunk/freenet/src/freenet/config/Option.java
===================================================================
--- branches/config/src/freenet/config/Option.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/config/Option.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,41 +0,0 @@
-package freenet.config;
-
-/**
- * A config option.
- */
-public abstract class Option {
-
- /** The parent SubConfig object */
- final SubConfig config;
- /** The option name */
- final String name;
- /** The sort order */
- final int sortOrder;
- /** Is this config variable expert-only? */
- final boolean expert;
- /** Short description of value e.g. "FCP port" */
- final String shortDesc;
- /** Long description of value e.g. "The TCP port to listen for FCP
connections on" */
- final String longDesc;
-
- Option(SubConfig config, String name, int sortOrder, boolean expert,
String shortDesc, String longDesc) {
- this.config = config;
- this.name = name;
- this.sortOrder = sortOrder;
- this.expert = expert;
- this.shortDesc = shortDesc;
- this.longDesc = longDesc;
- }
-
- public abstract void setValue(String val) throws
InvalidConfigValueException;
-
- public abstract String getValueString();
-
- /** Set to a value from the config file; this is not passed on to the
callback, as we
- * expect the client-side initialization to check the value. The
callback is not valid
- * until the client calls finishedInitialization().
- * @throws InvalidConfigValueException
- */
- public abstract void setInitialValue(String val) throws
InvalidConfigValueException;
-
-}
Copied: trunk/freenet/src/freenet/config/Option.java (from rev 8077,
branches/config/src/freenet/config/Option.java)
Deleted: trunk/freenet/src/freenet/config/OptionFormatException.java
===================================================================
--- branches/config/src/freenet/config/OptionFormatException.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/config/OptionFormatException.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -1,13 +0,0 @@
-package freenet.config;
-
-/**
- * Thrown when a format error occurs, and we cannot parse the string set into
the appropriate
- * type.
- */
-public class OptionFormatException extends InvalidConfigValueException {
-
- public OptionFormatException(String msg) {
- super(msg);
- }
-
-}
Copied: trunk/freenet/src/freenet/config/OptionFormatException.java (from rev
8077, branches/config/src/freenet/config/OptionFormatException.java)
Deleted: trunk/freenet/src/freenet/config/ShortCallback.java
===================================================================
--- branches/config/src/freenet/config/ShortCallback.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/config/ShortCallback.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,22 +0,0 @@
-package freenet.config;
-
-/**
- * A callback to be called when a config value of short type changes.
- * Also reports the current value.
- */
-public interface ShortCallback {
-
- /**
- * Get the current, used value of the config variable.
- */
- short get();
-
- /**
- * Set the config variable to a new value.
- * @param val The new value.
- * @throws InvalidConfigOptionException If the new value is invalid for
- * this particular option.
- */
- void set(short val) throws InvalidConfigValueException;
-
-}
Copied: trunk/freenet/src/freenet/config/ShortCallback.java (from rev 8077,
branches/config/src/freenet/config/ShortCallback.java)
Deleted: trunk/freenet/src/freenet/config/ShortOption.java
===================================================================
--- branches/config/src/freenet/config/ShortOption.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/config/ShortOption.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,42 +0,0 @@
-package freenet.config;
-
-import freenet.support.Fields;
-
-public class ShortOption extends Option {
-
- final short defaultValue;
- final ShortCallback cb;
- private short currentValue;
-
- public ShortOption(SubConfig conf, String optionName, short
defaultValue, int sortOrder,
- boolean expert, String shortDesc, String longDesc,
ShortCallback cb) {
- super(conf, optionName, sortOrder, expert, shortDesc, longDesc);
- this.defaultValue = defaultValue;
- this.cb = cb;
- this.currentValue = defaultValue;
- }
-
- /** Get the current value. This is the value in use if we have finished
- * initialization, otherwise it is the value set at startup (possibly
the default). */
- public short getValue() {
- if(config.hasFinishedInitialization())
- return currentValue = cb.get();
- else return currentValue;
- }
-
- public void setValue(String val) throws InvalidConfigValueException {
- short x = Fields.parseShort(val);
- cb.set(x);
- currentValue = x;
- }
-
- public String getValueString() {
- return Short.toString(getValue());
- }
-
- public void setInitialValue(String val) throws
InvalidConfigValueException {
- short x = Fields.parseShort(val);
- currentValue = x;
- }
-
-}
Copied: trunk/freenet/src/freenet/config/ShortOption.java (from rev 8077,
branches/config/src/freenet/config/ShortOption.java)
Deleted: trunk/freenet/src/freenet/config/StringCallback.java
===================================================================
--- branches/config/src/freenet/config/StringCallback.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/config/StringCallback.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -1,19 +0,0 @@
-package freenet.config;
-
-/** Callback (getter/setter) for a string config variable */
-public interface StringCallback {
-
- /**
- * Get the current, used value of the config variable.
- */
- String get();
-
- /**
- * Set the config variable to a new value.
- * @param val The new value.
- * @throws InvalidConfigOptionException If the new value is invalid for
- * this particular option.
- */
- void set(String val) throws InvalidConfigValueException;
-
-}
Copied: trunk/freenet/src/freenet/config/StringCallback.java (from rev 8077,
branches/config/src/freenet/config/StringCallback.java)
Deleted: trunk/freenet/src/freenet/config/StringOption.java
===================================================================
--- branches/config/src/freenet/config/StringOption.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/config/StringOption.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,38 +0,0 @@
-package freenet.config;
-
-public class StringOption extends Option {
-
- final String defaultValue;
- final StringCallback cb;
- private String currentValue;
-
- public StringOption(SubConfig conf, String optionName, String
defaultValue, int sortOrder,
- boolean expert, String shortDesc, String longDesc,
StringCallback cb) {
- super(conf, optionName, sortOrder, expert, shortDesc, longDesc);
- this.defaultValue = defaultValue;
- this.cb = cb;
- this.currentValue = defaultValue;
- }
-
- /** Get the current value. This is the value in use if we have finished
- * initialization, otherwise it is the value set at startup (possibly
the default). */
- public String getValue() {
- if(config.hasFinishedInitialization())
- return currentValue = cb.get();
- else return currentValue;
- }
-
- public void setValue(String val) throws InvalidConfigValueException {
- cb.set(val);
- this.currentValue = val;
- }
-
- public String getValueString() {
- return getValue();
- }
-
- public void setInitialValue(String val) throws
InvalidConfigValueException {
- this.currentValue = val;
- }
-
-}
Copied: trunk/freenet/src/freenet/config/StringOption.java (from rev 8077,
branches/config/src/freenet/config/StringOption.java)
Deleted: trunk/freenet/src/freenet/config/SubConfig.java
===================================================================
--- branches/config/src/freenet/config/SubConfig.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/config/SubConfig.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,168 +0,0 @@
-package freenet.config;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import freenet.support.Logger;
-import freenet.support.SimpleFieldSet;
-
-/**
- * A specific configuration block.
- */
-public class SubConfig {
-
- private final HashMap map;
- public final Config config;
- final String prefix;
- private boolean hasInitialized;
-
- public SubConfig(String prefix, Config config) {
- this.config = config;
- this.prefix = prefix;
- map = new HashMap();
- hasInitialized = false;
- config.register(this);
- }
-
- public void register(Option o) {
- synchronized(this) {
- if(o.name.indexOf(SimpleFieldSet.MULTI_LEVEL_CHAR) !=
-1)
- throw new IllegalArgumentException("Option
names must not contain "+SimpleFieldSet.MULTI_LEVEL_CHAR);
- if(map.containsKey(o.name))
- throw new IllegalArgumentException("Already
registered: "+o.name+" on "+this);
- map.put(o.name, o);
- }
- config.onRegister(this, o);
- }
-
- public void register(String optionName, int defaultValue, int sortOrder,
- boolean expert, String shortDesc, String longDesc,
IntCallback cb) {
- register(new IntOption(this, optionName, defaultValue, null,
sortOrder, expert, shortDesc, longDesc, cb));
- }
-
- public void register(String optionName, long defaultValue, int
sortOrder,
- boolean expert, String shortDesc, String longDesc,
LongCallback cb) {
- register(new LongOption(this, optionName, defaultValue, null,
sortOrder, expert, shortDesc, longDesc, cb));
- }
-
- public void register(String optionName, String defaultValueString, int
sortOrder,
- boolean expert, String shortDesc, String longDesc,
IntCallback cb) {
- register(new IntOption(this, optionName, defaultValueString,
sortOrder, expert, shortDesc, longDesc, cb));
- }
-
- public void register(String optionName, String defaultValueString, int
sortOrder,
- boolean expert, String shortDesc, String longDesc,
LongCallback cb) {
- register(new LongOption(this, optionName, defaultValueString,
sortOrder, expert, shortDesc, longDesc, cb));
- }
-
- public void register(String optionName, boolean defaultValue, int
sortOrder,
- boolean expert, String shortDesc, String longDesc,
BooleanCallback cb) {
- register(new BooleanOption(this, optionName, defaultValue,
sortOrder, expert, shortDesc, longDesc, cb));
- }
-
- public void register(String optionName, String defaultValue, int
sortOrder,
- boolean expert, String shortDesc, String longDesc,
StringCallback cb) {
- register(new StringOption(this, optionName, defaultValue,
sortOrder, expert, shortDesc, longDesc, cb));
- }
-
- public void register(String optionName, short defaultValue, int
sortOrder,
- boolean expert, String shortDesc, String longDesc,
ShortCallback cb) {
- register(new ShortOption(this, optionName, defaultValue,
sortOrder, expert, shortDesc, longDesc, cb));
- }
-
- public int getInt(String optionName) {
- IntOption o;
- synchronized(this) {
- o = (IntOption) map.get(optionName);
- }
- return o.getValue();
- }
-
- public long getLong(String optionName) {
- LongOption o;
- synchronized(this) {
- o = (LongOption) map.get(optionName);
- }
- return o.getValue();
- }
-
- public boolean getBoolean(String optionName) {
- BooleanOption o;
- synchronized(this) {
- o = (BooleanOption) map.get(optionName);
- }
- return o.getValue();
- }
-
- public String getString(String optionName) {
- StringOption o;
- synchronized(this) {
- o = (StringOption) map.get(optionName);
- }
- return o.getValue();
- }
-
- public short getShort(String optionName) {
- ShortOption o;
- synchronized(this) {
- o = (ShortOption) map.get(optionName);
- }
- return o.getValue();
- }
-
- /**
- * Has the object we are attached to finished initialization?
- */
- public boolean hasFinishedInitialization() {
- return hasInitialized;
- }
-
- /**
- * Called when the object we are attached to has finished init.
- * After this point, the callbacks are authoritative for values of
- * config variables, and will be called when values are changed by
- * the user.
- */
- public void finishedInitialization() {
- hasInitialized = true;
- }
-
- /**
- * Set options from a SimpleFieldSet. Once we process an option, we
must remove it.
- */
- public void setOptions(SimpleFieldSet sfs) {
- Set entrySet = map.entrySet();
- Iterator i = entrySet.iterator();
- while(i.hasNext()) {
- Map.Entry entry = (Map.Entry) i.next();
- String key = (String) entry.getKey();
- Option o = (Option) entry.getValue();
- String val = sfs.get(key);
- if(val != null) {
- try {
- o.setValue(val);
- } catch (InvalidConfigValueException e) {
- String msg = "Invalid config value:
"+prefix+SimpleFieldSet.MULTI_LEVEL_CHAR+key+" = "+val+" : error: "+e;
- Logger.error(this, msg, e);
- System.err.println(msg); // might be
about logging?
- }
- }
- }
- }
-
- public SimpleFieldSet exportFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet(true);
- Set entrySet = map.entrySet();
- Iterator i = entrySet.iterator();
- while(i.hasNext()) {
- Map.Entry entry = (Map.Entry) i.next();
- String key = (String) entry.getKey();
- Option o = (Option) entry.getValue();
- fs.put(key, o.getValueString());
- }
- return fs;
- }
-
-}
Copied: trunk/freenet/src/freenet/config/SubConfig.java (from rev 8077,
branches/config/src/freenet/config/SubConfig.java)
Modified: trunk/freenet/src/freenet/io/comm/UdpSocketManager.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/UdpSocketManager.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/io/comm/UdpSocketManager.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -77,7 +77,6 @@
public UdpSocketManager(int listenPort) throws SocketException {
super("UdpSocketManager sender thread on port " + listenPort);
- try {
// Keep the Updater code in, just commented out, for now
// We may want to be able to do on-line updates.
// if (Updater.hasResource()) {
@@ -85,9 +84,6 @@
// } else {
_sock = new DatagramSocket(listenPort);
// }
- } catch (BindException e) {
- Logger.fatal(UdpSocketManager.class, -1, "Couldn't
connect to UDP port " + listenPort + ", is another instance of Dijjer
running?");
- }
// Only used for debugging, no need to seed from Yarrow
dropRandom = new Random();
}
Modified: trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java
===================================================================
--- trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -52,43 +52,106 @@
final PacketThrottle throttle;
long timeAllSent = -1;
+ // FIXME make this stuff non-static. Have a context object for limiting.
+
// Static stuff for global bandwidth limiter
/** Synchronization object for bandwidth limiting */
static final Object lastPacketSendTimeSync = new Object();
+ // Use nanosecond long values for accuracy reasons
/** Time at which the last known packet is scheduled to be sent.
* We will not send another packet until at least minPacketDelay ms
after this time. */
- static long hardLastPacketSendTime = System.currentTimeMillis();
+ static long hardLastPacketSendTimeNSec = System.currentTimeMillis() *
1000*1000;
/** Minimum interval between packet sends, for overall hard bandwidth
limiter */
- static long minPacketDelay = 0;
+ static int minPacketDelayNSec = 0;
/** Minimum average interval between packet sends, for averaged (soft)
overall
* bandwidth usage limiter. */
- static long minSoftDelay = 0;
+ static int minSoftDelayNSec = 0;
/** "Soft" equivalent to hardLastPacketSendTime. Can lag up to half the
softLimitPeriod
* behind the current time. Otherwise is similar. This gives it
flexibility; we can have
* spurts above the average limit, but over the softLimitPeriod, it
will average out to
* the target minSoftDelay. */
- static long softLastPacketSendTime = System.currentTimeMillis();
+ static long softLastPacketSendTimeNSec = System.currentTimeMillis() *
1000*1000;
/** Period over which the soft limiter should work */
- static long softLimitPeriod;
+ static long softLimitPeriodNSec;
- public static void setMinPacketInterval(int delay) {
+ /**
+ * Set the hard bandwidth limiter.
+ * @param bytesPerSecond The maximum number of bytes (of data blocks)
to be sent in any
+ * one second.
+ */
+ public static void setHardBandwidthLimit(int bytesPerSecond) {
+ int newMinPacketDelayNS =
convertBytesPerSecondToNanosPerPacket(bytesPerSecond);
synchronized(lastPacketSendTimeSync) {
- minPacketDelay = delay;
+ if(minPacketDelayNSec != newMinPacketDelayNS) {
+ minPacketDelayNSec = newMinPacketDelayNS;
+ hardLastPacketSendTimeNSec =
System.currentTimeMillis() * 1000*1000;
+ }
}
}
+
+ public static int convertBytesPerSecondToNanosPerPacket(int
bytesPerSecond) {
+ if(bytesPerSecond <= 0)
+ return 0; // no limits
+
+ int packetSize = getPacketSize();
+ double minNanoSecondsBetweenPackets =
+ ((1000.0*1000.0*1000.0) * packetSize) / ((double)
bytesPerSecond);
+ int newMinPacketDelayNS = (int) minNanoSecondsBetweenPackets;
+ double inaccuracy = minNanoSecondsBetweenPackets -
newMinPacketDelayNS;
+ double inaccuracyPercent = (inaccuracy /
minNanoSecondsBetweenPackets) * 100.0;
+ Logger.minor(BlockTransmitter.class, "Quantization inaccuracy:
"+inaccuracyPercent+"%");
+ return newMinPacketDelayNS;
+ }
- public static void setSoftMinPacketInterval(int delay) {
+ public static int convertBytesPerPeriodToNanosPerPacket(int
bytesPerSecond, long periodLengthNanos) {
+ if(bytesPerSecond <= 0)
+ return 0; // no limits
+
+ int packetSize = getPacketSize();
+ double minNanoSecondsBetweenPackets =
+ (periodLengthNanos * packetSize) / ((double)
bytesPerSecond);
+ int newMinPacketDelayNS = (int) minNanoSecondsBetweenPackets;
+ double inaccuracy = minNanoSecondsBetweenPackets -
newMinPacketDelayNS;
+ double inaccuracyPercent = (inaccuracy /
minNanoSecondsBetweenPackets) * 100.0;
+ Logger.minor(BlockTransmitter.class, "Quantization inaccuracy:
"+inaccuracyPercent+"%");
+ return newMinPacketDelayNS;
+ }
+
+ public static int convertNanosPerPacketToBytesPerSecond(int delay) {
+ if(delay == 0) return 0;
+ return (int) (((1000.0*1000.0*1000.0) * getPacketSize()) /
((double)delay));
+ }
+
+ /** @return The average packet size for a block sent by a
BlockTransmitter, including all
+ * headers and protocol overhead */
+ private static int getPacketSize() {
+ // FIXME make this more accurate!
+ return 1024 + 200;
+ }
+
+ public static int getHardBandwidthLimit() {
+ int delay;
synchronized(lastPacketSendTimeSync) {
- minSoftDelay = delay;
+ delay = minPacketDelayNSec;
}
+ return convertNanosPerPacketToBytesPerSecond(delay);
}
-
- public static void setSoftLimitPeriod(long period) {
+
+ /**
+ * Set the long-term bandwidth limiter.
+ * @param bytes The number of bytes to allow at most over the period.
(in data packets)
+ * @param period The length of time over which the limit should apply.
(ms)
+ */
+ public static void setSoftBandwidthLimit(int bytes, long period) {
+ if(period > Long.MAX_VALUE / (1000*1000)) throw new
IllegalArgumentException("Period too long");
+ int newSoftLimit = convertBytesPerPeriodToNanosPerPacket(bytes,
period);
+ period = period * 1000 * 1000;
synchronized(lastPacketSendTimeSync) {
- softLimitPeriod = period;
- long now = System.currentTimeMillis();
- if(now - softLastPacketSendTime > period / 2) {
- softLastPacketSendTime = now - (period / 2);
+ minSoftDelayNSec = newSoftLimit;
+ softLimitPeriodNSec = period;
+ long nowNS = System.currentTimeMillis() * 1000 * 1000;
+ if(nowNS - softLastPacketSendTimeNSec > period / 2) {
+ softLastPacketSendTimeNSec = nowNS - (period /
2);
}
}
}
@@ -149,10 +212,10 @@
((PeerNode)_destination).reportThrottledPacketSendTime(delayTime);
((PeerNode)_destination).sendAsync(DMT.createPacketTransmit(_uid, packetNo,
_sentPackets, _prb.getPacket(packetNo)), null);
// May have been delays
in sending, so update to avoid sending more frequently than allowed
- long now =
System.currentTimeMillis();
+ long nowNS =
System.currentTimeMillis() * 1000 * 1000;
synchronized(lastPacketSendTimeSync) {
-
if(hardLastPacketSendTime < now)
-
hardLastPacketSendTime = now;
+
if(hardLastPacketSendTimeNSec < nowNS)
+
hardLastPacketSendTimeNSec = nowNS;
}
// We accelerate the ping rate
during the transfer to keep a closer eye on round-trip-time
sentSinceLastPing++;
@@ -185,7 +248,7 @@
while(true) {
- long now = System.currentTimeMillis();
+ long nowNS = System.currentTimeMillis()
* 1000 * 1000;
long endTime = -1;
@@ -195,15 +258,18 @@
synchronized(lastPacketSendTimeSync) {
// Get the current time
- now =
System.currentTimeMillis();
+ nowNS =
System.currentTimeMillis() * 1000 * 1000;
// Update time if necessary to
avoid spurts
- if(hardLastPacketSendTime <
(now - minPacketDelay))
- hardLastPacketSendTime
= now - minPacketDelay;
+ if(hardLastPacketSendTimeNSec <
(nowNS - minPacketDelayNSec))
+
hardLastPacketSendTimeNSec = nowNS - minPacketDelayNSec;
// Wait until the next send
window
+ long
newHardLastPacketSendTimeNS =
+
hardLastPacketSendTimeNSec + minPacketDelayNSec;
+
long newHardLastPacketSendTime =
- hardLastPacketSendTime
+ minPacketDelay;
+
newHardLastPacketSendTimeNS / (1000 * 1000);
long earliestSendTime =
startCycleTime + delay;
@@ -212,24 +278,32 @@
thenSend = false;
endTime =
earliestSendTime;
} else {
- hardLastPacketSendTime
= newHardLastPacketSendTime;
- endTime =
hardLastPacketSendTime;
+
hardLastPacketSendTimeNSec = newHardLastPacketSendTimeNS;
+ endTime =
hardLastPacketSendTimeNSec / (1000 * 1000);
// What about the soft
limit?
- if(now -
softLastPacketSendTime > minSoftDelay / 2) {
-
softLastPacketSendTime = now - (minSoftDelay / 2);
+ // We can only
accumulate burst traffic rights for a full period at most.
+ // If we have a period
of 1 hour, and we send no traffic in the first 30 minutes,
+ // then we can use up
our whole hour's quota in the next 30 minutes if we need to.
+ // We could even use
our entire quota in the last 5 minutes. After that, we can
+ // only send at the
limit (which may be very low), since we have no quota left.
+ // However, after 1
hour we forget our burst rights.
+ if(nowNS -
softLastPacketSendTimeNSec > softLimitPeriodNSec) {
+
softLastPacketSendTimeNSec = nowNS - (softLimitPeriodNSec);
}
- softLastPacketSendTime
+= minSoftDelay;
+
softLastPacketSendTimeNSec += minSoftDelayNSec;
-
if(softLastPacketSendTime > hardLastPacketSendTime) {
- endTime =
hardLastPacketSendTime = softLastPacketSendTime;
+
if(softLastPacketSendTimeNSec > hardLastPacketSendTimeNSec) {
+ endTime =
((hardLastPacketSendTimeNSec = softLastPacketSendTimeNSec) / (1000 * 1000));
}
}
}
- while(now < endTime) {
+ long now = nowNS / (1000 * 1000);
+
+ while(nowNS < endTime) {
synchronized(_senderThread) {
if(_sendComplete)
return true;
@@ -244,6 +318,8 @@
now =
System.currentTimeMillis();
}
+ nowNS = now * 1000 * 1000;
+
if(thenSend) return false;
}
}
Modified: trunk/freenet/src/freenet/node/CPUAdjustingSwapRequestInterval.java
===================================================================
--- trunk/freenet/src/freenet/node/CPUAdjustingSwapRequestInterval.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/CPUAdjustingSwapRequestInterval.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -27,8 +27,8 @@
t.start();
}
- public synchronized double getValue() {
- return currentValue;
+ public synchronized int getValue() {
+ return (int)currentValue;
}
public void run() {
Modified: trunk/freenet/src/freenet/node/LocationManager.java
===================================================================
--- trunk/freenet/src/freenet/node/LocationManager.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/node/LocationManager.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -99,7 +99,7 @@
long startTime = System.currentTimeMillis();
double nextRandom = r.nextDouble();
while(true) {
- double sleepTime = interval.getValue();
+ int sleepTime = interval.getValue();
sleepTime *= nextRandom;
sleepTime = Math.min(sleepTime, Integer.MAX_VALUE);
long endTime = startTime + (int)sleepTime;
Copied: trunk/freenet/src/freenet/node/LoggingConfigHandler.java (from rev
8077, branches/config/src/freenet/node/LoggingConfigHandler.java)
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2006-02-21 02:24:26 UTC (rev
8077)
+++ trunk/freenet/src/freenet/node/Node.java 2006-02-21 02:31:47 UTC (rev
8078)
@@ -15,6 +15,7 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
+import java.net.BindException;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
@@ -37,6 +38,14 @@
import freenet.client.async.ClientRequestScheduler;
import freenet.clients.http.FproxyToadlet;
import freenet.clients.http.SimpleToadletServer;
+import freenet.config.BooleanCallback;
+import freenet.config.Config;
+import freenet.config.FilePersistentConfig;
+import freenet.config.IntCallback;
+import freenet.config.InvalidConfigValueException;
+import freenet.config.LongCallback;
+import freenet.config.StringCallback;
+import freenet.config.SubConfig;
import freenet.crypt.DSAPublicKey;
import freenet.crypt.DiffieHellman;
import freenet.crypt.RandomSource;
@@ -76,6 +85,7 @@
import freenet.support.LRUHashtable;
import freenet.support.LRUQueue;
import freenet.support.Logger;
+import freenet.support.LoggerHookChain;
import freenet.support.PaddedEphemerallyEncryptedBucketFactory;
import freenet.support.SimpleFieldSet;
import freenet.support.io.FilenameGenerator;
@@ -86,9 +96,19 @@
* @author amphibian
*/
public class Node {
-
- static final long serialVersionUID = -1;
+
+ /** Config object for the whole node. */
+ public final Config config;
+ // Static stuff related to logger
+
+ /** Directory to log to */
+ static File logDir;
+ /** Maximum size of gzipped logfiles */
+ static long maxLogSize;
+ /** Log config handler */
+ static LoggingConfigHandler logConfigHandler;
+
/** If true, local requests and inserts aren't cached.
* This opens up a glaring vulnerability; connected nodes
* can then probe the store, and if the node doesn't have the
@@ -136,7 +156,18 @@
// FIXME: abstract out address stuff? Possibly to something like
NodeReference?
final int portNumber;
+
+ /** Datastore directory */
+ private final File storeDir;
+
+ /** The number of bytes per key total in all the different datastores. All
the datastores
+ * are always the same size in number of keys. */
+ static final int sizePerKey = CHKBlock.DATA_LENGTH +
CHKBlock.TOTAL_HEADERS_LENGTH +
+ DSAPublicKey.PADDED_SIZE + SSKBlock.DATA_LENGTH +
SSKBlock.TOTAL_HEADERS_LENGTH;
+ /** The maximum number of keys stored in each of the datastores. */
+ private long maxStoreKeys;
+
/** These 3 are private because must be protected by synchronized(this) */
/** The CHK datastore */
private final FreenetStore chkDatastore;
@@ -163,19 +194,21 @@
String myName;
final LocationManager lm;
final PeerManager peers; // my peers
+ /** Directory to put node, peers, etc into */
+ final File nodeDir;
+ final File tempDir;
public final RandomSource random; // strong RNG
final UdpSocketManager usm;
final FNPPacketMangler packetMangler;
final PacketSender ps;
final NodeDispatcher dispatcher;
final NodePinger nodePinger;
- final String filenamesPrefix;
final FilenameGenerator tempFilenameGenerator;
- final FileLoggerHook fileLoggerHook;
static final int MAX_CACHED_KEYS = 1000;
final LRUHashtable cachedPubKeys;
final boolean testnetEnabled;
- final int testnetPort;
+ final TestnetHandler testnetHandler;
+ final StaticSwapRequestInterval swapInterval;
static short MAX_HTL = 10;
static final int EXIT_STORE_FILE_NOT_FOUND = 1;
static final int EXIT_STORE_IOEXCEPTION = 2;
@@ -185,7 +218,18 @@
static final int EXIT_TEMP_INIT_ERROR = 6;
static final int EXIT_TESTNET_FAILED = 7;
public static final int EXIT_MAIN_LOOP_LOST = 8;
+ public static final int EXIT_COULD_NOT_BIND_USM = 9;
+ static final int EXIT_IMPOSSIBLE_USM_PORT = 10;
+ static final int EXIT_NO_AVAILABLE_UDP_PORTS = 11;
+ public static final int EXIT_TESTNET_DISABLED_NOT_SUPPORTED = 12;
+ static final int EXIT_INVALID_STORE_SIZE = 13;
+ static final int EXIT_BAD_DOWNLOADS_DIR = 14;
+ static final int EXIT_BAD_NODE_DIR = 15;
+ static final int EXIT_BAD_TEMP_DIR = 16;
+ static final int EXIT_COULD_NOT_START_FCP = 17;
+ static final int EXIT_COULD_NOT_START_FPROXY = 18;
+
public final long bootID;
public final long startupTime;
@@ -196,11 +240,13 @@
final RequestStarter requestStarter;
final RequestThrottle insertThrottle;
final RequestStarter insertStarter;
- final File downloadDir;
- final TestnetHandler testnetHandler;
- final TestnetStatusUploader statusUploader;
+ File downloadDir;
public final ClientRequestScheduler fetchScheduler;
public final ClientRequestScheduler putScheduler;
+ TextModeClientInterface tmci;
+ FCPServer fcpServer;
+ FproxyToadlet fproxyServlet;
+ SimpleToadletServer toadletContainer;
// Things that's needed to keep track of
public final PluginManager pluginManager;
@@ -211,7 +257,7 @@
static final long MAX_ARCHIVE_SIZE = 1024*1024; // ??? FIXME
static final long MAX_ARCHIVED_FILE_SIZE = 1024*1024; // arbitrary... FIXME
static final int MAX_CACHED_ELEMENTS = 1024; // equally arbitrary! FIXME
hopefully we can cache many of these though
-
+
// Helpers
public final InetAddress localhostAddress;
@@ -224,7 +270,7 @@
FileInputStream fis = new FileInputStream(filename);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
- SimpleFieldSet fs = new SimpleFieldSet(br);
+ SimpleFieldSet fs = new SimpleFieldSet(br, false);
br.close();
// Read contents
String physical = fs.get("physical.udp");
@@ -274,18 +320,16 @@
public void writeNodeFile() {
try {
- writeNodeFile(filenamesPrefix+"node-"+portNumber,
filenamesPrefix+"node-"+portNumber+".bak");
+ writeNodeFile(new File(nodeDir, "node-"+portNumber), new
File(nodeDir, "node-"+portNumber+".bak"));
} catch (IOException e) {
Logger.error(this, "Cannot write node file!: "+e+" :
"+"node-"+portNumber);
}
}
- private void writeNodeFile(String filename, String backupFilename) throws
IOException {
+ private void writeNodeFile(File orig, File backup) throws IOException {
SimpleFieldSet fs = exportFieldSet();
- File orig = new File(filename);
- File backup = new File(backupFilename);
orig.renameTo(backup);
- FileOutputStream fos = new FileOutputStream(filename);
+ FileOutputStream fos = new FileOutputStream(orig);
OutputStreamWriter osr = new OutputStreamWriter(fos);
fs.writeTo(osr);
osr.close();
@@ -311,169 +355,421 @@
/**
* Read the port number from the arguments.
* Then create a node.
+ * Anything that needs static init should ideally be in here.
*/
public static void main(String[] args) throws IOException {
- int length = args.length;
- if (length < 1 || length > 3) {
- System.out.println("Usage: $ java freenet.node.Node
<portNumber> [ipOverride] [max data packets / second]");
+ if(args.length>1) {
+ System.out.println("Usage: $ java freenet.node.Node
<configFile>");
+ System.out.println("We recommend you move your old
<filename>-<portnumber> files to <filename>, otherwise the node won't use
them!");
return;
}
- int port = Integer.parseInt(args[0]);
- System.out.println("Port number: "+port);
- File logDir = new File("logs-"+port);
- logDir.mkdir();
- FileLoggerHook logger = new FileLoggerHook(true, new File(logDir,
"freenet-"+port).getAbsolutePath(),
- "d (c, t, p): m", "MMM dd, yyyy HH:mm:ss:SSS",
Logger.MINOR, false, true,
- 1024*1024*1024 /* 1GB of old compressed logfiles */);
- logger.setInterval("5MINUTES");
- Logger.setupChain();
- Logger.globalSetThreshold(Logger.MINOR);
- Logger.globalAddHook(logger);
- logger.start();
- Logger.normal(Node.class, "Creating node...");
- Yarrow yarrow = new Yarrow();
- InetAddress overrideIP = null;
- int packetsPerSecond = 15;
- if(args.length > 1) {
- overrideIP = InetAddress.getByName(args[1]);
- System.err.println("Overriding IP detection:
"+overrideIP.getHostAddress());
- if(args.length > 2) {
- packetsPerSecond = Integer.parseInt(args[2]);
- }
- }
- DiffieHellman.init(yarrow);
- Node n = new Node(port, yarrow, overrideIP, "", 1000 /
packetsPerSecond, true, logger, 32768 /* 1GB */);
- n.start(new StaticSwapRequestInterval(2000));
- new TextModeClientInterface(n);
+ File configFilename;
+ if(args.length == 0) {
+ System.out.println("Using default config filename freenet.ini");
+ configFilename = new File("freenet.ini");
+ } else
+ configFilename = new File(args[0]);
+
+ FilePersistentConfig cfg = new FilePersistentConfig(configFilename);
+
+ // First, set up logging. It is global, and may be shared between
several nodes.
+
+ SubConfig loggingConfig = new SubConfig("logger", cfg);
+
+ try {
+ logConfigHandler = new
LoggingConfigHandler(loggingConfig);
+ } catch (InvalidConfigValueException e) {
+ System.err.println("Error: could not set up logging:
"+e.getMessage());
+ e.printStackTrace();
+ return;
+ }
+
+ // Setup RNG
+
+ RandomSource random = new Yarrow();
+
+ DiffieHellman.init(random);
+
Thread t = new Thread(new MemoryChecker(), "Memory checker");
t.setPriority(Thread.MAX_PRIORITY);
t.start();
- SimpleToadletServer server = new SimpleToadletServer(port+2000);
- FproxyToadlet fproxy = new
FproxyToadlet(n.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS));
- server.register(fproxy, "/", false);
- System.out.println("Starting fproxy on port "+(port+2000));
- new FCPServer(port+3000, n);
- System.out.println("Starting FCP server on port "+(port+3000));
- SNMPAgent.setSNMPPort(port+4000);
- System.out.println("Starting SNMP server on port "+(port+4000));
- SNMPStarter.initialize();
- //server.register(fproxy, "/SSK@", false);
- //server.register(fproxy, "/KSK@", false);
+
+ Node node;
+ try {
+ node = new Node(cfg, random);
+ node.start(false);
+ } catch (NodeInitException e) {
+ System.err.println("Failed to load node:
"+e.getMessage());
+ e.printStackTrace();
+ System.exit(e.exitCode);
+ }
}
- // FIXME - the whole overrideIP thing is a hack to avoid config
- // Implement the config!
- Node(int port, RandomSource rand, InetAddress overrideIP, String prefix,
int throttleInterval, boolean enableTestnet, FileLoggerHook logger, int
maxStoreKeys) {
- this.fileLoggerHook = logger;
+ static class NodeInitException extends Exception {
+ // One of the exit codes from above
+ public final int exitCode;
+
+ NodeInitException(int exitCode, String msg) {
+ super(msg+" ("+exitCode+")");
+ this.exitCode = exitCode;
+ }
+ }
+
+ /**
+ * Create a Node from a Config object.
+ * @param config The Config object for this node.
+ * @param random The random number generator for this node. Passed in
because we may want
+ * to use a non-secure RNG for e.g. one-JVM live-code simulations. Should
be a Yarrow in
+ * a production node.
+ * @throws NodeInitException If the node initialization fails.
+ */
+ private Node(Config config, RandomSource random) throws NodeInitException {
+
+ // Easy stuff
+ startupTime = System.currentTimeMillis();
+ recentlyCompletedIDs = new LRUQueue();
+ this.config = config;
+ this.random = random;
cachedPubKeys = new LRUHashtable();
- if(enableTestnet) {
- Logger.error(this, "WARNING: ENABLING TESTNET CODE! This may
seriously jeopardize your anonymity!");
- testnetEnabled = true;
- testnetPort = 1024 + (port-1024+1000) % (65536 - 1024);
- testnetHandler = new TestnetHandler(this, testnetPort);
- statusUploader = new TestnetStatusUploader(this, 180000);
- } else {
- testnetEnabled = false;
- testnetPort = -1;
- testnetHandler = null;
- statusUploader = null;
- }
+ lm = new LocationManager(random);
try {
localhostAddress = InetAddress.getByName("127.0.0.1");
} catch (UnknownHostException e3) {
// Does not do a reverse lookup, so this is impossible
throw new Error(e3);
}
- portNumber = port;
- startupTime = System.currentTimeMillis();
- recentlyCompletedIDs = new LRUQueue();
ipDetector = new IPAddressDetector(10*1000, this);
- if(prefix == null) prefix = "";
- filenamesPrefix = prefix;
- this.overrideIPAddress = overrideIP;
- downloadDir = new File("downloads");
- downloadDir.mkdir();
- try {
- chkDatastore = new
BerkeleyDBFreenetStore(prefix+"store-"+portNumber, maxStoreKeys, 32768,
CHKBlock.TOTAL_HEADERS_LENGTH);
- sskDatastore = new
BerkeleyDBFreenetStore(prefix+"sskstore-"+portNumber, maxStoreKeys, 1024,
SSKBlock.TOTAL_HEADERS_LENGTH);
- pubKeyDatastore = new
BerkeleyDBFreenetStore(prefix+"pubkeystore-"+portNumber, maxStoreKeys,
DSAPublicKey.PADDED_SIZE, 0);
- } catch (FileNotFoundException e1) {
- Logger.error(this, "Could not open datastore: "+e1, e1);
- System.err.println("Could not open datastore: "+e1);
- System.exit(EXIT_STORE_FILE_NOT_FOUND);
- throw new Error();
- } catch (IOException e1) {
- Logger.error(this, "Could not open datastore: "+e1, e1);
- System.err.println("Could not open datastore: "+e1);
- System.exit(EXIT_STORE_IOEXCEPTION);
- throw new Error();
- } catch (Exception e1) {
- Logger.error(this, "Could not open datastore: "+e1, e1);
- System.err.println("Could not open datastore: "+e1);
- System.exit(EXIT_STORE_OTHER);
- throw new Error();
- }
- random = rand;
requestSenders = new HashMap();
transferringRequestSenders = new HashMap();
insertSenders = new HashMap();
runningUIDs = new HashSet();
+ ps = new PacketSender(this);
+ // FIXME maybe these should persist? They need to be private though,
so after the node/peers split. (bug 51).
+ decrementAtMax = random.nextDouble() <= DECREMENT_AT_MAX_PROB;
+ decrementAtMin = random.nextDouble() <= DECREMENT_AT_MIN_PROB;
+ bootID = random.nextLong();
- BlockTransmitter.setMinPacketInterval(throttleInterval);
+ // Setup node-specific configuration
+
+ SubConfig nodeConfig = new SubConfig("node", config);
- /*
- * FIXME: test the soft limit.
- *
- * The soft limit is implemented, except for:
- * - We need to write the current status to disk every 1 minute or so.
- * - When we start up, we need to read this in, assume that the node
sent
- * as many packets as it was allowed to in the following minute, and
- * then shut down before writing again (worst case scenario).
- * - We need to test the soft limit!
- */
- BlockTransmitter.setSoftLimitPeriod(14*24*60*60*1000);
- BlockTransmitter.setSoftMinPacketInterval(0);
+ // IP address override
+
+ nodeConfig.register("ipAddressOverride", "", 0, true, "IP address
override", "IP address override (not usually needed)", new StringCallback() {
+
+ public String get() {
+ if(overrideIPAddress == null) return "";
+ else return Peer.getHostName(overrideIPAddress);
+ }
+
+ public void set(String val) throws
InvalidConfigValueException {
+ // FIXME do we need to tell anyone?
+ if(val.length() == 0) {
+ // Set to null
+ overrideIPAddress = null;
+ return;
+ }
+ InetAddress addr;
+ try {
+ addr = InetAddress.getByName(val);
+ } catch (UnknownHostException e) {
+ throw new
InvalidConfigValueException("Unknown host: "+e.getMessage());
+ }
+ overrideIPAddress = addr;
+ }
+
+ });
+
+ String ipOverrideString = nodeConfig.getString("ipAddressOverride");
+ if(ipOverrideString.length() == 0)
+ overrideIPAddress = null;
+ else {
+ try {
+ overrideIPAddress =
InetAddress.getByName(ipOverrideString);
+ } catch (UnknownHostException e) {
+ String msg = "Unknown host:
"+ipOverrideString+" in config: "+e.getMessage();
+ Logger.error(this, msg);
+ System.err.println(msg+" but starting up anyway
with no IP override");
+ overrideIPAddress = null;
+ }
+ }
+
+ // Determine the port number
+
+ nodeConfig.register("listenPort", -1 /* means random */, 1, true, "FNP
port number (UDP)", "UDP port for node-to-node communications (Freenet Node
Protocol)",
+ new IntCallback() {
+ public int get() {
+ return portNumber;
+ }
+ public void set(int val) throws
InvalidConfigValueException {
+ // FIXME implement on the fly
listenPort changing
+ // Note that this sort of thing
should be the exception rather than the rule!!!!
+ String msg = "Switching
listenPort on the fly not yet supported!";
+ Logger.error(this, msg);
+ throw new
InvalidConfigValueException(msg);
+ }
+ });
+
+ int port = nodeConfig.getInt("listenPort");
+
+ UdpSocketManager u = null;
+
+ if(port > 65535) {
+ throw new NodeInitException(EXIT_IMPOSSIBLE_USM_PORT,
"Impossible port number: "+port);
+ } else if(port == -1) {
+ // Pick a random port
+ for(int i=0;i<200000;i++) {
+ int portNo = 1024 + random.nextInt(65535-1024);
+ try {
+ u = new UdpSocketManager(portNo);
+ port = u.getPortNumber();
+ break;
+ } catch (SocketException e) {
+ Logger.normal(this, "Could not use port:
"+portNo+": "+e, e);
+ System.err.println("Could not use port:
"+portNo+": "+e);
+ e.printStackTrace();
+ continue;
+ }
+ }
+ if(u == null)
+ throw new
NodeInitException(EXIT_NO_AVAILABLE_UDP_PORTS, "Could not find an available UDP
port number for FNP (none specified)");
+ } else {
+ try {
+ u = new UdpSocketManager(port);
+ } catch (SocketException e) {
+ throw new NodeInitException(EXIT_IMPOSSIBLE_USM_PORT,
"Could not bind to port: "+port+" (node already running?)");
+ }
+ }
+ usm = u;
+
+ System.out.println("Port number: "+port);
+ portNumber = port;
- lm = new LocationManager(random);
+ Logger.normal(Node.class, "Creating node...");
+ // Bandwidth limit
+
+ // FIXME These should not be static !!!! Need a context object for BT
for bwlimiting.
+ // See bug 77
+ nodeConfig.register("outputBandwidthLimit", "15K", 3, false,
+ "Output bandwidth limit", "Hard output bandwidth limit
(bytes/sec); the node should almost never exceed this",
+ new IntCallback() {
+ public int get() {
+ return
BlockTransmitter.getHardBandwidthLimit();
+ }
+ public void set(int val) throws
InvalidConfigValueException {
+
BlockTransmitter.setHardBandwidthLimit(val);
+ }
+ });
+
+ int obwLimit = nodeConfig.getInt("outputBandwidthLimit");
+ BlockTransmitter.setHardBandwidthLimit(obwLimit);
+ // FIXME add an averaging/long-term/soft bandwidth limit. (bug 76)
+ // There is already untested support for this in BlockTransmitter.
+ // No long-term limit for now.
+ BlockTransmitter.setSoftBandwidthLimit(0, 0);
+
+ // SwapRequestInterval
+
+ nodeConfig.register("swapRequestSendInterval", 2000, 4, true,
+ "Swap request send interval (ms)", "Interval between
swap attempting to send swap requests in milliseconds. Leave this alone!",
+ new IntCallback() {
+ public int get() {
+ return
swapInterval.fixedInterval;
+ }
+ public void set(int val) throws
InvalidConfigValueException {
+ swapInterval.set(val);
+ }
+ });
+
+ swapInterval = new
StaticSwapRequestInterval(nodeConfig.getInt("swapRequestSendInterval"));
+
+ // Testnet.
+ // Cannot be enabled/disabled on the fly.
+ // If enabled, forces certain other config options.
+
+ if((testnetHandler = TestnetHandler.maybeCreate(this, config)) !=
null) {
+ String msg = "WARNING: ENABLING TESTNET CODE! This WILL
seriously jeopardize your anonymity!";
+ Logger.error(this, msg);
+ System.err.println(msg);
+ testnetEnabled = true;
+ Logger.globalSetThreshold(Logger.MINOR);
+ } else {
+ Logger.normal(this, "Testnet mode DISABLED. You may have some
level of anonymity. :)");
+ testnetEnabled = false;
+ }
+
+ // Directory for node-related files other than store
+
+ nodeConfig.register("nodeDir", ".", 6, true, "Node directory", "Name
of directory to put node-related files e.g. peers list in",
+ new StringCallback() {
+ public String get() {
+ return nodeDir.getPath();
+ }
+ public void set(String val) throws
InvalidConfigValueException {
+ if(nodeDir.equals(new
File(val))) return;
+ // FIXME
+ throw new
InvalidConfigValueException("Moving node directory on the fly not supported at
present");
+ }
+ });
+
+ nodeDir = new File(nodeConfig.getString("nodeDir"));
+ if(!((nodeDir.exists() && nodeDir.isDirectory()) ||
(nodeDir.mkdir()))) {
+ String msg = "Could not find or create datastore directory";
+ throw new NodeInitException(EXIT_BAD_NODE_DIR, msg);
+ }
+
+ // After we have set up testnet and IP address, load the node file
try {
- readNodeFile(prefix+"node-"+portNumber);
+ // FIXME should take file directly?
+ readNodeFile(new File(nodeDir, "node-"+portNumber).getPath());
} catch (IOException e) {
try {
- readNodeFile(prefix+"node-"+portNumber+".bak");
+ readNodeFile(new File("node-"+portNumber+".bak").getPath());
} catch (IOException e1) {
initNodeFileSettings(random);
}
}
writeNodeFile();
+
+ // Then read the peers
+ peers = new PeerManager(this, new File(nodeDir,
"peers-"+portNumber).getPath());
+ peers.writePeers();
+ nodePinger = new NodePinger(this);
+
+ usm.setDispatcher(dispatcher=new NodeDispatcher(this));
+ usm.setLowLevelFilter(packetMangler = new FNPPacketMangler(this));
+
+ // Temp files
- ps = new PacketSender(this);
- peers = new PeerManager(this, prefix+"peers-"+portNumber);
+ nodeConfig.register("tempDir", new File(nodeDir,
"temp-"+portNumber).toString(), 6, true, "Temp files directory", "Name of
directory to put temporary files in",
+ new StringCallback() {
+ public String get() {
+ return tempDir.getPath();
+ }
+ public void set(String val) throws
InvalidConfigValueException {
+ if(tempDir.equals(new
File(val))) return;
+ // FIXME
+ throw new
InvalidConfigValueException("Moving node directory on the fly not supported at
present");
+ }
+ });
- try {
- usm = new UdpSocketManager(portNumber);
- usm.setDispatcher(dispatcher=new NodeDispatcher(this));
- usm.setLowLevelFilter(packetMangler = new FNPPacketMangler(this));
- } catch (SocketException e2) {
- Logger.error(this, "Could not listen for traffic: "+e2, e2);
- System.exit(EXIT_USM_DIED);
- throw new Error();
+ tempDir = new File(nodeConfig.getString("tempDir"));
+ if(!((tempDir.exists() && tempDir.isDirectory()) ||
(tempDir.mkdir()))) {
+ String msg = "Could not find or create temporary directory";
+ throw new NodeInitException(EXIT_BAD_TEMP_DIR, msg);
}
- decrementAtMax = random.nextDouble() <= DECREMENT_AT_MAX_PROB;
- decrementAtMin = random.nextDouble() <= DECREMENT_AT_MIN_PROB;
- bootID = random.nextLong();
- peers.writePeers();
+
try {
- String dirName = "temp-"+portNumber;
- tempFilenameGenerator = new FilenameGenerator(random,
true, new File(dirName), "temp-");
+ tempFilenameGenerator = new FilenameGenerator(random,
true, tempDir, "temp-");
} catch (IOException e) {
Logger.error(this, "Could not create temp bucket
factory: "+e, e);
System.exit(EXIT_TEMP_INIT_ERROR);
throw new Error();
}
- nodePinger = new NodePinger(this);
tempBucketFactory = new
PaddedEphemerallyEncryptedBucketFactory(new
TempBucketFactory(tempFilenameGenerator), random, 1024);
+
+
+ // Datastore
+
+ nodeConfig.register("storeSize", "1G", 5, false, "Store size in
bytes", "Store size in bytes",
+ new LongCallback() {
+
+ public long get() {
+ return maxStoreKeys *
sizePerKey;
+ }
+
+ public void set(long storeSize) throws
InvalidConfigValueException {
+ if(storeSize < 0 || storeSize <
(32 * 1024 * 1024))
+ throw new
InvalidConfigValueException("Invalid store size");
+ long newMaxStoreKeys =
storeSize / sizePerKey;
+ if(newMaxStoreKeys ==
maxStoreKeys) return;
+ // Update each datastore
+ maxStoreKeys = newMaxStoreKeys;
+
chkDatastore.setMaxKeys(maxStoreKeys);
+
sskDatastore.setMaxKeys(maxStoreKeys);
+
pubKeyDatastore.setMaxKeys(maxStoreKeys);
+ }
+ });
+
+ long storeSize = nodeConfig.getLong("storeSize");
+
+ if(/*storeSize < 0 || */storeSize < (32 * 1024 * 1024)) { // totally
arbitrary minimum!
+ throw new NodeInitException(EXIT_INVALID_STORE_SIZE, "Invalid
store size");
+ }
+
+ maxStoreKeys = storeSize / sizePerKey;
+
+ nodeConfig.register("storeDir", ".", 6, true, "Store directory", "Name
of directory to put store files in",
+ new StringCallback() {
+ public String get() {
+ return storeDir.getPath();
+ }
+ public void set(String val) throws
InvalidConfigValueException {
+ if(storeDir.equals(new
File(val))) return;
+ // FIXME
+ throw new
InvalidConfigValueException("Moving datastore on the fly not supported at
present");
+ }
+ });
+
+ storeDir = new File(nodeConfig.getString("storeDir"));
+ if(!((storeDir.exists() && storeDir.isDirectory()) ||
(storeDir.mkdir()))) {
+ String msg = "Could not find or create datastore directory";
+ throw new NodeInitException(EXIT_STORE_OTHER, msg);
+ }
+
+ try {
+ chkDatastore = new
BerkeleyDBFreenetStore(storeDir.getPath()+File.separator+"store-"+portNumber,
maxStoreKeys, 32768, CHKBlock.TOTAL_HEADERS_LENGTH);
+ sskDatastore = new
BerkeleyDBFreenetStore(storeDir.getPath()+File.separator+"sskstore-"+portNumber,
maxStoreKeys, 1024, SSKBlock.TOTAL_HEADERS_LENGTH);
+ pubKeyDatastore = new
BerkeleyDBFreenetStore(storeDir.getPath()+File.separator+"pubkeystore-"+portNumber,
maxStoreKeys, DSAPublicKey.PADDED_SIZE, 0);
+ } catch (FileNotFoundException e1) {
+ String msg = "Could not open datastore: "+e1;
+ Logger.error(this, msg, e1);
+ System.err.println(msg);
+ throw new NodeInitException(EXIT_STORE_FILE_NOT_FOUND, msg);
+ } catch (IOException e1) {
+ String msg = "Could not open datastore: "+e1;
+ Logger.error(this, msg, e1);
+ System.err.println(msg);
+ throw new NodeInitException(EXIT_STORE_IOEXCEPTION, msg);
+ } catch (Exception e1) {
+ String msg = "Could not open datastore: "+e1;
+ Logger.error(this, msg, e1);
+ System.err.println(msg);
+ throw new NodeInitException(EXIT_STORE_OTHER, msg);
+ }
+
+ // Downloads directory
+
+ nodeConfig.register("downloadsDir", "downloads", 8, false, "Default
download directory", "The directory to save downloaded files into by default",
new StringCallback() {
+
+ public String get() {
+ return downloadDir.getPath();
+ }
+
+ public void set(String val) throws
InvalidConfigValueException {
+ if(downloadDir.equals(new File(val)))
+ return;
+ File f = new File(val);
+ if(!((f.exists() && f.isDirectory()) || (f.mkdir()))) {
+ throw new InvalidConfigValueException("Could
not find or create directory");
+ }
+ downloadDir = new File(val);
+ }
+
+ });
+
+ String val = nodeConfig.getString("downloadsDir");
+ downloadDir = new File(val);
+ if(!((downloadDir.exists() && downloadDir.isDirectory()) ||
(downloadDir.mkdir()))) {
+ throw new NodeInitException(EXIT_BAD_DOWNLOADS_DIR, "Could not
find or create default downloads directory");
+ }
+
+ nodeConfig.finishedInitialization();
+
+ // FIXME make all the below arbitrary constants configurable!
+
archiveManager = new ArchiveManager(MAX_ARCHIVE_HANDLERS,
MAX_CACHED_ARCHIVE_DATA, MAX_ARCHIVE_SIZE, MAX_ARCHIVED_FILE_SIZE,
MAX_CACHED_ELEMENTS, random, tempFilenameGenerator);
requestThrottle = new RequestThrottle(5000, 2.0F);
requestStarter = new RequestStarter(this, requestThrottle,
"Request starter ("+portNumber+")");
@@ -487,11 +783,6 @@
putScheduler = new ClientRequestScheduler(true, random,
insertStarter, this);
insertStarter.setScheduler(putScheduler);
insertStarter.start();
- if(testnetHandler != null)
- testnetHandler.start();
- if(statusUploader != null)
- statusUploader.start();
-
// And finally, Initialize the plugin manager
PluginManager pm = null;
try {
@@ -504,14 +795,58 @@
System.err.println("THIS SHOULDN'T OCCUR!!!! (plugin
system now disabled)");
}
pluginManager = pm;
- System.err.println("Created Node on port "+port);
}
-
- void start(SwapRequestInterval interval) {
- if(interval != null)
- lm.startSender(this, interval);
+
+ private InetAddress resolve(String val) {
+ try {
+ if(val == null || val.length() == 0)
+ return null;
+ else
+ return InetAddress.getByName(val);
+ } catch (UnknownHostException e) {
+ Logger.error(this, "Ignoring unresolvable overridden IP
address: "+overrideIPAddress);
+ return null;
+ }
+ }
+
+ void start(boolean noSwaps) throws NodeInitException {
+ if(!noSwaps)
+ lm.startSender(this, this.swapInterval);
ps.start();
usm.start();
+
+ // Start services
+
+ // TMCI
+ TextModeClientInterface.maybeCreate(this, config);
+
+ // Fproxy
+ // FIXME this is a hack, the real way to do this is plugins
+ try {
+ FproxyToadlet.maybeCreateFproxyEtc(this, config);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new
NodeInitException(EXIT_COULD_NOT_START_FPROXY, "Could not start fproxy: "+e);
+ }
+
+ // FCP
+ try {
+ fcpServer = FCPServer.maybeCreate(this, config);
+ } catch (IOException e) {
+ throw new NodeInitException(EXIT_COULD_NOT_START_FCP,
"Could not start FCP: "+e);
+ }
+
+ // SNMP
+ SNMPStarter.maybeCreate(this, config);
+
+ // After everything has been created, write the config file back to
disk.
+ config.finishedInit();
+ config.store();
+
+ // Start testnet handler
+ if(testnetHandler != null)
+ testnetHandler.start();
+
}
public ClientKeyBlock realGetKey(ClientKey key, boolean localOnly, boolean
cache, boolean ignoreStore) throws LowLevelGetException {
@@ -942,7 +1277,7 @@
* @return
*/
public SimpleFieldSet exportFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
fs.put("physical.udp",
Peer.getHostName(getPrimaryIPAddress())+":"+portNumber);
fs.put("identity", HexUtil.bytesToHex(myIdentity));
fs.put("location", Double.toString(lm.getLocation().getValue()));
@@ -950,7 +1285,7 @@
fs.put("testnet", Boolean.toString(testnetEnabled));
fs.put("lastGoodVersion", Version.getLastGoodVersionString());
if(testnetEnabled)
- fs.put("testnetPort", Integer.toString(testnetPort));
+ fs.put("testnetPort",
Integer.toString(testnetHandler.testnetPort));
fs.put("myName", myName);
Logger.minor(this, "My reference: "+fs);
return fs;
@@ -1551,4 +1886,28 @@
if(block == null) return null;
return new ClientCHKBlock(block, clientCHK);
}
+
+ public FCPServer getFCPServer() {
+ return fcpServer;
+ }
+
+ public void setToadletContainer(SimpleToadletServer server) {
+ toadletContainer = server;
+ }
+
+ public FproxyToadlet getFproxy() {
+ return fproxyServlet;
+ }
+
+ public SimpleToadletServer getToadletContainer() {
+ return toadletContainer;
+ }
+
+ public void setFproxy(FproxyToadlet fproxy) {
+ this.fproxyServlet = fproxy;
+ }
+
+ public void setFCPServer(FCPServer fcp) {
+ this.fcpServer = fcp;
+ }
}
Modified: trunk/freenet/src/freenet/node/PeerManager.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerManager.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/node/PeerManager.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -62,7 +62,7 @@
while(true) {
// Read a single NodePeer
SimpleFieldSet fs;
- fs = new SimpleFieldSet(br);
+ fs = new SimpleFieldSet(br, false);
PeerNode pn;
try {
pn = new PeerNode(fs, node);
Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/node/PeerNode.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -825,7 +825,7 @@
BufferedReader br = new BufferedReader(isr);
SimpleFieldSet fs;
try {
- fs = new SimpleFieldSet(br);
+ fs = new SimpleFieldSet(br, false);
} catch (IOException e) {
Logger.error(this, "Impossible: e", e);
return;
@@ -967,7 +967,7 @@
* Export our noderef as a SimpleFieldSet
*/
private SimpleFieldSet exportFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
if(lastGoodVersion != null)
fs.put("lastGoodVersion", lastGoodVersion);
for(int i=0;i<nominalPeer.size();i++)
Modified: trunk/freenet/src/freenet/node/StaticSwapRequestInterval.java
===================================================================
--- trunk/freenet/src/freenet/node/StaticSwapRequestInterval.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/StaticSwapRequestInterval.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -1,20 +1,18 @@
package freenet.node;
-/**
- * @author root
- *
- * TODO To change the template for this generated type comment go to
- * Window - Preferences - Java - Code Generation - Code and Comments
- */
public class StaticSwapRequestInterval implements SwapRequestInterval {
- double fixedInterval;
+ int fixedInterval;
- public StaticSwapRequestInterval(double d) {
+ public StaticSwapRequestInterval(int d) {
fixedInterval = d;
}
- public double getValue() {
+ public int getValue() {
return fixedInterval;
}
+
+ public void set(int val) {
+ this.fixedInterval = val;
+ }
}
Modified: trunk/freenet/src/freenet/node/SwapRequestInterval.java
===================================================================
--- trunk/freenet/src/freenet/node/SwapRequestInterval.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/SwapRequestInterval.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -4,5 +4,5 @@
* Interface to get the current swap request interval
*/
public interface SwapRequestInterval {
- double getValue();
+ int getValue();
}
Modified: trunk/freenet/src/freenet/node/TestnetHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/TestnetHandler.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/node/TestnetHandler.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -14,6 +14,13 @@
import java.util.Locale;
import java.util.TimeZone;
+import freenet.config.BooleanCallback;
+import freenet.config.Config;
+import freenet.config.IntCallback;
+import freenet.config.InvalidConfigValueException;
+import freenet.config.SubConfig;
+import freenet.node.Node.NodeInitException;
+import freenet.support.FileLoggerHook;
import freenet.support.Logger;
/**
@@ -33,6 +40,8 @@
*/
public class TestnetHandler implements Runnable {
+ private final TestnetStatusUploader uploader;
+
public TestnetHandler(Node node2, int testnetPort) {
this.node = node2;
this.testnetPort = testnetPort;
@@ -44,18 +53,20 @@
System.err.println("We repeat: YOU HAVE NO ANONYMITY
WHATSOEVER. DO NOT POST ANYTHING YOU DO NOT WANT TO BE ASSOCIATED WITH.");
System.err.println("If you want a real freenet node, with
anonymity, turn off testnet mode.");
System.err.println("Note, this node will not connect to
non-testnet nodes, for security reasons. You can of course run a testnet node
and a non-testnet node separately.");
+ uploader = new TestnetStatusUploader(node, 180000);
}
public void start() {
serverThread = new Thread(this, "Testnet handler thread");
serverThread.setDaemon(true);
serverThread.start();
+ uploader.start();
System.err.println("Started testnet handler on port
"+testnetPort);
}
private final Node node;
private Thread serverThread;
- private final int testnetPort;
+ final int testnetPort;
public void run() {
// Set up server socket
@@ -102,10 +113,18 @@
String command = br.readLine();
if(command == null) return;
Logger.minor(this, "Command: "+command);
+ FileLoggerHook loggerHook;
+ loggerHook =
Node.logConfigHandler.getFileLoggerHook();
+ if(loggerHook == null) {
+ Logger.error(this, "Could not serve
testnet command because no FileLoggerHook");
+ OutputStreamWriter osw = new
OutputStreamWriter(os);
+ osw.write("ERROR: Could not serve
testnet command because no FileLoggerHook");
+ return;
+ }
if(command.equalsIgnoreCase("LIST")) {
Logger.minor(this, "Listing available
logs");
OutputStreamWriter osw = new
OutputStreamWriter(os, "ISO-8859-1");
-
node.fileLoggerHook.listAvailableLogs(osw);
+ loggerHook.listAvailableLogs(osw);
osw.close();
} else if(command.startsWith("GET:")) {
Logger.minor(this, "Sending log:
"+command);
@@ -119,7 +138,7 @@
Logger.minor(this, "Cannot
parse: "+e+" for "+date);
return;
}
-
node.fileLoggerHook.sendLogByContainedDate(d.getTime(), os);
+
loggerHook.sendLogByContainedDate(d.getTime(), os);
} else if(command.equalsIgnoreCase("STATUS")) {
Logger.minor(this, "Sending status");
OutputStreamWriter osw = new
OutputStreamWriter(os, "ISO-8859-1");
@@ -148,4 +167,82 @@
}
+ private static class TestnetEnabledCallback implements BooleanCallback {
+
+ final Node node;
+
+ TestnetEnabledCallback(Node node) {
+ this.node = node;
+ }
+
+ public boolean get() {
+ return node.testnetEnabled;
+ }
+
+ public void set(boolean val) throws InvalidConfigValueException
{
+ if(node.testnetEnabled == val) return;
+ String msg = "On-line enable/disable of testnet mode
impossible; restart the node and get new connections";
+ throw new InvalidConfigValueException(msg);
+ }
+
+ }
+
+ private static class TestnetPortNumberCallback implements IntCallback {
+
+ final Node node;
+
+ TestnetPortNumberCallback(Node node) {
+ this.node = node;
+ }
+
+ public int get() {
+ TestnetHandler th = node.testnetHandler;
+ if(th == null)
+ return node.portNumber+1000;
+ else
+ return th.testnetPort;
+ }
+
+ public void set(int val) throws InvalidConfigValueException {
+ TestnetHandler th = node.testnetHandler;
+ if(th == null)
+ return;
+ if(val == th.testnetPort) return;
+ throw new InvalidConfigValueException("Changing testnet
port number on the fly not yet supported");
+ }
+ }
+
+ public static TestnetHandler maybeCreate(Node node, Config config)
throws NodeInitException {
+ SubConfig testnetConfig = new SubConfig("node.testnet", config);
+
+ testnetConfig.register("enabled", true /* for now */, 1, false,
"Enable testnet mode? (DANGEROUS)",
+ "Whether to enable testnet mode (DANGEROUS!). Testnet
mode eliminates your anonymity in exchange for greatly assisting the developers
in debugging the node.",
+ new TestnetEnabledCallback(node));
+
+ boolean enabled = testnetConfig.getBoolean("enabled");
+
+ if(!enabled) {
+ // FIXME
+ String msg = "Sorry, testnet must be enabled while Freenet 0.7
is in pre-alpha testing phase.";
+ Logger.error(TestnetHandler.class, msg);
+ System.err.println(msg);
+ throw new
Node.NodeInitException(Node.EXIT_TESTNET_DISABLED_NOT_SUPPORTED, msg);
+ }
+
+ // Testnet is enabled.
+
+ // Get the testnet port
+
+ // Default to node port plus 1000
+
+ int defaultPort = 1024 + (node.portNumber-1024+1000) % (65536 - 1024);
+
+ testnetConfig.register("port", defaultPort, 2, true, "Testnet port",
"Testnet port number",
+ new TestnetPortNumberCallback(node));
+
+ testnetConfig.finishedInitialization();
+
+ return new TestnetHandler(node, testnetConfig.getInt("port"));
+ }
+
}
Modified: trunk/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -24,6 +24,10 @@
import freenet.client.InserterException;
import freenet.client.Metadata;
import freenet.client.events.EventDumper;
+import freenet.config.BooleanCallback;
+import freenet.config.Config;
+import freenet.config.InvalidConfigValueException;
+import freenet.config.SubConfig;
import freenet.crypt.RandomSource;
import freenet.io.comm.PeerParseException;
import freenet.keys.FreenetURI;
@@ -630,7 +634,7 @@
SimpleFieldSet fs;
System.out.println("Connecting to:\n"+content);
try {
- fs = new SimpleFieldSet(content);
+ fs = new SimpleFieldSet(content, false);
} catch (IOException e) {
System.err.println("Did not parse: "+e);
e.printStackTrace();
@@ -681,4 +685,10 @@
}
return sb.toString();
}
+
+ public static void maybeCreate(Node node, Config config) {
+ // FIXME make this configurable.
+ // Depends on fixing QUIT issues. (bug #81)
+ new TextModeClientInterface(node);
+ }
}
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-02-21 02:24:26 UTC (rev
8077)
+++ trunk/freenet/src/freenet/node/Version.java 2006-02-21 02:31:47 UTC (rev
8078)
@@ -20,7 +20,7 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- private static final int buildNumber = 449;
+ private static final int buildNumber = 450;
/** Oldest build of Fred we will talk to */
private static final int lastGoodBuild = 403;
Modified: trunk/freenet/src/freenet/node/fcp/AllDataMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/AllDataMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/AllDataMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -25,7 +25,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
fs.put("DataLength", Long.toString(dataLength));
fs.put("Identifier", identifier);
return fs;
Modified: trunk/freenet/src/freenet/node/fcp/ClientGetMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientGetMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/ClientGetMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -156,7 +156,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
fs.put("IgnoreDS", Boolean.toString(ignoreDS));
fs.put("URI", uri.toString(false));
fs.put("Identifier", identifier);
Modified: trunk/freenet/src/freenet/node/fcp/ClientHelloMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientHelloMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/ClientHelloMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -26,7 +26,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet sfs = new SimpleFieldSet();
+ SimpleFieldSet sfs = new SimpleFieldSet(false);
sfs.put("Name", clientName);
sfs.put("ExpectedVersion", clientExpectedVersion);
return sfs;
Modified: trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -120,7 +120,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet sfs = new SimpleFieldSet();
+ SimpleFieldSet sfs = new SimpleFieldSet(false);
sfs.put("URI", uri.toString());
sfs.put("Identifier", identifier);
sfs.put("DataLength", Long.toString(dataLength));
Modified: trunk/freenet/src/freenet/node/fcp/DataFoundMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/DataFoundMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/DataFoundMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -17,7 +17,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
fs.put("Identifier", identifier);
fs.put("Metadata.ContentType", mimeType);
fs.put("DataLength", Long.toString(dataLength));
Modified: trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -44,7 +44,7 @@
// Read a message
String messageType = lis.readLine(64, 64);
if(messageType.equals("")) continue;
- fs = new SimpleFieldSet(lis, 4096, 128);
+ fs = new SimpleFieldSet(lis, 4096, 128, false);
FCPMessage msg;
try {
msg = FCPMessage.create(messageType, fs);
Modified: trunk/freenet/src/freenet/node/fcp/FCPServer.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPServer.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/FCPServer.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -5,6 +5,10 @@
import java.net.ServerSocket;
import java.net.Socket;
+import freenet.config.Config;
+import freenet.config.IntCallback;
+import freenet.config.InvalidConfigValueException;
+import freenet.config.SubConfig;
import freenet.node.Node;
import freenet.support.Logger;
@@ -15,8 +19,10 @@
final ServerSocket sock;
final Node node;
+ final int port;
public FCPServer(int port, Node node) throws IOException {
+ this.port = port;
this.sock = new ServerSocket(port, 0,
InetAddress.getByName("127.0.0.1"));
this.node = node;
Thread t = new Thread(this, "FCP server");
@@ -42,4 +48,35 @@
FCPConnectionHandler handler = new FCPConnectionHandler(s,
node);
}
+ static class FCPPortNumberCallback implements IntCallback {
+
+ final Node node;
+
+ FCPPortNumberCallback(Node node) {
+ this.node = node;
+ }
+
+ public int get() {
+ return node.getFCPServer().port;
+ }
+
+ public void set(int val) throws InvalidConfigValueException {
+ if(val != get()) {
+ throw new InvalidConfigValueException("Cannot
change FCP port number on the fly");
+ }
+ }
+
+ }
+
+ public static FCPServer maybeCreate(Node node, Config config) throws
IOException {
+ SubConfig fcpConfig = new SubConfig("fcp", config);
+ // FIXME check enabled etc
+ fcpConfig.register("port", 9481 /* anagram of 1984, and 1000 up
from old number */,
+ 2, true, "FCP port number", "FCP port number",
new FCPPortNumberCallback(node));
+ FCPServer fcp = new FCPServer(fcpConfig.getInt("port"), node);
+ node.setFCPServer(fcp);
+ fcpConfig.finishedInitialization();
+ return fcp;
+ }
+
}
Modified: trunk/freenet/src/freenet/node/fcp/FinishedCompressionMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FinishedCompressionMessage.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/FinishedCompressionMessage.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -19,7 +19,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
fs.put("Identifier", identifier);
fs.put("Codec", Integer.toString(codec));
fs.put("OriginalSize", Long.toString(origSize));
Modified: trunk/freenet/src/freenet/node/fcp/GenerateSSKMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/GenerateSSKMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/GenerateSSKMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -15,7 +15,7 @@
}
public SimpleFieldSet getFieldSet() {
- return new SimpleFieldSet();
+ return new SimpleFieldSet(false);
}
public String getName() {
Modified: trunk/freenet/src/freenet/node/fcp/GetFailedMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/GetFailedMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/GetFailedMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -26,7 +26,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet sfs = new SimpleFieldSet();
+ SimpleFieldSet sfs = new SimpleFieldSet(false);
sfs.put("Code", Integer.toString(code));
sfs.put("CodeDescription", codeDescription);
if(extraDescription != null)
Modified: trunk/freenet/src/freenet/node/fcp/IdentifierCollisionMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/IdentifierCollisionMessage.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/IdentifierCollisionMessage.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -12,7 +12,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet sfs = new SimpleFieldSet();
+ SimpleFieldSet sfs = new SimpleFieldSet(false);
sfs.put("Identifier", identifier);
return sfs;
}
Modified: trunk/freenet/src/freenet/node/fcp/NodeHelloMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/NodeHelloMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/NodeHelloMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -23,7 +23,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet sfs = new SimpleFieldSet();
+ SimpleFieldSet sfs = new SimpleFieldSet(false);
// FIXME
sfs.put("FCPVersion", "2.0");
sfs.put("Node", "Fred");
Modified: trunk/freenet/src/freenet/node/fcp/ProtocolErrorMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ProtocolErrorMessage.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/ProtocolErrorMessage.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -82,7 +82,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet sfs = new SimpleFieldSet();
+ SimpleFieldSet sfs = new SimpleFieldSet(false);
if(ident != null)
sfs.put("Identifier", ident);
sfs.put("Code", Integer.toString(code));
Modified: trunk/freenet/src/freenet/node/fcp/PutFailedMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/PutFailedMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/PutFailedMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -29,7 +29,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
fs.put("Identifier", identifier);
fs.put("Code", Integer.toString(code));
fs.put("CodeDescription", codeDescription);
Modified: trunk/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -15,7 +15,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
fs.put("Identifier", identifier);
fs.put("URI", uri.toString());
return fs;
Modified: trunk/freenet/src/freenet/node/fcp/SSKKeypairMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/SSKKeypairMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/SSKKeypairMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -17,7 +17,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet sfs = new SimpleFieldSet();
+ SimpleFieldSet sfs = new SimpleFieldSet(false);
sfs.put("InsertURI", insertURI.toString());
sfs.put("RequestURI", requestURI.toString());
if(identifier != null) // is optional on these two only
Modified: trunk/freenet/src/freenet/node/fcp/SimpleProgressMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/SimpleProgressMessage.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/SimpleProgressMessage.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -15,7 +15,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
fs.put("Total", Integer.toString(event.totalBlocks));
fs.put("Required", Integer.toString(event.minSuccessfulBlocks));
fs.put("Failed", Integer.toString(event.failedBlocks));
Modified: trunk/freenet/src/freenet/node/fcp/StartedCompressionMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/StartedCompressionMessage.java
2006-02-21 02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/StartedCompressionMessage.java
2006-02-21 02:31:47 UTC (rev 8078)
@@ -15,7 +15,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
fs.put("Identifier", identifier);
fs.put("Codec", Integer.toString(codec));
return fs;
Modified: trunk/freenet/src/freenet/node/fcp/URIGeneratedMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/URIGeneratedMessage.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/node/fcp/URIGeneratedMessage.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -15,7 +15,7 @@
}
public SimpleFieldSet getFieldSet() {
- SimpleFieldSet fs = new SimpleFieldSet();
+ SimpleFieldSet fs = new SimpleFieldSet(false);
fs.put("URI", uri.toString());
fs.put("Identifier", identifier);
return fs;
Modified: trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java
===================================================================
--- trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -54,7 +54,7 @@
private final TupleBinding longTupleBinding;
private int chkBlocksInStore;
- private final int maxChkBlocks;
+ private long maxChkBlocks;
private final Database chkDB;
private final Database chkDB_accessTime;
private final RandomAccessFile chkStore;
@@ -68,7 +68,7 @@
* @param the directory where the store is located
* @throws FileNotFoundException if the dir does not exist and could not
be created
*/
- public BerkeleyDBFreenetStore(String storeDir, int maxChkBlocks, int
blockSize, int headerSize) throws Exception {
+ public BerkeleyDBFreenetStore(String storeDir, long maxChkBlocks, int
blockSize, int headerSize) throws Exception {
this.dataBlockSize = blockSize;
this.headerBlockSize = headerSize;
// Percentage of the database that must contain usefull data
@@ -425,7 +425,7 @@
synchronized(chkStore) {
if(chkBlocksInStore<maxChkBlocks) {
// Expand the store file
- int byteOffset =
chkBlocksInStore*(dataBlockSize+headerBlockSize);
+ long byteOffset =
chkBlocksInStore*(dataBlockSize+headerBlockSize);
StoreBlock storeBlock = new
StoreBlock(chkBlocksInStore);
DatabaseEntry blockDBE = new DatabaseEntry();
storeBlockTupleBinding.objectToEntry(storeBlock,
blockDBE);
@@ -494,7 +494,7 @@
synchronized(chkStore) {
if(chkBlocksInStore<maxChkBlocks) {
// Expand the store file
- int byteOffset =
chkBlocksInStore*(dataBlockSize+headerBlockSize);
+ long byteOffset =
chkBlocksInStore*(dataBlockSize+headerBlockSize);
StoreBlock storeBlock = new
StoreBlock(chkBlocksInStore);
DatabaseEntry blockDBE = new DatabaseEntry();
storeBlockTupleBinding.objectToEntry(storeBlock,
blockDBE);
@@ -538,14 +538,14 @@
private class StoreBlock
{
private long recentlyUsed;
- private int offset;
+ private long offset;
- public StoreBlock(int offset)
+ public StoreBlock(long offset)
{
this(offset,getNewRecentlyUsed());
}
- public StoreBlock(int offset,long recentlyUsed)
+ public StoreBlock(long offset,long recentlyUsed)
{
this.offset = offset;
this.recentlyUsed = recentlyUsed;
@@ -566,11 +566,11 @@
recentlyUsed = getNewRecentlyUsed();
}
- public int getOffset() {
+ public long getOffset() {
return offset;
}
}
-
+
/**
* Convert StoreBlock's to the format used by the database
*/
@@ -580,12 +580,12 @@
public void objectToEntry(Object object, TupleOutput to) {
StoreBlock myData = (StoreBlock)object;
- to.writeInt(myData.getOffset());
+ to.writeLong(myData.getOffset());
to.writeLong(myData.getRecentlyUsed());
}
public Object entryToObject(TupleInput ti) {
- int offset = ti.readInt();
+ long offset = ti.available() == 12 ? ti.readInt() :
ti.readLong();
long lastAccessed = ti.readLong();
StoreBlock storeBlock = new StoreBlock(offset,lastAccessed);
@@ -679,4 +679,8 @@
lastRecentlyUsed++;
return lastRecentlyUsed;
}
+
+ public void setMaxKeys(long maxStoreKeys) {
+ maxChkBlocks = maxStoreKeys;
+ }
}
\ No newline at end of file
Modified: trunk/freenet/src/freenet/store/FreenetStore.java
===================================================================
--- trunk/freenet/src/freenet/store/FreenetStore.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/store/FreenetStore.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -43,4 +43,10 @@
* Store a public key.
*/
public void put(byte[] hash, DSAPublicKey key) throws IOException;
+
+ /**
+ * Change the store size.
+ * @param maxStoreKeys The maximum number of keys to be cached.
+ */
+ public void setMaxKeys(long maxStoreKeys);
}
Modified: trunk/freenet/src/freenet/support/Fields.java
===================================================================
--- trunk/freenet/src/freenet/support/Fields.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/support/Fields.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -522,4 +522,99 @@
return buf;
}
+ /**
+ * Parse a human-readable string possibly including SI units into a short.
+ * @throws NumberFormatException
+ * if the string is not parseable
+ */
+ public static short parseShort(String s) throws NumberFormatException {
+ short res = 1;
+ int x = s.length() - 1;
+ int idx;
+ try {
+ long[] l =
+ {
+ 1000,
+ 1 << 10 };
+ while (x >= 0
+ && ((idx = "kK".indexOf(s.charAt(x))) != -1)) {
+ x--;
+ res *= l[idx];
+ }
+ res *= Double.parseDouble(s.substring(0, x + 1));
+ } catch (ArithmeticException e) {
+ res = Short.MAX_VALUE;
+ throw new NumberFormatException(e.getMessage());
+ }
+ return res;
+ }
+
+ /**
+ * Parse a human-readable string possibly including SI units into an
integer.
+ * @throws NumberFormatException
+ * if the string is not parseable
+ */
+ public static int parseInt(String s) throws NumberFormatException {
+ int res = 1;
+ int x = s.length() - 1;
+ int idx;
+ try {
+ long[] l =
+ {
+ 1000,
+ 1 << 10,
+ 1000 * 1000,
+ 1 << 20,
+ 1000 * 1000 * 1000,
+ 1 << 30 };
+ while (x >= 0
+ && ((idx = "kKmMgG".indexOf(s.charAt(x))) !=
-1)) {
+ x--;
+ res *= l[idx];
+ }
+ res *= Double.parseDouble(s.substring(0, x + 1));
+ } catch (ArithmeticException e) {
+ res = Integer.MAX_VALUE;
+ throw new NumberFormatException(e.getMessage());
+ }
+ return res;
+ }
+
+ /**
+ * Parse a human-readable string possibly including SI units into a
long.
+ * @throws NumberFormatException
+ * if the string is not parseable
+ */
+ public static long parseLong(String s) throws NumberFormatException {
+ long res = 1;
+ int x = s.length() - 1;
+ int idx;
+ try {
+ long[] l =
+ {
+ 1000,
+ 1 << 10,
+ 1000 * 1000,
+ 1 << 20,
+ 1000 * 1000 * 1000,
+ 1 << 30,
+ 1000 * 1000 * 1000 * 1000,
+ 1 << 40,
+ 1000 * 1000 * 1000 * 1000 * 1000,
+ 1 << 50,
+ 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
+ 1 << 60 };
+ while (x >= 0
+ && ((idx = "kKmMgGtTpPeE".indexOf(s.charAt(x)))
!= -1)) {
+ x--;
+ res *= l[idx];
+ }
+ res *= Double.parseDouble(s.substring(0, x + 1));
+ } catch (ArithmeticException e) {
+ res = Long.MAX_VALUE;
+ throw new NumberFormatException(e.getMessage());
+ }
+ return res;
+ }
+
}
Modified: trunk/freenet/src/freenet/support/FileLoggerHook.java
===================================================================
--- trunk/freenet/src/freenet/support/FileLoggerHook.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/support/FileLoggerHook.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -13,6 +13,7 @@
import java.io.PrintWriter;
import java.net.InetAddress;
import java.text.DateFormat;
+import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@@ -26,6 +27,7 @@
import java.util.zip.GZIPOutputStream;
import freenet.node.Version;
+import freenet.support.LoggerHook.InvalidThresholdException;
/**
* Converted the old StandardLogger to Ian's loggerhook interface.
@@ -96,7 +98,7 @@
protected long MAX_LIST_BYTES = 10 * (1 << 20);
// FIXME: should reimplement LinkedList with minimal locking
- final long maxOldLogfilesDiskUsage;
+ long maxOldLogfilesDiskUsage;
protected final LinkedList logFiles = new LinkedList();
private long oldLogFilesDiskSpaceUsage = 0;
@@ -121,7 +123,7 @@
MAX_LIST_BYTES = len;
}
- public void setInterval(String intervalName) {
+ public void setInterval(String intervalName) throws
IntervalParseException {
StringBuffer sb = new StringBuffer(intervalName.length());
for(int i=0;i<intervalName.length();i++) {
char c = intervalName.charAt(i);
@@ -151,10 +153,17 @@
else if (intervalName.equalsIgnoreCase("YEAR"))
INTERVAL = Calendar.YEAR;
else
- throw new IllegalArgumentException(
- "invalid interval " + intervalName);
+ throw new IntervalParseException("invalid interval " +
intervalName);
}
+ public class IntervalParseException extends Exception {
+
+ public IntervalParseException(String string) {
+ super(string);
+ }
+
+ }
+
protected String getHourLogName(Calendar c, boolean compressed) {
StringBuffer buf = new StringBuffer(50);
buf.append(baseFilename).append('-');
@@ -243,7 +252,7 @@
try {
thisTime = System.currentTimeMillis();
if (baseFilename != null) {
- if (thisTime > nextHour) {
+ if (thisTime > nextHour ||
switchedBaseFilename) {
// Switch logs
try {
logStream.flush();
@@ -292,6 +301,11 @@
gc.add(INTERVAL,
INTERVAL_MULTIPLIER);
nextHour =
gc.getTimeInMillis();
//System.err.println("Rotated");
+
if(switchedBaseFilename) {
+
synchronized(FileLoggerHook.class) {
+
switchedBaseFilename = false;
+ }
+ }
}
}
if(list.size() == 0) {
@@ -437,16 +451,20 @@
maxOldLogfilesDiskUsage);
}
+ private final Object trimOldLogFilesLock = new Object();
+
public void trimOldLogFiles() {
- while(oldLogFilesDiskSpaceUsage > maxOldLogfilesDiskUsage) {
- OldLogFile olf;
- synchronized(logFiles) {
- olf = (OldLogFile) logFiles.removeFirst();
+ synchronized(trimOldLogFilesLock) {
+ while(oldLogFilesDiskSpaceUsage >
maxOldLogfilesDiskUsage) {
+ OldLogFile olf;
+ synchronized(logFiles) {
+ olf = (OldLogFile)
logFiles.removeFirst();
+ }
+ olf.filename.delete();
+ oldLogFilesDiskSpaceUsage -= olf.size;
+ Logger.minor(this, "Deleting "+olf.filename+" -
saving "+olf.size+
+ " bytes, disk usage now:
"+oldLogFilesDiskSpaceUsage+" of "+maxOldLogfilesDiskUsage);
}
- olf.filename.delete();
- oldLogFilesDiskSpaceUsage -= olf.size;
- Logger.minor(this, "Deleting "+olf.filename+" - saving
"+olf.size+
- " bytes, disk usage now:
"+oldLogFilesDiskSpaceUsage+" of "+maxOldLogfilesDiskUsage);
}
}
@@ -463,6 +481,7 @@
prefix =
baseFilename.substring(slashIndex+1).toLowerCase();
}
File[] files = dir.listFiles();
+ if(files == null) return;
java.util.Arrays.sort(files);
long lastStartTime = -1;
File oldFile = null;
@@ -551,7 +570,7 @@
boolean assumeWorking,
boolean logOverwrite,
long maxOldLogFilesDiskUsage)
- throws IOException {
+ throws IOException, InvalidThresholdException {
this(filename,
fmt,
dfmt,
@@ -587,7 +606,7 @@
OutputStream os,
String fmt,
String dfmt,
- String threshold) {
+ String threshold) throws InvalidThresholdException {
this(new PrintStream(os), fmt, dfmt,
priorityOf(threshold), true);
logStream = os;
}
@@ -656,7 +675,7 @@
String threshold,
boolean assumeWorking,
boolean logOverwrite,
- long maxOldLogFilesDiskUsage) throws IOException{
+ long maxOldLogFilesDiskUsage) throws IOException,
InvalidThresholdException{
this(rotate,baseFilename,fmt,dfmt,priorityOf(threshold),assumeWorking,logOverwrite,maxOldLogFilesDiskUsage);
}
@@ -903,4 +922,45 @@
written += toRead;
}
}
+
+ /** Set the maximum size of old (gzipped) log files to keep.
+ * Will start to prune old files immediately, but this will likely not
be completed
+ * by the time the function returns as it is run off-thread.
+ */
+ public void setMaxOldLogsSize(long val) {
+ maxOldLogfilesDiskUsage = val;
+ Runnable r = new Runnable() {
+ public void run() {
+ trimOldLogFiles();
+ }
+ };
+ Thread t = new Thread(r, "Shrink logs");
+ t.setDaemon(true);
+ t.start();
+ }
+
+ private boolean switchedBaseFilename;
+
+ public void switchBaseFilename(String filename) {
+ synchronized(this) {
+ this.baseFilename = filename;
+ switchedBaseFilename = true;
+ }
+ }
+
+ public void waitForSwitch() {
+ synchronized(this) {
+ if(!switchedBaseFilename) return;
+ long startTime = System.currentTimeMillis();
+ long endTime = startTime + 10000;
+ long now;
+ while((now = System.currentTimeMillis()) < endTime &&
!switchedBaseFilename) {
+ try {
+ wait(Math.max(1, endTime-now));
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ }
+ }
}
Modified: trunk/freenet/src/freenet/support/Logger.java
===================================================================
--- trunk/freenet/src/freenet/support/Logger.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/support/Logger.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -1,5 +1,7 @@
package freenet.support;
+import freenet.support.LoggerHook.InvalidThresholdException;
+
/**
* @author Iakin
@@ -28,7 +30,7 @@
*/
static Logger logger = new VoidLogger();
- public static FileLoggerHook setupStdoutLogging(int level, String
detail) {
+ public static FileLoggerHook setupStdoutLogging(int level, String
detail) throws InvalidThresholdException {
setupChain();
logger.setThreshold(level);
logger.setDetailedThresholds(detail);
@@ -180,15 +182,16 @@
*
* @param symbolicThreshold
* The new threshhold, must be one of ERROR,NORMAL etc..
+ * @throws InvalidThresholdException
*/
- public abstract void setThreshold(String symbolicThreshold);
+ public abstract void setThreshold(String symbolicThreshold) throws
InvalidThresholdException;
/**
* @return The currently used logging threshold
*/
public abstract int getThreshold();
- public abstract void setDetailedThresholds(String details);
+ public abstract void setDetailedThresholds(String details) throws
InvalidThresholdException;
/**
* Report a fatal error and exit.
@@ -201,11 +204,36 @@
System.exit(retcode);
}
- public static void globalAddHook(LoggerHook logger2) {
- ((LoggerHookChain)logger).addHook(logger2);
+ public synchronized static void globalAddHook(LoggerHook logger2) {
+ if(logger instanceof VoidLogger)
+ setupChain();
+ ((LoggerHookChain)logger).addHook(logger2);
}
public static void globalSetThreshold(int i) {
logger.setThreshold(i);
}
+
+ public synchronized static void globalRemoveHook(FileLoggerHook hook) {
+ if(logger instanceof LoggerHookChain)
+ ((LoggerHookChain)logger).removeHook(hook);
+ else
+ System.err.println("Cannot remove hook: "+hook+" global
logger is "+logger);
+ }
+
+ public synchronized static void destroyChainIfEmpty() {
+ if(logger instanceof VoidLogger) return;
+ if(logger instanceof LoggerHookChain &&
((LoggerHookChain)logger).getHooks().length == 0) {
+ logger = new VoidLogger();
+ }
+ }
+
+ public static LoggerHookChain getChain() {
+ if(logger instanceof LoggerHookChain)
+ return (LoggerHookChain) logger;
+ else {
+ setupChain();
+ return (LoggerHookChain) logger;
+ }
+ }
}
Modified: trunk/freenet/src/freenet/support/LoggerHook.java
===================================================================
--- trunk/freenet/src/freenet/support/LoggerHook.java 2006-02-21 02:24:26 UTC
(rev 8077)
+++ trunk/freenet/src/freenet/support/LoggerHook.java 2006-02-21 02:31:47 UTC
(rev 8078)
@@ -20,7 +20,7 @@
this.threshold = thresh;
}
- LoggerHook(String thresh){
+ LoggerHook(String thresh) throws InvalidThresholdException{
this.threshold = priorityOf(thresh);
}
@@ -107,11 +107,11 @@
return threshold;
}
- public void setThreshold(String symbolicThreshold) {
+ public void setThreshold(String symbolicThreshold) throws
InvalidThresholdException {
setThreshold(priorityOf(symbolicThreshold));
}
- public void setDetailedThresholds(String details) {
+ public void setDetailedThresholds(String details) throws
InvalidThresholdException {
if (details == null || details.length() == 0)
return;
StringTokenizer st = new StringTokenizer(details, ",", false);
@@ -141,7 +141,7 @@
* @param s A string matching one of the logging priorities, case
* insensitive.
**/
- public static int priorityOf(String s) {
+ public static int priorityOf(String s) throws InvalidThresholdException {
if (s.equalsIgnoreCase("error"))
return Logger.ERROR;
else if (s.equalsIgnoreCase("normal"))
@@ -152,10 +152,17 @@
return Logger.DEBUG;
else if (s.equalsIgnoreCase("debug"))
return Logger.DEBUG;
- else
- return Logger.NORMAL;
+ else
+ throw new InvalidThresholdException("Unrecognized priority:
"+s);
+ // return Logger.NORMAL;
}
+ public static class InvalidThresholdException extends Exception {
+ InvalidThresholdException(String msg) {
+ super(msg);
+ }
+ }
+
/**
* Returns the name of the priority matching a number, null if none do
* @param priority The priority
Modified: trunk/freenet/src/freenet/support/LoggerHookChain.java
===================================================================
--- trunk/freenet/src/freenet/support/LoggerHookChain.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/support/LoggerHookChain.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -1,5 +1,7 @@
package freenet.support;
+import freenet.support.LoggerHook.InvalidThresholdException;
+
/**
* A class that takes logging messages and distributes them to LoggerHooks.
* It implements LoggerHook itself, so that instances can be chained (just
@@ -27,7 +29,7 @@
super(threshold);
hooks = new LoggerHook[0];
}
- public LoggerHookChain(String threshold) {
+ public LoggerHookChain(String threshold) throws InvalidThresholdException {
super(threshold);
hooks = new LoggerHook[0];
}
@@ -101,7 +103,7 @@
return ((2*ERROR)-1) & ~(threshold-1);
}
- public void setDetailedThresholds(String details) {
+ public void setDetailedThresholds(String details) throws
InvalidThresholdException {
super.setDetailedThresholds(details);
LoggerHook[] h = getHooks();
for (int i = 0; i < h.length; i++)
Modified: trunk/freenet/src/freenet/support/SimpleFieldSet.java
===================================================================
--- trunk/freenet/src/freenet/support/SimpleFieldSet.java 2006-02-21
02:24:26 UTC (rev 8077)
+++ trunk/freenet/src/freenet/support/SimpleFieldSet.java 2006-02-21
02:31:47 UTC (rev 8078)
@@ -11,8 +11,6 @@
import java.util.Map;
import java.util.Set;
-import java.util.Vector;
-
import freenet.support.io.LineReader;
/**
@@ -23,32 +21,38 @@
*/
public class SimpleFieldSet {
- final Map map;
+ final Map map;
String endMarker;
+ final boolean multiLevel;
+ static public final char MULTI_LEVEL_CHAR = '.';
- public SimpleFieldSet(BufferedReader br) throws IOException {
+ public SimpleFieldSet(BufferedReader br, boolean multiLevel) throws
IOException {
map = new HashMap();
+ this.multiLevel = multiLevel;
read(br);
}
- public SimpleFieldSet(LineReader lis, int maxLineLength, int
lineBufferSize) throws IOException {
+ public SimpleFieldSet(LineReader lis, int maxLineLength, int
lineBufferSize, boolean multiLevel) throws IOException {
map = new HashMap();
+ this.multiLevel = multiLevel;
read(lis, maxLineLength, lineBufferSize);
}
/**
* Empty constructor
*/
- public SimpleFieldSet() {
+ public SimpleFieldSet(boolean multiLevel) {
map = new HashMap();
+ this.multiLevel = multiLevel;
}
/**
* Construct from a string.
* @throws IOException if the string is too short or invalid.
*/
- public SimpleFieldSet(String content) throws IOException {
+ public SimpleFieldSet(String content, boolean multiLevel) throws
IOException {
map = new HashMap();
+ this.multiLevel = multiLevel;
StringReader sr = new StringReader(content);
BufferedReader br = new BufferedReader(sr);
read(br);
@@ -58,8 +62,9 @@
* Construct from a string[].
* @throws IOException if the string is too short or invalid.
*/
- public SimpleFieldSet(String[] content) throws IOException {
+ public SimpleFieldSet(String[] content, boolean multiLevel) throws
IOException {
map = new HashMap();
+ this.multiLevel = multiLevel;
String content2=new String();
for(int i=0;i<content.length;i++)
content2.concat(content[i]+";");
@@ -89,7 +94,7 @@
// Mapping
String before = line.substring(0, index);
String after = line.substring(index+1);
- map.put(before, after);
+ put(before, after);
} else {
endMarker = line;
return;
@@ -119,7 +124,7 @@
// Mapping
String before = line.substring(0, index);
String after = line.substring(index+1);
- map.put(before, after);
+ put(before, after);
} else {
endMarker = line;
return;
@@ -127,56 +132,97 @@
}
}
-
public String get(String key) {
- return (String) map.get(key);
+ if(multiLevel) {
+ int idx = key.indexOf(MULTI_LEVEL_CHAR);
+ if(idx == -1)
+ return (String) map.get(key);
+ else {
+ String before = key.substring(0, idx);
+ String after = key.substring(idx+1);
+ SimpleFieldSet fs = (SimpleFieldSet) (map.get(before));
+ if(fs == null) return null;
+ return fs.get(after);
+ }
+ } else {
+ return (String) map.get(key);
+ }
}
public String[] getAll(String key) {
- int index = key.indexOf(';');
- if(index == -1) return null;
- Vector v=new Vector();
- v.removeAllElements();
- while(index>0){
- // Mapping
- String before = key.substring(0, index);
- String after = key.substring(index+1);
- v.addElement(before);
- key=after;
- index = key.indexOf(';');
- }
-
- return (String[]) v.toArray();
+ return split(get(key));
}
- public void put(String key, String value) {
- String x = (String) map.get(key);
-
- if(x == null) {
- map.put(key, value);
- } else {
- map.put(key, ((String)map.get(key))+";"+value);
- }
+ private static final String[] split(String string) {
+ return string.split(";"); // slower???
+// int index = string.indexOf(';');
+// if(index == -1) return null;
+// Vector v=new Vector();
+// v.removeAllElements();
+// while(index>0){
+// // Mapping
+// String before = string.substring(0, index);
+// String after = string.substring(index+1);
+// v.addElement(before);
+// string=after;
+// index = string.indexOf(';');
+// }
+//
+// return (String[]) v.toArray();
+ }
+
+ public void put(String key, String value) {
+ int idx;
+ if((!multiLevel) || (idx = key.indexOf(MULTI_LEVEL_CHAR)) ==
-1) {
+ String x = (String) map.get(key);
+
+ if(x == null) {
+ map.put(key, value);
+ } else {
+ map.put(key, ((String)map.get(key))+";"+value);
+ }
+ } else {
+ String before = key.substring(0, idx);
+ String after = key.substring(idx+1);
+ SimpleFieldSet fs = (SimpleFieldSet) (map.get(before));
+ if(fs == null) {
+ fs = new SimpleFieldSet(true);
+ map.put(before, fs);
+ }
+ fs.put(after, value);
+ }
}
/**
* Write the contents of the SimpleFieldSet to a Writer.
* @param osr
*/
- public void writeTo(Writer w) throws IOException {
+ public void writeTo(Writer w) throws IOException {
+ writeTo(w, "", false);
+ }
+
+ void writeTo(Writer w, String prefix, boolean noEndMarker) throws
IOException {
Set s = map.entrySet();
Iterator i = s.iterator();
for(;i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
String key = (String) entry.getKey();
- String value = (String) entry.getValue();
- w.write(key+"="+value+"\n");
+ Object v = entry.getValue();
+ if(v instanceof String) {
+ String value = (String) v;
+ w.write(prefix+key+"="+value+"\n");
+ } else {
+ SimpleFieldSet sfs = (SimpleFieldSet) v;
+ sfs.writeTo(w, prefix+key+MULTI_LEVEL_CHAR, true);
+ }
}
- if(endMarker != null)
- w.write(endMarker+"\n");
- else
- w.write("End\n");
+ if(!noEndMarker) {
+ if(endMarker != null)
+ w.write(endMarker+"\n");
+ else
+ w.write("End\n");
+ }
}
public String toString() {
@@ -196,4 +242,73 @@
public void setEndMarker(String s) {
endMarker = s;
}
+
+ public SimpleFieldSet subset(String key) {
+ if(!multiLevel)
+ throw new IllegalArgumentException("Not multi-level!");
+ int idx = key.indexOf(MULTI_LEVEL_CHAR);
+ if(idx == -1)
+ return (SimpleFieldSet) map.get(key);
+ String before = key.substring(0, idx);
+ String after = key.substring(idx+1);
+ SimpleFieldSet fs = (SimpleFieldSet) map.get(before);
+ if(fs == null) return null;
+ return fs.subset(after);
+ }
+
+ public Iterator keyIterator() {
+ return new KeyIterator();
+ }
+
+ public class KeyIterator implements Iterator {
+
+ final Iterator mapIterator;
+ KeyIterator subIterator;
+
+ public KeyIterator() {
+ mapIterator = map.keySet().iterator();
+ }
+
+ public boolean hasNext() {
+ if(subIterator != null && subIterator.hasNext()) return
true;
+ if(subIterator != null) subIterator = null;
+ return mapIterator.hasNext();
+ }
+
+ public Object next() {
+ while(true) { // tail-recurse so we get infinite loop
instead of OOM in case of a loop...
+ if(subIterator != null && subIterator.hasNext())
+ return subIterator.next();
+ if(subIterator != null) subIterator = null;
+ if(mapIterator.hasNext()) {
+ String key = (String)
mapIterator.next();
+ Object value = map.get(key);
+ if(value instanceof String)
+ return value;
+ else {
+ SimpleFieldSet fs =
(SimpleFieldSet) value;
+ subIterator = (KeyIterator)
fs.keyIterator();
+ continue;
+ }
+ }
+ return null;
+ }
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ public void put(String key, SimpleFieldSet fs) {
+ if(!multiLevel)
+ throw new IllegalArgumentException("Not multi-level");
+ if(!fs.multiLevel)
+ throw new IllegalArgumentException("Argument not
multi-level");
+ if(map.containsKey(key))
+ throw new IllegalArgumentException("Already contains
"+key+" but trying to add a SimpleFieldSet!");
+ map.put(key, fs);
+ }
+
}
Modified: trunk/freenet/src/snmplib/SNMPStarter.java
===================================================================
--- trunk/freenet/src/snmplib/SNMPStarter.java 2006-02-21 02:24:26 UTC (rev
8077)
+++ trunk/freenet/src/snmplib/SNMPStarter.java 2006-02-21 02:31:47 UTC (rev
8078)
@@ -1,6 +1,8 @@
package snmplib;
+import freenet.config.Config;
import freenet.io.comm.IOStatisticCollector;
+import freenet.node.Node;
/**
* @author cyberdo
@@ -23,4 +25,8 @@
has_been_runned = true;
}
+
+ public static void maybeCreate(Node node, Config config) {
+ // FIXME any config needed for SNMPStarter?
+ }
}