⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vivaldiclient.java

📁 这是一个基于java编写的torrent的P2P源码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
package edu.harvard.syrah.nc;

/*
 * NCLib - a network coordinate library
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details (
 * see the LICENSE file ).
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.logging.Logger;

/**
 * A class that is responsible for updating the local Vivaldi coordinates, both
 * at the system and application level, and also maintaining the state of remote
 * hosts that support Vivaldi.
 * 
 * @author Michael Parker, Jonathan Ledlie
 * 
 * @param <T>
 * the type of the unique identifier of a host
 */
public class VivaldiClient<T> {

  //protected static edu.harvard.syrah.prp.Log crawler_log =
	//new edu.harvard.syrah.prp.Log(VivaldiClient.class);
  protected static Logger crawler_log = Logger.getLogger(VivaldiClient.class.getName()); 
  
  public static final boolean SIMULATION = false;
  public static boolean debug = false;
  public static boolean debugCrawler = false;
  // include even good events in output, not just problems
  public static boolean debugGood = false;

  // Old version
  public static final byte VERSION_02 = 0x02;
  // Height added
  public static final byte VERSION_03 = 0x03;
  // Changed filter percentile from 0.125 to 0.5
  // and added ping timer at 10sec
  // c_error = 0.10, c_control = 0.25
  public static final byte VERSION_04 = 0x04;
  public static final byte CURRENT_VERSION = VERSION_04;

  
	public static double COORD_ERROR = 0.10; // c_e parameter
	public static double COORD_CONTROL = 0.25; // c_c parameter

  // The last element of the coordinate is a "height" away from the Euclidean space
  public static boolean USE_HEIGHT = true;
  
  // Try to minimize our error between up to MAX_NEIGHBORS guys at once
  
    final public static int MAX_NEIGHBORS = 512;
    final protected static int WINDOW_SIZE = 64;

  // Toss remote state of nodes if we haven't heard from them for three days
  // This allows us to keep around a list of RTTs for the node even if
  // we currently aren't using its coordinate for update
    public static long RS_EXPIRATION = 3 * 24 * 60 * 60 * 1000;
    final public static long MAINTENANCE_PERIOD = 10 * 60 * 1000; // ten minutes
    // target max number of remote states kept
    // set to be larger than MAX_NEIGHBORS
    public final static int MAX_RS_MAP_SIZE = 32 * 1024;
    private long lastMaintenanceStamp = 0;

  
	public static Random random = new Random();

	// Do an update if we've moved a third of the way to our nearest known
	// neighbor
	// Lowering this value leads to more frequent updates
	// Should be less than 0.5
	public static final double APP_UPDATE_THRESHOLD = 0.1;

	// completely ignore any RTT larger than ten seconds
	public static final double OUTRAGEOUSLY_LARGE_RTT = 20000.0;

	// range from origin where pull of gravity is 1
	public static double GRAVITY_DIAMETER = 512.;
	
	// We reject remote coords with any component larger than this value
	// This is to prevent serialization problems from leaking into coords
	// we're actually going to use
	// Gravity should keep everybody within this ball
	public static double MAX_DIST_FROM_ORIGIN = 60000.;
	

	final static protected NumberFormat nf = NumberFormat.getInstance();
	final static protected int NFDigits = 3;
	static boolean haveSetFormat = false;
  
	protected final int num_dims;

	protected Coordinate app_coord;

  protected Coordinate sys_coord;
  
  // error should always be less than or equal to MAX_ERROR
  // and greater than 0
  protected double error;
  public static final double MAX_ERROR = 1.;
  
	public static boolean keepStatistics = true;
	// keeping an EWMA of some of these things gives skewed results
	// so we use a filter
	final public static int RUNNING_STAT_HISTORY = 1024;
	// 30 minutes
	//final public static long STAT_EXPIRE_TIME = 30 * 60 * 1000;
	protected WindowStatistic running_sys_error;
	protected WindowStatistic running_app_error;
	protected EWMAStatistic running_sys_dd;
	protected EWMAStatistic running_app_dd;
	protected EWMAStatistic running_neighbors_used;
	protected EWMAStatistic running_relative_diff;
	protected EWMAStatistic running_sys_update_frequency;
	protected EWMAStatistic running_app_update_frequency;
  protected EWMAStatistic running_age;
  protected EWMAStatistic running_gravity;
	protected long time_of_last_app_update = -1;

