|
@@ -20,43 +20,83 @@
|
|
|
#include <dns/rrset.h>
|
|
|
#include <dns/rrsetlist.h>
|
|
|
#include <boost/shared_ptr.hpp>
|
|
|
+#include <boost/utility.hpp>
|
|
|
|
|
|
using namespace isc::dns;
|
|
|
namespace isc {
|
|
|
namespace datasrc {
|
|
|
|
|
|
+/// \brief rbtree color define
|
|
|
enum RBTreeColor {BLACK = 1, RED};
|
|
|
class RBTree;
|
|
|
|
|
|
-/// RBNode generally contains the data for one domain name
|
|
|
-/// It's a general node of one rbtree with left, right, parent and color
|
|
|
-/// It also carray the dns data like the rrsets belongs to the domain name
|
|
|
-/// and a rbtree which is the subdomain of this node
|
|
|
-/// the name of the node is relative. One special kind of node is non-terminal node
|
|
|
+/// \brief \c RBNode class represent one domain name in the domain space
|
|
|
+
|
|
|
+/// It has two roles, the first one is as one node in the \c RBTree the second one
|
|
|
+/// is store the data related to DNS. As for the first role, it has left, right, parent and color memebers
|
|
|
+/// which used to keey the balance of the \c RBTree. As for the second role,
|
|
|
+// it stores the rrsets belongs to the domain name and a rbtree which includes all the subdomains of this node
|
|
|
+/// the name stored in the node is relative related to its parent node.
|
|
|
+/// One special kind of node is non-terminal node
|
|
|
/// which has subdomains with rrset but it self doesn't has any rrset
|
|
|
///
|
|
|
-///
|
|
|
-/// RBNode memory management is totally handled by rbtree, so no constructor and destructor function is exposed
|
|
|
+/// \b Note: \c RBNode should create or destroied only by \c RBTree so constructor and destructor function aren't exposed
|
|
|
+
|
|
|
|
|
|
-class RBNode {
|
|
|
+class RBNode : public boost::noncopyable{
|
|
|
public:
|
|
|
+ /// only /c RBTree can create and destroy \c RBNode
|
|
|
friend class RBTree;
|
|
|
typedef boost::shared_ptr<RRsetList> RRsetListPtr;
|
|
|
|
|
|
- ///whether current domain name contains ns records
|
|
|
+ /// \name Test functions
|
|
|
+ ///
|
|
|
+ //@{
|
|
|
+ /// \brief return whether current domain name has ns records
|
|
|
bool isDelegate() const { return is_delegate_;}
|
|
|
- //subname has rrset, but it self doesn't has
|
|
|
+
|
|
|
+ /// \brief return whether current domain name is non-terminal
|
|
|
+ /// A non-terminal domain has no rrsets but at least one its descendant
|
|
|
+ /// domain has rrset
|
|
|
bool isNonterminal() const { return is_nonterminal_;}
|
|
|
- int addRRset(RRsetPtr rrset);
|
|
|
+
|
|
|
+ /// \brief return the name of current node, it's relative to its parents
|
|
|
+ //
|
|
|
+ /// \todo Is it meaningful to return the absolute of the node?
|
|
|
const Name &getName() const {return name_;}
|
|
|
|
|
|
- //next domain name which is bigger than current one
|
|
|
+ // \brief return next node whose name is bigger than current node
|
|
|
RBNode* successor();
|
|
|
+ //@}
|
|
|
+
|
|
|
+
|
|
|
+ /// \name modify function
|
|
|
+ //@{
|
|
|
+
|
|
|
+ /// \brief add the rrset to the node
|
|
|
+ /// \Note: there is no check whether the node already has the rrset or not
|
|
|
+ /// and no check about whether the name of the rrset is same with the node or not
|
|
|
+ /// All of above is rely on interface user
|
|
|
+ int addRRset(RRsetPtr rrset);
|
|
|
+ //@}
|
|
|
|
|
|
private:
|
|
|
+ /// \name Constructors and destructor
|
|
|
+ //@{
|
|
|
+ /// \param nullnode The null point for \c RBNode isnot use \c NULL, but use one specified
|
|
|
+ /// default node singled as null node, this is intended to keep the code more unify
|
|
|
RBNode(const Name& name, RRsetListPtr rrsets = RRsetListPtr(), RBNode* nullnode = NULL);
|
|
|
- ~RBNode(); //the class isn't left to be inherited
|
|
|
+
|
|
|
+ /// the class isn't left to be inherted
|
|
|
+ ~RBNode();
|
|
|
+ //@}
|
|
|
+
|
|
|
+
|
|
|
+ /// \brief copy the DNS related date to another node except the sub domain tree
|
|
|
void cloneDNSData(RBNode& node);
|
|
|
+ /// \brief when copy the DNS data from one node to another, except the rrsets, name etc,
|
|
|
+ /// also needs to maintain the down and up relationship, which includes set the down point of current
|
|
|
+ /// node and up point of sub domain tree
|
|
|
void setDownTree(RBTree* down);
|
|
|
|
|
|
/// data to maintain the rbtree balance
|
|
@@ -73,57 +113,92 @@ class RBNode {
|
|
|
bool is_nonterminal_;
|
|
|
};
|
|
|
|
|
|
-/// RBTree is a generic red black tree, it contains all the node with same suffix
|
|
|
+/// \brief \c RBTree class represent all the domains with same suffix, so it can be used to store
|
|
|
+/// the domains in one zone
|
|
|
+///
|
|
|
+/// \c RBTree is a generic red black tree, and contains all the node with same suffix, since each
|
|
|
+/// name may have sub domain names so \c RBTree is a recursive data struct or tree in tree
|
|
|
/// So for one zone, severl RBTrees are involved. But from outside, the sub tree is
|
|
|
-/// opaque for end user. if the sub tree only has one node and the base node which is pointed by the
|
|
|
-/// "up_" pointer is one non-terminal, the single node will merge with the "up_" node then the sub tree will
|
|
|
-/// be deleted
|
|
|
-class RBTree {
|
|
|
+/// opaque for end user.
|
|
|
+class RBTree : public boost::noncopyable{
|
|
|
friend class RBNode;
|
|
|
public:
|
|
|
+ /// \brief The return value for find method
|
|
|
+ /// - EXACTMATCH: return the node in the tree exactly same with the target
|
|
|
+ /// - FINDREFERRAL: return the node which is the ancestor of the target containing ns record
|
|
|
+ /// - NOTFOUND: other conditions except EXACTMATCH & FINDREFERRAL
|
|
|
enum FindResult{EXACTMATCH, FINDREFERRAL, NOTFOUND};
|
|
|
|
|
|
+ /// \name Constructor and Destructor
|
|
|
+ //@{
|
|
|
RBTree();
|
|
|
+ /// \b Note: RBTree is not intended to be inherited so the destructor isnot virtual
|
|
|
~RBTree();
|
|
|
-
|
|
|
- /// if find result isn't NOTFOUND, the node will point to the result
|
|
|
- /// with return value equal to NOTFOUND, the value of node is undetermined
|
|
|
+ //@}
|
|
|
+
|
|
|
+ /// \name Inquery methods
|
|
|
+ //@{
|
|
|
+ /// \brief find the node with the name
|
|
|
+ /// \param name Target to be found
|
|
|
+ /// \param node Point to the node when the return vaule is \c not NOTFOUND, if
|
|
|
+ /// if the return value is NOTFOUND, the value of node is \c unknown
|
|
|
FindResult find(const Name& name, RBNode** node)const;
|
|
|
|
|
|
- /// get all the node count recursively, including the sub trees
|
|
|
- /// note that the return value isn't same with valid domain names in the tree
|
|
|
- /// the interface just used for test the tree logic, later will be removed
|
|
|
+ /// \brief Get all the node count in the tree
|
|
|
int getNodeCount() const;
|
|
|
+ //@}
|
|
|
|
|
|
-
|
|
|
+ /// \name Debug function
|
|
|
+ //@{
|
|
|
+ /// \brief print the node in the trees
|
|
|
+ /// \todo is it better to return one string instead of print to the stdout?
|
|
|
void printTree(int depth = 0)const;
|
|
|
-
|
|
|
- /// if the name exists, return value will be one, and inserted_node will point to
|
|
|
- /// the existed node, otherwise return value is zero, and inserted_node points to
|
|
|
- /// new created node
|
|
|
+ //@}
|
|
|
+
|
|
|
+ /// \name Modify function
|
|
|
+ //@{
|
|
|
+ /// \brief insert the domain name into the tree
|
|
|
+ /// \param name The name want to be inserted into the tree
|
|
|
+ /// \param inserted_node If no node with the name in the tree,
|
|
|
+ /// new \c RBNode will be created, otherwise nothing will be done
|
|
|
+ /// anyway the pointer point to the node with the name will be assign to inserted_node
|
|
|
+ /// \return return 0 means no node exists in the tree with the name before insert
|
|
|
+ /// return 1 means already has the node with the given name
|
|
|
+ //
|
|
|
+ /// If want to add rrset into one node, but not sure whether the node already exist
|
|
|
+ /// Instead of call \c find, call \c insert and then call the RBNode interface to
|
|
|
+ /// add rrset into the node is a better way
|
|
|
int insert(const Name& name, RBNode** inserted_node);
|
|
|
|
|
|
- /// if the node doesn't exist, return value will be one otherwise zero
|
|
|
+ /// \brief erase the node with the domain name
|
|
|
+ /// \return If no node with the name, return one otherwise return zero
|
|
|
int erase(const Name& name);
|
|
|
+ //@}
|
|
|
|
|
|
private:
|
|
|
+ /// \name RBTree balance function
|
|
|
+ //@{
|
|
|
void deleteRebalance(RBNode* node);
|
|
|
void insertRebalance(RBNode* node);
|
|
|
RBNode* rightRotate(RBNode* p);
|
|
|
RBNode* leftRotate(RBNode* p);
|
|
|
- void printTreeHelper(RBNode* node, int depth)const;
|
|
|
- void eraseNode(RBNode* node);
|
|
|
+ //@}
|
|
|
|
|
|
- /// recursive find one name in the tree, and return the exact tree has the name
|
|
|
+ /// \name Helper function
|
|
|
+ //@{
|
|
|
+ /// All the public function has related recursive helper function
|
|
|
+ void eraseNode(RBNode* node);
|
|
|
FindResult findHelper(const Name& name, RBTree** tree, RBNode** node)const;
|
|
|
int getNodeCountHelper(const RBNode* node) const;
|
|
|
+ void printTreeHelper(RBNode* node, int depth)const;
|
|
|
+ //@}
|
|
|
|
|
|
- void setUpNode(RBNode *node);
|
|
|
|
|
|
RBNode* root_;
|
|
|
RBNode* NULLNODE;
|
|
|
RBNode* up_;
|
|
|
- unsigned int node_count_; //current tree node count exclude the node in down pointing trees
|
|
|
+ /// the node count of current tree except the sub domain trees
|
|
|
+ unsigned int node_count_;
|
|
|
};
|
|
|
}
|
|
|
}
|