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
${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()
--- /dev/null
+/* 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;
+ }
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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
--- /dev/null
+#! ./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
--- /dev/null
+<?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