X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/9932a0c0d2c44e34633c97a827b2b04d615cb4e9..903d96f4c7e2f761608b4591faa573aab5891994:/examples/java/chord/Node.java diff --git a/examples/java/chord/Node.java b/examples/java/chord/Node.java index 93099237ae..6456b6b3c4 100644 --- a/examples/java/chord/Node.java +++ b/examples/java/chord/Node.java @@ -6,473 +6,410 @@ package chord; +import org.simgrid.msg.Msg; import org.simgrid.msg.Comm; import org.simgrid.msg.Host; -import org.simgrid.msg.Msg; -import org.simgrid.msg.MsgException; -import org.simgrid.msg.Process; import org.simgrid.msg.Task; +import org.simgrid.msg.Process; +import org.simgrid.msg.MsgException; import org.simgrid.msg.TimeoutException; -/** - * Node data - */ public class Node extends Process { - /** - * Node id - */ - protected int id; - /** - * Node mailbox - */ - protected String mailbox; - /** - * Predecessor id - */ - protected int predId; - /** - * Predecessor mailbox - */ - protected String predMailbox; - /** - * Index of the next finger to fix - */ - protected int nextFingerToFix; - /** - * Current communication - */ - protected Comm commReceive; - /** - * Last time I changed a finger or my predecessor - */ - protected double lastChangeDate; - /** - * Node fingers - */ - int fingers[]; - /** - * Constructor - */ - public Node(Host host, String name, String[] args) { - super(host,name,args); - } - @Override - public void main(String[] args) throws MsgException { - if (args.length != 2 && args.length != 4) { - Msg.info("You need to provide 2 or 4 arguments."); - return; - } - double initTime = Msg.getClock(); - int i; - boolean joinSuccess = false; - double deadline; - - double nextStabilizeDate = initTime + Common.PERIODIC_STABILIZE_DELAY; - double nextFixFingersDate = initTime + Common.PERIODIC_FIX_FINGERS_DELAY; - double nextCheckPredecessorDate = initTime + Common.PERIODIC_CHECK_PREDECESSOR_DELAY; - double nextLookupDate = initTime + Common.PERIODIC_LOOKUP_DELAY; - - id = Integer.valueOf(args[0]); - mailbox = Integer.toString(id); - - fingers = new int[Common.NB_BITS]; - for (i = 0; i < Common.NB_BITS; i++) { - fingers[i] = -1; - setFinger(i,this.id); - } - - //First node - if (args.length == 2) { - deadline = Integer.valueOf(args[1]); - create(); - joinSuccess = true; - } - else { - int knownId = Integer.valueOf(args[1]); - deadline = Integer.valueOf(args[3]); - //Msg.info("Hey! Let's join the system with the id " + id + "."); - - joinSuccess = join(knownId); - } - if (joinSuccess) { - double currentClock = Msg.getClock(); - while (currentClock < (initTime + deadline) && currentClock < Common.MAX_SIMULATION_TIME) { - if (commReceive == null) { - commReceive = Task.irecv(this.mailbox); - } - try { - if (!commReceive.test()) { - if (currentClock >= nextStabilizeDate) { - stabilize(); - nextStabilizeDate = Msg.getClock() + Common.PERIODIC_STABILIZE_DELAY; - } - else if (currentClock >= nextFixFingersDate) { - fixFingers(); - nextFixFingersDate = Msg.getClock() + Common.PERIODIC_FIX_FINGERS_DELAY; - } - else if (currentClock >= nextCheckPredecessorDate) { - this.checkPredecessor(); - nextCheckPredecessorDate = Msg.getClock() + Common.PERIODIC_CHECK_PREDECESSOR_DELAY; - } - else if (currentClock >= nextLookupDate) { - this.randomLookup(); - nextLookupDate = Msg.getClock() + Common.PERIODIC_LOOKUP_DELAY; - } - else { - waitFor(5); - } - currentClock = Msg.getClock(); - } - else { - handleTask(commReceive.getTask()); - currentClock = Msg.getClock(); - commReceive = null; - - } - } - catch (Exception e) { - currentClock = Msg.getClock(); - commReceive = null; - } - - } - leave(); - if (commReceive != null) { - commReceive = null; - } - } - else { - Msg.info("I couldn't join the ring"); - } - } - void handleTask(Task task) { - if (task instanceof FindSuccessorTask) { - FindSuccessorTask fTask = (FindSuccessorTask)task; - Msg.debug("Receiving a 'Find Successor' request from " + fTask.issuerHostName + " for id " + fTask.requestId); - // is my successor the successor? - if (isInInterval(fTask.requestId, this.id + 1, fingers[0])) { - //Msg.info("Send the request to " + fTask.answerTo + " with answer " + fingers[0]); - FindSuccessorAnswerTask answer = new FindSuccessorAnswerTask(getHost().getName(), mailbox, fingers[0]); - answer.dsend(fTask.answerTo); - } - else { - // otherwise, forward the request to the closest preceding finger in my table - int closest = closestPrecedingNode(fTask.requestId); - //Msg.info("Forward the request to " + closest); - fTask.dsend(Integer.toString(closest)); - } - } - else if (task instanceof GetPredecessorTask) { - GetPredecessorTask gTask = (GetPredecessorTask)(task); - Msg.debug("Receiving a 'Get Predecessor' request from " + gTask.issuerHostName); - GetPredecessorAnswerTask answer = new GetPredecessorAnswerTask(getHost().getName(), mailbox, predId); - answer.dsend(gTask.answerTo); - } - else if (task instanceof NotifyTask) { - NotifyTask nTask = (NotifyTask)task; - notify(nTask.requestId); - } - else { - Msg.debug("Ignoring unexpected task of type:" + task); - } - } - /** - * @brief Makes the current node quit the system - */ - void leave() { - Msg.debug("Well Guys! I Think it's time for me to quit ;)"); - quitNotify(1); //Notify my successor - quitNotify(-1); //Notify my predecessor. - // TODO ... - } - /** - * @brief Notifies the successor or the predecessor of the current node - * of the departure - * @param to 1 to notify the successor, -1 to notify the predecessor - */ - static void quitNotify( int to) { - //TODO - } - /** - * @brief Initializes the current node as the first one of the system. - */ - void create() { - Msg.debug("Create a new Chord ring..."); - setPredecessor(-1); - - } - /** - * Makes the current node join the ring, knowing the id of a node - * already in the ring - */ - boolean join(int knownId) { - Msg.info("Joining the ring with id " + this.id + " knowing node " + knownId); - setPredecessor(-1); - int successorId = remoteFindSuccessor(knownId, this.id); - if (successorId == -1) { - Msg.info("Cannot join the ring."); - } - else { - setFinger(0, successorId); - } - return successorId != -1; - } - - /** - * Sets the node predecessor - */ - void setPredecessor(int predecessorId) { - if (predecessorId != predId) { - predId = predecessorId; - if (predecessorId != -1) { - predMailbox = Integer.toString(predId); - } - lastChangeDate = Msg.getClock(); - } - } - /** - * @brief Asks another node its predecessor. - * @param askTo the node to ask to - * @return the id of its predecessor node, or -1 if the request failed - * (or if the node does not know its predecessor) - */ - int remoteGetPredecessor(int askTo) { - int predecessorId = -1; - boolean stop = false; - Msg.debug("Sending a 'Get Predecessor' request to " + askTo); - String mailboxTo = Integer.toString(askTo); - GetPredecessorTask sendTask = new GetPredecessorTask(getHost().getName(), this.mailbox); - try { - sendTask.send(mailboxTo, Common.TIMEOUT); - try { - do { - if (commReceive == null) { - commReceive = Task.irecv(this.mailbox); - } - commReceive.waitCompletion(Common.TIMEOUT); - Task taskReceived = commReceive.getTask(); - if (taskReceived instanceof GetPredecessorAnswerTask) { - predecessorId = ((GetPredecessorAnswerTask) taskReceived).answerId; - stop = true; - } - else { - handleTask(taskReceived); - } - commReceive = null; - } while (!stop); - - } - catch (MsgException e) { - commReceive = null; - stop = true; - } - } - catch (MsgException e) { - Msg.debug("Failed to send the Get Predecessor request"); - } - - - return predecessorId; - } - /** - * @brief Makes the current node find the successor node of an id. - * @param node the current node - * @param id the id to find - * @return the id of the successor node, or -1 if the request failed - */ - int findSuccessor(int id) { - if (isInInterval(id, this.id + 1, fingers[0])) { - return fingers[0]; - } - - int closest = this.closestPrecedingNode(id); - return remoteFindSuccessor(closest, id); - } - /** - * @brief Asks another node the successor node of an id. - */ - int remoteFindSuccessor(int askTo, int id) { - int successor = -1; - boolean stop = false; - String mailbox = Integer.toString(askTo); - Task sendTask = new FindSuccessorTask(getHost().getName(), this.mailbox, id); - Msg.debug("Sending a 'Find Successor' request to " + mailbox + " for id " + id); - try { - sendTask.send(mailbox, Common.TIMEOUT); - do { - if (commReceive == null) { - commReceive = Task.irecv(this.mailbox); - } - try { - commReceive.waitCompletion(Common.TIMEOUT); - Task task = commReceive.getTask(); - if (task instanceof FindSuccessorAnswerTask) { - //TODO: Check if this this our answer. - FindSuccessorAnswerTask fTask = (FindSuccessorAnswerTask) task; - stop = true; - successor = fTask.answerId; - } - else { - handleTask(task); - } - commReceive = null; - } - catch (TimeoutException e) { - stop = true; - commReceive = null; - } - } while (!stop); - } - catch (TimeoutException e) { - Msg.debug("Failed to send the 'Find Successor' request"); - } - catch (MsgException e) { - Msg.debug("Failed to receive Find Successor"); - } - - return successor; - - } - /** - * @brief This function is called periodically. It checks the immediate - * successor of the current node. - */ - void stabilize() { - Msg.debug("Stabilizing node"); - int candidateId; - int successorId = fingers[0]; - if (successorId != this.id){ - candidateId = remoteGetPredecessor(successorId); - } - else { - candidateId = predId; - } - //This node is a candidate to become my new successor - if (candidateId != -1 && isInInterval(candidateId, this.id + 1, successorId - 1)) { - setFinger(0, candidateId); - } - if (successorId != this.id) { - remoteNotify(successorId, this.id); - } - - } - /** - * \brief Notifies the current node that its predecessor may have changed. - * \param candidate_id the possible new predecessor - */ - void notify(int predecessorCandidateId) { - if (predId == -1 || isInInterval(predecessorCandidateId, predId + 1, this.id - 1 )) { - setPredecessor(predecessorCandidateId); - } - else { - //Don't have to change the predecessor. - } - } - /** - * \brief Notifies a remote node that its predecessor may have changed. - * \param notify_id id of the node to notify - * \param candidate_id the possible new predecessor - */ - void remoteNotify(int notifyId, int predecessorCandidateId) { - Msg.debug("Sending a 'Notify' request to " + notifyId); - Task sentTask = new NotifyTask(getHost().getName(), this.mailbox, predecessorCandidateId); - sentTask.dsend(Integer.toString(notifyId)); - } - /** - * \brief This function is called periodically. - * It refreshes the finger table of the current node. - */ - void fixFingers() { - Msg.debug("Fixing fingers"); - int i = this.nextFingerToFix; - int id = this.findSuccessor(this.id + (int)Math.pow(2,i)); //FIXME: SLOW - if (id != -1) { - if (id != fingers[i]) { - setFinger(i, id); - } - nextFingerToFix = (i + 1) % Common.NB_BITS; - } - } - /** - * \brief This function is called periodically. - * It checks whether the predecessor has failed - */ - void checkPredecessor() { - //TODO - } - /** - * \brief Performs a find successor request to a random id. - */ - void randomLookup() { - int id = 1337; - //Msg.info("Making a lookup request for id " + id); - findSuccessor(id); - } - - - - /** - * @brief Returns the closest preceding finger of an id - * with respect to the finger table of the current node. - * @param id the id to find - * \return the closest preceding finger of that id - */ - int closestPrecedingNode(int id) { - int i; - for (i = Common.NB_BITS - 1; i >= 0; i--) { - if (isInInterval(fingers[i], this.id + 1, id - 1)) { - return fingers[i]; - } - } - return this.id; - } - /** - * @brief Returns whether an id belongs to the interval [start, end]. - * - * The parameters are noramlized to make sure they are between 0 and nb_keys - 1). - * 1 belongs to [62, 3] - * 1 does not belong to [3, 62] - * 63 belongs to [62, 3] - * 63 does not belong to [3, 62] - * 24 belongs to [21, 29] - * 24 does not belong to [29, 21] - * - * \param id id to check - * \param start lower bound - * \param end upper bound - * \return a non-zero value if id in in [start, end] - */ - static boolean isInInterval(int id, int start, int end) { - id = normalize(id); - start = normalize(start); - end = normalize(end); - - // make sure end >= start and id >= start - if (end < start) { - end += Common.NB_KEYS; - } - if (id < start) { - id += Common.NB_KEYS; - } - return (id <= end); - - } - /** - * @brief Turns an id into an equivalent id in [0, nb_keys). - * @param id an id - * @return the corresponding normalized id - */ - static int normalize(int id) { - return id & (Common.NB_KEYS - 1); - } - /** - * \brief Sets a finger of the current node. - * \param finger_index index of the finger to set (0 to nb_bits - 1) - * \param id the id to set for this finger - */ - void setFinger(int fingerIndex, int id) { - if (id != fingers[fingerIndex]) { - fingers[fingerIndex] = id; - lastChangeDate = Msg.getClock(); - } - } + protected int id; + protected String mailbox; + protected int predId; + protected String predMailbox; + protected int nextFingerToFix; + protected Comm commReceive; + ///Last time I changed a finger or my predecessor + protected double lastChangeDate; + int fingers[]; + + public Node(Host host, String name, String[] args) { + super(host,name,args); + } + + @Override + public void main(String[] args) throws MsgException { + if (args.length != 2 && args.length != 4) { + Msg.info("You need to provide 2 or 4 arguments."); + return; + } + double initTime = Msg.getClock(); + int i; + boolean joinSuccess = false; + double deadline; + + double nextStabilizeDate = initTime + Common.PERIODIC_STABILIZE_DELAY; + double nextFixFingersDate = initTime + Common.PERIODIC_FIX_FINGERS_DELAY; + double nextCheckPredecessorDate = initTime + Common.PERIODIC_CHECK_PREDECESSOR_DELAY; + double nextLookupDate = initTime + Common.PERIODIC_LOOKUP_DELAY; + + id = Integer.valueOf(args[0]); + mailbox = Integer.toString(id); + + fingers = new int[Common.NB_BITS]; + for (i = 0; i < Common.NB_BITS; i++) { + fingers[i] = -1; + setFinger(i,this.id); + } + + //First node + if (args.length == 2) { + deadline = Integer.valueOf(args[1]); + create(); + joinSuccess = true; + } else { + int knownId = Integer.valueOf(args[1]); + deadline = Integer.valueOf(args[3]); + //Msg.info("Hey! Let's join the system with the id " + id + "."); + + joinSuccess = join(knownId); + } + if (joinSuccess) { + double currentClock = Msg.getClock(); + while (currentClock < (initTime + deadline) && currentClock < Common.MAX_SIMULATION_TIME) { + if (commReceive == null) { + commReceive = Task.irecv(this.mailbox); + } + try { + if (!commReceive.test()) { + if (currentClock >= nextStabilizeDate) { + stabilize(); + nextStabilizeDate = Msg.getClock() + Common.PERIODIC_STABILIZE_DELAY; + } else if (currentClock >= nextFixFingersDate) { + fixFingers(); + nextFixFingersDate = Msg.getClock() + Common.PERIODIC_FIX_FINGERS_DELAY; + } else if (currentClock >= nextCheckPredecessorDate) { + this.checkPredecessor(); + nextCheckPredecessorDate = Msg.getClock() + Common.PERIODIC_CHECK_PREDECESSOR_DELAY; + } else if (currentClock >= nextLookupDate) { + this.randomLookup(); + nextLookupDate = Msg.getClock() + Common.PERIODIC_LOOKUP_DELAY; + } else { + waitFor(5); + } + currentClock = Msg.getClock(); + } else { + handleTask(commReceive.getTask()); + currentClock = Msg.getClock(); + commReceive = null; + } + } + catch (Exception e) { + currentClock = Msg.getClock(); + commReceive = null; + } + } + leave(); + if (commReceive != null) { + commReceive = null; + } + } else { + Msg.info("I couldn't join the ring"); + } + } + + void handleTask(Task task) { + if (task instanceof FindSuccessorTask) { + FindSuccessorTask fTask = (FindSuccessorTask)task; + Msg.debug("Receiving a 'Find Successor' request from " + fTask.issuerHostName + " for id " + fTask.requestId); + // is my successor the successor? + if (isInInterval(fTask.requestId, this.id + 1, fingers[0])) { + //Msg.info("Send the request to " + fTask.answerTo + " with answer " + fingers[0]); + FindSuccessorAnswerTask answer = new FindSuccessorAnswerTask(getHost().getName(), mailbox, fingers[0]); + answer.dsend(fTask.answerTo); + } else { + // otherwise, forward the request to the closest preceding finger in my table + int closest = closestPrecedingNode(fTask.requestId); + //Msg.info("Forward the request to " + closest); + fTask.dsend(Integer.toString(closest)); + } + } else if (task instanceof GetPredecessorTask) { + GetPredecessorTask gTask = (GetPredecessorTask)(task); + Msg.debug("Receiving a 'Get Predecessor' request from " + gTask.issuerHostName); + GetPredecessorAnswerTask answer = new GetPredecessorAnswerTask(getHost().getName(), mailbox, predId); + answer.dsend(gTask.answerTo); + } else if (task instanceof NotifyTask) { + NotifyTask nTask = (NotifyTask)task; + notify(nTask.requestId); + } else { + Msg.debug("Ignoring unexpected task of type:" + task); + } + } + + void leave() { + Msg.debug("Well Guys! I Think it's time for me to quit ;)"); + quitNotify(1); //Notify my successor + quitNotify(-1); //Notify my predecessor. + } + + /** + * @brief Notifies the successor or the predecessor of the current node of the departure + * @param to 1 to notify the successor, -1 to notify the predecessor + */ + static void quitNotify( int to) { + //TODO + } + + /** + * @brief Initializes the current node as the first one of the system. + */ + void create() { + Msg.debug("Create a new Chord ring..."); + setPredecessor(-1); + } + + // Makes the current node join the ring, knowing the id of a node already in the ring + boolean join(int knownId) { + Msg.info("Joining the ring with id " + this.id + " knowing node " + knownId); + setPredecessor(-1); + int successorId = remoteFindSuccessor(knownId, this.id); + if (successorId == -1) { + Msg.info("Cannot join the ring."); + } else { + setFinger(0, successorId); + } + return successorId != -1; + } + + void setPredecessor(int predecessorId) { + if (predecessorId != predId) { + predId = predecessorId; + if (predecessorId != -1) { + predMailbox = Integer.toString(predId); + } + lastChangeDate = Msg.getClock(); + } + } + + /** + * @brief Asks another node its predecessor. + * @param askTo the node to ask to + * @return the id of its predecessor node, or -1 if the request failed(or if the node does not know its predecessor) + */ + int remoteGetPredecessor(int askTo) { + int predecessorId = -1; + boolean stop = false; + Msg.debug("Sending a 'Get Predecessor' request to " + askTo); + String mailboxTo = Integer.toString(askTo); + GetPredecessorTask sendTask = new GetPredecessorTask(getHost().getName(), this.mailbox); + try { + sendTask.send(mailboxTo, Common.TIMEOUT); + try { + do { + if (commReceive == null) { + commReceive = Task.irecv(this.mailbox); + } + commReceive.waitCompletion(Common.TIMEOUT); + Task taskReceived = commReceive.getTask(); + if (taskReceived instanceof GetPredecessorAnswerTask) { + predecessorId = ((GetPredecessorAnswerTask) taskReceived).answerId; + stop = true; + } else { + handleTask(taskReceived); + } + commReceive = null; + } while (!stop); + } + catch (MsgException e) { + commReceive = null; + stop = true; + } + } + catch (MsgException e) { + Msg.debug("Failed to send the Get Predecessor request"); + } + return predecessorId; + } + + /** + * @brief Makes the current node find the successor node of an id. + * @param node the current node + * @param id the id to find + * @return the id of the successor node, or -1 if the request failed + */ + int findSuccessor(int id) { + if (isInInterval(id, this.id + 1, fingers[0])) { + return fingers[0]; + } + + int closest = this.closestPrecedingNode(id); + return remoteFindSuccessor(closest, id); + } + + // Asks another node the successor node of an id. + int remoteFindSuccessor(int askTo, int id) { + int successor = -1; + boolean stop = false; + String mailbox = Integer.toString(askTo); + Task sendTask = new FindSuccessorTask(getHost().getName(), this.mailbox, id); + Msg.debug("Sending a 'Find Successor' request to " + mailbox + " for id " + id); + try { + sendTask.send(mailbox, Common.TIMEOUT); + do { + if (commReceive == null) { + commReceive = Task.irecv(this.mailbox); + } + try { + commReceive.waitCompletion(Common.TIMEOUT); + Task task = commReceive.getTask(); + if (task instanceof FindSuccessorAnswerTask) { + //TODO: Check if this this our answer. + FindSuccessorAnswerTask fTask = (FindSuccessorAnswerTask) task; + stop = true; + successor = fTask.answerId; + } else { + handleTask(task); + } + commReceive = null; + } + catch (TimeoutException e) { + stop = true; + commReceive = null; + } + } while (!stop); + } + catch (TimeoutException e) { + Msg.debug("Failed to send the 'Find Successor' request"); + } + catch (MsgException e) { + Msg.debug("Failed to receive Find Successor"); + } + + return successor; + } + + // This function is called periodically. It checks the immediate successor of the current node. + void stabilize() { + Msg.debug("Stabilizing node"); + int candidateId; + int successorId = fingers[0]; + if (successorId != this.id){ + candidateId = remoteGetPredecessor(successorId); + } else { + candidateId = predId; + } + //This node is a candidate to become my new successor + if (candidateId != -1 && isInInterval(candidateId, this.id + 1, successorId - 1)) { + setFinger(0, candidateId); + } + if (successorId != this.id) { + remoteNotify(successorId, this.id); + } + } + + /** + * @brief Notifies the current node that its predecessor may have changed. + * @param candidate_id the possible new predecessor + */ + void notify(int predecessorCandidateId) { + if (predId == -1 || isInInterval(predecessorCandidateId, predId + 1, this.id - 1 )) { + setPredecessor(predecessorCandidateId); + } + } + + /** + * @brief Notifies a remote node that its predecessor may have changed. + * @param notify_id id of the node to notify + * @param candidate_id the possible new predecessor + */ + void remoteNotify(int notifyId, int predecessorCandidateId) { + Msg.debug("Sending a 'Notify' request to " + notifyId); + Task sentTask = new NotifyTask(getHost().getName(), this.mailbox, predecessorCandidateId); + sentTask.dsend(Integer.toString(notifyId)); + } + + // This function is called periodically. + // It refreshes the finger table of the current node. + void fixFingers() { + Msg.debug("Fixing fingers"); + int i = this.nextFingerToFix; + int id = this.findSuccessor(this.id + (int)Math.pow(2,i)); //FIXME: SLOW + if (id != -1) { + if (id != fingers[i]) { + setFinger(i, id); + } + nextFingerToFix = (i + 1) % Common.NB_BITS; + } + } + + // This function is called periodically. + // It checks whether the predecessor has failed + void checkPredecessor() { + //TODO + } + + // Performs a find successor request to a random id. + void randomLookup() { + int id = 1337; + //Msg.info("Making a lookup request for id " + id); + findSuccessor(id); + } + + /** + * @brief Returns the closest preceding finger of an id with respect to the finger table of the current node. + * @param id the id to find + * @return the closest preceding finger of that id + */ + int closestPrecedingNode(int id) { + int i; + for (i = Common.NB_BITS - 1; i >= 0; i--) { + if (isInInterval(fingers[i], this.id + 1, id - 1)) { + return fingers[i]; + } + } + return this.id; + } + + /** + * @brief Returns whether an id belongs to the interval [start, end]. + * + * The parameters are noramlized to make sure they are between 0 and nb_keys - 1). + * 1 belongs to [62, 3] + * 1 does not belong to [3, 62] + * 63 belongs to [62, 3] + * 63 does not belong to [3, 62] + * 24 belongs to [21, 29] + * 24 does not belong to [29, 21] + * + * @param id id to check + * @param start lower bound + * @param end upper bound + * @return a non-zero value if id in in [start, end] + */ + static boolean isInInterval(int id, int start, int end) { + id = normalize(id); + start = normalize(start); + end = normalize(end); + + // make sure end >= start and id >= start + if (end < start) { + end += Common.NB_KEYS; + } + if (id < start) { + id += Common.NB_KEYS; + } + return (id <= end); + } + + /** + * @brief Turns an id into an equivalent id in [0, nb_keys). + * @param id an id + * @return the corresponding normalized id + */ + static int normalize(int id) { + return id & (Common.NB_KEYS - 1); + } + + /** + * @brief Sets a finger of the current node. + * @param finger_index index of the finger to set (0 to nb_bits - 1) + * @param id the id to set for this finger + */ + void setFinger(int fingerIndex, int id) { + if (id != fingers[fingerIndex]) { + fingers[fingerIndex] = id; + lastChangeDate = Msg.getClock(); + } + } }