  // keep the list of neighbors around for computing statistics
	protected final List<RemoteState<T>> neighbors;
  
  // note: not just part of statistics
  // this is returned to querier of our coords so he knows how stale they are
  protected long time_of_last_sys_update = -1;

	protected final ObserverList obs_list;

	protected final HashMap<T, RemoteState<T>> rs_map;

	protected final Set<T> hosts;

	protected Coordinate start_centroid;

	protected boolean updated_app_coord_at_least_once = false;

	protected final List<Coordinate> start_coords;

	protected final List<Coordinate> current_coords;

	protected Coordinate nearest_neighbor;
	protected T local_addr;
  
  
	/**
	 * Creates a new instance. Typically an application should only have one
	 * instance of this class, as it only needs one set of Vivaldi coordinates.
	 * 
	 * @param _num_dims
	 * the number of Euclidian dimensions coordinates should have
	 */
	public VivaldiClient(int _num_dims) {
		num_dims = _num_dims;

		app_coord = new Coordinate(num_dims);
    sys_coord = new Coordinate(num_dims);

		error = MAX_ERROR;
    neighbors = new ArrayList<RemoteState<T>>();
    
		obs_list = new ObserverList();
		rs_map = new HashMap<T, RemoteState<T>>();
		hosts = Collections.unmodifiableSet(rs_map.keySet());
		start_coords = new LinkedList<Coordinate>();
		current_coords = new LinkedList<Coordinate>();
    nearest_neighbor = null;
    
    //bootstrapCoordinates ();
    
    if (keepStatistics) {
			running_sys_update_frequency = new EWMAStatistic();
			running_app_update_frequency = new EWMAStatistic();
			running_sys_error = new WindowStatistic(RUNNING_STAT_HISTORY);
			running_app_error = new WindowStatistic(RUNNING_STAT_HISTORY);
			running_sys_dd = new EWMAStatistic();
			running_app_dd = new EWMAStatistic();
			running_neighbors_used = new EWMAStatistic();
			running_relative_diff = new EWMAStatistic();
      running_age = new EWMAStatistic();
      running_gravity = new EWMAStatistic();
		}
		
		if (!haveSetFormat) {
		  if (nf.getMaximumFractionDigits() > NFDigits) {
		    nf.setMaximumFractionDigits(NFDigits);
		  }
		  if (nf.getMinimumFractionDigits() > NFDigits) {
		    nf.setMinimumFractionDigits(NFDigits);
		  }
		  nf.setGroupingUsed(false);
		  haveSetFormat = true;
		}
	}

  // for debugging simulations
  public void setLocalID (T _local_addr) {
    local_addr = _local_addr;
  }
  
	// See Lua IMC 2005, Pietzuch WORLDS 2005, Ledlie ICDCS 2006
	// for description of these statistics
	protected ApplicationStatistics computeApplicationStatistics() {

		ApplicationStatistics appStats = new ApplicationStatistics();

		if (sys_coord.atOrigin() || neighbors == null ||
      neighbors.size() == 0) return appStats;    

		int rrl_wrong = 0;
		int rrl_count = 0;
		double narl_loss = 0;
		double narl_sum = 0;
		double ralp_loss = 0;
		double ralp_sum = 0;

    // TODO might want to use the app coord here so as to get the average location
    
		for (Iterator<RemoteState<T>> i = neighbors.iterator(); i.hasNext();) {
			RemoteState<T> A_rs = i.next();

			double A_rtt = A_rs.getSample();
			double A_metric = sys_coord.distanceTo(A_rs.getLastCoordinate());
			if (A_rtt > 0 && A_metric > 0) {

				for (Iterator<RemoteState<T>> j = neighbors.iterator(); j
						.hasNext();) {
					RemoteState<T> B_rs = j.next();

					if (!A_rs.addr.equals(B_rs.addr)) {

						double B_rtt = B_rs.getSample();
						double B_metric = sys_coord.distanceTo(B_rs
								.getLastCoordinate());
						if (B_rtt > 0 && B_metric > 0) {

							double rtt_diff = Math.abs(A_rtt - B_rtt);
							rrl_count++;
							narl_sum += rtt_diff;

							if ((A_rtt > B_rtt && A_metric < B_metric)
									|| (B_rtt > A_rtt && B_metric < A_metric)) {
								// oops coordinates have incorrectly ranked
								// these two guys
								rrl_wrong++;
								narl_loss += rtt_diff;
							}

							// relative latency penalty for using A,
							// which the metric says is closer,
							// when A is actually further away
							if (A_rtt > B_rtt && A_metric < B_metric) {
								ralp_loss += rtt_diff;
								ralp_sum += A_rtt;
							}
							if (B_rtt > A_rtt && B_metric < A_metric) {
								ralp_loss += rtt_diff;
								ralp_sum += B_rtt;
							}
						}
					}
				}
			}
		}

		appStats.validLinkCount = rrl_count;
		if (rrl_count > 0)
			appStats.rrl = rrl_wrong / (double) rrl_count;
		if (narl_sum > 0)
			appStats.narl = narl_loss / narl_sum;
		if (ralp_sum > 0)
			appStats.ralp = ralp_loss / ralp_sum;
		return appStats;
	}

	// poor man's public struct
	class ApplicationStatistics {
		double rrl = 0;
		double narl = 0;
		double ralp = 0;
		int validLinkCount = 0;

		public ApplicationStatistics() {
		};
	}

	synchronized public String toString() {
		if (keepStatistics) {
			ApplicationStatistics appStats = computeApplicationStatistics();

			return new String("[sc=" + sys_coord + ",ac=" + app_coord + ",er="
					+ nf.format(error) + ",sys_re50="
					+ nf.format(running_sys_error.getPercentile(.5))
					+ ",sys_re95="
					+ nf.format(running_sys_error.getPercentile(.95))
					+ ",app_re50="
					+ nf.format(running_app_error.getPercentile(.5))
					+ ",app_re95="
					+ nf.format(running_app_error.getPercentile(.95))
					+ ",sys_dd=" + nf.format(running_sys_dd.get()) + ",app_dd="
					+ nf.format(running_app_dd.get()) + ",ne="
					+ nf.format(running_neighbors_used.get()) + ",rd="
					+ nf.format(running_relative_diff.get()) + ",sf="
					+ nf.format(running_sys_update_frequency.get()) + ",af="
					+ nf.format(running_app_update_frequency.get()) + ",rrl="
					+ nf.format(appStats.rrl) + ",narl="
					+ nf.format(appStats.narl) + ",ralp="
					+ nf.format(appStats.ralp) + ",age="
					+ getAge(System.currentTimeMillis()) + ",vl="
					+ nf.format(appStats.validLinkCount) +",gr=" 
          + nf.format(running_gravity.get())+",nn="
					+ nf.format(sys_coord.distanceTo(nearest_neighbor)) + "]");
		}
		else {
			return new String("[sc=" + sys_coord + ",ac=" + app_coord + ",er="
					+ nf.format(error) + ",nn="
					+ nf.format(sys_coord.distanceTo(nearest_neighbor)) + "]");
		}
	}

	synchronized public Hashtable<String, Double> getStatistics() {
		Hashtable<String, Double> stats = new Hashtable<String, Double>();
		for (int i = 0; i < num_dims; i++) {
			stats.put("sys_coord_" + i, sys_coord.coords[i]);
			stats.put("app_coord_" + i, sys_coord.coords[i]);
		}
		stats.put("er", error);
		stats.put("nn", sys_coord.distanceTo(nearest_neighbor));

		if (keepStatistics) {
			ApplicationStatistics appStats = computeApplicationStatistics();

			stats.put("rrl", appStats.rrl);
			stats.put("narl", appStats.narl);
			stats.put("ralp", appStats.ralp);
			stats.put("age", new Double (getAge(System.currentTimeMillis())));
			stats.put("vl", new Double(appStats.validLinkCount));
			stats.put("gr", running_gravity.get());
      
			stats.put("sys_re50", running_sys_error.getPercentile(.5));
			stats.put("sys_re95", running_sys_error.getPercentile(.95));
			stats.put("app_re50", running_app_error.getPercentile(.5));
			stats.put("app_re95", running_app_error.getPercentile(.95));

			stats.put("sys_dd", running_sys_dd.get());
			stats.put("app_dd", running_app_dd.get());

			stats.put("ne", running_neighbors_used.get());
			stats.put("rd", running_relative_diff.get());
			stats.put("sf", running_sys_update_frequency.get());
			stats.put("af", running_app_update_frequency.get());
		}
		return stats;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -