X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/d8eb62b207b566949a0d9ce649a7b21e226b9168..39c935d6d5ee86d153f6f7e6a10d723ae7c57f6f:/examples/s4u/dht-chord/s4u-dht-chord-node.cpp diff --git a/examples/s4u/dht-chord/s4u-dht-chord-node.cpp b/examples/s4u/dht-chord/s4u-dht-chord-node.cpp index 90ae8c18b4..4a2e4f53c6 100644 --- a/examples/s4u/dht-chord/s4u-dht-chord-node.cpp +++ b/examples/s4u/dht-chord/s4u-dht-chord-node.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2018. The SimGrid Team. All rights reserved. */ +/* Copyright (c) 2010-2021. 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. */ @@ -20,9 +20,9 @@ XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(s4u_chord); * @param id id to check * @param start lower bound * @param end upper bound - * @return a non-zero value if id in in [start, end] + * @return true if id in in [start, end] */ -static int is_in_interval(int id, int start, int end) +static bool is_in_interval(int id, int start, int end) { int i = id % nb_keys; int s = start % nb_keys; @@ -52,14 +52,11 @@ Node::Node(std::vector args) // initialize my node id_ = std::stoi(args[1]); - stream = simgrid::s4u::this_actor::get_host()->extension()->getStream(); + XBT_DEBUG("Initialize node with id: %d", id_); + random.set_seed(id_); mailbox_ = simgrid::s4u::Mailbox::by_name(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_; - } + fingers_.resize(nb_bits, id_); if (args.size() == 3) { // first ring deadline_ = std::stod(args[2]); @@ -74,10 +71,6 @@ Node::Node(std::vector args) } } -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 @@ -111,34 +104,30 @@ void Node::leave() void Node::notifyAndQuit() { // send the PREDECESSOR_LEAVING to our successor - ChordMessage* pred_msg = new ChordMessage(PREDECESSOR_LEAVING); + auto* pred_msg = new ChordMessage(MessageType::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::Mailbox::by_name(std::to_string(fingers_[0]))->put(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; - } + } catch (const simgrid::TimeoutException&) { + XBT_DEBUG("Timeout expired when sending a 'PREDECESSOR_LEAVING' to my successor %d", fingers_[0]); + delete pred_msg; } if (pred_id_ != -1 && pred_id_ != id_) { // send the SUCCESSOR_LEAVING to our predecessor (only if I have one that is not me) - ChordMessage* succ_msg = new ChordMessage(SUCCESSOR_LEAVING); + auto* succ_msg = new ChordMessage(MessageType::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::Mailbox::by_name(std::to_string(pred_id_))->put(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; - } + } catch (const simgrid::TimeoutException&) { + XBT_DEBUG("Timeout expired when sending a 'SUCCESSOR_LEAVING' to my predecessor %d", pred_id_); + delete succ_msg; } } } @@ -147,7 +136,7 @@ void Node::notifyAndQuit() void Node::randomLookup() { int res = id_; - int random_index = RngStream_RandInt(stream, 0, nb_bits - 1); + int random_index = random.uniform_int(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_) @@ -212,41 +201,38 @@ void Node::printFingerTable() 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::by_name(std::to_string(pred_id_)); - simgrid::s4u::MailboxPtr return_mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(id_) + "_is_alive"); + simgrid::s4u::Mailbox* mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(pred_id_)); + simgrid::s4u::Mailbox* return_mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(id_) + "_is_alive"); - ChordMessage* message = new ChordMessage(PREDECESSOR_ALIVE); + auto* message = new ChordMessage(MessageType::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 { mailbox->put(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; - } + } catch (const simgrid::TimeoutException&) { + 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->get_cname()); - simgrid::s4u::CommPtr comm = return_mailbox->get_async(&data); + ChordMessage* answer = nullptr; + simgrid::s4u::CommPtr comm = return_mailbox->get_async(&answer); try { - comm->wait(timeout); + comm->wait_for(timeout); XBT_DEBUG("Received the answer to my 'Predecessor Alive': my predecessor %d is alive", pred_id_); - delete static_cast(data); - } catch (xbt_ex& e) { - if (e.category == timeout_error) { - XBT_DEBUG("Failed to receive the answer to my 'Predecessor Alive' request"); - pred_id_ = -1; - } + delete answer; + } catch (const simgrid::TimeoutException&) { + XBT_DEBUG("Failed to receive the answer to my 'Predecessor Alive' request"); + pred_id_ = -1; } } @@ -258,11 +244,10 @@ void Node::checkPredecessor() int Node::remoteGetPredecessor(int ask_to) { int predecessor_id = -1; - void* data = nullptr; - simgrid::s4u::MailboxPtr mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(ask_to)); - simgrid::s4u::MailboxPtr return_mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(id_) + "_pred"); + simgrid::s4u::Mailbox* mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(ask_to)); + simgrid::s4u::Mailbox* return_mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(id_) + "_pred"); - ChordMessage* message = new ChordMessage(GET_PREDECESSOR); + auto* message = new ChordMessage(MessageType::GET_PREDECESSOR); message->request_id = id_; message->answer_to = return_mailbox; @@ -270,31 +255,27 @@ int Node::remoteGetPredecessor(int ask_to) XBT_DEBUG("Sending a 'Get Predecessor' request to %d", ask_to); try { mailbox->put(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; - } + } catch (const simgrid::TimeoutException&) { + 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->get_cname()); - simgrid::s4u::CommPtr comm = return_mailbox->get_async(&data); + ChordMessage* answer = nullptr; + simgrid::s4u::CommPtr comm = return_mailbox->get_async(&answer); try { - comm->wait(timeout); - ChordMessage* answer = static_cast(data); + comm->wait_for(timeout); 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(data); - } + } catch (const simgrid::TimeoutException&) { + XBT_DEBUG("Failed to receive the answer to my 'Get Predecessor' request"); + delete answer; } return predecessor_id; @@ -334,11 +315,10 @@ int Node::findSuccessor(int id) int Node::remoteFindSuccessor(int ask_to, int id) { int successor = -1; - void* data = nullptr; - simgrid::s4u::MailboxPtr mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(ask_to)); - simgrid::s4u::MailboxPtr return_mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(id_) + "_succ"); + simgrid::s4u::Mailbox* mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(ask_to)); + simgrid::s4u::Mailbox* return_mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(id_) + "_succ"); - ChordMessage* message = new ChordMessage(FIND_SUCCESSOR); + auto* message = new ChordMessage(MessageType::FIND_SUCCESSOR); message->request_id = id_; message->answer_to = return_mailbox; @@ -346,30 +326,27 @@ int Node::remoteFindSuccessor(int ask_to, int id) XBT_DEBUG("Sending a 'Find Successor' request to %d for id %d", ask_to, id); try { mailbox->put(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; - } + } catch (const simgrid::TimeoutException&) { + 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::CommPtr comm = return_mailbox->get_async(&data); + ChordMessage* answer = nullptr; + simgrid::s4u::CommPtr comm = return_mailbox->get_async(&answer); try { - comm->wait(timeout); - ChordMessage* answer = static_cast(data); + comm->wait_for(timeout); 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(data); - } + } catch (const simgrid::TimeoutException&) { + XBT_DEBUG("Failed to receive the answer to my 'Find Successor' request"); + delete answer; } + return successor; } @@ -385,15 +362,15 @@ void Node::notify(int predecessor_candidate_id) } /* Notifies a remote node that its predecessor may have changed. */ -void Node::remoteNotify(int notify_id, int predecessor_candidate_id) +void Node::remoteNotify(int notify_id, int predecessor_candidate_id) const { - ChordMessage* message = new ChordMessage(NOTIFY); + auto* message = new ChordMessage(MessageType::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::by_name(std::to_string(notify_id)); + simgrid::s4u::Mailbox* mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(notify_id)); mailbox->put_init(message, 10)->detach(ChordMessage::destroy); } @@ -424,76 +401,150 @@ void Node::stabilize() 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->get_cname(), message->request_id, - message->answer_id); + case MessageType::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 = MessageType::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->get_cname(), message->request_id, + message->answer_id); + message->answer_to->put_init(message, 10)->detach(ChordMessage::destroy); + } 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::Mailbox* mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(closest)); + mailbox->put_init(message, 10)->detach(ChordMessage::destroy); + } + break; + + case MessageType::GET_PREDECESSOR: + XBT_DEBUG("Receiving a 'Get Predecessor' request from %s", message->issuer_host_name.c_str()); + message->type = MessageType::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->get_cname(), message->answer_id); message->answer_to->put_init(message, 10)->detach(ChordMessage::destroy); + break; + + case MessageType::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 MessageType::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 MessageType::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 MessageType::PREDECESSOR_ALIVE: + XBT_DEBUG("Receiving a 'Predecessor Alive' request from %s", message->issuer_host_name.c_str()); + message->type = MessageType::PREDECESSOR_ALIVE_ANSWER; + XBT_DEBUG("Sending back a 'Predecessor Alive Answer' to %s (mailbox %s)", message->issuer_host_name.c_str(), + message->answer_to->get_cname()); + message->answer_to->put_init(message, 10)->detach(ChordMessage::destroy); + break; + + default: + XBT_DEBUG("Ignoring unexpected message: %d from %s", static_cast(message->type), + message->issuer_host_name.c_str()); + delete message; + } +} + +void Node::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 (not joined) + return; + ChordMessage* message = nullptr; + double now = simgrid::s4u::Engine::get_clock(); + 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; + simgrid::s4u::CommPtr comm_receive = nullptr; + while (now < std::min(start_time_ + deadline_, MAX_SIMULATION_TIME)) { + if (comm_receive == nullptr) + comm_receive = mailbox_->get_async(&message); + bool comm_completed = true; + try { + if (not comm_receive->test()) + comm_completed = false; + } catch (const simgrid::TimeoutException&) { + XBT_DEBUG("Caught a timeout, go ahead."); + } + + if (comm_completed) { + if (message != nullptr) { + handleMessage(message); + message = nullptr; + } + comm_receive = nullptr; } 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::by_name(std::to_string(closest)); - mailbox->put_init(message, 10)->detach(ChordMessage::destroy); + // no task was received: make some periodic calls + if (now >= next_stabilize_date) { + stabilize(); + next_stabilize_date = simgrid::s4u::Engine::get_clock() + PERIODIC_STABILIZE_DELAY; + } else if (now >= next_fix_fingers_date) { + fixFingers(); + next_fix_fingers_date = simgrid::s4u::Engine::get_clock() + PERIODIC_FIX_FINGERS_DELAY; + } else if (now >= next_check_predecessor_date) { + checkPredecessor(); + next_check_predecessor_date = simgrid::s4u::Engine::get_clock() + PERIODIC_CHECK_PREDECESSOR_DELAY; + } else if (now >= next_lookup_date) { + randomLookup(); + next_lookup_date = simgrid::s4u::Engine::get_clock() + PERIODIC_LOOKUP_DELAY; + } else { + // nothing to do: sleep for a while + simgrid::s4u::this_actor::sleep_for(SLEEP_DELAY); + } } - 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->get_cname(), message->answer_id); - message->answer_to->put_init(message, 10)->detach(ChordMessage::destroy); - 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->get_cname()); - message->answer_to->put_init(message, 10)->detach(ChordMessage::destroy); - break; - - default: - XBT_DEBUG("Ignoring unexpected message: %d from %s", message->type, message->issuer_host_name.c_str()); - delete message; + now = simgrid::s4u::Engine::get_clock(); + } + if (comm_receive != nullptr) { + try { + if (comm_receive->test()) + delete message; + else + comm_receive->cancel(); + } catch (const simgrid::TimeoutException&) { + XBT_DEBUG("Caught a timeout for last message, nevermind."); + } } + // leave the ring + leave(); }