Skip to content

Commit

Permalink
refactor(minhton): Stateless hop count usage
Browse files Browse the repository at this point in the history
  • Loading branch information
palask committed Sep 14, 2023
1 parent 6cf9e75 commit ab20000
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "minhton/message/types_all.h"

namespace minhton {
#define MAX_HOP_COUNT 64U

class MinhtonFindEndAlgorithm : public AlgorithmInterface {
public:
Expand All @@ -23,19 +22,21 @@ class MinhtonFindEndAlgorithm : public AlgorithmInterface {

void process(const MessageVariant &) override {}

/// Helper method to send a message for forwarding the join / Leave request to another node
/// Helper method to send a message for forwarding the join / leave request to another node
///
/// \param target Node to forward the join / leave request to
/// \param request_origin The node which wishes to join / leave the network
/// \param search_progress The current step of the join / leave algorithm
/// \param hop_count Counter for how many times the request has been forwarded
void forwardRequest(minhton::NodeInfo target, minhton::NodeInfo request_origin,
SearchProgress search_progress);
SearchProgress search_progress, uint16_t hop_count);

/// Helper method to jump to the most beneficial adjacent node (during a join / leave)
///
/// \param request_origin The new node that wants to join or the existing node that wants to leave
/// the network.
void forwardToAdjacentNode(minhton::NodeInfo request_origin);
/// \param hop_count Counter for how many times the request has been forwarded
void forwardToAdjacentNode(minhton::NodeInfo request_origin, uint16_t hop_count);

/// Helper method to check if the current node is the wanted join / leave replacement node
/// position. Only use after it is known which level is the last one!
Expand All @@ -48,7 +49,8 @@ class MinhtonFindEndAlgorithm : public AlgorithmInterface {
/// \param request_origin The new node that wants to join or the existing node that wants to leave
/// the network.
/// \param left_side Set to true to only search on the left side, else on the right side
void searchEndOnLevel(minhton::NodeInfo request_origin, bool left_side);
/// \param hop_count Counter for how many times the request has been forwarded
void searchEndOnLevel(minhton::NodeInfo request_origin, bool left_side, uint16_t hop_count);

/// Helper method to get a node which is either the direct parent of a node or somewhere close to
/// where the actual parent is, if the parent isn't in the routing table
Expand All @@ -61,7 +63,8 @@ class MinhtonFindEndAlgorithm : public AlgorithmInterface {
///
/// \param request_origin The new node that wants to join or the existing node that wants to leave
/// the network.
void checkRight(minhton::NodeInfo request_origin);
/// \param hop_count Counter for how many times the request has been forwarded
void checkRight(minhton::NodeInfo request_origin, uint16_t hop_count);

/// Helper method to check if the passed node is the last one that can exists on a level and is
/// initialized
Expand All @@ -76,19 +79,13 @@ class MinhtonFindEndAlgorithm : public AlgorithmInterface {
/// \param request_origin The new node that wants to join or the existing node that wants to leave
/// the network.
/// \returns true when found correct position, false when concurrent steps are needed
bool decideNextStep(minhton::NodeInfo request_origin);

void setHopCount(uint16_t hop_count);

void resetHopCount();
/// \param hop_count Counter for how many times the request has been forwarded
bool decideNextStep(minhton::NodeInfo request_origin, uint16_t hop_count);

private:
/// Set to true if the Find End Algorithm should operate in the mode for the join procedure, or
/// set to false for usage with the leave procedure
bool join_;

/// How often message for finding the position has been sent during this procedure so far
uint16_t hop_count_ = 0;
};

} // namespace minhton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,21 @@
#include "minhton/logging/logging.h"

namespace minhton {
static constexpr uint16_t kMaxHopCount = 64U;

void MinhtonFindEndAlgorithm::forwardRequest(const minhton::NodeInfo target,
const minhton::NodeInfo request_origin,
SearchProgress search_progress) {
SearchProgress search_progress, uint16_t hop_count) {
uint16_t new_hop_count = ++hop_count;
if (new_hop_count > kMaxHopCount) {
throw std::runtime_error("MINHTON message to be forwarded exceeds max hop count");
}

MinhtonMessageHeader header(getSelfNodeInfo(), target);

if (join_) {
header.setRefEventId(access_->procedure_info->loadEventId(ProcedureKey::kJoinProcedure));
MessageJoin msg_to_forward(header, request_origin, search_progress, ++hop_count_);
MessageJoin msg_to_forward(header, request_origin, search_progress, new_hop_count);
send(msg_to_forward);
access_->procedure_info->removeEventId(ProcedureKey::kJoinProcedure);
} else {
Expand All @@ -30,7 +36,7 @@ void MinhtonFindEndAlgorithm::forwardRequest(const minhton::NodeInfo target,
header.setRefEventId(ref_event_id);
}

MessageFindReplacement msg_to_forward(header, request_origin, search_progress, ++hop_count_);
MessageFindReplacement msg_to_forward(header, request_origin, search_progress, new_hop_count);
send(msg_to_forward);
if (ref_event_id == 0U) {
auto event_id = msg_to_forward.getHeader().getEventId();
Expand All @@ -40,7 +46,8 @@ void MinhtonFindEndAlgorithm::forwardRequest(const minhton::NodeInfo target,
}
}

void MinhtonFindEndAlgorithm::forwardToAdjacentNode(const minhton::NodeInfo request_origin) {
void MinhtonFindEndAlgorithm::forwardToAdjacentNode(const minhton::NodeInfo request_origin,
uint16_t hop_count) {
auto level_capacity = pow(getSelfNodeInfo().getFanout(), getSelfNodeInfo().getLevel());
bool in_left_half = getSelfNodeInfo().getNumber() + 1 < (level_capacity / 2);
minhton::NodeInfo target;
Expand All @@ -57,7 +64,7 @@ void MinhtonFindEndAlgorithm::forwardToAdjacentNode(const minhton::NodeInfo requ
throw std::logic_error("Adjacent node isn't initialized");
}

forwardRequest(target, request_origin, SearchProgress::kNone);
forwardRequest(target, request_origin, SearchProgress::kNone, hop_count);
}

bool MinhtonFindEndAlgorithm::isCorrectParent() {
Expand Down Expand Up @@ -99,7 +106,7 @@ bool MinhtonFindEndAlgorithm::isCorrectParent() {
}

void MinhtonFindEndAlgorithm::searchEndOnLevel(const minhton::NodeInfo request_origin,
bool left_side) {
bool left_side, uint16_t hop_count) {
std::vector<minhton::NodeInfo> chosen_side_init;
if (left_side) {
chosen_side_init = getRoutingInfo()->getAllInitializedLeftRoutingTableNeighborsAndChildren();
Expand All @@ -119,7 +126,8 @@ void MinhtonFindEndAlgorithm::searchEndOnLevel(const minhton::NodeInfo request_o
}

// Perfect tree during leave procedure, forward to own parent
forwardRequest(getRoutingInfo()->getParent(), request_origin, SearchProgress::kSearchRight);
forwardRequest(getRoutingInfo()->getParent(), request_origin, SearchProgress::kSearchRight,
hop_count);
return;
}

Expand All @@ -133,11 +141,11 @@ void MinhtonFindEndAlgorithm::searchEndOnLevel(const minhton::NodeInfo request_o
}
// If we search the left side: Continue searching on the left side
// Else: The neighbor directly on the right should be the final position
forwardRequest(chosen_side_init.front(), request_origin,
static_cast<SearchProgress>(left_side));
forwardRequest(chosen_side_init.front(), request_origin, static_cast<SearchProgress>(left_side),
hop_count);
} else {
auto closest_node_to_parent = findReachableNodeClosestToParent(last_child);
forwardRequest(closest_node_to_parent, request_origin, SearchProgress::kSearchRight);
forwardRequest(closest_node_to_parent, request_origin, SearchProgress::kSearchRight, hop_count);
}
}

Expand All @@ -163,7 +171,8 @@ minhton::NodeInfo MinhtonFindEndAlgorithm::findReachableNodeClosestToParent(
return last_known_null_node;
}

void MinhtonFindEndAlgorithm::checkRight(const minhton::NodeInfo request_origin) {
void MinhtonFindEndAlgorithm::checkRight(const minhton::NodeInfo request_origin,
uint16_t hop_count) {
auto rightmost_neighbor = getRoutingInfo()->getRightmostNeighbor();

// We are at rightmost possible node
Expand All @@ -175,14 +184,15 @@ void MinhtonFindEndAlgorithm::checkRight(const minhton::NodeInfo request_origin)
if (rightmost_neighbor.isInitialized()) {
// Is the rightmost possible neighbor initialized and in our routing infos?
if (isRightmostPossibleNode(rightmost_neighbor)) {
searchEndOnLevel(request_origin, true);
searchEndOnLevel(request_origin, true, hop_count);
} else {
// Continue looking for the end of the level
forwardRequest(rightmost_neighbor, request_origin, SearchProgress::kCheckRight);
forwardRequest(rightmost_neighbor, request_origin, SearchProgress::kCheckRight, hop_count);
}
} else {
// Rightmost neighbor doesn't exist yet, so hop to the level below and seach to the right there
forwardRequest(getRoutingInfo()->getParent(), request_origin, SearchProgress::kSearchRight);
forwardRequest(getRoutingInfo()->getParent(), request_origin, SearchProgress::kSearchRight,
hop_count);
}
}

Expand All @@ -191,7 +201,8 @@ bool MinhtonFindEndAlgorithm::isRightmostPossibleNode(const minhton::NodeInfo no
return at_rightmost_number && node.isInitialized();
}

bool MinhtonFindEndAlgorithm::decideNextStep(const minhton::NodeInfo request_origin) {
bool MinhtonFindEndAlgorithm::decideNextStep(const minhton::NodeInfo request_origin,
uint16_t hop_count) {
// Check left neighbors
auto leftmost_neighbor_child = getRoutingInfo()->getLeftmostNeighborChild();
if (leftmost_neighbor_child.isValidPeer()) {
Expand All @@ -202,7 +213,7 @@ bool MinhtonFindEndAlgorithm::decideNextStep(const minhton::NodeInfo request_ori

// Has the leftmost neighbor at least one child?
if (leftmost_neighbor_child.isInitialized()) {
searchEndOnLevel(request_origin, true);
searchEndOnLevel(request_origin, true, hop_count);
return false;
}
}
Expand All @@ -228,11 +239,11 @@ bool MinhtonFindEndAlgorithm::decideNextStep(const minhton::NodeInfo request_ori

// Search on a direction depending on the own capacity for children
bool search_on_left_side = !(getRoutingInfo()->areChildrenFull());
searchEndOnLevel(request_origin, search_on_left_side);
searchEndOnLevel(request_origin, search_on_left_side, hop_count);
return false;
}

forwardRequest(target, request_origin, search_progress);
forwardRequest(target, request_origin, search_progress, hop_count);
return false;
}

Expand All @@ -242,17 +253,8 @@ bool MinhtonFindEndAlgorithm::decideNextStep(const minhton::NodeInfo request_ori
return true;
}

searchEndOnLevel(request_origin, true);
searchEndOnLevel(request_origin, true, hop_count);
return false;
}

void MinhtonFindEndAlgorithm::setHopCount(uint16_t hop_count) {
if (hop_count > MAX_HOP_COUNT) {
throw std::runtime_error("Incoming MINHTON message exceeds max hop count");
}
hop_count_ = hop_count;
}

void MinhtonFindEndAlgorithm::resetHopCount() { hop_count_ = 0; }

} // namespace minhton
11 changes: 4 additions & 7 deletions minhton/src/algorithms/join/minhton_join_algorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ void MinhtonJoinAlgorithm::processJoin(const MessageJoin &msg) {
access_->procedure_info->saveEventId(ProcedureKey::kJoinProcedure,
msg.getHeader().getRefEventId());
}
find_end_helper_.setHopCount(msg.getHopCount());

NodeInfo entering_node = msg.getEnteringNode();
bool accept = false;
Expand All @@ -37,9 +36,9 @@ void MinhtonJoinAlgorithm::processJoin(const MessageJoin &msg) {
case SearchProgress::kNone:
// Check if it's not a null node
if (getRoutingInfo()->areChildrenFull()) {
find_end_helper_.forwardToAdjacentNode(entering_node);
find_end_helper_.forwardToAdjacentNode(entering_node, msg.getHopCount());
} else {
accept = find_end_helper_.decideNextStep(entering_node);
accept = find_end_helper_.decideNextStep(entering_node, msg.getHopCount());
}
break;

Expand All @@ -51,14 +50,14 @@ void MinhtonJoinAlgorithm::processJoin(const MessageJoin &msg) {
if (!accept) {
// The SearchProgress is either left (1) or right (0) in this case
auto search_left = static_cast<bool>(msg.getSearchProgress());
find_end_helper_.searchEndOnLevel(entering_node, search_left);
find_end_helper_.searchEndOnLevel(entering_node, search_left, msg.getHopCount());
}
break;

// Find out whether the current level is completely filled (level h-2 or perfect tree) or not
// (level h-1)
case SearchProgress::kCheckRight:
find_end_helper_.checkRight(entering_node);
find_end_helper_.checkRight(entering_node, msg.getHopCount());
break;

default:
Expand All @@ -70,8 +69,6 @@ void MinhtonJoinAlgorithm::processJoin(const MessageJoin &msg) {
if (accept) {
performAcceptChild(entering_node, true);
}

find_end_helper_.resetHopCount();
}

uint32_t MinhtonJoinAlgorithm::performSendUpdateNeighborMessagesAboutEnteringNode(
Expand Down
19 changes: 9 additions & 10 deletions minhton/src/algorithms/leave/minhton_leave_algorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,9 @@ void MinhtonLeaveAlgorithm::processFindReplacement(const minhton::MessageFindRep
event_id = message.getHeader().getEventId();
}
this->access_->procedure_info->saveEventId(ProcedureKey::kLeaveProcedure, event_id);
find_end_helper_.setHopCount(message.getHopCount());

this->performFindReplacement(message);
this->access_->procedure_info->removeEventId(ProcedureKey::kLeaveProcedure);
find_end_helper_.resetHopCount();
}

void MinhtonLeaveAlgorithm::performFindReplacement() {
Expand All @@ -73,16 +71,16 @@ void MinhtonLeaveAlgorithm::performFindReplacement() {

// Check if the start position is not a null node
if (getRoutingInfo()->areChildrenFull()) {
find_end_helper_.forwardToAdjacentNode(leaving_node);
find_end_helper_.forwardToAdjacentNode(leaving_node, 0);
} else {
is_correct_parent = find_end_helper_.decideNextStep(leaving_node);
is_correct_parent = find_end_helper_.decideNextStep(leaving_node, 0);
}

// Currently at the parent of the last node of the network
if (is_correct_parent) {
auto last_child = getRoutingInfo()->getInitializedChildren().back();
// Forward to last child with own SearchProgress just for this case
find_end_helper_.forwardRequest(last_child, leaving_node, SearchProgress::kReplacementNode);
find_end_helper_.forwardRequest(last_child, leaving_node, SearchProgress::kReplacementNode, 0);
}
}

Expand All @@ -108,9 +106,9 @@ void MinhtonLeaveAlgorithm::performFindReplacement(const minhton::MessageFindRep
LOG_INFO("FR Case 1");
// Check if it's not a null node
if (getRoutingInfo()->areChildrenFull()) {
find_end_helper_.forwardToAdjacentNode(leaving_node);
find_end_helper_.forwardToAdjacentNode(leaving_node, msg.getHopCount());
} else {
is_correct_parent = find_end_helper_.decideNextStep(leaving_node);
is_correct_parent = find_end_helper_.decideNextStep(leaving_node, msg.getHopCount());
}
break;

Expand All @@ -121,15 +119,15 @@ void MinhtonLeaveAlgorithm::performFindReplacement(const minhton::MessageFindRep
// Check if we already are at the correct node to join
is_correct_parent = find_end_helper_.isCorrectParent();
if (!is_correct_parent) {
find_end_helper_.searchEndOnLevel(leaving_node, static_cast<bool>(prog));
find_end_helper_.searchEndOnLevel(leaving_node, static_cast<bool>(prog), msg.getHopCount());
}
break;

// Find out whether the current level is completely filled (level h-2 or perfect tree) or not
// (level h-1)
case SearchProgress::kCheckRight:
LOG_INFO("FR Case 3");
find_end_helper_.checkRight(leaving_node);
find_end_helper_.checkRight(leaving_node, msg.getHopCount());
break;

// The current node emerged as the last node of the network
Expand Down Expand Up @@ -159,7 +157,8 @@ void MinhtonLeaveAlgorithm::performFindReplacement(const minhton::MessageFindRep
if (is_correct_parent) {
auto last_child = getRoutingInfo()->getInitializedChildren().back();
// Forward to last child with own SearchProgress just for this case
find_end_helper_.forwardRequest(last_child, leaving_node, SearchProgress::kReplacementNode);
find_end_helper_.forwardRequest(last_child, leaving_node, SearchProgress::kReplacementNode,
msg.getHopCount());
}
}

Expand Down

0 comments on commit ab20000

Please sign in to comment.