Package freenet.node

Source Code of freenet.node.NodePinger$CapacityChecker

/* 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 static java.util.concurrent.TimeUnit.DAYS;

import java.util.Arrays;

import freenet.node.NodeStats.PeerLoadStats;
import freenet.support.LogThresholdCallback;
import freenet.support.Logger;
import freenet.support.Logger.LogLevel;

/**
* Track average round-trip time for each peer node, get a geometric mean.
*/
public class NodePinger implements Runnable {
    private static volatile boolean logMINOR;

    static {
        Logger.registerLogThresholdCallback(new LogThresholdCallback() {

            @Override
            public void shouldUpdate() {
                logMINOR = Logger.shouldLog(LogLevel.MINOR, this);
            }
        });
    }

  private final Node node;
  private volatile double meanPing = 0;

  public static final double CRAZY_MAX_PING_TIME = 365.25 * DAYS.toMillis(1);

  NodePinger(Node n) {
    this.node = n;
  }

  void start() {
    run();
  }
 
  @Override
  public void run() {
        try {
        PeerNode[] peers = null;
        synchronized(node.peers) {
          peers = node.peers.connectedPeers();
        }
        if(peers == null || peers.length == 0) return;

        // Now we don't have to care about synchronization anymore
        recalculateMean(peers);
        capacityInputRealtime.calculate(peers);
        capacityInputBulk.calculate(peers);
        capacityOutputRealtime.calculate(peers);
        capacityOutputBulk.calculate(peers);
        } finally {
          // Requeue after to avoid exacerbating overload
          node.getTicker().queueTimedJob(this, 200);
        }
  }

  /** Recalculate the mean ping time */
  private void recalculateMean(PeerNode[] peers) {
    if(peers.length == 0) return;
    meanPing = calculateMedianPing(peers);
    if(logMINOR)
      Logger.minor(this, "Median ping: "+meanPing);
  }
 
  private double calculateMedianPing(PeerNode[] peers) {
    double[] allPeers = new double[peers.length];
        for(int i = 0; i < peers.length; i++) {
            PeerNode peer = peers[i];
            allPeers[i] = peer.averagePingTime();
        }
   
    Arrays.sort(allPeers);
    return allPeers[peers.length / 2];
  }

  public double averagePingTime() {
    return meanPing;
  }
 
  final CapacityChecker capacityInputRealtime = new CapacityChecker(true, true);
  final CapacityChecker capacityInputBulk = new CapacityChecker(true, false);
  final CapacityChecker capacityOutputRealtime = new CapacityChecker(false, true);
  final CapacityChecker capacityOutputBulk = new CapacityChecker(false, false);
 
  class CapacityChecker {
    final boolean isInput;
    final boolean isRealtime;
    private double min;
    private double median;
    private double firstQuartile;
    private double lastQuartile;
    private double max;
   
    CapacityChecker(boolean input, boolean realtime) {
      isInput = input;
      isRealtime = realtime;
    }
   
    void calculate(PeerNode[] peers) {
      double[] allPeers = new double[peers.length];
      int x = 0;
      for(PeerNode peer : peers) {
        PeerLoadStats stats = peer.outputLoadTracker(isRealtime).getLastIncomingLoadStats();
        if(stats == null) continue;
        allPeers[x++] = stats.peerLimit(isInput);
      }
      if(x != peers.length) {
        allPeers = Arrays.copyOf(allPeers, x);
      }
      Arrays.sort(allPeers);
      if(x == 0) return;
      synchronized(this) {
        min = allPeers[0];
        median = allPeers[x / 2];
        firstQuartile = allPeers[x / 4];
        lastQuartile = allPeers[(x * 3) / 4];
        max = allPeers[x - 1];
        if(logMINOR) Logger.minor(this, "Quartiles for peer capacities: "+(isInput?"input ":"output ")+(isRealtime?"realtime: ":"bulk: ")+Arrays.toString(getQuartiles()));
      }
    }
   
    synchronized double[] getQuartiles() {
      return new double[] { min, firstQuartile, median, lastQuartile, max };
    }
   
    /** Get min(half the median, first quartile). Used as a threshold. */
    synchronized double getThreshold() {
      return Math.min(median/2, firstQuartile);
    }
  }

  public double capacityThreshold(boolean isRealtime, boolean isInput) {
    return capacityChecker(isRealtime, isInput).getThreshold();
  }

  private CapacityChecker capacityChecker(boolean isRealtime, boolean isInput) {
    if(isRealtime) {
      return isInput ? capacityInputRealtime : capacityOutputRealtime;
    } else {
      return isInput ? capacityInputBulk: capacityOutputBulk;
    }
  }
}
TOP

Related Classes of freenet.node.NodePinger$CapacityChecker

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.