Commit a5996789 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[2098] supported isSameKind.

parent 87c9372f
......@@ -463,4 +463,65 @@ TEST_F(TreeNodeRRsetTest, toText) {
false),
ConstRRsetPtr(), ConstRRsetPtr());
}
TEST_F(TreeNodeRRsetTest, isSameKind) {
const TreeNodeRRset rrset(rrclass_, www_node_, a_rdataset_, true);
// Same name (node), same type (rdataset) => same kind
EXPECT_TRUE(rrset.isSameKind(TreeNodeRRset(rrclass_, www_node_,
a_rdataset_, true)));
// Same name (node), different type (rdataset) => not same kind
EXPECT_FALSE(rrset.isSameKind(TreeNodeRRset(rrclass_, www_node_,
aaaa_rdataset_, true)));
// Different name, different type => not same kind
EXPECT_FALSE(rrset.isSameKind(TreeNodeRRset(rrclass_, origin_node_,
ns_rdataset_, true)));
// Different name, same type => not same kind.
// Note: this shouldn't happen in our in-memory data source implementation,
// but API doesn't prohibit it.
EXPECT_FALSE(rrset.isSameKind(TreeNodeRRset(rrclass_, origin_node_,
a_rdataset_, true)));
// Wildcard and expanded RRset
const TreeNodeRRset wildcard_rrset(rrclass_, wildcard_node_,
wildcard_rdataset_, true);
const TreeNodeRRset match_rrset(match_name_, rrclass_, wildcard_node_,
wildcard_rdataset_, true);
EXPECT_FALSE(wildcard_rrset.isSameKind(match_rrset));
EXPECT_FALSE(match_rrset.isSameKind(wildcard_rrset));
// Both are wildcard expanded, and have different names
const TreeNodeRRset match2_rrset(Name("match2.example.com"), rrclass_,
wildcard_node_, wildcard_rdataset_, true);
EXPECT_FALSE(match_rrset.isSameKind(match2_rrset));
EXPECT_FALSE(match2_rrset.isSameKind(match_rrset));
// Pathological case. "badwild" is constructed as if expanded due to
// a wildcard, but has the same owner name of the wildcard itself.
// Technically, they should be considered of the same kind, but this
// implementation considers they are not. But this case shouldn't happen
// as long as the RRsets are only constructed inside the in-memory
// zone finder implementation.
const TreeNodeRRset badwild_rrset(wildcard_name_, rrclass_, wildcard_node_,
wildcard_rdataset_, true);
EXPECT_FALSE(wildcard_rrset.isSameKind(badwild_rrset));
EXPECT_EQ(wildcard_rrset.toText(), badwild_rrset.toText());
// Pathological case: Same name, same type, but different class.
// This case should be impossible because if the RRsets share the same
// tree node, they must belong to the same RR class. This case is
// a caller's bug, and the isSameKind() implementation returns the
// "wrong" (= true) answer.
EXPECT_TRUE(rrset.isSameKind(TreeNodeRRset(RRClass::CH(), www_node_,
a_rdataset_, true)));
// Same kind of different RRset class
EXPECT_TRUE(rrset.isSameKind(*a_rrset_));
// Different kind of different RRset class
EXPECT_FALSE(rrset.isSameKind(*aaaa_rrset_));
}
}
......@@ -40,7 +40,8 @@ namespace isc {
namespace datasrc {
namespace memory {
TreeNodeRRset::TreeNodeRRset(const dns::Name& realname, dns::RRClass rrclass,
TreeNodeRRset::TreeNodeRRset(const dns::Name& realname,
const dns::RRClass& rrclass,
const ZoneNode* node, const RdataSet* rdataset,
bool dnssec_ok) :
node_(node), rdataset_(rdataset),
......@@ -329,10 +330,49 @@ TreeNodeRRset::removeRRsig() {
isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
}
// needed
bool
TreeNodeRRset::isSameKind(const AbstractRRset& /*other*/) const {
isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
TreeNodeRRset::isSameKind(const AbstractRRset& abs_other) const {
const TreeNodeRRset* other =
dynamic_cast<const TreeNodeRRset*>(&abs_other);
if (other != NULL) {
// If type is different, they are not the same kind
if (rdataset_ != other->rdataset_) {
return (false);
}
// Same for the owner name (note: in practice this method would be
// called for rrsets at different nodes, so we check that condition
// first). Note also that based on the basic assumption of the
// ZoneTree, if the nodes are different their RR classes must be
// different.
if (node_ != other->node_ || !hasSameRealName(*other)) {
return (false);
}
return (true);
}
return (AbstractRRset::isSameKind(abs_other));
}
bool
TreeNodeRRset::hasSameRealName(const TreeNodeRRset& other) const {
// If one is constructed with a "real name" and the other isn't
// *we consider* them different.
if ((realname_buf_ == NULL && other.realname_buf_ != NULL) ||
(realname_buf_ != NULL && other.realname_buf_ == NULL)) {
return (false);
}
// If both are constructed with a "real name", we compare their names
// (as label sequences) explicitly.
if (realname_buf_ != NULL && other.realname_buf_ != NULL) {
uint8_t labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH];
uint8_t other_labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH];
if (!getOwnerLabels(labels_buf).equals(
other.getOwnerLabels(other_labels_buf))) {
return (false);
}
}
return (true);
}
} // namespace memory
......
......@@ -37,14 +37,14 @@ namespace memory {
class TreeNodeRRset : public dns::AbstractRRset {
public:
TreeNodeRRset(dns::RRClass rrclass, const ZoneNode* node,
TreeNodeRRset(const dns::RRClass& rrclass, const ZoneNode* node,
const RdataSet* rdataset, bool dnssec_ok) :
node_(node), rdataset_(rdataset),
rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass),
dnssec_ok_(dnssec_ok), name_(NULL), realname_buf_(NULL)
{}
TreeNodeRRset(const dns::Name& realname, dns::RRClass rrclass,
TreeNodeRRset(const dns::Name& realname, const dns::RRClass& rrclass,
const ZoneNode* node, const RdataSet* rdataset,
bool dnssec_ok);
......@@ -94,8 +94,24 @@ public:
virtual void addRRsig(const dns::RRsetPtr& sigs);
virtual void removeRRsig();
// needed
virtual bool isSameKind(const dns::AbstractRRset& other) const;
/// \brief Specialized version of \c isSameKind() for \c TreeNodeRRset.
///
/// As a kind of optimization, this implementation exploits the assumption
/// of how \c TreeNodeRRset objects are created: They must be always
/// created inside the in-memory data source finder implementation,
/// and they are constructed with the \c realname parameter if and only
/// if the corresponding query name is subject to wildcard substitution.
///
/// So, if the given RRset is of \c TreeNodeRRset, and one and only one of
/// of them has \c realname, they are considered to have different names.
///
/// Also, this implementation does not compare RR classes explicitly;
/// if two \c TreeNodeRRset objects belong to different RR classes,
/// they should belong to different zone trees (according to the assumption
/// of how the zone data are built), and therefore they cannot be at
/// same zone node. So it's sufficient to compare the (address of the)
/// node; if they are different they cannot be of the same kind.
virtual bool isSameKind(const dns::AbstractRRset& abs_other) const;
private:
dns::RdataIteratorPtr getSigRdataIterator() const;
......@@ -110,6 +126,11 @@ private:
return (node_->getAbsoluteLabels(labels_buf));
}
// A helper for isSameKind() to check if 'this' and 'other' has
// the same "real" name in case at least either is constructed with
// a real name.
bool hasSameRealName(const TreeNodeRRset& other) const;
const ZoneNode* node_;
const RdataSet* rdataset_;
const size_t rrsig_count_;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment