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

📄 bttracker.java

📁 p2p仿真
💻 JAVA
字号:
/*
 * @(#)BTTracker.java	ver 1.2  6/20/2005
 *
 * Copyright 2005 Weishuai Yang (wyang@cs.binghamton.edu). 
 * All rights reserved.
 * 
 */

package gps.protocol.BT;
import gps.Simulator;
import gps.event.SimEvent;
import gps.protocol.Server;
import gps.protocol.BT.algorithm.BTAlgorithmPeerSelectionAtTracker;
import gps.protocol.BT.param.BTGetRequest;
import gps.protocol.BT.param.BTTorrent;
import gps.protocol.BT.param.BTTrackerResponse;
import gps.util.PowerLaw;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Random;
import java.util.logging.Logger;

/**
 * BT Tracker
 * 
 * @author  Weishuai Yang
 * @version 1.2,  6/20/2005
 *
 * In Bram Cohen's BT protocol, all logistical problems of file 
 * downloading are handled in the interactions between peers. 
 * Some information about upload and download rates is sent to 
 * the tracker, but that's just for statistics gathering. The 
 * tracker's responsibilities are strictly limited to helping 
 * peers find each other.
 *
 * The standard tracker algorithm is to return a random list of peers.
 *
 */
public class BTTracker extends Server {
	
	/**
	 * document records
	 */
	 
	private class BTDocRecord{
		public String mDocHashKey=null;
		public BTTorrent mTorrent=null;
		public LinkedHashSet mPeerList=null;
		public int mPopularity=0;
		BTDocRecord(String key, BTTorrent t){
			mDocHashKey=key;
			mTorrent=t;
			mPeerList=new LinkedHashSet();
			mPopularity=t.mPopularity;
		} 
		public boolean addPeer(BTPeer p){
		    return mPeerList.add(p);
		}
	}

	/**
	 * document records comparator
	 */
	private class DocRecordComparator implements Comparator
	{
		//sort the max at the head
		public int compare(Object o1, Object o2) {
			
			BTDocRecord r1=(BTDocRecord)docDB.get(o1);;
			BTDocRecord r2=(BTDocRecord)docDB.get(o2);;

			if(r1.mPopularity<r2.mPopularity)
				return 1;
			else if(r1.mPopularity>r2.mPopularity)
				return -1;
			else
				return 0;
		} 
	}


	
	/**
	 * peer records
	 */
	private class BTPeerRecord{
		public BTPeer mNode=null;
		public double mUploaded=0;
		public double mDownloaded=0;
		public double mInBandwidth=0;
		public double mOutBandwidth=0;
		BTPeerRecord(BTPeer n){
			mNode=n;
		}
	}


	
	/**
	 * collection of documents published on this tracker
	 */
	protected HashMap docDB=null;
	/**
	 * collection of peers downloading from this tracker, providing reference for selection peer list;
	 */
	protected HashMap peerDB=null;
	
	//peer selection algorithm
	private BTAlgorithmPeerSelectionAtTracker mPeerSelection=new BTAlgorithmPeerSelectionAtTracker(getID());
	
	//debug logger
	public static Logger mDebugLog = Logger.getLogger("Debug");
	public static PowerLaw mPowerLaw=new PowerLaw(new Random(Integer.parseInt(Simulator.getInstance().getProperties().getProperty("RandomSeed"))));

	
	/**
	 * Method Server initialization
	 */
	 
	public BTTracker() {}
	public BTTracker(int i) {
		super(i);
		docDB=new LinkedHashMap();
		peerDB=new LinkedHashMap();
	}
	
	public void reset(){
		super.reset();
		docDB.clear();
		peerDB.clear();
		mPowerLaw=new PowerLaw(new Random(Integer.parseInt(Simulator.getInstance().getProperties().getProperty("RandomSeed"))));
		}
	//do some BTTracker specific drawing on the graph
	public void agentDraw(Graphics g, int x, int y){
			g.setColor( Color.magenta );
			g.fillOval( x-5, y-5, 10, 10 );

			g.drawString("Tracker("+mAgentID+")",x-16,y-6 );
		
	}
	
	public boolean addTorrent(BTTorrent btpt){
		if(docDB.get(btpt.mDocHashKey)!=null){
			mDebugLog.warning("duplicated document hash key when adding torrent!");
			return false;
		}
		docDB.put(btpt.mDocHashKey, new BTDocRecord(btpt.mDocHashKey, btpt));
		return true;
	}
	
	public BTTorrent getTorrent(String key){
		if(docDB.isEmpty())
			return null;
			
		BTDocRecord btdr=(BTDocRecord)docDB.get(key);
		if(btdr!=null){
			return btdr.mTorrent;
		}
		return null;
	}
	
	public BTTorrent getRandomTorrent(HashMap db){
		
		if(docDB.isEmpty())
			return null;
		
		ArrayList tmpDB=new ArrayList(docDB.keySet());		
		tmpDB.removeAll(db.keySet());		
		if(tmpDB.isEmpty()) return null;
		
		//sort keys according to doc rank
		Collections.sort(tmpDB, new DocRecordComparator());
		
		BTDocRecord btdr=null;
		
		int index=mPowerLaw.zipf(tmpDB.size());
		btdr=(BTDocRecord)docDB.get(tmpDB.get(index));
		return btdr.mTorrent;
	}

	
	public HashSet getNodesAssociatedWithDoc(String docHashKey){
		if(docDB.isEmpty())
			return null;
		BTDocRecord btdr=(BTDocRecord)docDB.get(docHashKey);
		if(btdr!=null){
			return btdr.mPeerList;
		}
		return null;
	}
	
	public boolean addNodeAssociatedWithDoc(String docHashKey, BTPeer peer){
		/**
		 * for performance, the reference to peer rather than peer id 
		 * is directly added into hashmap
		 */
		
		if(getTorrent(docHashKey)==null){
			mDebugLog.warning("trying to add nodes associated with a document, but the torrent doesn't exist!");
			return false;
		}
			
		BTDocRecord btdr=(BTDocRecord)docDB.get(docHashKey);
		return btdr.addPeer(peer);
	}
	

	/**
	 * handles tracker level events
	 */
	public boolean handle(SimEvent e){
		if(super.handle(e))
		    return true;
		switch(e.getType()){
			case BTEvent.TRACKER_GET_REQUEST: 
				handleGetRequest((BTEvent)e);
				return true;
			default:
				mDebugLog.warning("received event "+e+" unprocessed");
		}
		return false;
	}
	
	public void handleGetRequest(BTEvent e){
		
		BTGetRequest btgr=(BTGetRequest)e.getAddParam();

		mDebugLog.info(""+mScheduler.getCurrent()+" "+this+" receiving request from " + 
						btgr.mBTPeer+" for "+btgr.mDocHashKey+" Event: "+
						btgr.eventToString()+" left: "+ btgr.mLeft);

		//TODO:update peer record in peerDB
		
		/**
		 * if it's completed or stopped, don't have to reply, 
		 * but may need to addjusted the node list sequense in peerDB
		 * such as sort according to finished length
		 * it's possible to let tracker remember each peer's status
		 *
		 * if it's started, but the left size is 0, that means this 
		 * is the original seed. don't have to reply either
		 */
		if(btgr.mEvent==BTGetRequest.COMPLETED){
		    addNodeAssociatedWithDoc(btgr.mDocHashKey, btgr.mBTPeer);
		    return;
		}
		if(btgr.mEvent==BTGetRequest.STOPPED)
			return;
		else if(btgr.mLeft==0){
			addNodeAssociatedWithDoc(btgr.mDocHashKey, btgr.mBTPeer);
			return;
		}

		BTPeer btp=(BTPeer)e.getParam();
		ArrayList nodeList=new ArrayList(getNodesAssociatedWithDoc(btgr.mDocHashKey));
		
		//elements in this nodeList are supposed to be unique since it's from a set
		BTTrackerResponse bttr=new BTTrackerResponse(btgr.mDocHashKey, mPeerSelection.selectPeers(nodeList));

		double t=mScheduler.getCurrent()+BT.getInstance().getDelayAgent(this,btp);

		//the event is to be handled by the session instance after the network delay
		BTEvent bte=new BTEvent(t, BTEvent.SESSION_TRACKER_RESPONSE, btgr.mBTSession, this);
		//first param is the tracker object, additional param is tracker response		
		bte.setAddParam(bttr);	
		mScheduler.enqueue(bte);
	
		//add the requesting peer into database, it's possible the nodelist including 
		//the new peer is retrieved by somebody else before the new peer receive the 
		//reply, but it does no harm.
		addNodeAssociatedWithDoc(btgr.mDocHashKey, btp);
	}
	
	
	public String toString(){
		return "BTTracker("+mAgentID+")";
	}
	
}

⌨️ 快捷键说明

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