Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
new s4u example: chord
authorFrederic Suter <frederic.suter@cc.in2p3.fr>
Wed, 5 Apr 2017 16:56:53 +0000 (18:56 +0200)
committerFrederic Suter <frederic.suter@cc.in2p3.fr>
Wed, 5 Apr 2017 17:02:49 +0000 (19:02 +0200)
leaking a lot, not perfect, but hopefully better than the C version

examples/s4u/CMakeLists.txt
examples/s4u/dht-chord/node.cpp [new file with mode: 0644]
examples/s4u/dht-chord/s4u_dht-chord.cpp [new file with mode: 0644]
examples/s4u/dht-chord/s4u_dht-chord.hpp [new file with mode: 0644]
examples/s4u/dht-chord/s4u_dht-chord.tesh [new file with mode: 0644]
examples/s4u/dht-chord/s4u_dht-chord_d.xml [new file with mode: 0644]

index 5a6183f..088ef9e 100644 (file)
@@ -8,13 +8,23 @@ foreach (example actions-comm actions-storage actor-create actor-kill actor-migr
   set(examples_src  ${examples_src}  ${CMAKE_CURRENT_SOURCE_DIR}/${example}/s4u_${example}.cpp)
 endforeach()
 
-set(examples_src  ${examples_src}                                     PARENT_SCOPE)
-set(tesh_files    ${tesh_files}                                       PARENT_SCOPE)
+# CHORD EXAMPLE
+add_executable       (s4u_dht-chord dht-chord/s4u_dht-chord.cpp dht-chord/node.cpp)
+target_link_libraries(s4u_dht-chord simgrid)
+set_target_properties(s4u_dht-chord PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dht-chord)
+foreach (file s4u_dht-chord node)
+  set(examples_src  ${examples_src}  ${CMAKE_CURRENT_SOURCE_DIR}/dht-chord/${file}.cpp)
+endforeach()
+set(examples_src  ${examples_src}  ${CMAKE_CURRENT_SOURCE_DIR}/dht-chord/s4u_dht-chord.hpp)
+
+set(examples_src  ${examples_src}                                                                          PARENT_SCOPE)
+set(tesh_files    ${tesh_files}   ${CMAKE_CURRENT_SOURCE_DIR}/dht-chord/s4u_dht-chord.tesh                 PARENT_SCOPE)
 set(xml_files     ${xml_files}    ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/s4u_actions-comm_split_d.xml
                                   ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/s4u_actions-comm_d.xml
                                   ${CMAKE_CURRENT_SOURCE_DIR}/actions-storage/s4u_actions-storage_d.xml
                                   ${CMAKE_CURRENT_SOURCE_DIR}/actor-create/s4u_actor-create_d.xml
-                                  ${CMAKE_CURRENT_SOURCE_DIR}/app-masterworker/s4u_app-masterworker_d.xml  PARENT_SCOPE)
+                                  ${CMAKE_CURRENT_SOURCE_DIR}/app-masterworker/s4u_app-masterworker_d.xml
+                                  ${CMAKE_CURRENT_SOURCE_DIR}/dht-chord/s4u_dht-chord_d.xml                PARENT_SCOPE)
 set(txt_files     ${txt_files}    ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/s4u_actions-comm_split_p0.txt
                                   ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/s4u_actions-comm_split_p1.txt
                                   ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/s4u_actions-comm.txt
@@ -22,6 +32,6 @@ set(txt_files     ${txt_files}    ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/s4u_a
                                   ${CMAKE_CURRENT_SOURCE_DIR}/README.doc                                   PARENT_SCOPE)
 
 foreach(example actions-comm actions-storage actor-create actor-kill actor-migration actor-suspend 
-                 app-masterworker app-token-ring io  mutex )
+                 app-masterworker app-token-ring dht-chord io mutex )
   ADD_TESH_FACTORIES(s4u-${example} "thread;ucontext;raw;boost" --setenv bindir=${CMAKE_CURRENT_BINARY_DIR}/${example} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/platforms --cd ${CMAKE_HOME_DIRECTORY}/examples/s4u/${example} s4u_${example}.tesh)
 endforeach()
