Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Correct a few a/an.
[simgrid.git] / examples / s4u / dht-kademlia / node.cpp
index ba7f12f..86130d5 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2018. The SimGrid Team. All rights reserved.          */
+/* Copyright (c) 2010-2020. 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. */
@@ -11,7 +11,7 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(kademlia_node, "Messages specific for this example"
 namespace kademlia {
 static void destroy(void* message)
 {
-  Message* msg = static_cast<Message*>(message);
+  const auto* msg = static_cast<Message*>(message);
   delete msg->answer_;
   delete msg;
 }
@@ -22,8 +22,7 @@ static void destroy(void* message)
   */
 bool Node::join(unsigned int known_id)
 {
-  Answer* node_list;
-  unsigned int i;
+  const Answer* node_list;
   bool got_answer = false;
 
   /* Add the guy we know to our routing table and ourselves. */
@@ -33,7 +32,7 @@ bool Node::join(unsigned int known_id)
   /* First step: Send a "FIND_NODE" request to the node we know */
   sendFindNode(known_id, id_);
 
-  simgrid::s4u::MailboxPtr mailbox = simgrid::s4u::Mailbox::byName(std::to_string(id_));
+  simgrid::s4u::Mailbox* mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(id_));
   do {
     if (receive_comm == nullptr)
       receive_comm = mailbox->get_async(&received_msg);
@@ -41,10 +40,10 @@ bool Node::join(unsigned int known_id)
       XBT_DEBUG("Received an answer from the node I know.");
       got_answer = true;
       // retrieve the node list and ping them.
-      Message* msg = static_cast<Message*>(received_msg);
+      const auto* msg = static_cast<Message*>(received_msg);
       node_list    = msg->answer_;
       if (node_list) {
-        for (auto contact : node_list->nodes)
+        for (auto const& contact : node_list->getNodes())
           routingTableUpdate(contact.first);
       } else {
         handleFindNode(msg);
@@ -56,15 +55,15 @@ bool Node::join(unsigned int known_id)
       simgrid::s4u::this_actor::sleep_for(1);
   } while (not got_answer);
 
-  /* Second step: Send a FIND_NODE to a random node in buckets */
-  unsigned int bucket_id = table->findBucket(known_id)->getId();
-  xbt_assert(bucket_id <= identifier_size);
-  for (i = 0; ((bucket_id > i) || (bucket_id + i) <= identifier_size) && i < JOIN_BUCKETS_QUERIES; i++) {
+  /* Second step: Send a FIND_NODE to a random node in buckets */
+  unsigned int bucket_id = table.findBucket(known_id)->getId();
+  xbt_assert(bucket_id <= IDENTIFIER_SIZE);
+  for (unsigned int i = 0; ((bucket_id > i) || (bucket_id + i) <= IDENTIFIER_SIZE) && i < JOIN_BUCKETS_QUERIES; i++) {
     if (bucket_id > i) {
       unsigned int id_in_bucket = get_id_in_prefix(id_, bucket_id - i);
       findNode(id_in_bucket, false);
     }
-    if (bucket_id + i <= identifier_size) {
+    if (bucket_id + i <= IDENTIFIER_SIZE) {
       unsigned int id_in_bucket = get_id_in_prefix(id_, bucket_id + i);
       findNode(id_in_bucket, false);
     }
@@ -76,13 +75,14 @@ bool Node::join(unsigned int known_id)
   * @param id node we are querying
   * @param destination node we are trying to find.
   */
-void Node::sendFindNode(unsigned int id, unsigned int destination)
+void Node::sendFindNode(unsigned int id, unsigned int destination) const
 {
   /* Gets the mailbox to send to */
-  simgrid::s4u::MailboxPtr mailbox = simgrid::s4u::Mailbox::byName(std::to_string(id));
+  simgrid::s4u::Mailbox* mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(id));
   /* Build the task */
-  Message* msg = new Message(id_, destination, simgrid::s4u::Mailbox::byName(std::to_string(id_)),
-                             simgrid::s4u::Host::current()->get_cname());
+
+  auto* msg = new Message(id_, destination, simgrid::s4u::Mailbox::by_name(std::to_string(id_)),
+                          simgrid::s4u::Host::current()->get_cname());
 
   /* Send the task */
   mailbox->put_init(msg, 1)->detach(kademlia::destroy);
@@ -90,23 +90,23 @@ void Node::sendFindNode(unsigned int id, unsigned int destination)
 }
 
 /**
-  * Sends to the best "kademlia_alpha" nodes in the "node_list" array a "FIND_NODE" request, to ask them for their best
+  * Sends to the best "KADEMLIA_ALPHA" nodes in the "node_list" array a "FIND_NODE" request, to ask them for their best
   * nodes
   */
-unsigned int Node::sendFindNodeToBest(Answer* node_list)
+unsigned int Node::sendFindNodeToBest(const Answer* node_list) const
 {
   unsigned int i           = 0;
   unsigned int j           = 0;
   unsigned int destination = node_list->getDestinationId();
-  for (auto node_to_query : node_list->nodes) {
-    /* We need to have at most "kademlia_alpha" requests each time, according to the protocol */
+  for (auto const& node_to_query : node_list->getNodes()) {
+    /* We need to have at most "KADEMLIA_ALPHA" requests each time, according to the protocol */
     /* Gets the node we want to send the query to */
     if (node_to_query.first != id_) { /* No need to query ourselves */
       sendFindNode(node_to_query.first, destination);
       j++;
     }
     i++;
-    if (j == kademlia_alpha)
+    if (j == KADEMLIA_ALPHA)
       break;
   }
   return i;
@@ -118,22 +118,22 @@ unsigned int Node::sendFindNodeToBest(Answer* node_list)
 void Node::routingTableUpdate(unsigned int id)
 {
   // retrieval of the bucket in which the should be
-  Bucket* bucket = table->findBucket(id);
+  Bucket* bucket = table.findBucket(id);
 
   // check if the id is already in the bucket.
-  auto id_pos = std::find(bucket->nodes.begin(), bucket->nodes.end(), id);
+  auto id_pos = std::find(bucket->nodes_.begin(), bucket->nodes_.end(), id);
 
-  if (id_pos == bucket->nodes.end()) {
+  if (id_pos == bucket->nodes_.end()) {
     /* We check if the bucket is full or not. If it is, we evict an old element */
-    if (bucket->nodes.size() >= BUCKET_SIZE) {
-      bucket->nodes.pop_back();
+    if (bucket->nodes_.size() >= BUCKET_SIZE) {
+      bucket->nodes_.pop_back();
     }
-    bucket->nodes.push_front(id);
+    bucket->nodes_.push_front(id);
     XBT_VERB("I'm adding to my routing table %08x", id);
   } else {
     // We push the element to the front
-    bucket->nodes.erase(id_pos);
-    bucket->nodes.push_front(id);
+    bucket->nodes_.erase(id_pos);
+    bucket->nodes_.push_front(id);
     XBT_VERB("I'm updating %08x", id);
   }
 }
@@ -144,31 +144,30 @@ void Node::routingTableUpdate(unsigned int id)
   */
 Answer* Node::findClosest(unsigned int destination_id)
 {
-  Answer* answer = new Answer(destination_id);
+  auto* answer = new Answer(destination_id);
   /* We find the corresponding bucket for the id */
-  Bucket* bucket = table->findBucket(destination_id);
+  const Bucket* bucket = table.findBucket(destination_id);
   int bucket_id  = bucket->getId();
-  xbt_assert((bucket_id <= identifier_size), "Bucket found has a wrong identifier");
+  xbt_assert((bucket_id <= IDENTIFIER_SIZE), "Bucket found has a wrong identifier");
   /* So, we copy the contents of the bucket unsigned into our answer */
   answer->addBucket(bucket);
 
-  /* However, if we don't have enough elements in our bucket, we NEED to include at least "bucket_size" elements
-   * (if, of course, we know at least "bucket_size" elements. So we're going to look unsigned into the other buckets.
+  /* However, if we don't have enough elements in our bucket, we NEED to include at least "BUCKET_SIZE" elements
+   * (if, of course, we know at least "BUCKET_SIZE" elements. So we're going to look unsigned into the other buckets.
    */
-  for (int i = 1; answer->getSize() < BUCKET_SIZE && ((bucket_id - i > 0) || (bucket_id + i < identifier_size)); i++) {
+  for (int i = 1; answer->getSize() < BUCKET_SIZE && ((bucket_id - i > 0) || (bucket_id + i < IDENTIFIER_SIZE)); i++) {
     /* We check the previous buckets */
     if (bucket_id - i >= 0) {
-      Bucket* bucket_p = table->buckets[bucket_id - i];
+      const Bucket* bucket_p = &table.getBucketAt(bucket_id - i);
       answer->addBucket(bucket_p);
     }
     /* We check the next buckets */
-    if (bucket_id + i <= identifier_size) {
-      Bucket* bucket_n = table->buckets[bucket_id + i];
+    if (bucket_id + i <= IDENTIFIER_SIZE) {
+      const Bucket* bucket_n = &table.getBucketAt(bucket_id + i);
       answer->addBucket(bucket_n);
     }
   }
-  /* We trim the array to have only bucket_size or less elements */
-  std::sort(answer->nodes.begin(), answer->nodes.end(), sortbydistance);
+  /* We trim the array to have only BUCKET_SIZE or less elements */
   answer->trim();
 
   return answer;
@@ -183,7 +182,7 @@ bool Node::findNode(unsigned int id_to_find, bool count_in_stats)
   unsigned int answers;
   bool destination_found   = false;
   unsigned int nodes_added = 0;
-  double global_timeout    = simgrid::s4u::Engine::getClock() + find_node_global_timeout;
+  double global_timeout    = simgrid::s4u::Engine::get_clock() + FIND_NODE_GLOBAL_TIMEOUT;
   unsigned int steps       = 0;
 
   /* First we build a list of who we already know */
@@ -196,28 +195,28 @@ bool Node::findNode(unsigned int id_to_find, bool count_in_stats)
     answers        = 0;
     queries        = sendFindNodeToBest(node_list);
     nodes_added    = 0;
-    double timeout = simgrid::s4u::Engine::getClock() + find_node_timeout;
+    double timeout = simgrid::s4u::Engine::get_clock() + FIND_NODE_TIMEOUT;
     steps++;
-    double time_beginreceive = simgrid::s4u::Engine::getClock();
+    double time_beginreceive = simgrid::s4u::Engine::get_clock();
 
-    simgrid::s4u::MailboxPtr mailbox = simgrid::s4u::Mailbox::byName(std::to_string(id_));
+    simgrid::s4u::Mailbox* mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(id_));
     do {
       if (receive_comm == nullptr)
         receive_comm = mailbox->get_async(&received_msg);
 
       if (receive_comm->test()) {
-        Message* msg = static_cast<Message*>(received_msg);
+        const auto* msg = static_cast<Message*>(received_msg);
         // Check if what we have received is what we are looking for.
         if (msg->answer_ && msg->answer_->getDestinationId() == id_to_find) {
           routingTableUpdate(msg->sender_id_);
           // Handle the answer
-          for (auto contact : node_list->nodes)
+          for (auto const& contact : node_list->getNodes())
             routingTableUpdate(contact.first);
           answers++;
 
           nodes_added = node_list->merge(msg->answer_);
           XBT_DEBUG("Received an answer from %s (%s) with %zu nodes on it", msg->answer_to_->get_cname(),
-                    msg->issuer_host_name_, msg->answer_->nodes.size());
+                    msg->issuer_host_name_.c_str(), msg->answer_->getSize());
         } else {
           if (msg->answer_) {
             routingTableUpdate(msg->sender_id_);
@@ -226,8 +225,8 @@ bool Node::findNode(unsigned int id_to_find, bool count_in_stats)
             handleFindNode(msg);
           }
           // Update the timeout if we didn't have our answer
-          timeout += simgrid::s4u::Engine::getClock() - time_beginreceive;
-          time_beginreceive = simgrid::s4u::Engine::getClock();
+          timeout += simgrid::s4u::Engine::get_clock() - time_beginreceive;
+          time_beginreceive = simgrid::s4u::Engine::get_clock();
         }
         delete msg->answer_;
         delete msg;
@@ -235,10 +234,10 @@ bool Node::findNode(unsigned int id_to_find, bool count_in_stats)
       } else {
         simgrid::s4u::this_actor::sleep_for(1);
       }
-    } while (simgrid::s4u::Engine::getClock() < timeout && answers < queries);
+    } while (simgrid::s4u::Engine::get_clock() < timeout && answers < queries);
     destination_found = node_list->destinationFound();
   } while (not destination_found && (nodes_added > 0 || answers == 0) &&
-           simgrid::s4u::Engine::getClock() < global_timeout && steps < MAX_STEPS);
+           simgrid::s4u::Engine::get_clock() < global_timeout && steps < MAX_STEPS);
 
   if (destination_found) {
     if (count_in_stats)
@@ -262,25 +261,30 @@ bool Node::findNode(unsigned int id_to_find, bool count_in_stats)
 void Node::randomLookup()
 {
   unsigned int id_to_look = RANDOM_LOOKUP_NODE; // Totally random.
-  /* TODO: Use some pseudo-random generator like RngStream. */
+  /* TODO: Use some pseudo-random generator. */
   XBT_DEBUG("I'm doing a random lookup");
   findNode(id_to_look, true);
 }
 
 /** @brief Handles the answer to an incoming "find_node" task */
-void Node::handleFindNode(Message* msg)
+void Node::handleFindNode(const Message* msg)
 {
   routingTableUpdate(msg->sender_id_);
   XBT_VERB("Received a FIND_NODE from %s (%s), he's trying to find %08x", msg->answer_to_->get_cname(),
-           msg->issuer_host_name_, msg->destination_id_);
+           msg->issuer_host_name_.c_str(), msg->destination_id_);
   // Building the answer to the request
-  Message* answer =
+  auto* answer =
       new Message(id_, msg->destination_id_, findClosest(msg->destination_id_),
-                  simgrid::s4u::Mailbox::byName(std::to_string(id_)), simgrid::s4u::Host::current()->get_cname());
+                  simgrid::s4u::Mailbox::by_name(std::to_string(id_)), simgrid::s4u::Host::current()->get_cname());
   // Sending the answer
   msg->answer_to_->put_init(answer, 1)->detach(kademlia::destroy);
 }
+
+void Node::displaySuccessRate() const
+{
+  XBT_INFO("%u/%u FIND_NODE have succeeded", find_node_success, find_node_success + find_node_failed);
 }
+} // namespace kademlia
 /**@brief Returns an identifier which is in a specific bucket of a routing table
  * @param id id of the routing table owner
  * @param prefix id of the bucket where we want that identifier to be
@@ -290,7 +294,7 @@ unsigned int get_id_in_prefix(unsigned int id, unsigned int prefix)
   if (prefix == 0) {
     return 0;
   } else {
-    return (1U << ((unsigned int)(prefix - 1))) ^ id;
+    return (1U << (prefix - 1)) ^ id;
   }
 }