Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 23 additions & 22 deletions collector/lib/NRadix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@ bool NRadixTree::Insert(const IPNet& network) const {
const uint64_t* net_mask_p = net_mask.data();
uint64_t bit(0x8000000000000000ULL);

nRadixNode* node = this->root_;
nRadixNode* next = this->root_;
nRadixNode* node = this->root_.get();
nRadixNode* next = this->root_.get();

size_t i = 0;
// Traverse the tree for the bits that already exist in the tree.
while (bit & *net_mask_p) {
// If the bit is set, go right, otherwise left.
if (ntohll(*addr_p) & bit) {
next = node->right_;
next = node->right_.get();
} else {
next = node->left_;
next = node->left_.get();
}

if (!next) {
Expand Down Expand Up @@ -90,18 +90,19 @@ bool NRadixTree::Insert(const IPNet& network) const {
CLOG(ERROR) << "CIDR " << network << " already exists";
return false;
}
node->value_ = new IPNet(network);
node->value_ = std::make_unique<IPNet>(network);
return true;
}

// There still are bits to be walked, so go ahead and add them to the tree.
while (bit & *net_mask_p) {
next = new nRadixNode();
auto new_node = std::make_unique<nRadixNode>();
next = new_node.get();

if (ntohll(*addr_p) & bit) {
node->right_ = next;
node->right_ = std::move(new_node);
} else {
node->left_ = next;
node->left_ = std::move(new_node);
}

bit >>= 1;
Expand All @@ -121,7 +122,7 @@ bool NRadixTree::Insert(const IPNet& network) const {
}
}

node->value_ = new IPNet(network);
node->value_ = std::make_unique<IPNet>(network);
return true;
}

Expand All @@ -141,17 +142,17 @@ IPNet NRadixTree::Find(const IPNet& network) const {
uint64_t bit(0x8000000000000000ULL);

IPNet ret;
nRadixNode* node = this->root_;
nRadixNode* node = this->root_.get();
size_t i = 0;
while (node) {
if (node->value_) {
ret = *node->value_;
}

if (ntohll(*addr_p) & bit) {
node = node->right_;
node = node->right_.get();
} else {
node = node->left_;
node = node->left_.get();
}

// All network bits are traversed. If a supernet was found along the way, `ret` holds it,
Expand Down Expand Up @@ -195,13 +196,13 @@ void getAll(nRadixNode* node, std::vector<IPNet>& ret) {
ret.push_back(*node->value_);
}

getAll(node->left_, ret);
getAll(node->right_, ret);
getAll(node->left_.get(), ret);
getAll(node->right_.get(), ret);
}

std::vector<IPNet> NRadixTree::GetAll() const {
std::vector<IPNet> ret;
getAll(this->root_, ret);
getAll(this->root_.get(), ret);
return ret;
}

Expand All @@ -227,11 +228,11 @@ bool isAnyIPNetSubsetUtil(Address::Family family, const nRadixNode* n1, const nR
}

if (n1 && n1->value_) {
containing_net = n1->value_;
containing_net = n1->value_.get();
}

if (n2->value_) {
contained_net = n2->value_;
contained_net = n2->value_.get();
}

// If we find a network in first tree, that means it contains
Expand All @@ -240,11 +241,11 @@ bool isAnyIPNetSubsetUtil(Address::Family family, const nRadixNode* n1, const nR
// finding the smaller network down the path.

if (n1) {
return isAnyIPNetSubsetUtil(family, n1->left_, n2->left_, containing_net, contained_net) ||
isAnyIPNetSubsetUtil(family, n1->right_, n2->right_, containing_net, contained_net);
return isAnyIPNetSubsetUtil(family, n1->left_.get(), n2->left_.get(), containing_net, contained_net) ||
isAnyIPNetSubsetUtil(family, n1->right_.get(), n2->right_.get(), containing_net, contained_net);
}
return isAnyIPNetSubsetUtil(family, nullptr, n2->left_, containing_net, contained_net) ||
isAnyIPNetSubsetUtil(family, nullptr, n2->right_, containing_net, contained_net);
return isAnyIPNetSubsetUtil(family, nullptr, n2->left_.get(), containing_net, contained_net) ||
isAnyIPNetSubsetUtil(family, nullptr, n2->right_.get(), containing_net, contained_net);
}

bool NRadixTree::IsEmpty() const {
Expand All @@ -256,7 +257,7 @@ bool NRadixTree::IsAnyIPNetSubset(const NRadixTree& other) const {
}

bool NRadixTree::IsAnyIPNetSubset(Address::Family family, const NRadixTree& other) const {
return isAnyIPNetSubsetUtil(family, root_, other.root_, nullptr, nullptr);
return isAnyIPNetSubsetUtil(family, root_.get(), other.root_.get(), nullptr, nullptr);
}

} // namespace collector
40 changes: 16 additions & 24 deletions collector/lib/NRadix.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#pragma once

#include <memory>
#include <mutex>

#include "Logging.h"
Expand All @@ -38,45 +39,40 @@ namespace collector {

struct nRadixNode {
nRadixNode() : value_(nullptr), left_(nullptr), right_(nullptr) {}
explicit nRadixNode(const IPNet& value) : value_(new IPNet(value)), left_(nullptr), right_(nullptr) {}
explicit nRadixNode(const IPNet& value) : value_(std::make_unique<IPNet>(value)), left_(nullptr), right_(nullptr) {}

nRadixNode(const nRadixNode& other) : value_(nullptr), left_(nullptr), right_(nullptr) {
if (other.value_) {
value_ = new IPNet(*other.value_);
value_ = std::make_unique<IPNet>(*other.value_);
}
if (other.left_) {
left_ = new nRadixNode(*other.left_);
left_ = std::make_unique<nRadixNode>(*other.left_);
}
if (other.right_) {
right_ = new nRadixNode(*other.right_);
right_ = std::make_unique<nRadixNode>(*other.right_);
}
}

nRadixNode& operator=(const nRadixNode& other) {
if (this == &other) {
return *this;
}
auto* new_node = new nRadixNode(other);
auto new_node = std::make_unique<nRadixNode>(other);
std::swap(*new_node, *this);
delete new_node;
return *this;
}

~nRadixNode() {
delete left_;
delete right_;
delete value_;
}
~nRadixNode() = default;

const IPNet* value_;
nRadixNode* left_;
nRadixNode* right_;
std::unique_ptr<const IPNet> value_;
std::unique_ptr<nRadixNode> left_;
std::unique_ptr<nRadixNode> right_;
};

class NRadixTree {
public:
NRadixTree() : root_(new nRadixNode()) {}
explicit NRadixTree(const std::vector<IPNet>& networks) : root_(new nRadixNode()) {
NRadixTree() : root_(std::make_unique<nRadixNode>()) {}
explicit NRadixTree(const std::vector<IPNet>& networks) : root_(std::make_unique<nRadixNode>()) {
for (const auto& network : networks) {
auto inserted = this->Insert(network);
if (!inserted) {
Expand All @@ -85,20 +81,16 @@ class NRadixTree {
}
}

NRadixTree(const NRadixTree& other) : root_(new nRadixNode(*other.root_)) {}
NRadixTree(const NRadixTree& other) : root_(std::make_unique<nRadixNode>(*other.root_)) {}

~NRadixTree() {
// This calls the node destructor which in turn cleans up all the nodes.
delete root_;
}
~NRadixTree() = default;

NRadixTree& operator=(const NRadixTree& other) {
if (this == &other) {
return *this;
}
delete root_;
// This calls the node copy constructor which in turn copies all the nodes.
root_ = new nRadixNode(*other.root_);
root_ = std::make_unique<nRadixNode>(*other.root_);
return *this;
}

Expand All @@ -120,7 +112,7 @@ class NRadixTree {
// Determines whether any network in `other` is fully contained by any network in this tree, for a given family.
bool IsAnyIPNetSubset(Address::Family family, const NRadixTree& other) const;

nRadixNode* root_;
std::unique_ptr<nRadixNode> root_;
};

} // namespace collector
Loading