Author: toad
Date: 2006-12-21 01:52:49 +0000 (Thu, 21 Dec 2006)
New Revision: 11503

Added:
   trunk/freenet/src/freenet/node/simulator/
   trunk/freenet/src/freenet/node/simulator/RealNodePingTest.java
   trunk/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java
   trunk/freenet/src/freenet/node/simulator/RealNodeRoutingTest.java
Removed:
   trunk/freenet/src/freenet/node/RealNodePingTest.java
   trunk/freenet/src/freenet/node/RealNodeRequestInsertTest.java
   trunk/freenet/src/freenet/node/RealNodeRoutingTest.java
Modified:
   trunk/freenet/src/freenet/config/FilePersistentConfig.java
   trunk/freenet/src/freenet/config/FreenetFilePersistentConfig.java
   trunk/freenet/src/freenet/config/PersistentConfig.java
   trunk/freenet/src/freenet/io/comm/UdpSocketManager.java
   trunk/freenet/src/freenet/node/InsertHandler.java
   trunk/freenet/src/freenet/node/LocationManager.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/NodeClientCore.java
   trunk/freenet/src/freenet/node/NodeDispatcher.java
   trunk/freenet/src/freenet/node/NodeStarter.java
   trunk/freenet/src/freenet/node/PeerNode.java
   trunk/freenet/src/freenet/node/RequestHandler.java
   trunk/freenet/src/freenet/node/SSKInsertHandler.java
Log:
freenet/node/simulator - initially just the old Test classes. This is a 
directory for code which does network simulations using the real live freenet 
node code, by creating multiple nodes in one VM.
also related refactorings, and various new expert config options.

Modified: trunk/freenet/src/freenet/config/FilePersistentConfig.java
===================================================================
--- trunk/freenet/src/freenet/config/FilePersistentConfig.java  2006-12-20 
23:49:34 UTC (rev 11502)
+++ trunk/freenet/src/freenet/config/FilePersistentConfig.java  2006-12-21 
01:52:49 UTC (rev 11503)
@@ -31,25 +31,28 @@
        final File filename;
        final File tempFilename;
        protected final Object storeSync = new Object();
+
+       public static FilePersistentConfig constructFilePersistentConfig(File 
f) throws IOException {
+               File filename = f;
+               File tempFilename = new File(f.getPath()+".tmp");
+               return new FilePersistentConfig(load(filename, tempFilename), 
filename, tempFilename);
+       }

-       public FilePersistentConfig(File f) throws IOException {
-               this.filename = f;
-               this.tempFilename = new File(f.getPath()+".tmp");
+       static SimpleFieldSet load(File filename, File tempFilename) throws 
IOException {
                boolean filenameExists = filename.exists();
                boolean tempFilenameExists = tempFilename.exists();
                if(filenameExists && !filename.canWrite()) {
-                       Logger.error(this, "Warning: Cannot write to config 
file: "+filename);
+                       Logger.error(FilePersistentConfig.class, "Warning: 
Cannot write to config file: "+filename);
                        System.err.println("Warning: Cannot write to config 
file: "+filename);
                }
                if(tempFilenameExists && !tempFilename.canWrite()) {
-                       Logger.error(this, "Warning: Cannot write to config 
tempfile: "+tempFilename);
+                       Logger.error(FilePersistentConfig.class, "Warning: 
Cannot write to config tempfile: "+tempFilename);
                        System.err.println("Warning: Cannot write to config 
tempfile: "+tempFilename);
                }
                if(filenameExists) {
-                       if(f.canRead()) {
+                       if(filename.canRead()) {
                                try {
-                                       initialLoad(filename);
-                                       return;
+                                       return initialLoad(filename);
                                } catch (FileNotFoundException e) {
                                        System.err.println("Cannot open config 
file "+filename+" : "+e+" - checking for temp file "+tempFilename);
                                } catch (EOFException e) {
@@ -65,7 +68,7 @@
                if(tempFilename.exists()) {
                        if(tempFilename.canRead()) {
                                try {
-                                       initialLoad(tempFilename);
+                                       return initialLoad(tempFilename);
                                } catch (FileNotFoundException e) {
                                        System.err.println("Cannot open temp 
config file either: "+tempFilename+" : "+e);
                                } // Other IOE's indicate a more serious 
problem.
@@ -74,25 +77,31 @@
                                throw new IOException("Cannot read (temp) 
config file "+tempFilename);
                        }
                }
-               System.err.println("No config file found, creating new: "+f);
+               System.err.println("No config file found, creating new: 
"+filename);
+               return null;
        }
+       
+       protected FilePersistentConfig(SimpleFieldSet origFS, File fnam, File 
temp) throws IOException {
+               super(origFS);
+               this.filename = fnam;
+               this.tempFilename = temp;
+       }

        /** Load the config file into a SimpleFieldSet. 
         * @throws IOException */
-       protected void initialLoad(File toRead) throws IOException {
+       private static SimpleFieldSet initialLoad(File toRead) throws 
IOException {
+               if(toRead == null) return null;
                FileInputStream fis = new FileInputStream(toRead);
                BufferedInputStream bis = new BufferedInputStream(fis);
                try {
                        LineReadingInputStream lis = new 
LineReadingInputStream(bis);
                        // Config file is UTF-8 too!
-                       synchronized (this) {
-                               origConfigFileContents = new 
SimpleFieldSet(lis, 32768, 128, true, true);
-                       }
+                       return new SimpleFieldSet(lis, 32768, 128, true, true);
                } finally {
                        try {
                                fis.close();
                        } catch (IOException e) {
-                               System.err.println("Could not close 
"+filename+": "+e);
+                               System.err.println("Could not close "+toRead+": 
"+e);
                                e.printStackTrace();
                        }
                }

Modified: trunk/freenet/src/freenet/config/FreenetFilePersistentConfig.java
===================================================================
--- trunk/freenet/src/freenet/config/FreenetFilePersistentConfig.java   
2006-12-20 23:49:34 UTC (rev 11502)
+++ trunk/freenet/src/freenet/config/FreenetFilePersistentConfig.java   
2006-12-21 01:52:49 UTC (rev 11503)
@@ -5,6 +5,7 @@

 import freenet.node.Ticker;
 import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;

 public class FreenetFilePersistentConfig extends FilePersistentConfig {
        private boolean isWritingConfig = false;
@@ -34,10 +35,16 @@
                }
        };

-       public FreenetFilePersistentConfig(File f) throws IOException {
-               super(f);
+       public FreenetFilePersistentConfig(SimpleFieldSet set, File filename, 
File tempFilename) throws IOException {
+               super(set, filename, tempFilename);
        }

+       public static FreenetFilePersistentConfig 
constructFreenetFilePersistentConfig(File f) throws IOException {
+               File filename = f;
+               File tempFilename = new File(f.getPath()+".tmp");
+               return new FreenetFilePersistentConfig(load(filename, 
tempFilename), filename, tempFilename);
+       }
+       
        public void store() {
                synchronized(this) {
                        if(!finishedInit) {

Modified: trunk/freenet/src/freenet/config/PersistentConfig.java
===================================================================
--- trunk/freenet/src/freenet/config/PersistentConfig.java      2006-12-20 
23:49:34 UTC (rev 11502)
+++ trunk/freenet/src/freenet/config/PersistentConfig.java      2006-12-21 
01:52:49 UTC (rev 11503)
@@ -13,6 +13,10 @@
        protected SimpleFieldSet origConfigFileContents;
        protected boolean finishedInit;

+       public PersistentConfig(SimpleFieldSet initialContents) {
+               this.origConfigFileContents = initialContents;
+       }
+       
        /**
         * Finished initialization. So any remaining options must be invalid.
         */

Modified: trunk/freenet/src/freenet/io/comm/UdpSocketManager.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/UdpSocketManager.java     2006-12-20 
23:49:34 UTC (rev 11502)
+++ trunk/freenet/src/freenet/io/comm/UdpSocketManager.java     2006-12-21 
01:52:49 UTC (rev 11503)
@@ -708,4 +708,8 @@
                }
                return messageCounts;
        }
+
+       public int getDropProbability() {
+               return _dropProbability;
+       }
 }

Modified: trunk/freenet/src/freenet/node/InsertHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/InsertHandler.java   2006-12-20 23:49:34 UTC 
(rev 11502)
+++ trunk/freenet/src/freenet/node/InsertHandler.java   2006-12-21 01:52:49 UTC 
(rev 11503)
@@ -59,7 +59,7 @@
         double myLoc = node.lm.getLocation().getValue();
         if(PeerManager.distance(targetLoc, myLoc) < 
PeerManager.distance(targetLoc, closestLoc)) {
             closestLoc = myLoc;
-            htl = Node.MAX_HTL;
+            htl = node.maxHTL();
             resetNearestLoc = true;
         } else resetNearestLoc = false;
         logMINOR = Logger.shouldLog(Logger.MINOR, this);

Modified: trunk/freenet/src/freenet/node/LocationManager.java
===================================================================
--- trunk/freenet/src/freenet/node/LocationManager.java 2006-12-20 23:49:34 UTC 
(rev 11502)
+++ trunk/freenet/src/freenet/node/LocationManager.java 2006-12-21 01:52:49 UTC 
(rev 11503)
@@ -28,7 +28,7 @@
  * Tracks the Location of the node. Negotiates swap attempts.
  * Initiates swap attempts. Deals with locking.
  */
-class LocationManager {
+public class LocationManager {

     public class MyCallback extends SendMessageOnErrorCallback {


Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-12-20 23:49:34 UTC (rev 
11502)
+++ trunk/freenet/src/freenet/node/Node.java    2006-12-21 01:52:49 UTC (rev 
11503)
@@ -37,8 +37,10 @@
 import com.sleepycat.je.EnvironmentMutableConfig;

 import freenet.client.FetcherContext;
+import freenet.config.Config;
 import freenet.config.FreenetFilePersistentConfig;
 import freenet.config.InvalidConfigValueException;
+import freenet.config.PersistentConfig;
 import freenet.config.SubConfig;
 import freenet.crypt.DSA;
 import freenet.crypt.DSAGroup;
@@ -56,6 +58,7 @@
 import freenet.io.comm.MessageFilter;
 import freenet.io.comm.Peer;
 import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
 import freenet.io.comm.UdpSocketManager;
 import freenet.io.xfer.PartiallyReceivedBlock;
 import freenet.keys.CHKBlock;
@@ -100,8 +103,10 @@
 import freenet.support.SimpleFieldSet;
 import freenet.support.TimeUtil;
 import freenet.support.TokenBucket;
+import freenet.support.api.BooleanCallback;
 import freenet.support.api.IntCallback;
 import freenet.support.api.LongCallback;
+import freenet.support.api.ShortCallback;
 import freenet.support.api.StringCallback;
 import freenet.support.math.RunningAverage;
 import freenet.support.math.TimeDecayingRunningAverage;
@@ -163,7 +168,7 @@
        }

        /** Config object for the whole node. */
-       public final FreenetFilePersistentConfig config;
+       public final PersistentConfig config;

        // Static stuff related to logger

@@ -344,6 +349,10 @@
        public final TimeDecayingRunningAverage pInstantRejectIncoming;
        /** IP detector */
        public final NodeIPDetector ipDetector;
+    /** For debugging/testing, set this to true to stop the
+     * probabilistic decrement at the edges of the HTLs.
+     */
+    boolean disableProbabilisticHTLs;

        private final HashSet runningUIDs;

@@ -372,7 +381,7 @@
        public final PacketSender ps;
        final NodeDispatcher dispatcher;
        final NodePinger nodePinger;
-       static final int MAX_CACHED_KEYS = 1000;
+       static final int MAX_MEMORY_CACHED_PUBKEYS = 1000;
        final LRUHashtable cachedPubKeys;
        final boolean testnetEnabled;
        final TestnetHandler testnetHandler;
@@ -381,7 +390,9 @@
        final TokenBucket requestOutputThrottle;
        final TokenBucket requestInputThrottle;
        private boolean inputLimitDefault;
-       public static short MAX_HTL = 10;
+       public static final short DEFAULT_MAX_HTL = (short)10;
+       public static final int DEFAULT_SWAP_INTERVAL = 2000;
+       private short maxHTL;
        public static final int EXIT_STORE_FILE_NOT_FOUND = 1;
        public static final int EXIT_STORE_IOEXCEPTION = 2;
        public static final int EXIT_STORE_OTHER = 3;
@@ -407,6 +418,7 @@
        public static final int EXIT_EXTRA_PEER_DATA_DIR = 22;
        public static final int EXIT_THROTTLE_FILE_ERROR = 23;
        public static final int EXIT_RESTART_FAILED = 24;
+       public static final int EXIT_TEST_ERROR = 25;

        public static final int PEER_NODE_STATUS_CONNECTED = 1;
        public static final int PEER_NODE_STATUS_ROUTING_BACKED_OFF = 2;
@@ -673,7 +685,7 @@
                NodeStarter.main(args);
        }

-       static class NodeInitException extends Exception {
+       public static class NodeInitException extends Exception {
                // One of the exit codes from above
                public final int exitCode;
                private static final long serialVersionUID = -1;
@@ -704,7 +716,7 @@
         * @param the loggingHandler
         * @throws NodeInitException If the node initialization fails.
         */
-        Node(FreenetFilePersistentConfig config, RandomSource random, 
LoggingConfigHandler lc, NodeStarter ns) throws NodeInitException {
+        Node(PersistentConfig config, RandomSource random, 
LoggingConfigHandler lc, NodeStarter ns) throws NodeInitException {
                // Easy stuff
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
                String tmp = "Initializing Node using freenet Build 
#"+Version.buildNumber()+" r"+Version.cvsRevision+" and freenet-ext Build 
#"+NodeStarter.extBuildNumber+" r"+NodeStarter.extRevisionNumber;
@@ -736,9 +748,6 @@
                runningUIDs = new HashSet();
                dnsr = new DNSRequester(this);
                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();
                throttledPacketSendAverage =
                        new TimeDecayingRunningAverage(1, 10*60*1000 /* should 
be significantly longer than a typical transfer */, 0, Long.MAX_VALUE);
@@ -749,7 +758,40 @@
                // Setup node-specific configuration
                SubConfig nodeConfig = new SubConfig("node", config);

+               nodeConfig.register("disableProbabilisticHTLs", false, 
sortOrder++, true, false, "Disable probabilistic HTL", "Disable probabilistic 
HTL (don't touch this unless you know what you are doing)", 
+                               new BooleanCallback() {
+
+                                       public boolean get() {
+                                               return disableProbabilisticHTLs;
+                                       }
+
+                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                               disableProbabilisticHTLs = val;
+                                       }
+                       
+               });

+               disableProbabilisticHTLs = 
nodeConfig.getBoolean("disableProbabilisticHTLs");
+               
+               nodeConfig.register("maxHTL", DEFAULT_MAX_HTL, sortOrder++, 
true, false, "Maximum HTL", "Maximum HTL (FOR DEVELOPER USE ONLY!)",
+                               new ShortCallback() {
+
+                                       public short get() {
+                                               return maxHTL;
+                                       }
+
+                                       public void set(short val) throws 
InvalidConfigValueException {
+                                               if(maxHTL < 0) throw new 
InvalidConfigValueException("Impossible max HTL");
+                                               maxHTL = val;
+                                       }
+               });
+               
+               maxHTL = nodeConfig.getShort("maxHTL");
+               
+               // FIXME maybe these should persist? They need to be private.
+               decrementAtMax = random.nextDouble() <= DECREMENT_AT_MAX_PROB;
+               decrementAtMin = random.nextDouble() <= DECREMENT_AT_MIN_PROB;
+               
                nodeConfig.register("aggressiveGC", aggressiveGCModificator, 
sortOrder++, true, false, "AggressiveGC modificator", "Enables the user to 
tweak the time in between GC and forced finalization. SHOULD NOT BE CHANGED 
unless you know what you're doing! -1 means : disable forced call to 
System.gc() and System.runFinalization()",
                                new IntCallback() {
                                        public int get() {
@@ -777,8 +819,6 @@

                // Determine where to bind to

-
-               
                nodeConfig.register("bindTo", "0.0.0.0", sortOrder++, true, 
true, "IP address to bind to", "IP address to bind to",
                                new NodeBindtoCallback(this));

@@ -843,7 +883,23 @@
                Logger.normal(this, "FNP port created on "+bindto+ ':' +port);
                System.out.println("FNP port created on "+bindto+ ':' +port);
                portNumber = port;
+
+               nodeConfig.register("testingDropPacketsEvery", 0, sortOrder++, 
true, false, "Testing packet drop frequency", "Frequency of dropping packets. 
Testing option used by devs to simulate packet loss. 0 means never artificially 
drop a packet. Don't touch this!",
+                               new IntCallback() {
+
+                                       public int get() {
+                                               return usm.getDropProbability();
+                                       }
+
+                                       public void set(int val) throws 
InvalidConfigValueException {
+                                               usm.setDropProbability(val);
+                                       }
+                       
+               });

+               int dropProb = nodeConfig.getInt("testingDropPacketsEvery");
+               usm.setDropProbability(dropProb);
+               
                Logger.normal(Node.class, "Creating node...");

                previous_input_stat = 0;
@@ -915,7 +971,7 @@

                // SwapRequestInterval

-               nodeConfig.register("swapRequestSendInterval", 2000, 
sortOrder++, true, false,
+               nodeConfig.register("swapRequestSendInterval", 
DEFAULT_SWAP_INTERVAL, sortOrder++, true, false,
                                "Swap request send interval (ms)", "Interval 
between swap attempting to send swap requests in milliseconds. Leave this 
alone!",
                                new IntCallback() {
                                        public int get() {
@@ -1348,7 +1404,7 @@
                "Note that the node will try to automatically restart the node 
in the event of such a deadlock, " +
                "but this will cause some disruption, and may not be 100% 
reliable.";

-       void start(boolean noSwaps) throws NodeInitException {
+       public void start(boolean noSwaps) throws NodeInitException {

                if(!noSwaps)
                        lm.startSender(this, this.swapInterval);
@@ -1402,8 +1458,11 @@
                this.clientCore.start(config);

                // After everything has been created, write the config file 
back to disk.
-               config.finishedInit(this.ps);
-               config.setHasNodeStarted();
+               if(config instanceof FreenetFilePersistentConfig) {
+                       FreenetFilePersistentConfig cfg = 
(FreenetFilePersistentConfig) config;
+                       cfg.finishedInit(this.ps);
+                       cfg.setHasNodeStarted();
+               }
                config.store();

                // Process any data in the extra peer data directory
@@ -1913,7 +1972,7 @@
        public int routedPing(double loc2) {
                long uid = random.nextLong();
                int initialX = random.nextInt();
-               Message m = DMT.createFNPRoutedPing(uid, loc2, MAX_HTL, 
initialX);
+               Message m = DMT.createFNPRoutedPing(uid, loc2, maxHTL, 
initialX);
                Logger.normal(this, "Message: "+m);

                dispatcher.handleRouted(m);
@@ -2238,14 +2297,14 @@
                if(source != null)
                        return source.decrementHTL(htl);
                // Otherwise...
-               if(htl >= MAX_HTL) htl = MAX_HTL;
+               if(htl >= maxHTL) htl = maxHTL;
                if(htl <= 0) htl = 1;
-               if(htl == MAX_HTL) {
-                       if(decrementAtMax) htl--;
+               if(htl == maxHTL) {
+                       if(decrementAtMax && !disableProbabilisticHTLs) htl--;
                        return htl;
                }
                if(htl == 1) {
-                       if(decrementAtMin) htl--;
+                       if(decrementAtMin && !disableProbabilisticHTLs) htl--;
                        return htl;
                }
                return --htl;
@@ -2537,7 +2596,7 @@
                                throw new IllegalArgumentException("Wrong 
hash?? Already have different key with same hash!");
                        }
                        cachedPubKeys.push(w, key);
-                       while(cachedPubKeys.size() > MAX_CACHED_KEYS)
+                       while(cachedPubKeys.size() > MAX_MEMORY_CACHED_PUBKEYS)
                                cachedPubKeys.popKey();
                }
                try {
@@ -3392,4 +3451,19 @@
        public int getUnclaimedFIFOSize() {
                return usm.getUnclaimedFIFOSize();
        }
+
+       /** 
+        * Connect this node to another node (for purposes of testing) 
+        */
+       public void connect(Node node) throws FSParseException, 
PeerParseException, ReferenceSignatureVerificationException {
+               peers.connect(node.exportPublicFieldSet());
+       }
+       
+       public short maxHTL() {
+               return maxHTL;
+       }
+
+       public int getPortNumber() {
+               return portNumber;
+       }
 }

Modified: trunk/freenet/src/freenet/node/NodeClientCore.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeClientCore.java  2006-12-20 23:49:34 UTC 
(rev 11502)
+++ trunk/freenet/src/freenet/node/NodeClientCore.java  2006-12-21 01:52:49 UTC 
(rev 11503)
@@ -282,7 +282,7 @@
                        Logger.error(this, "Could not lock UID just randomly 
generated: "+uid+" - probably indicates broken PRNG");
                        throw new 
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR);
                }
-               Object o = node.makeRequestSender(key.getNodeCHK(), 
Node.MAX_HTL, uid, null, node.getLocation(), false, localOnly, cache, 
ignoreStore);
+               Object o = node.makeRequestSender(key.getNodeCHK(), 
node.maxHTL(), uid, null, node.getLocation(), false, localOnly, cache, 
ignoreStore);
                if(o instanceof CHKBlock) {
                        try {
                                return new ClientCHKBlock((CHKBlock)o, key);
@@ -378,7 +378,7 @@
                        Logger.error(this, "Could not lock UID just randomly 
generated: "+uid+" - probably indicates broken PRNG");
                        throw new 
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR);
                }
-               Object o = node.makeRequestSender(key.getNodeKey(), 
Node.MAX_HTL, uid, null, node.getLocation(), false, localOnly, cache, 
ignoreStore);
+               Object o = node.makeRequestSender(key.getNodeKey(), 
node.maxHTL(), uid, null, node.getLocation(), false, localOnly, cache, 
ignoreStore);
                if(o instanceof SSKBlock) {
                        try {
                                SSKBlock block = (SSKBlock)o;
@@ -491,7 +491,7 @@
                        node.store(block);
                }
                is = node.makeInsertSender((NodeCHK)block.getKey(), 
-                               Node.MAX_HTL, uid, null, headers, prb, false, 
node.getLocation(), cache);
+                               node.maxHTL(), uid, null, headers, prb, false, 
node.getLocation(), cache);
                boolean hasReceivedRejectedOverload = false;
                // Wait for status
                while(true) {
@@ -603,7 +603,7 @@
                        }
                }
                is = node.makeInsertSender(block, 
-                               Node.MAX_HTL, uid, null, false, 
node.getLocation(), false, cache);
+                               node.maxHTL(), uid, null, false, 
node.getLocation(), false, cache);
                boolean hasReceivedRejectedOverload = false;
                // Wait for status
                while(true) {

Modified: trunk/freenet/src/freenet/node/NodeDispatcher.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeDispatcher.java  2006-12-20 23:49:34 UTC 
(rev 11502)
+++ trunk/freenet/src/freenet/node/NodeDispatcher.java  2006-12-21 01:52:49 UTC 
(rev 11503)
@@ -477,7 +477,8 @@

        private boolean innerHandleProbeRequest(PeerNode src, long id, Long 
lid, double target, double best, 
                        double nearest, short htl, short counter, boolean 
checkRecent, boolean canReject, ProbeCallback cb) {
-               if(htl > Node.MAX_HTL) htl = Node.MAX_HTL;
+               short max = node.maxHTL();
+               if(htl > max) htl = max;
                if(htl <= 1) htl = 1;
                ProbeContext ctx = null;
                boolean rejected = false;
@@ -580,9 +581,9 @@

                if(PeerManager.distance(myLoc, target) < 
PeerManager.distance(nearest, target)) {
                        if(logMINOR)
-                               Logger.minor(this, "Updating nearest to 
"+myLoc+" from "+nearest+" for "+target+" and resetting htl from "+htl+" to 
"+Node.MAX_HTL);
+                               Logger.minor(this, "Updating nearest to 
"+myLoc+" from "+nearest+" for "+target+" and resetting htl from "+htl+" to 
"+max);
                        nearest = myLoc;
-                       htl = Node.MAX_HTL;
+                       htl = max;
                        ctx.nearest = nearest;
                        ctx.htl = htl;
                } else {
@@ -724,6 +725,6 @@
                        recentProbeRequestIDs.push(ll);
                }
                double nodeLoc = node.getLocation();
-               innerHandleProbeRequest(null, l, ll, d, (nodeLoc > d) ? nodeLoc 
: 1.0, nodeLoc, Node.MAX_HTL, (short)0, false, false, cb);
+               innerHandleProbeRequest(null, l, ll, d, (nodeLoc > d) ? nodeLoc 
: 1.0, nodeLoc, node.maxHTL(), (short)0, false, false, cb);
        }
 }

Modified: trunk/freenet/src/freenet/node/NodeStarter.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeStarter.java     2006-12-20 23:49:34 UTC 
(rev 11502)
+++ trunk/freenet/src/freenet/node/NodeStarter.java     2006-12-21 01:52:49 UTC 
(rev 11503)
@@ -6,17 +6,21 @@
 import java.io.File;
 import java.io.IOException;

+import org.tanukisoftware.wrapper.WrapperListener;
 import org.tanukisoftware.wrapper.WrapperManager;
-import org.tanukisoftware.wrapper.WrapperListener;

 import freenet.config.FreenetFilePersistentConfig;
 import freenet.config.InvalidConfigValueException;
+import freenet.config.PersistentConfig;
 import freenet.config.SubConfig;
 import freenet.crypt.DiffieHellman;
 import freenet.crypt.RandomSource;
 import freenet.crypt.Yarrow;
 import freenet.node.Node.NodeInitException;
+import freenet.support.FileLoggerHook;
 import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;
+import freenet.support.LoggerHook.InvalidThresholdException;


 /**
@@ -30,7 +34,7 @@
     implements WrapperListener
 {
     private Node node;
-       static LoggingConfigHandler logConfigHandler;
+       private static LoggingConfigHandler logConfigHandler;
        //TODO: cleanup
        public static int RECOMMENDED_EXT_BUILD_NUMBER = 9;
        /*
@@ -85,7 +89,7 @@
        java.security.Security.setProperty("networkaddress.cache.negative.ttl" 
, "0");

        try{
-               cfg = new FreenetFilePersistentConfig(configFilename);  
+               cfg = 
FreenetFilePersistentConfig.constructFreenetFilePersistentConfig(configFilename);
 
        }catch(IOException e){
                System.out.println("Error : "+e);
                e.printStackTrace();
@@ -102,39 +106,9 @@
                e.printStackTrace();
                return new Integer(-2);
        }
+
+       getExtBuild();

-       try{
-               extBuildNumber = ExtVersion.buildNumber;
-                       extRevisionNumber = ExtVersion.cvsRevision;
-                       String builtWithMessage = "freenet.jar built with 
freenet-ext.jar Build #"+extBuildNumber+" r"+extRevisionNumber;
-                       Logger.normal(this, builtWithMessage);
-                       System.out.println(builtWithMessage);
-               extBuildNumber = ExtVersion.buildNumber();
-                       if(extBuildNumber == -42) {
-                               extBuildNumber = ExtVersion.extBuildNumber();
-                               extRevisionNumber = 
ExtVersion.extRevisionNumber();
-                       }
-                       if(extBuildNumber == 0) {
-                               String buildMessage = "extBuildNumber is 0; 
perhaps your freenet-ext.jar file is corrupted?";
-                               Logger.error(this, buildMessage);
-                               System.err.println(buildMessage);
-                               extBuildNumber = -1;
-                       }
-                       if(extRevisionNumber == null) {
-                               String revisionMessage = "extRevisionNumber is 
null; perhaps your freenet-ext.jar file is corrupted?";
-                               Logger.error(this, revisionMessage);
-                               System.err.println(revisionMessage);
-                               extRevisionNumber = "INVALID";
-                       }
-       }catch(Throwable t){     
-               // Compatibility code ... will be removed
-               Logger.error(this, "Unable to get the version of your 
freenet-ext file : it's probably corrupted!");
-               System.err.println("Unable to get the version of your 
freenet-ext file : it's probably corrupted!");
-               System.err.println(t.getMessage());
-               extRevisionNumber = "INVALID";
-               extBuildNumber = -1;
-       }
-       
        // Setup RNG
        RandomSource random = new Yarrow();

@@ -183,7 +157,41 @@
                return null;
     }

-    /**
+    private void getExtBuild() {
+       try{
+               extBuildNumber = ExtVersion.buildNumber;
+                       extRevisionNumber = ExtVersion.cvsRevision;
+                       String builtWithMessage = "freenet.jar built with 
freenet-ext.jar Build #"+extBuildNumber+" r"+extRevisionNumber;
+                       Logger.normal(this, builtWithMessage);
+                       System.out.println(builtWithMessage);
+               extBuildNumber = ExtVersion.buildNumber();
+                       if(extBuildNumber == -42) {
+                               extBuildNumber = ExtVersion.extBuildNumber();
+                               extRevisionNumber = 
ExtVersion.extRevisionNumber();
+                       }
+                       if(extBuildNumber == 0) {
+                               String buildMessage = "extBuildNumber is 0; 
perhaps your freenet-ext.jar file is corrupted?";
+                               Logger.error(this, buildMessage);
+                               System.err.println(buildMessage);
+                               extBuildNumber = -1;
+                       }
+                       if(extRevisionNumber == null) {
+                               String revisionMessage = "extRevisionNumber is 
null; perhaps your freenet-ext.jar file is corrupted?";
+                               Logger.error(this, revisionMessage);
+                               System.err.println(revisionMessage);
+                               extRevisionNumber = "INVALID";
+                       }
+       }catch(Throwable t){     
+               // Compatibility code ... will be removed
+               Logger.error(this, "Unable to get the version of your 
freenet-ext file : it's probably corrupted!");
+               System.err.println("Unable to get the version of your 
freenet-ext file : it's probably corrupted!");
+               System.err.println(t.getMessage());
+               extRevisionNumber = "INVALID";
+               extBuildNumber = -1;
+       }
+       }
+
+       /**
      * Called when the application is shutting down.  The Wrapper assumes that
      *  this method will return fairly quickly.  If the shutdown code code
      *  could potentially take a long time, then 
WrapperManager.signalStopping()
@@ -247,4 +255,106 @@
         //  will be called immediately.
         WrapperManager.start( new NodeStarter(), args );
     }
+
+    /**
+     * VM-specific init.
+     * Not Node-specific; many nodes may be created later.
+     * @param testName The name of the test instance.
+     */
+       public static RandomSource globalTestInit(String testName) throws 
InvalidThresholdException {
+               
+               File dir = new File(testName);
+               if((!dir.mkdir()) && ((!dir.exists()) || (!dir.isDirectory()))) 
{
+                       System.err.println("Cannot create directory for test");
+                       System.exit(Node.EXIT_TEST_ERROR);
+               }
+               
+        FileLoggerHook fh = Logger.setupStdoutLogging(Logger.MINOR, "");
+               
+       // set Java's DNS cache not to cache forever, since many people
+       // use dyndns hostnames
+       java.security.Security.setProperty("networkaddress.cache.ttl" , "0");
+       java.security.Security.setProperty("networkaddress.cache.negative.ttl" 
, "0");
+               
+       // Setup RNG
+       RandomSource random = new Yarrow();
+       
+       DiffieHellman.init(random);
+        
+               // Thread to keep the node up.
+               // JVM deadlocks losing a lock when two threads of different 
types (daemon|app)
+               // are contended for the same lock. So make USM daemon, and use 
useless to keep the JVM
+               // up.
+               // 
http://forum.java.sun.com/thread.jspa?threadID=343023&messageID=2942637 - last 
message
+               Runnable useless =
+                       new Runnable() {
+                       public void run() {
+                               while(true)
+                                       try {
+                                               Thread.sleep(60*60*1000);
+                                       } catch (InterruptedException e) {
+                                               // Ignore
+                                       } catch (Throwable t) {
+                                               try {
+                                                       Logger.error(this, 
"Caught "+t, t);
+                                               } catch (Throwable t1) {
+                                                       // Ignore
+                                               }
+                                       }
+                       }
+               };
+               Thread plug = new Thread(useless, "Plug");
+               // Not daemon, but doesn't do anything.
+               // Keeps the JVM alive.
+               // DO NOT do anything in the plug thread, if you do you risk 
the EvilJVMBug.
+               plug.setDaemon(false);
+               plug.start();
+               
+               return random;
+       }
+       
+       /**
+        * Create a test node.
+        * @param port The node port number. Each test node must have a 
different port
+        * number.
+        * @param testName The test name.
+        * @param doClient Boot up the client layer?
+        * @param doSwapping Allow swapping?
+        * @throws NodeInitException If the node cannot start up for some 
reason, most
+        * likely a config problem.
+        */
+       public static Node createTestNode(int port, String testName, boolean 
doClient, 
+                       boolean doSwapping, boolean disableProbabilisticHTLs, 
short maxHTL,
+                       int dropProb, int swapInterval, RandomSource random) 
throws NodeInitException {
+               
+               File baseDir = new File(testName);
+               File portDir = new File(baseDir, Integer.toString(port));
+               if((!portDir.mkdir()) && ((!portDir.exists()) || 
(!portDir.isDirectory()))) {
+                       System.err.println("Cannot create directory for test");
+                       System.exit(Node.EXIT_TEST_ERROR);
+               }
+               
+               // Set up config for testing
+               SimpleFieldSet configFS = new SimpleFieldSet();
+               configFS.put("node.listenPort", port);
+               configFS.put("node.disableProbabilisticHTLs", 
disableProbabilisticHTLs);
+               configFS.put("fproxy.enabled", false);
+               configFS.put("fcp.enabled", false);
+               configFS.put("console.enabled", false);
+               configFS.put("pluginmanager.loadplugin", "");
+               configFS.put("node.updater.enabled", false);
+               configFS.put("node.tempDir", new File(portDir, 
"temp").toString());
+               configFS.put("node.storeDir", new File(portDir, 
"store").toString());
+               configFS.put("node.persistentTempDir", new File(portDir, 
"persistent").toString());
+               configFS.put("node.throttleFile", new File(portDir, 
"throttle.dat").toString());
+               configFS.put("node.nodeDir", portDir.toString());
+               configFS.put("node.maxHTL", maxHTL);
+               configFS.put("node.testingDropPacketsEvery", dropProb);
+               configFS.put("node.swapRequestSendInterval", swapInterval);
+               
+               PersistentConfig config = new PersistentConfig(configFS);
+               
+               return new Node(config, random, null, null);
+       }
+       
 }

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2006-12-20 23:49:34 UTC 
(rev 11502)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2006-12-21 01:52:49 UTC 
(rev 11503)
@@ -90,11 +90,6 @@
      */
     private boolean verifiedIncompatibleNewerVersion;

-    /** For debugging/testing, set this to true to stop the
-     * probabilistic decrement at the edges of the HTLs.
-     */
-    static boolean disableProbabilisticHTLs;
-
     /** My low-level address for SocketManager purposes */
     private Peer detectedPeer;

@@ -1219,14 +1214,15 @@
      * @return The new HTL.
      */
     public short decrementHTL(short htl) {
-        if(htl > Node.MAX_HTL) htl = Node.MAX_HTL;
+       short max = node.maxHTL();
+        if(htl > max) htl = max;
         if(htl <= 0) htl = 1;
-        if(htl == Node.MAX_HTL) {
-            if(decrementHTLAtMaximum) htl--;
+        if(htl == max) {
+            if(decrementHTLAtMaximum && !node.disableProbabilisticHTLs) htl--;
             return htl;
         }
         if(htl == 1) {
-            if(decrementHTLAtMinimum) htl--;
+            if(decrementHTLAtMinimum && !node.disableProbabilisticHTLs) htl--;
             return htl;
         }
         htl--;

Deleted: trunk/freenet/src/freenet/node/RealNodePingTest.java
===================================================================
--- trunk/freenet/src/freenet/node/RealNodePingTest.java        2006-12-20 
23:49:34 UTC (rev 11502)
+++ trunk/freenet/src/freenet/node/RealNodePingTest.java        2006-12-21 
01:52:49 UTC (rev 11503)
@@ -1,67 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.node;
-
-import freenet.crypt.DiffieHellman;
-import freenet.crypt.Yarrow;
-import freenet.io.comm.NotConnectedException;
-import freenet.io.comm.PeerParseException;
-import freenet.support.FileLoggerHook;
-import freenet.support.Logger;
-import freenet.support.SimpleFieldSet;
-
-/**
- * @author amphibian
- * 
- * When the code is invoked via this class, it:
- * - Creates two nodes.
- * - Connects them to each other
- * - Sends pings from the first node to the second node.
- * - Prints on the logger when packets are sent, when they are
- *   received, (by both sides), and their sequence numbers.
- */
-public class RealNodePingTest {
-
-    public static void main(String[] args) throws FSParseException, 
PeerParseException, InterruptedException {
-        FileLoggerHook fh = Logger.setupStdoutLogging(Logger.MINOR, "");
-        Yarrow yarrow = new Yarrow();
-        DiffieHellman.init(yarrow);
-        // Create 2 nodes
-        Node node1 = new Node(5001, yarrow, null, "pingtest-", 0, false, fh, 
0);
-        Node node2 = new Node(5002, yarrow, null, "pingtest-", 0, false, fh, 
0);
-        SimpleFieldSet node1ref = node1.exportPublicFieldSet();
-        SimpleFieldSet node2ref = node2.exportPublicFieldSet();
-        // Connect
-        node1.peers.connect(node2ref);
-        node2.peers.connect(node1ref);
-        // No swapping
-        node1.start(null);
-        node2.start(null);
-        // Ping
-        PeerNode pn = node1.peers.myPeers[0];
-        int pingID = 0;
-        Thread.sleep(20000);
-        //node1.usm.setDropProbability(4);
-        while(true) {
-            Logger.minor(RealNodePingTest.class, "Sending PING "+pingID);
-            boolean success;
-            try {
-                success = pn.ping(pingID);
-            } catch (NotConnectedException e1) {
-                Logger.normal(RealNodePingTest.class, "Not connected");
-                continue;
-            }
-            if(success)
-                Logger.normal(RealNodePingTest.class, "PING "+pingID+" 
successful");
-            else
-                Logger.normal(RealNodePingTest.class, "PING FAILED: "+pingID);
-            try {
-                Thread.sleep(2000);
-            } catch (InterruptedException e) {
-                // Shouldn't happen
-            }
-            pingID++;
-        }
-    }
-}

Deleted: trunk/freenet/src/freenet/node/RealNodeRequestInsertTest.java
===================================================================
--- trunk/freenet/src/freenet/node/RealNodeRequestInsertTest.java       
2006-12-20 23:49:34 UTC (rev 11502)
+++ trunk/freenet/src/freenet/node/RealNodeRequestInsertTest.java       
2006-12-21 01:52:49 UTC (rev 11503)
@@ -1,211 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.node;
-
-import java.io.File;
-import java.util.Arrays;
-
-import freenet.crypt.DiffieHellman;
-import freenet.crypt.DummyRandomSource;
-import freenet.io.comm.PeerParseException;
-import freenet.keys.CHKEncodeException;
-import freenet.keys.ClientCHK;
-import freenet.keys.ClientCHKBlock;
-import freenet.keys.ClientKey;
-import freenet.node.PeerNode;
-import freenet.support.Fields;
-import freenet.support.FileLoggerHook;
-import freenet.support.HexUtil;
-import freenet.support.Logger;
-import freenet.support.SimpleFieldSet;
-import freenet.support.math.BootstrappingDecayingRunningAverage;
-import freenet.support.math.RunningAverage;
-import freenet.support.math.SimpleRunningAverage;
-
-/**
- * @author amphibian
- */
-public class RealNodeRequestInsertTest {
-
-    static final int NUMBER_OF_NODES = 10;
-    
-    public static void main(String[] args) throws FSParseException, 
PeerParseException, CHKEncodeException {
-        PeerNode.disableProbabilisticHTLs = true;
-        String wd = "realNodeRequestInsertTest";
-        new File(wd).mkdir();
-        // Don't clobber nearby nodes!
-        Node.MAX_HTL = 5;
-        FileLoggerHook fh = Logger.setupStdoutLogging(Logger.DEBUG, 
"freenet.store:minor,freenet.node.Location:normal" 
/*"freenet.node.LocationManager:debug,freenet.node.FNPPacketManager:normal,freenet.io.comm.UdpSocketManager:debug"*/);
-        Logger.globalSetThreshold(Logger.DEBUG);
-        System.out.println("Insert/retrieve test");
-        System.out.println();
-        DummyRandomSource random = new DummyRandomSource();
-        DiffieHellman.init(random);
-        Node[] nodes = new Node[NUMBER_OF_NODES];
-        Logger.normal(RealNodeRoutingTest.class, "Creating nodes...");
-        for(int i=0;i<NUMBER_OF_NODES;i++) {
-            nodes[i] = new Node(5000+i, random, null, wd+File.separator, 0, 
false, fh, 100);
-            nodes[i].usm.setDropProbability(20); // 5%
-            Logger.normal(RealNodeRoutingTest.class, "Created node "+i);
-        }
-        SimpleFieldSet refs[] = new SimpleFieldSet[NUMBER_OF_NODES];
-        for(int i=0;i<NUMBER_OF_NODES;i++)
-            refs[i] = nodes[i].exportPublicFieldSet();
-        Logger.normal(RealNodeRoutingTest.class, "Created "+NUMBER_OF_NODES+" 
nodes");
-        // Now link them up
-        // Connect the set
-        for(int i=0;i<NUMBER_OF_NODES;i++) {
-            int next = (i+1) % NUMBER_OF_NODES;
-            int prev = (i+NUMBER_OF_NODES-1)%NUMBER_OF_NODES;
-            nodes[i].peers.connect(refs[next]);
-            nodes[i].peers.connect(refs[prev]);
-        }
-        Logger.normal(RealNodeRoutingTest.class, "Connected nodes");
-        // Now add some random links
-        for(int i=0;i<NUMBER_OF_NODES*5;i++) {
-            if(i % NUMBER_OF_NODES == 0)
-                Logger.normal(RealNodeRoutingTest.class, ""+i);
-            int length = (int)Math.pow(NUMBER_OF_NODES, random.nextDouble());
-            int nodeA = random.nextInt(NUMBER_OF_NODES);
-            int nodeB = (nodeA+length)%NUMBER_OF_NODES;
-            //System.out.println(""+nodeA+" -> "+nodeB);
-            Node a = nodes[nodeA];
-            Node b = nodes[nodeB];
-            a.peers.connect(b.exportPublicFieldSet());
-            b.peers.connect(a.exportPublicFieldSet());
-        }
-        
-        Logger.normal(RealNodeRoutingTest.class, "Added random links");
-        
-        SwapRequestInterval sri =
-            new 
CPUAdjustingSwapRequestInterval(((500*1000*NUMBER_OF_NODES)/200), 50);
-        
-        for(int i=0;i<NUMBER_OF_NODES;i++)
-            nodes[i].start(sri);
-        
-        // Now sit back and watch the fireworks!
-        int cycleNumber = 0;
-        int lastSwaps = 0;
-        int lastNoSwaps = 0;
-        int failures = 0;
-        int successes = 0;
-        RunningAverage avg = new SimpleRunningAverage(100, 0.0);
-        RunningAverage avg2 = new BootstrappingDecayingRunningAverage(0.0, 
0.0, 1.0, 100);
-        int pings = 0;
-        while(true) {
-            cycleNumber++;
-            try {
-                Thread.sleep(5000);
-            } catch (InterruptedException e) {
-                // Ignore
-            }
-            for(int i=0;i<NUMBER_OF_NODES;i++) {
-                Logger.normal(RealNodeRoutingTest.class, "Cycle 
"+cycleNumber+" node "+i+": "+nodes[i].lm.getLocation().getValue());
-            }
-            int newSwaps = LocationManager.swaps;
-            int totalStarted = LocationManager.startedSwaps;
-            int noSwaps = LocationManager.noSwaps;
-            Logger.normal(RealNodeRoutingTest.class, "Swaps: 
"+(newSwaps-lastSwaps));
-            Logger.normal(RealNodeRoutingTest.class, "\nTotal swaps: 
Started*2: "+totalStarted*2+", succeeded: "+newSwaps+", last minute failures: 
"+noSwaps+
-                    ", ratio "+(double)noSwaps/(double)newSwaps+", early 
failures: "+((totalStarted*2)-(noSwaps+newSwaps)));
-            Logger.normal(RealNodeRoutingTest.class, "This cycle ratio: 
"+((double)(noSwaps-lastNoSwaps)) / ((double)(newSwaps - lastSwaps)));
-            lastNoSwaps = noSwaps;
-            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (already 
locked): "+LocationManager.swapsRejectedAlreadyLocked);
-            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (nowhere 
to go): "+LocationManager.swapsRejectedNowhereToGo);
-            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (rate 
limit): "+LocationManager.swapsRejectedRateLimit);
-            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (loop): 
"+LocationManager.swapsRejectedLoop);
-            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected 
(recognized ID):" +LocationManager.swapsRejectedRecognizedID);
-            lastSwaps = newSwaps;
-            // Do some (routed) test-pings
-            for(int i=0;i<10;i++) {
-                try {
-                    Thread.sleep(2000);
-                } catch (InterruptedException e1) {
-                }
-                try {
-                Node randomNode = nodes[random.nextInt(NUMBER_OF_NODES)];
-                Node randomNode2 = randomNode;
-                while(randomNode2 == randomNode)
-                    randomNode2 = nodes[random.nextInt(NUMBER_OF_NODES)];
-                Logger.normal(RealNodeRoutingTest.class, "Pinging 
"+randomNode2.portNumber+" from "+randomNode.portNumber);
-                double loc2 = randomNode2.lm.getLocation().getValue();
-                int hopsTaken = randomNode.routedPing(loc2);
-                pings++;
-                if(hopsTaken < 0) {
-                    failures++;
-                    avg.report(0.0);
-                    avg2.report(0.0);
-                    double ratio = (double)successes / 
((double)(failures+successes));
-                    Logger.normal(RealNodeRoutingTest.class, "Routed ping 
"+pings+" FAILED from "+randomNode.portNumber+" to "+randomNode2.portNumber+" 
(long:"+ratio+", short:"+avg.currentValue()+", vague:"+avg2.currentValue()+ 
')');
-                } else {
-                    successes++;
-                    avg.report(1.0);
-                    avg2.report(1.0);
-                    double ratio = (double)successes / 
((double)(failures+successes));
-                    Logger.normal(RealNodeRoutingTest.class, "Routed ping 
"+pings+" success: "+hopsTaken+ ' ' +randomNode.portNumber+" to 
"+randomNode2.portNumber+" (long:"+ratio+", short:"+avg.currentValue()+", 
vague:"+avg2.currentValue()+ ')');
-                }
-                } catch (Throwable t) {
-                    Logger.error(RealNodeRoutingTest.class, "Caught "+t, t);
-                }
-            }
-            if(pings > 10 && avg.currentValue() > 0.98 && ((double)successes / 
((double)(failures+successes)) > 0.98)) {
-                break;
-            }
-        }
-        System.out.println();
-        System.out.println("Ping average > 98%, lets do some 
inserts/requests");
-        System.out.println();
-        int requestNumber = 0;
-        RunningAverage requestsAvg = new SimpleRunningAverage(100, 0.0);
-        String baseString = System.currentTimeMillis() + ' ';
-        while(true) {
-            try {
-                requestNumber++;
-                try {
-                    Thread.sleep(5000);
-                } catch (InterruptedException e1) {
-                }
-                String dataString = baseString + requestNumber;
-                // Pick random node to insert to
-                int node1 = random.nextInt(NUMBER_OF_NODES);
-                Node randomNode = nodes[node1];
-                Logger.error(RealNodeRequestInsertTest.class,"Inserting: 
\""+dataString+"\" to "+node1);
-                byte[] data = dataString.getBytes();
-                ClientCHKBlock block;
-                block = ClientCHKBlock.encode(data, false, false, (short)-1, 
0);
-                ClientCHK chk = (ClientCHK) block.getClientKey();
-                byte[] encData = block.getData();
-                byte[] encHeaders = block.getHeaders();
-                ClientCHKBlock newBlock = new ClientCHKBlock(encData, 
encHeaders, chk, true);
-                Logger.error(RealNodeRequestInsertTest.class, "Decoded: "+new 
String(newBlock.memoryDecode()));
-                Logger.error(RealNodeRequestInsertTest.class,"CHK: 
"+chk.getURI());
-                Logger.error(RealNodeRequestInsertTest.class,"Headers: 
"+HexUtil.bytesToHex(block.getHeaders()));
-                randomNode.realPut(block, true);
-                Logger.error(RealNodeRequestInsertTest.class, "Inserted to 
"+node1);
-                Logger.error(RealNodeRequestInsertTest.class, "Data: 
"+Fields.hashCode(encData)+", Headers: "+Fields.hashCode(encHeaders));
-                // Pick random node to request from
-                int node2;
-                do {
-                    node2 = random.nextInt(NUMBER_OF_NODES);
-                } while(node2 == node1);
-                Node fetchNode = nodes[node2];
-                block = (ClientCHKBlock) fetchNode.realGetKey((ClientKey) chk, 
false, true, false);
-                if(block == null) {
-                    Logger.error(RealNodeRequestInsertTest.class, "Fetch 
FAILED from "+node2);
-                    requestsAvg.report(0.0);
-                } else {
-                    byte[] results = block.memoryDecode();
-                    requestsAvg.report(1.0);
-                    if(Arrays.equals(results, data)) {
-                        Logger.error(RealNodeRequestInsertTest.class, "Fetch 
succeeded: "+new String(results));
-                    } else {
-                        Logger.error(RealNodeRequestInsertTest.class, 
"Returned invalid data!: "+new String(results));
-                    }
-                }
-            } catch (Throwable t) {
-                Logger.error(RealNodeRequestInsertTest.class, "Caught "+t, t);
-            }
-        }
-    }
-}

Deleted: trunk/freenet/src/freenet/node/RealNodeRoutingTest.java
===================================================================
--- trunk/freenet/src/freenet/node/RealNodeRoutingTest.java     2006-12-20 
23:49:34 UTC (rev 11502)
+++ trunk/freenet/src/freenet/node/RealNodeRoutingTest.java     2006-12-21 
01:52:49 UTC (rev 11503)
@@ -1,147 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.node;
-
-import java.io.File;
-
-import freenet.crypt.DiffieHellman;
-import freenet.crypt.DummyRandomSource;
-import freenet.io.comm.PeerParseException;
-import freenet.support.FileLoggerHook;
-import freenet.support.Logger;
-import freenet.support.SimpleFieldSet;
-import freenet.support.math.BootstrappingDecayingRunningAverage;
-import freenet.support.math.RunningAverage;
-import freenet.support.math.SimpleRunningAverage;
-
-/**
- * @author amphibian
- * 
- * Create a mesh of nodes and let them sort out their locations.
- * 
- * Then run some node-to-node searches.
- */
-public class RealNodeRoutingTest {
-
-    static final int NUMBER_OF_NODES = 150;
-    
-    public static void main(String[] args) throws FSParseException, 
PeerParseException {
-        PeerNode.disableProbabilisticHTLs = true;
-        Node.MAX_HTL = 6;
-        FileLoggerHook fh = Logger.setupStdoutLogging(Logger.NORMAL, 
"freenet.node.CPUAdjustingSwapRequestInterval:minor" 
/*"freenet.node.LocationManager:debug,freenet.node.FNPPacketManager:normal,freenet.io.comm.UdpSocketManager:debug"*/);
-        System.out.println("Routing test using real nodes:");
-        System.out.println();
-        String wd = "realNodeRequestInsertTest";
-        new File(wd).mkdir();
-        DummyRandomSource random = new DummyRandomSource();
-        DiffieHellman.init(random);
-        Node[] nodes = new Node[NUMBER_OF_NODES];
-        Logger.normal(RealNodeRoutingTest.class, "Creating nodes...");
-        for(int i=0;i<NUMBER_OF_NODES;i++) {
-            nodes[i] = new Node(5000+i, random, null, wd+File.separator, 0, 
false, fh, 0);
-            Logger.normal(RealNodeRoutingTest.class, "Created node "+i);
-        }
-        SimpleFieldSet refs[] = new SimpleFieldSet[NUMBER_OF_NODES];
-        for(int i=0;i<NUMBER_OF_NODES;i++)
-            refs[i] = nodes[i].exportPublicFieldSet();
-        Logger.normal(RealNodeRoutingTest.class, "Created "+NUMBER_OF_NODES+" 
nodes");
-        // Now link them up
-        // Connect the set
-        for(int i=0;i<NUMBER_OF_NODES;i++) {
-            int next = (i+1) % NUMBER_OF_NODES;
-            int prev = (i+NUMBER_OF_NODES-1)%NUMBER_OF_NODES;
-            nodes[i].peers.connect(refs[next]);
-            nodes[i].peers.connect(refs[prev]);
-        }
-        Logger.normal(RealNodeRoutingTest.class, "Connected nodes");
-        // Now add some random links
-        for(int i=0;i<NUMBER_OF_NODES*5;i++) {
-            if(i % NUMBER_OF_NODES == 0)
-                Logger.normal(RealNodeRoutingTest.class, ""+i);
-            int length = (int)Math.pow(NUMBER_OF_NODES, random.nextDouble());
-            int nodeA = random.nextInt(NUMBER_OF_NODES);
-            int nodeB = (nodeA+length)%NUMBER_OF_NODES;
-            //System.out.println(""+nodeA+" -> "+nodeB);
-            Node a = nodes[nodeA];
-            Node b = nodes[nodeB];
-            a.peers.connect(b.exportPublicFieldSet());
-            b.peers.connect(a.exportPublicFieldSet());
-        }
-
-        Logger.normal(RealNodeRoutingTest.class, "Added random links");
-        
-        SwapRequestInterval sri =
-            new 
CPUAdjustingSwapRequestInterval(((500*1000*NUMBER_OF_NODES)/200), 50);
-        
-        for(int i=0;i<NUMBER_OF_NODES;i++)
-            nodes[i].start(sri);
-        
-        // Now sit back and watch the fireworks!
-        int cycleNumber = 0;
-        int lastSwaps = 0;
-        int lastNoSwaps = 0;
-        int failures = 0;
-        int successes = 0;
-        RunningAverage avg = new SimpleRunningAverage(100, 0.0);
-        RunningAverage avg2 = new BootstrappingDecayingRunningAverage(0.0, 
0.0, 1.0, 100);
-        int pings = 0;
-        while(true) {
-            cycleNumber++;
-            try {
-                Thread.sleep(5000);
-            } catch (InterruptedException e) {
-                // Ignore
-            }
-            for(int i=0;i<NUMBER_OF_NODES;i++) {
-                Logger.normal(RealNodeRoutingTest.class, "Cycle 
"+cycleNumber+" node "+i+": "+nodes[i].lm.getLocation().getValue());
-            }
-            int newSwaps = LocationManager.swaps;
-            int totalStarted = LocationManager.startedSwaps;
-            int noSwaps = LocationManager.noSwaps;
-            Logger.normal(RealNodeRoutingTest.class, "Swaps: 
"+(newSwaps-lastSwaps));
-            Logger.normal(RealNodeRoutingTest.class, "\nTotal swaps: 
Started*2: "+totalStarted*2+", succeeded: "+newSwaps+", last minute failures: 
"+noSwaps+
-                    ", ratio "+(double)noSwaps/(double)newSwaps+", early 
failures: "+((totalStarted*2)-(noSwaps+newSwaps)));
-            Logger.normal(RealNodeRoutingTest.class, "This cycle ratio: 
"+((double)(noSwaps-lastNoSwaps)) / ((double)(newSwaps - lastSwaps)));
-            lastNoSwaps = noSwaps;
-            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (already 
locked): "+LocationManager.swapsRejectedAlreadyLocked);
-            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (nowhere 
to go): "+LocationManager.swapsRejectedNowhereToGo);
-            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (rate 
limit): "+LocationManager.swapsRejectedRateLimit);
-            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (loop): 
"+LocationManager.swapsRejectedLoop);
-            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected 
(recognized ID):" +LocationManager.swapsRejectedRecognizedID);
-            lastSwaps = newSwaps;
-            // Do some (routed) test-pings
-            for(int i=0;i<10;i++) {
-                try {
-                    Thread.sleep(5000);
-                } catch (InterruptedException e1) {
-                }
-                try {
-                Node randomNode = nodes[random.nextInt(NUMBER_OF_NODES)];
-                Node randomNode2 = randomNode;
-                while(randomNode2 == randomNode)
-                    randomNode2 = nodes[random.nextInt(NUMBER_OF_NODES)];
-                Logger.normal(RealNodeRoutingTest.class, "Pinging 
"+randomNode2.portNumber+" from "+randomNode.portNumber);
-                double loc2 = randomNode2.lm.getLocation().getValue();
-                int hopsTaken = randomNode.routedPing(loc2);
-                pings++;
-                if(hopsTaken < 0) {
-                    failures++;
-                    avg.report(0.0);
-                    avg2.report(0.0);
-                    double ratio = (double)successes / 
((double)(failures+successes));
-                    Logger.normal(RealNodeRoutingTest.class, "Routed ping 
"+pings+" FAILED from "+randomNode.portNumber+" to "+randomNode2.portNumber+" 
(long:"+ratio+", short:"+avg.currentValue()+", vague:"+avg2.currentValue()+ 
')');
-                } else {
-                    successes++;
-                    avg.report(1.0);
-                    avg2.report(1.0);
-                    double ratio = (double)successes / 
((double)(failures+successes));
-                    Logger.normal(RealNodeRoutingTest.class, "Routed ping 
"+pings+" success: "+hopsTaken+ ' ' +randomNode.portNumber+" to 
"+randomNode2.portNumber+" (long:"+ratio+", short:"+avg.currentValue()+", 
vague:"+avg2.currentValue()+ ')');
-                }
-                } catch (Throwable t) {
-                    Logger.error(RealNodeRoutingTest.class, "Caught "+t, t);
-                }
-            }
-        }
-    }
-}

Modified: trunk/freenet/src/freenet/node/RequestHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestHandler.java  2006-12-20 23:49:34 UTC 
(rev 11502)
+++ trunk/freenet/src/freenet/node/RequestHandler.java  2006-12-21 01:52:49 UTC 
(rev 11503)
@@ -51,7 +51,7 @@
         double keyLoc = key.toNormalizedDouble();
         if(PeerManager.distance(keyLoc, myLoc) < PeerManager.distance(keyLoc, 
closestLoc)) {
             closestLoc = myLoc;
-            htl = Node.MAX_HTL;
+            htl = node.maxHTL();
             resetClosestLoc = true;
         } else
                resetClosestLoc = false;

Modified: trunk/freenet/src/freenet/node/SSKInsertHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/SSKInsertHandler.java        2006-12-20 
23:49:34 UTC (rev 11502)
+++ trunk/freenet/src/freenet/node/SSKInsertHandler.java        2006-12-21 
01:52:49 UTC (rev 11503)
@@ -56,7 +56,7 @@
         double myLoc = node.lm.getLocation().getValue();
         if(PeerManager.distance(targetLoc, myLoc) < 
PeerManager.distance(targetLoc, closestLoc)) {
             closestLoc = myLoc;
-            htl = Node.MAX_HTL;
+            htl = node.maxHTL();
             resetClosestLoc = true;
         } else resetClosestLoc = false;
         byte[] pubKeyHash = 
((ShortBuffer)req.getObject(DMT.PUBKEY_HASH)).getData();

Copied: trunk/freenet/src/freenet/node/simulator/RealNodePingTest.java (from 
rev 11497, trunk/freenet/src/freenet/node/RealNodePingTest.java)
===================================================================
--- trunk/freenet/src/freenet/node/simulator/RealNodePingTest.java              
                (rev 0)
+++ trunk/freenet/src/freenet/node/simulator/RealNodePingTest.java      
2006-12-21 01:52:49 UTC (rev 11503)
@@ -0,0 +1,66 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.node.simulator;
+
+import freenet.crypt.RandomSource;
+import freenet.io.comm.NotConnectedException;
+import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
+import freenet.node.FSParseException;
+import freenet.node.Node;
+import freenet.node.NodeStarter;
+import freenet.node.PeerNode;
+import freenet.support.Logger;
+import freenet.support.LoggerHook.InvalidThresholdException;
+
+/**
+ * @author amphibian
+ * 
+ * When the code is invoked via this class, it:
+ * - Creates two nodes.
+ * - Connects them to each other
+ * - Sends pings from the first node to the second node.
+ * - Prints on the logger when packets are sent, when they are
+ *   received, (by both sides), and their sequence numbers.
+ */
+public class RealNodePingTest {
+
+    public static void main(String[] args) throws FSParseException, 
PeerParseException, InterruptedException, 
ReferenceSignatureVerificationException, Node.NodeInitException, 
InvalidThresholdException {
+        RandomSource random = NodeStarter.globalTestInit("pingtest");
+        // Create 2 nodes
+        Node node1 = NodeStarter.createTestNode(5001, "pingtest", false, 
false, true, Node.DEFAULT_MAX_HTL, 0, Node.DEFAULT_SWAP_INTERVAL, random);
+        Node node2 = NodeStarter.createTestNode(5002, "pingtest", false, 
false, true, Node.DEFAULT_MAX_HTL, 0, Node.DEFAULT_SWAP_INTERVAL, random);
+        // Connect
+        node1.connect(node2);
+        node2.connect(node1);
+        // No swapping
+        node1.start(true);
+        node2.start(true);
+        // Ping
+        PeerNode pn = node1.getPeerNodes()[0];
+        int pingID = 0;
+        Thread.sleep(20000);
+        //node1.usm.setDropProbability(4);
+        while(true) {
+            Logger.minor(RealNodePingTest.class, "Sending PING "+pingID);
+            boolean success;
+            try {
+                success = pn.ping(pingID);
+            } catch (NotConnectedException e1) {
+                Logger.normal(RealNodePingTest.class, "Not connected");
+                continue;
+            }
+            if(success)
+                Logger.normal(RealNodePingTest.class, "PING "+pingID+" 
successful");
+            else
+                Logger.normal(RealNodePingTest.class, "PING FAILED: "+pingID);
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                // Shouldn't happen
+            }
+            pingID++;
+        }
+    }
+}


Property changes on: 
trunk/freenet/src/freenet/node/simulator/RealNodePingTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Copied: trunk/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java 
(from rev 11497, trunk/freenet/src/freenet/node/RealNodeRequestInsertTest.java)
===================================================================
--- trunk/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java     
                        (rev 0)
+++ trunk/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java     
2006-12-21 01:52:49 UTC (rev 11503)
@@ -0,0 +1,213 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.node.simulator;
+
+import java.io.File;
+import java.util.Arrays;
+
+import freenet.crypt.DiffieHellman;
+import freenet.crypt.DummyRandomSource;
+import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
+import freenet.keys.CHKEncodeException;
+import freenet.keys.ClientCHK;
+import freenet.keys.ClientCHKBlock;
+import freenet.keys.ClientKey;
+import freenet.node.FSParseException;
+import freenet.node.LocationManager;
+import freenet.node.Node;
+import freenet.node.NodeStarter;
+import freenet.node.Node.NodeInitException;
+import freenet.support.Fields;
+import freenet.support.HexUtil;
+import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;
+import freenet.support.LoggerHook.InvalidThresholdException;
+import freenet.support.math.BootstrappingDecayingRunningAverage;
+import freenet.support.math.RunningAverage;
+import freenet.support.math.SimpleRunningAverage;
+
+/**
+ * @author amphibian
+ */
+public class RealNodeRequestInsertTest {
+
+    static final int NUMBER_OF_NODES = 10;
+    static final short MAX_HTL = 5;
+    
+    public static void main(String[] args) throws FSParseException, 
PeerParseException, CHKEncodeException, InvalidThresholdException, 
NodeInitException, ReferenceSignatureVerificationException {
+        String wd = "realNodeRequestInsertTest";
+        new File(wd).mkdir();
+        NodeStarter.globalTestInit(wd); // ignore Random, using our own
+        // Don't clobber nearby nodes!
+        Logger.setupStdoutLogging(Logger.DEBUG, 
"freenet.store:minor,freenet.node.Location:normal" 
/*"freenet.node.LocationManager:debug,freenet.node.FNPPacketManager:normal,freenet.io.comm.UdpSocketManager:debug"*/);
+        Logger.globalSetThreshold(Logger.DEBUG);
+        System.out.println("Insert/retrieve test");
+        System.out.println();
+        DummyRandomSource random = new DummyRandomSource();
+        DiffieHellman.init(random);
+        Node[] nodes = new Node[NUMBER_OF_NODES];
+        Logger.normal(RealNodeRoutingTest.class, "Creating nodes...");
+        for(int i=0;i<NUMBER_OF_NODES;i++) {
+            nodes[i] = 
+               NodeStarter.createTestNode(5001+i, wd, false, true, true, 
MAX_HTL, 20 /* 5% */, Node.DEFAULT_SWAP_INTERVAL, random);
+            Logger.normal(RealNodeRoutingTest.class, "Created node "+i);
+        }
+        SimpleFieldSet refs[] = new SimpleFieldSet[NUMBER_OF_NODES];
+        for(int i=0;i<NUMBER_OF_NODES;i++)
+            refs[i] = nodes[i].exportPublicFieldSet();
+        Logger.normal(RealNodeRoutingTest.class, "Created "+NUMBER_OF_NODES+" 
nodes");
+        // Now link them up
+        // Connect the set
+        for(int i=0;i<NUMBER_OF_NODES;i++) {
+            int next = (i+1) % NUMBER_OF_NODES;
+            int prev = (i+NUMBER_OF_NODES-1)%NUMBER_OF_NODES;
+            nodes[i].connect(nodes[next]);
+            nodes[i].connect(nodes[prev]);
+        }
+        Logger.normal(RealNodeRoutingTest.class, "Connected nodes");
+        // Now add some random links
+        for(int i=0;i<NUMBER_OF_NODES*5;i++) {
+            if(i % NUMBER_OF_NODES == 0)
+                Logger.normal(RealNodeRoutingTest.class, ""+i);
+            int length = (int)Math.pow(NUMBER_OF_NODES, random.nextDouble());
+            int nodeA = random.nextInt(NUMBER_OF_NODES);
+            int nodeB = (nodeA+length)%NUMBER_OF_NODES;
+            //System.out.println(""+nodeA+" -> "+nodeB);
+            Node a = nodes[nodeA];
+            Node b = nodes[nodeB];
+            a.connect(b);
+            b.connect(a);
+        }
+        
+        Logger.normal(RealNodeRoutingTest.class, "Added random links");
+        
+        for(int i=0;i<NUMBER_OF_NODES;i++)
+            nodes[i].start(false);
+        
+        // Now sit back and watch the fireworks!
+        int cycleNumber = 0;
+        int lastSwaps = 0;
+        int lastNoSwaps = 0;
+        int failures = 0;
+        int successes = 0;
+        RunningAverage avg = new SimpleRunningAverage(100, 0.0);
+        RunningAverage avg2 = new BootstrappingDecayingRunningAverage(0.0, 
0.0, 1.0, 100, null);
+        int pings = 0;
+        while(true) {
+            cycleNumber++;
+            try {
+                Thread.sleep(5000);
+            } catch (InterruptedException e) {
+                // Ignore
+            }
+            for(int i=0;i<NUMBER_OF_NODES;i++) {
+                Logger.normal(RealNodeRoutingTest.class, "Cycle 
"+cycleNumber+" node "+i+": "+nodes[i].getLocation());
+            }
+            int newSwaps = LocationManager.swaps;
+            int totalStarted = LocationManager.startedSwaps;
+            int noSwaps = LocationManager.noSwaps;
+            Logger.normal(RealNodeRoutingTest.class, "Swaps: 
"+(newSwaps-lastSwaps));
+            Logger.normal(RealNodeRoutingTest.class, "\nTotal swaps: 
Started*2: "+totalStarted*2+", succeeded: "+newSwaps+", last minute failures: 
"+noSwaps+
+                    ", ratio "+(double)noSwaps/(double)newSwaps+", early 
failures: "+((totalStarted*2)-(noSwaps+newSwaps)));
+            Logger.normal(RealNodeRoutingTest.class, "This cycle ratio: 
"+((double)(noSwaps-lastNoSwaps)) / ((double)(newSwaps - lastSwaps)));
+            lastNoSwaps = noSwaps;
+            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (already 
locked): "+LocationManager.swapsRejectedAlreadyLocked);
+            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (nowhere 
to go): "+LocationManager.swapsRejectedNowhereToGo);
+            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (rate 
limit): "+LocationManager.swapsRejectedRateLimit);
+            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (loop): 
"+LocationManager.swapsRejectedLoop);
+            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected 
(recognized ID):" +LocationManager.swapsRejectedRecognizedID);
+            lastSwaps = newSwaps;
+            // Do some (routed) test-pings
+            for(int i=0;i<10;i++) {
+                try {
+                    Thread.sleep(2000);
+                } catch (InterruptedException e1) {
+                }
+                try {
+                Node randomNode = nodes[random.nextInt(NUMBER_OF_NODES)];
+                Node randomNode2 = randomNode;
+                while(randomNode2 == randomNode)
+                    randomNode2 = nodes[random.nextInt(NUMBER_OF_NODES)];
+                Logger.normal(RealNodeRoutingTest.class, "Pinging 
"+randomNode2.getPortNumber()+" from "+randomNode.getPortNumber());
+                double loc2 = randomNode2.getLocation();
+                int hopsTaken = randomNode.routedPing(loc2);
+                pings++;
+                if(hopsTaken < 0) {
+                    failures++;
+                    avg.report(0.0);
+                    avg2.report(0.0);
+                    double ratio = (double)successes / 
((double)(failures+successes));
+                    Logger.normal(RealNodeRoutingTest.class, "Routed ping 
"+pings+" FAILED from "+randomNode.getPortNumber()+" to 
"+randomNode2.getPortNumber()+" (long:"+ratio+", short:"+avg.currentValue()+", 
vague:"+avg2.currentValue()+ ')');
+                } else {
+                    successes++;
+                    avg.report(1.0);
+                    avg2.report(1.0);
+                    double ratio = (double)successes / 
((double)(failures+successes));
+                    Logger.normal(RealNodeRoutingTest.class, "Routed ping 
"+pings+" success: "+hopsTaken+ ' ' +randomNode.getPortNumber()+" to 
"+randomNode2.getPortNumber()+" (long:"+ratio+", short:"+avg.currentValue()+", 
vague:"+avg2.currentValue()+ ')');
+                }
+                } catch (Throwable t) {
+                    Logger.error(RealNodeRoutingTest.class, "Caught "+t, t);
+                }
+            }
+            if(pings > 10 && avg.currentValue() > 0.98 && ((double)successes / 
((double)(failures+successes)) > 0.98)) {
+                break;
+            }
+        }
+        System.out.println();
+        System.out.println("Ping average > 98%, lets do some 
inserts/requests");
+        System.out.println();
+        int requestNumber = 0;
+        RunningAverage requestsAvg = new SimpleRunningAverage(100, 0.0);
+        String baseString = System.currentTimeMillis() + " ";
+        while(true) {
+            try {
+                requestNumber++;
+                try {
+                    Thread.sleep(5000);
+                } catch (InterruptedException e1) {
+                }
+                String dataString = baseString + requestNumber;
+                // Pick random node to insert to
+                int node1 = random.nextInt(NUMBER_OF_NODES);
+                Node randomNode = nodes[node1];
+                Logger.error(RealNodeRequestInsertTest.class,"Inserting: 
\""+dataString+"\" to "+node1);
+                byte[] data = dataString.getBytes();
+                ClientCHKBlock block;
+                block = ClientCHKBlock.encode(data, false, false, (short)-1, 
0);
+                ClientCHK chk = (ClientCHK) block.getClientKey();
+                byte[] encData = block.getData();
+                byte[] encHeaders = block.getHeaders();
+                ClientCHKBlock newBlock = new ClientCHKBlock(encData, 
encHeaders, chk, true);
+                Logger.error(RealNodeRequestInsertTest.class, "Decoded: "+new 
String(newBlock.memoryDecode()));
+                Logger.error(RealNodeRequestInsertTest.class,"CHK: 
"+chk.getURI());
+                Logger.error(RealNodeRequestInsertTest.class,"Headers: 
"+HexUtil.bytesToHex(block.getHeaders()));
+                randomNode.clientCore.realPut(block, true);
+                Logger.error(RealNodeRequestInsertTest.class, "Inserted to 
"+node1);
+                Logger.error(RealNodeRequestInsertTest.class, "Data: 
"+Fields.hashCode(encData)+", Headers: "+Fields.hashCode(encHeaders));
+                // Pick random node to request from
+                int node2;
+                do {
+                    node2 = random.nextInt(NUMBER_OF_NODES);
+                } while(node2 == node1);
+                Node fetchNode = nodes[node2];
+                block = (ClientCHKBlock) 
fetchNode.clientCore.realGetKey((ClientKey) chk, false, true, false);
+                if(block == null) {
+                    Logger.error(RealNodeRequestInsertTest.class, "Fetch 
FAILED from "+node2);
+                    requestsAvg.report(0.0);
+                } else {
+                    byte[] results = block.memoryDecode();
+                    requestsAvg.report(1.0);
+                    if(Arrays.equals(results, data)) {
+                        Logger.error(RealNodeRequestInsertTest.class, "Fetch 
succeeded: "+new String(results));
+                    } else {
+                        Logger.error(RealNodeRequestInsertTest.class, 
"Returned invalid data!: "+new String(results));
+                    }
+                }
+            } catch (Throwable t) {
+                Logger.error(RealNodeRequestInsertTest.class, "Caught "+t, t);
+            }
+        }
+    }
+}


Property changes on: 
trunk/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Copied: trunk/freenet/src/freenet/node/simulator/RealNodeRoutingTest.java (from 
rev 11497, trunk/freenet/src/freenet/node/RealNodeRoutingTest.java)
===================================================================
--- trunk/freenet/src/freenet/node/simulator/RealNodeRoutingTest.java           
                (rev 0)
+++ trunk/freenet/src/freenet/node/simulator/RealNodeRoutingTest.java   
2006-12-21 01:52:49 UTC (rev 11503)
@@ -0,0 +1,147 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.node.simulator;
+
+import java.io.File;
+
+import freenet.crypt.DiffieHellman;
+import freenet.crypt.DummyRandomSource;
+import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
+import freenet.node.FSParseException;
+import freenet.node.LocationManager;
+import freenet.node.Node;
+import freenet.node.NodeStarter;
+import freenet.node.Node.NodeInitException;
+import freenet.support.Logger;
+import freenet.support.LoggerHook.InvalidThresholdException;
+import freenet.support.math.BootstrappingDecayingRunningAverage;
+import freenet.support.math.RunningAverage;
+import freenet.support.math.SimpleRunningAverage;
+
+/**
+ * @author amphibian
+ * 
+ * Create a mesh of nodes and let them sort out their locations.
+ * 
+ * Then run some node-to-node searches.
+ */
+public class RealNodeRoutingTest {
+
+    static final int NUMBER_OF_NODES = 150;
+    static final short MAX_HTL = (short)6;
+    
+    public static void main(String[] args) throws FSParseException, 
PeerParseException, InvalidThresholdException, NodeInitException, 
ReferenceSignatureVerificationException {
+        Logger.setupStdoutLogging(Logger.NORMAL, 
"freenet.node.CPUAdjustingSwapRequestInterval:minor" 
/*"freenet.node.LocationManager:debug,freenet.node.FNPPacketManager:normal,freenet.io.comm.UdpSocketManager:debug"*/);
+        System.out.println("Routing test using real nodes:");
+        System.out.println();
+        String wd = "realNodeRequestInsertTest";
+        new File(wd).mkdir();
+        NodeStarter.globalTestInit(wd); // ignore Random, using our own
+        DummyRandomSource random = new DummyRandomSource();
+        DiffieHellman.init(random);
+        Node[] nodes = new Node[NUMBER_OF_NODES];
+        Logger.normal(RealNodeRoutingTest.class, "Creating nodes...");
+        for(int i=0;i<NUMBER_OF_NODES;i++) {
+            nodes[i] = 
+               NodeStarter.createTestNode(5001+i, wd, false, true, true, 
MAX_HTL, 0 /* no dropped packets */, /* Node.DEFAULT_SWAP_INTERVAL */ 0, 
random);
+            Logger.normal(RealNodeRoutingTest.class, "Created node "+i);
+        }
+        Logger.normal(RealNodeRoutingTest.class, "Created "+NUMBER_OF_NODES+" 
nodes");
+        // Now link them up
+        // Connect the set
+        for(int i=0;i<NUMBER_OF_NODES;i++) {
+            int next = (i+1) % NUMBER_OF_NODES;
+            int prev = (i+NUMBER_OF_NODES-1)%NUMBER_OF_NODES;
+            nodes[i].connect(nodes[next]);
+            nodes[i].connect(nodes[prev]);
+        }
+        Logger.normal(RealNodeRoutingTest.class, "Connected nodes");
+        // Now add some random links
+        for(int i=0;i<NUMBER_OF_NODES*5;i++) {
+            if(i % NUMBER_OF_NODES == 0)
+                Logger.normal(RealNodeRoutingTest.class, ""+i);
+            int length = (int)Math.pow(NUMBER_OF_NODES, random.nextDouble());
+            int nodeA = random.nextInt(NUMBER_OF_NODES);
+            int nodeB = (nodeA+length)%NUMBER_OF_NODES;
+            //System.out.println(""+nodeA+" -> "+nodeB);
+            Node a = nodes[nodeA];
+            Node b = nodes[nodeB];
+            a.connect(b);
+            b.connect(a);
+        }
+
+        Logger.normal(RealNodeRoutingTest.class, "Added random links");
+        
+        for(int i=0;i<NUMBER_OF_NODES;i++)
+            nodes[i].start(false);
+        
+        // Now sit back and watch the fireworks!
+        int cycleNumber = 0;
+        int lastSwaps = 0;
+        int lastNoSwaps = 0;
+        int failures = 0;
+        int successes = 0;
+        RunningAverage avg = new SimpleRunningAverage(100, 0.0);
+        RunningAverage avg2 = new BootstrappingDecayingRunningAverage(0.0, 
0.0, 1.0, 100, null);
+        int pings = 0;
+        while(true) {
+            cycleNumber++;
+            try {
+                Thread.sleep(5000);
+            } catch (InterruptedException e) {
+                // Ignore
+            }
+            for(int i=0;i<NUMBER_OF_NODES;i++) {
+                Logger.normal(RealNodeRoutingTest.class, "Cycle 
"+cycleNumber+" node "+i+": "+nodes[i].getLocation());
+            }
+            int newSwaps = LocationManager.swaps;
+            int totalStarted = LocationManager.startedSwaps;
+            int noSwaps = LocationManager.noSwaps;
+            Logger.normal(RealNodeRoutingTest.class, "Swaps: 
"+(newSwaps-lastSwaps));
+            Logger.normal(RealNodeRoutingTest.class, "\nTotal swaps: 
Started*2: "+totalStarted*2+", succeeded: "+newSwaps+", last minute failures: 
"+noSwaps+
+                    ", ratio "+(double)noSwaps/(double)newSwaps+", early 
failures: "+((totalStarted*2)-(noSwaps+newSwaps)));
+            Logger.normal(RealNodeRoutingTest.class, "This cycle ratio: 
"+((double)(noSwaps-lastNoSwaps)) / ((double)(newSwaps - lastSwaps)));
+            lastNoSwaps = noSwaps;
+            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (already 
locked): "+LocationManager.swapsRejectedAlreadyLocked);
+            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (nowhere 
to go): "+LocationManager.swapsRejectedNowhereToGo);
+            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (rate 
limit): "+LocationManager.swapsRejectedRateLimit);
+            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected (loop): 
"+LocationManager.swapsRejectedLoop);
+            Logger.normal(RealNodeRoutingTest.class, "Swaps rejected 
(recognized ID):" +LocationManager.swapsRejectedRecognizedID);
+            lastSwaps = newSwaps;
+            // Do some (routed) test-pings
+            for(int i=0;i<10;i++) {
+                try {
+                    Thread.sleep(5000);
+                } catch (InterruptedException e1) {
+                }
+                try {
+                Node randomNode = nodes[random.nextInt(NUMBER_OF_NODES)];
+                Node randomNode2 = randomNode;
+                while(randomNode2 == randomNode)
+                    randomNode2 = nodes[random.nextInt(NUMBER_OF_NODES)];
+                Logger.normal(RealNodeRoutingTest.class, "Pinging 
"+randomNode2.getPortNumber()+" from "+randomNode.getPortNumber());
+                double loc2 = randomNode2.getLocation();
+                int hopsTaken = randomNode.routedPing(loc2);
+                pings++;
+                if(hopsTaken < 0) {
+                    failures++;
+                    avg.report(0.0);
+                    avg2.report(0.0);
+                    double ratio = (double)successes / 
((double)(failures+successes));
+                    Logger.normal(RealNodeRoutingTest.class, "Routed ping 
"+pings+" FAILED from "+randomNode.getPortNumber()+" to 
"+randomNode2.getPortNumber()+" (long:"+ratio+", short:"+avg.currentValue()+", 
vague:"+avg2.currentValue()+ ')');
+                } else {
+                    successes++;
+                    avg.report(1.0);
+                    avg2.report(1.0);
+                    double ratio = (double)successes / 
((double)(failures+successes));
+                    Logger.normal(RealNodeRoutingTest.class, "Routed ping 
"+pings+" success: "+hopsTaken+ ' ' +randomNode.getPortNumber()+" to 
"+randomNode2.getPortNumber()+" (long:"+ratio+", short:"+avg.currentValue()+", 
vague:"+avg2.currentValue()+ ')');
+                }
+                } catch (Throwable t) {
+                    Logger.error(RealNodeRoutingTest.class, "Caught "+t, t);
+                }
+            }
+        }
+    }
+}


Property changes on: 
trunk/freenet/src/freenet/node/simulator/RealNodeRoutingTest.java
___________________________________________________________________
Name: svn:eol-style
   + native


Reply via email to