/// if not found in the entire list, it returns NULL. The head pointer
/// can be NULL, in which case this function will simply return NULL.
///
+ /// By default, this method ignores an RdataSet that only contains an
+ /// RRSIG (i.e., missing the covered RdataSet); if the optional
+ /// sigonly_ok parameter is explicitly set to true, it matches such
+ /// RdataSet and returns it if found.
+ ///
/// \note This function is defined as a (static) class method to
/// clarify its an operation for \c RdataSet objects and to make the
/// name shorter. But its implementation does not depend on private
/// \param rdata_head A pointer to \c RdataSet from which the search
/// starts. It can be NULL.
/// \param type The RRType of \c RdataSet to find.
+ /// \param sigonly_ok Whether it should find an RdataSet that only has
+ /// RRSIG
/// \return A pointer to the found \c RdataSet or NULL if none found.
static const RdataSet*
- find(const RdataSet* rdataset_head, const dns::RRType& type) {
- return (find<const RdataSet>(rdataset_head, type));
+ find(const RdataSet* rdataset_head, const dns::RRType& type,
+ bool sigonly_ok = false)
+ {
+ return (find<const RdataSet>(rdataset_head, type, sigonly_ok));
}
/// \brief Find \c RdataSet of given RR type from a list (non const
/// This is similar to the const version, except it takes and returns non
/// const pointers.
static RdataSet*
- find(RdataSet* rdataset_head, const dns::RRType& type) {
- return (find<RdataSet>(rdataset_head, type));
+ find(RdataSet* rdataset_head, const dns::RRType& type,
+ bool sigonly_ok = false)
+ {
+ return (find<RdataSet>(rdataset_head, type, sigonly_ok));
}
typedef boost::interprocess::offset_ptr<RdataSet> RdataSetPtr;
// Shared by both mutable and immutable versions of find()
template <typename RdataSetType>
static RdataSetType*
- find(RdataSetType* rdataset_head, const dns::RRType& type) {
+ find(RdataSetType* rdataset_head, const dns::RRType& type, bool sigonly_ok)
+ {
for (RdataSetType* rdataset = rdataset_head;
rdataset != NULL;
rdataset = rdataset->getNext()) // use getNext() for efficiency
{
- if (rdataset->type == type) {
+ if (rdataset->type == type &&
+ (rdataset->getRdataCount() > 0 || sigonly_ok)) {
return (rdataset);
}
}
using namespace isc::dns::rdata;
using namespace isc::datasrc::memory;
using namespace isc::testutils;
+using isc::datasrc::memory::detail::SegmentObjectHolder;
using boost::lexical_cast;
namespace {
RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN());
}
+TEST_F(RdataSetTest, find) {
+ // Create some RdataSets and make a chain of them.
+ SegmentObjectHolder<RdataSet, RRClass> holder1(
+ mem_sgmt_,
+ RdataSet::create(mem_sgmt_, encoder_, a_rrset_, ConstRRsetPtr()),
+ RRClass::IN());
+ ConstRRsetPtr aaaa_rrset =
+ textToRRset("www.example.com. 1076895760 IN AAAA 2001:db8::1");
+ SegmentObjectHolder<RdataSet, RRClass> holder2(
+ mem_sgmt_,
+ RdataSet::create(mem_sgmt_, encoder_, aaaa_rrset, ConstRRsetPtr()),
+ RRClass::IN());
+ ConstRRsetPtr sigonly_rrset =
+ textToRRset("www.example.com. 1076895760 IN RRSIG "
+ "TXT 5 2 3600 20120814220826 20120715220826 "
+ "1234 example.com. FAKE");
+ SegmentObjectHolder<RdataSet, RRClass> holder3(
+ mem_sgmt_,
+ RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(), sigonly_rrset),
+ RRClass::IN());
+
+ RdataSet* rdataset_a = holder1.get();
+ RdataSet* rdataset_aaaa = holder2.get();
+ RdataSet* rdataset_sigonly = holder3.get();
+ RdataSet* rdataset_null = NULL;
+ rdataset_a->next = rdataset_aaaa;
+ rdataset_aaaa->next = rdataset_sigonly;
+
+ // If a non-RRSIG part of rdataset exists for the given type, it will be
+ // returned regardless of the value of sigonly_ok. If it's RRSIG-only
+ // rdataset, it returns non NULL iff sigonly_ok is explicitly set to true.
+ EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a, RRType::AAAA()));
+ EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a, RRType::AAAA(), true));
+ EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a, RRType::AAAA(), false));
+
+ EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a, RRType::TXT()));
+ EXPECT_EQ(rdataset_sigonly, RdataSet::find(rdataset_a, RRType::TXT(),
+ true));
+ EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a, RRType::TXT(), false));
+
+ // Same tests for the const version of find().
+ const RdataSet* rdataset_a_const = holder1.get();
+ EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a_const, RRType::AAAA()));
+ EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a_const, RRType::AAAA(),
+ true));
+ EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a_const, RRType::AAAA(),
+ false));
+
+ EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a_const, RRType::TXT()));
+ EXPECT_EQ(rdataset_sigonly, RdataSet::find(rdataset_a_const, RRType::TXT(),
+ true));
+ EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a_const, RRType::TXT(),
+ false));
+}
+
// A helper function to create an RRset containing the given number of
// unique RDATAs.
ConstRRsetPtr