Package freenet.node.simulator

Source Code of freenet.node.simulator.RealNodeRoutingTest

/* 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.DummyRandomSource;
import freenet.crypt.RandomSource;
import freenet.node.LocationManager;
import freenet.node.Node;
import freenet.node.NodeStarter;
import freenet.support.Executor;
import freenet.support.Logger;
import freenet.support.PooledExecutor;
import freenet.support.Logger.LogLevel;
import freenet.support.io.FileUtil;
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 extends RealNodeTest {

  static final int NUMBER_OF_NODES = 100;
  static final int DEGREE = 10;
  static final short MAX_HTL = (short) 5;
  static final boolean START_WITH_IDEAL_LOCATIONS = true;
  static final boolean FORCE_NEIGHBOUR_CONNECTIONS = true;
  static final int MAX_PINGS = 2000;
  static final boolean ENABLE_SWAPPING = false;
  static final boolean ENABLE_SWAP_QUEUEING = false;
  static final boolean ENABLE_FOAF = true;
 
  public static int DARKNET_PORT_BASE = RealNodeRequestInsertTest.DARKNET_PORT_END;
  public static final int DARKNET_PORT_END = DARKNET_PORT_BASE + NUMBER_OF_NODES;

  public static void main(String[] args) throws Exception {
    System.out.println("Routing test using real nodes:");
    System.out.println();
    String dir = "realNodeRequestInsertTest";
    File wd = new File(dir);
    if(!FileUtil.removeAll(wd)) {
      System.err.println("Mass delete failed, test may not be accurate.");
      System.exit(EXIT_CANNOT_DELETE_OLD_DATA);
    }
    wd.mkdir();
    //NOTE: globalTestInit returns in ignored random source
    NodeStarter.globalTestInit(dir, false, LogLevel.ERROR, "", true);
    // Make the network reproducible so we can easily compare different routing options by specifying a seed.
    DummyRandomSource random = new DummyRandomSource(3142);
    //DiffieHellman.init(random);
    Node[] nodes = new Node[NUMBER_OF_NODES];
    Logger.normal(RealNodeRoutingTest.class, "Creating nodes...");
    Executor executor = new PooledExecutor();
    for(int i = 0; i < NUMBER_OF_NODES; i++) {
      System.err.println("Creating node " + i);
      nodes[i] = NodeStarter.createTestNode(DARKNET_PORT_BASE + i, 0, dir, true, MAX_HTL, 0 /* no dropped packets */, random, executor, 500 * NUMBER_OF_NODES, 65536, true, ENABLE_SWAPPING, false, false, false, ENABLE_SWAP_QUEUEING, true, 0, ENABLE_FOAF, false, true, false, null);
      Logger.normal(RealNodeRoutingTest.class, "Created node " + i);
    }
    Logger.normal(RealNodeRoutingTest.class, "Created " + NUMBER_OF_NODES + " nodes");
    // Now link them up
    makeKleinbergNetwork(nodes, START_WITH_IDEAL_LOCATIONS, DEGREE, FORCE_NEIGHBOUR_CONNECTIONS, random);

    Logger.normal(RealNodeRoutingTest.class, "Added random links");

    for(int i = 0; i < NUMBER_OF_NODES; i++) {
      System.err.println("Starting node " + i);
      nodes[i].start(false);
    }

    waitForAllConnected(nodes);

    // Make the choice of nodes to ping to and from deterministic too.
    // There is timing noise because of all the nodes, but the network
    // and the choice of nodes to start and finish are deterministic, so
    // the overall result should be more or less deterministic.
    waitForPingAverage(0.98, nodes, new DummyRandomSource(3143), MAX_PINGS, 5000);
    System.exit(0);
  }

  static void waitForPingAverage(double accuracy, Node[] nodes, RandomSource random, int maxTests, int sleepTime) throws InterruptedException {
    int totalHopsTaken = 0;
    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;
    for(int total = 0; total < maxTests; total++) {
      cycleNumber++;
      try {
        Thread.sleep(sleepTime);
      } catch(InterruptedException e) {
        // Ignore
      }
      for(int i = 0; i < nodes.length; i++) {
        System.err.println("Cycle " + cycleNumber + " node " + i + ": " + nodes[i].getLocation());
      }
      int newSwaps = LocationManager.swaps;
      int totalStarted = LocationManager.startedSwaps;
      int noSwaps = LocationManager.noSwaps;
      System.err.println("Swaps: " + (newSwaps - lastSwaps));
      System.err.println("\nTotal swaps: Started*2: " + totalStarted * 2 + ", succeeded: " + newSwaps + ", last minute failures: " + noSwaps +
        ", ratio " + (double) noSwaps / (double) newSwaps + ", early failures: " + ((totalStarted * 2) - (noSwaps + newSwaps)));
      System.err.println("This cycle ratio: " + ((double) (noSwaps - lastNoSwaps)) / ((double) (newSwaps - lastSwaps)));
      lastNoSwaps = noSwaps;
      System.err.println("Swaps rejected (already locked): " + LocationManager.swapsRejectedAlreadyLocked);
      System.err.println("Swaps rejected (nowhere to go): " + LocationManager.swapsRejectedNowhereToGo);
      System.err.println("Swaps rejected (rate limit): " + LocationManager.swapsRejectedRateLimit);
      System.err.println("Swaps rejected (recognized ID):" + LocationManager.swapsRejectedRecognizedID);
      System.err.println("Swaps failed:" + LocationManager.noSwaps);
      System.err.println("Swaps succeeded:" + LocationManager.swaps);

      double totalSwapInterval = 0.0;
      double totalSwapTime = 0.0;
      for(int i = 0; i < nodes.length; i++) {
        totalSwapInterval += nodes[i].lm.getSendSwapInterval();
        totalSwapTime += nodes[i].lm.getAverageSwapTime();
      }
      System.err.println("Average swap time: " + (totalSwapTime / nodes.length));
      System.err.println("Average swap sender interval: " + (totalSwapInterval / nodes.length));

      waitForAllConnected(nodes);

      lastSwaps = newSwaps;
      // Do some (routed) test-pings
      for(int i = 0; i < 10; i++) {
        try {
          Thread.sleep(sleepTime);
        } catch(InterruptedException e1) {
        }
        try {
          Node randomNode = nodes[random.nextInt(nodes.length)];
          Node randomNode2 = randomNode;
          while(randomNode2 == randomNode) {
            randomNode2 = nodes[random.nextInt(nodes.length)];
          }
          double loc2 = randomNode2.getLocation();
          Logger.normal(RealNodeRoutingTest.class, "Pinging " + randomNode2.getDarknetPortNumber() + " @ " + loc2 + " from " + randomNode.getDarknetPortNumber() + " @ " + randomNode.getLocation());
         
          int hopsTaken = randomNode.routedPing(loc2, randomNode2.getDarknetPubKeyHash());
          pings++;
          if(hopsTaken < 0) {
            failures++;
            avg.report(0.0);
            avg2.report(0.0);
            double ratio = (double) successes / ((double) (failures + successes));
            System.err.println("Routed ping " + pings + " FAILED from " + randomNode.getDarknetPortNumber() + " to " + randomNode2.getDarknetPortNumber() + " (long:" + ratio + ", short:" + avg.currentValue() + ", vague:" + avg2.currentValue() + ')');
          } else {
            totalHopsTaken += hopsTaken;
            successes++;
            avg.report(1.0);
            avg2.report(1.0);
            double ratio = (double) successes / ((double) (failures + successes));
            System.err.println("Routed ping " + pings + " success: " + hopsTaken + ' ' + randomNode.getDarknetPortNumber() + " to " + randomNode2.getDarknetPortNumber() + " (long:" + ratio + ", short:" + avg.currentValue() + ", vague:" + avg2.currentValue() + ')');
          }
        } catch(Throwable t) {
          Logger.error(RealNodeRoutingTest.class, "Caught " + t, t);
        }
      }
      System.err.println("Average path length for successful requests: "+totalHopsTaken/successes);
      if(pings > 10 && avg.currentValue() > accuracy && ((double) successes / ((double) (failures + successes)) > accuracy)) {
        System.err.println();
        System.err.println("Reached " + (accuracy * 100) + "% accuracy.");
        System.err.println();
        System.err.println("Network size: " + nodes.length);
        System.err.println("Maximum HTL: " + MAX_HTL);
        System.err.println("Average path length for successful requests: "+totalHopsTaken/successes);
        System.err.println("Total started swaps: " + LocationManager.startedSwaps);
        System.err.println("Total rejected swaps (already locked): " + LocationManager.swapsRejectedAlreadyLocked);
        System.err.println("Total swaps rejected (nowhere to go): " + LocationManager.swapsRejectedNowhereToGo);
        System.err.println("Total swaps rejected (rate limit): " + LocationManager.swapsRejectedRateLimit);
        System.err.println("Total swaps rejected (recognized ID):" + LocationManager.swapsRejectedRecognizedID);
        System.err.println("Total swaps failed:" + LocationManager.noSwaps);
        System.err.println("Total swaps succeeded:" + LocationManager.swaps);
        return;
      }
    }
    System.exit(EXIT_PING_TARGET_NOT_REACHED);
  }
}
TOP

Related Classes of freenet.node.simulator.RealNodeRoutingTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.