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

📄 chordnode.java

📁 p2p仿真器。开发者可以工作在覆盖层中进行创造和测试逻辑算法或者创建和测试新的服务。PlanetSim还可以将仿真代码平稳转换为在Internet上的实验代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
	/* ************************* MESSAGE LISTENERS ********************/
	
	public class LookupListener implements MessageListener {
		private ChordNode node;
		private Id key;
		public LookupListener(ChordNode node, Id key) {
			this.node = node;
			this.key = key;
		}
		public void onMessage(RouteMessage msg) {
			NodeHandle own = ((NodeMessage) msg.getMessage()).getNode();
			Results.addLookup(key, own.getId());
		}
	}
	
	public class GetPreListener implements MessageListener {
		private ChordNode node;
		public GetPreListener(ChordNode node) {
			this.node = node;
		}
		public void onMessage(RouteMessage msg) {
			// continues stabilize()
		    node.hasReceivedSucc = true;
			NodeHandle msgNh = ((NodeMessage) msg.getMessage()).getNode();
			if (msgNh != null && msgNh.getId().between(node.getId(), node.getSucc().getId())) {
				node.setSucc(msgNh);
			}
			//send notify
            node.sendMessage(msg,null,node.getLocalHandle(),node.getSucc(),node.getSucc(),NOTIFY,REFRESH,msg.getMessage());
		}
	}
	
	
	public class FindSuccListener implements MessageListener {
		private ChordNode node;
		public FindSuccListener(ChordNode node) {
			this.node = node;
		}
		public void onMessage(RouteMessage msg) {
			//continues join()
			NodeHandle succ = ((NodeMessage) msg.getMessage()).getNode();
			node.setSucc(succ);
			GenericFactory.freeMessage(msg);
		}
	}
	
	
	public class FindPredListener implements MessageListener {
		/** Flag that shows that this listener type is for a fix finger purposes. */
		public static final int FIND_PRED_FOR_FIX_FINGER = 1;
		/** Flag that shows that this listener type is for a response on a remote join. */
		public static final int FIND_PRED_FOR_JOIN       = 2;
		/** Reference to the local node. */
		private ChordNode node;
		/** Purpose for this listener. */
		private int listenerPurpose = 0;
		/** The finger position to be set on a FIND_PRED_FOR_FIX_FINGER case. */
		private int fixFingerPosition = 0;
		/** The message key to be set to the RouteMessage on a FIND_PRED_FOR_JOIN case. */
		private String keyForJoinMessage = null;
		
		/**
		 * Builds a FindPredListener for a fix finger purposes.
		 * @param localNode The local Node.
		 * @param fingerPosition The position of the finger to be updated.
		 */
		public FindPredListener(ChordNode localNode, int fingerPosition)
		{
			listenerPurpose = FIND_PRED_FOR_FIX_FINGER;
			node = localNode;
			fixFingerPosition = fingerPosition;
		}
		
		/**
		 * Builds a FindPredListener for a join message response.
		 * @param localNode The local node.
		 * @param msgKey The RouteMessage key for the response.
		 */
		public FindPredListener(ChordNode localNode, String msgKey)
		{
			listenerPurpose = FIND_PRED_FOR_JOIN;
			node = localNode;
			keyForJoinMessage = new String(msgKey); //make a copy of the String!!
		}

		/**
		 * Make a different action using the actual listener purpose.
		 * In a first case, it updates the finger position with the incoming information.
		 * In a second case, it makes a response for a remote join message. 
		 */
		public void onMessage(RouteMessage msg) {
			//n.id from --> n of n.find_successor(n)
			//n1.id to --> n1 of n1.find_successor(n)
			switch(listenerPurpose)
			{
			case FIND_PRED_FOR_FIX_FINGER:
				node.setFinger(fixFingerPosition, ((NodeMessage) msg.getMessage()).getNode());
				GenericFactory.freeMessage(msg);
				break;
			case FIND_PRED_FOR_JOIN:
                node.sendMessage(msg,keyForJoinMessage,msg.getDestination(),msg.getSource(),msg.getSource(),FIND_SUCC,REPLY,msg.getMessage());
				break;
			}
		}
	}
	
	/**
	 * Sets alive flag to false.
	 * @see planet.commonapi.Node#fail()
	 */
	public void fail() {
		this.hasFailed = true;
		this.nodeHandle.setAlive(false);
	}
	
	/**
	 * Overwrites the outMessages to evaluates the internal flag
	 * <b>hasFailed</b> for not to deliver the outgoing queue of
	 * messages. This implementation is only for Chord overlay.
	 * @see planet.commonapi.Node#outMessages()
	 * @see planet.generic.commonapi.NodeImpl#outMessages()
	 * @return null if the node has failed. The outgoing queue
	 * if the node is alive or just has leaved at this simulation step.
	 */
	public Queue outMessages() {
		if (hasFailed) return null;
		return super.outMessages();
	}

	/* END ************************* MESSAGE LISTENERS ********************/
	
	/* ***************** TIMER TASKS *************************************/
	
	/**
	 * Simple TimerTask that invoke stabilize() Node method.
	 * 
	 * @author <a href="mailto: jordi.pujol@estudiants.urv.es">Jordi Pujol </a>
	 *         Date: 07/05/2004
	 */
	public class StabilizeTask extends TimerTaskImpl {
		/**
		 * Initialize this StabilizeTask.
		 */
		public StabilizeTask() {
			super(true);
		}
		/**
		 * Invoke stabilize() method of Node.
		 * 
		 * @see java.util.TimerTask#run()
		 */
		public void run() {
			super.run();
			if (!isFinished()) {
				if (finger[0] != null) {
					stabilize();
				}
			}
		}
		/**
		 * Shows the name of the TimerTask, showing if is periodic.
		 * 
		 * @see java.lang.Object#toString()
		 * @return The name of the TimerTask
		 */
		public String toString() {
			return "StabilizeTask: periodic";
		}
	}
	
	/**
	 * Simple TimerTask that invoke fix_fingers() Node method.
	 * 
	 * @author <a href="mailto: jordi.pujol@estudiants.urv.es">Jordi Pujol </a>
	 *         Date: 07/05/2004
	 */
	public class FixFingerTask extends TimerTaskImpl {
		/**
		 * Initialize this StabilizeTask.
		 */
		public FixFingerTask() {
			super(true);
		}
		/**
		 * Invoke stabilize() method of Node.
		 * 
		 * @see java.util.TimerTask#run()
		 */
		public void run() {
			super.run();
			if (!isFinished()) {
				fixFingers();
			}
		}
		/**
		 * Shows the name of the TimerTask, showing if is periodic.
		 * 
		 * @see java.lang.Object#toString()
		 * @return The name of the TimerTask
		 */
		public String toString() {
			return "FixFingerTask: periodic";
		}
	}
	
	/* END ************************ TIMER TASKS ****************************/
	
	/* BEGIN **************************** GML  ****************************/
    /**
     * This method is a callback method used to collect all edges of a graph 
     * according to <b>resultName</b> format.
     * @param resultName Result type name to use.
     * @param edgeCollection Edge collection where to put in all produced ResultEdges.
     * @param constraint ResultsConstraint for edge selection
     */
    public void buildEdges(String resultName, Collection edgeCollection, ResultsConstraint constraint) {
		if (edgeCollection == null || constraint == null) return;
		
		Iterator it;
		
		it = succList.iterator();
		addEdges(resultName, it, constraint, edgeCollection, "#0000FF");
		
        int bitsPerKey = ((ChordProperties)Properties.overlayPropertiesInstance).bitsPerKey;
        Id lastId = null;
		for (int i = 0; i < bitsPerKey; i++) {
            //am I?
			if (finger[i].getId().equals(getId())) continue;
            //is a repeated node?
            if (lastId != null && finger[i].getId().equals(lastId)) continue;
            lastId = finger[i].getId();
			try {
				ResultsEdge e = GenericFactory.buildEdge(resultName, getId(),lastId, false, "#FF0000");
				if (constraint.isACompliantEdge(e)) edgeCollection.add(e);
			} catch (InitializationException e)
			{ e.printStackTrace();}
		}
	}
	
	/* END ************************ GML ****************************/
	
	
	/* ************************ COMMON API METHODS ****************************/

	/**
	 * Returns a list of nodes that can be used as next hops on a route
	 * towards key. If is safe, the expected fraction of faulty nodes in the
	 * list is guaranteed to be no higher than the fraction of
	 * faulty nodes in the overlay. 
	 * <br><br>
	 * In Chord, must be returns the <b>max</b> successors of <b>key</b> in
	 * the node's location table.
	 * @param key Target key
	 * @param max Number of next hops.
	 * @param safe This flag is not consulted.
	 * @return Until a maximum of max nodes to use as next hop, or null if 
	 * key is not in range of node's location table.
	 * @see planet.commonapi.Node#localLookup(planet.commonapi.Id, int, boolean)
	 */
	public Vector localLookup(Id key, int max, boolean safe) {
		Vector nodes = new Vector(); //to permit only one instance of each one
		int first = firstLocalLookup(key);
		//if key is not in finger table range.
		if (first==-1) return null;
		for (int i=first; i<((ChordProperties)Properties.overlayPropertiesInstance).bitsPerKey && nodes.size()<max; i++)
				nodes.add(finger[i]);
		return nodes;
	}
	
	/**
	 * Detects de first position that key is in range of some position of 
	 * finger table.
	 * @param key Id to find the first position of finger table is responsible.
	 * @return -1 if the key is not in range of the finger table, or some value
	 * between 0..Properties.bitsKey-1
	 */
	public int firstLocalLookup(Id key) {
		int i;
		if (key.compareTo(start[((ChordProperties)Properties.overlayPropertiesInstance).bitsPerKey-1])>0 ||
			key.compareTo(start[0])<0) return -1;
		for (i=((ChordProperties)Properties.overlayPropertiesInstance).bitsPerKey-1;i>=0 && key.compareTo(this.start[i])<=0; i++);
		return i; 
	}
	
	
	/**
	 * @see planet.commonapi.Node#neighborSet(int)
	 * Obtains an unordered list of up to max nodes that are neighbors 
	 * of the local node.
	 * @param max Maximum of nodes to return.
	 * @return Neighbor nodes. At the first position appears the predecessor node,
	 * and following the rest of successors nodes.
	 */
	public Vector neighborSet(int max) {
		int maxIndex = Math.min(max-1,succList.size());
		auxCAPI=this.getSuccList(maxIndex);
		auxCAPI.add(0,predecessor);
		return auxCAPI;
	}
	
	/**
	 * @see planet.commonapi.Node#range(planet.commonapi.NodeHandle, planet.commonapi.Id, planet.commonapi.Id, planet.commonapi.Id)
	 * This operation provides information about ranges of keys for
	 * which the <b>node</b> is currently a root. Returns false if
	 * the range could not be determined, true otherwise.
	 * <br><br>
	 * It is an error to query the range of a node not present in
	 * the neighbor set.
	 * <br><br>
	 * The [leftKey,rightKey] denotes the inclusive range of key values.
	 * @param node Node that is currently a root of some range of keys.
	 * @param rank Number of keys that is root the node (rank=rightKey-leftKey).
	 * @param leftKey The value that appears in the invokation is the candidate left
	 * key of the range. It may be modified to reflect the correct left margin
	 * once invokation has finished.
	 * @param rightKey Shows once the invokation has finished the left margin of
	 * the range. It must be initialized to 0 (zero) before this method could be invoked.
	 * @return true if the range could be determined; false otherwise, including
	 * the case of node is not present in the neighbor set returned by neighborSet().
	 * If false is returned, the leftKey and rightKey are not corrects.
	 */
	public boolean range(NodeHandle node, Id rank, Id leftKey, Id rightKey) {
		/* Must be an error if 'node' is not in array returned by neighborSet()
		 * method. In this case, evaluates the best case of neighborSet()
		 * invokation, using all elements in successor list. */
		if (!node.equals(predecessor) && !succList.contains(node)) 
			return false;
		
		try {
			/* Correct the value for 'leftKey'. Only in the case in which the
			 * 'leftkey' is minor than or equals to predecessor for the actual
			 * node. */
			if (leftKey.compareTo(predecessor.getId())<=0) {
				leftKey.add(GenericFactory.buildId(ChordId.ONE_CHORD));
			
			}
		
			/* Sets the value of 'rightKey' to the correct maximum value.
			 * That is, rightKey = min(leftKey+rank,node), once the leftKey 
			 * already has been corrected. */
			rightKey.add(leftKey);
			rightKey.add(rank);
			
			//verify if the sum leaves rank
			BigInteger max = new BigInteger("2").pow(((ChordProperties)Properties.overlayPropertiesInstance).bitsPerKey);
			Id maxId = GenericFactory.buildId(max);
			if (maxId.compareTo(rightKey)<=0) {
				rightKey.subtract(maxId);
			}
			//sets the correct value
			if (rightKey.compareTo(node)>0) {
				rightKey.setValue(node);
			}
		} catch (InitializationException e) {
			// because the value cannot be set, return false
			return false;
		}
		return true;
	}
	
	/**
	 * @see planet.commonapi.Node#replicaSet(planet.commonapi.Id, int)
	 * Returns the replica node set.
	 * The number of successor list is defined in the context.
	 * @param key Key from which obtain the replica set.
	 * @param maxRank Number of nodes in replica set.
	 * @return Up to maxRank nodes as replica set.
	 */
	public Vector replicaSet(Id key, int maxRank) {
		if (!key.betweenE(getPred().getId(),getId())) return null;
		if (!(maxRank>=1)) return null;
		auxCAPI = new Vector();
		int maxIndex = Math.min(maxRank-1,succList.size());
		if (maxIndex>0) { 
			auxCAPI.addAll(getSuccList(maxIndex));
		}
		auxCAPI.add(0,nodeHandle);
		return auxCAPI;
	}
	
	/* END ************************ COMMON API METHODS ****************************/
	
	
	/**
	 * Gets all node connections to other nodes as its NodeHandles. The order of NodeHandles
	 * is unexpected. 
	 * @return A set with all connections as NodeHandles.
	 */
	public Set getAllLinks() {
	    HashSet conns = new HashSet();
	    
	    //recollect all fingers not null
	    for (int i=0; i<finger.length; i++)
	    {
            conns.add(finger[i]);
	    }
	    //recollect the predecessor
        conns.add(getPred());
	    
	    //recollect the successors
	    conns.addAll(succList);
	    
	    //remove the null element if exists
	    conns.remove(null);
	    
	    return conns;
	}
	
	/** 
	 * Returns the NodeHandle closest to <b>id</b>.
	 * @param id Id to find.
	 * @return The NodeHandle closest to <b>id</b>.
	 */
	public NodeHandle getClosestNodeHandle(Id id)
	{
	    return closestPrecedingFinger(id);
	}
    
    
    /**
     * Sets the new Id for this node.
     * @param newId The new Id.
     * @return The same instance, after it has been updated.
     * @see planet.commonapi.Node#setValues(planet.commonapi.Id)
     */
    public Node setValues(Id newId) throws InitializationException {
        super.setValues(newId);
        for (int i = 0; i < bitsPerKey; i++) {
            start[i] = (id.add(deux.shift(-(i - 1), 0)));
        }
        return this;
    }
}

⌨️ 快捷键说明

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