Author: robert
Date: 2008-02-08 20:31:19 +0000 (Fri, 08 Feb 2008)
New Revision: 17719

Added:
   trunk/freenet/src/freenet/node/simulator/RealNodeNetworkColoringTest.java
Modified:
   trunk/freenet/src/freenet/node/simulator/RealNodeSecretPingTest.java
Log:
implement connectivity & network coloring simulator


Added: trunk/freenet/src/freenet/node/simulator/RealNodeNetworkColoringTest.java
===================================================================
--- trunk/freenet/src/freenet/node/simulator/RealNodeNetworkColoringTest.java   
                        (rev 0)
+++ trunk/freenet/src/freenet/node/simulator/RealNodeNetworkColoringTest.java   
2008-02-08 20:31:19 UTC (rev 17719)
@@ -0,0 +1,319 @@
+/* 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.HashSet;
+import java.util.Iterator;
+
+import freenet.crypt.DummyRandomSource;
+import freenet.io.comm.DisconnectedException;
+import freenet.io.comm.DMT;
+import freenet.io.comm.Message;
+import freenet.io.comm.MessageFilter;
+import freenet.io.comm.NotConnectedException;
+import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
+import freenet.node.FSParseException;
+import freenet.node.Location;
+import freenet.node.LocationManager;
+import freenet.node.Node;
+import freenet.node.NodeInitException;
+import freenet.node.NodeStarter;
+import freenet.node.PeerNode;
+import freenet.support.Executor;
+import freenet.support.Logger;
+import freenet.support.PooledExecutor;
+import freenet.support.LoggerHook.InvalidThresholdException;
+import freenet.support.math.BootstrappingDecayingRunningAverage;
+import freenet.support.math.RunningAverage;
+import freenet.support.math.SimpleRunningAverage;
+
+/**
+ * Create a bunch of nodes
+ * Connect them into two or more s.w. networks (rather than just letting them 
sort out their locations)
+ * Weakly connect the two networks.
+ * See if they will be able to separate themselves.
+ */
+public class RealNodeNetworkColoringTest {
+
+    //static final int NUMBER_OF_NODES = 150;
+       static final int NUMBER_OF_NODES = 20;
+       static final int BRIDGES = 3;
+       
+       //either the number of connections between the two networks (if 
BRIDGES=0)
+       //or the number of connections from each bridge to each network (if 
BRIDGES>0)
+       static final int BRIDGE_LINKS = 2;
+       
+    static final short MAX_HTL = (short)6;
+       static final int DEGREE = 5;
+       
+       static final long storeSize = 1024*1024;
+       
+       //Use something shorter than 
'freenet.node.simulator.RealNodeNetworkColoringTest' !
+       private static final Object log = new Object();
+       
+    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.MessageCore:debug"*/);
+        System.out.println("SecretPing/NetworkColoring test using real 
nodes:");
+        System.out.println();
+        String wd = "realNodeNetworkColorTest";
+        new File(wd).mkdir();
+        //NOTE: globalTestInit returns in ignored random source
+        NodeStarter.globalTestInit(wd, false);
+               Logger.setupStdoutLogging(Logger.ERROR, 
"freenet.node.Location:normal,freenet.node.simulator.RealNodeNetworkColoringTest:normal,freenet.node.NetworkIDManager:normal");
+               Logger.globalSetThreshold(Logger.ERROR);
+
+        DummyRandomSource random = new DummyRandomSource();
+        //DiffieHellman.init(random);
+        Node[] subnetA = new Node[NUMBER_OF_NODES];
+               Node[] subnetB = new Node[NUMBER_OF_NODES];
+               Node[] bridges = new Node[BRIDGES];
+               
+               int totalNodes=NUMBER_OF_NODES*2+BRIDGES;
+               Node[] allNodes = new Node[totalNodes];
+               
+               //cheat and use totalNodes as a counter for a moment...
+               totalNodes=0;
+               
+        Logger.normal(RealNodeRoutingTest.class, "Creating nodes...");
+        Executor executor = new PooledExecutor();
+               
+               //Allow secret pings, and send them automatically, must be done 
before creating the nodes.
+               freenet.node.NetworkIDManager.disableSecretPings=false;
+               freenet.node.NetworkIDManager.disableSecretPinger=false;
+               
+        for(int i=0;i<NUMBER_OF_NODES;i++) {
+                       allNodes[totalNodes] =
+            subnetA[i] = 
+               NodeStarter.createTestNode(5001+totalNodes, wd, false, true, 
true, MAX_HTL, 0 /* no dropped packets */, random, executor, 
500*NUMBER_OF_NODES, storeSize, true);
+                       totalNodes++;
+            Logger.normal(RealNodeRoutingTest.class, "Created 'A' node 
"+totalNodes);
+        }
+        for(int i=0;i<NUMBER_OF_NODES;i++) {
+                       allNodes[totalNodes] =
+            subnetB[i] = 
+                       NodeStarter.createTestNode(5001+totalNodes, wd, false, 
true, true, MAX_HTL, 0 /* no dropped packets */, random, executor, 
500*NUMBER_OF_NODES, storeSize, true);
+                       totalNodes++;
+            Logger.normal(RealNodeRoutingTest.class, "Created 'B' node 
"+totalNodes);
+        }
+               for(int i=0;i<BRIDGES;i++) {
+                       allNodes[totalNodes] =
+            bridges[i] = 
+                       NodeStarter.createTestNode(5001+totalNodes, wd, false, 
true, true, MAX_HTL, 0 /* no dropped packets */, random, executor, 
500*NUMBER_OF_NODES, storeSize, true);
+                       totalNodes++;
+            Logger.normal(RealNodeRoutingTest.class, "Created bridge node 
"+totalNodes);
+        }
+        
+        Logger.normal(RealNodeRoutingTest.class, "Created "+totalNodes+" 
nodes");
+               
+        // Now link them up
+        makeKleinbergNetwork(subnetA);
+               makeKleinbergNetwork(subnetB);
+               
+        Logger.normal(RealNodeRoutingTest.class, "Added small-world links, 
weakly connect the subnets");
+        
+               if (BRIDGES==0) {
+                       for (int i=0; i<BRIDGE_LINKS; i++) {
+                               //connect a random node from A to a random node 
from B
+                               Node a = 
subnetA[random.nextInt(NUMBER_OF_NODES)];
+                               Node b = 
subnetB[random.nextInt(NUMBER_OF_NODES)];
+                               connect(a, b);
+                       }
+               } else {
+                       for (int b=0; b<BRIDGES; b++) {
+                               Node bridge=bridges[b];
+                               //make BRIDGE_LINKS into A
+                               for (int i=0; i<BRIDGE_LINKS; i++) {
+                                       Node nodeA = 
subnetA[random.nextInt(NUMBER_OF_NODES)];
+                                       connect(bridge, nodeA);
+                               }
+                               //make BRIDGE_LINKS into B
+                               for (int i=0; i<BRIDGE_LINKS; i++) {
+                                       Node nodeB = 
subnetB[random.nextInt(NUMBER_OF_NODES)];
+                                       connect(bridge, nodeB);
+                               }
+                       }
+               }
+               
+               for(int i=0;i<totalNodes;i++)
+            allNodes[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 general = new 
BootstrappingDecayingRunningAverage(0.0, 0.0, 1.0, 2000, null);
+        RunningAverage aRate = new BootstrappingDecayingRunningAverage(0.0, 
0.0, 1.0, 500, null);
+               RunningAverage bRate = new 
BootstrappingDecayingRunningAverage(0.0, 0.0, 1.0, 500, null);
+               RunningAverage bridgeRate = new 
BootstrappingDecayingRunningAverage(0.0, 0.0, 1.0, 500, null);
+               HashSet generalIds=new HashSet();
+               HashSet aIds=new HashSet();
+               HashSet bIds=new HashSet();
+               HashSet bridgeIds=new HashSet();
+        int pings = 0;
+               
+        while(true) {
+            cycleNumber++;
+                       
+                       try {
+                Thread.sleep(5000);
+            } catch (InterruptedException e) {
+                // Ignore
+            }
+                       
+                       long totalSuccesses=0;
+                       long totalTotalPings=0;
+                       generalIds.clear();
+                       aIds.clear();
+                       bIds.clear();
+                       bridgeIds.clear();
+                       
+                       for (int i=0; i<NUMBER_OF_NODES; i++) {
+                               long good=subnetA[i].netid.secretPingSuccesses;
+                               long 
total=subnetA[i].netid.totalSecretPingAttempts;
+                               int id=subnetA[i].netid.ourNetworkId;
+                               totalSuccesses+=good;
+                               totalTotalPings+=total;
+                               //eh... not really, but I guess it's close; 
reset this nodes good/total?
+                               double rate = 0.0;
+                               if (total!=0)
+                                       rate = 1.0*good/total;
+                               general.report(rate);
+                               aRate.report(rate);
+                               generalIds.add(new Integer(id));
+                               aIds.add(new Integer(id));
+                       }
+                       
+                       for (int i=0; i<NUMBER_OF_NODES; i++) {
+                               long good=subnetB[i].netid.secretPingSuccesses;
+                               long 
total=subnetB[i].netid.totalSecretPingAttempts;
+                               int id=subnetB[i].netid.ourNetworkId;
+                               totalSuccesses+=good;
+                               totalTotalPings+=total;
+                               //eh... not really, but I guess it's close; 
reset this nodes good/total?
+                               double rate = 0.0;
+                               if (total!=0)
+                                       rate = 1.0*good/total;
+                               general.report(rate);
+                               bRate.report(rate);
+                               generalIds.add(new Integer(id));
+                               bIds.add(new Integer(id));
+                       }
+                       
+                       for (int i=0; i<BRIDGES; i++) {
+                               long good=bridges[i].netid.secretPingSuccesses;
+                               long 
total=bridges[i].netid.totalSecretPingAttempts;
+                               int id=bridges[i].netid.ourNetworkId;
+                               totalSuccesses+=good;
+                               totalTotalPings+=total;
+                               //eh... not really, but I guess it's close; 
reset this nodes good/total?
+                               double rate = 0.0;
+                               if (total!=0)
+                                       rate = 1.0*good/total;
+                               general.report(rate);
+                               bridgeRate.report(rate);
+                               generalIds.add(new Integer(id));
+                               bridgeIds.add(new Integer(id));
+                       }
+                       
+                       Logger.error(log, "cycle = "+cycleNumber);
+                       Logger.error(log, "total SecretPings= 
"+totalTotalPings);
+                       Logger.error(log, "total successful = "+totalSuccesses);
+                       
+                       Logger.error(log, "  pSuccess(All)  = 
"+general.currentValue());
+                       Logger.error(log, "  pSuccess( A )  = 
"+aRate.currentValue());
+                       Logger.error(log, "  pSuccess( B )  = 
"+bRate.currentValue());
+                       if (BRIDGES!=0)
+                               Logger.error(log, "  pSuccess(BRG)  = 
"+bridgeRate.currentValue());
+                       
+                       idReport("All", generalIds);
+                       idReport(" A ", generalIds);
+                       idReport(" B ", generalIds);
+                       if (BRIDGES!=0)
+                               idReport("BRG", generalIds);
+               }
+    }
+       
+       private static void idReport(String group, HashSet ids) {
+               //Print out the number which are non-zero & display the 
distinct ones if a few...
+               int size=ids.size();
+               int MAX=4;
+               StringBuffer sb=new 
StringBuffer(Integer.toString(size)).append(" ids (").append(group).append(") = 
");
+               Iterator iter=ids.iterator();
+               for (int i=0; i<MAX && i<size; i++) {
+                       String thisId=iter.next().toString();
+                       if (i==0)
+                               sb.append(thisId);
+                       else
+                               sb.append(", ").append(thisId);
+               }
+               if (size>MAX)
+                       sb.append(", ...");
+               Logger.error(log, sb.toString());
+       }
+       
+       /*
+        Borrowed from mrogers simulation code (February 6, 2008)
+        */
+       static void makeKleinbergNetwork (Node[] nodes)
+       {
+               for (int i=0; i<nodes.length; i++) {
+                       Node a = nodes[i];
+                       // Normalise the probabilities
+                       double norm = 0.0;
+                       for (int j=0; j<nodes.length; j++) {
+                               Node b = nodes[j];
+                               if (a.getLocation() == b.getLocation()) 
continue;
+                               norm += 1.0 / distance (a, b);
+                       }
+                       // Create DEGREE/2 outgoing connections
+                       for (int k=0; k<nodes.length; k++) {
+                               Node b = nodes[k];
+                               if (a.getLocation() == b.getLocation()) 
continue;
+                               double p = 1.0 / distance (a, b) / norm;
+                               for (int n = 0; n < DEGREE / 2; n++) {
+                                       if (Math.random() < p) {
+                                               connect(a, b);
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       static void connect(Node a, Node b) {
+               try {
+                       a.connect (b);
+                       b.connect (a);
+               } catch (FSParseException e) {
+                       Logger.error(RealNodeSecretPingTest.class, "cannot 
connect!!!!", e);
+               } catch (PeerParseException e) {
+                       Logger.error(RealNodeSecretPingTest.class, "cannot 
connect #2!!!!", e);
+               } catch 
(freenet.io.comm.ReferenceSignatureVerificationException e) {
+                       Logger.error(RealNodeSecretPingTest.class, "cannot 
connect #3!!!!", e);
+               }
+       }
+       
+       static double distance(Node a, Node b) {
+               double aL=a.getLocation();
+               double bL=b.getLocation();
+               return Location.distance(aL, bL);
+       }
+       
+       static String getPortNumber(PeerNode p) {
+               if (p == null || p.getPeer() == null)
+                       return "null";
+               return Integer.toString(p.getPeer().getPort());
+       }
+       
+       static String getPortNumber(Node n) {
+               if (n == null)
+                       return "null";
+               return Integer.toString(n.getDarknetPortNumber());
+       }
+       
+}

Modified: trunk/freenet/src/freenet/node/simulator/RealNodeSecretPingTest.java
===================================================================
--- trunk/freenet/src/freenet/node/simulator/RealNodeSecretPingTest.java        
2008-02-08 20:20:21 UTC (rev 17718)
+++ trunk/freenet/src/freenet/node/simulator/RealNodeSecretPingTest.java        
2008-02-08 20:31:19 UTC (rev 17719)
@@ -63,6 +63,11 @@
         Node[] nodes = new Node[NUMBER_OF_NODES];
         Logger.normal(RealNodeRoutingTest.class, "Creating nodes...");
         Executor executor = new PooledExecutor();
+               
+               //Allow secret pings, but don't automatically send them (this 
is the test for them!)
+               freenet.node.NetworkIDManager.disableSecretPings=false;
+               freenet.node.NetworkIDManager.disableSecretPinger=true;
+               
         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 */, random, executor, 500*NUMBER_OF_NODES, 
storeSize, true);
@@ -75,9 +80,6 @@

         for(int i=0;i<NUMBER_OF_NODES;i++)
             nodes[i].start(false);
-        
-               //In case they are hard-coded off, allow secret pings (this is 
the test for them!)
-               freenet.node.NetworkIDManager.disableSecretPings=false;

         // Now sit back and watch the fireworks!
         int cycleNumber = 0;


Reply via email to