2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-03 07:25:18 +00:00

Merge branch 'master' into jreed-docs

This commit is contained in:
Jeremy C. Reed
2011-01-20 11:54:06 -06:00
8 changed files with 210 additions and 82 deletions

View File

@@ -1,3 +1,11 @@
154. [bug] jinmei
b10-xfrin/b10-zonemgr: Fixed a bug where these programs didn't
receive command responses from CC sessions. Eventually the
receive buffer became full, and many other components that rely
on CC channels would stall (as noted in #420 and #513). This is
an urgent care fix due to the severity of the problem; we'll need
to revisit it for cleaner fix later. (Trac #516, git 62c72fc)
153. [bug] jelte 153. [bug] jelte
b10-cfgmgr: Fixed a bug where configuration updates sometimes b10-cfgmgr: Fixed a bug where configuration updates sometimes
lost previous settings in the configuration manager. lost previous settings in the configuration manager.

View File

@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_PREREQ([2.59]) AC_PREREQ([2.59])
AC_INIT(bind10-devel, 20101201, bind10-dev@isc.org) AC_INIT(bind10-devel, 20110120, bind10-dev@isc.org)
AC_CONFIG_SRCDIR(README) AC_CONFIG_SRCDIR(README)
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
@@ -714,7 +714,6 @@ AC_OUTPUT([doc/version.ent
chmod +x src/bin/cmdctl/run_b10-cmdctl.sh chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
chmod +x src/bin/xfrin/run_b10-xfrin.sh chmod +x src/bin/xfrin/run_b10-xfrin.sh
chmod +x src/bin/xfrout/run_b10-xfrout.sh chmod +x src/bin/xfrout/run_b10-xfrout.sh
chmod +x src/bin/resolver/run_b10-resolver.sh
chmod +x src/bin/zonemgr/run_b10-zonemgr.sh chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
chmod +x src/bin/stats/tests/stats_test chmod +x src/bin/stats/tests/stats_test
chmod +x src/bin/stats/run_b10-stats.sh chmod +x src/bin/stats/run_b10-stats.sh

View File

@@ -66,6 +66,8 @@ private:
public: public:
ResolverImpl() : ResolverImpl() :
config_session_(NULL), config_session_(NULL),
timeout_(2000),
retries_(3),
rec_query_(NULL) rec_query_(NULL)
{} {}
@@ -76,7 +78,7 @@ public:
void querySetup(DNSService& dnss) { void querySetup(DNSService& dnss) {
assert(!rec_query_); // queryShutdown must be called first assert(!rec_query_); // queryShutdown must be called first
dlog("Query setup"); dlog("Query setup");
rec_query_ = new RecursiveQuery(dnss, upstream_); rec_query_ = new RecursiveQuery(dnss, upstream_, timeout_, retries_);
} }
void queryShutdown() { void queryShutdown() {

22
src/bin/xfrin/xfrin.py.in Normal file → Executable file
View File

@@ -521,8 +521,19 @@ class Xfrin:
msg = create_command(notify_out.ZONE_NEW_DATA_READY_CMD, param) msg = create_command(notify_out.ZONE_NEW_DATA_READY_CMD, param)
# catch the exception, in case msgq has been killed. # catch the exception, in case msgq has been killed.
try: try:
self._send_cc_session.group_sendmsg(msg, XFROUT_MODULE_NAME) seq = self._send_cc_session.group_sendmsg(msg,
self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME) XFROUT_MODULE_NAME)
try:
answer, env = self._send_cc_session.group_recvmsg(False,
seq)
except isc.cc.session.SessionTimeout:
pass # for now we just ignore the failure
seq = self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
try:
answer, env = self._send_cc_session.group_recvmsg(False,
seq)
except isc.cc.session.SessionTimeout:
pass # for now we just ignore the failure
except socket.error as err: except socket.error as err:
log_error("Fail to send message to %s and %s, msgq may has been killed" log_error("Fail to send message to %s and %s, msgq may has been killed"
% (XFROUT_MODULE_NAME, ZONE_MANAGER_MODULE_NAME)) % (XFROUT_MODULE_NAME, ZONE_MANAGER_MODULE_NAME))
@@ -530,7 +541,12 @@ class Xfrin:
msg = create_command(ZONE_XFRIN_FAILED, param) msg = create_command(ZONE_XFRIN_FAILED, param)
# catch the exception, in case msgq has been killed. # catch the exception, in case msgq has been killed.
try: try:
self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME) seq = self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
try:
answer, env = self._send_cc_session.group_recvmsg(False,
seq)
except isc.cc.session.SessionTimeout:
pass # for now we just ignore the failure
except socket.error as err: except socket.error as err:
log_error("Fail to send message to %s, msgq may has been killed" log_error("Fail to send message to %s, msgq may has been killed"
% ZONE_MANAGER_MODULE_NAME) % ZONE_MANAGER_MODULE_NAME)

View File

@@ -43,6 +43,9 @@ class MySession():
if module_name not in ("Auth", "Xfrin"): if module_name not in ("Auth", "Xfrin"):
raise ZonemgrTestException("module name not exist") raise ZonemgrTestException("module name not exist")
def group_recvmsg(self, nonblock, seq):
return None, None
class MyZonemgrRefresh(ZonemgrRefresh): class MyZonemgrRefresh(ZonemgrRefresh):
def __init__(self): def __init__(self):
class FakeConfig: class FakeConfig:

6
src/bin/zonemgr/zonemgr.py.in Normal file → Executable file
View File

@@ -266,7 +266,11 @@ class ZonemgrRefresh:
"""Send command between modules.""" """Send command between modules."""
msg = create_command(command_name, params) msg = create_command(command_name, params)
try: try:
self._cc.group_sendmsg(msg, module_name) seq = self._cc.group_sendmsg(msg, module_name)
try:
answer, env = self._cc.group_recvmsg(False, seq)
except isc.cc.session.SessionTimeout:
pass # for now we just ignore the failure
except socket.error: except socket.error:
sys.stderr.write("[b10-zonemgr] Failed to send to module %s, the session has been closed." % module_name) sys.stderr.write("[b10-zonemgr] Failed to send to module %s, the session has been closed." % module_name)

View File

@@ -54,7 +54,7 @@ operator-(const isc::dns::Name& super_name, const isc::dns::Name& sub_name) {
} }
} }
template <typename T> template <typename T, bool returnEmptyNode>
class RBTree; class RBTree;
/// \brief \c RBNode is used by RBTree to store any data related to one domain /// \brief \c RBNode is used by RBTree to store any data related to one domain
@@ -82,7 +82,8 @@ class RBNode : public boost::noncopyable {
private: private:
/// The RBNode is meant for use from within RBTree, so it has access to /// The RBNode is meant for use from within RBTree, so it has access to
/// it. /// it.
friend class RBTree<T>; template <typename U, bool returnEmptyNode>
friend class RBTree;
/// \name Constructors /// \name Constructors
/// ///
@@ -238,6 +239,7 @@ template <typename T>
RBNode<T>::~RBNode() { RBNode<T>::~RBNode() {
} }
// note: the following class description is documented using multiline comments // note: the following class description is documented using multiline comments
// because the verbatim diagram contain a backslash, which could be interpreted // because the verbatim diagram contain a backslash, which could be interpreted
// as escape of newline in singleline comment. // as escape of newline in singleline comment.
@@ -256,6 +258,12 @@ RBNode<T>::~RBNode() {
* - Decreases the memory footprint, as it doesn't store the suffix labels * - Decreases the memory footprint, as it doesn't store the suffix labels
* multiple times. * multiple times.
* *
* Depending on different usage, rbtree will support different search policy.
* Whether return empty node to end user is one policy among them. Search
* policy is as the last template parameter, the default policy will NOT
* return empty node to end user, pass ture will get empty node during find
* is needed
*
* \anchor diagram * \anchor diagram
* *
* with the following names: * with the following names:
@@ -285,10 +293,6 @@ RBNode<T>::~RBNode() {
/ \ / \
o q o q
\endverbatim \endverbatim
* \note open problems:
* - current \c find() function only returns non-empty nodes, so there is no
* difference between find a non existent name and a name corresponding to
* an empty non-terminal nodes, but in DNS query logic, they are different
* \todo * \todo
* - add remove interface * - add remove interface
* - add iterator to iterate over the whole \c RBTree. This may be necessary, * - add iterator to iterate over the whole \c RBTree. This may be necessary,
@@ -296,7 +300,7 @@ RBNode<T>::~RBNode() {
* - since \c RBNode only has down pointer without up pointer, the node path * - since \c RBNode only has down pointer without up pointer, the node path
* during finding should be recorded for later use * during finding should be recorded for later use
*/ */
template <typename T> template <typename T, bool returnEmptyNode = false>
class RBTree : public boost::noncopyable { class RBTree : public boost::noncopyable {
friend class RBNode<T>; friend class RBNode<T>;
public: public:
@@ -531,21 +535,22 @@ private:
unsigned int node_count_; unsigned int node_count_;
}; };
template <typename T> template <typename T, bool S>
RBTree<T>::RBTree() { RBTree<T,S>::RBTree() {
NULLNODE = RBNode<T>::NULL_NODE(); NULLNODE = RBNode<T>::NULL_NODE();
root_ = NULLNODE; root_ = NULLNODE;
node_count_ = 0; node_count_ = 0;
} }
template <typename T> template <typename T, bool S>
RBTree<T>::~RBTree() { RBTree<T,S>::~RBTree() {
deleteHelper(root_); deleteHelper(root_);
assert(node_count_ == 0); assert(node_count_ == 0);
} }
template <typename T> template <typename T, bool S>
void RBTree<T> ::deleteHelper(RBNode<T> *root) { void
RBTree<T,S>::deleteHelper(RBNode<T> *root) {
if (root == NULLNODE) { if (root == NULLNODE) {
return; return;
} }
@@ -574,9 +579,10 @@ void RBTree<T> ::deleteHelper(RBNode<T> *root) {
--node_count_; --node_count_;
} }
template <typename T> template <typename CBARG> template <typename T, bool S>
typename RBTree<T>::Result template <typename CBARG>
RBTree<T>::find(const isc::dns::Name& name, RBNode<T>** node, typename RBTree<T,S>::Result
RBTree<T,S>::find(const isc::dns::Name& name, RBNode<T>** node,
bool (*callback)(const RBNode<T>&, CBARG), bool (*callback)(const RBNode<T>&, CBARG),
CBARG callback_arg) const CBARG callback_arg) const
{ {
@@ -584,15 +590,16 @@ RBTree<T>::find(const isc::dns::Name& name, RBNode<T>** node,
return (findHelper(name, &up_node, node, callback, callback_arg)); return (findHelper(name, &up_node, node, callback, callback_arg));
} }
template <typename T> template <typename CBARG> template <typename T, bool S>
typename RBTree<T>::Result template <typename CBARG>
RBTree<T>::find(const isc::dns::Name& name, const RBNode<T>** node, typename RBTree<T,S>::Result
RBTree<T,S>::find(const isc::dns::Name& name, const RBNode<T>** node,
bool (*callback)(const RBNode<T>&, CBARG), bool (*callback)(const RBNode<T>&, CBARG),
CBARG callback_arg) const CBARG callback_arg) const
{ {
const RBNode<T>* up_node; const RBNode<T>* up_node;
RBNode<T>* target_node; RBNode<T>* target_node;
const typename RBTree<T>::Result ret = const typename RBTree<T,S>::Result ret =
findHelper(name, &up_node, &target_node, callback, callback_arg); findHelper(name, &up_node, &target_node, callback, callback_arg);
if (ret != NOTFOUND) { if (ret != NOTFOUND) {
*node = target_node; *node = target_node;
@@ -600,18 +607,19 @@ RBTree<T>::find(const isc::dns::Name& name, const RBNode<T>** node,
return (ret); return (ret);
} }
template <typename T> template <typename CBARG> template <typename T, bool returnEmptyNode>
typename RBTree<T>::Result template <typename CBARG>
RBTree<T>::findHelper(const isc::dns::Name& target_name, typename RBTree<T,returnEmptyNode>::Result
const RBNode<T>** up_node, RBTree<T,returnEmptyNode>::findHelper(const isc::dns::Name& target_name,
RBNode<T>** target, const RBNode<T>** up_node,
bool (*callback)(const RBNode<T>&, CBARG), RBNode<T>** target,
CBARG callback_arg) const bool (*callback)(const RBNode<T>&, CBARG),
CBARG callback_arg) const
{ {
using namespace helper; using namespace helper;
RBNode<T>* node = root_; RBNode<T>* node = root_;
typename RBTree<T>::Result ret = NOTFOUND; typename RBTree<T,returnEmptyNode>::Result ret = NOTFOUND;
*up_node = NULLNODE; *up_node = NULLNODE;
isc::dns::Name name = target_name; isc::dns::Name name = target_name;
@@ -621,7 +629,7 @@ RBTree<T>::findHelper(const isc::dns::Name& target_name,
const isc::dns::NameComparisonResult::NameRelation relation = const isc::dns::NameComparisonResult::NameRelation relation =
compare_result.getRelation(); compare_result.getRelation();
if (relation == isc::dns::NameComparisonResult::EQUAL) { if (relation == isc::dns::NameComparisonResult::EQUAL) {
if (!node->isEmpty()) { if (returnEmptyNode || !node->isEmpty()) {
*target = node; *target = node;
ret = EXACTMATCH; ret = EXACTMATCH;
} }
@@ -634,8 +642,8 @@ RBTree<T>::findHelper(const isc::dns::Name& target_name,
node = (compare_result.getOrder() < 0) ? node = (compare_result.getOrder() < 0) ?
node->left_ : node->right_; node->left_ : node->right_;
} else if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) { } else if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
if (!node->isEmpty()) { if (returnEmptyNode || !node->isEmpty()) {
ret = RBTree<T>::PARTIALMATCH; ret = RBTree<T,returnEmptyNode>::PARTIALMATCH;
*target = node; *target = node;
if (callback != NULL && node->callback_required_) { if (callback != NULL && node->callback_required_) {
if ((callback)(*node, callback_arg)) { if ((callback)(*node, callback_arg)) {
@@ -655,9 +663,11 @@ RBTree<T>::findHelper(const isc::dns::Name& target_name,
return (ret); return (ret);
} }
template <typename T>
typename RBTree<T>::Result template <typename T, bool returnEmptyNode>
RBTree<T>::insert(const isc::dns::Name& target_name, RBNode<T>** new_node) { typename RBTree<T,returnEmptyNode>::Result
RBTree<T,returnEmptyNode>::insert(const isc::dns::Name& target_name,
RBNode<T>** new_node) {
using namespace helper; using namespace helper;
RBNode<T>* parent = NULLNODE; RBNode<T>* parent = NULLNODE;
RBNode<T>* current = root_; RBNode<T>* current = root_;
@@ -674,7 +684,12 @@ RBTree<T>::insert(const isc::dns::Name& target_name, RBNode<T>** new_node) {
if (new_node != NULL) { if (new_node != NULL) {
*new_node = current; *new_node = current;
} }
return (ALREADYEXISTS);
if (current->isEmpty() && !returnEmptyNode) {
return (SUCCESS);
} else {
return (ALREADYEXISTS);
}
} else { } else {
const int common_label_count = compare_result.getCommonLabels(); const int common_label_count = compare_result.getCommonLabels();
if (common_label_count == 1) { if (common_label_count == 1) {
@@ -730,9 +745,10 @@ RBTree<T>::insert(const isc::dns::Name& target_name, RBNode<T>** new_node) {
return (SUCCESS); return (SUCCESS);
} }
template <typename T>
template <typename T, bool S>
void void
RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) { RBTree<T,S>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
using namespace helper; using namespace helper;
const isc::dns::Name sub_name = node.name_ - base_name; const isc::dns::Name sub_name = node.name_ - base_name;
// using auto_ptr here is to avoid memory leak in case of exception raised // using auto_ptr here is to avoid memory leak in case of exception raised
@@ -752,9 +768,10 @@ RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
down_node.release(); down_node.release();
} }
template <typename T>
template <typename T, bool S>
void void
RBTree<T>::insertRebalance(RBNode<T>** root, RBNode<T>* node) { RBTree<T,S>::insertRebalance(RBNode<T>** root, RBNode<T>* node) {
RBNode<T>* uncle; RBNode<T>* uncle;
while (node != *root && node->parent_->color_ == RBNode<T>::RED) { while (node != *root && node->parent_->color_ == RBNode<T>::RED) {
@@ -798,9 +815,9 @@ RBTree<T>::insertRebalance(RBNode<T>** root, RBNode<T>* node) {
} }
template <typename T> template <typename T, bool S>
RBNode<T>* RBNode<T>*
RBTree<T>::leftRotate(RBNode<T>** root, RBNode<T>* node) { RBTree<T,S>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
RBNode<T>* right = node->right_; RBNode<T>* right = node->right_;
node->right_ = right->left_; node->right_ = right->left_;
if (right->left_ != NULLNODE) if (right->left_ != NULLNODE)
@@ -823,9 +840,9 @@ RBTree<T>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
return (node); return (node);
} }
template <typename T> template <typename T, bool S>
RBNode<T>* RBNode<T>*
RBTree<T>::rightRotate(RBNode<T>** root, RBNode<T>* node) { RBTree<T,S>::rightRotate(RBNode<T>** root, RBNode<T>* node) {
RBNode<T>* left = node->left_; RBNode<T>* left = node->left_;
node->left_ = left->right_; node->left_ = left->right_;
if (left->right_ != NULLNODE) if (left->right_ != NULLNODE)
@@ -847,17 +864,18 @@ RBTree<T>::rightRotate(RBNode<T>** root, RBNode<T>* node) {
return (node); return (node);
} }
template <typename T>
template <typename T, bool S>
void void
RBTree<T>::dumpTree(std::ostream& os, unsigned int depth) const { RBTree<T,S>::dumpTree(std::ostream& os, unsigned int depth) const {
indent(os, depth); indent(os, depth);
os << "tree has " << node_count_ << " node(s)\n"; os << "tree has " << node_count_ << " node(s)\n";
dumpTreeHelper(os, root_, depth); dumpTreeHelper(os, root_, depth);
} }
template <typename T> template <typename T, bool S>
void void
RBTree<T>::dumpTreeHelper(std::ostream& os, const RBNode<T>* node, RBTree<T,S>::dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
unsigned int depth) const unsigned int depth) const
{ {
if (node == NULLNODE) { if (node == NULLNODE) {
@@ -882,13 +900,15 @@ RBTree<T>::dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
dumpTreeHelper(os, node->right_, depth + 1); dumpTreeHelper(os, node->right_, depth + 1);
} }
template <typename T> template <typename T, bool S>
void void
RBTree<T>::indent(std::ostream& os, unsigned int depth) { RBTree<T,S>::indent(std::ostream& os, unsigned int depth) {
static const unsigned int INDENT_FOR_EACH_DEPTH = 5; static const unsigned int INDENT_FOR_EACH_DEPTH = 5;
os << std::string(depth * INDENT_FOR_EACH_DEPTH, ' '); os << std::string(depth * INDENT_FOR_EACH_DEPTH, ' ');
} }
} }
} }

View File

@@ -51,30 +51,22 @@ namespace {
class RBTreeTest : public::testing::Test { class RBTreeTest : public::testing::Test {
protected: protected:
RBTreeTest() : rbtree() { RBTreeTest() : rbtree() {
rbtree.insert(Name("c"), &rbtnode); const char * domain_names[] = {"c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h",
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(1))); "o.w.y.d.e.f", "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f"};
rbtree.insert(Name("b"), &rbtnode); int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(2))); for (int i = 0; i < name_count; ++i) {
rbtree.insert(Name("a"), &rbtnode); rbtree.insert(Name(domain_names[i]), &rbtnode);
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(3))); rbtnode->setData(RBNode<int>::NodeDataPtr(new int(i + 1)));
rbtree.insert(Name("x.d.e.f"), &rbtnode);
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(4))); rbtree_expose_empty_node.insert(Name(domain_names[i]), &rbtnode);
rbtree.insert(Name("z.d.e.f"), &rbtnode); rbtnode->setData(RBNode<int>::NodeDataPtr(new int(i + 1)));
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(5)));
rbtree.insert(Name("g.h"), &rbtnode); }
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(6)));
rbtree.insert(Name("i.g.h"), &rbtnode);
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(7)));
rbtree.insert(Name("o.w.y.d.e.f"), &rbtnode);
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(8)));
rbtree.insert(Name("j.z.d.e.f"), &rbtnode);
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(9)));
rbtree.insert(Name("p.w.y.d.e.f"), &rbtnode);
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(10)));
rbtree.insert(Name("q.w.y.d.e.f"), &rbtnode);
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(11)));
} }
RBTree<int> rbtree; RBTree<int> rbtree;
typedef RBTree<int, true> ExposeRBTree;
ExposeRBTree rbtree_expose_empty_node;
RBNode<int>* rbtnode; RBNode<int>* rbtnode;
const RBNode<int>* crbtnode; const RBNode<int>* crbtnode;
}; };
@@ -90,32 +82,69 @@ TEST_F(RBTreeTest, setGetData) {
} }
TEST_F(RBTreeTest, insertNames) { TEST_F(RBTreeTest, insertNames) {
EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("d.e.f"), &rbtnode)); //if don't expose empty node, even the node already exsit which is caused by node fission
//we will return succeed
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("d.e.f"), &rbtnode));
EXPECT_EQ(Name("d.e.f"), rbtnode->getName()); EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
EXPECT_EQ(13, rbtree.getNodeCount()); EXPECT_EQ(13, rbtree.getNodeCount());
EXPECT_EQ(ExposeRBTree::ALREADYEXISTS,
rbtree_expose_empty_node.insert(Name("d.e.f"), &rbtnode));
EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
EXPECT_EQ(13, rbtree_expose_empty_node.getNodeCount());
//insert not exist node
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("."), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("."), &rbtnode));
EXPECT_EQ(Name("."), rbtnode->getName()); EXPECT_EQ(Name("."), rbtnode->getName());
EXPECT_EQ(14, rbtree.getNodeCount()); EXPECT_EQ(14, rbtree.getNodeCount());
EXPECT_EQ(ExposeRBTree::SUCCESS, rbtree_expose_empty_node.insert(
Name("."), &rbtnode));
EXPECT_EQ(Name("."), rbtnode->getName());
EXPECT_EQ(14, rbtree_expose_empty_node.getNodeCount());
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("example.com"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("example.com"), &rbtnode));
EXPECT_EQ(15, rbtree.getNodeCount()); EXPECT_EQ(15, rbtree.getNodeCount());
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(12))); rbtnode->setData(RBNode<int>::NodeDataPtr(new int(12)));
EXPECT_EQ(ExposeRBTree::SUCCESS, rbtree_expose_empty_node.insert(
Name("example.com"), &rbtnode));
EXPECT_EQ(15, rbtree_expose_empty_node.getNodeCount());
rbtnode->setData(RBNode<int>::NodeDataPtr(new int(12)));
// return ALREADYEXISTS, since node "example.com" already has been explicitly inserted // return ALREADYEXISTS, since node "example.com" already has been explicitly inserted
EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("example.com"), &rbtnode)); EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("example.com"), &rbtnode));
EXPECT_EQ(15, rbtree.getNodeCount()); EXPECT_EQ(15, rbtree.getNodeCount());
EXPECT_EQ(ExposeRBTree::ALREADYEXISTS,
rbtree_expose_empty_node.insert(Name("example.com"), &rbtnode));
EXPECT_EQ(15, rbtree_expose_empty_node.getNodeCount());
// split the node "d.e.f" // split the node "d.e.f"
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("k.e.f"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("k.e.f"), &rbtnode));
EXPECT_EQ(Name("k"), rbtnode->getName()); EXPECT_EQ(Name("k"), rbtnode->getName());
EXPECT_EQ(17, rbtree.getNodeCount()); EXPECT_EQ(17, rbtree.getNodeCount());
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("k.e.f"), &rbtnode));
EXPECT_EQ(Name("k"), rbtnode->getName());
EXPECT_EQ(17, rbtree_expose_empty_node.getNodeCount());
// split the node "g.h" // split the node "g.h"
EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("h"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("h"), &rbtnode));
EXPECT_EQ(Name("h"), rbtnode->getName()); EXPECT_EQ(Name("h"), rbtnode->getName());
EXPECT_EQ(18, rbtree.getNodeCount()); EXPECT_EQ(18, rbtree.getNodeCount());
//node fission will create node "h"
EXPECT_EQ(ExposeRBTree::ALREADYEXISTS,
rbtree_expose_empty_node.insert(Name("h"), &rbtnode));
EXPECT_EQ(Name("h"), rbtnode->getName());
EXPECT_EQ(18, rbtree_expose_empty_node.getNodeCount());
// add child domain // add child domain
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("m.p.w.y.d.e.f"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("m.p.w.y.d.e.f"), &rbtnode));
EXPECT_EQ(Name("m"), rbtnode->getName()); EXPECT_EQ(Name("m"), rbtnode->getName());
@@ -124,18 +153,41 @@ TEST_F(RBTreeTest, insertNames) {
EXPECT_EQ(Name("n"), rbtnode->getName()); EXPECT_EQ(Name("n"), rbtnode->getName());
EXPECT_EQ(20, rbtree.getNodeCount()); EXPECT_EQ(20, rbtree.getNodeCount());
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("m.p.w.y.d.e.f"), &rbtnode));
EXPECT_EQ(Name("m"), rbtnode->getName());
EXPECT_EQ(19, rbtree_expose_empty_node.getNodeCount());
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("n.p.w.y.d.e.f"), &rbtnode));
EXPECT_EQ(Name("n"), rbtnode->getName());
EXPECT_EQ(20, rbtree_expose_empty_node.getNodeCount());
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("l.a"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("l.a"), &rbtnode));
EXPECT_EQ(Name("l"), rbtnode->getName()); EXPECT_EQ(Name("l"), rbtnode->getName());
EXPECT_EQ(21, rbtree.getNodeCount()); EXPECT_EQ(21, rbtree.getNodeCount());
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("l.a"), &rbtnode));
EXPECT_EQ(Name("l"), rbtnode->getName());
EXPECT_EQ(21, rbtree_expose_empty_node.getNodeCount());
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("r.d.e.f"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("r.d.e.f"), &rbtnode));
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("s.d.e.f"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("s.d.e.f"), &rbtnode));
EXPECT_EQ(23, rbtree.getNodeCount()); EXPECT_EQ(23, rbtree.getNodeCount());
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("r.d.e.f"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("s.d.e.f"), &rbtnode));
EXPECT_EQ(23, rbtree_expose_empty_node.getNodeCount());
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("h.w.y.d.e.f"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("h.w.y.d.e.f"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("h.w.y.d.e.f"), &rbtnode));
// add more nodes one by one to cover leftRotate and rightRotate // add more nodes one by one to cover leftRotate and rightRotate
EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("f"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("f"), &rbtnode));
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("m"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("m"), &rbtnode));
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("nm"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("nm"), &rbtnode));
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("om"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("om"), &rbtnode));
@@ -146,8 +198,32 @@ TEST_F(RBTreeTest, insertNames) {
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("i"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("i"), &rbtnode));
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("ae"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("ae"), &rbtnode));
EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("n"), &rbtnode)); EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("n"), &rbtnode));
EXPECT_EQ(ExposeRBTree::ALREADYEXISTS,
rbtree_expose_empty_node.insert(Name("f"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("m"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("nm"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("om"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("k"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("l"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("fe"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("ge"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("i"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("ae"), &rbtnode));
EXPECT_EQ(ExposeRBTree::SUCCESS,
rbtree_expose_empty_node.insert(Name("n"), &rbtnode));
} }
TEST_F(RBTreeTest, findName) { TEST_F(RBTreeTest, findName) {
// find const rbtnode // find const rbtnode
// exact match // exact match
@@ -196,7 +272,7 @@ TEST_F(RBTreeTest, callback) {
&subrbtnode)); &subrbtnode));
subrbtnode->setData(RBNode<int>::NodeDataPtr(new int(2))); subrbtnode->setData(RBNode<int>::NodeDataPtr(new int(2)));
RBNode<int>* parentrbtnode; RBNode<int>* parentrbtnode;
EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("example"), EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("example"),
&parentrbtnode)); &parentrbtnode));
// the chilld/parent nodes shouldn't "inherit" the callback flag. // the chilld/parent nodes shouldn't "inherit" the callback flag.
// "rbtnode" may be invalid due to the insertion, so we need to re-find // "rbtnode" may be invalid due to the insertion, so we need to re-find