diff --git a/examples/s4u/dht-chord/node.cpp b/examples/s4u/dht-chord/node.cpp
new file mode 100644 (file)
index 0000000..6ce9d5c
--- /dev/null
@@ -0,0 +1,530 @@
+/* Copyright (c) 2010-2016. The SimGrid Team. All rights reserved.          */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "s4u_dht-chord.hpp"
+
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(s4u_chord);
+
+/* Returns whether an id belongs to the interval [start, end].
+ *
+ * The parameters are normalized 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 int is_in_interval(int id, int start, int end)
+{
+  int i = id % nb_keys;
+  int s = start % nb_keys;
+  int e = end % nb_keys;
+
+  // make sure end >= start and id >= start
+  if (e < s) {
+    e += nb_keys;
+  }
+
+  if (i < s) {
+    i += nb_keys;
+  }
+
+  return i <= e;
+}
+
+/* Initializes the current node as the first one of the system */
+Node::Node(std::vector<std::string> args)
+{
+  xbt_assert(args.size() == 3 || args.size() == 5, "Wrong number of arguments for this node");
+
+  // initialize my node
+  id_                = std::stoi(args[1]);
+  stream             = simgrid::s4u::this_actor::host()->extension<HostChord>()->getStream();
+  mailbox_           = simgrid::s4u::Mailbox::byName(std::to_string(id_));
+  next_finger_to_fix = 0;
+  fingers_           = new int[nb_bits];
+
+  for (int i = 0; i < nb_bits; i++) {
+    fingers_[i] = id_;
+  }
+
+  if (args.size() == 3) { // first ring
+    deadline_   = std::stod(args[2]);
+    start_time_ = simgrid::s4u::Engine::instance()->getClock();
+    XBT_DEBUG("Create a new Chord ring...");
+  } else {
+    known_id_   = std::stoi(args[2]);
+    start_time_ = std::stod(args[3]);
+    deadline_   = std::stod(args[4]);
+    XBT_DEBUG("Hey! Let's join the system in %f seconds (shall leave at time %f)", start_time_,
+              start_time_ + deadline_);
+  }
+}
+
+Node::~Node()
+{
+  delete[] fingers_;
+}
+/* Makes the current node join the ring, knowing the id of a node already in the ring
+ *
+ * \param known_id id of a node already in the ring
+ * \return true if the join operation succeeded
+ *  */
+
+void Node::join(int known_id)
+{
+  XBT_INFO("Joining the ring with id %d, knowing node %d", id_, known_id);
+  setPredecessor(-1); // no predecessor (yet)
+
+  int successor_id = remoteFindSuccessor(known_id, id_);
+  if (successor_id == -1) {
+    XBT_INFO("Cannot join the ring.");
+  } else {
+    setFinger(0, successor_id);
+    printFingerTable();
+    joined = true;
+  }
+}
+
+/* Makes the current node quit the system */
+void Node::leave()
+{
+  XBT_INFO("Well Guys! I Think it's time for me to leave ;)");
+  notifyAndQuit();
+  joined = false;
+}
+
+/* Notifies the successor and the predecessor of the current node before leaving */
+void Node::notifyAndQuit()
+{
+  // send the PREDECESSOR_LEAVING to our successor
+  ChordMessage* pred_msg = new ChordMessage(PREDECESSOR_LEAVING);
+  pred_msg->request_id   = pred_id_;
+  pred_msg->answer_to    = mailbox_;
+
+  XBT_DEBUG("Sending a 'PREDECESSOR_LEAVING' to my successor %d", fingers_[0]);
+  try {
+    simgrid::s4u::this_actor::send(simgrid::s4u::Mailbox::byName(std::to_string(fingers_[0])), pred_msg, 10, timeout);
+  } catch (xbt_ex& e) {
+    if (e.category == timeout_error) {
+      XBT_DEBUG("Timeout expired when sending a 'PREDECESSOR_LEAVING' to my successor %d", fingers_[0]);
+      delete pred_msg;
+    }
+  }
+
+  // send the SUCCESSOR_LEAVING to our predecessor
+  ChordMessage* succ_msg = new ChordMessage(SUCCESSOR_LEAVING);
+  succ_msg->request_id   = fingers_[0];
+  succ_msg->answer_to    = mailbox_;
+  XBT_DEBUG("Sending a 'SUCCESSOR_LEAVING' to my predecessor %d", pred_id_);
+
+  try {
+    simgrid::s4u::this_actor::send(simgrid::s4u::Mailbox::byName(std::to_string(pred_id_)), succ_msg, 10, timeout);
+  } catch (xbt_ex& e) {
+    if (e.category == timeout_error) {
+      XBT_DEBUG("Timeout expired when sending a 'SUCCESSOR_LEAVING' to my predecessor %d", pred_id_);
+      delete succ_msg;
+    }
+  }
+}
+
+/* Performs a find successor request to a random id */
+void Node::randomLookup()
+{
+  int res          = id_;
+  int random_index = RngStream_RandInt(stream, 0, nb_bits - 1);
+  int random_id    = fingers_[random_index];
+  XBT_DEBUG("Making a lookup request for id %d", random_id);
+  if (random_id != id_)
+    res = findSuccessor(random_id);
+  XBT_DEBUG("The successor of node %d is %d", random_id, res);
+}
+
+/* Sets a finger of the current node.
+ *
+ * \param node 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 Node::setFinger(int finger_index, int id)
+{
+  if (id != fingers_[finger_index]) {
+    fingers_[finger_index] = id;
+    XBT_VERB("My new finger #%d is %d", finger_index, id);
+  }
+}
+
+/* Sets the predecessor of the current node.
+ * \param id the id to predecessor, or -1 to unset the predecessor
+ */
+void Node::setPredecessor(int predecessor_id)
+{
+  if (predecessor_id != pred_id_) {
+    pred_id_ = predecessor_id;
+    XBT_VERB("My new predecessor is %d", predecessor_id);
+  }
+}
+
+/** refreshes the finger table of the current node (called periodically) */
+void Node::fixFingers()
+{
+  XBT_DEBUG("Fixing fingers");
+  int id = findSuccessor(id_ + powers2[next_finger_to_fix]);
+  if (id != -1) {
+    if (id != fingers_[next_finger_to_fix]) {
+      setFinger(next_finger_to_fix, id);
+      printFingerTable();
+    }
+    next_finger_to_fix = (next_finger_to_fix + 1) % nb_bits;
+  }
+}
+
+/** Displays the finger table of a node. */
+void Node::printFingerTable()
+{
+  if (XBT_LOG_ISENABLED(s4u_chord, xbt_log_priority_verbose)) {
+    XBT_VERB("My finger table:");
+    XBT_VERB("Start | Succ");
+    for (int i = 0; i < nb_bits; i++) {
+      XBT_VERB(" %3d  | %3d", (id_ + powers2[i]) % nb_keys, fingers_[i]);
+    }
+
+    XBT_VERB("Predecessor: %d", pred_id_);
+  }
+}
+
+/* checks whether the predecessor has failed (called periodically) */
+void Node::checkPredecessor()
+{
+  XBT_DEBUG("Checking whether my predecessor is alive");
+  void* data = nullptr;
+  if (pred_id_ == -1)
+    return;
+
+  simgrid::s4u::MailboxPtr mailbox        = simgrid::s4u::Mailbox::byName(std::to_string(pred_id_));
+  simgrid::s4u::MailboxPtr return_mailbox = simgrid::s4u::Mailbox::byName(std::to_string(id_) + "_is_alive");
+
+  ChordMessage* message = new ChordMessage(PREDECESSOR_ALIVE);
+  message->request_id   = pred_id_;
+  message->answer_to    = return_mailbox;
+
+  XBT_DEBUG("Sending a 'Predecessor Alive' request to my predecessor %d", pred_id_);
+  try {
+    simgrid::s4u::this_actor::send(mailbox, message, 10, timeout);
+  } catch (xbt_ex& e) {
+    if (e.category == timeout_error) {
+      XBT_DEBUG("Failed to send the 'Predecessor Alive' request to %d", pred_id_);
+      delete message;
+      return;
+    }
+  }
+  // receive the answer
+  XBT_DEBUG("Sent 'Predecessor Alive' request to %d, waiting for the answer on my mailbox '%s'", pred_id_,
+            message->answer_to->name());
+  simgrid::s4u::Comm& comm = simgrid::s4u::this_actor::irecv(return_mailbox, &data);
+
+  try {
+    comm.wait(timeout);
+    XBT_DEBUG("Received the answer to my 'Predecessor Alive': my predecessor %d is alive", pred_id_);
+    delete message;
+  } catch (xbt_ex& e) {
+    if (e.category == timeout_error) {
+      XBT_DEBUG("Failed to receive the answer to my 'Predecessor Alive' request");
+      pred_id_ = -1;
+    }
+  }
+}
+
+/* Asks its predecessor to a remote node
+ *
+ * \param ask_to 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 Node::remoteGetPredecessor(int ask_to)
+{
+  int predecessor_id                      = -1;
+  void* data                              = nullptr;
+  simgrid::s4u::MailboxPtr mailbox        = simgrid::s4u::Mailbox::byName(std::to_string(ask_to));
+  simgrid::s4u::MailboxPtr return_mailbox = simgrid::s4u::Mailbox::byName(std::to_string(id_) + "_pred");
+
+  ChordMessage* message = new ChordMessage(GET_PREDECESSOR);
+  message->request_id   = id_;
+  message->answer_to    = return_mailbox;
+
+  // send a "Get Predecessor" request to ask_to_id
+  XBT_DEBUG("Sending a 'Get Predecessor' request to %d", ask_to);
+  try {
+    simgrid::s4u::this_actor::send(mailbox, message, 10, timeout);
+  } catch (xbt_ex& e) {
+    if (e.category == timeout_error) {
+      XBT_DEBUG("Failed to send the 'Get Predecessor' request to %d", ask_to);
+      delete message;
+      return predecessor_id;
+    }
+  }
+
+  // receive the answer
+  XBT_DEBUG("Sent 'Get Predecessor' request to %d, waiting for the answer on my mailbox '%s'", ask_to,
+            message->answer_to->name());
+  simgrid::s4u::Comm& comm = simgrid::s4u::this_actor::irecv(return_mailbox, &data);
+
+  try {
+    comm.wait(timeout);
+    ChordMessage* answer = static_cast<ChordMessage*>(data);
+    XBT_DEBUG("Received the answer to my 'Get Predecessor' request: the predecessor of node %d is %d", ask_to,
+              answer->answer_id);
+    predecessor_id = answer->answer_id;
+    delete answer;
+  } catch (xbt_ex& e) {
+    if (e.category == timeout_error) {
+      XBT_DEBUG("Failed to receive the answer to my 'Get Predecessor' request");
+      delete static_cast<ChordMessage*>(data);
+    }
+  }
+
+  return predecessor_id;
+}
+
+/* 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 Node::closestPrecedingFinger(int id)
+{
+  for (int i = nb_bits - 1; i >= 0; i--) {
+    if (is_in_interval(fingers_[i], id_ + 1, id - 1)) {
+      return fingers_[i];
+    }
+  }
+  return id_;
+}
+
+/* Makes the current node find the successor node of an id.
+ *
+ * \param id the id to find
+ * \return the id of the successor node, or -1 if the request failed
+ */
+int Node::findSuccessor(int id)
+{
+  // is my successor the successor?
+  if (is_in_interval(id, id_ + 1, fingers_[0])) {
+    return fingers_[0];
+  }
+
+  // otherwise, ask the closest preceding finger in my table
+  return remoteFindSuccessor(closestPrecedingFinger(id), id);
+}
+
+int Node::remoteFindSuccessor(int ask_to, int id)
+{
+  int successor                           = -1;
+  void* data                              = nullptr;
+  simgrid::s4u::MailboxPtr mailbox        = simgrid::s4u::Mailbox::byName(std::to_string(ask_to));
+  simgrid::s4u::MailboxPtr return_mailbox = simgrid::s4u::Mailbox::byName(std::to_string(id_) + "_succ");
+
+  ChordMessage* message = new ChordMessage(FIND_SUCCESSOR);
+  message->request_id   = id_;
+  message->answer_to    = return_mailbox;
+
+  // send a "Find Successor" request to ask_to_id
+  XBT_DEBUG("Sending a 'Find Successor' request to %d for id %d", ask_to, id);
+  try {
+    simgrid::s4u::this_actor::send(mailbox, message, 10, timeout);
+  } catch (xbt_ex& e) {
+    if (e.category == timeout_error) {
+      XBT_DEBUG("Failed to send the 'Find Successor' request to %d for id %d", ask_to, id_);
+      delete message;
+      return successor;
+    }
+  }
+  // receive the answer
+  XBT_DEBUG("Sent a 'Find Successor' request to %d for key %d, waiting for the answer", ask_to, id);
+  simgrid::s4u::Comm& comm = simgrid::s4u::this_actor::irecv(return_mailbox, &data);
+
+  try {
+    comm.wait(timeout);
+    ChordMessage* answer = static_cast<ChordMessage*>(data);
+    XBT_DEBUG("Received the answer to my 'Find Successor' request for id %d: the successor of key %d is %d",
+              answer->request_id, id_, answer->answer_id);
+    successor = answer->answer_id;
+    delete answer;
+  } catch (xbt_ex& e) {
+    if (e.category == timeout_error) {
+      XBT_DEBUG("Failed to receive the answer to my 'Find Successor' request");
+      delete static_cast<ChordMessage*>(data);
+    }
+  }
+  return successor;
+}
+
+/* Notifies the current node that its predecessor may have changed. */
+void Node::notify(int predecessor_candidate_id)
+{
+  if (pred_id_ == -1 || is_in_interval(predecessor_candidate_id, pred_id_ + 1, id_ - 1)) {
+    setPredecessor(predecessor_candidate_id);
+    printFingerTable();
+  } else {
+    XBT_DEBUG("I don't have to change my predecessor to %d", predecessor_candidate_id);
+  }
+}
+
+/* Notifies a remote node that its predecessor may have changed. */
+void Node::remoteNotify(int notify_id, int predecessor_candidate_id)
+{
+  ChordMessage* message = new ChordMessage(NOTIFY);
+  message->request_id   = predecessor_candidate_id;
+  message->answer_to    = nullptr;
+
+  // send a "Notify" request to notify_id
+  XBT_DEBUG("Sending a 'Notify' request to %d", notify_id);
+  simgrid::s4u::MailboxPtr mailbox = simgrid::s4u::Mailbox::byName(std::to_string(notify_id));
+  try {
+    // TODO make it a dsend
+    simgrid::s4u::this_actor::isend(mailbox, message, 10);
+  } catch (xbt_ex& e) {
+    if (e.category == timeout_error) {
+      XBT_DEBUG("Send of 'Notify' failed due du an expired timeout on receiver side");
+      delete message;
+    }
+  }
+}
+
+/* This function is called periodically. It checks the immediate successor of the current node. */
+void Node::stabilize()
+{
+  XBT_DEBUG("Stabilizing node");
+
+  // get the predecessor of my immediate successor
+  int candidate_id;
+  int successor_id = fingers_[0];
+  if (successor_id != id_) {
+    candidate_id = remoteGetPredecessor(successor_id);
+  } else {
+    candidate_id = pred_id_;
+  }
+
+  // this node is a candidate to become my new successor
+  if (candidate_id != -1 && is_in_interval(candidate_id, id_ + 1, successor_id - 1)) {
+    setFinger(0, candidate_id);
+  }
+  if (successor_id != id_) {
+    remoteNotify(successor_id, id_);
+  }
+}
+
+/* This function is called when a node receives a message.
+ *
+ * \param message the message to handle (don't touch it afterward: it will be destroyed, reused or forwarded)
+ */
+void Node::handleMessage(ChordMessage* message)
+{
+  switch (message->type) {
+  case FIND_SUCCESSOR:
+    XBT_DEBUG("Received a 'Find Successor' request from %s for id %d", message->issuer_host_name.c_str(),
+        message->request_id);
+    // is my successor the successor?
+    if (is_in_interval(message->request_id, id_ + 1, fingers_[0])) {
+      message->type = FIND_SUCCESSOR_ANSWER;
+      message->answer_id = fingers_[0];
+      XBT_DEBUG("Sending back a 'Find Successor Answer' to %s (mailbox %s): the successor of %d is %d",
+          message->issuer_host_name.c_str(), message->answer_to->name(), message->request_id, message->answer_id);
+      // TODO Replace by dsend
+      try {
+        simgrid::s4u::this_actor::isend(message->answer_to, message, 10);
+      } catch(xbt_ex& e) {
+        if (e.category == timeout_error) {
+          XBT_DEBUG("Send of 'Find Successor Answer' failed due du an expired timeout on receiver side");
+        }
+      }
+    } else {
+      // otherwise, forward the request to the closest preceding finger in my table
+      int closest = closestPrecedingFinger(message->request_id);
+      XBT_DEBUG("Forwarding the 'Find Successor' request for id %d to my closest preceding finger %d",
+          message->request_id, closest);
+      simgrid::s4u::MailboxPtr mailbox = simgrid::s4u::Mailbox::byName(std::to_string(closest));
+      //TODO make it a dsend
+      try{
+        simgrid::s4u::this_actor::isend(mailbox, message, 10);
+      } catch (xbt_ex& e) {
+        if (e.category == timeout_error) {
+          XBT_DEBUG("Forward of 'Find Successor' failed due du an expired timeout on receiver side");
+        }
+      }
+    }
+    break;
+
+  case GET_PREDECESSOR:
+    XBT_DEBUG("Receiving a 'Get Predecessor' request from %s", message->issuer_host_name.c_str());
+    message->type = GET_PREDECESSOR_ANSWER;
+    message->answer_id = pred_id_;
+    XBT_DEBUG("Sending back a 'Get Predecessor Answer' to %s via mailbox '%s': my predecessor is %d",
+        message->issuer_host_name.c_str(), message->answer_to->name(), message->answer_id);
+    //TODO make it a dsend
+    try{
+      simgrid::s4u::this_actor::isend(message->answer_to, message, 10);
+    } catch (xbt_ex& e) {
+      if (e.category == timeout_error) {
+        XBT_DEBUG("Send of 'Get Predecessor Answer' failed due du an expired timeout on receiver side");
+      }
+    }
+    break;
+
+  case NOTIFY:
+    // someone is telling me that he may be my new predecessor
+    XBT_DEBUG("Receiving a 'Notify' request from %s", message->issuer_host_name.c_str());
+    notify(message->request_id);
+    delete message;
+    break;
+
+  case PREDECESSOR_LEAVING:
+    // my predecessor is about to quit
+    XBT_DEBUG("Receiving a 'Predecessor Leaving' message from %s", message->issuer_host_name.c_str());
+    // modify my predecessor
+    setPredecessor(message->request_id);
+    delete message;
+    /*TODO :
+      >> notify my new predecessor
+      >> send a notify_predecessors !!
+     */
+    break;
+
+  case SUCCESSOR_LEAVING:
+    // my successor is about to quit
+    XBT_DEBUG("Receiving a 'Successor Leaving' message from %s", message->issuer_host_name.c_str());
+    // modify my successor FIXME : this should be implicit ?
+    setFinger(0, message->request_id);
+    delete message;
+    /* TODO
+       >> notify my new successor
+       >> update my table & predecessors table */
+    break;
+
+  case PREDECESSOR_ALIVE:
+    XBT_DEBUG("Receiving a 'Predecessor Alive' request from %s", message->issuer_host_name.c_str());
+    message->type = PREDECESSOR_ALIVE_ANSWER;
+    XBT_DEBUG("Sending back a 'Predecessor Alive Answer' to %s (mailbox %s)",
+        message->issuer_host_name.c_str(), message->answer_to->name());
+    //TODO Make it a dsend
+    try{
+      simgrid::s4u::this_actor::isend(message->answer_to, message, 10);
+    } catch (xbt_ex& e) {
+      if (e.category == timeout_error) {
+        XBT_DEBUG("Send of 'Predecessor Alive' failed due du an expired timeout on receiver side");
+      }
+    }
+    break;
+
+  default:
+    XBT_DEBUG("Ignoring unexpected message: %d from %s", message->type, message->issuer_host_name.c_str());
+    delete message;
+  }
+}
diff --git a/examples/s4u/dht-chord/s4u_dht-chord.cpp b/examples/s4u/dht-chord/s4u_dht-chord.cpp
new file mode 100644 (file)
index 0000000..4105503
--- /dev/null
@@ -0,0 +1,80 @@
+/* Copyright (c) 2010-2016. The SimGrid Team. All rights reserved.          */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "s4u_dht-chord.hpp"
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_chord, "Messages specific for this s4u example");
+simgrid::xbt::Extension<simgrid::s4u::Host, HostChord> HostChord::EXTENSION_ID;
+
+int nb_bits  = 24;
+int nb_keys  = 0;
+int timeout  = 50;
+int* powers2 = nullptr;
+
+/* Global initialization of the Chord simulation. */
+static void chord_init()
+{
+  // compute the powers of 2 once for all
+  powers2 = new int[nb_bits];
+  int pow = 1;
+  for (int i = 0; i < nb_bits; i++) {
+    powers2[i] = pow;
+    pow        = pow << 1;
+  }
+  nb_keys = pow;
+  XBT_DEBUG("Sets nb_keys to %d", nb_keys);
+
+  HostChord::EXTENSION_ID = simgrid::s4u::Host::extension_create<HostChord>();
+
+  std::vector<simgrid::s4u::Host*> list;
+  simgrid::s4u::Engine::instance()->hostList(&list);
+  for (auto host : list)
+    host->extension_set(new HostChord(host));
+}
+
+static void chord_exit(void)
+{
+  delete[] powers2;
+}
+
+int main(int argc, char* argv[])
+{
+  simgrid::s4u::Engine* e = new simgrid::s4u::Engine(&argc, argv);
+  xbt_assert(argc > 2, "Usage: %s [-nb_bits=n] [-timeout=t] platform_file deployment_file\n"
+                       "\tExample: %s ../msg_platform.xml chord.xml\n",
+             argv[0], argv[0]);
+  char** options = &argv[1];
+  while (!strncmp(options[0], "-", 1)) {
+    unsigned int length = strlen("-nb_bits=");
+    if (!strncmp(options[0], "-nb_bits=", length) && strlen(options[0]) > length) {
+      nb_bits = xbt_str_parse_int(options[0] + length, "Invalid nb_bits parameter: %s");
+      XBT_DEBUG("Set nb_bits to %d", nb_bits);
+    } else {
+      length = strlen("-timeout=");
+      if (!strncmp(options[0], "-timeout=", length) && strlen(options[0]) > length) {
+        timeout = xbt_str_parse_int(options[0] + length, "Invalid timeout parameter: %s");
+        XBT_DEBUG("Set timeout to %d", timeout);
+      } else {
+        xbt_die("Invalid chord option '%s'", options[0]);
+      }
+    }
+    options++;
+  }
+
+  e->loadPlatform(options[0]);
+
+  chord_init();
+
+  e->registerFunction<Node>("node");
+  e->loadDeployment(options[1]);
+
+  e->run();
+
+  XBT_INFO("Simulated time: %g", e->getClock());
+
+  chord_exit();
+
+  return 0;
+}
diff --git a/examples/s4u/dht-chord/s4u_dht-chord.hpp b/examples/s4u/dht-chord/s4u_dht-chord.hpp
new file mode 100644 (file)
index 0000000..7ff0be3
--- /dev/null
@@ -0,0 +1,165 @@
+/* Copyright (c) 2016. The SimGrid Team.
+* All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef S4U_CHORD_HPP
+#define S4U_CHORD_HPP
+#include "simgrid/s4u.hpp"
+#include <string>
+#include <xbt/RngStream.h>
+#include <xbt/ex.hpp>
+#include <xbt/str.h>
+
+#define MAX_SIMULATION_TIME 1000
+#define PERIODIC_STABILIZE_DELAY 20
+#define PERIODIC_FIX_FINGERS_DELAY 120
+#define PERIODIC_CHECK_PREDECESSOR_DELAY 120
+#define PERIODIC_LOOKUP_DELAY 10
+#define SLEEP_DELAY 4.9999
+
+extern int nb_bits;
+extern int nb_keys;
+extern int timeout;
+extern int* powers2;
+
+class HostChord {
+  RngStream stream_;
+  simgrid::s4u::Host* host = nullptr;
+
+public:
+  static simgrid::xbt::Extension<simgrid::s4u::Host, HostChord> EXTENSION_ID;
+
+  explicit HostChord(simgrid::s4u::Host* ptr) : host(ptr)
+  {
+    std::string descr = std::string("RngSream<") + host->name() + ">";
+    stream_           = RngStream_CreateStream(descr.c_str());
+  }
+
+  ~HostChord() { RngStream_DeleteStream(&stream_); };
+
+  RngStream getStream() { return stream_; };
+};
+
+/* Types of tasks exchanged between nodes. */
+typedef enum {
+  FIND_SUCCESSOR,
+  FIND_SUCCESSOR_ANSWER,
+  GET_PREDECESSOR,
+  GET_PREDECESSOR_ANSWER,
+  NOTIFY,
+  SUCCESSOR_LEAVING,
+  PREDECESSOR_LEAVING,
+  PREDECESSOR_ALIVE,
+  PREDECESSOR_ALIVE_ANSWER
+} e_message_type_t;
+
+class ChordMessage {
+public:
+  e_message_type_t type;              // type of message
+  std::string issuer_host_name;       // used for logging
+  int request_id     = -1;            // id (used by some types of messages)
+  int request_finger = 1;             // finger parameter (used by some types of messages)
+  int answer_id      = -1;            // answer (used by some types of messages)
+  simgrid::s4u::MailboxPtr answer_to; // mailbox to send an answer to (if any)
+
+  ChordMessage(e_message_type_t type) : type(type) { issuer_host_name = simgrid::s4u::this_actor::host()->name(); }
+
+  ~ChordMessage() = default;
+};
+
+class Node {
+  int known_id_      = -1;
+  double start_time_ = -1;
+  double deadline_   = -1;
+  bool joined        = false;
+  int id_;                           // my id
+  int pred_id_ = -1;                 // predecessor id
+  simgrid::s4u::MailboxPtr mailbox_; // my mailbox
+  int* fingers_;                     // finger table,(fingers[0] is my successor)
+  int next_finger_to_fix;            // index of the next finger to fix in fix_fingers()
+  RngStream stream;
+
+public:
+  explicit Node(std::vector<std::string> args);
+  ~Node();
+  void join(int known_id);
+  void leave();
+  void notifyAndQuit();
+
+  void randomLookup();
+  void setFinger(int finger_index, int id);
+  void fixFingers();
+  void printFingerTable();
+
+  void setPredecessor(int predecessor_id);
+  void checkPredecessor();
+  int remoteGetPredecessor(int ask_to);
+  int closestPrecedingFinger(int id);
+  int findSuccessor(int id);
+  int remoteFindSuccessor(int ask_to, int id);
+
+  void notify(int predecessor_candidate_id);
+  void remoteNotify(int notify_id, int predecessor_candidate_id);
+  void stabilize();
+  void handleMessage(ChordMessage* message);
+
+  void operator()()
+  {
+    simgrid::s4u::this_actor::sleep_for(start_time_);
+    if (known_id_ == -1) {
+      setPredecessor(-1); // -1 means that I have no predecessor
+      printFingerTable();
+      joined = true;
+    } else {
+      join(known_id_);
+    }
+
+    if (!joined)
+      return;
+    ChordMessage* message              = nullptr;
+    void* data                         = nullptr;
+    double now                         = simgrid::s4u::Engine::instance()->getClock();
+    double next_stabilize_date         = start_time_ + PERIODIC_STABILIZE_DELAY;
+    double next_fix_fingers_date       = start_time_ + PERIODIC_FIX_FINGERS_DELAY;
+    double next_check_predecessor_date = start_time_ + PERIODIC_CHECK_PREDECESSOR_DELAY;
+    double next_lookup_date            = start_time_ + PERIODIC_LOOKUP_DELAY;
+
+    while ((now < (start_time_ + deadline_)) && now < MAX_SIMULATION_TIME) {
+      data                             = nullptr;
+      simgrid::s4u::Comm& comm_receive = simgrid::s4u::this_actor::irecv(mailbox_, &data);
+      while ((now < (start_time_ + deadline_)) && now < MAX_SIMULATION_TIME && !comm_receive.test()) {
+        // no task was received: make some periodic calls
+        if (now >= next_stabilize_date) {
+          stabilize();
+          next_stabilize_date = simgrid::s4u::Engine::instance()->getClock() + PERIODIC_STABILIZE_DELAY;
+        } else if (now >= next_fix_fingers_date) {
+          fixFingers();
+          next_fix_fingers_date = simgrid::s4u::Engine::instance()->getClock() + PERIODIC_FIX_FINGERS_DELAY;
+        } else if (now >= next_check_predecessor_date) {
+          checkPredecessor();
+          next_check_predecessor_date = simgrid::s4u::Engine::instance()->getClock() + PERIODIC_CHECK_PREDECESSOR_DELAY;
+        } else if (now >= next_lookup_date) {
+          randomLookup();
+          next_lookup_date = simgrid::s4u::Engine::instance()->getClock() + PERIODIC_LOOKUP_DELAY;
+        } else {
+          // nothing to do: sleep for a while
+          simgrid::s4u::this_actor::sleep_for(SLEEP_DELAY);
+        }
+        now = simgrid::s4u::Engine::instance()->getClock();
+      }
+
+      if (data != nullptr) {
+        message = static_cast<ChordMessage*>(data);
+        handleMessage(message);
+      }
+      now = simgrid::s4u::Engine::instance()->getClock();
+    }
+
+    // leave the ring
+    leave();
+  }
+};
+
+#endif
diff --git a/examples/s4u/dht-chord/s4u_dht-chord.tesh b/examples/s4u/dht-chord/s4u_dht-chord.tesh
new file mode 100644 (file)
index 0000000..ebe7b47
--- /dev/null
@@ -0,0 +1,237 @@
+#! ./tesh
+
+p Testing the Chord implementation with MSG
+
+! output sort 19
+$ $SG_TEST_EXENV ${bindir:=.}/s4u_dht-chord$EXEEXT -nb_bits=3 ${srcdir:=.}/cluster.xml ${srcdir:=.}/../s4u/dht-chord/s4u_dht-chord_d.xml --log=s4u_chord.thres:verbose "--log=root.fmt:[%10.5r]%e(%P@%h)%e%m%n"
+> [   0.00000] (node@node-0.acme.org) My finger table:
+> [   0.00000] (node@node-0.acme.org) Start | Succ
+> [   0.00000] (node@node-0.acme.org)    3  |  42
+> [   0.00000] (node@node-0.acme.org)    4  |  42
+> [   0.00000] (node@node-0.acme.org)    6  |  42
+> [   0.00000] (node@node-0.acme.org) Predecessor: -1
+> [  10.00000] (node@node-1.acme.org) Joining the ring with id 366680, knowing node 42
+> [  15.00751] (node@node-1.acme.org) My new finger #0 is 42
+> [  15.00751] (node@node-1.acme.org) My finger table:
+> [  15.00751] (node@node-1.acme.org) Start | Succ
+> [  15.00751] (node@node-1.acme.org)    1  |  42
+> [  15.00751] (node@node-1.acme.org)    2  | 366680
+> [  15.00751] (node@node-1.acme.org)    4  | 366680
+> [  15.00751] (node@node-1.acme.org) Predecessor: -1
+> [  20.00000] (node@node-2.acme.org) Joining the ring with id 533744, knowing node 366680
+> [  30.00000] (node@node-3.acme.org) Joining the ring with id 1319738, knowing node 42
+> [  30.00721] (node@node-2.acme.org) My new finger #0 is 42
+> [  30.00721] (node@node-2.acme.org) My finger table:
+> [  30.00721] (node@node-2.acme.org) Start | Succ
+> [  30.00721] (node@node-2.acme.org)    1  |  42
+> [  30.00721] (node@node-2.acme.org)    2  | 533744
+> [  30.00721] (node@node-2.acme.org)    4  | 533744
+> [  30.00721] (node@node-2.acme.org) Predecessor: -1
+> [  35.00711] (node@node-3.acme.org) My new finger #0 is 42
+> [  35.00711] (node@node-3.acme.org) My finger table:
+> [  35.00711] (node@node-3.acme.org) Start | Succ
+> [  35.00711] (node@node-3.acme.org)    3  |  42
+> [  35.00711] (node@node-3.acme.org)    4  | 1319738
+> [  35.00711] (node@node-3.acme.org)    6  | 1319738
+> [  35.00711] (node@node-3.acme.org) Predecessor: -1
+> [  40.00000] (node@node-4.acme.org) Joining the ring with id 16509405, knowing node 366680
+> [  49.99900] (node@node-0.acme.org) My new predecessor is 366680
+> [  49.99900] (node@node-0.acme.org) My finger table:
+> [  49.99900] (node@node-0.acme.org) Start | Succ
+> [  49.99900] (node@node-0.acme.org)    3  |  42
+> [  49.99900] (node@node-0.acme.org)    4  |  42
+> [  49.99900] (node@node-0.acme.org)    6  |  42
+> [  49.99900] (node@node-0.acme.org) Predecessor: 366680
+> [  49.99900] (node@node-0.acme.org) My new finger #0 is 366680
+> [  55.00671] (node@node-4.acme.org) My new finger #0 is 366680
+> [  55.00671] (node@node-4.acme.org) My finger table:
+> [  55.00671] (node@node-4.acme.org) Start | Succ
+> [  55.00671] (node@node-4.acme.org)    6  | 366680
+> [  55.00671] (node@node-4.acme.org)    7  | 16509405
+> [  55.00671] (node@node-4.acme.org)    1  | 16509405
+> [  55.00671] (node@node-4.acme.org) Predecessor: -1
+> [  60.00000] (node@node-6.acme.org) Joining the ring with id 16728096, knowing node 1319738
+> [  65.00651] (node@node-3.acme.org) My new finger #0 is 366680
+> [  65.01431] (node@node-6.acme.org) My new finger #0 is 366680
+> [  65.01431] (node@node-6.acme.org) My finger table:
+> [  65.01431] (node@node-6.acme.org) Start | Succ
+> [  65.01431] (node@node-6.acme.org)    1  | 366680
+> [  65.01431] (node@node-6.acme.org)    2  | 16728096
+> [  65.01431] (node@node-6.acme.org)    4  | 16728096
+> [  65.01431] (node@node-6.acme.org) Predecessor: -1
+> [  70.00641] (node@node-1.acme.org) My new predecessor is 16509405
+> [  70.00641] (node@node-1.acme.org) My finger table:
+> [  70.00641] (node@node-1.acme.org) Start | Succ
+> [  70.00641] (node@node-1.acme.org)    1  |  42
+> [  70.00641] (node@node-1.acme.org)    2  | 366680
+> [  70.00641] (node@node-1.acme.org)    4  | 366680
+> [  70.00641] (node@node-1.acme.org) Predecessor: 16509405
+> [  80.01401] (node@node-0.acme.org) My new finger #0 is 16509405
+> [  85.01391] (node@node-6.acme.org) My new finger #0 is 16509405
+> [ 100.02922] (node@node-3.acme.org) My new finger #0 is 16509405
+> [ 110.02902] (node@node-4.acme.org) My new predecessor is 42
+> [ 110.02902] (node@node-4.acme.org) My finger table:
+> [ 110.02902] (node@node-4.acme.org) Start | Succ
+> [ 110.02902] (node@node-4.acme.org)    6  | 366680
+> [ 110.02902] (node@node-4.acme.org)    7  | 16509405
+> [ 110.02902] (node@node-4.acme.org)    1  | 16509405
+> [ 110.02902] (node@node-4.acme.org) Predecessor: 42
+> [ 115.03673] (node@node-6.acme.org) My new finger #0 is 42
+> [ 200.05164] (node@node-3.acme.org) Well Guys! I Think it's time for me to leave ;)
+> [ 210.04364] (node@node-1.acme.org) Well Guys! I Think it's time for me to leave ;)
+> [ 210.05925] (node@node-4.acme.org) My new predecessor is -1
+> [ 220.05905] (node@node-4.acme.org) My new predecessor is 42
+> [ 220.05905] (node@node-4.acme.org) My finger table:
+> [ 220.05905] (node@node-4.acme.org) Start | Succ
+> [ 220.05905] (node@node-4.acme.org)    6  | 366680
+> [ 220.05905] (node@node-4.acme.org)    7  | 16509405
+> [ 220.05905] (node@node-4.acme.org)    1  | 16509405
+> [ 220.05905] (node@node-4.acme.org) Predecessor: 42
+> [ 220.07466] (node@node-0.acme.org) My new predecessor is 16509405
+> [ 225.05895] (node@node-4.acme.org) My new finger #0 is 42
+> [ 230.07446] (node@node-0.acme.org) My new predecessor is 533744
+> [ 230.07446] (node@node-0.acme.org) My finger table:
+> [ 230.07446] (node@node-0.acme.org) Start | Succ
+> [ 230.07446] (node@node-0.acme.org)    3  | 16509405
+> [ 230.07446] (node@node-0.acme.org)    4  |  42
+> [ 230.07446] (node@node-0.acme.org)    6  |  42
+> [ 230.07446] (node@node-0.acme.org) Predecessor: 533744
+> [ 235.08217] (node@node-4.acme.org) My new finger #0 is 533744
+> [ 240.08987] (node@node-0.acme.org) My new finger #1 is 16509405
+> [ 240.08987] (node@node-0.acme.org) My finger table:
+> [ 240.08987] (node@node-0.acme.org) Start | Succ
+> [ 240.08987] (node@node-0.acme.org)    3  | 16509405
+> [ 240.08987] (node@node-0.acme.org)    4  | 16509405
+> [ 240.08987] (node@node-0.acme.org)    6  |  42
+> [ 240.08987] (node@node-0.acme.org) Predecessor: 533744
+> [ 250.00000] (node@node-5.acme.org) Joining the ring with id 10874876, knowing node 533744
+> [ 255.11299] (node@node-5.acme.org) My new finger #0 is 16509405
+> [ 255.11299] (node@node-5.acme.org) My finger table:
+> [ 255.11299] (node@node-5.acme.org) Start | Succ
+> [ 255.11299] (node@node-5.acme.org)    5  | 16509405
+> [ 255.11299] (node@node-5.acme.org)    6  | 10874876
+> [ 255.11299] (node@node-5.acme.org)    0  | 10874876
+> [ 255.11299] (node@node-5.acme.org) Predecessor: -1
+> [ 265.09718] (node@node-2.acme.org) My new predecessor is 16509405
+> [ 265.09718] (node@node-2.acme.org) My finger table:
+> [ 265.09718] (node@node-2.acme.org) Start | Succ
+> [ 265.09718] (node@node-2.acme.org)    1  |  42
+> [ 265.09718] (node@node-2.acme.org)    2  | 533744
+> [ 265.09718] (node@node-2.acme.org)    4  | 533744
+> [ 265.09718] (node@node-2.acme.org) Predecessor: 16509405
+> [ 275.11259] (node@node-5.acme.org) My new finger #0 is 42
+> [ 280.10468] (node@node-4.acme.org) My new predecessor is 10874876
+> [ 280.10468] (node@node-4.acme.org) My finger table:
+> [ 280.10468] (node@node-4.acme.org) Start | Succ
+> [ 280.10468] (node@node-4.acme.org)    6  | 533744
+> [ 280.10468] (node@node-4.acme.org)    7  | 16509405
+> [ 280.10468] (node@node-4.acme.org)    1  | 16509405
+> [ 280.10468] (node@node-4.acme.org) Predecessor: 10874876
+> [ 285.13581] (node@node-4.acme.org) My new predecessor is 42
+> [ 285.13581] (node@node-4.acme.org) My finger table:
+> [ 285.13581] (node@node-4.acme.org) Start | Succ
+> [ 285.13581] (node@node-4.acme.org)    6  | 533744
+> [ 285.13581] (node@node-4.acme.org)    7  | 16509405
+> [ 285.13581] (node@node-4.acme.org)    1  | 16509405
+> [ 285.13581] (node@node-4.acme.org) Predecessor: 42
+> [ 300.13551] (node@node-4.acme.org) My new finger #1 is 533744
+> [ 300.13551] (node@node-4.acme.org) My finger table:
+> [ 300.13551] (node@node-4.acme.org) Start | Succ
+> [ 300.13551] (node@node-4.acme.org)    6  | 533744
+> [ 300.13551] (node@node-4.acme.org)    7  | 533744
+> [ 300.13551] (node@node-4.acme.org)    1  | 16509405
+> [ 300.13551] (node@node-4.acme.org) Predecessor: 42
+> [ 300.14332] (node@node-2.acme.org) My new finger #1 is 42
+> [ 300.14332] (node@node-2.acme.org) My finger table:
+> [ 300.14332] (node@node-2.acme.org) Start | Succ
+> [ 300.14332] (node@node-2.acme.org)    1  |  42
+> [ 300.14332] (node@node-2.acme.org)    2  |  42
+> [ 300.14332] (node@node-2.acme.org)    4  | 533744
+> [ 300.14332] (node@node-2.acme.org) Predecessor: 16509405
+> [ 305.14322] (node@node-5.acme.org) My new finger #0 is 533744
+> [ 305.15102] (node@node-0.acme.org) My new finger #0 is 10874876
+> [ 310.15873] (node@node-6.acme.org) My new finger #1 is 42
+> [ 310.15873] (node@node-6.acme.org) My finger table:
+> [ 310.15873] (node@node-6.acme.org) Start | Succ
+> [ 310.15873] (node@node-6.acme.org)    1  |  42
+> [ 310.15873] (node@node-6.acme.org)    2  |  42
+> [ 310.15873] (node@node-6.acme.org)    4  | 16728096
+> [ 310.15873] (node@node-6.acme.org) Predecessor: -1
+> [ 330.16613] (node@node-5.acme.org) My new finger #0 is 16509405
+> [ 335.16603] (node@node-5.acme.org) My new predecessor is 42
+> [ 335.16603] (node@node-5.acme.org) My finger table:
+> [ 335.16603] (node@node-5.acme.org) Start | Succ
+> [ 335.16603] (node@node-5.acme.org)    5  | 16509405
+> [ 335.16603] (node@node-5.acme.org)    6  | 10874876
+> [ 335.16603] (node@node-5.acme.org)    0  | 10874876
+> [ 335.16603] (node@node-5.acme.org) Predecessor: 42
+> [ 340.16593] (node@node-4.acme.org) Well Guys! I Think it's time for me to leave ;)
+> [ 350.15793] (node@node-2.acme.org) My new predecessor is 42
+> [ 350.16573] (node@node-0.acme.org) My new finger #0 is 533744
+> [ 360.18115] (node@node-0.acme.org) My new finger #2 is 533744
+> [ 360.18115] (node@node-0.acme.org) My finger table:
+> [ 360.18115] (node@node-0.acme.org) Start | Succ
+> [ 360.18115] (node@node-0.acme.org)    3  | 533744
+> [ 360.18115] (node@node-0.acme.org)    4  | 16509405
+> [ 360.18115] (node@node-0.acme.org)    6  | 533744
+> [ 360.18115] (node@node-0.acme.org) Predecessor: 533744
+> [ 420.23459] (node@node-2.acme.org) Well Guys! I Think it's time for me to leave ;)
+> [ 425.22668] (node@node-0.acme.org) My new predecessor is 42
+> [ 475.23449] (node@node-0.acme.org) My new finger #0 is 42
+> [ 480.23439] (node@node-0.acme.org) My new predecessor is 16728096
+> [ 480.23439] (node@node-0.acme.org) My finger table:
+> [ 480.23439] (node@node-0.acme.org) Start | Succ
+> [ 480.23439] (node@node-0.acme.org)    3  |  42
+> [ 480.23439] (node@node-0.acme.org)    4  | 16509405
+> [ 480.23439] (node@node-0.acme.org)    6  | 533744
+> [ 480.23439] (node@node-0.acme.org) Predecessor: 16728096
+> [ 485.24209] (node@node-6.acme.org) My new finger #2 is 42
+> [ 485.24209] (node@node-6.acme.org) My finger table:
+> [ 485.24209] (node@node-6.acme.org) Start | Succ
+> [ 485.24209] (node@node-6.acme.org)    1  |  42
+> [ 485.24209] (node@node-6.acme.org)    2  |  42
+> [ 485.24209] (node@node-6.acme.org)    4  |  42
+> [ 485.24209] (node@node-6.acme.org) Predecessor: -1
+> [ 495.24970] (node@node-0.acme.org) My new finger #0 is 16728096
+> [ 575.26471] (node@node-6.acme.org) My new predecessor is 42
+> [ 575.26471] (node@node-6.acme.org) My finger table:
+> [ 575.26471] (node@node-6.acme.org) Start | Succ
+> [ 575.26471] (node@node-6.acme.org)    1  |  42
+> [ 575.26471] (node@node-6.acme.org)    2  |  42
+> [ 575.26471] (node@node-6.acme.org)    4  |  42
+> [ 575.26471] (node@node-6.acme.org) Predecessor: 42
+> [ 600.27202] (node@node-0.acme.org) My new finger #1 is 16728096
+> [ 600.27202] (node@node-0.acme.org) My finger table:
+> [ 600.27202] (node@node-0.acme.org) Start | Succ
+> [ 600.27202] (node@node-0.acme.org)    3  | 16728096
+> [ 600.27202] (node@node-0.acme.org)    4  | 16728096
+> [ 600.27202] (node@node-0.acme.org)    6  | 533744
+> [ 600.27202] (node@node-0.acme.org) Predecessor: 16728096
+> [ 720.36329] (node@node-0.acme.org) My new finger #2 is 16728096
+> [ 720.36329] (node@node-0.acme.org) My finger table:
+> [ 720.36329] (node@node-0.acme.org) Start | Succ
+> [ 720.36329] (node@node-0.acme.org)    3  | 16728096
+> [ 720.36329] (node@node-0.acme.org)    4  | 16728096
+> [ 720.36329] (node@node-0.acme.org)    6  | 16728096
+> [ 720.36329] (node@node-0.acme.org) Predecessor: 16728096
+> [ 855.46207] (node@node-6.acme.org) My new finger #2 is 16728096
+> [ 855.46207] (node@node-6.acme.org) My finger table:
+> [ 855.46207] (node@node-6.acme.org) Start | Succ
+> [ 855.46207] (node@node-6.acme.org)    1  |  42
+> [ 855.46207] (node@node-6.acme.org)    2  |  42
+> [ 855.46207] (node@node-6.acme.org)    4  | 16728096
+> [ 855.46207] (node@node-6.acme.org) Predecessor: 42
+> [ 860.46197] (node@node-6.acme.org) Well Guys! I Think it's time for me to leave ;)
+> [ 865.45406] (node@node-0.acme.org) My new predecessor is 42
+> [ 890.43115] (node@node-5.acme.org) Well Guys! I Think it's time for me to leave ;)
+> [ 915.45406] (node@node-0.acme.org) My new finger #0 is 42
+> [ 940.45356] (node@node-0.acme.org) My new finger #0 is 16509405
+> [ 990.45356] (node@node-0.acme.org) My new finger #1 is 16509405
+> [ 990.45356] (node@node-0.acme.org) My finger table:
+> [ 990.45356] (node@node-0.acme.org) Start | Succ
+> [ 990.45356] (node@node-0.acme.org)    3  | 16509405
+> [ 990.45356] (node@node-0.acme.org)    4  | 16509405
+> [ 990.45356] (node@node-0.acme.org)    6  | 16728096
+> [ 990.45356] (node@node-0.acme.org) Predecessor: 42
+> [1040.45356] (node@node-0.acme.org) Well Guys! I Think it's time for me to leave ;)
+> [1090.46137] (maestro@) Simulated time: 1090.46
diff --git a/examples/s4u/dht-chord/s4u_dht-chord_d.xml b/examples/s4u/dht-chord/s4u_dht-chord_d.xml
new file mode 100644 (file)
index 0000000..26e2b17
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version='1.0'?>
+<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid/simgrid.dtd">
+<platform version="4">
+  <process host="node-0.acme.org" function="node">
+    <argument value="42"/>
+    <argument value="1000"/>
+  </process>
+  <process host="node-1.acme.org" function="node">
+    <argument value="366680" />
+    <argument value="42" />
+    <argument value="10" />
+    <argument value="200" />
+  </process>
+  <process host="node-2.acme.org" function="node">
+    <argument value="533744" />
+    <argument value="366680" />
+    <argument value="20" />
+    <argument value="400" />
+  </process>
+  <process host="node-3.acme.org" function="node">
+    <argument value="1319738" />
+    <argument value="42" />
+    <argument value="30" />
+    <argument value="150" />
+  </process>
+  <process host="node-4.acme.org" function="node">
+    <argument value="16509405" />
+    <argument value="366680" />
+    <argument value="40" />
+    <argument value="300" />
+  </process>
+  <process host="node-5.acme.org" function="node">
+    <argument value="10874876" />
+    <argument value="533744" />
+    <argument value="250" />
+    <argument value="600" />
+  </process>
+  <process host="node-6.acme.org" function="node">
+    <argument value="16728096" />
+    <argument value="1319738" />
+    <argument value="60" />
+    <argument value="800" />
+  </process>
+</platform>
\ No newline at end of file