📄 chordnode.java
字号:
/* ************************* 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 + -