📄 chordnode.java
字号:
package planet.chord;
import java.math.BigInteger;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import planet.chord.message.BroadcastMessage;
import planet.chord.message.IdMessage;
import planet.chord.message.NodeMessage;
import planet.chord.message.SuccListMessage;
import planet.commonapi.EndPoint;
import planet.commonapi.Id;
import planet.commonapi.Message;
import planet.commonapi.Node;
import planet.commonapi.NodeHandle;
import planet.commonapi.RouteMessage;
import planet.commonapi.exception.InitializationException;
import planet.commonapi.results.ResultsConstraint;
import planet.commonapi.results.ResultsEdge;
import planet.generic.commonapi.factory.GenericFactory;
import planet.simulate.Globals;
import planet.simulate.Logger;
import planet.simulate.MessageListener;
import planet.simulate.Results;
import planet.util.Properties;
import planet.util.Queue;
import planet.util.timer.TimerTaskImpl;
/**
*
* A Chord node is single entity in the chord network. It extends of the class
* NodeImpl and specializes following the lookup Chord protocol. Moreover, the
* stabilization implementation, producing the periodic stabilition events.
*
* @author <a href="mailto:Ruben.Mondejar@estudiants.urv.es">Ruben Mondejar</a>
* @author <a href="mailto:cpairot@etse.urv.es">Carles Pairot</a>
* @author <a href="mailto:jordi.pujol@estudiants.urv.es">Jordi Pujol</a>
* @author <a href="mailto:marc.sanchez@estudiants.urv.es">Marc Sanchez</a>
*
*/
public class ChordNode extends planet.generic.commonapi.NodeImpl {
/* ****************** CONSTANTS FOR MODE OF ROUTEMESSAGE *******/
/**
* Mode value: Defines the start of communication that requires
* response (REPLY).
*/
public final static int REQUEST = 0;
/**
* Mode value: Defines the response of a communication.
*/
public final static int REPLY = 1;
/**
* Mode value: Defines a message's mode that requires only
* communication on one way.
*/
public final static int REFRESH = 2;
/* END ****************** CONSTANTS FOR MODE OF ROUTEMESSAGE *******/
/* ****************** CONSTANTS FOR TYPE OF ROUTEMESSAGE *******/
/**
* Type value: First message that is send by any node to get its
* inmediate successor.
*/
public final static int FIND_SUCC = 0;
/**
* Type value: Start a set of messages that permits to find the
* inmediate successor of any new incoming node to the network.
*/
public final static int FIND_PRE = 1;
/**
* Type value: Informs to the node that receives this message its
* new inmediate successor.
*/
public final static int SET_SUCC = 2;
/**
* Type value: Informs to the node that receive this message its
* new inmediate predecessor. This type forces to node to change its
* predecessor.
*/
public final static int SET_PRE = 3;
/**
* Type value: Start a set of messages that permits to find the
* inmediate node in charge of any key.
*/
public final static int GET_PRE = 4;
/**
* Type value: Informs to the node that receive this message its
* inmediate predecessor. This type permits to the node to evaluate
* if this notification informs really of the predecessor of the node.
*/
public final static int NOTIFY = 5;
/**
* Type value: Start a set of messages that permits the harvesting of
* successors of the node that send originally this message.
*/
public final static int SUCC_LIST = 6;
/**
* Type value: The message with this type identifies a broadcast message.
*/
public final static int BROADCAST = 7;
/**
* Type value: It identifies that this message contains an application
* level Message.
*/
public final static int DATA = 8;
/* END ****************** CONSTANTS FOR TYPE OF ROUTEMESSAGE *******/
/* ****************** CONSTANTS FOR TYPE/MODE OF ROUTEMESSAGE *******/
/**
* This String contains a string representation of each of types
* and modes values of the RouteMessage.
*/
public final static String[] TYPES = {
"FIND_SUCC", "FIND_PRE", "SET_SUCC", "SET_PRE", "GET_PRE", "NOTIFY",
"SUCC_LIST", "BROADCAST", "DATA"};
/**
* This String contains a string representation of each mode
* value of the RouteMessage.
*/
public final static String[] MODES = {"REQUEST", "REPLY", "REFRESH" };
/* END ****************** CONSTANTS FOR TYPE/MODE OF ROUTEMESSAGE *******/
/**
* Return a RouteMessage with the specified values. If there are RouteMessages free,
* just build a new one. For generate new instances of RouteMessage will be used
* the implementation class that appears in properties file.
* @param appId Application Id name.
* @param from Source node.
* @param to Destination node.
* @param nextHop NextHop node.
* @return A RouteMessage with the specified values.
*/
public static RouteMessage getDataMessage(String appId,
NodeHandle from, NodeHandle to, NodeHandle nextHop, Message msg)
throws InitializationException {
RouteMessage toReturn = GenericFactory.getMessage(GenericFactory.generateKey(), from, to, nextHop, null, DATA, REQUEST, appId);
toReturn.setMessage(msg);
return toReturn;
}
/**
* Return a RouteMessage with the specified values. If there are RouteMessages free,
* just build a new one. For generate new instances of RouteMessage will be used
* the implementation class that appears in properties file.
* @param appId Application Id name.
* @param from Source node.
* @param to Destination node.
* @param nextHop NextHop node.
* @return A RouteMessage with the specified values.
*/
public static RouteMessage getBroadcastMessage(String appId,
NodeHandle from, NodeHandle to, NodeHandle nextHop, Message msg)
throws InitializationException {
RouteMessage toReturn = GenericFactory.getMessage("",from,to,nextHop,null,BROADCAST,REFRESH,appId);
toReturn.setMessage(msg);
return toReturn;
}
/**
* Maximum Id value with the current configuration.
*/
protected Id MAX;
/**
* Index to use within stabilization process onto the finger table.
*/
protected int nullPointers = 0;
/**
* Detect the number of finger changes only on one simulation step.
*/
protected int fingerChanges = 0;
/**
* Number of simulation steps without changes on finger table.
*/
protected int stabRate = 0;
/**
* Number of bits per key to use as current configuration.
*/
protected int bitsPerKey = ((ChordProperties)Properties.overlayPropertiesInstance).bitsPerKey;
/**
* Number of simulation steps without changes on finger table, that
* represents a real stabilization of this node.
*/
protected int realStabilizationRate =
((ChordProperties)Properties.overlayPropertiesInstance).stabilizeSteps *
((ChordProperties)Properties.overlayPropertiesInstance).bitsPerKey * 2;
/**
* The current predecessor in the Chord ring.
*/
protected NodeHandle predecessor;
/**
* Flag that shows when this node has failed.
*/
protected boolean hasFailed; // For Failed Case
/**
* Flag that shows when this node has leaved.
*/
protected boolean hasLeaved; // For Leaved Case
/** Shows when has been received the GET_PRE response, requested on the stabilize() method to find the successor. */
protected boolean hasReceivedSucc;
/**
* Flag that optimizes the number of invokations of <b>closestPrecedingFinger</b>
* method.
*/
private boolean cpfFound;
/**
* Current finger table.
*/
public NodeHandle[] finger;
/**
* The starting indices for the finger table (as Finger[k].start).
*/
public Id[] start;
/**
* Current successor list.
*/
public Vector succList;
/**
* Temporal use in Common API methods.
*/
protected Vector auxCAPI;
public Id deux;
protected NodeHandle[] temp;
/**
* Constructor, create a new BadChordNode instance with this node Id
*/
public ChordNode() throws InitializationException {
super();
deux = GenericFactory.buildId(ChordId.TWO_CHORD);
finger = new NodeHandle[bitsPerKey];
start = new Id[bitsPerKey];
temp = new NodeHandle[3];
succList = new Vector(((ChordProperties)Properties.overlayPropertiesInstance).succListMax+2);
hasLeaved = false;
hasFailed = false;
hasReceivedSucc = true; //permits the send
//add stabilize timer
setTimer(new StabilizeTask(), ((ChordProperties)Properties.overlayPropertiesInstance).stabilizeSteps,
((ChordProperties)Properties.overlayPropertiesInstance).stabilizeSteps);
// add fix finger timer
setTimer(new FixFingerTask(), ((ChordProperties)Properties.overlayPropertiesInstance).fixFingerSteps,
((ChordProperties)Properties.overlayPropertiesInstance).fixFingerSteps);
}
/**
* Sets the predecessor node
*
* @param handle
* NodeHandle of the predecessor
*/
public void setPred(NodeHandle handle) {
predecessor = handle;
}
/**
* Sets the successor node
*
* @param handle
* NodeHandle of the successor
*/
public void setSucc(NodeHandle handle) {
finger[0] = handle;
//always the successor at the first position
if (succList.size()>0)
succList.add(0,handle);
else
succList.add(handle);
}
/**
* Deletes all NodeHandles that exceeds the required size of successor list.
*/
protected void cleanSuccList()
{
int succListMax = ((ChordProperties)Properties.overlayPropertiesInstance).succListMax;
for (int i=succList.size(); i > succListMax; i--)
{
succList.remove(i-1);
}
}
/**
* Returns the NodeHandle of the present identification of the precursor of the
* node
*
* @return predeccesor NodeHandle
*/
public NodeHandle getPred() {
return predecessor;
}
/**
* Returns the NodeHandle of the present identification of the successor of the
* node
*
* @return predeccesor NodeHandle
*/
public NodeHandle getSucc() {
return finger[0];
}
/**
* Returns the successor list of the present node
*
* @param max
* number of the elements to return
* @return successor list Vector
*/
public Vector getSuccList(int max) {
Iterator it = succList.iterator();
Vector sl = new Vector();
int i = 0;
while (it.hasNext() && i < max)
sl.add(it.next());
return sl;
}
/**
* Clears the counter of the finger table changes
*/
protected void clearFingerChanges() {
fingerChanges = 0;
}
/**
* Returns the count of the finger table changes
*
* @return finger_changes int counter
*/
protected int getFingerChanges() {
return fingerChanges;
}
/**
* Sets a especific finger of the finger table
* @param pos position of the finger
* @param handle new NodeHandle to change
*/
protected void setFinger(int pos, NodeHandle handle) {
if (finger[pos] == null || !finger[pos].equals(handle)) {
fingerChanges++;
finger[pos] = handle;
}
}
public Hashtable getInfo() {
Hashtable info = new Hashtable();
info.put("predecessor", predecessor);
info.put("finger", finger);
info.put("start", start);
info.put("succ_list", succList);
return info;
}
/**
* Shows for System.out all information of the node, including finger
* table.
*/
public void printNode() {
System.out.println("######\nNode: " + getId());
System.out.println("Finger table:");
for (int i = 0; i < finger.length; i++) {
if (finger[i] != null)
System.out.println(start[i] + " : " + finger[i]);
else
System.out.println(" finger [" + i + "] == null ");
System.out.println("-----------");
}
System.out.println("Predecessor: " + predecessor);
System.out.println("Succ-List: " + succList);
System.out.println("###### END OF NODE\n");
}
/**
* Shows for System.out only the owner Id, its predecessor and successor.
*/
public void prettyPrintNode() {
System.out.println("######\nNode: " + getId());
System.out.println("Successor: " + finger[0]);
System.out.println("Predecessor: " + predecessor);
System.out.println("###### END OF NODE\n");
}
/**
* Finds the successor of a node. If the result if null because the
* information its not contain in the finger table, it generate a request
* message and the response message content the real result
*
* @param handle
* NodeHandle of the one node
* @return successor Id of the node successor
*/
protected NodeHandle findSuccessor(NodeHandle handle) {
if (predecessor != null && handle.getId().betweenE(predecessor.getId(), this.id)) {
return this.nodeHandle;
} else {
return findPredecessor(handle);
}
}
/**
* Finds the predecessor of a node. If the result if null because the
* information its not contain in the finger table, it generate a request
* message and the response message content the real result
*
* @param handle
* NodeHandle of the one node
* @return successor NodeHandle of the node predecessor
*/
protected NodeHandle findPredecessor(NodeHandle handle) {
if (handle.getId().equals(this.id)) {
return this.nodeHandle; //return predecessor.successor();
} else if (finger[0] != null && handle.getId().betweenE(this.id, finger[0].getId())) {
return finger[0];
} else {
return null;
}
}
/**
* Finds the closest preceding finger of a node
*
* @param id
* Id of the one node
* @return successor NodeHandle of the node successor
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -